using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using HarmonyLib; using RimWorld; using Verse; using rjw; namespace Rimworld_Animations { [HarmonyPatch(typeof(JobDriver_SexBaseInitiator), "Start")] static class HarmonyPatch_JobDriver_SexBaseInitiator_Start { public static void Postfix(ref JobDriver_SexBaseInitiator __instance) { if(__instance is JobDriver_JoinInBed) { Log.Warning("Tried to start wrong JobDriver with Rimworld-Animations installed. If you see this warning soon after installing this mod, it's fine and animated sex will start soon. If you see this a long time after installing, that's a problem."); return; } Pawn Target = __instance.Target; Pawn pawn = __instance.pawn; Building_Bed bed = __instance.Bed; if (__instance is JobDriver_BestialityForFemale) bed = (__instance as JobDriver_BestialityForFemale).Bed; else if (__instance is JobDriver_WhoreIsServingVisitors) { bed = (__instance as JobDriver_WhoreIsServingVisitors).Bed; } else if(__instance is JobDriver_SexCasualForAnimation) { bed = (__instance as JobDriver_SexCasualForAnimation).Bed; } if (__instance.Target.jobs?.curDriver is JobDriver_SexBaseReciever) { if (!(Target.jobs.curDriver as JobDriver_SexBaseReciever).parteners.Contains(pawn)) { (Target.jobs.curDriver as JobDriver_SexBaseReciever).parteners.Add(pawn); } if (bed != null) { RerollAnimations(Target, __instance.duration, bed as Thing); } else { RerollAnimations(Target, __instance.duration); } } } public static void RerollAnimations(Pawn pawn, int duration, Thing bed = null) { if(pawn == null || !(pawn.jobs?.curDriver is JobDriver_SexBaseReciever)) { Log.Message("Error: Tried to reroll animations when pawn isn't sexing"); return; } List pawnsToAnimate = (pawn.jobs.curDriver as JobDriver_SexBaseReciever).parteners.ToList(); if (!pawnsToAnimate.Contains(pawn)) { pawnsToAnimate = pawnsToAnimate.Append(pawn).ToList(); } AnimationDef anim = AnimationUtility.tryFindAnimation(ref pawnsToAnimate); if (anim != null) { Log.Message("Now playing " + anim.defName); bool mirror = GenTicks.TicksGame % 2 == 0; IntVec3 pos = pawn.Position; for (int i = 0; i < pawnsToAnimate.Count; i++) { if (bed != null) pawnsToAnimate[i].TryGetComp().setAnchor(bed); else { pawnsToAnimate[i].TryGetComp().setAnchor(pos); } pawnsToAnimate[i].TryGetComp().StartAnimation(anim, i, mirror); (pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).ticks_left = anim.animationTimeTicks; (pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).ticksLeftThisToil = anim.animationTimeTicks; (pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).duration = anim.animationTimeTicks; (pawnsToAnimate[i].jobs.curDriver as JobDriver_Sex).ticks_remaining = anim.animationTimeTicks; } } else { Log.Message("Anim not found"); //if pawn isn't already animating, if (!pawn.TryGetComp().isAnimating) { (pawn.jobs.curDriver as JobDriver_SexBaseReciever).increase_time(duration); //they'll just do the thrusting anim } } } } [HarmonyPatch(typeof(JobDriver_SexBaseInitiator), "End")] static class HarmonyPatch_JobDriver_SexBaseInitiator_End { public static void Postfix(ref JobDriver_SexBaseInitiator __instance) { //Stolen from vanilla lovin //to make sure vanilla lovin variables are set if(__instance.pawn?.mindState?.canLovinTick != null) { SimpleCurve LovinIntervalHoursFromAgeCurve = new SimpleCurve { new CurvePoint(16f, 1.5f), new CurvePoint(22f, 1.5f), new CurvePoint(30f, 4f), new CurvePoint(50f, 12f), new CurvePoint(75f, 36f) }; int ticksToNextLovin; if (DebugSettings.alwaysDoLovin) { ticksToNextLovin = 100; } else { float centerX = LovinIntervalHoursFromAgeCurve.Evaluate(__instance.pawn.ageTracker.AgeBiologicalYearsFloat); centerX = Rand.Gaussian(centerX, 0.3f); if (centerX < 0.5f) { centerX = 0.5f; } ticksToNextLovin = (int)(centerX * 2500f); } __instance.pawn.mindState.canLovinTick = Find.TickManager.TicksGame + ticksToNextLovin; } if (__instance.Target.jobs?.curDriver is JobDriver_SexBaseReciever) { if (__instance.pawn.TryGetComp().isAnimating) { List parteners = (__instance.Target.jobs.curDriver as JobDriver_SexBaseReciever).parteners; for (int i = 0; i < parteners.Count; i++) { //prevents pawns who started a new anim from stopping their new anim if (!((parteners[i].jobs.curDriver as JobDriver_SexBaseInitiator) != null && (parteners[i].jobs.curDriver as JobDriver_SexBaseInitiator).Target != __instance.pawn)) parteners[i].TryGetComp().isAnimating = false; } __instance.Target.TryGetComp().isAnimating = false; if (xxx.is_human(__instance.Target)) { __instance.Target.Drawer.renderer.graphics.ResolveApparelGraphics(); PortraitsCache.SetDirty(__instance.Target); } } (__instance.Target.jobs.curDriver as JobDriver_SexBaseReciever).parteners.Remove(__instance.pawn); } if (xxx.is_human(__instance.pawn)) { __instance.pawn.Drawer.renderer.graphics.ResolveApparelGraphics(); PortraitsCache.SetDirty(__instance.pawn); } } } }