using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BoneLib.BoneMenu; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Marrow.AI; using Il2CppSLZ.Marrow.Combat; using Il2CppSLZ.Marrow.Data; using Il2CppSLZ.Marrow.PuppetMasta; using InjuriesMod.Core; using InjuriesMod.Modules; using MelonLoader; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(ModClass), "Brain Injuries", "2.2.0", "PolskiAnt", "https://thunderstore.io/c/bonelab/p/PolskiAnt/BrainInjuries/")] [assembly: AssemblyTitle("Brain Injuries")] [assembly: AssemblyDescription("Adds a little realism to the game (PATCH 6)")] [assembly: MelonColor(255, 200, 30, 20)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("InjuriesMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("InjuriesMod")] [assembly: AssemblyVersion("1.0.0.0")] namespace InjuriesMod.Patches { [HarmonyPatch(typeof(SubBehaviourHealth), "TakeDamage")] public static class DamagePatch { private static readonly Random rnd = new Random(); public static void Prefix(SubBehaviourHealth __instance, int m, Attack attack) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Invalid comparison between Unknown and I4 //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Invalid comparison between Unknown and I4 //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Invalid comparison between Unknown and I4 //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Invalid comparison between Unknown and I4 //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Invalid comparison between Unknown and I4 //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Invalid comparison between Unknown and I4 if (__instance.muscles == null || m >= ((Il2CppArrayBase)(object)__instance.muscles).Count) { return; } PuppetMaster puppetMaster = ((SubBehaviourBase)__instance).behaviour.puppetMaster; if ((Object)(object)puppetMaster == (Object)null) { return; } ReactionContext reactionContext = new ReactionContext(puppetMaster); if (!reactionContext.IsValid()) { return; } string text = ((object)((Il2CppArrayBase)(object)__instance.muscles)[m]/*cast due to .constrained prefix*/).ToString(); if (!DeathTracker.PriorityDeathCause.ContainsKey(reactionContext.Ptr)) { DeathTracker.LastHitBone[reactionContext.Ptr] = ((text == "Head" && (int)attack.attackType != 2 && (int)attack.attackType != 1) ? "Unknown" : text); } if (text == "Head" && (int)attack.attackType == 2 && ModClass.HeadBluntResistEnabled) { attack.damage *= 0.7f; } if (text == "Head") { DeathTracker.LastAttackType[reactionContext.Ptr] = attack.attackType; DeathTracker.LastAttackDamage[reactionContext.Ptr] = attack.damage; if (attack.damage > 5f && ((int)attack.attackType == 2 || (int)attack.attackType == 1)) { DeathTracker.PriorityDeathCause[reactionContext.Ptr] = "Head"; } if (attack.damage > 2f && attack.damage <= 5f && (int)attack.attackType == 2 && ModClass.UnconsciousEnabled && !DeathTracker.AlreadyDead.Contains(reactionContext.Ptr) && !DeathTracker.UnconsciousNPCs.Contains(reactionContext.Ptr) && rnd.Next(101) <= 50) { DeathTracker.UnconsciousNPCs.Add(reactionContext.Ptr); DeathTracker.UnconsciousStartTime[reactionContext.Ptr] = Time.time; MelonCoroutines.Start(ModuleD_Consciousness.Unconscious(reactionContext.Puppet)); } } if (text == "Spine" && ModClass.TorsoArmorEnabled) { attack.damage *= 0.5f; } } } [HarmonyPatch(typeof(PuppetMaster), "Kill", new Type[] { })] public static class DeathPatch { public static void Postfix(PuppetMaster __instance) { //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return; } ReactionContext reactionContext = new ReactionContext(__instance); if (!reactionContext.IsValid() || DeathTracker.AlreadyDead.Contains(reactionContext.Ptr)) { return; } DeathTracker.AlreadyDead.Add(reactionContext.Ptr); string value; string value2; string text = (DeathTracker.PriorityDeathCause.TryGetValue(reactionContext.Ptr, out value) ? value : ((!DeathTracker.LastHitBone.TryGetValue(reactionContext.Ptr, out value2)) ? "Unknown" : value2)); if (!ModClass.BrainInjuriesEnabled) { text = "Disabled"; } if (DeathTracker.UnconsciousNPCs.Contains(reactionContext.Ptr)) { ((MelonBase)ModClass.Instance).LoggerInstance.Msg("NPC died while unconscious."); PhysicsHelper.ApplyProfile(reactionContext.Puppet); DeathTracker.UnconsciousNPCs.Remove(reactionContext.Ptr); return; } ((MelonBase)ModClass.Instance).LoggerInstance.Msg("NPC died | cause: " + text); if (!(text != "Head")) { AttackType value3; AttackType attackType = (AttackType)((!DeathTracker.LastAttackType.TryGetValue(reactionContext.Ptr, out value3)) ? 64 : ((int)value3)); float value4; float damage = (DeathTracker.LastAttackDamage.TryGetValue(reactionContext.Ptr, out value4) ? value4 : 0f); MelonCoroutines.Start(ModuleA_Impact.HandleImpact(reactionContext.Puppet, attackType, damage)); } } } [HarmonyPatch(typeof(PuppetMaster))] public static class PuppetMasterLifecyclePatches { [HarmonyPatch("OnEnable")] [HarmonyPostfix] public static void OnEnablePostfix(PuppetMaster __instance) { if (!((Object)(object)__instance == (Object)null) && !(((Il2CppObjectBase)__instance).Pointer == IntPtr.Zero)) { IntPtr pointer = ((Il2CppObjectBase)__instance).Pointer; if (DeathTracker.TryRegisterSpawn(pointer, out var currentGeneration)) { PhysicsHelper.EnsureBindPoseCached(__instance); MelonLogger.Msg($"[Diag] NPC spawned: {pointer}, Gen Token: {currentGeneration}"); } } } [HarmonyPatch("OnDisable")] [HarmonyPrefix] public static void OnDisablePrefix(PuppetMaster __instance) { if ((Object)(object)__instance != (Object)null && ((Il2CppObjectBase)__instance).Pointer != IntPtr.Zero) { PhysicsHelper.ResetProfile(__instance); DeathTracker.ClearNPC(((Il2CppObjectBase)__instance).Pointer); } } [HarmonyPatch("OnDestroy")] [HarmonyPrefix] public static void OnDestroyPrefix(PuppetMaster __instance) { if ((Object)(object)__instance != (Object)null && ((Il2CppObjectBase)__instance).Pointer != IntPtr.Zero) { PhysicsHelper.ResetProfile(__instance); DeathTracker.ClearNPC(((Il2CppObjectBase)__instance).Pointer); } } } } namespace InjuriesMod.Modules { public static class JointSpaceHelper { public static Quaternion GetCurrentRelativeRotation(ConfigurableJoint joint, Quaternion initialLocalRotation) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) Vector3 axis = ((Joint)joint).axis; Vector3 val = Vector3.Cross(((Joint)joint).axis, joint.secondaryAxis); Vector3 normalized = ((Vector3)(ref val)).normalized; val = Vector3.Cross(normalized, axis); Vector3 normalized2 = ((Vector3)(ref val)).normalized; Quaternion val2 = Quaternion.LookRotation(normalized, normalized2); Quaternion localRotation = ((Component)joint).transform.localRotation; Quaternion val3 = Quaternion.Inverse(val2); val3 *= Quaternion.Inverse(localRotation) * initialLocalRotation; return val3 * val2; } } public static class ModuleA_Impact { public enum ImmediateReaction { FlaccidParalysis, None, Posturing, ForwardBuckle, Fencing } public enum PostureTendency { None, Flexor, Extensor, Mixed } public static IEnumerator HandleImpact(PuppetMaster puppet, AttackType attackType, float damage) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!ModClass.BrainInjuriesEnabled) { yield break; } ReactionContext ctx = new ReactionContext(puppet); if (!ctx.IsValid()) { yield break; } ImmediateReaction reaction = ChooseImmediateReaction(attackType, damage); if (!ModClass.BrainInjuriesEnabled) { reaction = ImmediateReaction.None; } ((MelonBase)ModClass.Instance).LoggerInstance.Msg($"[ModuleA] Reaction: {reaction}"); if (ModClass.SeizuresEnabled) { if (1 == 0) { } float num = (((int)attackType == 1) ? ModClass.SeizureChancePiercing : (((int)attackType != 2) ? 0f : ModClass.SeizureChanceBlunt)); if (1 == 0) { } float seizureChance = num; if (seizureChance > 0f && DeathTracker.Rng.NextDouble() * 100.0 < (double)seizureChance) { ModuleC_Seizures.Start(ctx.Ptr, Random.Range(0.5f, 0.9f), Random.Range(5f, 10f)); } } yield return MelonCoroutines.Start(RunImmediateReaction(ctx.Puppet, reaction, attackType, damage)); } private static PostureTendency ChoosePostureTendency(AttackType attackType) { int[] array = new int[3] { 35, 25, 40 }; PostureTendency[] array2 = new PostureTendency[3] { PostureTendency.Flexor, PostureTendency.Extensor, PostureTendency.Mixed }; float num = 0f; float[] array3 = new float[array2.Length]; for (int i = 0; i < array2.Length; i++) { float multiplier = ModClass.GetMultiplier(ModClass.PosturingSettings[array2[i]]); array3[i] = (float)array[i] * multiplier; num += array3[i]; } if (num <= 0f) { return PostureTendency.None; } double num2 = DeathTracker.Rng.NextDouble() * (double)num; float num3 = 0f; for (int j = 0; j < array3.Length; j++) { num3 += array3[j]; if (num2 < (double)num3) { return array2[j]; } } return array2[0]; } private static ImmediateReaction ChooseImmediateReaction(AttackType attackType, float damage) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 if ((int)attackType == 1) { int[] baseWeights = new int[4] { 40, 15, 25, 20 }; return WeightedRandom(new ImmediateReaction[4] { ImmediateReaction.FlaccidParalysis, ImmediateReaction.None, ImmediateReaction.Posturing, ImmediateReaction.ForwardBuckle }, baseWeights); } if ((int)attackType == 2) { if (damage >= 5f) { int[] baseWeights2 = new int[5] { 25, 35, 15, 10, 15 }; return WeightedRandom(new ImmediateReaction[5] { ImmediateReaction.FlaccidParalysis, ImmediateReaction.Posturing, ImmediateReaction.Fencing, ImmediateReaction.None, ImmediateReaction.ForwardBuckle }, baseWeights2); } if (damage >= 2f) { int[] baseWeights3 = new int[5] { 15, 15, 45, 15, 10 }; return WeightedRandom(new ImmediateReaction[5] { ImmediateReaction.FlaccidParalysis, ImmediateReaction.Posturing, ImmediateReaction.Fencing, ImmediateReaction.None, ImmediateReaction.ForwardBuckle }, baseWeights3); } int[] baseWeights4 = new int[5] { 20, 5, 0, 60, 15 }; return WeightedRandom(new ImmediateReaction[5] { ImmediateReaction.FlaccidParalysis, ImmediateReaction.Posturing, ImmediateReaction.Fencing, ImmediateReaction.None, ImmediateReaction.ForwardBuckle }, baseWeights4); } int[] baseWeights5 = new int[3] { 45, 45, 10 }; return WeightedRandom(new ImmediateReaction[3] { ImmediateReaction.FlaccidParalysis, ImmediateReaction.None, ImmediateReaction.ForwardBuckle }, baseWeights5); } private static ImmediateReaction WeightedRandom(ImmediateReaction[] options, int[] baseWeights) { float num = 0f; float[] array = new float[options.Length]; for (int i = 0; i < options.Length; i++) { float multiplier = ModClass.GetMultiplier(ModClass.UserSettings[options[i]]); array[i] = (float)baseWeights[i] * multiplier; num += array[i]; } if (num <= 0f) { return ImmediateReaction.None; } double num2 = DeathTracker.Rng.NextDouble() * (double)num; float num3 = 0f; for (int j = 0; j < array.Length; j++) { num3 += array[j]; if (num2 < (double)num3) { return options[j]; } } return options[^1]; } private static IEnumerator RunImmediateReaction(PuppetMaster puppet, ImmediateReaction reaction, AttackType attackType, float damage) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) ReactionContext ctx = new ReactionContext(puppet); if (ctx.IsValid()) { switch (reaction) { case ImmediateReaction.Posturing: { PostureTendency tendency = ChoosePostureTendency(attackType); float intensity = Random.Range(0.6f, 1f); yield return RunPosturing(onsetDelay: (Random.value < 0.5f) ? 0f : Random.Range(0.1f, 0.4f), blendInTime: Mathf.Lerp(0.5f, 0.15f, intensity), holdTime: Mathf.Lerp(2f, 8f, intensity), puppet: ctx.Puppet, tendency: tendency, intensity: intensity, decayTime: 6f); break; } case ImmediateReaction.FlaccidParalysis: yield return FlaccidParalysis(ctx.Puppet); break; case ImmediateReaction.ForwardBuckle: yield return ForwardBuckle(ctx.Puppet); break; case ImmediateReaction.Fencing: yield return Fencing(ctx.Puppet); break; case ImmediateReaction.None: yield return Collapse(ctx.Puppet); break; } } } private static IEnumerator RunPosturing(PuppetMaster puppet, PostureTendency tendency, float intensity, float onsetDelay, float blendInTime, float holdTime, float decayTime) { if (tendency == PostureTendency.None || intensity <= 0f) { yield break; } ReactionContext ctx = new ReactionContext(puppet); if (!ctx.IsValid()) { yield break; } Dictionary originalWeights = PhysicsHelper.SaveMuscleWeights(ctx.Puppet); if (onsetDelay > 0f) { float delayTimer = 0f; while (delayTimer < onsetDelay) { if (ctx.IsValid()) { delayTimer += Time.deltaTime; yield return null; continue; } yield break; } } if (!ctx.IsValid()) { yield break; } Quaternion flexElbow = Quaternion.Euler(50f, 0f, 0f); Quaternion flexWrist = Quaternion.Euler(50f, 0f, 0f); Quaternion flexShoulder = Quaternion.Euler(0f, 0f, 0f); Quaternion extendKneeSubtle = Quaternion.Euler(-8f, 0f, 0f); Quaternion extendAnkleSubtle = Quaternion.Euler(-20f, 0f, 0f); Quaternion extElbow = Quaternion.Euler(-50f, 0f, 0f); Quaternion extWrist = Quaternion.Euler(-40f, 0f, 0f); Quaternion extShoulder = Quaternion.Euler(-15f, 0f, -15f); Quaternion extendKnee = Quaternion.Euler(15f, 0f, 0f); Quaternion extendAnkle = Quaternion.Euler(20f, 0f, 0f); float totalDuration = blendInTime + holdTime + decayTime; float e = 0f; try { while (e < totalDuration && ctx.IsValid()) { ModuleC_Seizures.Tick(ctx.Ptr); float strength = ((e < blendInTime) ? (Mathf.Clamp01(e / blendInTime) * intensity) : ((!(e < blendInTime + holdTime)) ? Mathf.Lerp(intensity, 0f, (e - blendInTime - holdTime) / decayTime) : intensity)); if (!DeathTracker.BindPoseRotations.TryGetValue(ctx.Ptr, out var bindPose)) { bindPose = PhysicsHelper.SaveInitialLocalRotations(ctx.Puppet); } Dictionary livePose = PhysicsHelper.SaveMuscleCurrentPose(ctx.Puppet, bindPose); foreach (Muscle muscle in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (muscle == null) { continue; } string name = muscle.name.ToLower(); ConfigurableJoint joint = ((Component)muscle.transform).GetComponent(); if ((Object)(object)joint == (Object)null || !livePose.TryGetValue(muscle.name, out var currentPose)) { continue; } bool isKnee = name.Contains("knee"); bool isAnkle = name.Contains("ankle"); bool isElbow = name.Contains("elbow"); bool isWrist = name.Contains("wrist"); bool isShoulder = name.Contains("shoulder"); bool isLeg = isKnee || isAnkle || name.Contains("hip"); Quaternion offset = Quaternion.identity; bool matched = true; switch (tendency) { case PostureTendency.Flexor: if (isElbow) { offset = flexElbow; } else if (isWrist) { offset = flexWrist; } else if (isShoulder) { offset = flexShoulder; } else if (isKnee) { offset = extendKneeSubtle; } else if (isAnkle) { offset = extendAnkleSubtle; } else { matched = false; } break; case PostureTendency.Extensor: if (isElbow) { offset = extElbow; } else if (isWrist) { offset = extWrist; } else if (isShoulder) { offset = extShoulder; } else if (isKnee) { offset = extendKnee; } else if (isAnkle) { offset = extendAnkle; } else { matched = false; } break; case PostureTendency.Mixed: if (isElbow) { offset = flexElbow; } else if (isWrist) { offset = flexWrist; } else if (isShoulder) { offset = flexShoulder; } else if (isKnee) { offset = extendKnee; } else if (isAnkle) { offset = extendAnkle; } else { matched = false; } break; } if (matched) { (float, float) modifiers = ModuleC_Seizures.GetModifiers(ctx.Ptr, muscle.name); float seizureMultiplier = modifiers.Item1; float seizureAngleOffset = modifiers.Item2; Quaternion target = currentPose * Quaternion.Slerp(Quaternion.identity, offset, strength); target *= Quaternion.Euler(seizureAngleOffset, 0f, 0f); joint.targetRotation = target; float legFactor = (isLeg ? 1.5f : 0.7f); float absoluteMaxForce = (isLeg ? Mathf.Lerp(20f, 400f, strength) : Mathf.Lerp(15f, 200f, strength)); float finalStrength = strength * legFactor * seizureMultiplier; PhysicsHelper.SetJointDrive(joint, 2300f * finalStrength, 800f * finalStrength, absoluteMaxForce); muscle.props.muscleWeight = finalStrength; } } e += Time.deltaTime; yield return null; bindPose = null; } } finally { if ((Object)(object)ctx.Puppet != (Object)null && (Object)(object)ctx.Root != (Object)null) { PhysicsHelper.RestoreAndResetJoints(ctx.Puppet, originalWeights); } } } private static IEnumerator ForwardBuckle(PuppetMaster puppet) { ReactionContext ctx = new ReactionContext(puppet); if (!ctx.IsValid()) { yield break; } Dictionary originalWeights = PhysicsHelper.SaveMuscleWeights(ctx.Puppet); if (!DeathTracker.BindPoseRotations.TryGetValue(ctx.Ptr, out var _)) { PhysicsHelper.SaveInitialLocalRotations(ctx.Puppet); } if (!ctx.IsValid()) { yield break; } Rigidbody chestRb = null; foreach (Muscle m in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (m != null && m.name.ToLower().Contains("chest")) { chestRb = ((Component)m.transform).GetComponent(); break; } } if ((Object)(object)chestRb != (Object)null) { Vector3 forwardDir = -((Component)chestRb).transform.right; chestRb.AddForce(forwardDir * 5.5f, (ForceMode)2); } float fallDuration = Random.Range(1f, 1.3f); float e1 = 0f; try { while (e1 < fallDuration && ctx.IsValid()) { ModuleC_Seizures.Tick(ctx.Ptr); float bendProgress = Mathf.Clamp01(e1 / 0.45f); float easeBend = bendProgress * bendProgress; float currentSpring = Mathf.Lerp(900f, 20f, bendProgress); float currentDamping = Mathf.Lerp(150f, 5f, bendProgress); float muscleWeight = Mathf.Lerp(0.85f, 0.05f, bendProgress); foreach (Muscle muscle in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (muscle == null) { continue; } string name = muscle.name.ToLower(); ConfigurableJoint joint = ((Component)muscle.transform).GetComponent(); if ((Object)(object)joint == (Object)null) { continue; } var (seizureMultiplier, seizureAngleOffset) = ModuleC_Seizures.GetModifiers(ctx.Ptr, muscle.name); _ = Quaternion.identity; Quaternion targetOffset; if (name.Contains("spine")) { targetOffset = Quaternion.Slerp(Quaternion.identity, Quaternion.Euler(-75f, 0f, 0f), easeBend); } else if (name.Contains("chest")) { targetOffset = Quaternion.Slerp(Quaternion.identity, Quaternion.Euler(-60f, 0f, 0f), easeBend); } else { if (!name.Contains("hip")) { if (name.Contains("knee")) { float kneeSpring = ((e1 < 0.35f) ? 400f : currentSpring); PhysicsHelper.SetJointDrive(joint, kneeSpring * seizureMultiplier, currentDamping, kneeSpring * seizureMultiplier); muscle.props.muscleWeight = ((e1 < 0.35f) ? 0.9f : muscleWeight) * seizureMultiplier; } continue; } targetOffset = Quaternion.Slerp(Quaternion.identity, Quaternion.Euler(150f, 0f, 0f), easeBend); } joint.targetRotation = targetOffset * Quaternion.Euler(seizureAngleOffset, 0f, 0f); PhysicsHelper.SetJointDrive(joint, currentSpring * seizureMultiplier, currentDamping, currentSpring * seizureMultiplier); muscle.props.muscleWeight = muscleWeight * seizureMultiplier; } e1 += Time.deltaTime; yield return null; } } finally { PhysicsHelper.RestoreAndResetJoints(ctx.Puppet, originalWeights); } } private static IEnumerator FlaccidParalysis(PuppetMaster puppet) { ReactionContext ctx = new ReactionContext(puppet); if (!ctx.IsValid()) { yield break; } Dictionary originalWeights = PhysicsHelper.SaveMuscleWeights(ctx.Puppet); if (!DeathTracker.BindPoseRotations.TryGetValue(ctx.Ptr, out var localRotations)) { localRotations = PhysicsHelper.SaveInitialLocalRotations(ctx.Puppet); } float jerkDuration = Random.Range(0.02f, 0.05f); float jerkStrength = Random.Range(0.8f, 1.5f); Dictionary currentPoseBeforeJerk = PhysicsHelper.SaveMuscleCurrentPose(ctx.Puppet, localRotations); MelonCoroutines.Start(SuppressHitReaction(ctx.Puppet)); Dictionary jerkOffsets = new Dictionary(); foreach (Muscle muscle in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (muscle != null) { Vector3 randEuler = new Vector3(Random.Range(-40f, 40f), Random.Range(-50f, 50f), Random.Range(-30f, 30f)); Quaternion cp; Quaternion basePose = (currentPoseBeforeJerk.TryGetValue(muscle.name, out cp) ? cp : Quaternion.identity); jerkOffsets[muscle.name] = basePose * Quaternion.Euler(randEuler); } } ApplyImpactImpulse(ctx.Puppet); float e0 = 0f; try { while (e0 < jerkDuration) { if (!ctx.IsValid()) { yield break; } float t = Mathf.Clamp01(e0 / jerkDuration); foreach (Muscle muscle2 in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (muscle2 != null) { ConfigurableJoint joint = ((Component)muscle2.transform).GetComponent(); if (!((Object)(object)joint == (Object)null) && jerkOffsets.TryGetValue(muscle2.name, out var offset) && currentPoseBeforeJerk.TryGetValue(muscle2.name, out var basePose2)) { joint.targetRotation = Quaternion.Slerp(basePose2, offset, t); PhysicsHelper.SetJointDrive(joint, 2500f * jerkStrength, 400f * jerkStrength, 60f); muscle2.props.muscleWeight = jerkStrength; } } } e0 += Time.deltaTime; yield return null; } if (!ctx.IsValid()) { yield break; } float fallTime = Random.Range(0.8f, 1.2f); float fallStrengthTorso = 0.2f; float fallStrengthLegs = 0f; float e1 = 0f; while (e1 < fallTime) { if (!ctx.IsValid()) { yield break; } float localT = e1 / fallTime; foreach (Muscle muscle3 in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (muscle3 != null) { string name = muscle3.name.ToLower(); ConfigurableJoint joint2 = ((Component)muscle3.transform).GetComponent(); if (!((Object)(object)joint2 == (Object)null)) { bool isLeg = name.Contains("knee") || name.Contains("ankle") || name.Contains("hip"); float baseStrength = (isLeg ? fallStrengthLegs : fallStrengthTorso); float currentStrength = Mathf.Lerp(baseStrength, baseStrength * 0.3f, localT); float absoluteMaxForce = (isLeg ? 2f : 20f); PhysicsHelper.SetJointDrive(joint2, 300f * currentStrength, 100f * currentStrength, absoluteMaxForce); muscle3.props.muscleWeight = currentStrength; } } } e1 += Time.deltaTime; yield return null; } if (!ctx.IsValid()) { yield break; } Dictionary frozenTargets = PhysicsHelper.SaveMuscleCurrentPose(ctx.Puppet, localRotations); float freezeTime = 0.4f; float legDecay = 4f; float torsoDecay = 8f; float e2 = 0f; float totalDuration = freezeTime + torsoDecay; float rampIn = 0.1f; while (e2 < totalDuration && ctx.IsValid()) { ModuleC_Seizures.Tick(ctx.Ptr); foreach (Muscle muscle4 in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (muscle4 == null) { continue; } string name2 = muscle4.name.ToLower(); ConfigurableJoint joint3 = ((Component)muscle4.transform).GetComponent(); if (!((Object)(object)joint3 == (Object)null)) { bool isLeg2 = name2.Contains("knee") || name2.Contains("ankle") || name2.Contains("hip"); float decayDuration = (isLeg2 ? legDecay : torsoDecay); float localElapsed = Mathf.Max(0f, e2 - freezeTime); float strength = ((e2 < freezeTime) ? Mathf.Clamp01(e2 / rampIn) : Mathf.Clamp01(1f - localElapsed / decayDuration)); var (seizureMultiplier, seizureAngleOffset) = ModuleC_Seizures.GetModifiers(ctx.Ptr, muscle4.name); if (frozenTargets.TryGetValue(muscle4.name, out var frozenTarget)) { joint3.targetRotation = frozenTarget * Quaternion.Euler(seizureAngleOffset, 0f, 0f); } float absoluteMaxForce2 = (isLeg2 ? 40f : 25f); float legFactor = (isLeg2 ? 0.35f : 0.45f); float finalStrength = strength * legFactor * seizureMultiplier; PhysicsHelper.SetJointDrive(joint3, 300f * finalStrength, 300f * finalStrength, absoluteMaxForce2); } } e2 += Time.deltaTime; yield return null; } } finally { PhysicsHelper.RestoreAndResetJoints(ctx.Puppet, originalWeights); } } private static IEnumerator Collapse(PuppetMaster puppet) { ReactionContext ctx = new ReactionContext(puppet); if (!ctx.IsValid()) { yield break; } Dictionary originalWeights = PhysicsHelper.SaveMuscleWeights(ctx.Puppet); MelonCoroutines.Start(SuppressHitReaction(ctx.Puppet)); if (!ctx.IsValid()) { yield break; } foreach (Muscle muscle in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (muscle != null) { muscle.name.ToLower(); ConfigurableJoint joint = ((Component)muscle.transform).GetComponent(); if (!((Object)(object)joint == (Object)null)) { PhysicsHelper.SetJointDrive(joint, 0f, 0f, 0f); muscle.props.muscleWeight = 0f; } } } PhysicsHelper.RestoreAndResetJoints(ctx.Puppet, originalWeights); } private static IEnumerator Fencing(PuppetMaster puppet) { ReactionContext ctx = new ReactionContext(puppet); if (!ctx.IsValid()) { yield break; } Dictionary originalWeights = PhysicsHelper.SaveMuscleWeights(ctx.Puppet); if (!DeathTracker.BindPoseRotations.TryGetValue(ctx.Ptr, out var bindPose)) { bindPose = PhysicsHelper.SaveInitialLocalRotations(ctx.Puppet); } float bs = Random.Range(0.25f, 0.35f); float d = Random.Range(0.6f, 0.8f); float rt = Random.Range(0.8f, 1.5f); float e = 0f; float suppressWindow = 0.3f; bool leftIsExtended = Random.value < 0.5f; Quaternion extendedElbow = Quaternion.Euler(-10f, 0f, 0f); Quaternion extendedShoulder = Quaternion.Euler(70f, 0f, -30f); Quaternion extendedWrist = Quaternion.Euler(-10f, 0f, 0f); Quaternion flexedElbow = Quaternion.Euler(110f, 0f, 0f); Quaternion flexedShoulder = Quaternion.Euler(20f, 0f, 15f); Quaternion flexedWrist = Quaternion.Euler(60f, 0f, 0f); try { while (e < bs + d + rt && ctx.IsValid()) { float progress = PhysicsHelper.GetProgress(e, bs, d, rt); float strength = PhysicsHelper.GetStrength(e, bs, d, rt); if (e < suppressWindow) { foreach (Muscle m in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (m == null) { continue; } string mName = m.name.ToLower(); if (!mName.Contains("elbow") && !mName.Contains("shoulder") && !mName.Contains("wrist")) { Rigidbody rb = ((Component)m.transform).GetComponent(); if (!((Object)(object)rb == (Object)null)) { rb.angularVelocity = Vector3.ClampMagnitude(rb.angularVelocity, 2f); } } } } Dictionary currentPose = PhysicsHelper.SaveMuscleCurrentPose(ctx.Puppet, bindPose); foreach (Muscle muscle in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (muscle == null) { continue; } string name = muscle.name.ToLower(); ConfigurableJoint joint = ((Component)muscle.transform).GetComponent(); if (!((Object)(object)joint == (Object)null) && currentPose.TryGetValue(muscle.name, out var basePose)) { bool thisArmExtended = (name.Contains("_l") ? leftIsExtended : (!leftIsExtended)); Quaternion offset = Quaternion.identity; bool matched = true; if (name.Contains("elbow")) { offset = (thisArmExtended ? extendedElbow : flexedElbow); } else if (name.Contains("shoulder")) { offset = (thisArmExtended ? extendedShoulder : flexedShoulder); } else if (name.Contains("wrist")) { offset = (thisArmExtended ? extendedWrist : flexedWrist); } else { matched = false; } if (matched) { Quaternion target = basePose * Quaternion.Slerp(Quaternion.identity, offset, progress); joint.targetRotation = target; PhysicsHelper.SetJointDrive(joint, 2300f * strength, 700f * strength, 900f * strength); muscle.props.muscleWeight = strength; } } } e += Time.deltaTime; yield return null; } } finally { PhysicsHelper.RestoreAndResetJoints(ctx.Puppet, originalWeights); } } private static void ApplyImpactImpulse(PuppetMaster puppet) { //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) ReactionContext reactionContext = new ReactionContext(puppet); if (!reactionContext.IsValid()) { return; } Rigidbody val = null; Rigidbody val2 = null; foreach (Muscle item in (Il2CppArrayBase)(object)reactionContext.Puppet.muscles) { if (item != null) { string text = item.name.ToLower(); if (text.Contains("head")) { val = ((Component)item.transform).GetComponent(); } if (text.Contains("chest")) { val2 = ((Component)item.transform).GetComponent(); } } } Vector3 val3 = new Vector3(Random.Range(-1f, 1f), Random.Range(-0.2f, 0.3f), Random.Range(-1f, 1f)); Vector3 normalized = ((Vector3)(ref val3)).normalized; float num = Random.Range(5f, 10f); if ((Object)(object)val != (Object)null) { val.AddForce(normalized * num * 0.2f, (ForceMode)1); } if ((Object)(object)val2 != (Object)null) { val2.AddForce(normalized * num, (ForceMode)1); } } private static IEnumerator SuppressHitReaction(PuppetMaster puppet, float duration = 0.3f) { ReactionContext ctx = new ReactionContext(puppet); if (!ctx.IsValid()) { yield break; } float elapsed = 0f; float maxReasonableSpin = 2f; while (elapsed < duration && ctx.IsValid()) { foreach (Muscle m in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (m != null) { Rigidbody rb = ((Component)m.transform).GetComponent(); if (!((Object)(object)rb == (Object)null)) { Vector3 av = rb.angularVelocity; rb.angularVelocity = Vector3.ClampMagnitude(av, maxReasonableSpin); } } } elapsed += Time.fixedDeltaTime; yield return (object)new WaitForFixedUpdate(); } } } internal class ModuleC_Seizures { public struct SeizureData { public float intensity; public float frequency; public float elapsed; public float duration; } private static readonly Dictionary _active = new Dictionary(); public static void Start(IntPtr ptr, float intensity, float duration) { if (ModClass.SeizuresEnabled) { _active[ptr] = new SeizureData { intensity = Mathf.Clamp01(intensity), frequency = Mathf.Lerp(3f, 8f, intensity) * 0.8f, elapsed = 0f, duration = duration }; ((MelonBase)ModClass.Instance).LoggerInstance.Msg($"[ModuleC] Seizure start | instensity: {intensity} | duration: {duration}"); } } public static void Tick(IntPtr ptr) { if (_active.TryGetValue(ptr, out var value)) { value.elapsed += Time.deltaTime; if (value.elapsed >= value.duration) { _active.Remove(ptr); MelonLogger.Msg("[ModuleC] Seizure ended"); } else { _active[ptr] = value; } } } public static void Stop(IntPtr ptr) { _active.Remove(ptr); } public static void Clear(IntPtr ptr) { _active.Remove(ptr); } public static bool IsActive(IntPtr ptr) { return _active.ContainsKey(ptr); } public static (float strengthMultiplier, float angleOffset) GetModifiers(IntPtr ptr, string muscleName) { if (!ModClass.SeizuresEnabled) { return (strengthMultiplier: 1f, angleOffset: 0f); } if (!_active.TryGetValue(ptr, out var value)) { return (strengthMultiplier: 1f, angleOffset: 0f); } float num = 1f - Mathf.Clamp01((value.elapsed - value.duration * 0.6f) / (value.duration * 0.4f)); float num2 = value.intensity * num; float num3 = (float)(muscleName.GetHashCode() % 100) * 0.063f; float item = 1f + num2 * 2f; float item2 = Mathf.Sin(value.elapsed * value.frequency * (float)Math.PI * 2f + num3) * 20f * num2; return (strengthMultiplier: item, angleOffset: item2); } public static void ClearAll() { _active.Clear(); } } internal class ModuleD_Consciousness { public static IEnumerator Unconscious(PuppetMaster puppet, float duration = 20f) { ReactionContext ctx = new ReactionContext(puppet); if (!ctx.IsValid() || DeathTracker.AlreadyDead.Contains(ctx.Ptr)) { yield break; } BehaviourBaseNav behaviour = null; AIBrain brain = null; Animator animator = null; AIManager manager = null; try { Transform mainTransform = (((Object)(object)ctx.Puppet != (Object)null) ? ((Component)ctx.Puppet).transform : null); if ((Object)(object)mainTransform != (Object)null) { brain = ((Component)mainTransform).GetComponentInParent(); } if ((Object)(object)brain != (Object)null) { GameObject brainGO = ((Component)brain).gameObject; behaviour = brain.behaviour; if ((Object)(object)behaviour == (Object)null) { behaviour = brainGO.GetComponentInChildren(true); } animator = brainGO.GetComponentInChildren(true); manager = brainGO.GetComponentInChildren(true); } else { object obj; if (!((Object)(object)ctx.Root != (Object)null)) { if (mainTransform == null) { obj = null; } else { Transform root = mainTransform.root; obj = ((root != null) ? ((Component)root).gameObject : null); } } else { obj = ((Component)ctx.Root).gameObject; } GameObject topRoot = (GameObject)obj; if ((Object)(object)topRoot != (Object)null) { behaviour = topRoot.GetComponentInChildren(true); animator = topRoot.GetComponentInChildren(true); manager = topRoot.GetComponentInChildren(true); } } } catch (Exception ex) { Exception ex2 = ex; ((MelonBase)ModClass.Instance).LoggerInstance.Error($"[Unconscious] Exception while fetching components: {ex2}"); } if ((Object)(object)brain != (Object)null) { ((Behaviour)brain).enabled = false; } if ((Object)(object)animator != (Object)null) { ((Behaviour)animator).enabled = false; } PhysicsHelper.SaveProfile(ctx.Puppet); if (!ctx.IsValid() || DeathTracker.AlreadyDead.Contains(ctx.Ptr)) { yield break; } ctx.Puppet.angularLimitsEnabled = true; ctx.Puppet.angularLimits = true; ctx.Puppet.animationDisabledbyStates = true; ctx.Puppet.mappingWeight = 0f; ctx.Puppet.ActivateRagdoll(Object.op_Implicit((Object)(object)manager)); JointDrive val; foreach (Muscle m in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (m != null) { m.props.muscleWeight = 0f; ConfigurableJoint joint = ((Component)m.transform).GetComponent(); if ((Object)(object)joint != (Object)null) { val = default(JointDrive); ((JointDrive)(ref val)).positionSpring = 0f; ((JointDrive)(ref val)).positionDamper = 5f; JointDrive drive = (joint.angularXDrive = (joint.slerpDrive = val)); joint.angularYZDrive = drive; } } } ((MelonBase)ModClass.Instance).LoggerInstance.Msg("NPC unconcious!"); float elapsedGuard = 0f; val = default(JointDrive); ((JointDrive)(ref val)).positionSpring = 1f; ((JointDrive)(ref val)).positionDamper = 100400f; ((JointDrive)(ref val)).maximumForce = 0f; JointDrive zeroDrive = val; try { while (elapsedGuard < duration) { if (!ctx.IsValid() || DeathTracker.AlreadyDead.Contains(ctx.Ptr)) { yield break; } if (!DeathTracker.UnconsciousNPCs.Contains(ctx.Ptr)) { PhysicsHelper.ApplyProfile(ctx.Puppet); yield break; } if ((Object)(object)behaviour != (Object)null) { behaviour.locoState = (LocoState)5; } if ((Object)(object)brain != (Object)null && (Object)(object)brain.behaviour != (Object)null) { brain.behaviour.mentalState = (MentalState)0; } foreach (Muscle m2 in (Il2CppArrayBase)(object)ctx.Puppet.muscles) { if (m2 != null) { ConfigurableJoint joint2 = ((Component)m2.transform).GetComponent(); if ((Object)(object)joint2 != (Object)null) { joint2.slerpDrive = zeroDrive; joint2.angularXDrive = zeroDrive; joint2.angularYZDrive = zeroDrive; } } } elapsedGuard += Time.deltaTime; yield return (object)new WaitForFixedUpdate(); } if (!ctx.IsValid() || DeathTracker.AlreadyDead.Contains(ctx.Ptr) || (int)ctx.Puppet.state == 1 || !DeathTracker.UnconsciousNPCs.Contains(ctx.Ptr)) { yield break; } ((MelonBase)ModClass.Instance).LoggerInstance.Msg("NPC woke up!"); if ((Object)(object)animator != (Object)null) { ((Behaviour)animator).enabled = true; } if ((Object)(object)manager != (Object)null) { ((Behaviour)manager).enabled = true; } if ((Object)(object)brain != (Object)null) { ((Behaviour)brain).enabled = true; } if ((Object)(object)behaviour != (Object)null) { behaviour.locoState = (LocoState)3; } if ((Object)(object)brain != (Object)null && (Object)(object)brain.behaviour != (Object)null) { brain.behaviour.mentalState = (MentalState)2; } float recoverTime = 1.5f; float elapsed = 0f; while (elapsed < recoverTime) { if (!ctx.IsValid() || DeathTracker.AlreadyDead.Contains(ctx.Ptr) || !DeathTracker.UnconsciousNPCs.Contains(ctx.Ptr)) { yield break; } float t = elapsed / recoverTime; ctx.Puppet.mappingWeight = t; PhysicsHelper.ApplyProfile(ctx.Puppet, t); elapsed += Time.deltaTime; yield return null; } if (ctx.IsValid()) { ctx.Puppet.mappingWeight = 1f; PhysicsHelper.ApplyProfile(ctx.Puppet); } } finally { CleanupTracker(ctx.Ptr); } } private static void CleanupTracker(IntPtr ptr) { DeathTracker.UnconsciousNPCs.Remove(ptr); DeathTracker.UnconsciousStartTime.Remove(ptr); DeathTracker.Profiles.Remove(ptr); } } public static class PhysicsHelper { public static void EnsureBindPoseCached(PuppetMaster puppet) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)puppet == (Object)null || ((Il2CppObjectBase)puppet).Pointer == IntPtr.Zero || DeathTracker.BindPoseRotations.ContainsKey(((Il2CppObjectBase)puppet).Pointer)) { return; } Dictionary dictionary = new Dictionary(); foreach (Muscle item in (Il2CppArrayBase)(object)puppet.muscles) { if (item != null) { dictionary[item.name] = item.transform.localRotation; } } DeathTracker.BindPoseRotations[((Il2CppObjectBase)puppet).Pointer] = dictionary; } public static Dictionary SaveMuscleCurrentPose(PuppetMaster puppet, Dictionary initialLocalRotations) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); foreach (Muscle item in (Il2CppArrayBase)(object)puppet.muscles) { if (item != null) { ConfigurableJoint component = ((Component)item.transform).GetComponent(); if (!((Object)(object)component == (Object)null) && initialLocalRotations.TryGetValue(item.name, out var value)) { dictionary[item.name] = JointSpaceHelper.GetCurrentRelativeRotation(component, value); } } } return dictionary; } public static Dictionary SaveInitialLocalRotations(PuppetMaster puppet) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); foreach (Muscle item in (Il2CppArrayBase)(object)puppet.muscles) { if (item != null) { dictionary[item.name] = item.transform.localRotation; } } return dictionary; } public static void SetJointDrive(ConfigurableJoint joint, float spring, float damper, float maxForce) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) JointDrive val = default(JointDrive); ((JointDrive)(ref val)).positionSpring = spring; ((JointDrive)(ref val)).positionDamper = damper; ((JointDrive)(ref val)).maximumForce = maxForce; JointDrive angularYZDrive = (joint.angularXDrive = (joint.slerpDrive = val)); joint.angularYZDrive = angularYZDrive; } public static void ApplyToSpine(PuppetMaster puppet, float progress, float strength, Quaternion spineRot, Quaternion headRot, Quaternion chestRot, Quaternion hipRot) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) foreach (Muscle item in (Il2CppArrayBase)(object)puppet.muscles) { if (item == null) { continue; } string text = item.name.ToLower(); ConfigurableJoint component = ((Component)item.transform).GetComponent(); if ((Object)(object)component == (Object)null) { continue; } Quaternion identity = Quaternion.identity; if (text.Contains("spine")) { identity = spineRot; } else if (text.Contains("chest")) { identity = chestRot; } else if (text.Contains("head")) { identity = headRot; } else { if (!text.Contains("hip")) { continue; } identity = hipRot; } component.targetRotation = Quaternion.Slerp(Quaternion.identity, identity, progress); SetJointDrive(component, 3000f * strength, 800f * strength, 3000f * strength); item.props.muscleWeight = strength; } } public static void ApplyToMuscles(PuppetMaster puppet, float progress, float strength, Quaternion elbowRot, Quaternion wristRot, Quaternion shoulderRot, Quaternion kneeRot, Quaternion ankleRot, string sideFilter = null, bool includeLegs = true, bool includeArms = true) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) ModuleC_Seizures.Tick(((Il2CppObjectBase)puppet).Pointer); foreach (Muscle item3 in (Il2CppArrayBase)(object)puppet.muscles) { if (item3 == null) { continue; } string text = item3.name.ToLower(); if (sideFilter != null && !text.Contains(sideFilter)) { continue; } ConfigurableJoint component = ((Component)item3.transform).GetComponent(); if ((Object)(object)component == (Object)null) { continue; } Quaternion identity = Quaternion.identity; bool flag = text.Contains("knee") || text.Contains("ankle") || text.Contains("hip"); bool flag2 = text.Contains("wrist") || text.Contains("shoulder") || text.Contains("elbow"); if ((flag && !includeLegs) || (flag2 && !includeArms)) { continue; } if (text.Contains("elbow")) { identity = elbowRot; } else if (text.Contains("wrist")) { identity = wristRot; } else if (text.Contains("shoulder")) { identity = shoulderRot; } else if (text.Contains("knee")) { identity = kneeRot; } else { if (!text.Contains("ankle")) { continue; } identity = ankleRot; } (float strengthMultiplier, float angleOffset) modifiers = ModuleC_Seizures.GetModifiers(((Il2CppObjectBase)puppet).Pointer, item3.name); float item = modifiers.strengthMultiplier; float item2 = modifiers.angleOffset; Quaternion val = Quaternion.Slerp(Quaternion.identity, identity, progress); val *= Quaternion.Euler(item2, 0f, 0f); component.targetRotation = val; float num = strength * item; float num2 = (flag ? 0.35f : 1f); SetJointDrive(component, 3000f * num, 800f * num * num2, 3000f * num * num2); item3.props.muscleWeight = num; } } public static float GetProgress(float e, float bs, float d, float rt) { return (e < bs) ? Mathf.Clamp01(e / bs) : 1f; } public static float GetStrength(float e, float bs, float d, float rt) { if (e < bs) { return Mathf.Clamp01(e / bs); } if (e < bs + d) { return 1f; } return 1f - Mathf.Clamp01((e - bs - d) / rt); } public static void RestoreAndResetJoints(PuppetMaster puppet, Dictionary originalWeights) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)puppet == (Object)null || ((Il2CppObjectBase)puppet).Pointer == IntPtr.Zero) { return; } foreach (Muscle item in (Il2CppArrayBase)(object)puppet.muscles) { if (item != null) { if (originalWeights.TryGetValue(item.name, out var value)) { item.props.muscleWeight = value; } ConfigurableJoint component = ((Component)item.transform).GetComponent(); if (!((Object)(object)component == (Object)null)) { SetJointDrive(component, 0f, 0f, 0f); component.targetRotation = Quaternion.identity; } } } } public static Dictionary SaveMuscleWeights(PuppetMaster puppet) { Dictionary dictionary = new Dictionary(); foreach (Muscle item in (Il2CppArrayBase)(object)puppet.muscles) { if (item != null) { dictionary[item.name] = item.props.muscleWeight; } } return dictionary; } public static void SaveProfile(PuppetMaster puppet) { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)puppet == (Object)null || ((Il2CppObjectBase)puppet).Pointer == IntPtr.Zero) { return; } NPCMuscleProfile nPCMuscleProfile = new NPCMuscleProfile(); foreach (Muscle item in (Il2CppArrayBase)(object)puppet.muscles) { if (item != null) { nPCMuscleProfile.MaxForces[item.name] = item._maxForce; nPCMuscleProfile.MuscleWeights[item.name] = item.props.muscleWeight; nPCMuscleProfile.MuscleDampers[item.name] = item.props.muscleDamper; ConfigurableJoint component = ((Component)item.transform).GetComponent(); if ((Object)(object)component != (Object)null) { nPCMuscleProfile.Drives[item.name] = component.slerpDrive; } } } DeathTracker.Profiles[((Il2CppObjectBase)puppet).Pointer] = nPCMuscleProfile; } public static void ApplyProfile(PuppetMaster puppet, float t = 1f) { //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)puppet == (Object)null || ((Il2CppObjectBase)puppet).Pointer == IntPtr.Zero || !DeathTracker.Profiles.TryGetValue(((Il2CppObjectBase)puppet).Pointer, out var value)) { return; } foreach (Muscle item in (Il2CppArrayBase)(object)puppet.muscles) { if (item == null) { continue; } if (value.MaxForces.TryGetValue(item.name, out var value2)) { item._maxForce = Mathf.Lerp(0f, value2, t); } if (value.MuscleWeights.TryGetValue(item.name, out var value3)) { item.props.muscleWeight = Mathf.Lerp(0f, value3, t); } if (value.MuscleDampers.TryGetValue(item.name, out var value4)) { item.props.muscleDamper = Mathf.Lerp(0f, value4, t); } if (t >= 1f) { ConfigurableJoint component = ((Component)item.transform).GetComponent(); if ((Object)(object)component != (Object)null && value.Drives.TryGetValue(item.name, out var value5)) { component.slerpDrive = value5; component.angularXDrive = value5; component.angularYZDrive = value5; } } } } public static void ResetProfile(PuppetMaster puppet) { if (!DeathTracker.Profiles.TryGetValue(((Il2CppObjectBase)puppet).Pointer, out var value)) { return; } foreach (Muscle item in (Il2CppArrayBase)(object)puppet.muscles) { if (item != null) { if (value.MaxForces.TryGetValue(item.name, out var value2)) { item._maxForce = value2; } if (value.MuscleWeights.TryGetValue(item.name, out var value3)) { item.props.muscleWeight = value3; } if (value.MuscleDampers.TryGetValue(item.name, out var value4)) { item.props.muscleDamper = value4; } } } } public static string ShowStats(PuppetMaster puppet) { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)puppet == (Object)null || ((Il2CppObjectBase)puppet).Pointer == IntPtr.Zero) { return "Puppet NULL"; } float value = -1f; float value2 = -1f; float mappingWeight = puppet.mappingWeight; float value3 = -1f; float value4 = -1f; float value5 = -1f; foreach (Muscle item in (Il2CppArrayBase)(object)puppet.muscles) { if (item != null) { value = item.props.muscleWeight; value2 = item.props.muscleDamper; value3 = item._maxForce; ConfigurableJoint component = ((Component)item.transform).GetComponent(); if ((Object)(object)component != (Object)null) { JointDrive slerpDrive = component.slerpDrive; value4 = ((JointDrive)(ref slerpDrive)).positionSpring; slerpDrive = component.slerpDrive; value5 = ((JointDrive)(ref slerpDrive)).positionDamper; } break; } } return $"[Diag] mWeight={value}, mDamper={value2}, maxForce={value3} | mapWeight={mappingWeight}, DriveSpring={value4}, DriveDamper={value5}"; } } } namespace InjuriesMod.Core { public class NPCMuscleProfile { public Dictionary MaxForces = new Dictionary(); public Dictionary MuscleWeights = new Dictionary(); public Dictionary MuscleDampers = new Dictionary(); public Dictionary Drives = new Dictionary(); } public static class DeathTracker { public static Dictionary Profiles = new Dictionary(); public static Dictionary PointerGeneration = new Dictionary(); public static Dictionary LastRegisteredFrame = new Dictionary(); public static HashSet AlreadyDead = new HashSet(); public static HashSet UnconsciousNPCs = new HashSet(); public static Dictionary UnconsciousStartTime = new Dictionary(); public static Dictionary LastHitBone = new Dictionary(); public static Dictionary PriorityDeathCause = new Dictionary(); public static Dictionary LastAttackType = new Dictionary(); public static Dictionary LastAttackDamage = new Dictionary(); public static Dictionary> BindPoseRotations = new Dictionary>(); public static Random Rng = new Random(); public static bool TryRegisterSpawn(IntPtr ptr, out int currentGeneration) { currentGeneration = -1; if (ptr == IntPtr.Zero) { return false; } int frameCount = Time.frameCount; if (LastRegisteredFrame.TryGetValue(ptr, out var value) && value == frameCount) { currentGeneration = ((!PointerGeneration.TryGetValue(ptr, out var value2)) ? 1 : value2); return false; } LastRegisteredFrame[ptr] = frameCount; if (PointerGeneration.TryGetValue(ptr, out var value3)) { currentGeneration = value3 + 1; } else { currentGeneration = 1; } PointerGeneration[ptr] = currentGeneration; return true; } public static void ClearNPC(IntPtr ptr) { if (!(ptr == IntPtr.Zero) && (AlreadyDead.Contains(ptr) || LastHitBone.ContainsKey(ptr) || UnconsciousNPCs.Contains(ptr) || LastAttackType.ContainsKey(ptr) || BindPoseRotations.ContainsKey(ptr) || Profiles.ContainsKey(ptr))) { ((MelonBase)ModClass.Instance).LoggerInstance.Msg($"Clearing NPC data (ptr: {ptr})"); ModuleC_Seizures.Clear(ptr); AlreadyDead.Remove(ptr); UnconsciousNPCs.Remove(ptr); UnconsciousStartTime.Remove(ptr); LastHitBone.Remove(ptr); PriorityDeathCause.Remove(ptr); LastAttackType.Remove(ptr); LastAttackDamage.Remove(ptr); BindPoseRotations.Remove(ptr); Profiles.Remove(ptr); } } public static void ClearAll() { AlreadyDead.Clear(); UnconsciousNPCs.Clear(); UnconsciousStartTime.Clear(); LastHitBone.Clear(); PriorityDeathCause.Clear(); LastAttackType.Clear(); LastAttackDamage.Clear(); BindPoseRotations.Clear(); Profiles.Clear(); } } public class ModClass : MelonMod { public enum FrequencyScale { None, Rare, Default, Common, Always } public static ModClass Instance; public static bool UnconsciousEnabled = true; public static bool BrainInjuriesEnabled = true; public static bool TorsoArmorEnabled = true; public static bool HeadBluntResistEnabled = true; public static bool SeizuresEnabled = true; public static float SeizureChanceBlunt = 20f; public static float SeizureChancePiercing = 8f; public static Dictionary UserSettings = new Dictionary { { ModuleA_Impact.ImmediateReaction.FlaccidParalysis, FrequencyScale.Default }, { ModuleA_Impact.ImmediateReaction.Posturing, FrequencyScale.Default }, { ModuleA_Impact.ImmediateReaction.ForwardBuckle, FrequencyScale.Default }, { ModuleA_Impact.ImmediateReaction.Fencing, FrequencyScale.Default }, { ModuleA_Impact.ImmediateReaction.None, FrequencyScale.Default } }; public static Dictionary PosturingSettings = new Dictionary { { ModuleA_Impact.PostureTendency.Flexor, FrequencyScale.Default }, { ModuleA_Impact.PostureTendency.Extensor, FrequencyScale.Default }, { ModuleA_Impact.PostureTendency.Mixed, FrequencyScale.Default }, { ModuleA_Impact.PostureTendency.None, FrequencyScale.Default } }; public override void OnInitializeMelon() { Harmony.CreateAndPatchAll(typeof(ModClass).Assembly, (string)null); SetupBoneMenu(); Instance = this; ((MelonBase)this).LoggerInstance.Msg("Mod loaded!"); } public static float GetMultiplier(FrequencyScale scale) { if (1 == 0) { } float result = scale switch { FrequencyScale.None => 0f, FrequencyScale.Rare => 0.5f, FrequencyScale.Default => 1f, FrequencyScale.Common => 2f, FrequencyScale.Always => 10f, _ => 1f, }; if (1 == 0) { } return result; } private static void SetupBoneMenu() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) Color val = default(Color); ((Color)(ref val))..ctor(1f, 0.988f, 0.729f); Color val2 = default(Color); ((Color)(ref val2))..ctor(1f, 0.25f, 0.25f); Page val3 = Page.Root.CreatePage("Brain Injuries", val2, 0, true); Page val4 = val3.CreatePage("GENERAL SETTINGS", val, 0, true); val4.CreateBool("Knockouts / Unconscious", Color.cyan, true, (Action)delegate(bool v) { UnconsciousEnabled = v; }); val4.CreateBool("Brain Injuries", Color.yellow, true, (Action)delegate(bool v) { BrainInjuriesEnabled = v; }); val4.CreateBool("Seizures", Color.yellow, true, (Action)delegate(bool v) { SeizuresEnabled = v; if (!v) { ModuleC_Seizures.ClearAll(); } }); Page val5 = val3.CreatePage("SEIZURE CHANCE", val, 0, true); val5.CreateFloat("Blunt Seizure Chance %", Color.white, SeizureChanceBlunt, 1f, 0f, 100f, (Action)delegate(float v) { SeizureChanceBlunt = v; }); val5.CreateFloat("Piercing Seizure Chance %", Color.white, SeizureChancePiercing, 1f, 0f, 100f, (Action)delegate(float v) { SeizureChancePiercing = v; }); Page val6 = val3.CreatePage("DAMAGE RESISTANCE", val, 0, true); val6.CreateBool("Reduced Torso Damage", Color.white, true, (Action)delegate(bool v) { TorsoArmorEnabled = v; }); val6.CreateBool("Reduced Blunt Head Damage", Color.white, true, (Action)delegate(bool v) { HeadBluntResistEnabled = v; }); Page val7 = val3.CreatePage("REACTION WEIGHTS", Color.yellow, 0, true); Page val8 = val7.CreatePage("IMMEDIATE REACTIONS", Color.white, 0, true); Page val9 = val7.CreatePage("POSTURING TYPES", Color.white, 0, true); foreach (ModuleA_Impact.ImmediateReaction reaction in UserSettings.Keys.ToList()) { val8.CreateEnum(reaction.ToString(), Color.white, (Enum)UserSettings[reaction], (Action)delegate(Enum obj) { UserSettings[reaction] = (FrequencyScale)(object)obj; }); } foreach (ModuleA_Impact.PostureTendency reaction2 in PosturingSettings.Keys.ToList()) { val9.CreateEnum(reaction2.ToString(), Color.white, (Enum)PosturingSettings[reaction2], (Action)delegate(Enum obj) { PosturingSettings[reaction2] = (FrequencyScale)(object)obj; }); } val7.CreateFunction("RESTORE TO DEFAULT", Color.blue, (Action)delegate { foreach (ModuleA_Impact.ImmediateReaction item in UserSettings.Keys.ToList()) { UserSettings[item] = FrequencyScale.Default; } foreach (ModuleA_Impact.PostureTendency item2 in PosturingSettings.Keys.ToList()) { PosturingSettings[item2] = FrequencyScale.Default; } SeizureChanceBlunt = 20f; SeizureChancePiercing = 8f; MelonLogger.Msg("Restored settings (buttons will still show old values)"); }); } public override void OnSceneWasUnloaded(int buildIndex, string sceneName) { DeathTracker.ClearAll(); ((MelonBase)this).LoggerInstance.Msg("Scene cleared."); } } public class ReactionContext { public readonly IntPtr Ptr; public readonly int Generation; public readonly Transform Root; public readonly PuppetMaster Puppet; public ReactionContext(PuppetMaster puppet) { Puppet = puppet; Ptr = (((Object)(object)puppet != (Object)null) ? ((Il2CppObjectBase)puppet).Pointer : IntPtr.Zero); Root = (((Object)(object)puppet != (Object)null) ? ((Component)puppet).transform : null); if (Ptr != IntPtr.Zero && DeathTracker.PointerGeneration.TryGetValue(Ptr, out var value)) { Generation = value; } else { Generation = -1; } } public bool IsValid() { if ((Object)(object)Root == (Object)null || Ptr == IntPtr.Zero || Generation < 0) { return false; } int value; return DeathTracker.PointerGeneration.TryGetValue(Ptr, out value) && value == Generation; } } }