Patched SecondaryRomanceChanceFactor for incest precept

This commit is contained in:
amevarashi 2022-11-24 23:10:03 +05:00
parent 355d409eb6
commit 785eac31de
1 changed files with 90 additions and 1 deletions

View File

@ -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
{
/// <summary>
@ -64,7 +67,6 @@ namespace RJWSexperience.Ideology.Patches
/// <param name="two">Target for romance</param>
/// <param name="__result">Result of the original method</param>
/// <returns>Run original method implementation</returns>
[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
{
/// <summary>
/// <para>
/// Replace
/// float num = 1f;
/// foreach (PawnRelationDef pawnRelationDef in this.pawn.GetRelations(otherPawn))
/// {
/// num *= pawnRelationDef.romanceChanceFactor;
/// }
/// </para>
/// <para>with</para>
/// <para>
/// float num = 1f;
/// num = RomanceChanceFactorHelpers.GetRomanceChanceFactor(this.pawn, otherPawn)
/// </para>
/// </summary>
/// <param name="instructions">Original method body</param>
/// <returns>Modified method body</returns>
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> 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;
}
}
}
}