mirror of
https://gitgud.io/amevarashi/rjw-sexperience-ideology.git
synced 2024-08-15 00:43:19 +00:00
299 lines
9.7 KiB
C#
299 lines
9.7 KiB
C#
using HarmonyLib;
|
|
using RimWorld;
|
|
using rjw;
|
|
using rjw.Modules.Interactions.Internals.Implementation;
|
|
using rjw.Modules.Interactions.Objects;
|
|
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
|
|
{
|
|
public static void Postfix(Pawn pawn, ref bool __result)
|
|
{
|
|
Ideo ideo = pawn.Ideo;
|
|
if (ideo != null && !pawn.IsSubmissive())
|
|
{
|
|
__result = __result || ideo.HasMeme(RsiDefOf.Meme.Rapist);
|
|
}
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch(typeof(xxx), nameof(xxx.is_zoophile))]
|
|
public static class RJW_Patch_is_zoophile
|
|
{
|
|
public static void Postfix(Pawn pawn, ref bool __result)
|
|
{
|
|
Ideo ideo = pawn.Ideo;
|
|
if (ideo != null)
|
|
{
|
|
__result = __result || ideo.HasMeme(RsiDefOf.Meme.Zoophile);
|
|
}
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch(typeof(xxx), nameof(xxx.is_necrophiliac))]
|
|
public static class RJW_Patch_is_necrophiliac
|
|
{
|
|
public static void Postfix(Pawn pawn, ref bool __result)
|
|
{
|
|
Ideo ideo = pawn.Ideo;
|
|
if (ideo != null)
|
|
{
|
|
__result = __result || ideo.HasMeme(RsiDefOf.Meme.Necrophile);
|
|
}
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch(typeof(SexUtility), nameof(SexUtility.Aftersex), new Type[] { typeof(SexProps) })]
|
|
public static class RJW_Patch_SexUtility_Aftersex_RecordHistoryEvents
|
|
{
|
|
public static void Postfix(SexProps props)
|
|
{
|
|
InteractionDefExtension_HistoryEvents interactionEvents = props.dictionaryKey.GetModExtension<InteractionDefExtension_HistoryEvents>();
|
|
|
|
if (props.hasPartner())
|
|
{
|
|
if (xxx.is_human(props.pawn))
|
|
AfterSexHuman(props.pawn, props.partner);
|
|
if (xxx.is_human(props.partner))
|
|
AfterSexHuman(props.partner, props.pawn);
|
|
|
|
if (interactionEvents != null)
|
|
{
|
|
foreach (HistoryEventDef eventDef in interactionEvents.pawnEvents)
|
|
eventDef.RecordEventWithPartner(props.pawn, props.partner);
|
|
|
|
foreach (HistoryEventDef eventDef in interactionEvents.partnerEvents)
|
|
eventDef.RecordEventWithPartner(props.partner, props.pawn);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (interactionEvents != null)
|
|
{
|
|
foreach (HistoryEventDef eventDef in interactionEvents.pawnEvents)
|
|
Find.HistoryEventsManager.RecordEvent(eventDef.CreateEvent(props.pawn));
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void AfterSexHuman(Pawn human, Pawn partner)
|
|
{
|
|
RsiDefOf.HistoryEvent.RSI_NonIncestuosSex.RecordEventWithPartner(human, partner);
|
|
|
|
if (partner.IsAnimal())
|
|
RsiDefOf.HistoryEvent.RSI_SexWithAnimal.RecordEventWithPartner(human, partner);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set prefer sextype using precepts
|
|
/// </summary>
|
|
[HarmonyPatch(typeof(InteractionScoringService), nameof(InteractionScoringService.Score), new Type[] { typeof(InteractionWithExtension), typeof(InteractionPawn), typeof(InteractionPawn) })]
|
|
public static class RJW_Patch_DetermineSexScores
|
|
{
|
|
public static void Postfix(InteractionWithExtension interaction, InteractionPawn dominant, InteractionPawn submissive, ref InteractionScore __result)
|
|
{
|
|
InteractionDefExtension_HistoryEvents interactionEvents = interaction.Interaction.GetModExtension<InteractionDefExtension_HistoryEvents>();
|
|
if (interactionEvents == null)
|
|
return;
|
|
|
|
if (dominant.Pawn.Ideo != null)
|
|
__result.Dominant = PreceptSextype(dominant.Pawn, submissive.Pawn, __result.Dominant, interactionEvents.pawnEvents);
|
|
|
|
if (submissive.Pawn.Ideo != null)
|
|
__result.Submissive = PreceptSextype(submissive.Pawn, dominant.Pawn, __result.Submissive, interactionEvents.partnerEvents);
|
|
}
|
|
|
|
public static float PreceptSextype(Pawn pawn, Pawn partner, float score, List<HistoryEventDef> historyEventDefs)
|
|
{
|
|
for (int i = 0; i < historyEventDefs.Count; i++)
|
|
{
|
|
HistoryEventDef eventDef = historyEventDefs[i];
|
|
|
|
if (eventDef.CreateEventWithPartner(pawn, partner).DoerWillingToDo())
|
|
{
|
|
float mult = 8.0f * Math.Max(0.3f, 1 / Math.Max(0.01f, pawn.GetStatValue(xxx.sex_drive_stat, cacheStaleAfterTicks: 60)));
|
|
return score * mult;
|
|
}
|
|
}
|
|
return score;
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch(typeof(SexAppraiser), nameof(SexAppraiser.would_fuck), new Type[] { typeof(Pawn), typeof(Pawn), typeof(bool), typeof(bool), typeof(bool) })]
|
|
public static class RJW_Patch_would_fuck
|
|
{
|
|
public static void Postfix(Pawn fucker, Pawn fucked, ref float __result)
|
|
{
|
|
if (!xxx.is_human(fucker))
|
|
return;
|
|
|
|
Ideo ideo = fucker.Ideo;
|
|
if (ideo == null)
|
|
return;
|
|
|
|
for(int i = 0; i < ideo.PreceptsListForReading.Count; i++)
|
|
ideo.PreceptsListForReading[i].def.GetModExtension<DefExtension_ModifyPreference>()?.Apply(fucker, fucked, ref __result);
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch(typeof(PawnDesignations_Breedee), nameof(PawnDesignations_Breedee.UpdateCanDesignateBreeding))]
|
|
public static class RJW_Patch_UpdateCanDesignateBreeding
|
|
{
|
|
public static void Postfix(Pawn pawn, ref bool __result)
|
|
{
|
|
Ideo ideo = pawn.Ideo;
|
|
if (ideo?.HasMeme(RsiDefOf.Meme.Zoophile) == true)
|
|
{
|
|
SaveStorage.DataStore.GetPawnData(pawn).CanDesignateBreeding = true;
|
|
__result = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch(typeof(PawnDesignations_Comfort))]
|
|
public static class RJW_Patch_PawnDesignations_Comfort_Submissive
|
|
{
|
|
[HarmonyPostfix, HarmonyPatch(nameof(PawnDesignations_Comfort.UpdateCanDesignateComfort))]
|
|
public static void UpdateCanDesignateComfort(Pawn pawn, ref bool __result)
|
|
{
|
|
if (pawn.IsSubmissive())
|
|
{
|
|
SaveStorage.DataStore.GetPawnData(pawn).CanDesignateComfort = true;
|
|
__result = true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// RJW undesignates if it thinks that the pawn can't be a comfort pawn.
|
|
/// Why the hell checker method changes the state?
|
|
/// </summary>
|
|
/// <param name="pawn">Pawn to check</param>
|
|
/// <param name="__result">Is pawn currenlty designated as comfort</param>
|
|
/// <returns>Run the original method</returns>
|
|
[HarmonyPrefix, HarmonyPatch(nameof(PawnDesignations_Comfort.IsDesignatedComfort))]
|
|
public static bool IsDesignatedComfort(Pawn pawn, ref bool __result)
|
|
{
|
|
if (pawn.IsSubmissive() && !pawn.Dead)
|
|
{
|
|
__result = pawn.GetRJWPawnData().Comfort;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch(typeof(Hediff_BasePregnancy), nameof(Hediff_BasePregnancy.PostBirth))]
|
|
public static class RJW_Patch_PostBirth
|
|
{
|
|
public static void Postfix(Pawn mother, Pawn baby)
|
|
{
|
|
if (!mother.IsAnimal())
|
|
{
|
|
Faction faction = baby.GetFactionUsingPrecept(out Ideo ideo);
|
|
if (baby.Faction != faction)
|
|
baby.SetFaction(faction);
|
|
|
|
baby.ideo?.SetIdeo(ideo);
|
|
|
|
if (baby.Faction == Find.FactionManager.OfPlayer && !baby.IsSlave)
|
|
baby.guest?.SetGuestStatus(null, GuestStatus.Guest);
|
|
}
|
|
}
|
|
|
|
private static Faction GetFactionUsingPrecept(this Pawn baby, out Ideo ideo)
|
|
{
|
|
Faction playerfaction = Find.FactionManager.OfPlayer;
|
|
Ideo mainideo = playerfaction.ideos.PrimaryIdeo;
|
|
if (mainideo != null)
|
|
{
|
|
if (mainideo.HasPrecept(RsiDefOf.Precept.BabyFaction_AlwaysFather))
|
|
{
|
|
Pawn parent = baby.GetFather() ?? baby.GetMother();
|
|
|
|
ideo = parent.Ideo;
|
|
return parent.Faction;
|
|
}
|
|
else if (mainideo.HasPrecept(RsiDefOf.Precept.BabyFaction_AlwaysColony))
|
|
{
|
|
ideo = mainideo;
|
|
return playerfaction;
|
|
}
|
|
}
|
|
Pawn mother = baby.GetMother();
|
|
ideo = mother?.Ideo;
|
|
return mother?.Faction ?? baby.Faction;
|
|
}
|
|
}
|
|
|
|
[HarmonyPatch(typeof(SexUtility), nameof(SexUtility.SatisfyPersonal))]
|
|
public static class RJW_Patch_Orgasm_IdeoConversion
|
|
{
|
|
public static void Postfix(SexProps props)
|
|
{
|
|
// ShortCuts: Exit Early if Pawn or Partner are null (can happen with Animals or Masturbation)
|
|
if (props.pawn?.Ideo == null || !props.hasPartner())
|
|
return;
|
|
|
|
if (props.partner.Ideo?.HasPrecept(RsiDefOf.Precept.ProselyzingByOrgasm) == true)
|
|
{
|
|
// Pawn is the one having the orgasm
|
|
// Partner is "giving" the orgasm, hence the pawn will be converted towards the partners ideology
|
|
IdeoUtility.ConvertPawnBySex(props.pawn, props.partner, 0.03f);
|
|
}
|
|
}
|
|
}
|
|
}
|