diff --git a/Languages/English/Keyed/RJW_Sexperience.xml b/Languages/English/Keyed/RJW_Sexperience.xml
index 92fe2bc..83d2026 100644
--- a/Languages/English/Keyed/RJW_Sexperience.xml
+++ b/Languages/English/Keyed/RJW_Sexperience.xml
@@ -9,6 +9,16 @@
not animal
capable of sex is required
+ Enable romance patch for incest precepts*
+ Patch for incest precepts to affect RomanceChanceFactor. May conflict with romance mods./n/n* Requires a game restart to apply changes
+ Enable manual romance patch for incest precepts*
+ Patch for incest precepts to affect manual romance options./n/n* Requires a game restart to apply changes
+
+ Time between bestiality attempts x{0}
+ Time between masturbation attempts x{0}
+ Time between necrophilia attempts x{0}
+ Time between rape attempts x{0}
+
- forbidden by ideology
+
\ No newline at end of file
diff --git a/Source/IdeologyAddon/IdeologyAddon.csproj b/Source/IdeologyAddon/IdeologyAddon.csproj
index 9f06941..f791556 100644
--- a/Source/IdeologyAddon/IdeologyAddon.csproj
+++ b/Source/IdeologyAddon/IdeologyAddon.csproj
@@ -54,6 +54,7 @@
+
@@ -87,6 +88,8 @@
+
+
@@ -97,7 +100,7 @@
- 1.4.3555
+ 1.4.3704
2.2.2
diff --git a/Source/IdeologyAddon/Keyed.cs b/Source/IdeologyAddon/Keyed.cs
index 8a98c01..4083479 100644
--- a/Source/IdeologyAddon/Keyed.cs
+++ b/Source/IdeologyAddon/Keyed.cs
@@ -4,11 +4,17 @@ namespace RJWSexperience.Ideology
{
public static class Keyed
{
+ public static readonly string ModTitle = "RSI_Mod_Title".Translate();
public static readonly string MemeStatFactor = "MemeStatFactor".Translate();
public static readonly string RSVictimCondition = "RSVictimCondition".Translate();
public static readonly string RSBreederCondition = "RSBreederCondition".Translate();
public static readonly string RSNotHuman = "RSNotHuman".Translate();
public static readonly string RSNotAnimal = "RSNotAnimal".Translate();
public static readonly string RSShouldCanFuck = "RSShouldCanFuck".Translate();
+
+ public static readonly string PatchRomanceChanceFactor = "RSI_PatchRomanceChanceFactor".Translate();
+ public static readonly string PatchRomanceChanceFactorTip = "RSI_PatchRomanceChanceFactorTip".Translate();
+ public static readonly string PatchIncestuousManualRomance = "RSI_PatchIncestuousManualRomance".Translate();
+ public static readonly string PatchIncestuousManualRomanceTip = "RSI_PatchIncestuousManualRomanceTip".Translate();
}
}
diff --git a/Source/IdeologyAddon/Patches/Rimworld_Patch.cs b/Source/IdeologyAddon/Patches/Rimworld_Patch.cs
index 5bd03b3..8d4498a 100644
--- a/Source/IdeologyAddon/Patches/Rimworld_Patch.cs
+++ b/Source/IdeologyAddon/Patches/Rimworld_Patch.cs
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
+using System.Text;
using Verse;
namespace RJWSexperience.Ideology.Patches
@@ -60,6 +61,8 @@ namespace RJWSexperience.Ideology.Patches
[HarmonyPatch(typeof(RelationsUtility), "Incestuous")]
public static class Rimworld_Patch_IncestuousManualRomance
{
+ public static bool Prepare() => RsiMod.Prefs.patchIncestuousManualRomance;
+
///
/// Override incestuous check in the manual romance
///
@@ -97,6 +100,8 @@ namespace RJWSexperience.Ideology.Patches
[HarmonyPatch(typeof(Pawn_RelationsTracker), nameof(Pawn_RelationsTracker.SecondaryRomanceChanceFactor))]
public static class Rimworld_Patch_SecondaryRomanceChanceFactor
{
+ public static bool Prepare() => RsiMod.Prefs.patchRomanceChanceFactor;
+
///
///
/// Replace
@@ -124,9 +129,6 @@ namespace RJWSexperience.Ideology.Patches
typeof(RomanceChanceFactorHelpers),
nameof(RomanceChanceFactorHelpers.GetRomanceChanceFactor),
new[] { typeof(Pawn), typeof(Pawn) });
- bool skipping = false;
- bool yieldNext = false;
- bool finished = false;
// Original IL looks something like this:
// Load this.pawn
@@ -142,41 +144,103 @@ namespace RJWSexperience.Ideology.Patches
// Idea is to substitute GetRelations call with a method with the same signature,
// store results in the same place original loop does and remove everything else until Endfinaly
- foreach (CodeInstruction instruction in instructions)
+ IEnumerator enumerator = instructions.GetEnumerator();
+ bool endOfInstructions = enumerator.MoveNext();
+
+ // Find and replace GetRelations
+ while (!endOfInstructions)
{
- if (finished)
- {
- yield return instruction;
- continue;
- }
-
- if (skipping)
- {
- if (yieldNext)
- {
- yield return instruction;
- yieldNext = false;
- }
- else if (instruction.opcode == OpCodes.Mul)
- {
- yieldNext = true;
- }
- else if (instruction.opcode == OpCodes.Endfinally)
- {
- finished = true;
- }
-
- continue;
- }
+ var instruction = enumerator.Current;
if (instruction.Calls(getRelationsInfo))
{
yield return new CodeInstruction(OpCodes.Call, helperInfo);
- skipping = true;
- continue;
+ enumerator.MoveNext(); // skip original method call
+ break;
}
yield return instruction;
+ endOfInstructions = enumerator.MoveNext();
+ }
+
+ if (endOfInstructions)
+ {
+ Log.Error("[RSI] Failed to transpile Pawn_RelationsTracker.SecondaryRomanceChanceFactor: PawnRelationUtility.GetRelations call not found");
+ yield break;
+ }
+
+ // Skip everything until Mul
+ while (!endOfInstructions)
+ {
+ if (enumerator.Current.opcode == OpCodes.Mul)
+ {
+ enumerator.MoveNext(); // skip Mul
+ yield return enumerator.Current; // return next op, it should be "store result"
+ break;
+ }
+
+ endOfInstructions = enumerator.MoveNext();
+ }
+
+ if (endOfInstructions)
+ {
+ Log.Error("[RSI] Failed to transpile Pawn_RelationsTracker.SecondaryRomanceChanceFactor: Mul not found. This error means half of SecondaryRomanceChanceFactor was erased. Very not good");
+ yield break;
+ }
+
+ // Skip the rest of the loop
+ while (!endOfInstructions)
+ {
+ if (enumerator.Current.opcode == OpCodes.Endfinally)
+ {
+ // Endfinally will be skipped by the next MoveNext()
+ break;
+ }
+
+ endOfInstructions = enumerator.MoveNext();
+ }
+
+ if (endOfInstructions)
+ {
+ Log.Error("[RSI] Failed to transpile Pawn_RelationsTracker.SecondaryRomanceChanceFactor: Endfinally not found. This error means half of SecondaryRomanceChanceFactor was erased. Very not good");
+ yield break;
+ }
+
+ // Return the rest of the method
+ while (enumerator.MoveNext())
+ {
+ yield return enumerator.Current;
+ }
+ }
+
+ [HarmonyPatch(typeof(Precept), nameof(Precept.GetTip))]
+ public static class Rimworld_Patch_PreceptTip
+ {
+ public static void Postfix(ref string __result, Precept __instance)
+ {
+ if (__instance.def.modExtensions.NullOrEmpty())
+ {
+ return;
+ }
+
+ bool tipChanged = false;
+ StringBuilder tipBuilder = new StringBuilder(__result);
+ tipBuilder.AppendLine();
+ tipBuilder.AppendInNewLine((Keyed.ModTitle + ":").Colorize(ColoredText.TipSectionTitleColor));
+
+ for (int i = 0; i < __instance.def.modExtensions.Count; i++)
+ {
+ if (__instance.def.modExtensions[i] is IPreceptTipPostfix tipPostfix)
+ {
+ tipBuilder.AppendInNewLine(" - " + tipPostfix.GetTip());
+ tipChanged = true;
+ }
+ }
+
+ if (tipChanged)
+ {
+ __result = tipBuilder.ToString();
+ }
}
}
}
diff --git a/Source/IdeologyAddon/Precepts/DefExtension_ModifyBestialityMtb.cs b/Source/IdeologyAddon/Precepts/DefExtension_ModifyBestialityMtb.cs
index 1d97595..111ee69 100644
--- a/Source/IdeologyAddon/Precepts/DefExtension_ModifyBestialityMtb.cs
+++ b/Source/IdeologyAddon/Precepts/DefExtension_ModifyBestialityMtb.cs
@@ -2,5 +2,6 @@
{
public class DefExtension_ModifyBestialityMtb : DefExtension_ModifyMtb
{
+ protected override string TipTemplateKey => "RSI_PreceptTipModifyBestialityMtb";
}
}
diff --git a/Source/IdeologyAddon/Precepts/DefExtension_ModifyFappinMtb.cs b/Source/IdeologyAddon/Precepts/DefExtension_ModifyFappinMtb.cs
index 8596b28..f01c4ed 100644
--- a/Source/IdeologyAddon/Precepts/DefExtension_ModifyFappinMtb.cs
+++ b/Source/IdeologyAddon/Precepts/DefExtension_ModifyFappinMtb.cs
@@ -2,5 +2,6 @@
{
public class DefExtension_ModifyFappinMtb : DefExtension_ModifyMtb
{
+ protected override string TipTemplateKey => "RSI_PreceptTipModifyFappinMtb";
}
}
diff --git a/Source/IdeologyAddon/Precepts/DefExtension_ModifyMtb.cs b/Source/IdeologyAddon/Precepts/DefExtension_ModifyMtb.cs
index e1553f3..361ceb1 100644
--- a/Source/IdeologyAddon/Precepts/DefExtension_ModifyMtb.cs
+++ b/Source/IdeologyAddon/Precepts/DefExtension_ModifyMtb.cs
@@ -1,11 +1,28 @@
-using System.Diagnostics.CodeAnalysis;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using Verse;
namespace RJWSexperience.Ideology.Precepts
{
- public abstract class DefExtension_ModifyMtb : DefModExtension
+ [SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field values are loaded from XML")]
+ public abstract class DefExtension_ModifyMtb : DefModExtension, IPreceptTipPostfix
{
- [SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
+ protected abstract string TipTemplateKey { get; }
+
public float multiplier = 1f;
+
+ public string GetTip() => TipTemplateKey.Translate(multiplier.ToString());
+
+ public override IEnumerable ConfigErrors()
+ {
+ if (multiplier == 1f)
+ {
+ yield return "There is no point if is 1";
+ }
+ else if (multiplier <= 0f)
+ {
+ yield return " must be > 0";
+ }
+ }
}
}
diff --git a/Source/IdeologyAddon/Precepts/DefExtension_ModifyNecroMtb.cs b/Source/IdeologyAddon/Precepts/DefExtension_ModifyNecroMtb.cs
index 3e544f7..ce35b27 100644
--- a/Source/IdeologyAddon/Precepts/DefExtension_ModifyNecroMtb.cs
+++ b/Source/IdeologyAddon/Precepts/DefExtension_ModifyNecroMtb.cs
@@ -2,5 +2,6 @@
{
public class DefExtension_ModifyNecroMtb : DefExtension_ModifyMtb
{
+ protected override string TipTemplateKey => "RSI_PreceptTipModifyNecroMtb";
}
}
diff --git a/Source/IdeologyAddon/Precepts/DefExtension_ModifyRapeCPMtb.cs b/Source/IdeologyAddon/Precepts/DefExtension_ModifyRapeCPMtb.cs
index e83be70..ff09728 100644
--- a/Source/IdeologyAddon/Precepts/DefExtension_ModifyRapeCPMtb.cs
+++ b/Source/IdeologyAddon/Precepts/DefExtension_ModifyRapeCPMtb.cs
@@ -2,5 +2,6 @@
{
public class DefExtension_ModifyRapeCPMtb : DefExtension_ModifyMtb
{
+ protected override string TipTemplateKey => "RSI_PreceptTipModifyRapeCPMtb";
}
}
diff --git a/Source/IdeologyAddon/Precepts/IPreceptTipPostfix.cs b/Source/IdeologyAddon/Precepts/IPreceptTipPostfix.cs
new file mode 100644
index 0000000..85411fb
--- /dev/null
+++ b/Source/IdeologyAddon/Precepts/IPreceptTipPostfix.cs
@@ -0,0 +1,7 @@
+namespace RJWSexperience.Ideology.Precepts
+{
+ public interface IPreceptTipPostfix
+ {
+ string GetTip();
+ }
+}
diff --git a/Source/IdeologyAddon/RsiMod.cs b/Source/IdeologyAddon/RsiMod.cs
new file mode 100644
index 0000000..66dab60
--- /dev/null
+++ b/Source/IdeologyAddon/RsiMod.cs
@@ -0,0 +1,26 @@
+using UnityEngine;
+using Verse;
+
+namespace RJWSexperience.Ideology
+{
+ public class RsiMod : Mod
+ {
+ public static RsiSettings Prefs { get; private set; }
+
+ public RsiMod(ModContentPack content) : base(content)
+ {
+ Prefs = GetSettings();
+ }
+
+ public override string SettingsCategory() => Keyed.ModTitle;
+
+ public override void DoSettingsWindowContents(Rect inRect)
+ {
+ Listing_Standard listmain = new Listing_Standard();
+ listmain.Begin(inRect);
+ listmain.CheckboxLabeled(Keyed.PatchRomanceChanceFactor, ref Prefs.patchRomanceChanceFactor, Keyed.PatchRomanceChanceFactorTip);
+ listmain.CheckboxLabeled(Keyed.PatchIncestuousManualRomance, ref Prefs.patchIncestuousManualRomance, Keyed.PatchIncestuousManualRomanceTip);
+ listmain.End();
+ }
+ }
+}
diff --git a/Source/IdeologyAddon/RsiSettings.cs b/Source/IdeologyAddon/RsiSettings.cs
new file mode 100644
index 0000000..215b625
--- /dev/null
+++ b/Source/IdeologyAddon/RsiSettings.cs
@@ -0,0 +1,17 @@
+using Verse;
+
+namespace RJWSexperience.Ideology
+{
+ public class RsiSettings : ModSettings
+ {
+ public bool patchRomanceChanceFactor;
+ public bool patchIncestuousManualRomance;
+
+ public override void ExposeData()
+ {
+ base.ExposeData();
+ Scribe_Values.Look(ref patchRomanceChanceFactor, "patchSecondaryRomanceChanceFactor", true);
+ Scribe_Values.Look(ref patchIncestuousManualRomance, "patchIncestuousManualRomance", true);
+ }
+ }
+}