diff --git a/Source/IdeologyAddon/HistoryEvents/HistoryEventDefExtensionMethods.cs b/Source/IdeologyAddon/HistoryEvents/HistoryEventDefExtensionMethods.cs index 8f1a4ab4735bcf064a025c115e40d5690f8a8dd2..808170c6e5b4073e9cc618a4a0d8e56484151eed 100644 --- a/Source/IdeologyAddon/HistoryEvents/HistoryEventDefExtensionMethods.cs +++ b/Source/IdeologyAddon/HistoryEvents/HistoryEventDefExtensionMethods.cs @@ -2,6 +2,7 @@ using Verse; using System.Linq; using System.Collections.Generic; +using System.Runtime.CompilerServices; namespace RJWSexperience.Ideology.HistoryEvents { @@ -27,6 +28,7 @@ namespace RJWSexperience.Ideology.HistoryEvents //Log.Message($"[RSI] Recorded event {historyEvent.def.ToStringWithPartner(pawn, partner)}"); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static HistoryEvent CreateEvent(this HistoryEventDef def, Pawn pawn) { return new HistoryEvent(def, pawn.Named(HistoryEventArgsNames.Doer)); diff --git a/Source/IdeologyAddon/Patches/RJW_Patch_Ideo.cs b/Source/IdeologyAddon/Patches/RJW_Patch_Ideo.cs index 4a06922ebf6a2d6142ca4277e4db2fb626a84bf4..9e9a808aa3798f36e7726e0047927a943102f0f7 100644 --- a/Source/IdeologyAddon/Patches/RJW_Patch_Ideo.cs +++ b/Source/IdeologyAddon/Patches/RJW_Patch_Ideo.cs @@ -7,10 +7,55 @@ using RJWSexperience.Ideology.HistoryEvents; using RJWSexperience.Ideology.Precepts; using System; using System.Collections.Generic; +using System.Reflection.Emit; using Verse; namespace RJWSexperience.Ideology.Patches { + [HarmonyPatch(typeof(xxx), nameof(xxx.can_rape))] + public static class RJW_Patch_CannotRapeBecauseIdeo + { + /// <summary> + /// Injects IdeoCanRape call into is_human block of xxx.can_rape + /// </summary> + /// <param name="instructions">Original method instructions</param> + /// <returns>Modified method instructions</returns> + [HarmonyTranspiler] + public static IEnumerable<CodeInstruction> AddIdeoCheck(IEnumerable<CodeInstruction> instructions, ILGenerator generator) + { + using IEnumerator<CodeInstruction> enumerator = instructions.GetEnumerator(); + + System.Reflection.FieldInfo wildMode = AccessTools.Field(typeof(RJWSettings), nameof(RJWSettings.WildMode)); + Label labelWildMode = generator.DefineLabel(); + bool done = false; + + while (enumerator.MoveNext()) + { + if (!done && enumerator.Current.LoadsField(wildMode)) + { + // Found RJWSettings.WildMode check, insert before + // Need to move labels to our instruction because previous check jumps to one of them, skipping our call + var existingLabels = enumerator.Current.labels; + enumerator.Current.labels = new List<Label>() { labelWildMode }; + // Load the first argument - Pawn + yield return new CodeInstruction(OpCodes.Ldarg_0) { labels = existingLabels }; + // Call the check. Consumes pawn and pushes bool + yield return CodeInstruction.Call(typeof(RJW_Patch_CannotRapeBecauseIdeo), nameof(IdeoCanRape));; + // If bool is true, jump to the next check + yield return new CodeInstruction(OpCodes.Brtrue_S, labelWildMode); + // The bool was false, push false and exit the method + yield return new CodeInstruction(OpCodes.Ldc_I4_0); + yield return new CodeInstruction(OpCodes.Ret); + done = true; + } + + yield return enumerator.Current; + } + } + + public static bool IdeoCanRape(Pawn pawn) => RsiDefOf.HistoryEvent.RSI_Raped.CreateEvent(pawn).DoerWillingToDo(); + } + [HarmonyPatch(typeof(xxx), nameof(xxx.is_rapist))] public static class RJW_Patch_is_rapist {