From 785eac31de0b07cd63c886e86f89f8ff31053217 Mon Sep 17 00:00:00 2001 From: amevarashi Date: Thu, 24 Nov 2022 23:10:03 +0500 Subject: [PATCH] Patched SecondaryRomanceChanceFactor for incest precept --- .../IdeologyAddon/Patches/Rimworld_Patch.cs | 91 ++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/Source/IdeologyAddon/Patches/Rimworld_Patch.cs b/Source/IdeologyAddon/Patches/Rimworld_Patch.cs index de49fe7..9a54dd4 100644 --- a/Source/IdeologyAddon/Patches/Rimworld_Patch.cs +++ b/Source/IdeologyAddon/Patches/Rimworld_Patch.cs @@ -5,6 +5,8 @@ using RJWSexperience.Ideology.HistoryEvents; using RJWSexperience.Ideology.Precepts; using System.Collections.Generic; using System.Linq; +using System.Reflection; +using System.Reflection.Emit; using Verse; namespace RJWSexperience.Ideology.Patches @@ -55,6 +57,7 @@ namespace RJWSexperience.Ideology.Patches } } + [HarmonyPatch(typeof(RelationsUtility), "Incestuous")] public static class Rimworld_Patch_IncestuousManualRomance { /// @@ -64,7 +67,6 @@ namespace RJWSexperience.Ideology.Patches /// Target for romance /// Result of the original method /// Run original method implementation - [HarmonyPatch(typeof(RelationsUtility), "Incestuous")] public static bool Prefix(Pawn one, Pawn two, ref bool __result) { __result = RsiIncestuous(one, two); @@ -91,4 +93,91 @@ namespace RJWSexperience.Ideology.Patches return !allowManualRomanceOnlyFor.Contains(relationDegree); } } + + [HarmonyPatch(typeof(Pawn_RelationsTracker), nameof(Pawn_RelationsTracker.SecondaryRomanceChanceFactor))] + public static class Rimworld_Patch_SecondaryRomanceChanceFactor + { + /// + /// + /// Replace + /// float num = 1f; + /// foreach (PawnRelationDef pawnRelationDef in this.pawn.GetRelations(otherPawn)) + /// { + /// num *= pawnRelationDef.romanceChanceFactor; + /// } + /// + /// with + /// + /// float num = 1f; + /// num = RomanceChanceFactorHelpers.GetRomanceChanceFactor(this.pawn, otherPawn) + /// + /// + /// Original method body + /// Modified method body + public static IEnumerable Transpiler(IEnumerable instructions) + { + MethodInfo getRelationsInfo = AccessTools.Method( + typeof(PawnRelationUtility), + nameof(PawnRelationUtility.GetRelations), + new[] { typeof(Pawn), typeof(Pawn) }); + MethodInfo helperInfo = AccessTools.Method( + 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 + // Load otherPawn + // Call GetRelations + // Start loop + // ... + // Mul num and romanceChanceFactor + // Store result + // ... + // Endfinaly + + // 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) + { + 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; + } + + if (instruction.Calls(getRelationsInfo)) + { + yield return new CodeInstruction(OpCodes.Call, helperInfo); + skipping = true; + continue; + } + + yield return instruction; + } + } + } }