diff --git a/Rimworld-Animations.csproj b/Rimworld-Animations.csproj index e5762cf..20d6133 100644 --- a/Rimworld-Animations.csproj +++ b/Rimworld-Animations.csproj @@ -86,6 +86,7 @@ + diff --git a/Source/AnimationUtility.cs b/Source/AnimationUtility.cs index 9563ef0..df9b5a8 100644 --- a/Source/AnimationUtility.cs +++ b/Source/AnimationUtility.cs @@ -161,5 +161,26 @@ namespace Rimworld_Animations { GenDraw.DrawMeshNowOrLater(mesh, pawnHeadPosition, Quaternion.AngleAxis(pawnAnimator.headAngle, Vector3.up), material, portrait); } } + + public static void RenderPawnHeadMeshInAnimation(Mesh mesh, Vector3 loc, Quaternion quaternion, Material material, bool portrait, Pawn pawn, float bodySizeFactor = 1) { + + if (pawn == null) { + GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, portrait); + return; + } + + CompBodyAnimator pawnAnimator = pawn.TryGetComp(); + + if (pawnAnimator == null || !pawnAnimator.isAnimating || portrait) { + GenDraw.DrawMeshNowOrLater(mesh, loc, quaternion, material, portrait); + } + else { + Vector3 pawnHeadPosition = pawnAnimator.getPawnHeadPosition(); + pawnHeadPosition.x *= bodySizeFactor; + pawnHeadPosition.x *= bodySizeFactor; + pawnHeadPosition.y = loc.y; + GenDraw.DrawMeshNowOrLater(mesh, pawnHeadPosition, Quaternion.AngleAxis(pawnAnimator.headAngle, Vector3.up), material, portrait); + } + } } } diff --git a/Source/Patches/HarmonyPatch_CSL.cs b/Source/Patches/HarmonyPatch_CSL.cs new file mode 100644 index 0000000..fb6ab64 --- /dev/null +++ b/Source/Patches/HarmonyPatch_CSL.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using HarmonyLib; +using rjw; +using Verse; +using RimWorld; +using System.Reflection.Emit; +using System.Reflection; +using UnityEngine; + +namespace Rimworld_Animations { + [StaticConstructorOnStartup] + public static class HarmonyPatch_CSL { + static HarmonyPatch_CSL() { + try { + ((Action)(() => { + if (LoadedModManager.RunningModsListForReading.Any(x => x.Name == "Children, school and learning")) { + + (new Harmony("rjw")).Patch(AccessTools.Method(AccessTools.TypeByName("PawnRenderer_RenderPawnInternal_Patch"), "RenderPawnInternalScaled"), + prefix: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_CSL), "Prefix_CSL")), + transpiler: new HarmonyMethod(AccessTools.Method(typeof(HarmonyPatch_CSL), "Transpiler_CSL"))); + } + }))(); + } + catch (TypeLoadException ex) { + + } + } + + public static void Prefix_CSL(PawnRenderer __instance, Pawn pawn, ref Vector3 rootLoc, ref float angle, bool renderBody, ref Rot4 bodyFacing, ref Rot4 headFacing, RotDrawMode bodyDrawType, bool portrait, bool headStump, bool invisible) { + + PawnGraphicSet graphics = __instance.graphics; + CompBodyAnimator bodyAnim = pawn.TryGetComp(); + + if (!graphics.AllResolved) { + graphics.ResolveAllGraphics(); + } + + + if (bodyAnim != null && bodyAnim.isAnimating && !portrait) { + bodyAnim.tickGraphics(graphics); + pawn.TryGetComp().animatePawn(ref rootLoc, ref angle, ref bodyFacing, ref headFacing); + + } + } + + public static IEnumerable Transpiler_CSL(IEnumerable instructions) { + + MethodInfo drawMeshNowOrLater = AccessTools.Method(typeof(GenDraw), "DrawMeshNowOrLater"); + FieldInfo headGraphic = AccessTools.Field(typeof(PawnGraphicSet), "headGraphic"); + + + List codes = instructions.ToList(); + bool forHead = true; + for (int i = 0; i < codes.Count(); i++) { + + //Instead of calling drawmeshnoworlater, add pawn to the stack and call my special static method + if (codes[i].OperandIs(drawMeshNowOrLater) && forHead) { + + yield return new CodeInstruction(OpCodes.Ldarg_0); + yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(PawnRenderer), "pawn")); + yield return new CodeInstruction(OpCodes.Ldarg_2); + yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationUtility), nameof(AnimationUtility.RenderPawnHeadMeshInAnimation), new Type[] { typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(bool), typeof(Pawn), typeof(float) })); + + } + //checking for if(graphics.headGraphic != null) + else if (codes[i].opcode == OpCodes.Ldfld && codes[i].OperandIs(headGraphic)) { + forHead = true; + yield return codes[i]; + } + //checking for if(renderbody) + else if (codes[i].opcode == OpCodes.Ldarg_3) { + forHead = false; + yield return codes[i]; + } + else { + yield return codes[i]; + } + } + } + + } +} diff --git a/Source/Patches/HarmonyPatch_PawnRenderer.cs b/Source/Patches/HarmonyPatch_PawnRenderer.cs index 0a1c753..a58b1e9 100644 --- a/Source/Patches/HarmonyPatch_PawnRenderer.cs +++ b/Source/Patches/HarmonyPatch_PawnRenderer.cs @@ -64,7 +64,7 @@ namespace Rimworld_Animations { yield return new CodeInstruction(OpCodes.Ldarg_0); yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(PawnRenderer), "pawn")); - yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationUtility), nameof(AnimationUtility.RenderPawnHeadMeshInAnimation))); + yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationUtility), nameof(AnimationUtility.RenderPawnHeadMeshInAnimation), new Type[] { typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(bool), typeof(Pawn) })); } //checking for if(graphics.headGraphic != null) diff --git a/Source/Patches/HarmonyPatch_ShowHairWithHats.cs b/Source/Patches/HarmonyPatch_ShowHairWithHats.cs index 87e59d2..3714503 100644 --- a/Source/Patches/HarmonyPatch_ShowHairWithHats.cs +++ b/Source/Patches/HarmonyPatch_ShowHairWithHats.cs @@ -6,6 +6,7 @@ using System.Reflection; using System.Reflection.Emit; using System.Text; using System.Threading.Tasks; +using UnityEngine; using Verse; namespace Rimworld_Animations { @@ -38,7 +39,7 @@ namespace Rimworld_Animations { yield return new CodeInstruction(OpCodes.Ldarg_0); yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(PawnRenderer), "pawn")); - yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationUtility), nameof(AnimationUtility.RenderPawnHeadMeshInAnimation))); + yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationUtility), nameof(AnimationUtility.RenderPawnHeadMeshInAnimation), new Type[] { typeof(Mesh), typeof(Vector3), typeof(Quaternion), typeof(Material), typeof(bool), typeof(Pawn) })); } else { diff --git a/Source/Settings/AnimationSettings.cs b/Source/Settings/AnimationSettings.cs index b37e614..b563e0c 100644 --- a/Source/Settings/AnimationSettings.cs +++ b/Source/Settings/AnimationSettings.cs @@ -43,6 +43,11 @@ namespace Rimworld_Animations { listingStandard.CheckboxLabeled("Enable Sound Override", ref AnimationSettings.soundOverride); listingStandard.CheckboxLabeled("Control Genital Rotation", ref AnimationSettings.controlGenitalRotation); listingStandard.CheckboxLabeled("Apply Semen on Animation Orgasm", ref AnimationSettings.applySemenOnAnimationOrgasm); + + if(AnimationSettings.applySemenOnAnimationOrgasm) { + listingStandard.Label("Recommended--turn down \"Cum on body percent\" in RJW settings to about 33%"); + } + listingStandard.CheckboxLabeled("Enable Orgasm Quiver", ref AnimationSettings.orgasmQuiver); listingStandard.CheckboxLabeled("Enable Rape Shiver", ref AnimationSettings.rapeShiver); listingStandard.CheckboxLabeled("Enable hearts during lovin'", ref AnimationSettings.hearts);