Decompiled source of DynamicRagdoll v1.0.5
Mods\DynamicRagdoll.dll
Decompiled 8 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BoneLib.BoneMenu; using EuphoriaLite; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Marrow.PuppetMasta; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using RagdollOnHit; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(EuphoriaLiteMod), "DynamicRagdoll", "1.0.3", "skait5k", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: MelonAdditionalDependencies(new string[] { "DynamicRagdoll2" })] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("DynamicRagdoll")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("DynamicRagdoll")] [assembly: AssemblyTitle("DynamicRagdoll")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EuphoriaLite { public class EuphoriaLiteMod : MelonMod { private sealed class Clutch { public PuppetMaster Pm; public SubBehaviourHealth Health; public Rigidbody Target; public Vector3 LocalPoint; public bool HasLocal; public Rigidbody LeftHand; public Rigidbody RightHand; public Rigidbody HeadBody; public Rigidbody LeftElbow; public Rigidbody RightElbow; public Vector3 OffsetL; public Vector3 OffsetR; public float StartedAt; public float Until; public float DelayUntil; public float Loosen; } private sealed class Downed { public PuppetMaster Pm; public SubBehaviourHealth Health; public Rigidbody[] Bodies; public float Until; public float NextWrithe; public bool BracingNow; public float PrevH = 99f; public bool Landed; public bool LastStand; public int Rolls; public MuscleRegion Region; public float NextStir; public float NextSfx; public Animator Anim; public float AnimSpeed = 1f; public bool HasAnim; } private sealed class BalanceState { public float Loss; public float LastTime = -100f; public float WindowT = -100f; public int WindowCount; public float LastWindowEnd = -100f; } private sealed class Stagger { public PuppetMaster Pm; public SubBehaviourHealth Health; public Animator TargetAnim; public float TargetSpeed = 1f; public Rigidbody[] Bodies; public Rigidbody Hips; public Rigidbody FootL; public Rigidbody FootR; public Vector3 Dir; public float StartedAt; public float HipsY0; public float V0; public float PeakDv; public float BornAt; public int Steps; public float BalancedSince = -1f; public float KickMul = 1f; public float Spin; public float StepForceMul = 1f; public float StepLiftMul = 1f; public bool Bracing; public MuscleRegion Region; public int HitMuscle; public float ShoveMul = 1f; public bool Pellet; public float MassScale = 1f; public float GunMul = 1f; public string GunName = "?"; public bool Melee; public bool Sharp; public float LastDSeg; public float LastDrop; public Vector3 StartPos; public float OrigSpine; public float OrigArmL; public float OrigArmR; public bool Swinging; public bool SwingLeft; public Vector3 SwingTarget; public Vector3 SwingFrom; public float SwingStart; public float SwingUntil; public float NextStepAt; public float PlantUntil; public Rigidbody LastFoot; } private sealed class NpcWatch { public PuppetMaster Pm; public Rigidbody Hips; } private sealed class AnimThaw { public Animator Anim; public float To; public float Until; } private sealed class Scales { public PuppetMaster Pm; public float[] Original = new float[17]; public float[] Factor = new float[17]; public float[] Target = new float[17]; public float[] Up = new float[17]; public float[] Down = new float[17]; public float[] LastSet = new float[17]; public float[] OriginalMap = new float[17]; public float[] FactorMap = new float[17]; public float[] TargetMap = new float[17]; public float[] LastSetMap = new float[17]; public Scales(PuppetMaster pm) { Pm = pm; for (int i = 0; i < 17; i++) { Original[i] = float.NaN; LastSet[i] = float.NaN; Factor[i] = 1f; Target[i] = 1f; Up[i] = 2f; Down[i] = 4f; OriginalMap[i] = float.NaN; FactorMap[i] = 1f; TargetMap[i] = 1f; LastSetMap[i] = float.NaN; } } } private const int RootM = 0; private const int SpineM = 7; private const int AnkleL = 3; private const int AnkleR = 6; private const int ChestM = 8; private const int HeadM = 9; private const int JawM = 16; private const int WristL = 12; private const int WristR = 15; private const int MuscleCount = 17; private static readonly int[] LegMusclesL = new int[3] { 1, 2, 3 }; private static readonly int[] LegMusclesR = new int[3] { 4, 5, 6 }; private static readonly int[] ArmMusclesL = new int[3] { 10, 11, 12 }; private static readonly int[] ArmMusclesR = new int[3] { 13, 14, 15 }; private static readonly int[] TorsoMuscles = new int[4] { 7, 8, 9, 16 }; private static readonly int[] WritheMuscles = new int[6] { 9, 8, 12, 15, 3, 6 }; internal static MelonPreferences_Entry<bool> Enabled; internal static MelonPreferences_Entry<bool> BalanceEnabled; internal static MelonPreferences_Entry<bool> FlipDirection; internal static MelonPreferences_Entry<bool> VarietyEnabled; internal static MelonPreferences_Entry<bool> MeleeEnabled; internal static MelonPreferences_Entry<bool> WalkThrough; internal static MelonPreferences_Entry<float> ClutchSeconds; internal static MelonPreferences_Entry<float> ClutchAcceleration; internal static MelonPreferences_Entry<float> ArmLooseness; internal static MelonPreferences_Entry<float> ClutchDelay; internal static MelonPreferences_Entry<float> HeadClutchChance; internal static MelonPreferences_Entry<float> FallThreshold; internal static MelonPreferences_Entry<float> BalanceRecovery; internal static MelonPreferences_Entry<float> LegGiveWay; internal static MelonPreferences_Entry<float> FallSeconds; internal static MelonPreferences_Entry<float> FallShove; internal static MelonPreferences_Entry<float> FallArmSplay; internal static MelonPreferences_Entry<float> StaggerArmFling; internal static MelonPreferences_Entry<float> FlailForce; internal static MelonPreferences_Entry<float> BraceForce; internal static MelonPreferences_Entry<float> LimbKick; internal static MelonPreferences_Entry<float> WritheForce; internal static MelonPreferences_Entry<float> HandSpeedCap; internal static MelonPreferences_Entry<float> GunForce; internal static MelonPreferences_Entry<float> MeleeForce; internal static MelonPreferences_Entry<float> SharpForce; internal static MelonPreferences_Entry<float> SharpClutchSeconds; internal static MelonPreferences_Entry<float> PunchClutchMax; internal static MelonPreferences_Entry<float> HeavyClutchDamage; internal static MelonPreferences_Entry<int> LastStandMaxRolls; internal static MelonPreferences_Entry<float> StaggerSeconds; internal static MelonPreferences_Entry<float> MinStaggerSeconds; internal static MelonPreferences_Entry<float> UpperBodyStun; internal static MelonPreferences_Entry<float> RecoverStun; internal static MelonPreferences_Entry<float> HipsKick; internal static MelonPreferences_Entry<float> ChestKick; internal static MelonPreferences_Entry<float> HeadKick; internal static MelonPreferences_Entry<float> SnapSeconds; internal static MelonPreferences_Entry<float> StaggerWeight; internal static MelonPreferences_Entry<float> StaggerMapping; internal static MelonPreferences_Entry<float> UpperMapWeight; internal static MelonPreferences_Entry<float> TorsoLift; internal static MelonPreferences_Entry<float> ForwardBend; internal static MelonPreferences_Entry<float> ShoveForce; internal static MelonPreferences_Entry<float> ShoveSeconds; internal static MelonPreferences_Entry<float> TorsoStrength; internal static MelonPreferences_Entry<float> HeadStrength; internal static MelonPreferences_Entry<float> MuscleRecoverSeconds; internal static MelonPreferences_Entry<float> MuscleLoosenSeconds; internal static MelonPreferences_Entry<float> LegStrength; internal static MelonPreferences_Entry<float> LegMapping; internal static MelonPreferences_Entry<float> LegHitStrength; internal static MelonPreferences_Entry<float> HipAssist; internal static MelonPreferences_Entry<float> LimpSway; internal static MelonPreferences_Entry<float> OrientToFall; internal static MelonPreferences_Entry<float> KneeChance; internal static MelonPreferences_Entry<float> DeathArch; internal static MelonPreferences_Entry<float> LastStandHp; internal static MelonPreferences_Entry<float> LastStandHpAbs; internal static MelonPreferences_Entry<float> AnimFreezeSeconds; internal static MelonPreferences_Entry<float> AdvanceForce; internal static MelonPreferences_Entry<int> MaxSteps; internal static MelonPreferences_Entry<int> CfgVersion; internal static MelonPreferences_Entry<float> MaxStepLength; internal static MelonPreferences_Entry<float> SwingSeconds; internal static MelonPreferences_Entry<float> SwingForce; internal static MelonPreferences_Entry<float> LiftForce; internal static MelonPreferences_Entry<float> PlantForce; internal static MelonPreferences_Entry<float> SwingLegStrength; internal static MelonPreferences_Entry<float> BalanceMargin; internal static MelonPreferences_Entry<float> StepMargin; internal static MelonPreferences_Entry<float> FallDistance; internal static MelonPreferences_Entry<float> FallDrop; internal static MelonPreferences_Entry<float> AssistRampSeconds; private static readonly Dictionary<int, Clutch> Clutches = new Dictionary<int, Clutch>(); private static readonly Dictionary<int, Downed> DownedMap = new Dictionary<int, Downed>(); private static readonly Dictionary<int, NpcWatch> KnownNpcs = new Dictionary<int, NpcWatch>(); private static int _scanFrame; private static int _scanLogs; private static readonly Dictionary<int, BalanceState> Balances = new Dictionary<int, BalanceState>(); private static readonly Dictionary<int, Stagger> Staggers = new Dictionary<int, Stagger>(); private static readonly List<int> Finished = new List<int>(); private static readonly Dictionary<int, AnimThaw> Thaws = new Dictionary<int, AnimThaw>(); private static bool _loggedClutch; private static int _balanceLogs; private static int _staggerLogs; private static int _stepLogs; private static int _endLogs; private static int _styleLogs; private static int _strideLogs; private static int _rigLogs; private static int _meshLogs; private static int _clutchDbg; private static int _standLogs; private static int _peakLogs; private static int _floorLogs; private static int _floorLastTick; private static int _spamTick; private static readonly Dictionary<int, Scales> ScaleMap = new Dictionary<int, Scales>(); private static int _propLogs; private static int _mapLogs; private static bool MeleeSharp(string attackType) { if (string.IsNullOrEmpty(attackType)) { return false; } string text = attackType.ToLowerInvariant(); if (!text.Contains("stab") && !text.Contains("slash") && !text.Contains("cut") && !text.Contains("claw") && !text.Contains("bite") && !text.Contains("whip")) { return text.Contains("chop"); } return true; } private static bool MeleeAxe(string attackType) { if (string.IsNullOrEmpty(attackType)) { return false; } return attackType.ToLowerInvariant().Contains("axe"); } private static float MeleeVol(string attackType) { try { return MeleeSharp(attackType) ? SharpForce.Value : MeleeForce.Value; } catch { return 1f; } } private static bool IsMelee(string attackType) { if (string.IsNullOrEmpty(attackType)) { return false; } string text = attackType.ToLowerInvariant(); if (!text.Contains("blunt") && !text.Contains("stab") && !text.Contains("slash") && !text.Contains("punch") && !text.Contains("melee") && !text.Contains("claw") && !text.Contains("bite") && !text.Contains("cut") && !text.Contains("axe") && !text.Contains("blade") && !text.Contains("bat") && !text.Contains("whip")) { return text.Contains("chop"); } return true; } private static bool PunchJab(NpcHitInfo info) { try { if (PunchClutchMax.Value <= 0f) { return false; } if (MeleeSharp(info.AttackType)) { return false; } if (!IsMelee(info.AttackType)) { return false; } return info.Damage >= 0f && info.Damage < PunchClutchMax.Value; } catch { return false; } } private static bool UsesLastStand(PuppetMaster pm, SubBehaviourHealth h) { try { if (RagdollApi.IsNullBody(pm)) { return false; } if (h == null) { return false; } float num = RagdollApi.CurHp(h); bool num2 = LastStandHpAbs.Value > 0f && num >= 0f && num <= LastStandHpAbs.Value; bool flag = LastStandHp.Value > 0f && HpFraction(h) < LastStandHp.Value; return num2 || flag; } catch { return false; } } private static float CaptureAnimSpeed(Animator ta) { try { float speed = ta.speed; return (speed > 0.01f) ? speed : 1f; } catch { return 1f; } } private static void RestoreAnimSpeed(Animator ta, float stored) { try { if ((Object)(object)ta != (Object)null) { ta.speed = ((stored > 0.01f) ? stored : 1f); } } catch { } } private static float DownedAnimSpeed(int id, float staggerBase, Animator ta) { try { if (Thaws.TryGetValue(id, out var value) && value.To > 0.01f) { return value.To; } if (staggerBase > 0.01f) { return staggerBase; } return CaptureAnimSpeed(ta); } catch { return 1f; } } public override void OnInitializeMelon() { MelonPreferences_Category obj = MelonPreferences.CreateCategory("EuphoriaLite"); Enabled = obj.CreateEntry<bool>("Enabled", true, "Euphoria layer on/off (clutch, stagger, falls)", (string)null, false, false, (ValueValidator)null, (string)null); ClutchSeconds = obj.CreateEntry<float>("ClutchSeconds", 0.8f, "How long the hands are pulled to the wound", (string)null, false, false, (ValueValidator)null, (string)null); ClutchAcceleration = obj.CreateEntry<float>("ClutchAcceleration", 60f, "Pull strength on the hands (m/s^2)", (string)null, false, false, (ValueValidator)null, (string)null); ArmLooseness = obj.CreateEntry<float>("ArmLooseness", 0.15f, "Arm stun level while clutching (0 = limp, 1 = normal)", (string)null, false, false, (ValueValidator)null, (string)null); ClutchDelay = obj.CreateEntry<float>("ClutchDelay", 0.15f, "RAGE CTaskNMShot: reach-for-wound delay 100-200ms (s)", (string)null, false, false, (ValueValidator)null, (string)null); HeadClutchChance = obj.CreateEntry<float>("HeadClutchChance", 0.25f, "RAGE DisableReachForWoundOnHeadShot: hands rarely reach to head (0-1)", (string)null, false, false, (ValueValidator)null, (string)null); BalanceEnabled = obj.CreateEntry<bool>("BalanceEnabled", true, "Legs try to hold the NPC up (off = every medium hit knocks him down)", (string)null, false, false, (ValueValidator)null, (string)null); VarietyEnabled = obj.CreateEntry<bool>("VarietyEnabled", true, "No two hits play out the same (kick strength, spin, clutch side)", (string)null, false, false, (ValueValidator)null, (string)null); FlipDirection = obj.CreateEntry<bool>("FlipDirection", false, "Set true if NPCs are pushed TOWARD you when shot", (string)null, false, false, (ValueValidator)null, (string)null); WalkThrough = obj.CreateEntry<bool>("WalkThrough", true, "Shot NPCs keep walking at you: legs stay game-driven, only the upper body reacts (off = full takeover)", (string)null, false, false, (ValueValidator)null, (string)null); FallThreshold = obj.CreateEntry<float>("FallThreshold", 1.6f, "Balance loss at which he falls outright (0 = every hit)", (string)null, false, false, (ValueValidator)null, (string)null); GunForce = obj.CreateEntry<float>("GunForce", 0.65f, "Global gun volume: Eder22-level. All kicks, shoves and loss scale off this", (string)null, false, false, (ValueValidator)null, (string)null); MeleeEnabled = obj.CreateEntry<bool>("MeleeEnabled", true, "Melee hits run the same reactions as gunshots (off = skipped, old behavior)", (string)null, false, false, (ValueValidator)null, (string)null); MeleeForce = obj.CreateEntry<float>("MeleeForce", 0.65f, "Blunt-melee volume (fists included: Marrow labels those Blunt, indistinguishable)", (string)null, false, false, (ValueValidator)null, (string)null); PunchClutchMax = obj.CreateEntry<float>("PunchClutchMax", 1.5f, "Blunt hits below this damage skip the clutch (jabs snap, don't grab). 0 = always clutch", (string)null, false, false, (ValueValidator)null, (string)null); HeavyClutchDamage = obj.CreateEntry<float>("HeavyClutchDamage", 3f, "Melee hits at/above this damage clutch as long as stabs (machete chops, axe). 0 = off", (string)null, false, false, (ValueValidator)null, (string)null); SharpForce = obj.CreateEntry<float>("SharpForce", 0.4f, "Stab/slash volume: low launch, the wound does the work via SharpClutchSeconds", (string)null, false, false, (ValueValidator)null, (string)null); SharpClutchSeconds = obj.CreateEntry<float>("SharpClutchSeconds", 1.6f, "How long stabs are clutched (a cut stays; ~2x the gunshot clutch)", (string)null, false, false, (ValueValidator)null, (string)null); BalanceRecovery = obj.CreateEntry<float>("BalanceRecovery", 1f, "Balance loss that drains per second", (string)null, false, false, (ValueValidator)null, (string)null); LegGiveWay = obj.CreateEntry<float>("LegGiveWay", 0.5f, "He falls if a leg's stun level is below this (leg shot)", (string)null, false, false, (ValueValidator)null, (string)null); FallSeconds = obj.CreateEntry<float>("FallSeconds", 3f, "How long he stays down once he falls", (string)null, false, false, (ValueValidator)null, (string)null); FallShove = obj.CreateEntry<float>("FallShove", 3f, "Push on the hit body part when he falls outright", (string)null, false, false, (ValueValidator)null, (string)null); FallArmSplay = obj.CreateEntry<float>("FallArmSplay", 3f, "How hard the arms fling out wide as he falls (m/s, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); StaggerArmFling = obj.CreateEntry<float>("StaggerArmFling", 0.6f, "Startle throw of the arms on every stagger hit (m/s, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); FlailForce = obj.CreateEntry<float>("FlailForce", 0f, "RAGE armsWindmillAdaptive: slow tightrope sway once clutch lets go (m/s^2, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); BraceForce = obj.CreateEntry<float>("BraceForce", 45f, "Arms stiffen and reach for the ground while falling (m/s^2, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); LimbKick = obj.CreateEntry<float>("LimbKick", 2.6f, "Extra yank on the exact limb that was shot (m/s, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); WritheForce = obj.CreateEntry<float>("WritheForce", 1.5f, "RAGE bodyWrithe: small fast writhe, mostly back/legs not arms (m/s, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); HandSpeedCap = obj.CreateEntry<float>("HandSpeedCap", 8f, "Hands can never exceed this speed (m/s): makes joint-stretching impossible", (string)null, false, false, (ValueValidator)null, (string)null); StaggerSeconds = obj.CreateEntry<float>("StaggerSeconds", 2.6f, "RAGE onFire staggerTime direction: longest a stagger lasts (s)", (string)null, false, false, (ValueValidator)null, (string)null); MinStaggerSeconds = obj.CreateEntry<float>("MinStaggerSeconds", 1.5f, "Staggers always play out at least this long (visible reaction)", (string)null, false, false, (ValueValidator)null, (string)null); AnimFreezeSeconds = obj.CreateEntry<float>("AnimFreezeSeconds", 0.3f, "How long the animator stays frozen on impact before running again under physics (0 = never freeze)", (string)null, false, false, (ValueValidator)null, (string)null); AdvanceForce = obj.CreateEntry<float>("AdvanceForce", 6f, "Stagger drive toward you: shot NPCs keep coming instead of stopping (0 = old statue)", (string)null, false, false, (ValueValidator)null, (string)null); StaggerWeight = obj.CreateEntry<float>("StaggerWeight", 0.7f, "RAGE skeleton 100->35: whole-body strength in a stagger (low = floppy)", (string)null, false, false, (ValueValidator)null, (string)null); StaggerMapping = obj.CreateEntry<float>("StaggerMapping", 0.3f, "Whole-body animation glue in a stagger (low = physics owns the pose)", (string)null, false, false, (ValueValidator)null, (string)null); UpperMapWeight = obj.CreateEntry<float>("UpperMapWeight", 0.1f, "How glued torso/head/arms are to the frozen pose in a stagger (low = they whip and clutch)", (string)null, false, false, (ValueValidator)null, (string)null); TorsoLift = obj.CreateEntry<float>("TorsoLift", 18f, "Upward force on the chest during a stagger, stops it folding (m/s^2, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); ForwardBend = obj.CreateEntry<float>("ForwardBend", 8f, "RAGE staggerFall.alwaysBendForwards: crouch forward at the hip while staggering", (string)null, false, false, (ValueValidator)null, (string)null); ShoveForce = obj.CreateEntry<float>("ShoveForce", 12f, "Sustained push along the shot during a stagger, carries him back (m/s^2, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); ShoveSeconds = obj.CreateEntry<float>("ShoveSeconds", 0.45f, "How long the sustained push lasts", (string)null, false, false, (ValueValidator)null, (string)null); SnapSeconds = obj.CreateEntry<float>("SnapSeconds", 0.22f, "Upper-body snap on impact before the struggle starts (0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); UpperBodyStun = obj.CreateEntry<float>("UpperBodyStun", 0.1f, "How limp the ARMS go in a stagger (0 = limp, 1 = stiff)", (string)null, false, false, (ValueValidator)null, (string)null); TorsoStrength = obj.CreateEntry<float>("TorsoStrength", 0.25f, "RAGE skeleton: spine/chest strength in a stagger (0 = limp, 1 = normal)", (string)null, false, false, (ValueValidator)null, (string)null); HeadStrength = obj.CreateEntry<float>("HeadStrength", 0.15f, "RAGE skeleton: head/neck strength in a stagger (neck 100->35-40)", (string)null, false, false, (ValueValidator)null, (string)null); LegStrength = obj.CreateEntry<float>("LegStrength", 0.6f, "RAGE lowerBodyStiffness 13->14: stance-leg strength (holds him up)", (string)null, false, false, (ValueValidator)null, (string)null); LegHitStrength = obj.CreateEntry<float>("LegHitStrength", 0.3f, "Shot-leg strength in a stagger (limps instead of ragdolling)", (string)null, false, false, (ValueValidator)null, (string)null); LegMapping = obj.CreateEntry<float>("LegMapping", 0.15f, "How glued legs are to the walk animation in a stagger (low = physics owns them)", (string)null, false, false, (ValueValidator)null, (string)null); MuscleRecoverSeconds = obj.CreateEntry<float>("MuscleRecoverSeconds", 1.6f, "How long spine/head take to stiffen back up afterwards", (string)null, false, false, (ValueValidator)null, (string)null); MuscleLoosenSeconds = obj.CreateEntry<float>("MuscleLoosenSeconds", 0.5f, "How fast spine/head go limp after a hit (higher = softer, less collapse)", (string)null, false, false, (ValueValidator)null, (string)null); HipAssist = obj.CreateEntry<float>("HipAssist", 30f, "RAGE removed hipLeanAcc/resistAcc cheats: small hip servo back over feet (m/s^2, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); LimpSway = obj.CreateEntry<float>("LimpSway", 15f, "Side-to-side sway on leg hits, forces weight shifts and limping steps (m/s^2, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); OrientToFall = obj.CreateEntry<float>("OrientToFall", 6f, "RAGE highFall.orientateBodyToFallDirection: chest steers toward travel dir", (string)null, false, false, (ValueValidator)null, (string)null); KneeChance = obj.CreateEntry<float>("KneeChance", 0.28f, "RAGE ChanceOfFallToKnees 0.25 + GutShot 0.30: fall becomes long stagger instead", (string)null, false, false, (ValueValidator)null, (string)null); LastStandHp = obj.CreateEntry<float>("LastStandHp", 0.15f, "Fallback fraction gate when absolute HP is unreadable (0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); LastStandHpAbs = obj.CreateEntry<float>("LastStandHpAbs", 5f, "Absolute HP at/below which last stand triggers even above the fraction gate (0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); DeathArch = obj.CreateEntry<float>("DeathArch", 2f, "RAGE smartFall: brief rigid arch on death before going limp (m/s, 0 = off)", (string)null, false, false, (ValueValidator)null, (string)null); RecoverStun = obj.CreateEntry<float>("RecoverStun", 0.7f, "Where upper-body stiffness restarts from afterwards (higher = recovers faster)", (string)null, false, false, (ValueValidator)null, (string)null); HipsKick = obj.CreateEntry<float>("HipsKick", 1.8f, "Instant speed given to the hips along the push (m/s)", (string)null, false, false, (ValueValidator)null, (string)null); ChestKick = obj.CreateEntry<float>("ChestKick", 3f, "Instant speed given to the chest along the push (m/s)", (string)null, false, false, (ValueValidator)null, (string)null); HeadKick = obj.CreateEntry<float>("HeadKick", 2f, "Instant speed given to the head along the push (m/s)", (string)null, false, false, (ValueValidator)null, (string)null); MaxSteps = obj.CreateEntry<int>("MaxSteps", 8, "Most catch-steps before he gives up and falls", (string)null, false, false, (ValueValidator)null, (string)null); LastStandMaxRolls = obj.CreateEntry<int>("LastStandMaxRolls", 3, "How many times a last stand extends before he gets up anyway (0 = forever)", (string)null, false, false, (ValueValidator)null, (string)null); MaxStepLength = obj.CreateEntry<float>("MaxStepLength", 0.6f, "Longest single catch-step (m)", (string)null, false, false, (ValueValidator)null, (string)null); SwingSeconds = obj.CreateEntry<float>("SwingSeconds", 0.2f, "How long a foot swing takes", (string)null, false, false, (ValueValidator)null, (string)null); SwingForce = obj.CreateEntry<float>("SwingForce", 100f, "Force swinging the stepping foot (m/s^2)", (string)null, false, false, (ValueValidator)null, (string)null); LiftForce = obj.CreateEntry<float>("LiftForce", 55f, "Force lifting the stepping foot so steps stomp, not slide (m/s^2)", (string)null, false, false, (ValueValidator)null, (string)null); PlantForce = obj.CreateEntry<float>("PlantForce", 70f, "Force stomping the foot down to grip (m/s^2)", (string)null, false, false, (ValueValidator)null, (string)null); SwingLegStrength = obj.CreateEntry<float>("SwingLegStrength", 0.45f, "Muscle strength of the stepping leg while it swings (lower = freer)", (string)null, false, false, (ValueValidator)null, (string)null); BalanceMargin = obj.CreateEntry<float>("BalanceMargin", 0.12f, "Centre of mass this close to his feet counts as balanced (m)", (string)null, false, false, (ValueValidator)null, (string)null); StepMargin = obj.CreateEntry<float>("StepMargin", 0.05f, "Centre of mass this far out triggers a catch-step (lower = steps constantly)", (string)null, false, false, (ValueValidator)null, (string)null); FallDistance = obj.CreateEntry<float>("FallDistance", 0.9f, "Centre of mass this far outside his feet = he can't recover (m)", (string)null, false, false, (ValueValidator)null, (string)null); FallDrop = obj.CreateEntry<float>("FallDrop", 0.55f, "Hips dropping this much = he's falling (m)", (string)null, false, false, (ValueValidator)null, (string)null); AssistRampSeconds = obj.CreateEntry<float>("AssistRampSeconds", 1f, "Hip servo ramps up over this long (early = flies with the shot, late = caught)", (string)null, false, false, (ValueValidator)null, (string)null); CfgVersion = obj.CreateEntry<int>("CfgVersion", 50, "Do not edit: resets tuning when the mod updates", (string)null, false, false, (ValueValidator)null, (string)null); if (CfgVersion.Value < 49) { Enabled.Value = true; ClutchSeconds.Value = 0.8f; ClutchAcceleration.Value = 60f; ArmLooseness.Value = 0.15f; ClutchDelay.Value = 0.15f; HeadClutchChance.Value = 0.25f; BalanceEnabled.Value = true; VarietyEnabled.Value = true; FlipDirection.Value = false; FallThreshold.Value = 1.6f; BalanceRecovery.Value = 1f; LegGiveWay.Value = 0.5f; GunForce.Value = 0.65f; LastStandHp.Value = 0.15f; LastStandHpAbs.Value = 5f; FallSeconds.Value = 3f; FallShove.Value = 3f; FallArmSplay.Value = 3f; StaggerArmFling.Value = 0.6f; FlailForce.Value = 0f; BraceForce.Value = 45f; LimbKick.Value = 2.6f; WritheForce.Value = 1.5f; StaggerSeconds.Value = 2.6f; MinStaggerSeconds.Value = 1.5f; UpperBodyStun.Value = 0.1f; SnapSeconds.Value = 0.22f; StaggerWeight.Value = 0.7f; StaggerMapping.Value = 0.3f; UpperMapWeight.Value = 0.1f; TorsoLift.Value = 18f; ForwardBend.Value = 8f; ShoveForce.Value = 10f; ShoveSeconds.Value = 0.55f; TorsoStrength.Value = 0.25f; HeadStrength.Value = 0.15f; LegStrength.Value = 0.6f; LegHitStrength.Value = 0.3f; MuscleRecoverSeconds.Value = 1.6f; MuscleLoosenSeconds.Value = 0.5f; HipAssist.Value = 30f; RecoverStun.Value = 0.7f; OrientToFall.Value = 6f; KneeChance.Value = 0.28f; DeathArch.Value = 2f; HipsKick.Value = 1.8f; ChestKick.Value = 3.6f; HeadKick.Value = 2f; MaxSteps.Value = 8; MaxStepLength.Value = 0.6f; SwingSeconds.Value = 0.2f; SwingForce.Value = 100f; LiftForce.Value = 55f; PlantForce.Value = 70f; SwingLegStrength.Value = 0.45f; BalanceMargin.Value = 0.12f; StepMargin.Value = 0.05f; FallDistance.Value = 0.9f; FallDrop.Value = 0.55f; AssistRampSeconds.Value = 1f; CfgVersion.Value = 49; MelonPreferences.Save(); } if (CfgVersion.Value < 50) { PunchClutchMax.Value = 1.5f; ShoveSeconds.Value = 0.45f; ChestKick.Value = 3f; CfgVersion.Value = 50; MelonPreferences.Save(); } RagdollApi.AutoKnockdown = !BalanceEnabled.Value; RagdollApi.OnNpcHit += OnHit; ((MelonBase)this).LoggerInstance.Msg("DynamicRagdoll 1.0.3 loaded (balance " + (BalanceEnabled.Value ? "ON" : "off") + ")."); ((MelonBase)this).LoggerInstance.Msg($"Tuning: torso={TorsoStrength.Value:F2} head={HeadStrength.Value:F2} steps={MaxSteps.Value} margin={BalanceMargin.Value:F2} fallDrop={FallDrop.Value:F2} hipAssist={HipAssist.Value:F0}"); } public override void OnDeinitializeMelon() { RagdollApi.OnNpcHit -= OnHit; RagdollApi.AutoKnockdown = true; } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { KnownNpcs.Clear(); Balances.Clear(); Staggers.Clear(); Clutches.Clear(); DownedMap.Clear(); ScaleMap.Clear(); Thaws.Clear(); Finished.Clear(); try { MenuPage.EnsureBuilt(); } catch { } } public override void OnLateUpdate() { if (DownedMap.Count == 0 && Staggers.Count == 0) { return; } foreach (KeyValuePair<int, Downed> item in DownedMap) { Downed value = item.Value; if ((Object)(object)value.Pm == (Object)null) { continue; } try { value.Pm.mappingWeight = 0.3f; value.Pm.muscleWeight = 0f; if (!ScaleMap.TryGetValue(item.Key, out var value2)) { continue; } for (int i = 0; i < 17; i++) { Muscle val = MuscleOf(value2.Pm, i); if (val != null && val.props != null) { if (!float.IsNaN(value2.LastSet[i])) { val.props.muscleWeight = value2.LastSet[i]; } if (!float.IsNaN(value2.LastSetMap[i])) { val.props.mappingWeight = value2.LastSetMap[i]; } } } } catch { } } foreach (KeyValuePair<int, Stagger> stagger in Staggers) { Stagger value3 = stagger.Value; if ((Object)(object)value3.Pm == (Object)null) { continue; } try { value3.Pm.mappingWeight = StaggerMapping.Value; if (!ScaleMap.TryGetValue(stagger.Key, out var value4)) { continue; } for (int j = 0; j < 17; j++) { Muscle val2 = MuscleOf(value4.Pm, j); if (val2 != null && val2.props != null) { if (!float.IsNaN(value4.LastSet[j])) { val2.props.muscleWeight = value4.LastSet[j]; } if (!float.IsNaN(value4.LastSetMap[j])) { val2.props.mappingWeight = value4.LastSetMap[j]; } } } } catch { } } } private static void OnHit(NpcHitInfo info) { //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: 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_017c: 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_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Invalid comparison between Unknown and I4 if ((Object)(object)info.Puppet == (Object)null || RagdollApi.IsExcluded(info.Puppet)) { return; } try { Il2CppReferenceArray<Muscle> muscles = info.Puppet.muscles; if (muscles == null || ((Il2CppArrayBase<Muscle>)(object)muscles).Length != 17) { if (_rigLogs < 3) { _rigLogs++; string value = "?"; try { value = ((Object)info.Puppet).name; } catch { } MelonLogger.Msg($"Rig gate: skipping non-humanoid '{value}' ({((Il2CppArrayBase<Muscle>)(object)muscles)?.Length ?? (-1)} muscles)"); } return; } } catch { } try { int instanceID = ((Object)info.Puppet).GetInstanceID(); if (!KnownNpcs.ContainsKey(instanceID)) { if (KnownNpcs.Count > 64) { KnownNpcs.Clear(); } KnownNpcs[instanceID] = new NpcWatch { Pm = info.Puppet, Hips = BodyOf(info.Puppet, 0) }; } } catch { } if (info.IsDead) { try { if (DeathArch.Value > 0f && (Object)(object)info.Body != (Object)null) { Rigidbody val = BodyOf(info.Puppet, 8); if ((Object)(object)val != (Object)null) { Vector3 val2 = Vector3.up * 0.8f - info.Direction * 0.4f; val.AddForce(((Vector3)(ref val2)).normalized * DeathArch.Value, (ForceMode)2); } info.Body.AddForce(info.Direction * DeathArch.Value * 0.6f, (ForceMode)2); } } catch { } ReleaseAllNow(info.Puppet); } else if (Enabled.Value && (!IsMelee(info.AttackType) || MeleeEnabled.Value)) { if (Enabled.Value && !PunchJab(info)) { StartClutch(info); } if (BalanceEnabled.Value && (int)info.Tier == 1) { HandleBalance(info); } } } internal static void ReleaseAllNow(PuppetMaster pm) { int instanceID; try { instanceID = ((Object)pm).GetInstanceID(); } catch { return; } if (!ScaleMap.TryGetValue(instanceID, out var value)) { return; } try { for (int i = 0; i < 17; i++) { Muscle val = MuscleOf(pm, i); if (val != null) { if (!float.IsNaN(value.Original[i])) { val.props.muscleWeight = value.Original[i]; } if (!float.IsNaN(value.OriginalMap[i])) { val.props.mappingWeight = value.OriginalMap[i]; } } } } catch { } ScaleMap.Remove(instanceID); } private static void HandleBalance(NpcHitInfo info) { //IL_050e: Unknown result type (might be due to invalid IL or missing references) //IL_0513: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Invalid comparison between Unknown and I4 //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Invalid comparison between Unknown and I4 //IL_043b: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Invalid comparison between Unknown and I4 //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Invalid comparison between Unknown and I4 PuppetMaster puppet = info.Puppet; int instanceID = ((Object)puppet).GetInstanceID(); float time = Time.time; if (!Balances.TryGetValue(instanceID, out var value)) { if (Balances.Count > 256) { Balances.Clear(); } value = new BalanceState(); Balances[instanceID] = value; } float num = time - value.LastTime; float num2 = Impulse(info); bool pellet = false; if (num < 0.12f) { value.WindowCount++; num2 *= 0.3f; if (value.WindowCount >= 3) { pellet = true; } } else { if (time - value.LastWindowEnd < 0.6f && value.LastWindowEnd > 0f) { num2 *= 0.75f; } value.WindowCount = 1; value.WindowT = time; } value.LastWindowEnd = time; value.Loss = Mathf.Max(0f, value.Loss - BalanceRecovery.Value * num) + num2; value.LastTime = time; bool flag = false; if (info.Health != null) { float limbStun = RagdollApi.GetLimbStun(info.Health, (MuscleRegion)6); float limbStun2 = RagdollApi.GetLimbStun(info.Health, (MuscleRegion)7); if ((int)info.Region == 6 || (int)info.Region == 7) { flag = limbStun < LegGiveWay.Value * 0.5f && limbStun2 < LegGiveWay.Value * 0.5f; } else { float num3 = LegGiveWay.Value * 0.5f; flag = Mathf.Min(limbStun, limbStun2) < num3; } } bool flag2 = value.Loss >= FallThreshold.Value || flag; if (_balanceLogs < 15) { _balanceLogs++; MelonLogger.Msg($"Balance: region={info.Region} loss={value.Loss:F2}/{FallThreshold.Value:F2} legsGaveWay={flag} -> {(flag2 ? "FALL" : "STAGGER")}"); } if (flag2) { if (((int)info.Region == 2 || (int)info.Region == 1) && KneeChance.Value > 0f && Random.value < KneeChance.Value) { value.Loss = FallThreshold.Value * 0.55f; if (_balanceLogs < 15) { _balanceLogs++; MelonLogger.Msg("Balance: gut-shot -> knees (long stagger instead of fall)"); } StartStagger(info, instanceID, pellet); if (Staggers.TryGetValue(instanceID, out var value2)) { value2.Steps = -2; value2.StartedAt -= 0.4f; } return; } value.Loss = 0f; if (Staggers.TryGetValue(instanceID, out var value3)) { GiveBackStun(value3); Staggers.Remove(instanceID); } float num4 = FallSeconds.Value; try { if (UsesLastStand(puppet, info.Health)) { num4 *= 3f; if (_balanceLogs < 15) { _balanceLogs++; MelonLogger.Msg($"Balance: last stand (long floor clutch, cur={RagdollApi.CurHp(info.Health):F0}hp)"); } } } catch { } RagdollApi.KnockDown(puppet, info.Health, num4); RagdollApi.HoldLoco(puppet, num4); RagdollApi.HoldNav(puppet, num4); RagdollApi.HoldLiteLoco(puppet, num4); if ((Object)(object)info.Body != (Object)null && FallShove.Value > 0f) { info.Body.AddForce(info.Direction * FallShove.Value * (IsMelee(info.AttackType) ? MeleeVol(info.AttackType) : GunForce.Value), (ForceMode)2); } FlingArms(puppet, FallArmSplay.Value); Rigidbody[] array = ((value3 != null) ? value3.Bodies : BodiesOf(puppet)); if (array != null) { if (DownedMap.Count > 64) { DownedMap.Clear(); } bool flag3 = false; try { flag3 = RagdollApi.SetGetupDisabled(puppet, true); } catch { } bool lastStand = false; try { lastStand = UsesLastStand(puppet, info.Health); } catch { } Downed downed = new Downed { Pm = puppet, Health = info.Health, Bodies = array, Until = time + num4, NextWrithe = time + Random.Range(0.15f, 0.3f), PrevH = 99f, Landed = false, LastStand = lastStand, Region = info.Region, NextStir = time + Random.Range(2f, 3f) }; try { Animator targetAnimator = puppet.targetAnimator; if ((Object)(object)targetAnimator != (Object)null) { downed.Anim = targetAnimator; downed.AnimSpeed = DownedAnimSpeed(instanceID, value3?.TargetSpeed ?? 0f, targetAnimator); downed.HasAnim = true; } } catch { } DownedMap[instanceID] = downed; Thaws.Remove(instanceID); if (_balanceLogs < 15) { _balanceLogs++; MelonLogger.Msg($"Downed: getup lock {(flag3 ? "HELD" : "FAILED")} for {num4:F0}s"); } } if (Clutches.TryGetValue(instanceID, out var value4)) { UpgradeClutch(value4); value4.Until = Mathf.Max(value4.Until, time + num4); } else { if (!Enabled.Value || !((Object)(object)info.Body != (Object)null)) { return; } try { StartClutch(info, force: true); if (Clutches.TryGetValue(instanceID, out var value5)) { value5.Until = Mathf.Max(value5.Until, time + num4); } } catch { } } } else { StartStagger(info, instanceID, pellet); } } private static float GunMult(string gun) { if (string.IsNullOrEmpty(gun)) { return 1f; } string text = gun.ToLowerInvariant(); if (text.Contains("eder")) { return 0.85f; } if (text.Contains("1911")) { return 1f; } if (text.Contains("mp5") || text.Contains("mp7") || text.Contains("uzi") || text.Contains("scorpion") || text.Contains("mac-")) { return 0.9f; } if (text.Contains("m4") || text.Contains("mk18") || text.Contains("m16") || text.Contains("akm") || text.Contains("scar")) { return 1.15f; } if (text.Contains("590") || text.Contains("shotgun")) { return 1f; } if (text.Contains("desert")) { return 1.25f; } if (!text.Contains("boardgun")) { text.Contains("blaster"); } return 1f; } private static float VolMul(Stagger s) { try { return s.Sharp ? SharpForce.Value : (s.Melee ? MeleeForce.Value : (GunForce.Value * s.GunMul)); } catch { return 1f; } } private static float HpFraction(SubBehaviourHealth h) { try { return RagdollApi.HpFraction(h); } catch { return 1f; } } private static float Impulse(NpcHitInfo info) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected I4, but got Unknown float num = ((info.Damage > 0f) ? info.Damage : 0.9f); MuscleRegion region = info.Region; float num2; switch (region - 3) { case 0: num2 = 1.3f; break; case 1: case 2: num2 = 0.5f; break; case 3: case 4: num2 = 0.8f; break; default: num2 = 1f; break; } float num3 = num * num2; if (VarietyEnabled.Value) { num3 *= Random.Range(0.85f, 1.2f); } return num3 * (IsMelee(info.AttackType) ? MeleeVol(info.AttackType) : GunForce.Value); } private static void StartStagger(NpcHitInfo info, int id, bool pellet = false) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0849: Unknown result type (might be due to invalid IL or missing references) //IL_0855: Unknown result type (might be due to invalid IL or missing references) //IL_085a: Unknown result type (might be due to invalid IL or missing references) //IL_085f: Unknown result type (might be due to invalid IL or missing references) //IL_087d: Unknown result type (might be due to invalid IL or missing references) //IL_0882: Unknown result type (might be due to invalid IL or missing references) //IL_0341: 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) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_0491: Unknown result type (might be due to invalid IL or missing references) //IL_0492: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04c7: Unknown result type (might be due to invalid IL or missing references) //IL_04cf: Unknown result type (might be due to invalid IL or missing references) //IL_04d4: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Unknown result type (might be due to invalid IL or missing references) //IL_04f4: Unknown result type (might be due to invalid IL or missing references) //IL_0510: Unknown result type (might be due to invalid IL or missing references) PuppetMaster puppet = info.Puppet; Vector3 val = info.Direction; if (FlipDirection.Value) { val = -val; } val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { return; } ((Vector3)(ref val)).Normalize(); float kickMul = 1f; float spin = 0f; if (VarietyEnabled.Value) { val = Quaternion.Euler(0f, Random.Range(-10f, 10f), 0f) * val; kickMul = Random.Range(0.8f, 1.3f); if (Random.value < 0.5f) { spin = Random.Range(-0.8f, 0.8f); } } float headM; float chestM; float hipsM; if (Staggers.TryGetValue(id, out var value)) { value.Dir = val; value.Steps = 0; value.BalancedSince = -1f; value.KickMul = kickMul; value.Spin = spin; value.Region = info.Region; value.HitMuscle = info.MuscleIndex; KickProfile(value.HitMuscle, value.Region, out headM, out chestM, out hipsM, out var shoveM); value.ShoveMul = shoveM; if (pellet) { value.ShoveMul *= 0.5f; value.Pellet = true; } value.Melee = IsMelee(info.AttackType); value.Sharp = value.Melee && MeleeSharp(info.AttackType); value.GunMul = (value.Melee ? 1f : GunMult(info.Gun)); value.GunName = (value.Melee ? ("melee:" + (info.AttackType ?? "?")) : (info.Gun ?? "?")); value.Bracing = false; value.NextStepAt = Mathf.Min(value.NextStepAt, Time.time + 0.1f); if (SnapSeconds.Value > 0f) { SnapUpperBody(puppet, value.Health); } Kick(value); FlingArms(puppet, StaggerArmFling.Value); RagdollApi.HoldMapping(puppet, StaggerSeconds.Value + 0.6f, StaggerMapping.Value); if (!WalkThrough.Value) { RagdollApi.HoldLimp(puppet, value.Health, StaggerWeight.Value, StaggerSeconds.Value + 0.6f); } if (!WalkThrough.Value) { RagdollApi.HoldLoco(puppet, StaggerSeconds.Value + 0.6f); } if (!WalkThrough.Value) { RagdollApi.HoldNav(puppet, StaggerSeconds.Value + 0.6f); } if (!WalkThrough.Value) { RagdollApi.HoldLiteLoco(puppet, StaggerSeconds.Value + 0.6f); } return; } Rigidbody[] array = (Rigidbody[])(object)new Rigidbody[17]; for (int i = 0; i < 17; i++) { array[i] = BodyOf(puppet, i); } Rigidbody val2 = array[0]; Rigidbody val3 = array[3]; Rigidbody val4 = array[6]; if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null) { return; } if (val2.position.y - Mathf.Min(val3.position.y, val4.position.y) < 0.45f) { RagdollApi.KnockDown(puppet, info.Health, FallSeconds.Value); RagdollApi.HoldLoco(puppet, FallSeconds.Value); RagdollApi.HoldNav(puppet, FallSeconds.Value); RagdollApi.HoldLiteLoco(puppet, FallSeconds.Value); try { float time = Time.time; int instanceID = ((Object)puppet).GetInstanceID(); if (Clutches.TryGetValue(instanceID, out var value2)) { UpgradeClutch(value2); value2.Until = Mathf.Max(value2.Until, time + FallSeconds.Value); } else if (Enabled.Value && (Object)(object)info.Body != (Object)null) { StartClutch(info, force: true); if (Clutches.TryGetValue(instanceID, out var value3)) { value3.Until = Mathf.Max(value3.Until, time + FallSeconds.Value); } } return; } catch { return; } } value = new Stagger { Pm = puppet, Health = info.Health, Bodies = array, Hips = val2, FootL = val3, FootR = val4, Dir = val, StartedAt = Time.time, BornAt = Time.time, HipsY0 = val2.position.y, StartPos = val2.position, V0 = Vector3.Dot(val2.velocity, val), KickMul = kickMul, Spin = spin, Region = info.Region, HitMuscle = info.MuscleIndex }; KickProfile(value.HitMuscle, value.Region, out hipsM, out chestM, out headM, out var shoveM2); value.ShoveMul = shoveM2; value.Melee = IsMelee(info.AttackType); value.Sharp = value.Melee && MeleeSharp(info.AttackType); value.GunMul = (value.Melee ? 1f : GunMult(info.Gun)); value.GunName = (value.Melee ? ("melee:" + (info.AttackType ?? "?")) : (info.Gun ?? "?")); if (pellet) { value.ShoveMul *= 0.5f; } value.Pellet = pellet; try { float num = 0f; Rigidbody[] bodies = value.Bodies; foreach (Rigidbody val5 in bodies) { if ((Object)(object)val5 != (Object)null) { num += val5.mass; } } if (num > 1f) { value.MassScale = Mathf.Clamp(80f / num, 0.6f, 1.5f); } } catch { } if (!WalkThrough.Value) { RagdollApi.HoldLoco(puppet, StaggerSeconds.Value + 0.6f); } if (!WalkThrough.Value) { RagdollApi.HoldNav(puppet, StaggerSeconds.Value + 0.6f); } if (!WalkThrough.Value) { RagdollApi.HoldLiteLoco(puppet, StaggerSeconds.Value + 0.6f); } if (!WalkThrough.Value) { RagdollApi.HoldLimp(puppet, info.Health, StaggerWeight.Value, StaggerSeconds.Value + 0.6f); } try { Animator targetAnimator = puppet.targetAnimator; if ((Object)(object)targetAnimator != (Object)null && !WalkThrough.Value) { value.TargetAnim = targetAnimator; value.TargetSpeed = CaptureAnimSpeed(targetAnimator); targetAnimator.speed = 0f; } } catch { } if (info.Health != null) { value.OrigSpine = RagdollApi.GetLimbStun(info.Health, (MuscleRegion)2); value.OrigArmL = RagdollApi.GetLimbStun(info.Health, (MuscleRegion)4); value.OrigArmR = RagdollApi.GetLimbStun(info.Health, (MuscleRegion)5); } Staggers[id] = value; if (Thaws.TryGetValue(id, out var value4)) { value.TargetSpeed = ((value4.To > 0.01f) ? value4.To : 1f); Thaws.Remove(id); } value.NextStepAt = Time.time + 0.12f; RagdollApi.HoldMapping(puppet, StaggerSeconds.Value + 0.6f, StaggerMapping.Value); RagdollApi.Diag(puppet); if (SnapSeconds.Value > 0f) { SnapUpperBody(puppet, info.Health); } Kick(value); FlingArms(puppet, StaggerArmFling.Value); if (_staggerLogs >= 8) { return; } _staggerLogs++; float value5 = float.NaN; Camera main = Camera.main; if ((Object)(object)main != (Object)null) { Vector3 val6 = val2.position - ((Component)main).transform.position; val6.y = 0f; if (((Vector3)(ref val6)).sqrMagnitude > 0.01f) { value5 = Vector3.Dot(((Vector3)(ref val6)).normalized, val); } } MelonLogger.Msg($"Stagger started: upper body limp, legs strong. direction vs 'away from you' = {value5:F2} (want about +1)"); } private static void KickProfile(int hitMuscle, MuscleRegion region, out float hipsM, out float chestM, out float headM, out float shoveM) { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Invalid comparison between Unknown and I4 //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Invalid comparison between Unknown and I4 switch (hitMuscle) { case 10: case 13: hipsM = 0.2f; chestM = 0.5f; headM = 0.2f; shoveM = 0.2f; return; case 0: case 7: hipsM = 1.3f; chestM = 0.6f; headM = 0.35f; shoveM = 0.8f; return; case 8: hipsM = 0.3f; chestM = 1.25f; headM = 0.9f; shoveM = 0.3f; return; case 9: case 16: hipsM = 0.35f; chestM = 0.7f; headM = 1.5f; shoveM = 0.35f; return; case 1: case 2: case 3: case 4: case 5: case 6: hipsM = 0.6f; chestM = 0.4f; headM = 0.3f; shoveM = 0.6f; return; } if ((int)region == 4 || (int)region == 5) { hipsM = 0.25f; chestM = 0.4f; headM = 0.25f; shoveM = 0.25f; } else { hipsM = 1f; chestM = 1f; headM = 1f; shoveM = 1f; } } private static void Kick(Stagger s) { //IL_001c: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0095: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Invalid comparison between Unknown and I4 //IL_010d: 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_011d: 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_01cd: Invalid comparison between Unknown and I4 //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: 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_01a2: 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_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Expected I4, but got Unknown //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_03e7: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) float num = s.KickMul * s.MassScale * VolMul(s); KickProfile(s.HitMuscle, s.Region, out var hipsM, out var chestM, out var headM, out var _); if ((Object)(object)s.Bodies[0] != (Object)null) { s.Bodies[0].AddForce(s.Dir * HipsKick.Value * hipsM * num, (ForceMode)2); } if ((Object)(object)s.Bodies[8] != (Object)null) { s.Bodies[8].AddForce(s.Dir * ChestKick.Value * chestM * num, (ForceMode)2); } if ((Object)(object)s.Bodies[9] != (Object)null) { s.Bodies[9].AddForce(s.Dir * HeadKick.Value * headM * num, (ForceMode)2); } if (s.Pellet && (Object)(object)s.Bodies[8] != (Object)null) { s.Bodies[8].AddForce(Vector3.up * 1.2f * num, (ForceMode)2); } Vector3 val2; if (LimbKick.Value > 0f && (s.HitMuscle == 10 || s.HitMuscle == 13)) { Rigidbody val = s.Bodies[s.HitMuscle]; if ((Object)(object)val != (Object)null) { val2 = s.Dir * 1.4f + Vector3.down * 0.2f; val.AddForce(((Vector3)(ref val2)).normalized * LimbKick.Value * 1.4f * num, (ForceMode)2); } } float num2 = (((int)s.Region == 2 || (int)s.Region == 1) ? 0.5f : 1f); if ((Object)(object)s.Bodies[0] != (Object)null && Mathf.Abs(s.Spin) > 0.05f) { s.Bodies[0].AddTorque(Vector3.up * s.Spin * num2, (ForceMode)2); } if (LimbKick.Value > 0f) { Vector3 val3 = Vector3.Cross(Vector3.up, s.Dir); if (((Vector3)(ref val3)).sqrMagnitude > 0.0001f) { ((Vector3)(ref val3)).Normalize(); } else { val3 = Vector3.right; } MuscleRegion region = s.Region; switch (region - 4) { case 2: if ((Object)(object)s.Bodies[3] != (Object)null) { Rigidbody obj4 = s.Bodies[3]; val2 = -val3 + Vector3.down * 0.7f; obj4.AddForce(((Vector3)(ref val2)).normalized * LimbKick.Value * num, (ForceMode)2); } break; case 3: if ((Object)(object)s.Bodies[6] != (Object)null) { Rigidbody obj2 = s.Bodies[6]; val2 = val3 + Vector3.down * 0.7f; obj2.AddForce(((Vector3)(ref val2)).normalized * LimbKick.Value * num, (ForceMode)2); } break; case 0: if ((Object)(object)s.Bodies[12] != (Object)null) { Rigidbody obj3 = s.Bodies[12]; val2 = s.Dir * 1.2f + Vector3.up * 0.6f; obj3.AddForce(((Vector3)(ref val2)).normalized * LimbKick.Value * num, (ForceMode)2); } break; case 1: if ((Object)(object)s.Bodies[15] != (Object)null) { Rigidbody obj = s.Bodies[15]; val2 = s.Dir * 1.2f + Vector3.up * 0.6f; obj.AddForce(((Vector3)(ref val2)).normalized * LimbKick.Value * num, (ForceMode)2); } break; } } if (_styleLogs < 12) { _styleLogs++; MelonLogger.Msg($"Stagger style: kick x{num:F2}, spin {s.Spin:F2}, gun {s.GunName} x{s.GunMul:F2}, adv={AdvanceForce.Value:F1}"); } } private static void SnapUpperBody(PuppetMaster pm, SubBehaviourHealth health) { if (health != null) { RagdollApi.SetLimbStun(health, (MuscleRegion)4, 0f); RagdollApi.SetLimbStun(health, (MuscleRegion)5, 0f); } ScaleMuscle(pm, 7, 0.25f, 1f, 25f); ScaleMuscle(pm, 8, 0.25f, 1f, 25f); ScaleMuscle(pm, 9, 0.25f, 1f, 25f); ScaleMuscle(pm, 16, 0.25f, 1f, 25f); } private static void FlingArms(PuppetMaster pm, float force) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_00bc: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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_00e9: Unknown result type (might be due to invalid IL or missing references) if (force <= 0f) { return; } Rigidbody val = BodyOf(pm, 0); Rigidbody val2 = BodyOf(pm, 12); Rigidbody val3 = BodyOf(pm, 15); if ((Object)(object)val == (Object)null) { return; } Vector3 right = ((Component)pm).transform.right; if (((Vector3)(ref right)).sqrMagnitude < 0.01f) { right = Vector3.right; } Vector3 val5; if ((Object)(object)val2 != (Object)null) { Vector3 val4 = val2.position - val.position; val4.y = 0f; if (((Vector3)(ref val4)).sqrMagnitude < 0.01f) { val4 = -right; } val5 = ((Vector3)(ref val4)).normalized + Vector3.up; val2.AddForce(((Vector3)(ref val5)).normalized * force, (ForceMode)2); } if ((Object)(object)val3 != (Object)null) { Vector3 val6 = val3.position - val.position; val6.y = 0f; if (((Vector3)(ref val6)).sqrMagnitude < 0.01f) { val6 = right; } val5 = ((Vector3)(ref val6)).normalized + Vector3.up; val3.AddForce(((Vector3)(ref val5)).normalized * force, (ForceMode)2); } } private static bool UpdateStagger(Stagger s, float now) { //IL_0d23: Unknown result type (might be due to invalid IL or missing references) //IL_0d25: Unknown result type (might be due to invalid IL or missing references) //IL_0d31: Unknown result type (might be due to invalid IL or missing references) //IL_0d3c: Unknown result type (might be due to invalid IL or missing references) //IL_0d41: Unknown result type (might be due to invalid IL or missing references) //IL_0d46: Unknown result type (might be due to invalid IL or missing references) //IL_0916: Unknown result type (might be due to invalid IL or missing references) //IL_091b: Unknown result type (might be due to invalid IL or missing references) //IL_0d4a: Unknown result type (might be due to invalid IL or missing references) //IL_0cc5: Unknown result type (might be due to invalid IL or missing references) //IL_0cc9: Unknown result type (might be due to invalid IL or missing references) //IL_0cce: Unknown result type (might be due to invalid IL or missing references) //IL_12aa: Unknown result type (might be due to invalid IL or missing references) //IL_12b0: Unknown result type (might be due to invalid IL or missing references) //IL_12b5: Unknown result type (might be due to invalid IL or missing references) //IL_12ba: Unknown result type (might be due to invalid IL or missing references) //IL_0cd2: Unknown result type (might be due to invalid IL or missing references) //IL_0cd7: Unknown result type (might be due to invalid IL or missing references) //IL_118c: Unknown result type (might be due to invalid IL or missing references) //IL_119b: Unknown result type (might be due to invalid IL or missing references) //IL_11a0: Unknown result type (might be due to invalid IL or missing references) //IL_12f9: Unknown result type (might be due to invalid IL or missing references) //IL_12fd: Unknown result type (might be due to invalid IL or missing references) //IL_12ca: Unknown result type (might be due to invalid IL or missing references) //IL_12cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_09eb: Unknown result type (might be due to invalid IL or missing references) //IL_09f1: Invalid comparison between Unknown and I4 //IL_0cff: Unknown result type (might be due to invalid IL or missing references) //IL_0d01: Unknown result type (might be due to invalid IL or missing references) //IL_0d08: Unknown result type (might be due to invalid IL or missing references) //IL_0d12: Unknown result type (might be due to invalid IL or missing references) //IL_0d17: Unknown result type (might be due to invalid IL or missing references) //IL_0d1c: Unknown result type (might be due to invalid IL or missing references) //IL_1206: Unknown result type (might be due to invalid IL or missing references) //IL_11b3: Unknown result type (might be due to invalid IL or missing references) //IL_11b6: Unknown result type (might be due to invalid IL or missing references) //IL_11c5: Unknown result type (might be due to invalid IL or missing references) //IL_11cf: Unknown result type (might be due to invalid IL or missing references) //IL_11d4: Unknown result type (might be due to invalid IL or missing references) //IL_11e3: Unknown result type (might be due to invalid IL or missing references) //IL_11ed: Unknown result type (might be due to invalid IL or missing references) //IL_11f2: Unknown result type (might be due to invalid IL or missing references) //IL_11f7: Unknown result type (might be due to invalid IL or missing references) //IL_11fc: Unknown result type (might be due to invalid IL or missing references) //IL_09f4: Unknown result type (might be due to invalid IL or missing references) //IL_09fa: Invalid comparison between Unknown and I4 //IL_0dda: Unknown result type (might be due to invalid IL or missing references) //IL_0de0: Unknown result type (might be due to invalid IL or missing references) //IL_0de5: Unknown result type (might be due to invalid IL or missing references) //IL_0dea: Unknown result type (might be due to invalid IL or missing references) //IL_0df7: Unknown result type (might be due to invalid IL or missing references) //IL_0dfd: Unknown result type (might be due to invalid IL or missing references) //IL_0e02: Unknown result type (might be due to invalid IL or missing references) //IL_0e07: Unknown result type (might be due to invalid IL or missing references) //IL_10c3: Unknown result type (might be due to invalid IL or missing references) //IL_10c5: Unknown result type (might be due to invalid IL or missing references) //IL_10c7: Unknown result type (might be due to invalid IL or missing references) //IL_10d1: Unknown result type (might be due to invalid IL or missing references) //IL_10d6: Unknown result type (might be due to invalid IL or missing references) //IL_10d8: Unknown result type (might be due to invalid IL or missing references) //IL_10dd: Unknown result type (might be due to invalid IL or missing references) //IL_13a9: Unknown result type (might be due to invalid IL or missing references) //IL_13af: Invalid comparison between Unknown and I4 //IL_1341: Unknown result type (might be due to invalid IL or missing references) //IL_1337: Unknown result type (might be due to invalid IL or missing references) //IL_09fd: Unknown result type (might be due to invalid IL or missing references) //IL_0a03: Invalid comparison between Unknown and I4 //IL_10f9: Unknown result type (might be due to invalid IL or missing references) //IL_1105: Unknown result type (might be due to invalid IL or missing references) //IL_116a: Unknown result type (might be due to invalid IL or missing references) //IL_116e: Unknown result type (might be due to invalid IL or missing references) //IL_13ba: Unknown result type (might be due to invalid IL or missing references) //IL_13c0: Unknown result type (might be due to invalid IL or missing references) //IL_13c5: Unknown result type (might be due to invalid IL or missing references) //IL_13ca: Unknown result type (might be due to invalid IL or missing references) //IL_13b2: Unknown result type (might be due to invalid IL or missing references) //IL_13b8: Invalid comparison between Unknown and I4 //IL_1346: Unknown result type (might be due to invalid IL or missing references) //IL_122c: Unknown result type (might be due to invalid IL or missing references) //IL_123c: Unknown result type (might be due to invalid IL or missing references) //IL_13fe: Unknown result type (might be due to invalid IL or missing references) //IL_1407: Unknown result type (might be due to invalid IL or missing references) //IL_1416: Unknown result type (might be due to invalid IL or missing references) //IL_13da: Unknown result type (might be due to invalid IL or missing references) //IL_13df: Unknown result type (might be due to invalid IL or missing references) //IL_136c: Unknown result type (might be due to invalid IL or missing references) //IL_137b: Unknown result type (might be due to invalid IL or missing references) //IL_16c1: Unknown result type (might be due to invalid IL or missing references) //IL_16cc: Unknown result type (might be due to invalid IL or missing references) //IL_16d1: Unknown result type (might be due to invalid IL or missing references) //IL_16d6: Unknown result type (might be due to invalid IL or missing references) //IL_1256: Unknown result type (might be due to invalid IL or missing references) //IL_1260: Unknown result type (might be due to invalid IL or missing references) //IL_1746: Unknown result type (might be due to invalid IL or missing references) //IL_1751: Unknown result type (might be due to invalid IL or missing references) //IL_1756: Unknown result type (might be due to invalid IL or missing references) //IL_175b: Unknown result type (might be due to invalid IL or missing references) //IL_1703: Unknown result type (might be due to invalid IL or missing references) //IL_1708: Unknown result type (might be due to invalid IL or missing references) //IL_1712: Unknown result type (might be due to invalid IL or missing references) //IL_1717: Unknown result type (might be due to invalid IL or missing references) //IL_171c: Unknown result type (might be due to invalid IL or missing references) //IL_1720: Unknown result type (might be due to invalid IL or missing references) //IL_172f: Unknown result type (might be due to invalid IL or missing references) //IL_16f3: Unknown result type (might be due to invalid IL or missing references) //IL_16f8: Unknown result type (might be due to invalid IL or missing references) //IL_16fd: Unknown result type (might be due to invalid IL or missing references) //IL_0a42: Unknown result type (might be due to invalid IL or missing references) //IL_0a47: Unknown result type (might be due to invalid IL or missing references) //IL_0a53: Unknown result type (might be due to invalid IL or missing references) //IL_0a5f: Unknown result type (might be due to invalid IL or missing references) //IL_0a61: Unknown result type (might be due to invalid IL or missing references) //IL_0a66: Unknown result type (might be due to invalid IL or missing references) //IL_0a6b: Unknown result type (might be due to invalid IL or missing references) //IL_0a73: Unknown result type (might be due to invalid IL or missing references) //IL_0a7b: Unknown result type (might be due to invalid IL or missing references) //IL_0a7d: Unknown result type (might be due to invalid IL or missing references) //IL_0a88: Expected O, but got Unknown //IL_1282: Unknown result type (might be due to invalid IL or missing references) //IL_128c: Unknown result type (might be due to invalid IL or missing references) //IL_101a: Unknown result type (might be due to invalid IL or missing references) //IL_101c: Unknown result type (might be due to invalid IL or missing references) //IL_101e: Unknown result type (might be due to invalid IL or missing references) //IL_1783: Unknown result type (might be due to invalid IL or missing references) //IL_1788: Unknown result type (might be due to invalid IL or missing references) //IL_1792: Unknown result type (might be due to invalid IL or missing references) //IL_1797: Unknown result type (might be due to invalid IL or missing references) //IL_179c: Unknown result type (might be due to invalid IL or missing references) //IL_17a0: Unknown result type (might be due to invalid IL or missing references) //IL_17af: Unknown result type (might be due to invalid IL or missing references) //IL_1778: Unknown result type (might be due to invalid IL or missing references) //IL_177d: Unknown result type (might be due to invalid IL or missing references) //IL_0ebb: Unknown result type (might be due to invalid IL or missing references) //IL_0eca: Unknown result type (might be due to invalid IL or missing references) //IL_14ca: Unknown result type (might be due to invalid IL or missing references) //IL_14d5: Unknown result type (might be due to invalid IL or missing references) //IL_14da: Unknown result type (might be due to invalid IL or missing references) //IL_14df: Unknown result type (might be due to invalid IL or missing references) //IL_1556: Unknown result type (might be due to invalid IL or missing references) //IL_1561: Unknown result type (might be due to invalid IL or missing references) //IL_1566: Unknown result type (might be due to invalid IL or missing references) //IL_156b: Unknown result type (might be due to invalid IL or missing references) //IL_150c: Unknown result type (might be due to invalid IL or missing references) //IL_1518: Unknown result type (might be due to invalid IL or missing references) //IL_151d: Unknown result type (might be due to invalid IL or missing references) //IL_1527: Unknown result type (might be due to invalid IL or missing references) //IL_152c: Unknown result type (might be due to invalid IL or missing references) //IL_1531: Unknown result type (might be due to invalid IL or missing references) //IL_1535: Unknown result type (might be due to invalid IL or missing references) //IL_153c: Unknown result type (might be due to invalid IL or missing references) //IL_14fc: Unknown result type (might be due to invalid IL or missing references) //IL_1501: Unknown result type (might be due to invalid IL or missing references) //IL_1506: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Invalid comparison between Unknown and I4 //IL_0f0a: Unknown result type (might be due to invalid IL or missing references) //IL_0f0f: Unknown result type (might be due to invalid IL or missing references) //IL_1593: Unknown result type (might be due to invalid IL or missing references) //IL_15a5: Unknown result type (might be due to invalid IL or missing references) //IL_15aa: Unknown result type (might be due to invalid IL or missing references) //IL_15b4: Unknown result type (might be due to invalid IL or missing references) //IL_15b9: Unknown result type (might be due to invalid IL or missing references) //IL_15be: Unknown result type (might be due to invalid IL or missing references) //IL_15c2: Unknown result type (might be due to invalid IL or missing references) //IL_15c9: Unknown result type (might be due to invalid IL or missing references) //IL_1588: Unknown result type (might be due to invalid IL or missing references) //IL_158d: Unknown result type (might be due to invalid IL or missing references) //IL_0f35: Unknown result type (might be due to invalid IL or missing references) //IL_0f37: Unknown result type (might be due to invalid IL or missing references) //IL_0f3e: Unknown result type (might be due to invalid IL or missing references) //IL_0f4b: Unknown result type (might be due to invalid IL or missing references) //IL_0f6a: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Invalid comparison between Unknown and I4 //IL_0b8a: Unknown result type (might be due to invalid IL or missing references) //IL_0b91: Unknown result type (might be due to invalid IL or missing references) //IL_0b96: Unknown result type (might be due to invalid IL or missing references) //IL_0b9b: Unknown result type (might be due to invalid IL or missing references) //IL_0bd9: Unknown result type (might be due to invalid IL or missing references) //IL_0be8: Unknown result type (might be due to invalid IL or missing references) //IL_0bf3: Unknown result type (might be due to invalid IL or missing references) //IL_0c05: Unknown result type (might be due to invalid IL or missing references) //IL_0c0a: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04b8: Unknown result type (might be due to invalid IL or missing references) //IL_04f5: Unknown result type (might be due to invalid IL or missing references) //IL_04fa: Unknown result type (might be due to invalid IL or missing references) //IL_0502: Unknown result type (might be due to invalid IL or missing references) //IL_0507: Unknown result type (might be due to invalid IL or missing references) //IL_0509: Unknown result type (might be due to invalid IL or missing references) //IL_0510: Unknown result type (might be due to invalid IL or missing references) //IL_0523: Unknown result type (might be due to invalid IL or missing references) //IL_0545: Unknown result type (might be due to invalid IL or missing references) //IL_054c: Unknown result type (might be due to invalid IL or missing references) //IL_0557: Unknown result type (might be due to invalid IL or missing references) //IL_055e: Unknown result type (might be due to invalid IL or missing references) //IL_0570: Unknown result type (might be due to invalid IL or missing references) //IL_0577: Unknown result type (might be due to invalid IL or missing references) //IL_0585: Unknown result type (might be due to invalid IL or missing references) //IL_058c: Unknown result type (might be due to invalid IL or missing references) //IL_0598: Unknown result type (might be due to invalid IL or missing references) //IL_059a: Unknown result type (might be due to invalid IL or missing references) //IL_059c: Unknown result type (might be due to invalid IL or missing references) //IL_05b1: Unknown result type (might be due to invalid IL or missing references) //IL_0c2e: Unknown result type (might be due to invalid IL or missing references) //IL_0c3d: Unknown result type (might be due to invalid IL or missing references) //IL_0c47: Unknown result type (might be due to invalid IL or missing references) //IL_0c52: Unknown result type (might be due to invalid IL or missing references) //IL_0c64: Unknown result type (might be due to invalid IL or missing references) //IL_0c69: Unknown result type (might be due to invalid IL or missing references) //IL_05e5: Unknown result type (might be due to invalid IL or missing references) //IL_05ea: Unknown result type (might be due to invalid IL or missing references) //IL_05ec: Unknown result type (might be due to invalid IL or missing references) //IL_0cac: Unknown result type (might be due to invalid IL or missing references) //IL_0c74: Unknown result type (might be due to invalid IL or missing references) //IL_0c76: Unknown result type (might be due to invalid IL or missing references) //IL_0c7a: Unknown result type (might be due to invalid IL or missing references) //IL_0c89: Unknown result type (might be due to invalid IL or missing references) //IL_0c93: Unknown result type (might be due to invalid IL or missing references) //IL_0c9e: Unknown result type (might be due to invalid IL or missing references) //IL_0ca3: Unknown result type (might be due to invalid IL or missing references) //IL_0ca8: Unknown result type (might be due to invalid IL or missing references) //IL_0663: Unknown result type (might be due to invalid IL or missing references) //IL_0667: Unknown result type (might be due to invalid IL or missing references) //IL_066c: Unknown result type (might be due to invalid IL or missing references) //IL_067d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s.Pm == (Object)null || !s.Pm.isAlive) { GiveBackStun(s); return true; } if ((Object)(object)s.TargetAnim != (Object)null) { try { float num = ((now - s.StartedAt < AnimFreezeSeconds.Value) ? 0f : s.TargetSpeed); float num2 = Time.fixedDeltaTime / ((num <= 0.01f) ? 0.12f : 0.4f); s.TargetAnim.speed = Mathf.MoveTowards(s.TargetAnim.speed, num, num2); } catch { } } float num3 = now - s.StartedAt; if (ShoveForce.Value > 0f && num3 < ShoveSeconds.Value && (Object)(object)s.Hips != (Object)null) { s.Hips.AddForce(s.Dir * ShoveForce.Value * s.ShoveMul * VolMul(s), (ForceMode)5); } if (!s.Bracing && (s.LastDSeg > FallDistance.Value * 0.6f || s.LastDrop > FallDrop.Value * 0.6f)) { s.Bracing = true; } bool flag = false; try { int num4 = (((Object)(object)s.Pm != (Object)null) ? ((Object)s.Pm).GetInstanceID() : 0); if (num4 != 0 && Clutches.TryGetValue(num4, out var value) && now < value.Until) { flag = true; } } catch { } if (s.Health != null && !s.Bracing) { float num5 = (flag ? UpperBodyStun.Value : 0.45f); RagdollApi.SetLimbStunLevel(s.Health, (MuscleRegion)4, num5); RagdollApi.SetLimbStunLevel(s.Health, (MuscleRegion)5, num5); } float downSpeed = 1f / Mathf.Max(0.05f, MuscleLoosenSeconds.Value); float upSpeed = 1f / Mathf.Max(0.05f, MuscleRecoverSeconds.Value); float factor = (flag ? TorsoStrength.Value : Mathf.Max(TorsoStrength.Value, 0.4f)); float factor2 = (flag ? HeadStrength.Value : Mathf.Max(HeadStrength.Value, 0.4f)); ScaleMuscle(s.Pm, 7, factor, upSpeed, downSpeed); ScaleMuscle(s.Pm, 8, factor, upSpeed, downSpeed); ScaleMuscle(s.Pm, 9, factor2, upSpeed, downSpeed); ScaleMuscle(s.Pm, 16, factor2, upSpeed, downSpeed); int[] torsoMuscles = TorsoMuscles; foreach (int idx in torsoMuscles) { ScaleMapWeight(s.Pm, idx, UpperMapWeight.Value, upSpeed, downSpeed); } torsoMuscles = ArmMusclesL; foreach (int idx2 in torsoMuscles) { ScaleMapWeight(s.Pm, idx2, UpperMapWeight.Value, upSpeed, downSpeed); } torsoMuscles = ArmMusclesR; foreach (int idx3 in torsoMuscles) { ScaleMapWeight(s.Pm, idx3, UpperMapWeight.Value, upSpeed, downSpeed); } float num6 = Mathf.Max(0.6f, 1f - (float)Mathf.Max(0, s.Steps) * 0.04f); float factor3 = (((int)s.Region == 6) ? LegHitStrength.Value : LegStrength.Value) * num6; float factor4 = (((int)s.Region == 7) ? LegHitStrength.Value : LegStrength.Value) * num6; if (!WalkThrough.Value) { torsoMuscles = LegMusclesL; foreach (int idx4 in torsoMuscles) { ScaleMuscle(s.Pm, idx4, factor3, upSpeed, downSpeed); } } if (!WalkThrough.Value) { torsoMuscles = LegMusclesR; foreach (int idx5 in torsoMuscles) { ScaleMuscle(s.Pm, idx5, factor4, upSpeed, downSpeed); } } if (!WalkThrough.Value) { torsoMuscles = LegMusclesL; foreach (int idx6 in torsoMuscles) { ScaleMapWeight(s.Pm, idx6, LegMapping.Value, upSpeed, downSpeed); } } if (!WalkThrough.Value) { torsoMuscles = LegMusclesR; foreach (int idx7 in torsoMuscles) { ScaleMapWeight(s.Pm, idx7, LegMapping.Value, upSpeed, downSpeed); } } float num7 = Vector3.Dot(s.Hips.velocity, s.Dir) - s.V0; if (num3 < 0.5f && num7 > s.PeakDv) { s.PeakDv = num7; } ComputeCom(s, out var com, out var vel); Vector3 position = s.FootL.position; Vector3 position2 = s.FootR.position; float num8 = Mathf.Min(position.y, position2.y); float num9 = Mathf.Max(0.35f, com.y - num8); float num10 = Mathf.Sqrt(9.81f / num9); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(com.x + vel.x / num10, com.z + vel.z / num10); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(position.x, position.z); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(position2.x, position2.z); float num11 = DistPointSegment(val, val2, val3); float num12 = s.HipsY0 - s.Hips.position.y; s.LastDSeg = num11; s.LastDrop = num12; try { if ((Object)(object)s.Hips != (Object)null) { Vector3 velocity = s.Hips.velocity; float y = velocity.y; velocity.y = 0f; float num13 = ((num11 <= BalanceMargin.Value) ? 8f : 3f); float num14 = Mathf.Max(0f, num13 - AdvanceForce.Value); if (WalkThrough.Value) { num14 = 0f; } float num15 = Mathf.Max(0f, 1f - num14 * Time.fixedDeltaTime); velocity *= num15; velocity.y = y; s.Hips.velocity = velocity; } } catch { } bool flag2 = !s.Swinging && s.Steps >= MaxSteps.Value && num11 > BalanceMargin.Value; if (flag2 && num12 < FallDrop.Value * 0.5f && num11 < FallDistance.Value * 0.5f && s.Steps < MaxSteps.Value + 4) { s.Steps = MaxSteps.Value - 2; flag2 = false; } if (num12 > FallDrop.Value || num11 > FallDistance.Value || flag2) { string text = ((num12 > FallDrop.Value) ? "hips dropping" : ((num11 > FallDistance.Value) ? "too far gone" : "out of steps")); LogEnd(s, "FELL (" + text + ")", num3, num11, num12); GiveBackStun(s); float num16 = FallSeconds.Value; try { if (UsesLastStand(s.Pm, s.Health)) { num16 *= 3f; if (_endLogs < 14) { _endLogs++; MelonLogger.Msg("Stagger end: last stand (long floor clutch)"); } } } catch { } RagdollApi.KnockDown(s.Pm, s.Health, num16); RagdollApi.HoldLoco(s.Pm, num16); RagdollApi.HoldNav(s.Pm, num16); RagdollApi.HoldLiteLoco(s.Pm, num16); try { int num17 = (((Object)(object)s.Pm != (Object)null) ? ((Object)s.Pm).GetInstanceID() : 0); if (num17 != 0 && s.Bodies != null) { if (DownedMap.Count > 64) { DownedMap.Clear(); } bool flag3 = false; try { flag3 = RagdollApi.SetGetupDisabled(s.Pm, true); } catch { } if (_standLogs < 40) { _standLogs++; MelonLogger.Msg("Downed: getup lock " + (flag3 ? "HELD" : "FAILED")); } Downed downed = new Downed { Pm = s.Pm, Health = s.Health, Bodies = s.Bodies, Until = now + num16, NextWrithe = now + Random.Range(0.15f, 0.3f), PrevH = 99f, Landed = false, LastStand = (num16 > FallSeconds.Value * 1.5f), Region = s.Region, NextStir = now + Random.Range(2f, 3f) }; try { Animator val4 = (((Object)(object)s.Pm != (Object)null) ? s.Pm.targetAnimator : null); if ((Object)(object)val4 != (Object)null) { downed.Anim = val4; downed.AnimSpeed = DownedAnimSpeed(num17, s.TargetSpeed, val4); downed.HasAnim = true; } } catch { } DownedMap[num17] = downed; Thaws.Remove(num17); try { if (Clutches.TryGetValue(num17, out var value2)) { UpgradeClutch(value2); value2.Until = Mathf.Max(value2.Until, now + num16); } else if (Enabled.Value) { int num18 = (((int)s.Region == 6) ? 3 : (((int)s.Region == 7) ? 6 : (((int)s.Region != 1) ? 8 : 0))); Rigidbody val5 = ((s.Bodies != null && num18 >= 0 && num18 < s.Bodies.Length) ? s.Bodies[num18] : null); if ((Object)(object)val5 != (Object)null) { StartClutch(new NpcHitInfo { Puppet = s.Pm, Health = s.Health, Region = s.Region, Body = val5, MuscleIndex = num18, Tier = (HitTier)1 }, force: true); if (Clutches.TryGetValue(num17, out var value3)) { value3.Until = Mathf.Max(value3.Until, now + num16); } } } } catch { } } } catch { } return true; } Vector3 val12; if (s.Swinging) { Rigidbody val6 = (s.SwingLeft ? s.FootL : s.FootR); torsoMuscles = (s.SwingLeft ? LegMusclesL : LegMusclesR); foreach (int idx8 in torsoMuscles) { ScaleMuscle(s.Pm, idx8, SwingLegStrength.Value, 12f, 12f); } float factor5 = StanceGrip(s, !s.SwingLeft); torsoMuscles = (s.SwingLeft ? LegMusclesR : LegMusclesL); foreach (int idx9 in torsoMuscles) { ScaleMuscle(s.Pm, idx9, factor5, 8f, 8f); } Vector3 val7 = s.SwingTarget - val6.position; val7.y = 0f; float magnitude = ((Vector3)(ref val7)).magnitude; float num19 = Mathf.Clamp01((now - s.SwingStart) / Mathf.Max(0.05f, s.SwingUntil - s.SwingStart)); Vector3 val8 = Vector3.up * LiftForce.Value * s.StepLiftMul * Mathf.Sin(num19 * (float)Math.PI); try { Rigidbody val9 = s.Bodies[s.SwingLeft ? 2 : 5]; if ((Object)(object)val9 != (Object)null) { Vector3 val10 = Vector3.up * LiftForce.Value * 0.7f * s.StepLiftMul * Mathf.Sin(num19 * (float)Math.PI); if (magnitude > 0.04f) { val10 += val7 / magnitude * SwingForce.Value * 0.15f * s.StepForceMul; } val9.AddForce(val10, (ForceMode)5); } } catch { } if (magnitude > 0.04f) { Vector3 val11 = val7 / magnitude; try { float num20 = Vector3.Dot(val6.velocity, val11); float num21 = Mathf.Clamp(magnitude * 4f, 0.25f, 4f); if (num20 > num21) { val8 -= val11 * (num20 - num21) * 14f; } } catch { } val8 += val11 * SwingForce.Value * s.StepForceMul; } val6.AddForce(val8, (ForceMode)5); float rate = 5f + AdvanceForce.Value * 1.5f; if (!WalkThrough.Value) { BrakeFoot(s.SwingLeft ? s.FootR : s.FootL, rate); } if (now >= s.SwingUntil) { ReleaseLeg(s); s.Swinging = false; s.PlantUntil = now + 0.16f; s.NextStepAt = now + 0.05f; s.LastFoot = val6; if (_strideLogs < 8) { try { val12 = s.SwingTarget - s.SwingFrom; float magnitude2 = ((Vector3)(ref val12)).magnitude; val12 = val6.position - s.SwingFrom; float magnitude3 = ((Vector3)(ref val12)).magnitude; _strideLogs++; MelonLogger.Msg($"Stride {s.Steps}: wanted {magnitude2:F2}m, foot travelled {magnitude3:F2}m"); } catch { } } } } else { if ((Object)(object)s.LastFoot != (Object)null && now < s.PlantUntil) { s.LastFoot.AddForce(Vector3.down * PlantForce.Value, (ForceMode)5); BrakeFoot(s.LastFoot, 12f + AdvanceForce.Value * 1.5f); try { if ((Object)(object)s.Hips != (Object)null) { Vector3 velocity2 = s.Hips.velocity; velocity2.y = 0f; float magnitude4 = ((Vector3)(ref velocity2)).magnitude; if (magnitude4 > 1.5f) { s.Hips.AddForce(-velocity2 / magnitude4 * (magnitude4 - 1.5f) * Mathf.Max(0f, 8f - AdvanceForce.Value), (ForceMode)5); } } } catch { } torsoMuscles = (((Object)(object)s.LastFoot == (Object)(object)s.FootL) ? LegMusclesL : LegMusclesR); foreach (int idx10 in torsoMuscles) { ScaleMuscle(s.Pm, idx10, StanceGrip(s, (Object)(object)s.LastFoot == (Object)(object)s.FootL), 8f, 8f); } } if (num11 > StepMargin.Value && now >= s.NextStepAt && s.Steps < MaxSteps.Value && !WalkThrough.Value) { BeginStep(s, now, val, val2, val3, num8, num11); } if (!WalkThrough.Value) { BrakeFoot(s.FootL, 5f + AdvanceForce.Value * 1.5f); } if (!WalkThrough.Value) { BrakeFoot(s.FootR, 5f + AdvanceForce.Value * 1.5f); } } if (!WalkThrough.Value && HipAssist.Value > 0f && num11 > 0.02f && (Object)(object)s.Hips != (Object)null) { Vector2 val13 = (val2 + val3) * 0.5f - val; if (((Vector2)(ref val13)).sqrMagnitude > 0.0001f) { ((Vector2)(ref val13)).Normalize(); Vector3 val14 = default(Vector3); ((Vector3)(ref val14))..ctor(val13.x, 0f, val13.y); float num22 = Mathf.Min(HipAssist.Value, HipAssist.Value * num11 / Mathf.Max(0.05f, BalanceMargin.Value)); num22 *= Mathf.Clamp01(num3 / Mathf.Max(0.05f, AssistRampSeconds.Value)); s.Hips.AddForce(val14 * num22, (ForceMode)5); } } if ((Object)(object)s.Bodies[8] != (Object)null) { Vector3 val15 = Vector3.up * TorsoLift.Value; if (ForwardBe
Mods\DynamicRagdoll2.dll
Decompiled 8 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Marrow.PuppetMasta; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using RagdollOnHit; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(Main), "DynamicRagdoll2", "1.0.1", "skait5k", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("DynamicRagdoll2")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("DynamicRagdoll2")] [assembly: AssemblyTitle("DynamicRagdoll2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RagdollOnHit { public enum HitTier { Light, Medium, Kill } public enum MuscleRegion { Unknown, Hips, Torso, Head, ArmL, ArmR, LegL, LegR } public sealed class NpcHitInfo { public PuppetMaster Puppet; public BehaviourPuppet Behaviour; public SubBehaviourHealth Health; public int MuscleIndex; public MuscleRegion Region; public Rigidbody Body; public Vector3 HitPoint; public bool HasHitPoint; public string AttackType; public string Gun; public Vector3 Direction; public float Damage; public HitTier Tier; public bool IsDead; } public static class RagdollApi { public static bool AutoKnockdown = true; public static MelonPreferences_Entry<bool> EnabledEntry; private static readonly Dictionary<int, object> SfxCache = new Dictionary<int, object>(); private static readonly HashSet<int> NoSfx = new HashSet<int>(); private static readonly string[] ExcludedTokens = new string[6] { "omni", "turret", "crablet", "skeleton", "nullrat", "cultist" }; private static readonly Dictionary<int, bool> ExcludedCache = new Dictionary<int, bool>(); private static int _excludeLogs; public static event Action<NpcHitInfo> OnNpcHit; public static void HoldMapping(PuppetMaster pm, float seconds) { if (!((Object)(object)pm == (Object)null)) { Main.HoldMapping(pm, seconds); } } public static void KnockDown(PuppetMaster pm, SubBehaviourHealth health, float seconds) { if (!((Object)(object)pm == (Object)null)) { Main.KnockDown(pm, health, seconds); } } public static void HoldLimp(PuppetMaster pm, SubBehaviourHealth health, float weight, float seconds) { if (!((Object)(object)pm == (Object)null)) { Main.HoldLimp(pm, health, weight, seconds); } } public static void HoldMapping(PuppetMaster pm, float seconds, float weight) { if (!((Object)(object)pm == (Object)null)) { Main.HoldMapping(pm, seconds, weight); } } public static void HoldLoco(PuppetMaster pm, float seconds) { if (!((Object)(object)pm == (Object)null)) { Main.HoldLoco(pm, seconds); } } public static void HoldNav(PuppetMaster pm, float seconds) { if (!((Object)(object)pm == (Object)null)) { Main.HoldNav(pm, seconds); } } public static void HoldLiteLoco(PuppetMaster pm, float seconds) { if (!((Object)(object)pm == (Object)null)) { Main.HoldLiteLoco(pm, seconds); } } public static void ReleaseAI(PuppetMaster pm) { if (!((Object)(object)pm == (Object)null)) { Main.ReleaseAI(pm); } } public static void Diag(PuppetMaster pm) { if (!((Object)(object)pm == (Object)null)) { Main.Diag(pm); } } public static MuscleRegion RegionOf(int muscleIndex) { switch (muscleIndex) { case 0: return MuscleRegion.Hips; case 1: case 2: case 3: return MuscleRegion.LegL; default: if (muscleIndex >= 4 && muscleIndex <= 6) { return MuscleRegion.LegR; } switch (muscleIndex) { case 7: case 8: return MuscleRegion.Torso; case 9: case 16: return MuscleRegion.Head; case 10: case 11: case 12: return MuscleRegion.ArmL; default: if (muscleIndex >= 13 && muscleIndex <= 15) { return MuscleRegion.ArmR; } return MuscleRegion.Unknown; } } } internal static string StunFieldOf(MuscleRegion region) { return region switch { MuscleRegion.ArmL => "stun_arm_lf", MuscleRegion.ArmR => "stun_arm_rt", MuscleRegion.LegL => "stun_leg_lf", MuscleRegion.LegR => "stun_leg_rt", _ => "stun_spine", }; } public static float GetLimbStun(SubBehaviourHealth h, MuscleRegion region) { if (!Reflect.TryGet<float>(h, StunFieldOf(region), out var value)) { return 1f; } return value; } public static void SetLimbStun(SubBehaviourHealth h, MuscleRegion region, float level) { if (h != null) { string name = StunFieldOf(region); if (Reflect.TryGet<float>(h, name, out var value) && level < value) { Reflect.TrySet(h, name, level); } } } public static float CurHp(SubBehaviourHealth h) { try { if (h != null && Reflect.TryGet<float>(h, "cur_hp", out var value)) { return value; } } catch { } return -1f; } public static float HpFraction(SubBehaviourHealth h) { try { if (h == null) { return 1f; } float num = -1f; float num2 = 0f; if (Reflect.TryGet<float>(h, "cur_hp", out var value)) { num = value; } if (Reflect.TryGet<float>(h, "maxHitPoints", out var value2)) { num2 = value2; } if (num2 > 0f && num >= 0f) { return Mathf.Clamp01(num / num2); } } catch { } return 1f; } public static object FindSfx(PuppetMaster pm) { int instanceID; try { instanceID = ((Object)pm).GetInstanceID(); } catch { return null; } if (SfxCache.TryGetValue(instanceID, out var value) && value != null) { return value; } if (NoSfx.Contains(instanceID)) { return null; } try { foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours) { if ((Object)(object)item == (Object)null) { continue; } string className; SubBehaviourSfx val = Reflect.FindMemberOfType<SubBehaviourSfx>(Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out className), out className); if (val != null) { if (SfxCache.Count > 512) { SfxCache.Clear(); } SfxCache[instanceID] = val; return val; } } } catch { } if (NoSfx.Count > 512) { NoSfx.Clear(); } NoSfx.Add(instanceID); return null; } public static bool SetGetupDisabled(PuppetMaster pm, bool disabled) { if ((Object)(object)pm == (Object)null) { return false; } try { if (Reflect.TrySetBool(pm, "getupDisabled", disabled) && Reflect.TryGet<bool>(pm, "getupDisabled", out var value) && value == disabled) { return true; } try { foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours) { if (!((Object)(object)item == (Object)null)) { object obj = null; try { obj = Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out var _); } catch { } object o = obj ?? item; if (Reflect.TrySetBool(o, "getupDisabled", disabled) && Reflect.TryGet<bool>(o, "getupDisabled", out var value2) && value2 == disabled) { return true; } if (Reflect.TrySetBool(o, "getUpDisabled", disabled) && Reflect.TryGet<bool>(o, "getUpDisabled", out var value3) && value3 == disabled) { return true; } } } } catch { } } catch { } return false; } public static void SetLimbStunLevel(SubBehaviourHealth h, MuscleRegion region, float level) { if (h != null) { Reflect.TrySet(h, StunFieldOf(region), Mathf.Clamp01(level)); } } internal static void ClearNpcCache() { ExcludedCache.Clear(); } private static string NormName(string s) { if (string.IsNullOrEmpty(s)) { return ""; } char[] array = new char[s.Length]; int length = 0; foreach (char c in s) { if (c >= 'a' && c <= 'z') { array[length++] = c; } else if (c >= 'A' && c <= 'Z') { array[length++] = (char)(c + 32); } else if (c >= '0' && c <= '9') { array[length++] = c; } } return new string(array, 0, length); } public static bool IsExcluded(PuppetMaster pm) { int instanceID; try { instanceID = ((Object)pm).GetInstanceID(); } catch { return true; } if (ExcludedCache.TryGetValue(instanceID, out var value)) { return value; } bool flag = CheckExcluded(pm); if (ExcludedCache.Count > 256) { ExcludedCache.Clear(); } ExcludedCache[instanceID] = flag; return flag; } private static bool CheckExcluded(PuppetMaster pm) { try { Transform val = ((Component)pm).transform; for (int i = 0; i < 6; i++) { if (!((Object)(object)val != (Object)null)) { break; } string text = null; try { text = ((Object)val).name; } catch { } string text2 = NormName(text); if (text2.Length > 0) { string[] excludedTokens = ExcludedTokens; foreach (string value in excludedTokens) { if (text2.Contains(value)) { if (_excludeLogs < 6) { _excludeLogs++; MelonLogger.Msg($"NPC gate: skipping '{text}' (matched '{value}')"); } return true; } } } try { val = val.parent; } catch { break; } } } catch { } return false; } public static bool IsNullBody(PuppetMaster pm) { try { Transform val = ((Component)pm).transform; for (int i = 0; i < 6; i++) { if (!((Object)(object)val != (Object)null)) { break; } try { if (NormName(((Object)val).name).Contains("nullbodyagent")) { return true; } } catch { } try { val = val.parent; } catch { break; } } } catch { } return false; } internal static void Raise(NpcHitInfo info) { Action<NpcHitInfo> onNpcHit = RagdollApi.OnNpcHit; if (onNpcHit == null) { return; } Delegate[] invocationList = onNpcHit.GetInvocationList(); foreach (Delegate obj in invocationList) { try { ((Action<NpcHitInfo>)obj)(info); } catch (Exception value) { MelonLogger.Error($"RagdollApi subscriber threw: {value}"); } } } } public class Main : MelonMod { private sealed class Reaction { public float Original; public float Weight; public float HoldUntil; public SubBehaviourHealth Health; public float[] Held; } private sealed class MapHold { public float Original; public float Weight; public float Until; } private sealed class FlagHold { public object Beh; public bool Original; public float Until; } private sealed class FloatHold { public object Target; public float Original; public float Until; } private static MelonPreferences_Entry<float> GetUpDelay; private static MelonPreferences_Entry<float> KnockbackForce; private static MelonPreferences_Entry<float> KnockdownDamage; private static MelonPreferences_Entry<bool> UseGameStun; private static MelonPreferences_Entry<float> LightStunLevel; private static MelonPreferences_Entry<float> LightMuscleWeight; private static MelonPreferences_Entry<float> LightSeconds; private static MelonPreferences_Entry<float> RecoverSeconds; private static MelonPreferences_Entry<float> SlowMoScale; private static MelonPreferences_Entry<float> SlowMoSeconds; private static MelonPreferences_Entry<bool> LogHits; private static MelonPreferences_Entry<bool> Enabled; private const float ReactCooldown = 0.25f; private const float DropSpeed = 20f; private static readonly string[] StunFields = new string[5] { "stun_spine", "stun_arm_lf", "stun_arm_rt", "stun_leg_lf", "stun_leg_rt" }; private static readonly Dictionary<int, Reaction> Reactions = new Dictionary<int, Reaction>(); private static readonly Dictionary<int, float> LastReact = new Dictionary<int, float>(); private static readonly Dictionary<int, SubBehaviourHealth> HealthCache = new Dictionary<int, SubBehaviourHealth>(); private static readonly HashSet<int> NoHealth = new HashSet<int>(); private static bool _dumpedAttack; private static bool _dumpedStructure; private static bool _loggedHealth; private static bool _loggedNoHealth; private static bool _loggedStun; private static bool _loggedLightDip; private static bool _loggedMedium; private static bool _loggedUnpin; private static bool _loggedKill; private static bool _slowActive; private static int _hitLogCount; private static int _locoLogs; private static int _originLogs; private static int _sourceLogs; private static readonly HashSet<string> _attackTypeLogs = new HashSet<string>(); private static readonly Dictionary<int, MapHold> MapHolds = new Dictionary<int, MapHold>(); private static readonly Dictionary<string, FlagHold> FlagHolds = new Dictionary<string, FlagHold>(); private static readonly Dictionary<string, FloatHold> FloatHolds = new Dictionary<string, FloatHold>(); private static int _diagCount; public override void OnInitializeMelon() { MelonPreferences_Category obj = MelonPreferences.CreateCategory("RagdollOnHit"); GetUpDelay = obj.CreateEntry<float>("GetUpDelay", 3f, "Seconds a knocked-down NPC stays limp", (string)null, false, false, (ValueValidator)null, (string)null); KnockbackForce = obj.CreateEntry<float>("KnockbackForce", 4f, "Shove on hit (0 = none)", (string)null, false, false, (ValueValidator)null, (string)null); KnockdownDamage = obj.CreateEntry<float>("KnockdownDamage", 0.5f, "Hits at/above this damage knock the NPC down (0 = every hit)", (string)null, false, false, (ValueValidator)null, (string)null); UseGameStun = obj.CreateEntry<bool>("UseGameStun", true, "Light hits use the game's own per-limb stun (false = whole-body muscle dip)", (string)null, false, false, (ValueValidator)null, (string)null); LightStunLevel = obj.CreateEntry<float>("LightStunLevel", 0.15f, "Light hits: how limp the hit limb goes (0 = fully limp, 1 = normal)", (string)null, false, false, (ValueValidator)null, (string)null); LightMuscleWeight = obj.CreateEntry<float>("LightMuscleWeight", 0.3f, "Fallback dip: muscle strength during a light hit (0 = limp, 1 = normal)", (string)null, false, false, (ValueValidator)null, (string)null); LightSeconds = obj.CreateEntry<float>("LightSeconds", 0.4f, "Fallback dip: how long a light hit lasts", (string)null, false, false, (ValueValidator)null, (string)null); RecoverSeconds = obj.CreateEntry<float>("RecoverSeconds", 0.8f, "How long it takes to stiffen back up afterwards", (string)null, false, false, (ValueValidator)null, (string)null); SlowMoScale = obj.CreateEntry<float>("SlowMoScale", 1f, "Time scale on a kill (1 = off, 0.3 = slow-mo)", (string)null, false, false, (ValueValidator)null, (string)null); SlowMoSeconds = obj.CreateEntry<float>("SlowMoSeconds", 1f, "Slow-mo length in real seconds", (string)null, false, false, (ValueValidator)null, (string)null); LogHits = obj.CreateEntry<bool>("LogHits", true, "Log the first 50 hits (damage, muscle, tier)", (string)null, false, false, (ValueValidator)null, (string)null); Enabled = obj.CreateEntry<bool>("Enabled", true, "Master switch: base reactions + API events on/off", (string)null, false, false, (ValueValidator)null, (string)null); RagdollApi.EnabledEntry = Enabled; ((MelonBase)this).LoggerInstance.Msg("DynamicRagdoll2 1.0.1 loaded."); GunHook.TryInstall(); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { LastReact.Clear(); HealthCache.Clear(); NoHealth.Clear(); RagdollApi.ClearNpcCache(); } private static string SafeName(PuppetMaster pm) { try { return ((Object)pm).name + "#" + ((Object)pm).GetInstanceID().ToString("X8"); } catch { return "?"; } } internal static void HandleHit(MuscleCollisionBroadcaster b, object attack) { //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0487: Unknown result type (might be due to invalid IL or missing references) //IL_04c1: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Unknown result type (might be due to invalid IL or missing references) //IL_04e4: Unknown result type (might be due to invalid IL or missing references) //IL_04e6: Unknown result type (might be due to invalid IL or missing references) PuppetMaster puppetMaster = b.puppetMaster; if ((Object)(object)puppetMaster == (Object)null || !Enabled.Value || RagdollApi.IsExcluded(puppetMaster)) { return; } if (!_dumpedAttack && attack != null) { _dumpedAttack = true; Reflect.LogMembers(attack, "Attack members", includeBases: false); } int muscleIndex = b.muscleIndex; if (!_dumpedStructure) { _dumpedStructure = true; DumpStructure(puppetMaster); } Rigidbody val = ((Component)b).GetComponent<Rigidbody>(); if ((Object)(object)val == (Object)null) { val = ((Component)b).GetComponentInParent<Rigidbody>(); } if (!Reflect.TryGet<float>(attack, "damage", out var value)) { value = -1f; } string text = "Unknown"; try { if (attack != null && Reflect.TryGetObj(attack, "attackType", out var value2) && value2 != null) { text = value2.ToString(); if (_attackTypeLogs.Count < 5 && _attackTypeLogs.Add(text)) { MelonLogger.Msg("AttackType seen: " + text); } } } catch { } if (_sourceLogs < 24) { bool flag = false; try { flag = !puppetMaster.isAlive || puppetMaster.isKilling; } catch { } if (value >= KnockdownDamage.Value || flag) { _sourceLogs++; string value3 = "?"; string value4 = "?"; try { if (attack != null && Reflect.TryGetObj(attack, "collider", out var value5) && value5 != null) { object value6 = null; try { Reflect.TryGetObj(value5, "name", out value6); } catch { } value3 = (value6 ?? value5.ToString())?.ToString() ?? "?"; } if (attack != null && Reflect.TryGetObj(attack, "proxy", out var value7) && value7 != null) { value4 = value7.ToString(); } } catch { } MelonLogger.Msg($"Hit source: type={text} collider={value3} proxy={value4} dmg={value:F2}"); } } Vector3 hitPoint = Vector3.zero; bool flag2 = false; Vector3 val2; try { if (attack != null && Reflect.TryGet<Vector3>(attack, "origin", out var value8)) { val2 = value8 - ((Component)b).transform.position; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude < 1.5f) { hitPoint = value8; flag2 = true; } if (_originLogs < 5) { _originLogs++; MelonLogger.Msg($"[hit-origin {_originLogs}/5] origin->muscle dist={magnitude:F2}m {(flag2 ? "TRUSTED" : "rejected (muzzle?)")}"); } } } catch { } Vector3 val3; if (Reflect.TryGet<Vector3>(attack, "direction", out var value9) && ((Vector3)(ref value9)).sqrMagnitude > 0.0001f) { val3 = ((Vector3)(ref value9)).normalized; } else { val3 = Vector3.up; Camera main = Camera.main; if ((Object)(object)main != (Object)null) { val2 = ((Component)b).transform.position - ((Component)main).transform.position; val3 = ((Vector3)(ref val2)).normalized; } } bool flag3 = !puppetMaster.isAlive || puppetMaster.isKilling; HitTier hitTier = (flag3 ? HitTier.Kill : ((!(value >= 0f) || !(value < KnockdownDamage.Value)) ? HitTier.Medium : HitTier.Light)); MuscleRegion muscleRegion = RagdollApi.RegionOf(muscleIndex); if (LogHits.Value && _hitLogCount < 50) { _hitLogCount++; MelonLogger.Msg($"[hit {_hitLogCount}/50] muscle={muscleIndex} ({muscleRegion}) damage={value:F2} tier={hitTier} dead={flag3} npc={SafeName(puppetMaster)}"); } BehaviourPuppet val4 = FindPuppet(puppetMaster); SubBehaviourHealth health = FindHealth(puppetMaster); React(puppetMaster, val4, health, hitTier, muscleRegion, val, val3); RagdollApi.Raise(new NpcHitInfo { Puppet = puppetMaster, Behaviour = val4, Health = health, MuscleIndex = muscleIndex, Region = muscleRegion, Body = val, HitPoint = hitPoint, HasHitPoint = flag2, AttackType = text, Gun = GunHook.Attribute(), Direction = val3, Damage = value, Tier = hitTier, IsDead = flag3 }); } private static BehaviourPuppet FindPuppet(PuppetMaster pm) { BehaviourPuppet componentInChildren = ((Component)pm).GetComponentInChildren<BehaviourPuppet>(true); if ((Object)(object)componentInChildren != (Object)null) { return componentInChildren; } try { Il2CppReferenceArray<BehaviourBase> behaviours = pm.behaviours; if (behaviours != null) { foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)behaviours) { if (!((Object)(object)item == (Object)null)) { BehaviourPuppet val = ((Il2CppObjectBase)item).TryCast<BehaviourPuppet>(); if ((Object)(object)val != (Object)null) { return val; } } } } } catch { } return null; } private static SubBehaviourHealth FindHealth(PuppetMaster pm) { int instanceID = ((Object)pm).GetInstanceID(); if (HealthCache.TryGetValue(instanceID, out var value) && value != null) { return value; } if (NoHealth.Contains(instanceID)) { return null; } try { foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours) { if ((Object)(object)item == (Object)null) { continue; } string className; string memberName; SubBehaviourHealth val = Reflect.FindMemberOfType<SubBehaviourHealth>(Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out className), out memberName); if (val != null) { if (HealthCache.Count > 512) { HealthCache.Clear(); } HealthCache[instanceID] = val; if (!_loggedHealth) { _loggedHealth = true; MelonLogger.Msg("Found SubBehaviourHealth at " + memberName); Reflect.LogValues(val, "SubBehaviourHealth values"); } return val; } } } catch (Exception ex) { MelonLogger.Warning("FindHealth failed: " + ex.Message); } if (NoHealth.Count > 512) { NoHealth.Clear(); } NoHealth.Add(instanceID); if (!_loggedNoHealth) { _loggedNoHealth = true; MelonLogger.Msg("No SubBehaviourHealth found on this NPC; light hits use the muscle dip instead."); } return null; } private static void React(PuppetMaster pm, BehaviourPuppet bp, SubBehaviourHealth health, HitTier tier, MuscleRegion region, Rigidbody body, Vector3 dir) { //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)pm).GetInstanceID(); float time = Time.time; if (tier != HitTier.Kill && LastReact.TryGetValue(instanceID, out var value) && time - value < 0.25f) { return; } LastReact[instanceID] = time; float num = 0f; switch (tier) { case HitTier.Light: num = 0.25f; if (health != null && UseGameStun.Value) { RagdollApi.SetLimbStun(health, region, LightStunLevel.Value); if (!_loggedStun) { _loggedStun = true; MelonLogger.Msg($"Light hit -> limb stun on {region}"); } } else { Dip(pm, null, LightMuscleWeight.Value, LightSeconds.Value); if (!_loggedLightDip) { _loggedLightDip = true; MelonLogger.Msg("Light hit -> muscleWeight dip"); } } break; case HitTier.Medium: if (!RagdollApi.AutoKnockdown) { break; } num = 1f; if ((Object)(object)bp != (Object)null) { bp.canGetUp = true; bp.getUpDelay = GetUpDelay.Value; bp.Unpin(); if (!_loggedUnpin) { _loggedUnpin = true; MelonLogger.Msg("Medium hit -> BehaviourPuppet.Unpin()"); } } else { Dip(pm, health, 0f, GetUpDelay.Value); if (!_loggedMedium) { _loggedMedium = true; MelonLogger.Msg("Medium hit -> muscleWeight drop (limb stun frozen while down)"); } } break; case HitTier.Kill: ReleaseNow(pm); num = 1.5f; SlowMo(SlowMoSeconds.Value, SlowMoScale.Value); if (!_loggedKill) { _loggedKill = true; Reflect.TryGet<object>(pm, "state", out var value2); MelonLogger.Msg($"Kill -> PuppetMaster state={value2}"); } break; } if ((Object)(object)body != (Object)null && num > 0f && KnockbackForce.Value > 0f) { body.AddForce(dir * KnockbackForce.Value * num, (ForceMode)2); } } internal static void HoldMapping(PuppetMaster pm, float seconds) { HoldMapping(pm, seconds, 1f); } internal static void HoldMapping(PuppetMaster pm, float seconds, float weight) { int instanceID = ((Object)pm).GetInstanceID(); float num = Time.time + seconds; if (MapHolds.TryGetValue(instanceID, out var value)) { value.Until = Mathf.Max(value.Until, num); value.Weight = Mathf.Min(value.Weight, weight); return; } value = new MapHold { Original = pm.mappingWeight, Weight = weight, Until = num }; MapHolds[instanceID] = value; MelonCoroutines.Start(MapRoutine(pm, instanceID, value)); } private static IEnumerator MapRoutine(PuppetMaster pm, int id, MapHold h) { while ((Object)(object)pm != (Object)null && pm.isAlive && Time.time < h.Until) { pm.mappingWeight = h.Weight; yield return null; } if ((Object)(object)pm != (Object)null) { try { pm.mappingWeight = h.Original; } catch { } } MapHolds.Remove(id); } internal static void HoldBoolFlag(PuppetMaster pm, string field, bool value, float seconds) { string key = ((Object)pm).GetInstanceID() + ":" + field; float num = Time.time + seconds; if (FlagHolds.TryGetValue(key, out var value2)) { value2.Until = Mathf.Max(value2.Until, num); return; } object obj = null; bool flag = !value; try { foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours) { if (!((Object)(object)item == (Object)null)) { string className; object obj2 = Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out className) ?? item; if (Reflect.TryGet<bool>(obj2, field, out var value3)) { obj = obj2; flag = value3; break; } } } } catch { } if (obj == null) { if (_locoLogs < 8) { _locoLogs++; MelonLogger.Msg("HoldFlag: no " + field + " found on this NPC, nothing held"); } return; } value2 = new FlagHold { Beh = obj, Original = flag, Until = num }; FlagHolds[key] = value2; Reflect.TrySetBool(obj, field, value); bool value4; bool flag2 = Reflect.TryGet<bool>(obj, field, out value4); if (_locoLogs < 8) { _locoLogs++; MelonLogger.Msg($"HoldFlag: {field} was {flag}, now reads {(flag2 ? value4.ToString() : "?")} -> {((flag2 && value4 == value) ? "held" : "WRITE FAILED")}"); } MelonCoroutines.Start(FlagRoutine(pm, key, value2, field, value)); } private static IEnumerator FlagRoutine(PuppetMaster pm, string key, FlagHold h, string field, bool value) { int frame = 0; while (((Object)(object)pm == (Object)null || pm.isAlive) && Time.time < h.Until) { if (h.Beh != null && (frame++ & 0xF) == 0) { Reflect.TrySetBool(h.Beh, field, value); } yield return null; } if (h.Beh != null && ((Object)(object)pm == (Object)null || pm.isAlive)) { Reflect.TrySetBool(h.Beh, field, h.Original); } FlagHolds.Remove(key); } internal static void HoldLoco(PuppetMaster pm, float seconds) { HoldBoolFlag(pm, "followPlayer", value: false, seconds); } internal static void HoldNav(PuppetMaster pm, float seconds) { HoldBoolFlag(pm, "_isNavAgentStopped", value: true, seconds); } internal static void HoldLiteLoco(PuppetMaster pm, float seconds) { string key = ((Object)pm).GetInstanceID() + ":liteloco.weight"; float num = Time.time + seconds; if (FloatHolds.TryGetValue(key, out var value)) { value.Until = Mathf.Max(value.Until, num); return; } object obj = null; float num2 = 1f; try { foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours) { if (!((Object)(object)item == (Object)null) && Reflect.TryGetObj(Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out var _) ?? item, "_liteLoco", out var value2) && value2 != null) { obj = value2; break; } } } catch { } if (obj == null) { if (_locoLogs < 10) { _locoLogs++; MelonLogger.Msg("HoldLiteLoco: no _liteLoco on this NPC, nothing held"); } return; } if (!Reflect.TryGet<float>(obj, "weight", out var value3)) { value3 = 1f; } num2 = value3; value = new FloatHold { Target = obj, Original = num2, Until = num }; FloatHolds[key] = value; Reflect.TrySet(obj, "weight", 0f); float value4; bool flag = Reflect.TryGet<float>(obj, "weight", out value4); if (_locoLogs < 10) { _locoLogs++; MelonLogger.Msg($"HoldLiteLoco: weight was {num2:F2}, now reads {(flag ? value4.ToString("F2") : "?")} -> {((flag && value4 < 0.01f) ? "held" : "WRITE FAILED")}"); } MelonCoroutines.Start(FloatRoutine(pm, key, value)); } private static IEnumerator FloatRoutine(PuppetMaster pm, string key, FloatHold h) { int frame = 0; while (((Object)(object)pm == (Object)null || pm.isAlive) && Time.time < h.Until) { if (h.Target != null && (frame++ & 0xF) == 0) { Reflect.TrySet(h.Target, "weight", 0f); } yield return null; } if (h.Target != null && ((Object)(object)pm == (Object)null || pm.isAlive)) { Reflect.TrySet(h.Target, "weight", h.Original); } FloatHolds.Remove(key); } internal static void ReleaseAI(PuppetMaster pm) { int instanceID; try { instanceID = ((Object)pm).GetInstanceID(); } catch { return; } string[] array = new string[2] { "followPlayer", "_isNavAgentStopped" }; foreach (string text in array) { string key = instanceID + ":" + text; if (FlagHolds.TryGetValue(key, out var value)) { value.Until = 0f; } } string key2 = instanceID + ":liteloco.weight"; if (FloatHolds.TryGetValue(key2, out var value2)) { value2.Until = 0f; } } internal static void KnockDown(PuppetMaster pm, SubBehaviourHealth health, float seconds) { Dip(pm, health, 0f, seconds); } internal static void HoldLimp(PuppetMaster pm, SubBehaviourHealth health, float weight, float seconds) { Dip(pm, health, weight, seconds); } internal static void ReleaseNow(PuppetMaster pm) { int instanceID; try { instanceID = ((Object)pm).GetInstanceID(); } catch { return; } if (Reactions.TryGetValue(instanceID, out var value)) { try { pm.muscleWeight = value.Original; } catch { } Reactions.Remove(instanceID); } if (MapHolds.TryGetValue(instanceID, out var value2)) { try { pm.mappingWeight = value2.Original; } catch { } MapHolds.Remove(instanceID); } } internal static void Diag(PuppetMaster pm) { if ((Object)(object)pm == (Object)null || _diagCount >= 8) { return; } _diagCount++; try { MelonLogger.Msg($"Diag #{_diagCount}: muscleWeight={pm.muscleWeight:F2} mappingWeight={pm.mappingWeight:F2} spring={pm.muscleSpring:F2} damper={pm.muscleDamper:F2}"); foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours) { if ((Object)(object)item == (Object)null) { continue; } string className; object o = Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out className) ?? item; List<string> list = new List<string>(); string[] array = new string[9] { "followPlayer", "_isNavAgentStopped", "engagedMode", "locoState", "mentalState", "useAiLocoController", "aggression", "_unbalancedTimer", "_dyingTime" }; foreach (string text in array) { if (Reflect.TryGetObj(o, text, out var value)) { list.Add($"{text}={value}"); } } MelonLogger.Msg($"Diag #{_diagCount} [{className}]: {string.Join(", ", list)}"); if (_diagCount != 1) { continue; } array = new string[2] { "aiLocoController", "_liteLoco" }; foreach (string text2 in array) { try { if (!Reflect.TryGetObj(o, text2, out var value2)) { goto IL_0281; } Il2CppObjectBase val = (Il2CppObjectBase)((value2 is Il2CppObjectBase) ? value2 : null); if (val == null || val == null) { goto IL_0281; } Reflect.LogMembers(Reflect.ResolveRuntimeType(val, out var className2) ?? value2, "Loco [" + className2 + "]", includeBases: false); goto end_IL_023b; IL_0281: MelonLogger.Msg("Loco [" + text2 + "]: null/unreadable"); end_IL_023b:; } catch (Exception ex) { MelonLogger.Msg("Loco [" + text2 + "]: " + ex.Message); } } } try { Muscle val2 = ((Il2CppArrayBase<Muscle>)(object)pm.muscles)[1]; if (val2 != null && val2.props != null) { Reflect.LogMembers(val2.props, "MuscleProps members", includeBases: false); } int[] array2 = new int[2] { 1, 4 }; foreach (int num in array2) { Muscle val3 = ((Il2CppArrayBase<Muscle>)(object)pm.muscles)[num]; if (val3 == null || val3.props == null) { continue; } List<string> list2 = new List<string>(); string[] array = new string[4] { "muscleWeight", "pinWeight", "mappingWeight", "muscleDamper" }; foreach (string text3 in array) { if (Reflect.TryGetObj(val3.props, text3, out var value3)) { list2.Add($"{text3}={value3}"); } } MelonLogger.Msg($"Diag #{_diagCount} muscle[{num}]: {string.Join(", ", list2)}"); } } catch (Exception ex2) { MelonLogger.Msg($"Diag #{_diagCount} muscles: unreadable ({ex2.Message})"); } } catch (Exception ex3) { MelonLogger.Warning("Diag failed: " + ex3.Message); } } private static void Dip(PuppetMaster pm, SubBehaviourHealth health, float weight, float hold) { int instanceID = ((Object)pm).GetInstanceID(); float time = Time.time; if (Reactions.TryGetValue(instanceID, out var value)) { bool flag = time < value.HoldUntil; if (!flag || !(weight > value.Weight)) { value.Weight = weight; value.HoldUntil = (flag ? Mathf.Max(value.HoldUntil, time + hold) : (time + hold)); } return; } value = new Reaction { Original = ((pm.muscleWeight > 0.01f) ? pm.muscleWeight : 1f), Weight = weight, HoldUntil = time + hold, Health = health, Held = ((health != null) ? new float[StunFields.Length] : null) }; if (health != null) { ReadStun(health, value.Held); } Reactions[instanceID] = value; MelonCoroutines.Start(ReactionRoutine(pm, instanceID, value)); } private static IEnumerator ReactionRoutine(PuppetMaster pm, int id, Reaction r) { float current = pm.muscleWeight; while ((Object)(object)pm != (Object)null) { if (!pm.isAlive || pm.isKilling) { try { pm.muscleWeight = r.Original; } catch { } Reactions.Remove(id); yield break; } if (Time.time < r.HoldUntil) { current = Mathf.MoveTowards(current, r.Weight, 20f * Time.deltaTime); if (r.Health != null) { HoldStun(r); } } else { if (r.Health != null) { ReadStun(r.Health, r.Held); } float num = r.Original / Mathf.Max(0.05f, RecoverSeconds.Value); current = Mathf.MoveTowards(current, r.Original, num * Time.deltaTime); if (Mathf.Approximately(current, r.Original)) { break; } } pm.muscleWeight = current; HoldMapping(pm, 0.15f); yield return null; } if ((Object)(object)pm != (Object)null && pm.isAlive) { pm.muscleWeight = r.Original; } Reactions.Remove(id); } private static void ReadStun(SubBehaviourHealth h, float[] into) { for (int i = 0; i < StunFields.Length; i++) { into[i] = (Reflect.TryGet<float>(h, StunFields[i], out var value) ? value : 1f); } } private static void HoldStun(Reaction r) { for (int i = 0; i < StunFields.Length; i++) { if (Reflect.TryGet<float>(r.Health, StunFields[i], out var value)) { float num = Mathf.Min(r.Held[i], value); r.Held[i] = num; if (value > num) { Reflect.TrySet(r.Health, StunFields[i], num); } } } } private static void SlowMo(float seconds, float scale) { if (!(seconds <= 0f) && !(scale >= 1f) && !_slowActive) { MelonCoroutines.Start(SlowRoutine(seconds, scale)); } } private static IEnumerator SlowRoutine(float seconds, float scale) { _slowActive = true; float previous = Time.timeScale; Time.timeScale = scale; float t = 0f; while (t < seconds) { t += Time.unscaledDeltaTime; yield return null; } if (Mathf.Approximately(Time.timeScale, scale)) { Time.timeScale = previous; } _slowActive = false; } private static void DumpStructure(PuppetMaster pm) { try { foreach (BehaviourBase item in (Il2CppArrayBase<BehaviourBase>)(object)pm.behaviours) { if (!((Object)(object)item == (Object)null)) { string className; object obj = Reflect.ResolveRuntimeType((Il2CppObjectBase)(object)item, out className); MelonLogger.Msg($"Behaviour runtime class: {className} (wrapper found: {obj != null})"); if (obj != null) { Reflect.LogMembers(obj, "Behaviour members", includeBases: true); } } } } catch (Exception ex) { MelonLogger.Warning("Structure dump failed: " + ex.Message); } } } internal static class GunHook { internal static string LastGun = "Unknown"; internal static float LastGunTime = -100f; private static readonly HashSet<string> Seen = new HashSet<string>(); private static readonly string[] KnownGuns = new string[4] { "Il2CppSLZ.Marrow.Gun", "Il2CppSLZ.Bonelab.ObjectiveGun", "Il2CppSLZ.Bonelab.GunHeat", "Il2CppSLZ.Bonelab.SpawnGun" }; private static readonly string[] KnownAssemblies = new string[4] { "Il2CppSLZ.Marrow", "Il2CppSLZ.Bonelab", "Assembly-CSharp", "Assembly-CSharp-firstpass" }; private static Type FindGunType(string fullName) { try { string[] knownAssemblies = KnownAssemblies; foreach (string text in knownAssemblies) { Assembly assembly = null; try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly2 in assemblies) { string name; try { name = assembly2.GetName().Name; } catch { continue; } if (name == text) { assembly = assembly2; break; } } } catch { continue; } if (!(assembly == null) && !assembly.IsDynamic) { Type type = null; try { type = assembly.GetType(fullName, throwOnError: false, ignoreCase: false); } catch { } if (type != null) { return type; } } } } catch { } return null; } private static int PatchOnFire(Type t, Harmony harmony, HarmonyMethod post) { MethodInfo[] array = null; try { array = t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } catch { return 0; } int num = 0; MethodInfo[] array2 = array; foreach (MethodInfo methodInfo in array2) { if (methodInfo == null || methodInfo.Name != "OnFire") { continue; } try { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, post, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; try { MelonLogger.Msg("Gun hook: " + t.FullName + ".OnFire"); } catch { } } catch (Exception ex) { MelonLogger.Warning("Gun hook failed on " + t.FullName + ": " + ex.Message); } if (num >= 2) { break; } } return num; } internal static void TryInstall() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown try { int num = 0; Harmony harmony = new Harmony("HitRagdoll.GunHook"); HarmonyMethod val = null; try { val = new HarmonyMethod(typeof(GunHook).GetMethod("Fired", BindingFlags.Static | BindingFlags.NonPublic)); } catch { } if (val != null) { string[] knownGuns = KnownGuns; foreach (string fullName in knownGuns) { Type type = null; try { type = FindGunType(fullName); } catch { } if (!(type == null)) { try { num += PatchOnFire(type, harmony, val); } catch { } if (num >= 6) { break; } } } } if (num == 0) { num = LegacyScan(); } MelonLogger.Msg((num > 0) ? $"Gun hook: {num} OnFire patched" : "Gun hook: no OnFire found, damage bands only"); } catch (Exception ex) { MelonLogger.Warning("Gun hook install failed: " + ex.Message); } } private static int LegacyScan() { //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) int num = 0; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { if (assembly.IsDynamic) { continue; } } catch { continue; } string name; try { name = assembly.GetName().Name; } catch { continue; } if (!name.StartsWith("Il2Cpp") && !(name == "Assembly-CSharp") && !(name == "Assembly-CSharp-firstpass")) { continue; } Type[] types; try { types = assembly.GetTypes(); } catch { continue; } Type[] array = types; foreach (Type type in array) { try { if (type.IsAbstract || type.IsInterface || type.IsEnum || (type.Name ?? "").IndexOf("Gun", StringComparison.OrdinalIgnoreCase) < 0) { continue; } MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "OnFire") { continue; } try { HarmonyMethod val = new HarmonyMethod(typeof(GunHook).GetMethod("Fired", BindingFlags.Static | BindingFlags.NonPublic)); new Harmony("HitRagdoll.GunHook").Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; try { MelonLogger.Msg("Gun hook: " + type.FullName + ".OnFire"); } catch { } } catch (Exception ex) { MelonLogger.Warning("Gun hook failed on " + type.FullName + ": " + ex.Message); } if (num >= 6) { break; } } goto IL_01a3; } catch { goto IL_01a3; } IL_01a3: if (num >= 6) { break; } } if (num >= 6) { break; } } return num; } private static void Fired(object __instance) { try { string text = null; try { if (__instance != null && Reflect.TryGetObj(__instance, "name", out var value) && value != null) { text = value.ToString(); } } catch { } if (string.IsNullOrEmpty(text)) { try { text = __instance?.GetType().Name; } catch { } } if (!string.IsNullOrEmpty(text)) { LastGun = text; LastGunTime = Time.time; if (Seen.Count < 8 && Seen.Add(text)) { MelonLogger.Msg("Gun seen: " + text); } } } catch { } } internal static string Attribute() { try { if (Time.time - LastGunTime < 0.6f) { return LastGun; } } catch { } return "Unknown"; } } [HarmonyPatch(typeof(MuscleCollisionBroadcaster), "ReceiveAttack")] internal static class HitPatch { private static void Postfix(MuscleCollisionBroadcaster __instance, object __0) { try { Main.HandleHit(__instance, __0); } catch (Exception value) { MelonLogger.Error($"RagdollOnHit: {value}"); } } } internal static class Reflect { private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static bool IsEngineNamespace(string ns) { ns = ns ?? ""; if (!ns.StartsWith("System") && !ns.StartsWith("UnityEngine") && !ns.StartsWith("Il2CppSystem")) { return ns.StartsWith("Il2CppInterop"); } return true; } internal static bool TryGetObj(object o, string name, out object value) { value = null; if (o == null) { return false; } try { Type type = o.GetType(); PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanRead && property.GetIndexParameters().Length == 0) { value = property.GetValue(o); return true; } FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { value = field.GetValue(o); return true; } } catch { } return false; } internal static bool TryGet<T>(object o, string name, out T value) { value = default(T); if (o == null) { return false; } try { for (Type type = o.GetType(); type != null && !IsEngineNamespace(type.Namespace); type = type.BaseType) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; object obj = null; bool flag = false; PropertyInfo property = type.GetProperty(name, bindingAttr); if (property != null && property.CanRead && property.GetIndexParameters().Length == 0) { obj = property.GetValue(o); flag = true; } else { FieldInfo field = type.GetField(name, bindingAttr); if (field == null) { continue; } obj = field.GetValue(o); flag = true; } if (flag) { if (obj is T val) { value = val; return true; } if (typeof(T) == typeof(float) && obj is IConvertible convertible) { value = (T)(object)convertible.ToSingle(null); return true; } return false; } } } catch { } return false; } internal static bool TrySet(object o, string name, float value) { return TrySetRaw(o, name, value); } internal static bool TrySetBool(object o, string name, bool value) { return TrySetRaw(o, name, value); } private static bool TrySetRaw(object o, string name, object value) { if (o == null) { return false; } try { Type type = o.GetType(); while (type != null && !IsEngineNamespace(type.Namespace)) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; PropertyInfo property = type.GetProperty(name, bindingAttr); if (property != null && property.CanWrite && property.GetIndexParameters().Length == 0) { property.SetValue(o, Convert.ChangeType(value, property.PropertyType)); return true; } FieldInfo field = type.GetField(name, bindingAttr); if (field != null) { field.SetValue(o, Convert.ChangeType(value, field.FieldType)); return true; } type = type.BaseType; } } catch (Exception ex) { MelonLogger.Warning("Couldn't set " + name + ": " + ex.Message); } return false; } internal static T FindMemberOfType<T>(object o, out string memberName) where T : class { memberName = null; if (o == null) { return null; } Type type = o.GetType(); while (type != null && !IsEngineNamespace(type.Namespace)) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; PropertyInfo[] properties = type.GetProperties(bindingAttr); foreach (PropertyInfo propertyInfo in properties) { if (!typeof(T).IsAssignableFrom(propertyInfo.PropertyType) || !propertyInfo.CanRead || propertyInfo.GetIndexParameters().Length != 0) { continue; } try { if (propertyInfo.GetValue(o) is T result) { memberName = type.Name + "." + propertyInfo.Name; return result; } } catch { } } FieldInfo[] fields = type.GetFields(bindingAttr); foreach (FieldInfo fieldInfo in fields) { if (!typeof(T).IsAssignableFrom(fieldInfo.FieldType)) { continue; } try { if (fieldInfo.GetValue(o) is T result2) { memberName = type.Name + "." + fieldInfo.Name; return result2; } } catch { } } type = type.BaseType; } return null; } internal static void LogMembers(object o, string label, bool includeBases) { Type type = o.GetType(); while (type != null && !IsEngineNamespace(type.Namespace)) { BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; IEnumerable<string> values = (from p in type.GetProperties(bindingAttr) select p.PropertyType.Name + " " + p.Name).Concat(from f in type.GetFields(bindingAttr) select f.FieldType.Name + " " + f.Name); MelonLogger.Msg($"{label} [{type.FullName}]: {string.Join(", ", values)}"); if (includeBases) { type = type.BaseType; continue; } break; } } internal static void LogValues(object o, string label) { if (o == null) { return; } try { List<string> list = new List<string>(); PropertyInfo[] properties = o.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { Type propertyType = propertyInfo.PropertyType; if ((propertyType.IsPrimitive || propertyType.IsEnum || propertyType == typeof(string)) && propertyInfo.CanRead && propertyInfo.GetIndexParameters().Length == 0) { try { list.Add($"{propertyInfo.Name}={propertyInfo.GetValue(o)}"); } catch { } } } MelonLogger.Msg(label + ": " + string.Join(", ", list)); } catch (Exception ex) { MelonLogger.Warning(label + ": dump failed (" + ex.Message + ")"); } } internal static object ResolveRuntimeType(Il2CppObjectBase obj, out string className) { className = "?"; try { IntPtr intPtr = IL2CPP.il2cpp_object_get_class(obj.Pointer); string text = Marshal.PtrToStringAnsi(IL2CPP.il2cpp_class_get_name(intPtr)); string text2 = Marshal.PtrToStringAnsi(IL2CPP.il2cpp_class_get_namespace(intPtr)); className = (string.IsNullOrEmpty(text2) ? text : (text2 + "." + text)); Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { type = assemblies[i].GetType("Il2Cpp" + className); if (type != null) { break; } } if (type == null) { return null; } return typeof(Il2CppObjectBase).GetMethod("TryCast").MakeGenericMethod(type).Invoke(obj, null); } catch (Exception ex) { MelonLogger.Warning("ResolveRuntimeType failed: " + ex.Message); return null; } } } }