using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using AudioImportLib; using BoneLib; using BoneLib.BoneMenu; using DeadPiece; using DeadPiece.Networking; using DeadPiece.Networking.Messages; using HarmonyLib; using Il2CppCysharp.Threading.Tasks; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Marrow; using Il2CppSLZ.Marrow.Combat; using Il2CppSLZ.Marrow.Data; using Il2CppSLZ.Marrow.Pool; using Il2CppSLZ.Marrow.Warehouse; using Il2CppSLZ.VRMK; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using LabFusion.Entities; using LabFusion.Network; using LabFusion.Network.Serialization; using LabFusion.Player; using LabFusion.Representation; using LabFusion.SDK.Modules; using LabFusion.Utilities; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: MelonColor(255, 139, 0, 0)] [assembly: MelonInfo(typeof(DeadPieceMod), "DeadPiece", "0.4.1", "VoidIndustries", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: MelonPlatform(/*Could not decode attribute arguments.*/)] [assembly: AssemblyVersion("0.0.0.0")] [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 DeadPiece { public static class AvatarHealthResolver { public const float MinVitalityHealth = 25f; public const float MaxVitalityHealth = 200f; public const float MaxSanityHealth = 500f; public const float DefaultUnsetHealth = 100f; public static float Resolve(RigManager rm, float fallbackHp) { if ((Object)(object)rm == (Object)null) { return Mathf.Max(1f, fallbackHp); } float num = Mathf.Max(1f, fallbackHp); float num2 = ReadMarrowHealth(rm.health); float num3 = ReadVitalityHealth(rm.avatar); if (num2 > 0f) { if (num3 > 0f && LooksLikeStaleDefaultHealth(num2, num3)) { return ClampHealth(num3, num); } return ClampHealth(num2, num); } if (num3 > 0f) { return ClampHealth(num3, num); } return num; } public static float ReadVitalityHealth(Avatar avatar) { if ((Object)(object)avatar == (Object)null) { return -1f; } float vitality = avatar.vitality; if (vitality <= 0f || float.IsNaN(vitality) || float.IsInfinity(vitality)) { return -1f; } if (vitality > 2f) { return ClampHealth(vitality, 200f); } return Mathf.Lerp(25f, 200f, Mathf.Clamp01(vitality)); } private static float ReadMarrowHealth(Health health) { if ((Object)(object)health == (Object)null) { return -1f; } float max_Health = health.max_Health; if (max_Health <= 0f || float.IsNaN(max_Health) || float.IsInfinity(max_Health)) { return -1f; } return max_Health; } private static bool LooksLikeStaleDefaultHealth(float marrowHp, float vitalityHp) { if (Mathf.Abs(marrowHp - 100f) > 0.5f) { return false; } return Mathf.Abs(vitalityHp - marrowHp) > 12f; } private static float ClampHealth(float hp, float fallback) { if (hp <= 0f || float.IsNaN(hp) || float.IsInfinity(hp)) { return fallback; } if (hp > 500f) { hp = 500f; } return Mathf.Max(1f, hp); } } [HarmonyPatch(typeof(BaseController), "GetThumbStickAxis")] internal static class RightStickPatch { private static void Postfix(BaseController __instance, ref Vector2 __result) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 if (!((Object)(object)__instance == (Object)null) && (int)__instance.handedness == 2) { RigManager rigManager = Player.RigManager; if (!((Object)(object)rigManager == (Object)null) && DeadPieceMod.Instance != null && DeadPieceMod.Instance.ShouldApplyLocalNoLegEffects(rigManager) && !DeadPieceMod.Instance.IsAutoInjectorUseActiveOrRecent() && !DeadPieceMod.Instance.IsCrouchForcingSuppressed()) { __result.y = 0f; } } } } [HarmonyPatch(typeof(RemapRig), "CrouchHold")] internal static class CrouchHoldPostfixPatch { private static void Postfix(RemapRig __instance) { RigManager rigManager = Player.RigManager; if (!((Object)(object)rigManager == (Object)null) && DeadPieceMod.Instance != null && !((Object)(object)rigManager.remapHeptaRig != (Object)(object)__instance) && DeadPieceMod.Instance.ShouldApplyLocalNoLegEffects(rigManager) && !DeadPieceMod.Instance.IsAutoInjectorUseActiveOrRecent() && !DeadPieceMod.Instance.IsCrouchForcingSuppressed() && !DeadPieceMod.Instance.IsHoldingNimbusGun(rigManager)) { __instance._spineCrouchOff = 0.8f; __instance._crouchTarget = 0.8f; __instance.vertState = (VertState)3; } } } [HarmonyPatch(typeof(RemapRig), "OnAfterFixedUpdate")] internal static class ForceCrouchHeight { private const float TARGET_CROUCH = 0.8f; private const float LERP_SPEED = 8f; private static void Postfix(RemapRig __instance) { RigManager rigManager = Player.RigManager; if (!((Object)(object)rigManager == (Object)null) && DeadPieceMod.Instance != null && !((Object)(object)rigManager.remapHeptaRig != (Object)(object)__instance) && DeadPieceMod.Instance.ShouldApplyLocalNoLegEffects(rigManager) && !DeadPieceMod.Instance.IsAutoInjectorUseActiveOrRecent() && !DeadPieceMod.Instance.IsCrouchForcingSuppressed() && !DeadPieceMod.Instance.IsHoldingNimbusGun(rigManager)) { float num = Time.deltaTime * 8f; __instance._spineCrouchOff = Mathf.Lerp(__instance._spineCrouchOff, 0.8f, num); __instance._crouchTarget = Mathf.Lerp(__instance._crouchTarget, 0.8f, num); __instance.vertState = (VertState)3; } } } [HarmonyPatch(typeof(PlayerDamageReceiver), "ReceiveAttack")] [HarmonyPriority(800)] public static class DamageInterceptor { internal static void Prefix(PlayerDamageReceiver __instance, ref Attack attack, out bool __state) { __state = false; try { __state = DeadPieceMod.Instance != null && DeadPieceMod.Instance.TryConsumeNonFatalAttack(__instance, attack); if (__state) { attack.damage = 0.1f; } } catch (Exception ex) { MelonLogger.Error("[DeadPiece] Damage prefix failed: " + ex); } } internal static void Postfix(PlayerDamageReceiver __instance, Attack attack, bool __state) { if (__state) { return; } try { Health health = __instance.health; RigManager val = ((health != null) ? health._rigManager : null); bool flag = (Object)(object)val != (Object)null && DeadPieceMod.Instance != null && DeadPieceMod.Instance.IsBothLegsGone(val); DeadPieceMod.Instance?.OnAttackReceived(__instance, attack); bool flag2 = (Object)(object)val != (Object)null && DeadPieceMod.Instance != null && DeadPieceMod.Instance.IsBothLegsGone(val); if (!flag && flag2) { DeadPieceMod.Instance?.SyncLegState(val, 3); } } catch (Exception ex) { MelonLogger.Error("[DeadPiece] Damage postfix failed: " + ex); } } } public class DamageVolume : MonoBehaviour { private float _damagePerSecond; private float _lifetime; private float _spawnTime; private float _nextTickTime; private bool _initialized; public void Initialize(float damagePerSecond, float lifetime) { _damagePerSecond = damagePerSecond; _lifetime = lifetime; _spawnTime = Time.time; _nextTickTime = 0f; _initialized = true; } private void Update() { if (_initialized && Time.time - _spawnTime >= _lifetime) { Object.Destroy((Object)(object)((Component)this).gameObject); } } private void OnTriggerStay(Collider other) { if (!_initialized || (Object)(object)other == (Object)null || _damagePerSecond <= 0f || Time.time < _nextTickTime) { return; } _nextTickTime = Time.time + 0.25f; try { float num = _damagePerSecond * 0.25f; if (num <= 0f) { return; } Transform val = ((Component)other).transform; for (int i = 0; i < 6; i++) { if (!((Object)(object)val != (Object)null)) { break; } RigManager component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.health != (Object)null && component.health.curr_Health > 0f) { component.health.Death(); break; } val = val.parent; } } catch { } } } public class DeadPieceMod : MelonMod { private struct PendingNetworkState { public ushort Sequence; public uint GoneBoneMask; public bool IsFallen; } [Flags] private enum LimbGoneMask : byte { None = 0, LeftArm = 1, RightArm = 2, LeftLeg = 4, RightLeg = 8, Spine = 0x10, Hips = 0x20 } private sealed class RigRuntimeCache { public int AvatarHash; public bool Initialized; public bool LimbDamageBlocked; public int LimbDamageBlockFrame; public bool HasMissingLimbs; public LimbGoneMask LimbGoneFlags; public Transform[] BoneTransforms; public VisualDamageController VisualDamage; } public static MelonPreferences_Category Category; public static MelonPreferences_Entry MaxLimbHealth; public static MelonPreferences_Entry DamageMultiplier; public static MelonPreferences_Entry EnableSoundEffects; public static MelonPreferences_Entry EnableDualStickDeathReset; public static MelonPreferences_Entry SeveredLimbBleedDamagePerSecond; public static MelonPreferences_Entry EnableVrEyeBlindness; public static MelonPreferences_Entry EnableHeadSever; public static MelonPreferences_Entry EnableVisualCuts; public static MelonPreferences_Entry EnableVisualHitMarks; public static MelonPreferences_Entry EnableAttackTypeBalancing; public static MelonPreferences_Entry PiercingDamageMultiplier; public static MelonPreferences_Entry BluntDamageMultiplier; public static MelonPreferences_Entry SlashDamageMultiplier; public static MelonPreferences_Entry StabDamageMultiplier; public static MelonPreferences_Entry FireDamageMultiplier; public static MelonPreferences_Entry SharpSeverChance; public static MelonPreferences_Entry ExplosionDamageThreshold; public static MelonPreferences_Entry ExplosionRadius; public static MelonPreferences_Entry EnableBlastLimbDamage; public static MelonPreferences_Entry EnableExplosiveHarmonyHooks; public static MelonPreferences_Entry EnableImpactBlood; public static MelonPreferences_Entry EnableBloodEffects; public static MelonPreferences_Entry EnableGameBloodEffects; public static MelonPreferences_Entry EnableFallbackBloodEffects; public static MelonPreferences_Entry BloodColorOverride; public static MelonPreferences_Entry EnableMovementPenalty; public static MelonPreferences_Entry EnableSecondLegRagdoll; public static DeadPieceMod Instance; private DataCardReference _fleshSurfaceCard; private bool _fleshCardFound; private readonly List _gameBloodSpawnableBarcodes = new List(); private bool _bloodSpawnablesScanned; private ParticleSystem _gameBloodParticlePrefab; private float _lastGameBloodParticleSearchTime = -999f; private bool _loggedMissingGameBloodParticles; private bool _loggedVanillaBloodSpawnable; private bool _loggedVanillaBloodSpawnableFailure; private Spawnable _smallBloodSplatterSpawnable; private Spawnable _largeBloodSplatterSpawnable; private Spawnable _bloodBagBlasterSpawnable; private bool _vanillaBloodSpawnablesRegistered; public ParticleSystem BloodPrefab; private bool _limitsSaved; private const float DefaultLocomotionMaxVelocity = 4.5f; private float _savedLocomotionMaxVelocity = 4.5f; private float _savedLocomotionCurrentMaxVelocity = 4.5f; private bool _savedLocomotionJumpEnabled = true; private bool _locomotionStateSaved; private bool _deadpieceNoLegUsageApplied; private bool _deadpieceJumpBlocked; private bool _deadpieceFallenStateApplied; private float _suppressNoLegRagdollUntil = -999f; private float _suppressCrouchForcingUntil = -999f; private float _lastLocalRespawnTime = -999f; private float _lastLocalBothLegsSeveredTime = -999f; private Harmony _harmony = new Harmony("com.deadpiece.patches"); private const string MetadataKey = "DeadPieceLimbs"; private const float FusionStateResyncInterval = 5f; private const float StumpBloodEffectInterval = 0.45f; private const float StumpBloodVisualDamage = 3f; private const float VanillaBloodLifetimeSeconds = 10f; private const float AutoInjectorUseWindowSeconds = 0.8f; private const string Explosive_SmallBigDamage = "BaBaCorp.MiscExplosiveDevices.Spawnable.ExplosionSmallBigDamage"; private const string Explosive_MicroNuke = "BaBaCorp.MiscExplosiveDevices.Spawnable.MicroNukeGrenade"; private const string Explosive_TimedNuke = "BaBaCorp.MiscExplosiveDevices.Spawnable.TimedNuke"; private const string Explosive_Dynamite = "BaBaCorp.MiscExplosiveDevices.Spawnable.Dynamite"; private const string Explosive_C4 = "BaBaCorp.MiscExplosiveDevices.Spawnable.CelebratoryC4"; private const string Explosive_Grenade = "BaBaCorp.MiscExplosiveDevices.Spawnable.FragmentationGrenade"; private const string Explosive_TimedC4 = "BaBaCorp.MiscExplosiveDevices.Spawnable.TimedC4"; private const string Explosive_ProxMine = "BaBaCorp.MiscExplosiveDevices.Spawnable.ProxMine"; private const string Explosive_GiftMine = "BaBaCorp.MiscExplosiveDevices.Spawnable.GiftMine"; private const string Explosive_FragGrenade = "BaBaCorp.MiscExplosiveDevices.Spawnable.FragmentationGrenade"; private const string Explosive_GasGrenade = "BaBaCorp.MiscExplosiveDevices.Spawnable.GasGrenade"; private const string Explosive_SmokeGrenade = "BaBaCorp.MiscExplosiveDevices.Spawnable.SmokeGrenade"; private const string Explosive_Flare = "BaBaCorp.MiscExplosiveDevices.Spawnable.Flare"; private const string Explosive_PropaneTank = "BaBaCorp.MiscExplosiveDevices.Spawnable.PropaneTank"; private const string Explosive_FuelTank = "BaBaCorp.MiscExplosiveDevices.Spawnable.FuelTank"; private const string Explosive_Missile = "BaBaCorp.MiscExplosiveDevices.Spawnable.Missile"; private const string Explosive_MiniMissile = "BaBaCorp.MiscExplosiveDevices.Spawnable.MiniMissile"; private const string Explosive_DivinationGrenade = "BaBaCorp.MiscExplosiveDevices.Spawnable.DivinationGrenade"; private const string Explosive_VoidTunneling = "BaBaCorp.MiscExplosiveDevices.Spawnable.KCB4VoidTunnelingDevice"; private const string Explosive_IncendiaryGrenade = "BaBaCorp.MiscExplosiveDevices.Spawnable.IncendiaryGrenade"; private const string Explosive_FireworkPurple = "BaBaCorp.MiscExplosiveDevices.Spawnable.PurpleFireworkRocket"; private const string Explosive_FireworkGreen = "BaBaCorp.MiscExplosiveDevices.Spawnable.GreenFireworkRocket"; private const string Explosive_FireworkBlue = "BaBaCorp.MiscExplosiveDevices.Spawnable.BlueFireworkRocket"; private const string Explosive_FireworkRed = "BaBaCorp.MiscExplosiveDevices.Spawnable.RedFireworkRocket"; private const string Explosive_Lighter = "BaBaCorp.MiscExplosiveDevices.Spawnable.Lighter"; private const string Explosive_M72Law = "BaBaCorp.MiscExplosiveDevices.Spawnable.M72LAW"; private const string Explosive_M72LawInf = "BaBaCorp.MiscExplosiveDevices.Spawnable.M72LawINF"; private const string Explosive_Stielhandgranate = "BaBaCorp.MiscExplosiveDevices.Spawnable.Stielhandgranate"; private const string Explosive_SmallRocket = "BaBaCorp.MiscExplosiveDevices.Spawnable.SmallRocket"; private const string Explosive_Jarate = "BaBaCorp.MiscExplosiveDevices.Spawnable.Jarate"; private const string Explosive_JoyousGreenGrenade = "BaBaCorp.MiscExplosiveDevices.Spawnable.JoyousGreenGrenade"; private const string Explosive_BatteryAcidGlass = "BaBaCorp.MiscExplosiveDevices.Spawnable.BatteryAcidGlass"; private const string Explosive_CrateWithLid = "BaBaCorp.MiscExplosiveDevices.Spawnable.CrateWithLid"; private const string Explosive_RemoteIED = "BaBaCorp.MiscExplosiveDevices.Spawnable.RemoteIED"; private const string Explosive_ClassicBomb = "BaBaCorp.MiscExplosiveDevices.Spawnable.ClassicBomb"; private const string Explosive_Frank = "BaBaCorp.MiscExplosiveDevices.Spawnable.Frank"; private const string Explosive_BirthdayCake = "BaBaCorp.MiscExplosiveDevices.Spawnable.BirthdayCake"; private const string Explosive_IncinMissile = "BaBaCorp.MiscExplosiveDevices.Spawnable.IncinMissile"; private const string Explosive_TriggeredExplosive = "BaBaCorp.MiscExplosiveDevices.Spawnable.TriggeredExplosive"; private const string Explosive_TimedExplosive6s = "BaBaCorp.MiscExplosiveDevices.Spawnable.TimedExplosive6sec"; private const string Explosive_ImpactExplosive = "BaBaCorp.MiscExplosiveDevices.Spawnable.ImpactExplosive"; private const string Explosive_Pliers = "BaBaCorp.MiscExplosiveDevices.Spawnable.Pliers"; private readonly Dictionary> _playersHealth = new Dictionary>(); private readonly Dictionary> _colliderBoneMap = new Dictionary>(); private readonly Dictionary> _colliderBoneDistanceMap = new Dictionary>(); private readonly Dictionary> _originalScales = new Dictionary>(); private readonly Dictionary> _lastHitEffectTimes = new Dictionary>(); private readonly Dictionary> _lastStumpBloodEffectTimes = new Dictionary>(); private readonly Dictionary> _stumpBloodStartTimes = new Dictionary>(); private readonly Dictionary _pendingNetworkStates = new Dictionary(); private readonly Dictionary _appliedStateMasks = new Dictionary(); private readonly HashSet _remoteFallenPlayers = new HashSet(); private bool _lastLeftArmUsable = true; private bool _lastRightArmUsable = true; private readonly Dictionary _lastAppliedNetworkSequence = new Dictionary(); private ushort _localStateSequence; private uint _lastSentStateMask = uint.MaxValue; private float _lastStateSyncTime = -999f; private float _lastRadialBlastDedupeTime = -999f; private Vector3 _lastRadialBlastDedupeOrigin; private readonly List _dismemberSounds = new List(); public AudioClip DismemberSound; private string _soundFolder; private readonly Dictionary _lastAvatarHashes = new Dictionary(); private readonly Dictionary _avatarBloodOverrides = new Dictionary(); private readonly Dictionary _bloodColorOverrides = new Dictionary(); private readonly Dictionary _bloodColorIndexOverrides = new Dictionary(); private string _lastBroadcastedBloodColor = "Auto"; private bool _boneMenuCreated; public static readonly HumanBodyBones[] DamageBones; private static readonly HashSet FatalBones; private static readonly HashSet TorsoBones; private static readonly HashSet CoreNearestExcludeBones; private const float NearestBoneMaxDistance = 0.75f; private const float NearestBoneTorsoBias = 0.35f; private const float TorsoBoneMaxHitDistance = 0.4f; private const float MaxColliderBoneWorldDistance = 0.55f; private const float MaxColliderHierarchyDepth = 5f; private const float InvincibleHealthThreshold = 9999f; private const int LimbDamageBlockRecheckFrames = 30; private const float SlowUpdateInterval = 0.5f; private const float AvatarSwapCheckInterval = 0.2f; private const float MinLimbHealthFloorAbsolute = 8f; private const float MinLimbHealthFloorRatio = 0.15f; private static readonly HumanBodyBones[] NetworkBones; public static readonly Dictionary BoneToIndexMap; private static readonly string[] GameBloodPositiveKeywords; private static readonly string[] GameBloodNegativeKeywords; private static readonly string[] VanillaBloodSpawnableBarcodes; private const string VanillaBloodBlasterBarcode = "c1534c5a-1ea0-4156-920b-f8a8426c6173"; private const float DualStickResetCooldown = 0.75f; private const float DualStickTapPairMaxGap = 0.25f; private const float DualStickTapWindowDuration = 1.75f; private const int DualStickResetTapCount = 2; private RigManager _cachedRm; private float _lastTrackedBodyHealth = -1f; private float _lastAutoInjectorUseTime = -999f; private float _lastExplosiveUseTime = -999f; private const float ExplosiveUseWindowSeconds = 1.5f; private int _dualStickResetTapCount; private float _dualStickResetTapWindowExpire; private float _lastLeftStickTapTime = -999f; private float _lastRightStickTapTime = -999f; private float _lastDualStickTapRegisteredTime = -999f; private float _lastDualStickResetTime = -999f; private readonly Dictionary _rigWasDead = new Dictionary(); private readonly Dictionary _avatarHealthBaseCache = new Dictionary(); private readonly Dictionary _avatarHealthHashCache = new Dictionary(); private readonly HashSet _trackedRigs = new HashSet(); private float _slowUpdateTimer; private float _avatarSwapTimer; private float _delayedDeathTime; private RigManager _delayedDeathRm; private RigManager _vrEyeCacheRig; private bool _vrEyeCamerasCached; private bool _lastAppliedLeftEyeBlind; private bool _lastAppliedRightEyeBlind; private readonly List _vrLeftEyeCameras = new List(); private readonly List _vrRightEyeCameras = new List(); private readonly Dictionary _vrCameraEnabledBackup = new Dictionary(); private readonly Dictionary _vrEyeBlackoutObjects = new Dictionary(); private int _updateFrame; private bool _localRigInitialized; private bool _startupScheduled; private bool _wasConnected; private readonly HashSet _pendingHealthRefresh = new HashSet(); private readonly Dictionary _rigCache = new Dictionary(); private Mesh _bloodQuadMesh; private bool _pluginCallbacksRegistered; private const float DamageVolumeLifetime = 8f; private const float DamageVolumeRadius = 0.12f; private const float DamageVolumeDps = 2f; private static Dictionary BuildBoneToIndexMap() { Dictionary dictionary = new Dictionary(DamageBones.Length); for (int i = 0; i < DamageBones.Length; i++) { dictionary[DamageBones[i]] = i; } return dictionary; } public override void OnUpdate() { //IL_0214: 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) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) NetworkSync.ProcessMainThreadQueue(); _updateFrame++; RigManager rigManager = Player.RigManager; if ((Object)(object)rigManager == (Object)null) { return; } if ((Object)(object)_cachedRm == (Object)null || (Object)(object)_cachedRm != (Object)(object)rigManager) { RigManager cachedRm = _cachedRm; _cachedRm = rigManager; _localRigInitialized = false; _startupScheduled = false; if ((Object)(object)cachedRm != (Object)null) { MelonLogger.Msg(ConsoleColor.Gray, "Local player RigManager changed, performing respawn cleanup."); RemoveRigFromCaches(cachedRm); SuppressNoLegRagdollForRespawn(); ResetLocalNoLegRagdollPermission(); StabilizeRespawnLocomotion(rigManager); RestoreDeadpieceLegUsage(rigManager); ResetLimbStats(rigManager, restoreBody: true); StabilizeRespawnLocomotion(rigManager); _lastTrackedBodyHealth = -1f; UpdateLimbPenaltyFlag(rigManager); SyncFullState(); NetworkSync.SendRespawn(PlayerIDManager.LocalSmallID); } } if (!_localRigInitialized) { if (!_startupScheduled) { _startupScheduled = true; MelonCoroutines.Start(DeferredStartup(rigManager)); } return; } float deltaTime = Time.deltaTime; _avatarSwapTimer += deltaTime; if (_avatarSwapTimer >= 0.2f) { _avatarSwapTimer = 0f; HandleAvatarSwap(rigManager); } HandleRespawnRestore(rigManager); HandleStickInputs(deltaTime); UpdateAutoInjectorUseWindow(); UpdateExplosiveUseWindow(); ProcessPlayerHealing(rigManager); ProcessSeveredLimbBleed(rigManager, deltaTime); if ((Object)(object)rigManager == (Object)(object)Player.RigManager) { ApplyMovementConstraints(rigManager); EnforceBothLegsGoneState(rigManager); if (IsBothLegsGone(rigManager) && (Object)(object)rigManager.physicsRig != (Object)null) { float num = Mathf.Pow(0.01f, Time.deltaTime); Rigidbody rbKnee = rigManager.physicsRig.rbKnee; Rigidbody rbFeet = rigManager.physicsRig.rbFeet; if ((Object)(object)rbKnee != (Object)null) { rbKnee.velocity *= num; rbKnee.angularVelocity *= num; } if ((Object)(object)rbFeet != (Object)null) { rbFeet.velocity *= num; rbFeet.angularVelocity *= num; } } } _slowUpdateTimer += deltaTime; if (_slowUpdateTimer >= 0.5f) { _slowUpdateTimer = 0f; try { string text = BloodColorOverride?.Value ?? "Auto"; if (text != _lastBroadcastedBloodColor) { _lastBroadcastedBloodColor = text; BroadcastBloodColor(); } } catch { } bool hasServer = NetworkInfo.HasServer; if (hasServer && !_wasConnected) { _wasConnected = true; NetworkSync.RegisterHandlers(); try { SyncFullState(); BroadcastBloodColor(); } catch { } } else if (!hasServer && _wasConnected) { _wasConnected = false; NetworkSync.ResetSessionState(); } if (hasServer) { ResyncLocalStateIfNeeded(); HandleAllRigsRespawnRestore(); if (_pendingNetworkStates.Count > 0) { ApplyPendingNetworkStates(); } } EnforceInvincibleRigsForAllTracked(); ProcessRemoteRigsStumpBlood(deltaTime); PruneTrackedRigs(); if (EnableVrEyeBlindness.Value) { UpdateVrEyeBlindness(rigManager); } } if ((_updateFrame & 7) == 0 && NetworkInfo.HasServer) { EnforceDismemberedBones(); EnforceAppliedStates(); EnforceRemoteFallenState(); } if ((_updateFrame & 3) == 0 && EnableMovementPenalty.Value) { EnforceLocalHandUsability(); } if ((Object)(object)_delayedDeathRm != (Object)null && Time.time >= _delayedDeathTime) { RigManager delayedDeathRm = _delayedDeathRm; _delayedDeathRm = null; if ((Object)(object)delayedDeathRm != (Object)null && (Object)(object)delayedDeathRm.health != (Object)null) { delayedDeathRm.health.Death(); } } } public override void OnLateUpdate() { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00c5: 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) RigManager rigManager = Player.RigManager; if (!((Object)(object)rigManager == (Object)null) && EnableMovementPenalty.Value && IsBothLegsGone(rigManager) && !((Object)(object)rigManager.avatar == (Object)null) && !((Object)(object)rigManager.avatar.animator == (Object)null)) { Transform boneTransform = rigManager.avatar.animator.GetBoneTransform((HumanBodyBones)0); Transform boneTransform2 = rigManager.avatar.animator.GetBoneTransform((HumanBodyBones)10); if ((Object)(object)boneTransform != (Object)null && (Object)(object)boneTransform2 != (Object)null) { Vector3 position = boneTransform2.position; boneTransform.position += Vector3.down * 0.5f; boneTransform2.position = position; } } } private IEnumerator DeferredStartup(RigManager rigManager) { yield return null; if (!_fleshCardFound) { TryCacheFleshSurface(); } if ((Object)(object)rigManager != (Object)null) { EnsureRigInitialized(rigManager); TrackRig(rigManager); } if (NetworkInfo.HasServer) { SyncExistingRemoteMetadata(); ApplyPendingNetworkStates(); } _localRigInitialized = true; SetupBoneMenu(); } private void SetupBoneMenu() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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_011e: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) if (_boneMenuCreated) { return; } _boneMenuCreated = true; try { Page val = Page.Root.CreatePage("Deadpiece", Color.red, 0, true); val.CreateFunction("Red", Color.red, (Action)delegate { SetBloodColor("Red"); }); val.CreateFunction("Green", Color.green, (Action)delegate { SetBloodColor("Green"); }); val.CreateFunction("Blue", Color.blue, (Action)delegate { SetBloodColor("Blue"); }); val.CreateFunction("Yellow", Color.yellow, (Action)delegate { SetBloodColor("Yellow"); }); val.CreateFunction("Black", Color.gray, (Action)delegate { SetBloodColor("Black"); }); val.CreateFunction("White", Color.white, (Action)delegate { SetBloodColor("White"); }); val.CreateFunction("Purple", new Color(0.5f, 0.02f, 0.6f), (Action)delegate { SetBloodColor("Purple"); }); val.CreateFunction("Orange", new Color(1f, 0.5f, 0f), (Action)delegate { SetBloodColor("Orange"); }); val.CreateFunction("Pink", new Color(1f, 0.4f, 0.7f), (Action)delegate { SetBloodColor("Pink"); }); val.CreateFunction("Auto", Color.white, (Action)delegate { SetBloodColor("Auto"); }); MelonLogger.Msg(ConsoleColor.Gray, "BoneMenu registered. Blood Color menu available."); } catch (Exception ex) { MelonLogger.Warning("Failed to setup BoneMenu: " + ex.Message); } } private void SetBloodColor(string color) { BloodColorOverride.Value = color; _lastBroadcastedBloodColor = color; BroadcastBloodColor(); } private void SyncExistingRemoteMetadata() { string value = default(string); RigRefs val = default(RigRefs); foreach (PlayerID playerID in PlayerIDManager.PlayerIDs) { if (playerID != null && !playerID.IsMe) { PlayerMetadata metadata = playerID.Metadata; if (((metadata != null) ? metadata.Metadata : null) != null && playerID.Metadata.Metadata.TryGetMetadata("DeadPieceLimbs", ref value)) { ApplyNetworkState(playerID.SmallID, value); } if (PlayerRepUtilities.TryGetReferences(playerID.SmallID, ref val) && (Object)(object)((val != null) ? val.RigManager : null) != (Object)null) { TrackRig(val.RigManager); } } } } public override void OnInitializeMelon() { //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Expected O, but got Unknown //IL_04ce: Unknown result type (might be due to invalid IL or missing references) //IL_04d8: Expected O, but got Unknown Instance = this; WarnAboutLegacyNetworkPlugin(); InitializeModules(); NetworkSync.Initialize(); _pluginCallbacksRegistered = NetworkSync.RegisterCallbacks(OnPluginLimbHit, OnPluginLimbSever, OnPluginRespawn, OnPluginBloodColor, OnPluginFullState, GetPluginStateMask); try { _harmony.PatchAll(); } catch (Exception ex) { MelonLogger.Warning("Harmony PatchAll failed: " + ex.Message); } Category = MelonPreferences.CreateCategory("DeadPiece", "DeadPiece Settings"); MaxLimbHealth = Category.CreateEntry("MaxLimbHealth", 100f, "Fallback Avatar HP", "Fallback max health when the avatar does not expose player health (limb HP scales from avatar max health)", false, false, (ValueValidator)null, (string)null); DamageMultiplier = Category.CreateEntry("DamageMultiplier", 1f, "Damage Multiplier", "Multiplier for damage dealt to limbs", false, false, (ValueValidator)null, (string)null); EnableImpactBlood = Category.CreateEntry("EnableImpactBlood", true, "Severed Limb Bleed", "Tiny damage ticks at severed bone tips (vanilla impact blood)", false, false, (ValueValidator)null, (string)null); EnableBloodEffects = Category.CreateEntry("EnableBloodEffects", true, "Blood Effects", "Enable blood particle effects on dismemberment", false, false, (ValueValidator)null, (string)null); EnableGameBloodEffects = Category.CreateEntry("EnableGameBloodEffects", true, "Game Blood", "Clone already-loaded BONELAB blood VFX instead of shipping custom particles", false, false, (ValueValidator)null, (string)null); EnableFallbackBloodEffects = Category.CreateEntry("EnableProceduralFallbackBlood", true, "Procedural Fallback", "Always keep a lightweight procedural blood fallback when native BONELAB blood VFX cannot be spawned", false, false, (ValueValidator)null, (string)null); BloodColorOverride = Category.CreateEntry("BloodColorOverride", "Auto", "Blood Color Override", "Force a specific blood color for all avatars (Auto = use per-avatar rules)", false, false, (ValueValidator)null, (string)null); EnableMovementPenalty = Category.CreateEntry("EnableMovementPenalty", true, "Movement Penalty", "Apply movement restrictions and body lowering when legs are lost", false, false, (ValueValidator)null, (string)null); EnableSecondLegRagdoll = Category.CreateEntry("EnableSecondLegRagdoll", false, "Second Leg Ragdoll", "Deprecated; DeadPiece no longer changes player leg physics", false, false, (ValueValidator)null, (string)null); SeveredLimbBleedDamagePerSecond = Category.CreateEntry("SeveredLimbBleedDamagePerSecond", 0.01f, "Bleed DPS", "Damage per second at each severed limb tip", false, false, (ValueValidator)null, (string)null); EnableDualStickDeathReset = Category.CreateEntry("EnableDualStickDeathReset", true, "Dual Stick Death Reset", "Double-tap both thumbsticks to die and respawn (full reset)", false, false, (ValueValidator)null, (string)null); EnableSoundEffects = Category.CreateEntry("EnableSoundEffects", true, "Sound Effects", "Enable sound effects on dismemberment", false, false, (ValueValidator)null, (string)null); EnableVrEyeBlindness = Category.CreateEntry("EnableVrEyeBlindness", true, "VR Eye Blindness", "When an eye is destroyed, blackout that eye in the VR headset (local player only)", false, false, (ValueValidator)null, (string)null); EnableHeadSever = Category.CreateEntry("EnableHeadSever", true, "Head Sever", "Make lethal head damage use stronger decapitation effects", false, false, (ValueValidator)null, (string)null); EnableVisualCuts = Category.CreateEntry("EnableAvatarCutMasks", false, "Visual Cuts", "Experimental Marrow cut masks; keep off if the avatar shows square artifacts", false, false, (ValueValidator)null, (string)null); EnableVisualHitMarks = Category.CreateEntry("EnableVisualHitMarks", true, "Visual Hit Marks", "Try to use Marrow's visual damage hit system on normal limb damage", false, false, (ValueValidator)null, (string)null); EnableAttackTypeBalancing = Category.CreateEntry("EnableAttackTypeBalancing", true, "Attack Type Balancing", "Use different limb damage rules for piercing, blunt, sharp, fire, and explosion-like attacks", false, false, (ValueValidator)null, (string)null); PiercingDamageMultiplier = Category.CreateEntry("PiercingDamageMultiplier", 1.35f, "Piercing Damage", "Limb damage multiplier for piercing attacks", false, false, (ValueValidator)null, (string)null); BluntDamageMultiplier = Category.CreateEntry("BluntDamageMultiplier", 0.65f, "Blunt Damage", "Limb damage multiplier for blunt attacks", false, false, (ValueValidator)null, (string)null); SlashDamageMultiplier = Category.CreateEntry("SlashDamageMultiplier", 1.55f, "Slash Damage", "Limb damage multiplier for slicing attacks", false, false, (ValueValidator)null, (string)null); StabDamageMultiplier = Category.CreateEntry("StabDamageMultiplier", 1.75f, "Stab Damage", "Limb damage multiplier for stabbing attacks", false, false, (ValueValidator)null, (string)null); FireDamageMultiplier = Category.CreateEntry("FireDamageMultiplier", 0.25f, "Fire Damage", "Limb damage multiplier for fire attacks", false, false, (ValueValidator)null, (string)null); SharpSeverChance = Category.CreateEntry("SharpSeverChance", 0.35f, "Sharp Sever Chance", "Chance for slicing or stabbing attacks to instantly sever a damaged limb", false, false, (ValueValidator)null, (string)null); ExplosionDamageThreshold = Category.CreateEntry("ExplosionDamageThreshold", 35f, "Explosion Threshold", "Minimum raw damage for grenade/mine/blast attacks to count as radial limb damage", false, false, (ValueValidator)null, (string)null); ExplosionRadius = Category.CreateEntry("ExplosionRadius", 2.25f, "Explosion Radius", "Default blast radius for limb damage when the weapon does not provide one", false, false, (ValueValidator)null, (string)null); EnableBlastLimbDamage = Category.CreateEntry("EnableBlastLimbDamage", true, "Grenade & Mine Limbs", "Radial limb damage from grenades, mines, and other explosions", false, false, (ValueValidator)null, (string)null); EnableExplosiveHarmonyHooks = Category.CreateEntry("EnableExplosiveHarmonyHooks", true, "Explosive Hooks", "Patch grenade (RigidbodyProjectile) and blast (SimpleExplosionForce) detonations", false, false, (ValueValidator)null, (string)null); if (EnableExplosiveHarmonyHooks.Value) { ExplosivePatches.TryRegister(_harmony); } FusionRigLoadingFix.TryRegister(_harmony); MultiplayerHooking.OnPlayerJoined += new PlayerUpdate(OnPlayerJoined); MultiplayerHooking.OnPlayerLeft += new PlayerUpdate(OnPlayerLeft); PlayerID.OnMetadataChangedEvent += OnMetadataChanged; NetworkPlayer.OnNetworkRigCreated += OnNetworkRigCreated; PropertyInfo property = typeof(MelonUtils).GetProperty("UserDataDirectory", BindingFlags.Static | BindingFlags.Public); _soundFolder = Path.Combine((string)property.GetValue(null), "DeadPiece", "Sounds"); try { if (!Directory.Exists(_soundFolder)) { Directory.CreateDirectory(_soundFolder); } } catch (Exception ex2) { MelonLogger.Warning("Sound folder setup failed: " + ex2.Message); } LoadBloodColorOverrides(); } private static void WarnAboutLegacyNetworkPlugin() { try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { string text = assemblies[i]?.GetName()?.Name ?? string.Empty; if (text.Equals("DeadPiecePlugin", StringComparison.OrdinalIgnoreCase)) { MelonLogger.Error("[DeadPiece] Legacy Plugins/DeadPiecePlugin.dll is loaded. Remove it from every client; it conflicts with the integrated Fusion transport and can break joins."); break; } } } catch (Exception ex) { MelonLogger.Warning("[DeadPiece] Could not check for the legacy network plugin: " + ex.Message); } } public override void OnLateInitializeMelon() { if (!NetworkSync.RegisterHandlers()) { MelonLogger.Error("[DeadPiece] Fusion network handlers are unavailable; multiplayer sync is disabled."); } } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { _playersHealth.Clear(); _colliderBoneMap.Clear(); _colliderBoneDistanceMap.Clear(); _originalScales.Clear(); _lastHitEffectTimes.Clear(); _lastStumpBloodEffectTimes.Clear(); _stumpBloodStartTimes.Clear(); _lastAvatarHashes.Clear(); _avatarHealthBaseCache.Clear(); _avatarHealthHashCache.Clear(); _trackedRigs.Clear(); _rigCache.Clear(); _localRigInitialized = false; _lastTrackedBodyHealth = -1f; _lastAutoInjectorUseTime = -999f; _startupScheduled = false; _pendingHealthRefresh.Clear(); _cachedRm = null; _rigWasDead.Clear(); _pendingNetworkStates.Clear(); _lastAppliedNetworkSequence.Clear(); _remoteFallenPlayers.Clear(); _lastLeftArmUsable = true; _lastRightArmUsable = true; _localStateSequence = 0; _lastSentStateMask = uint.MaxValue; _lastStateSyncTime = -999f; _dualStickResetTapCount = 0; _fleshCardFound = false; _gameBloodParticlePrefab = null; _lastGameBloodParticleSearchTime = -999f; _loggedMissingGameBloodParticles = false; _loggedVanillaBloodSpawnable = false; _loggedVanillaBloodSpawnableFailure = false; _smallBloodSplatterSpawnable = null; _largeBloodSplatterSpawnable = null; _bloodBagBlasterSpawnable = null; _vanillaBloodSpawnablesRegistered = false; _locomotionStateSaved = false; _deadpieceNoLegUsageApplied = false; _deadpieceJumpBlocked = false; _deadpieceFallenStateApplied = false; SuppressNoLegRagdollForRespawn(); ResetLocalNoLegRagdollPermission(); _savedLocomotionMaxVelocity = 4.5f; _savedLocomotionCurrentMaxVelocity = 4.5f; _savedLocomotionJumpEnabled = true; ClearVrEyeCameraCache(); ForceClearNoLegRagdollState(Player.RigManager); ResetLimbStats(Player.RigManager, restoreBody: true); if (_dismemberSounds.Count == 0) { MelonCoroutines.Start(LoadDismemberSounds()); } } private void HandleAvatarSwap(RigManager rm) { if (!((Object)(object)rm == (Object)null) && !((Object)(object)rm.avatar == (Object)null)) { int hashCode = ((Object)rm.avatar).GetHashCode(); if (!_lastAvatarHashes.TryGetValue(rm, out var value) || value != hashCode) { _lastAvatarHashes[rm] = hashCode; OnAvatarSwapped(rm); } } } private void OnAvatarSwapped(RigManager rm) { //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0265: 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_026d: 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_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return; } _colliderBoneMap.Remove(rm); InvalidateAvatarHealthCache(rm); InvalidateRigCache(rm); if ((Object)(object)rm == (Object)(object)Player.RigManager) { _locomotionStateSaved = false; } _colliderBoneDistanceMap.Remove(rm); if (IsRigLimbDamageBlocked(rm)) { ResetLimbStats(rm, restoreBody: true); if ((Object)(object)rm == (Object)(object)Player.RigManager) { UpdateLimbPenaltyFlag(rm); } return; } BuildColliderBoneMap(rm); RebuildBoneCache(rm); if (!_originalScales.ContainsKey(rm)) { _originalScales[rm] = new Dictionary(); } HashSet hashSet = new HashSet(); HumanBodyBones[] damageBones = DamageBones; HumanBodyBones[] array = damageBones; foreach (HumanBodyBones val in array) { Transform cachedBoneTransform = GetCachedBoneTransform(rm, val); if ((Object)(object)cachedBoneTransform == (Object)null) { continue; } if (_playersHealth.TryGetValue(rm, out var value) && value.TryGetValue(val, out var value2) && value2 <= 0f) { hashSet.Add(val); if (cachedBoneTransform.localScale != Vector3.zero) { _originalScales[rm][val] = cachedBoneTransform.localScale; } cachedBoneTransform.localScale = Vector3.zero; } else if (!_originalScales[rm].ContainsKey(val) || _originalScales[rm][val] == Vector3.zero) { _originalScales[rm][val] = ((cachedBoneTransform.localScale == Vector3.zero) ? Vector3.one : cachedBoneTransform.localScale); } } RestoreRigMeshes(rm); ResetLimbStats(rm, restoreBody: false); if (_playersHealth.TryGetValue(rm, out var value3)) { foreach (HumanBodyBones item in hashSet) { value3[item] = 0f - GetMaxHealthForBone(rm, item); } } RefreshLimbMaxHealth(rm); ScheduleDelayedHealthRefresh(rm); if ((Object)(object)rm == (Object)(object)Player.RigManager) { UpdateLimbPenaltyFlag(rm); SetHandUsable(Player.LeftHand, !IsLeftArmGone(rm)); SetHandUsable(Player.RightHand, !IsRightArmGone(rm)); } } public void OnHealthAvatarSet(Health health, Avatar avatar) { RigManager rigFromHealth = GetRigFromHealth(health); if ((Object)(object)rigFromHealth == (Object)null) { return; } TrackRig(rigFromHealth); InvalidateAvatarHealthCache(rigFromHealth); if (IsRigLimbDamageBlocked(rigFromHealth)) { ResetLimbStats(rigFromHealth, restoreBody: true); if ((Object)(object)rigFromHealth == (Object)(object)Player.RigManager) { UpdateLimbPenaltyFlag(rigFromHealth); SetLocalMetadata(""); SyncFullState(); } } else { RefreshLimbMaxHealth(rigFromHealth); } } private RigManager GetRigFromHealth(Health health) { if ((Object)(object)health == (Object)null) { return null; } return ((Component)health).GetComponentInParent(); } private void ScheduleDelayedHealthRefresh(RigManager rm) { if (!((Object)(object)rm == (Object)null) && _pendingHealthRefresh.Add(rm)) { MelonCoroutines.Start(DelayedRefreshLimbHealth(rm)); } } private IEnumerator DelayedRefreshLimbHealth(RigManager rm) { yield return null; yield return null; _pendingHealthRefresh.Remove(rm); if (!((Object)(object)rm == (Object)null)) { InvalidateAvatarHealthCache(rm); if (!IsRigLimbDamageBlocked(rm)) { RefreshLimbMaxHealth(rm); } } } public void EnsureRigInitialized(RigManager rm) { RigRuntimeCache orCreateRigCache = GetOrCreateRigCache(rm); if (orCreateRigCache.Initialized && _playersHealth.ContainsKey(rm) && _colliderBoneMap.ContainsKey(rm)) { TrackRig(rm); return; } if (!_playersHealth.ContainsKey(rm)) { ResetLimbStats(rm, restoreBody: false); } if (!_colliderBoneMap.ContainsKey(rm)) { BuildColliderBoneMap(rm); } RebuildBoneCache(rm); orCreateRigCache.Initialized = true; TrackRig(rm); } private void ResetLimbStats(RigManager rm, bool restoreBody) { //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: 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_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return; } if (restoreBody && TryGetPlayerIdForRig(rm, out var playerId)) { _appliedStateMasks.Remove(playerId); _remoteFallenPlayers.Remove(playerId); if ((Object)(object)rm == (Object)(object)Player.RigManager) { _lastLeftArmUsable = true; _lastRightArmUsable = true; } } if (!_playersHealth.ContainsKey(rm)) { _playersHealth[rm] = new Dictionary(); } if (!_originalScales.ContainsKey(rm)) { _originalScales[rm] = new Dictionary(); } HumanBodyBones[] damageBones = DamageBones; RebuildBoneCache(rm); RigRuntimeCache orCreateRigCache = GetOrCreateRigCache(rm); ResetLimbDamageBlockCache(rm); Transform[] boneTransforms = orCreateRigCache.BoneTransforms; for (int i = 0; i < damageBones.Length; i++) { HumanBodyBones val = damageBones[i]; Transform val2 = ((boneTransforms != null && i < boneTransforms.Length) ? boneTransforms[i] : null); if (!((Object)(object)val2 == (Object)null)) { if (!_originalScales[rm].ContainsKey(val)) { _originalScales[rm][val] = ((val2.localScale == Vector3.zero) ? Vector3.one : val2.localScale); } _playersHealth[rm][val] = GetMaxHealthForBone(rm, val); if (restoreBody) { val2.localScale = (_originalScales[rm].TryGetValue(val, out var value) ? value : Vector3.one); } } } RebuildLimbGoneFlags(rm); if (restoreBody) { ClearStumpBloodState(rm); RestoreRigMeshes(rm); if ((Object)(object)rm == (Object)(object)Player.RigManager) { ClearVrEyeCameraCache(); _lastAppliedLeftEyeBlind = false; _lastAppliedRightEyeBlind = false; UpdateVrEyeBlindness(rm); RestoreLocomotion(); RestoreOriginalLimits(rm); ResetLegRagdoll(rm); RestoreDeadpieceLegUsage(rm); RestoreNoLegJump(rm); RestoreNoLegFallenState(rm); SuppressCrouchForcingForRestoration(); SetHandUsable(Player.LeftHand, usable: true); SetHandUsable(Player.RightHand, usable: true); } ResetVisualDamage(rm); if ((Object)(object)rm.avatar != (Object)null && (Object)(object)rm.avatar.animator != (Object)null) { ((Behaviour)rm.avatar.animator).enabled = true; } } if ((Object)(object)rm == (Object)(object)Player.RigManager) { _lastTrackedBodyHealth = -1f; UpdateRigMissingLimbsFlag(rm); SetLocalMetadata(""); } InvalidateAvatarHealthCache(rm); RebuildBoneCache(rm); UpdateRigMissingLimbsFlag(rm); BuildColliderBoneMap(rm); } private void TryCacheFleshSurface() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown if (_fleshCardFound) { return; } try { AssetWarehouse instance = AssetWarehouse.Instance; if (instance == null || !AssetWarehouse.ready) { return; } SurfaceDataCard val = default(SurfaceDataCard); if (instance.TryGetDataCard(new Barcode("SLZ.Backlot.SurfaceDataCard.Blood"), ref val) && (Object)(object)val != (Object)null) { _fleshSurfaceCard = new DataCardReference(((Scannable)val).Barcode); _fleshCardFound = true; MelonLogger.Msg(ConsoleColor.Gray, "Found vanilla Blood surface card: SLZ.Backlot.SurfaceDataCard.Blood"); return; } SurfaceDataCard val2 = default(SurfaceDataCard); if (instance.TryGetDataCard(new Barcode("slz.marrow.surfacedata.Flesh"), ref val2) && (Object)(object)val2 != (Object)null) { _fleshSurfaceCard = new DataCardReference(((Scannable)val2).Barcode); _fleshCardFound = true; MelonLogger.Msg(ConsoleColor.Gray, "Found Flesh surface card by barcode: slz.marrow.surfacedata.Flesh"); return; } List dataCards = instance.GetDataCards(); if (dataCards == null) { return; } Enumerator enumerator = dataCards.GetEnumerator(); while (enumerator.MoveNext()) { DataCard current = enumerator.Current; if ((Object)(object)current == (Object)null) { continue; } SurfaceDataCard val3 = ((Il2CppObjectBase)current).TryCast(); if (!((Object)(object)val3 == (Object)null)) { string text = ((Scannable)val3).Title ?? string.Empty; string text2 = text.ToLowerInvariant(); if (text2.Contains("blood") || text2.Contains("flesh")) { _fleshSurfaceCard = new DataCardReference(((Scannable)val3).Barcode); _fleshCardFound = true; MelonLogger.Msg($"Found Flesh surface card by title: {text} ({((Scannable)val3).Barcode})"); break; } } } } catch (Exception ex) { MelonLogger.Warning("Flesh surface scan failed: " + ex.Message); } } private void SetFleshImpactProperties(RigManager rm, HumanBodyBones bone) { //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (!EnableImpactBlood.Value || !_fleshCardFound || (Object)(object)rm == (Object)null || !_colliderBoneMap.TryGetValue(rm, out var value)) { return; } try { foreach (KeyValuePair item in value) { if (item.Value != bone) { continue; } Collider key = item.Key; if (!((Object)(object)key == (Object)null)) { ImpactProperties val = ((Component)key).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)key).gameObject.AddComponent(); } if ((Object)(object)val != (Object)null) { val.SurfaceDataCard = _fleshSurfaceCard; } } } } catch (Exception ex) { MelonLogger.Warning($"SetFleshImpactProperties failed for {bone}: {ex.Message}"); } } private void ApplyBloodImpactProperties(RigManager rm) { if (!EnableImpactBlood.Value || (Object)(object)rm == (Object)null) { return; } if (!_fleshCardFound) { TryCacheFleshSurface(); } if (!_fleshCardFound || !_colliderBoneMap.TryGetValue(rm, out var value)) { return; } try { foreach (KeyValuePair item in value) { Collider key = item.Key; if (!((Object)(object)key == (Object)null)) { ImpactProperties val = ((Component)key).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)key).gameObject.AddComponent(); } if ((Object)(object)val != (Object)null) { val.SurfaceDataCard = _fleshSurfaceCard; } } } } catch (Exception ex) { MelonLogger.Warning("ApplyBloodImpactProperties failed: " + ex.Message); } } private static bool IsAvatarBodyCollider(Collider collider, Transform avatarRoot) { if ((Object)(object)collider == (Object)null || (Object)(object)avatarRoot == (Object)null) { return false; } Transform val = ((Component)collider).transform; if (!val.IsChildOf(avatarRoot)) { return false; } for (int i = 0; i < 14; i++) { if (!((Object)(object)val != (Object)null)) { break; } if (!((Object)(object)val != (Object)(object)avatarRoot)) { break; } string text = ((Object)val).name.ToLowerInvariant(); if (text.Contains("gun") || text.Contains("pistol") || text.Contains("rifle") || text.Contains("weapon") || text.Contains("magazine") || text.Contains("ammo") || text.Contains("slide") || text.Contains("barrel") || text.Contains("trigger") || text.Contains("holster")) { return false; } Type il2CppType = ((Object)val).GetIl2CppType(); if (il2CppType != (Type)null) { string text2 = il2CppType.FullName ?? string.Empty; if (text2.Contains("Gun") || text2.Contains("Weapon") || text2.Contains("Magazine") || text2.Contains("Ammo") || text2.Contains("Firearm") || text2.Contains("Cartridge") || text2.Contains("Projectile")) { return false; } } val = val.parent; } return true; } private void RegrowLimb(RigManager rm, HumanBodyBones bone) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return; } Transform cachedBoneTransform = GetCachedBoneTransform(rm, bone); if (!((Object)(object)cachedBoneTransform == (Object)null)) { if (!_originalScales.TryGetValue(rm, out var value)) { value = new Dictionary(); _originalScales[rm] = value; } if (!value.TryGetValue(bone, out var value2) || value2 == Vector3.zero) { value2 = (value[bone] = Vector3.one); } cachedBoneTransform.localScale = value2; if (_playersHealth.TryGetValue(rm, out var value3)) { value3[bone] = GetMaxHealthForBone(rm, bone); } ClearStumpBloodState(rm, bone); } } private void ProcessPlayerHealing(RigManager rm) { if ((Object)(object)rm != (Object)(object)Player.RigManager || (Object)(object)((rm != null) ? rm.health : null) == (Object)null || !rm.health.alive) { return; } if (IsRigLimbDamageBlocked(rm) || !_playersHealth.ContainsKey(rm)) { _lastTrackedBodyHealth = rm.health.curr_Health; return; } float curr_Health = rm.health.curr_Health; if (_lastTrackedBodyHealth < 0f) { _lastTrackedBodyHealth = curr_Health; return; } if (curr_Health <= _lastTrackedBodyHealth) { _lastTrackedBodyHealth = curr_Health; return; } _lastTrackedBodyHealth = curr_Health; if (IsAutoInjectorUseActiveOrRecent()) { RestoreMissingLimbsFromHealing(rm); } } public void OnHealthSetFullHealth(Health health, float previousHealth) { RigManager rigFromHealth = GetRigFromHealth(health); if ((Object)(object)rigFromHealth == (Object)null) { return; } if ((Object)(object)rigFromHealth == (Object)(object)Player.RigManager) { if (IsAutoInjectorUseActiveOrRecent()) { RestoreMissingLimbsFromHealing(rigFromHealth); } } else if (IsRemotePlayerRig(rigFromHealth) && health.curr_Health > previousHealth) { RestoreMissingLimbsFromHealing(rigFromHealth); } } private void UpdateAutoInjectorUseWindow() { try { if (IsAutoInjectorUsePressed(Player.LeftHand, Player.LeftController) || IsAutoInjectorUsePressed(Player.RightHand, Player.RightController)) { _lastAutoInjectorUseTime = Time.unscaledTime; } } catch { } } public bool IsAutoInjectorUseActiveOrRecent() { if (Time.unscaledTime - _lastAutoInjectorUseTime <= 0.8f) { return true; } return IsAutoInjectorUsePressed(Player.LeftHand, Player.LeftController) || IsAutoInjectorUsePressed(Player.RightHand, Player.RightController); } private void UpdateExplosiveUseWindow() { try { if ((IsExplosiveHeld(Player.LeftHand) || IsExplosiveHeld(Player.RightHand)) && (IsExplosiveDetonatePressed(Player.LeftHand, Player.LeftController) || IsExplosiveDetonatePressed(Player.RightHand, Player.RightController))) { _lastExplosiveUseTime = Time.unscaledTime; TriggerSelfExplosion(); } } catch { } } public bool IsExplosiveUseActiveOrRecent() { if (Time.unscaledTime - _lastExplosiveUseTime <= 1.5f) { return true; } return false; } private bool IsExplosiveHeld(Hand hand) { if ((Object)(object)hand == (Object)null) { return false; } try { HandReciever attachedReceiver = hand.AttachedReceiver; if ((Object)(object)attachedReceiver == (Object)null) { return false; } if (IsExplosiveObject(((Component)attachedReceiver).gameObject)) { return true; } IGrippable host = attachedReceiver.Host; GameObject gameObject = ((host != null) ? host.GetHostGameObject() : null); return IsExplosiveObject(gameObject); } catch { } return false; } private bool IsExplosiveObject(GameObject gameObject) { if ((Object)(object)gameObject == (Object)null) { return false; } Transform val = gameObject.transform; for (int i = 0; i < 8; i++) { if (!((Object)(object)val != (Object)null)) { break; } if (LooksLikeExplosiveName(((Object)val).name)) { return true; } val = val.parent; } return false; } private bool LooksLikeExplosiveName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return false; } string text = objectName.ToLowerInvariant(); return text.Contains("explosive") || text.Contains("micro") || text.Contains("nuke") || text.Contains("dynamite") || text.Contains("c4") || text.Contains("grenade") || text.Contains("prox") || text.Contains("ied") || text.Contains("mine") || (text.Contains("timed") && (text.Contains("explos") || text.Contains("nuke"))); } private bool IsExplosiveDetonatePressed(Hand hand, BaseController controller) { if ((Object)(object)hand == (Object)null || (Object)(object)controller == (Object)null) { return false; } bool primaryInteractionButtonDown = controller.GetPrimaryInteractionButtonDown(); bool secondaryInteractionButtonDown = controller.GetSecondaryInteractionButtonDown(); return primaryInteractionButtonDown && secondaryInteractionButtonDown; } private void TriggerSelfExplosion() { RigManager rigManager = Player.RigManager; if ((Object)(object)rigManager == (Object)null) { return; } string[] array = new string[41] { "BaBaCorp.MiscExplosiveDevices.Spawnable.MicroNukeGrenade", "BaBaCorp.MiscExplosiveDevices.Spawnable.TimedNuke", "BaBaCorp.MiscExplosiveDevices.Spawnable.KCB4VoidTunnelingDevice", "BaBaCorp.MiscExplosiveDevices.Spawnable.IncinMissile", "BaBaCorp.MiscExplosiveDevices.Spawnable.Missile", "BaBaCorp.MiscExplosiveDevices.Spawnable.MiniMissile", "BaBaCorp.MiscExplosiveDevices.Spawnable.TimedC4", "BaBaCorp.MiscExplosiveDevices.Spawnable.CelebratoryC4", "BaBaCorp.MiscExplosiveDevices.Spawnable.RemoteIED", "BaBaCorp.MiscExplosiveDevices.Spawnable.TriggeredExplosive", "BaBaCorp.MiscExplosiveDevices.Spawnable.ImpactExplosive", "BaBaCorp.MiscExplosiveDevices.Spawnable.TimedExplosive6sec", "BaBaCorp.MiscExplosiveDevices.Spawnable.M72LAW", "BaBaCorp.MiscExplosiveDevices.Spawnable.M72LawINF", "BaBaCorp.MiscExplosiveDevices.Spawnable.ClassicBomb", "BaBaCorp.MiscExplosiveDevices.Spawnable.Dynamite", "BaBaCorp.MiscExplosiveDevices.Spawnable.ProxMine", "BaBaCorp.MiscExplosiveDevices.Spawnable.GiftMine", "BaBaCorp.MiscExplosiveDevices.Spawnable.FragmentationGrenade", "BaBaCorp.MiscExplosiveDevices.Spawnable.IncendiaryGrenade", "BaBaCorp.MiscExplosiveDevices.Spawnable.DivinationGrenade", "BaBaCorp.MiscExplosiveDevices.Spawnable.GasGrenade", "BaBaCorp.MiscExplosiveDevices.Spawnable.JoyousGreenGrenade", "BaBaCorp.MiscExplosiveDevices.Spawnable.Stielhandgranate", "BaBaCorp.MiscExplosiveDevices.Spawnable.SmallRocket", "BaBaCorp.MiscExplosiveDevices.Spawnable.PurpleFireworkRocket", "BaBaCorp.MiscExplosiveDevices.Spawnable.GreenFireworkRocket", "BaBaCorp.MiscExplosiveDevices.Spawnable.BlueFireworkRocket", "BaBaCorp.MiscExplosiveDevices.Spawnable.RedFireworkRocket", "BaBaCorp.MiscExplosiveDevices.Spawnable.BirthdayCake", "BaBaCorp.MiscExplosiveDevices.Spawnable.Frank", "BaBaCorp.MiscExplosiveDevices.Spawnable.BatteryAcidGlass", "BaBaCorp.MiscExplosiveDevices.Spawnable.CrateWithLid", "BaBaCorp.MiscExplosiveDevices.Spawnable.PropaneTank", "BaBaCorp.MiscExplosiveDevices.Spawnable.FuelTank", "BaBaCorp.MiscExplosiveDevices.Spawnable.SmokeGrenade", "BaBaCorp.MiscExplosiveDevices.Spawnable.Flare", "BaBaCorp.MiscExplosiveDevices.Spawnable.Jarate", "BaBaCorp.MiscExplosiveDevices.Spawnable.Lighter", "BaBaCorp.MiscExplosiveDevices.Spawnable.Pliers", "BaBaCorp.MiscExplosiveDevices.Spawnable.ExplosionSmallBigDamage" }; string[] array2 = array; foreach (string text in array2) { try { TriggerExplosion(rigManager, text); MelonLogger.Msg(ConsoleColor.Gray, "Self explosion triggered with: " + text); break; } catch (Exception ex) { MelonLogger.Warning("Explosion failed for " + text + ": " + ex.Message); } } } private void TriggerExplosion(RigManager rm, string explosiveBarcode) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) MelonLogger.Msg(ConsoleColor.Gray, "TriggerExplosion: attempting " + explosiveBarcode); if ((Object)(object)rm == (Object)null) { MelonLogger.Error("RigManager is null!"); return; } try { Spawnable val = new Spawnable { crateRef = new SpawnableCrateReference(explosiveBarcode), policyData = null }; if (!val.IsValid()) { MelonLogger.Error("Spawnable is not valid for " + explosiveBarcode); return; } MelonLogger.Msg(ConsoleColor.Gray, "Spawnable valid, spawning at position..."); Vector3 val2 = ((Component)rm).transform.position + ((Component)rm).transform.forward * 0.5f + ((Component)rm).transform.up * 0.5f; Action action = OnExplosiveSpawned; AssetSpawner.Spawn(val, val2, Quaternion.identity, new Nullable(Vector3.one), (Transform)null, false, (Nullable)null, Action.op_Implicit(action), (Action)null); MelonLogger.Msg(ConsoleColor.Gray, "AssetSpawner.Spawn called for " + explosiveBarcode); } catch (Exception value) { MelonLogger.Error($"TriggerExplosion exception for {explosiveBarcode}: {value}"); } } private void OnExplosiveSpawned(GameObject spawned) { MelonLogger.Msg(ConsoleColor.Gray, $"OnExplosiveSpawned called, spawned: {(Object)(object)spawned != (Object)null}"); if ((Object)(object)spawned != (Object)null) { MelonLogger.Msg(ConsoleColor.Gray, $"Spawned object name: {((Object)spawned).name}, active: {spawned.activeInHierarchy}"); Il2CppArrayBase componentsInChildren = spawned.GetComponentsInChildren(true); MelonLogger.Msg(ConsoleColor.Gray, $"Found {componentsInChildren.Length} components"); foreach (MonoBehaviour item in componentsInChildren) { if ((Object)(object)item != (Object)null) { MelonLogger.Msg(ConsoleColor.Gray, "Component: " + ((object)item).GetType().Name); } } ForceDetonate(spawned); } else { MelonLogger.Error("Spawned object is null!"); } } private void ForceDetonate(GameObject spawned) { MelonLogger.Msg(ConsoleColor.Gray, "ForceDetonate called for " + ((Object)spawned).name); try { Il2CppArrayBase componentsInChildren = spawned.GetComponentsInChildren(true); MelonLogger.Msg(ConsoleColor.Gray, $"Checking {componentsInChildren.Length} components for Detonate/Explode methods"); foreach (MonoBehaviour item in componentsInChildren) { if (!((Object)(object)item == (Object)null)) { MethodInfo method = ((object)item).GetType().GetMethod("Detonate", BindingFlags.Instance | BindingFlags.Public); if (method != null) { MelonLogger.Msg(ConsoleColor.Gray, "Found Detonate() on " + ((object)item).GetType().Name + ", invoking..."); method.Invoke(item, null); MelonLogger.Msg(ConsoleColor.Gray, "Detonated via " + ((object)item).GetType().Name + ".Detonate()"); return; } } } Rigidbody component = spawned.GetComponent(); if ((Object)(object)component != (Object)null) { component.useGravity = true; component.isKinematic = false; MelonLogger.Msg(ConsoleColor.Gray, "Set rigidbody for gravity detonation"); } else { MelonLogger.Warning("No Rigidbody found on spawned object"); } foreach (MonoBehaviour item2 in componentsInChildren) { if (!((Object)(object)item2 == (Object)null)) { MethodInfo method2 = ((object)item2).GetType().GetMethod("Explode", BindingFlags.Instance | BindingFlags.Public); if (method2 != null) { MelonLogger.Msg(ConsoleColor.Gray, "Found Explode() on " + ((object)item2).GetType().Name + ", invoking..."); method2.Invoke(item2, null); MelonLogger.Msg(ConsoleColor.Gray, "Detonated via " + ((object)item2).GetType().Name + ".Explode()"); return; } } } MelonLogger.Warning("No detonation method found, object spawned but may not explode automatically"); } catch (Exception value) { MelonLogger.Error($"ForceDetonate exception: {value}"); } } public bool IsHoldingNimbusGun(RigManager rm) { return IsNimbusGunHand(Player.LeftHand) || IsNimbusGunHand(Player.RightHand); } private bool IsNimbusGunHand(Hand hand) { if ((Object)(object)hand == (Object)null) { return false; } try { HandReciever attachedReceiver = hand.AttachedReceiver; if ((Object)(object)attachedReceiver == (Object)null) { return false; } IGrippable host = attachedReceiver.Host; GameObject val = ((host != null) ? host.GetHostGameObject() : null); if ((Object)(object)val == (Object)null) { return false; } SpawnableCrate componentInChildren = val.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null && ((Scannable)componentInChildren).Barcode != (Barcode)null && ((Object)((Scannable)componentInChildren).Barcode).ToString().Contains("Nimbus")) { return true; } Transform val2 = val.transform; while ((Object)(object)val2 != (Object)null) { if (((Object)val2).name.Contains("Nimbus")) { return true; } val2 = val2.parent; } } catch { } return false; } private bool IsAutoInjectorUsePressed(Hand hand, BaseController controller) { if (!IsAutoInjectorHeldByHand(hand)) { return false; } bool flag = false; try { flag |= (Object)(object)hand != (Object)null && (hand.GetIndexButtonDown() || hand.GetIndexButton()); } catch { } try { flag |= (Object)(object)controller != (Object)null && (controller.GetPrimaryInteractionButtonDown() || controller.GetPrimaryInteractionButton()); flag |= (Object)(object)controller != (Object)null && (controller.GetSecondaryInteractionButtonDown() || controller.GetSecondaryInteractionButton()); flag |= (Object)(object)controller != (Object)null && (controller.GetAButtonDown() || controller.GetAButton()); flag |= (Object)(object)controller != (Object)null && (controller.GetBButtonDown() || controller.GetBButton()); } catch { } return flag; } private bool IsAutoInjectorHeldByHand(Hand hand) { if ((Object)(object)hand == (Object)null) { return false; } try { HandReciever attachedReceiver = hand.AttachedReceiver; if ((Object)(object)attachedReceiver == (Object)null) { return false; } if (IsAutoInjectorObject(((Component)attachedReceiver).gameObject)) { return true; } IGrippable host = attachedReceiver.Host; GameObject gameObject = ((host != null) ? host.GetHostGameObject() : null); return IsAutoInjectorObject(gameObject); } catch { return false; } } private bool IsAutoInjectorObject(GameObject gameObject) { Transform val = (((Object)(object)gameObject != (Object)null) ? gameObject.transform : null); for (int i = 0; i < 8; i++) { if (!((Object)(object)val != (Object)null)) { break; } if (LooksLikeAutoInjectorName(((Object)val).name)) { return true; } val = val.parent; } return false; } private bool LooksLikeAutoInjectorName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return false; } string text = objectName.ToLowerInvariant(); string text2 = text.Replace(" ", string.Empty).Replace("_", string.Empty).Replace("-", string.Empty); return text2.Contains("autoinjector") || (text2.Contains("auto") && text2.Contains("inject")) || text2.Contains("signalisautoinjector"); } private bool RestoreMissingLimbsFromHealing(RigManager rm) { //IL_00b9: 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_00d7: 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) if ((Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return false; } EnsureRigInitialized(rm); if (IsRigLimbDamageBlocked(rm)) { ResetLimbStats(rm, restoreBody: true); if ((Object)(object)rm != (Object)(object)Player.RigManager && TryGetPlayerIdForRig(rm, out var playerId)) { NetworkSync.SendFullState(playerId, 0u, 0, 0); } return true; } if (!_playersHealth.TryGetValue(rm, out var value)) { return false; } bool flag = false; for (int i = 0; i < DamageBones.Length; i++) { HumanBodyBones val = DamageBones[i]; float value2; bool flag2 = value.TryGetValue(val, out value2) && value2 < 0f; if (IsBoneGone(rm, val) || flag2) { RegrowLimb(rm, val); flag = true; } } if (!flag) { return false; } RebuildLimbGoneFlags(rm); UpdateRigMissingLimbsFlag(rm); ResetVisualDamage(rm); if ((Object)(object)rm == (Object)(object)Player.RigManager) { SetHandUsable(Player.LeftHand, !IsLeftArmGone(rm)); SetHandUsable(Player.RightHand, !IsRightArmGone(rm)); if (EnableVrEyeBlindness.Value) { UpdateVrEyeBlindness(rm); } RestoreLocomotion(); RestoreOriginalLimits(rm); ResetLegRagdoll(rm); RestoreDeadpieceLegUsage(rm); RestoreNoLegJump(rm); RestoreNoLegFallenState(rm); SuppressCrouchForcingForRestoration(); } byte playerId3; if (NetworkInfo.HasServer) { byte playerId2; if ((Object)(object)rm == (Object)(object)Player.RigManager) { SyncFullState(); } else if (TryGetPlayerIdForRig(rm, out playerId2)) { uint stateMask = GetStateMask(rm); NetworkSync.SendFullState(playerId2, stateMask, 0, 0); } } else if ((Object)(object)rm != (Object)(object)Player.RigManager && TryGetPlayerIdForRig(rm, out playerId3)) { uint stateMask2 = GetStateMask(rm); NetworkSync.SendFullState(playerId3, stateMask2, 0, 0); } return true; } private void ProcessSeveredLimbBleed(RigManager rm, float deltaTime) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) if (!EnableImpactBlood.Value || (Object)(object)rm == (Object)null || deltaTime <= 0f || !_playersHealth.ContainsKey(rm)) { return; } float num = Mathf.Max(0f, SeveredLimbBleedDamagePerSecond.Value) * deltaTime; if (num <= 0f && !EnableBloodEffects.Value) { return; } for (int i = 0; i < DamageBones.Length; i++) { HumanBodyBones bone = DamageBones[i]; if (!IsBoneGone(rm, bone)) { continue; } float remainingStumpBloodLifetime = GetRemainingStumpBloodLifetime(rm, bone, startIfMissing: true); if (!(remainingStumpBloodLifetime <= 0.05f)) { if (num > 0f) { TryApplyBleedAtBone(rm, bone, num); } TryPlayStumpBloodEffect(rm, bone, remainingStumpBloodLifetime); } } } private void ProcessRemoteRigsStumpBlood(float deltaTime) { if (!EnableImpactBlood.Value || _trackedRigs.Count == 0 || deltaTime <= 0f) { return; } RigManager[] array = _trackedRigs.ToArray(); foreach (RigManager val in array) { if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)Player.RigManager) { ProcessSeveredLimbBleed(val, deltaTime); } } } private void TryPlayStumpBloodEffect(RigManager rm, HumanBodyBones bone, float remainingBloodLifetime) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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_00c5: 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_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_00f6: 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_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) if (!EnableBloodEffects.Value || !EnableGameBloodEffects.Value || (Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null || remainingBloodLifetime <= 0.05f || !ShouldPlayStumpBloodEffect(rm, bone)) { return; } Transform cachedBoneTransform = GetCachedBoneTransform(rm, bone); if (!((Object)(object)cachedBoneTransform == (Object)null)) { Vector3 val = GetBoneStreamDirection(rm, bone, cachedBoneTransform); if (val == Vector3.zero) { val = cachedBoneTransform.up; } val = ((Vector3)(ref val)).normalized; Vector3 val2 = cachedBoneTransform.position + val * 0.04f; Color bloodColor = GetBloodColor(rm); TryApplyBloodImpactAtBone(rm, bone, val2, 3f, bloodColor); if (!TrySpawnVanillaBloodSpawnable(val2, 0.72f, stream: true, Quaternion.LookRotation(val), bloodColor, remainingBloodLifetime)) { TrySpawnGameBlood(val2, 0.55f, bloodColor, remainingBloodLifetime); } } } private bool ShouldPlayStumpBloodEffect(RigManager rm, HumanBodyBones bone) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (!_lastStumpBloodEffectTimes.TryGetValue(rm, out var value)) { value = new Dictionary(); _lastStumpBloodEffectTimes[rm] = value; } if (value.TryGetValue(bone, out var value2) && Time.time - value2 < 0.45f) { return false; } value[bone] = Time.time; return true; } private void MarkStumpBloodStarted(RigManager rm, HumanBodyBones bone) { //IL_003b: 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) if (!((Object)(object)rm == (Object)null)) { if (!_stumpBloodStartTimes.TryGetValue(rm, out var value)) { value = new Dictionary(); _stumpBloodStartTimes[rm] = value; } value[bone] = Time.time; if (_lastStumpBloodEffectTimes.TryGetValue(rm, out var value2)) { value2.Remove(bone); } } } private bool HasStumpBloodStart(RigManager rm, HumanBodyBones bone) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) Dictionary value; return (Object)(object)rm != (Object)null && _stumpBloodStartTimes.TryGetValue(rm, out value) && value.ContainsKey(bone); } private float GetRemainingStumpBloodLifetime(RigManager rm, HumanBodyBones bone, bool startIfMissing) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null) { return 0f; } if (!_stumpBloodStartTimes.TryGetValue(rm, out var value) || !value.TryGetValue(bone, out var value2)) { if (!startIfMissing) { return 0f; } MarkStumpBloodStarted(rm, bone); value2 = Time.time; } return Mathf.Max(0f, 10f - (Time.time - value2)); } private void ClearStumpBloodState(RigManager rm) { if (!((Object)(object)rm == (Object)null)) { _stumpBloodStartTimes.Remove(rm); _lastStumpBloodEffectTimes.Remove(rm); } } private void ClearStumpBloodState(RigManager rm, HumanBodyBones bone) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null) { return; } if (_stumpBloodStartTimes.TryGetValue(rm, out var value)) { value.Remove(bone); if (value.Count == 0) { _stumpBloodStartTimes.Remove(rm); } } if (_lastStumpBloodEffectTimes.TryGetValue(rm, out var value2)) { value2.Remove(bone); if (value2.Count == 0) { _lastStumpBloodEffectTimes.Remove(rm); } } } private void TryApplyBleedAtBone(RigManager rm, HumanBodyBones bone, float damage) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) TryApplyBloodImpactAtBone(rm, bone, Vector3.zero, damage); } private bool TryApplyBloodImpactAtBone(RigManager rm, HumanBodyBones bone, Vector3 origin, float damage) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) return TryApplyBloodImpactAtBone(rm, bone, origin, damage, Color.white); } private bool TryApplyBloodImpactAtBone(RigManager rm, HumanBodyBones bone, Vector3 origin, float damage, Color color) { //IL_0057: 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_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0171: 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_017a: 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_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018b: 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_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Expected O, but got Unknown //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((rm != null) ? rm.avatar : null) == (Object)null || damage <= 0f || !_colliderBoneMap.TryGetValue(rm, out var value)) { return false; } Collider val = null; foreach (KeyValuePair item in value) { if (item.Value == bone) { val = item.Key; break; } } if ((Object)(object)val == (Object)null) { return false; } try { ImpactProperties val2 = ((Component)val).GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).gameObject.AddComponent(); } if ((Object)(object)val2 == (Object)null) { return false; } if (_fleshCardFound) { val2.SurfaceDataCard = _fleshSurfaceCard; } Vector3 val3; Bounds bounds; if (!(origin == Vector3.zero)) { val3 = origin; } else { bounds = val.bounds; val3 = ((Bounds)(ref bounds)).center; } Vector3 val4 = val3; bounds = val.bounds; Vector3 val5 = ((Bounds)(ref bounds)).center - val4; if (val5 == Vector3.zero) { val5 = Vector3.down; } ((Vector3)(ref val5)).Normalize(); Attack val6 = new Attack { damage = damage, normal = -val5, origin = val4, direction = val5, backFacing = false, OrderInPool = 0, collider = val, attackType = (AttackType)1, proxy = null }; val2.ReceiveAttack(val6); return true; } catch { } return false; } private void SpawnBloodPoolDecal(Vector3 origin, Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_004d: Expected O, but got Unknown //IL_0055: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_0111: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) try { Vector3 val = origin; val.y += 2.5f; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.down, ref val2, 5f, -1, (QueryTriggerInteraction)1) && (Object)(object)((RaycastHit)(ref val2)).collider != (Object)null) { GameObject val3 = new GameObject("DeadPiece_BloodPool"); val3.transform.position = ((RaycastHit)(ref val2)).point + ((RaycastHit)(ref val2)).normal * 0.005f; val3.transform.rotation = Quaternion.LookRotation(((RaycastHit)(ref val2)).normal); val3.transform.localScale = Vector3.one * Mathf.Lerp(0.08f, 0.35f, Random.value); val3.transform.Rotate(0f, 0f, Random.Range(0f, 360f)); MeshFilter val4 = val3.AddComponent(); val4.sharedMesh = BuildBloodQuadMesh(); MeshRenderer val5 = val3.AddComponent(); ((Renderer)val5).material = new Material(Shader.Find("Sprites/Default")); ((Renderer)val5).material.color = color; ((Renderer)val5).material.mainTexture = null; Object.Destroy((Object)(object)val3, 10f); } } catch { } } private IEnumerator DelayedPoolClear(Poolee poolee, float delay) { yield return (object)new WaitForSeconds(delay); if ((Object)(object)poolee != (Object)null && (Object)(object)((Component)poolee).gameObject != (Object)null) { StopBloodEffectObject(((Component)poolee).gameObject); HideRenderers(((Component)poolee).gameObject); try { AssetSpawner.Clear(poolee); } catch { } if ((Object)(object)((Component)poolee).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)poolee).gameObject); } } } private IEnumerator RunAsyncSpawnBlood(Spawnable spawnable, Vector3 position, Quaternion rotation, Nullable scale, Color color, float clearDelay) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) Poolee result = null; bool done = false; UniTask task = AssetSpawner.SpawnAsync(spawnable, position, rotation, scale, (Transform)null, false, (Nullable)null, (Action)null, (Action)null, (Action)null); Awaiter awaiter = task.GetAwaiter(); for (int i = 0; i < 60; i++) { if (done) { break; } yield return null; try { result = awaiter.GetResult(); done = true; } catch { } } if (!((Object)(object)result != (Object)null) || !((Object)(object)((Component)result).gameObject != (Object)null)) { yield break; } if (color != Color.white) { Renderer[] renderers = Il2CppArrayBase.op_Implicit(((Component)result).GetComponentsInChildren(true)); Renderer[] array = renderers; foreach (Renderer r in array) { Material mat = r.material; string[] colorProps = new string[5] { "_Color", "_BaseColor", "_TintColor", "_EmissiveColor", "_MainColor" }; string[] array2 = colorProps; foreach (string prop in array2) { if (mat.HasProperty(prop)) { mat.SetColor(prop, color); break; } } } ParticleSystem[] particles = Il2CppArrayBase.op_Implicit(((Component)result).GetComponentsInChildren(true)); ParticleSystem[] array3 = particles; foreach (ParticleSystem ps in array3) { MainModule main = ps.main; main.startColor = MinMaxGradient.op_Implicit(color); } } MelonCoroutines.Start(DelayedPoolClear(result, clearDelay)); } private IEnumerator RunAsyncSpawnVanillaBlood(Spawnable spawnable, Vector3 position, Quaternion rotation, Nullable scale, Nullable groupId, Color color, float clearDelay) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) Poolee result = null; bool done = false; UniTask spawnTask = AssetSpawner.SpawnAsync(spawnable, position, rotation, scale, (Transform)null, false, groupId, (Action)null, (Action)null, (Action)null); Awaiter awaiter = spawnTask.GetAwaiter(); for (int i = 0; i < 60; i++) { if (done) { break; } yield return null; try { result = awaiter.GetResult(); done = true; } catch { } } if ((Object)(object)result == (Object)null) { if (!_loggedVanillaBloodSpawnableFailure) { _loggedVanillaBloodSpawnableFailure = true; MelonLogger.Warning("Vanilla BONELAB blood spawnable returned null."); } } else { if (!((Object)(object)((Component)result).gameObject != (Object)null)) { yield break; } Renderer[] allRenderers = Il2CppArrayBase.op_Implicit(((Component)result).GetComponentsInChildren(true)); Renderer[] array = allRenderers; foreach (Renderer r in array) { Material mat = r.material; string[] colorProps = new string[5] { "_Color", "_BaseColor", "_TintColor", "_EmissiveColor", "_MainColor" }; string[] array2 = colorProps; foreach (string prop in array2) { if (mat.HasProperty(prop)) { mat.SetColor(prop, color); break; } } } ParticleSystem[] particles = Il2CppArrayBase.op_Implicit(((Component)result).GetComponentsInChildren(true)); ParticleSystem[] array3 = particles; foreach (ParticleSystem ps in array3) { MainModule m = ps.main; m.startColor = MinMaxGradient.op_Implicit(color); } MelonCoroutines.Start(DelayedPoolClear(result, clearDelay)); } } private void StopBloodEffectObject(GameObject root) { if ((Object)(object)root == (Object)null) { return; } try { ParticleSystem[] array = Il2CppArrayBase.op_Implicit(root.GetComponentsInChildren(true)); ParticleSystem[] array2 = array; foreach (ParticleSystem val in array2) { if ((Object)(object)val != (Object)null) { val.Stop(true, (ParticleSystemStopBehavior)0); } } TrailRenderer[] array3 = Il2CppArrayBase.op_Implicit(root.GetComponentsInChildren(true)); TrailRenderer[] array4 = array3; foreach (TrailRenderer val2 in array4) { if ((Object)(object)val2 != (Object)null) { val2.Clear(); } } } catch { } } private void HideRenderers(GameObject root) { if ((Object)(object)root == (Object)null) { return; } try { Renderer[] array = Il2CppArrayBase.op_Implicit(root.GetComponentsInChildren(true)); Renderer[] array2 = array; foreach (Renderer val in array2) { if ((Object)(object)val != (Object)null) { val.enabled = false; } } } catch { } } private Mesh BuildBloodQuadMesh() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_00ac: 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_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_bloodQuadMesh != (Object)null) { return _bloodQuadMesh; } _bloodQuadMesh = new Mesh(); ((Object)_bloodQuadMesh).name = "DeadPiece_BloodQuad"; _bloodQuadMesh.vertices = Il2CppStructArray.op_Implicit((Vector3[])(object)new Vector3[4] { new Vector3(-0.5f, -0.5f, 0f), new Vector3(0.5f, -0.5f, 0f), new Vector3(-0.5f, 0.5f, 0f), new Vector3(0.5f, 0.5f, 0f) }); _bloodQuadMesh.triangles = Il2CppStructArray.op_Implicit(new int[6] { 0, 1, 2, 2, 1, 3 }); _bloodQuadMesh.uv = Il2CppStructArray.op_Implicit((Vector2[])(object)new Vector2[4] { new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0f, 1f), new Vector2(1f, 1f) }); _bloodQuadMesh.RecalculateNormals(); return _bloodQuadMesh; } private void HandleStickInputs(float deltaTime) { if (!EnableDualStickDeathReset.Value || (Object)(object)Player.RigManager == (Object)null) { return; } try { BaseController leftController = Player.LeftController; BaseController rightController = Player.RightController; bool leftStickDown = (Object)(object)leftController != (Object)null && leftController.GetThumbStickDown(); bool rightStickDown = (Object)(object)rightController != (Object)null && rightController.GetThumbStickDown(); TryRegisterDualStickDeathResetTap(leftStickDown, rightStickDown); } catch (Exception ex) { MelonLogger.Warning("Stick input handling failed: " + ex.Message); } } private void TryRegisterDualStickDeathResetTap(bool leftStickDown, bool rightStickDown) { float unscaledTime = Time.unscaledTime; if (leftStickDown) { _lastLeftStickTapTime = unscaledTime; } if (rightStickDown) { _lastRightStickTapTime = unscaledTime; } if ((leftStickDown || rightStickDown) && !(Mathf.Abs(_lastLeftStickTapTime - _lastRightStickTapTime) > 0.25f) && !(unscaledTime - _lastDualStickTapRegisteredTime < 0.08f)) { _lastDualStickTapRegisteredTime = unscaledTime; if (unscaledTime > _dualStickResetTapWindowExpire) { _dualStickResetTapCount = 0; } _dualStickResetTapCount++; _dualStickResetTapWindowExpire = unscaledTime + 1.75f; if (_dualStickResetTapCount >= 2 && unscaledTime - _lastDualStickResetTime >= 0.75f) { _dualStickResetTapCount = 0; _dualStickResetTapWindowExpire = 0f; _lastDualStickResetTime = unscaledTime; PerformDualStickDeathReset(); } } } private void PerformDualStickDeathReset() { RigManager rigManager = Player.RigManager; if (!((Object)(object)rigManager == (Object)null) && !((Object)(object)rigManager.health == (Object)null)) { KillRig(rigManager); } } private void SpawnEyePatch(Vector3 position, Vector3 direction) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("DeadPiece_EyePatch"); val.transform.position = position + direction * 0.04f; SpriteRenderer val2 = val.AddComponent(); Texture2D val3 = new Texture2D(16, 16, (TextureFormat)4, false); Color[] array = (Color[])(object)new Color[256]; Color val4 = default(Color); ((Color)(ref val4))..ctor(0.05f, 0.05f, 0.05f, 1f); for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { float num = ((float)i - 7.5f) / 7.5f; float num2 = ((float)j - 7.5f) / 7.5f; array[i * 16 + j] = ((num * num + num2 * num2 < 1f) ? val4 : Color.clear); } } val3.SetPixels(Il2CppStructArray.op_Implicit(array)); val3.Apply(); val2.sprite = Sprite.Create(val3, new Rect(0f, 0f, 16f, 16f), new Vector2(0.5f, 0.5f)); val.transform.localScale = new Vector3(0.08f, 0.08f, 1f); Object.Destroy((Object)(object)val, 6f); } private Vector3 GetBoneStreamDirection(RigManager rm, HumanBodyBones bone, Transform boneTransform) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) HumanBodyBones primaryChildBone = GetPrimaryChildBone(bone); Vector3 val; if ((int)primaryChildBone != 55) { Transform cachedBoneTransform = GetCachedBoneTransform(rm, primaryChildBone); if ((Object)(object)cachedBoneTransform != (Object)null) { val = cachedBoneTransform.position - boneTransform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; if (normalized != Vector3.zero) { return normalized; } } } if ((Object)(object)boneTransform.parent != (Object)null) { val = boneTransform.position - boneTransform.parent.position; return ((Vector3)(ref val)).normalized; } return boneTransform.forward; } private void BuildColliderBoneMap(RigManager rm) { //IL_00dd: 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_00e6: 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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return; } RebuildBoneCache(rm); Dictionary dictionary = new Dictionary(); Dictionary dictionary2 = new Dictionary(); RigRuntimeCache orCreateRigCache = GetOrCreateRigCache(rm); Transform[] boneTransforms = orCreateRigCache.BoneTransforms; if (boneTransforms == null) { return; } float num = 0.3025f; float num2 = 0.122499995f; Transform transform = ((Component)rm.avatar).transform; Il2CppArrayBase componentsInChildren = ((Component)rm.avatar).GetComponentsInChildren(true); foreach (Collider item in componentsInChildren) { if ((Object)(object)item == (Object)null || !IsAvatarBodyCollider(item, transform)) { continue; } Transform transform2 = ((Component)item).transform; Bounds bounds = item.bounds; Vector3 center = ((Bounds)(ref bounds)).center; float num3 = float.MaxValue; float value = float.MaxValue; int num4 = -1; for (int i = 0; i < boneTransforms.Length; i++) { Transform val = boneTransforms[i]; if (!((Object)(object)val == (Object)null)) { HumanBodyBones val2 = DamageBones[i]; Vector3 boneSegmentPoint = GetBoneSegmentPoint(rm, val2, val); float num5 = DistanceToSegmentSquared(center, val.position, boneSegmentPoint); if (CoreNearestExcludeBones.Contains(val2)) { num5 += num2; } if (num5 < num3) { num3 = num5; value = GetHierarchyDistance(transform2, val); num4 = i; } } } if (num4 >= 0 && num3 <= num) { dictionary[item] = DamageBones[num4]; dictionary2[item] = value; } } _colliderBoneMap[rm] = dictionary; _colliderBoneDistanceMap[rm] = dictionary2; ApplyBloodImpactProperties(rm); TrackRig(rm); } public void OnRaycastBoneHit(RigManager rm, RaycastHit hit, float damage) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null || (Object)(object)((RaycastHit)(ref hit)).collider == (Object)null || damage <= 0f || IsRigLimbDamageBlocked(rm)) { return; } EnsureRigInitialized(rm); if (TryGetBoneFromHit(rm, hit, out var bone)) { float damage2 = damage * DamageMultiplier.Value; if (IsRemotePlayerRig(rm)) { ProcessRemoteLimbHit(rm, bone, damage2, ((RaycastHit)(ref hit)).point); } else { OnBoneHit(rm, bone, damage2, ((RaycastHit)(ref hit)).point); } } } public void OnAttackReceived(PlayerDamageReceiver receiver, Attack attack) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Invalid comparison between Unknown and I4 //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Invalid comparison between Unknown and I4 //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Invalid comparison between Unknown and I4 //IL_00d1: 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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)receiver == (Object)null || attack == null || attack.damage <= 0f) { return; } Health health = receiver.health; RigManager val = (((Object)(object)health != (Object)null) ? health._rigManager : null); if (!((Object)(object)val == (Object)null) && !IsRemotePlayerRig(val) && !IsRigLimbDamageBlocked(val)) { EnsureRigInitialized(val); Vector3 attackPoint = GetAttackPoint(receiver, attack); HumanBodyBones bone = BodyPartToBone(receiver.bodyPart); if ((int)bone == 55 && (Object)(object)attack.collider != (Object)null) { TryGetBoneFromCollider(val, attack.collider, attackPoint, out bone); } if ((int)bone == 55 && !TryGetNearestExtremityBone(val, attackPoint, out bone)) { TryGetNearestBone(val, attackPoint, out bone); } if ((int)bone != 55) { OnBoneHit(val, bone, CalculateAttackDamage(attack, val, bone), attackPoint); } } } public bool TryConsumeNonFatalAttack(PlayerDamageReceiver receiver, Attack attack) { //IL_0119: 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_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Invalid comparison between Unknown and I4 //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: 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_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Invalid comparison between Unknown and I4 //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Invalid comparison between Unknown and I4 //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)receiver == (Object)null || attack == null || attack.damage <= 0f) { return false; } Health health = receiver.health; RigManager val = (((Object)(object)health != (Object)null) ? health._rigManager : null); if ((Object)(object)val == (Object)null) { MelonLogger.Warning($"[DeadPiece] TryConsumeNonFatalAttack: rigManager=null receiver={((receiver != null) ? ((Object)receiver).name : null)} health={(Object)(object)health != (Object)null}"); return false; } if (IsRemotePlayerRig(val)) { float damage = attack.damage; MelonLogger.Msg(ConsoleColor.DarkYellow, $"[DeadPiece] Remote rig hit: rig={((Object)val).name} damage={damage} bodyPart={receiver.bodyPart}"); attack.damage = 0f; ProcessRemotePlayerAttack(val, receiver, attack, damage); return true; } if (IsRigLimbDamageBlocked(val)) { attack.damage = 0f; return true; } if (IsExplosionLikeAttack(attack)) { attack.damage = 0f; Vector3 blastOrigin = GetBlastOrigin(receiver, attack); ApplyExplosionDamage(val, attack, blastOrigin); SyncFullState(); return true; } Vector3 attackPoint = GetAttackPoint(receiver, attack); HumanBodyBones bone = BodyPartToBone(receiver.bodyPart); if ((int)bone == 55 && (Object)(object)attack.collider != (Object)null) { TryGetBoneFromCollider(val, attack.collider, attackPoint, out bone); } if ((int)bone == 55 && !TryGetNearestExtremityBone(val, attackPoint, out bone)) { TryGetNearestBone(val, attackPoint, out bone); } EnsureRigInitialized(val); if ((int)bone == 55 || FatalBones.Contains(bone)) { return false; } OnBoneHit(val, bone, CalculateAttackDamage(attack, val, bone), attackPoint); return true; } private float CalculateAttackDamage(Attack attack, RigManager rm, HumanBodyBones bone) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) float num = attack.damage * DamageMultiplier.Value; if (!EnableAttackTypeBalancing.Value) { return num; } num *= GetAttackTypeMultiplier(attack.attackType); if (IsSharpAttack(attack.attackType) && Random.value <= SharpSeverChance.Value) { num = Mathf.Max(num, GetMaxHealthForBone(rm, bone)); } return num; } private float GetAttackTypeMultiplier(AttackType attackType) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Invalid comparison between Unknown and I4 //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Invalid comparison between Unknown and I4 float num = 1f; if ((attackType & 1) > 0) { num = Mathf.Max(num, PiercingDamageMultiplier.Value); } if ((attackType & 2) > 0) { num *= BluntDamageMultiplier.Value; } if ((attackType & 0x10) > 0) { num = Mathf.Max(num, SlashDamageMultiplier.Value); } if ((attackType & 0x20) > 0) { num = Mathf.Max(num, StabDamageMultiplier.Value); } if ((attackType & 8) > 0) { num *= FireDamageMultiplier.Value; } return Mathf.Max(0f, num); } private bool IsSharpAttack(AttackType attackType) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 return (attackType & 0x10) != 0 || (attackType & 0x20) > 0; } private bool IsExplosionLikeAttack(Attack attack) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Invalid comparison between Unknown and I4 //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Invalid comparison between Unknown and I4 //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Invalid comparison between Unknown and I4 if (!EnableBlastLimbDamage.Value || attack.damage <= 0f) { return false; } if ((Object)(object)attack.collider != (Object)null && IsExplosiveSourceCollider(attack.collider)) { return true; } if (attack.damage < ExplosionDamageThreshold.Value) { return false; } if ((Object)(object)attack.collider == (Object)null) { return true; } if ((int)attack.attackType == 64 || (int)attack.attackType == 0) { return true; } if ((attack.attackType & 2) != 0 || (attack.attackType & 8) > 0) { return IsRadialBlastHit(attack); } return EnableAttackTypeBalancing.Value && IsRadialBlastHit(attack); } private static bool IsRadialBlastHit(Attack attack) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)attack.collider == (Object)null) { return true; } Vector3 val = attack.collider.ClosestPoint(attack.origin); Vector3 val2 = val - attack.origin; return ((Vector3)(ref val2)).sqrMagnitude > 0.04f; } private static bool IsExplosiveSourceCollider(Collider collider) { if ((Object)(object)collider == (Object)null) { return false; } Transform val = ((Component)collider).transform; for (int i = 0; i < 12; i++) { if (!((Object)(object)val != (Object)null)) { break; } string text = ((Object)val).name.ToLowerInvariant(); if (text.Contains("grenade") || text.Contains("mine") || text.Contains("bomb") || text.Contains("explosive") || text.Contains("blast") || text.Contains("projectile") || text.Contains("detonat")) { return true; } Type il2CppType = ((Object)val).GetIl2CppType(); string text2 = ((il2CppType != null) ? il2CppType.FullName : null) ?? string.Empty; if (text2.Contains("RigidbodyProjectile") || text2.Contains("SimpleExplosionForce") || text2.Contains("Arena_Bomb")) { return true; } val = val.parent; } return false; } private Vector3 GetBlastOrigin(PlayerDamageReceiver receiver, Attack attack) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (attack.origin != Vector3.zero) { return attack.origin; } return GetAttackPoint(receiver, attack); } public void ApplyRadialBlast(Vector3 origin, float blastRadius, float blastDamage) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) if (!EnableBlastLimbDamage.Value || origin == Vector3.zero) { return; } float unscaledTime = Time.unscaledTime; Vector3 val = origin - _lastRadialBlastDedupeOrigin; if (((Vector3)(ref val)).sqrMagnitude < 0.01f && unscaledTime - _lastRadialBlastDedupeTime < 0.12f) { return; } _lastRadialBlastDedupeTime = unscaledTime; _lastRadialBlastDedupeOrigin = origin; float num = ((blastRadius > 0.1f) ? blastRadius : ExplosionRadius.Value); float damage = ((blastDamage > 0f) ? blastDamage : ExplosionDamageThreshold.Value); float radiusSquared = num * num; Attack val2 = null; val2.damage = damage; val2.origin = origin; val2.attackType = (AttackType)2; HashSet hashSet = CollectBlastCandidateRigs(); foreach (RigManager item in hashSet) { if ((Object)(object)item == (Object)null || IsRigLimbDamageBlocked(item) || !IsRigWithinBlastRadius(item, origin, radiusSquared)) { continue; } EnsureRigInitialized(item); ApplyExplosionDamage(item, val2, origin, num); if (IsRemotePlayerRig(item)) { if (TryGetPlayerIdForRig(item, out var playerId)) { BroadcastPredictedState(playerId, item); } } else if ((Object)(object)item == (Object)(object)Player.RigManager) { SyncFullState(); } } } private HashSet CollectBlastCandidateRigs() { HashSet hashSet = new HashSet(); if ((Object)(object)Player.RigManager != (Object)null) { hashSet.Add(Player.RigManager); } foreach (NetworkPlayer player in NetworkPlayer.Players) { object obj; if (player == null) { obj = null; } else { RigRefs rigRefs = player.RigRefs; obj = ((rigRefs != null) ? rigRefs.RigManager : null); } RigManager val = (RigManager)obj; if ((Object)(object)val != (Object)null) { hashSet.Add(val); } } foreach (RigManager trackedRig in _trackedRigs) { if ((Object)(object)trackedRig != (Object)null) { hashSet.Add(trackedRig); } } return hashSet; } private bool IsRigWithinBlastRadius(RigManager rigManager, Vector3 origin, float radiusSquared) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_0096: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) object obj; if (rigManager == null) { obj = null; } else { Avatar avatar = rigManager.avatar; obj = ((avatar != null) ? avatar.animator : null); } if ((Object)obj == (Object)null) { return false; } Transform boneTransform = rigManager.avatar.animator.GetBoneTransform((HumanBodyBones)0); Vector3 val; if ((Object)(object)boneTransform != (Object)null) { val = boneTransform.position - origin; if (((Vector3)(ref val)).sqrMagnitude <= radiusSquared) { return true; } } Transform boneTransform2 = rigManager.avatar.animator.GetBoneTransform((HumanBodyBones)8); if ((Object)(object)boneTransform2 != (Object)null) { val = boneTransform2.position - origin; if (((Vector3)(ref val)).sqrMagnitude <= radiusSquared) { return true; } } Transform boneTransform3 = rigManager.avatar.animator.GetBoneTransform((HumanBodyBones)10); if ((Object)(object)boneTransform3 != (Object)null) { val = boneTransform3.position - origin; if (((Vector3)(ref val)).sqrMagnitude <= radiusSquared) { return true; } } for (int i = 0; i < DamageBones.Length; i++) { Transform boneTransform4 = rigManager.avatar.animator.GetBoneTransform(DamageBones[i]); if (!((Object)(object)boneTransform4 == (Object)null)) { val = boneTransform4.position - origin; if (((Vector3)(ref val)).sqrMagnitude <= radiusSquared) { return true; } } } return false; } private void ApplyExplosionDamage(RigManager rm, Attack attack, Vector3 origin, float? blastRadiusOverride = null) { //IL_0099: 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_00bc: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: 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_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null || IsRigLimbDamageBlocked(rm)) { return; } float num = Mathf.Max(0.1f, blastRadiusOverride ?? ExplosionRadius.Value); float num2 = num * num; float num3 = attack.damage * DamageMultiplier.Value; HumanBodyBones[] damageBones = DamageBones; HumanBodyBones[] array = damageBones; foreach (HumanBodyBones val in array) { Transform boneTransform = rm.avatar.animator.GetBoneTransform(val); if (!((Object)(object)boneTransform == (Object)null) && !(boneTransform.localScale == Vector3.zero)) { float num4 = Vector3.SqrMagnitude(boneTransform.position - origin); if (!(num4 > num2)) { float num5 = 1f - Mathf.Clamp01(Mathf.Sqrt(num4) / num); float damage = num3 * Mathf.Lerp(0.35f, 1f, num5); OnBoneHit(rm, val, damage, origin); } } } } private Vector3 GetAttackPoint(PlayerDamageReceiver receiver, Attack attack) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)attack.collider != (Object)null) { return attack.collider.ClosestPoint(attack.origin); } Transform transform = ((Component)receiver).transform; if ((Object)(object)transform != (Object)null) { return transform.position; } return attack.origin; } private bool TryGetBoneFromCollider(RigManager rm, Collider collider, Vector3 hitPoint, out HumanBodyBones bone) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) bone = (HumanBodyBones)55; if ((Object)(object)collider == (Object)null) { return false; } if (_colliderBoneMap.TryGetValue(rm, out var value) && value.TryGetValue(collider, out bone)) { return ResolveColliderMappedBone(rm, collider, bone, hitPoint, out bone); } if (TryGetBoneFromTransform(rm, ((Component)collider).transform, out bone)) { return ResolveColliderMappedBone(rm, collider, bone, hitPoint, out bone); } return TryGetNearestExtremityBone(rm, hitPoint, out bone) || TryGetNearestBone(rm, hitPoint, out bone); } private HumanBodyBones BodyPartToBone(BodyPart bodyPart) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected I4, but got Unknown //IL_0053: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) switch ((int)bodyPart) { case 0: case 1: return (HumanBodyBones)10; case 2: case 3: return (HumanBodyBones)7; case 4: return (HumanBodyBones)0; case 5: return (HumanBodyBones)13; case 6: return (HumanBodyBones)15; case 7: return (HumanBodyBones)17; case 8: return (HumanBodyBones)14; case 9: return (HumanBodyBones)16; case 10: return (HumanBodyBones)18; case 11: return (HumanBodyBones)1; case 12: return (HumanBodyBones)3; case 13: return (HumanBodyBones)5; case 14: return (HumanBodyBones)2; case 15: return (HumanBodyBones)4; case 16: return (HumanBodyBones)6; default: return (HumanBodyBones)55; } } private bool TryGetBoneFromHit(RigManager rm, RaycastHit hit, out HumanBodyBones bone) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) bone = (HumanBodyBones)55; if (_colliderBoneMap.TryGetValue(rm, out var value) && value.TryGetValue(((RaycastHit)(ref hit)).collider, out bone)) { return ResolveColliderMappedBone(rm, ((RaycastHit)(ref hit)).collider, bone, ((RaycastHit)(ref hit)).point, out bone); } if (TryGetBoneFromTransform(rm, ((Component)((RaycastHit)(ref hit)).collider).transform, out bone)) { return ResolveColliderMappedBone(rm, ((RaycastHit)(ref hit)).collider, bone, ((RaycastHit)(ref hit)).point, out bone); } return TryGetNearestExtremityBone(rm, ((RaycastHit)(ref hit)).point, out bone) || TryGetNearestBone(rm, ((RaycastHit)(ref hit)).point, out bone); } private bool TryGetBoneFromTransform(RigManager rm, Transform source, out HumanBodyBones bone) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected I4, but got Unknown bone = (HumanBodyBones)55; if ((Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null || (Object)(object)source == (Object)null) { return false; } Transform val = source; while ((Object)(object)val != (Object)null) { HumanBodyBones[] damageBones = DamageBones; HumanBodyBones[] array = damageBones; foreach (HumanBodyBones val2 in array) { Transform boneTransform = rm.avatar.animator.GetBoneTransform(val2); if ((Object)(object)boneTransform == (Object)(object)val) { bone = (HumanBodyBones)(int)val2; return true; } } val = val.parent; } return false; } private bool TryGetNearestBone(RigManager rm, Vector3 point, out HumanBodyBones bone) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected I4, but got Unknown //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) if (TryGetNearestExtremityBone(rm, point, out bone)) { return true; } bone = (HumanBodyBones)55; if ((Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return false; } float num = float.MaxValue; float num2 = 0.5625f; float num3 = 0.122499995f; HumanBodyBones[] damageBones = DamageBones; HumanBodyBones[] array = damageBones; foreach (HumanBodyBones val in array) { Transform boneTransform = rm.avatar.animator.GetBoneTransform(val); if (!((Object)(object)boneTransform == (Object)null) && !(boneTransform.localScale == Vector3.zero)) { Vector3 boneSegmentPoint = GetBoneSegmentPoint(rm, val, boneTransform); float num4 = DistanceToSegmentSquared(point, boneTransform.position, boneSegmentPoint); if (TorsoBones.Contains(val)) { num4 += num3; } if (num4 < num) { num = num4; bone = (HumanBodyBones)(int)val; } } } if ((int)bone == 55 || num > num2) { bone = (HumanBodyBones)55; return false; } if (CoreNearestExcludeBones.Contains(bone) && point != Vector3.zero && !IsPointNearBone(rm, bone, point, 0.4f)) { return TryGetNearestExtremityBone(rm, point, out bone); } return true; } private bool TryGetNearestExtremityBone(RigManager rm, Vector3 point, out HumanBodyBones bone) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00d4: Expected I4, but got Unknown bone = (HumanBodyBones)55; if ((Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return false; } float num = float.MaxValue; float num2 = 0.5625f; HumanBodyBones[] damageBones = DamageBones; HumanBodyBones[] array = damageBones; foreach (HumanBodyBones val in array) { if (CoreNearestExcludeBones.Contains(val)) { continue; } Transform cachedBoneTransform = GetCachedBoneTransform(rm, val); if (!((Object)(object)cachedBoneTransform == (Object)null) && !(cachedBoneTransform.localScale == Vector3.zero)) { Vector3 boneSegmentPoint = GetBoneSegmentPoint(rm, val, cachedBoneTransform); float num3 = DistanceToSegmentSquared(point, cachedBoneTransform.position, boneSegmentPoint); if (num3 < num) { num = num3; bone = (HumanBodyBones)(int)val; } } } if ((int)bone == 55 || num > num2) { bone = (HumanBodyBones)55; return false; } return true; } private bool IsTorsoBone(HumanBodyBones bone) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 return (int)bone == 7 || (int)bone == 0; } private bool IsPointNearBone(RigManager rm, HumanBodyBones bone, Vector3 point, float maxDistance) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) Transform cachedBoneTransform = GetCachedBoneTransform(rm, bone); if ((Object)(object)cachedBoneTransform == (Object)null) { return false; } Vector3 boneSegmentPoint = GetBoneSegmentPoint(rm, bone, cachedBoneTransform); float num = maxDistance * maxDistance; return DistanceToSegmentSquared(point, cachedBoneTransform.position, boneSegmentPoint) <= num; } private bool ResolveColliderMappedBone(RigManager rm, Collider collider, HumanBodyBones mappedBone, Vector3 hitPoint, out HumanBodyBones bone) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Expected I4, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) bone = (HumanBodyBones)(int)mappedBone; if (_colliderBoneDistanceMap.TryGetValue(rm, out var value) && value.TryGetValue(collider, out var value2) && value2 > 5f) { return TryGetNearestExtremityBone(rm, hitPoint, out bone) || TryGetNearestBone(rm, hitPoint, out bone); } if (IsTorsoBone(bone) && hitPoint != Vector3.zero && !IsPointNearBone(rm, bone, hitPoint, 0.4f)) { return TryGetNearestExtremityBone(rm, hitPoint, out bone); } return true; } private Vector3 GetBoneSegmentPoint(RigManager rm, HumanBodyBones bone, Transform boneTransform) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 //IL_0021: 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_0058: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) HumanBodyBones primaryChildBone = GetPrimaryChildBone(bone); if ((int)primaryChildBone != 55) { Transform boneTransform2 = rm.avatar.animator.GetBoneTransform(primaryChildBone); if ((Object)(object)boneTransform2 != (Object)null) { return boneTransform2.position; } } if ((Object)(object)boneTransform.parent != (Object)null) { return boneTransform.parent.position; } return boneTransform.position; } private HumanBodyBones GetPrimaryChildBone(HumanBodyBones bone) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected I4, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0083: Unknown result type (might be due to invalid IL or missing references) return (HumanBodyBones)((int)bone switch { 13 => 15, 15 => 17, 14 => 16, 16 => 18, 1 => 3, 3 => 5, 2 => 4, 4 => 6, 0 => 7, 7 => 10, _ => 55, }); } private float DistanceToSegmentSquared(Vector3 point, Vector3 start, Vector3 end) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) Vector3 val = end - start; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude <= Mathf.Epsilon) { return Vector3.SqrMagnitude(point - start); } float num = Mathf.Clamp01(Vector3.Dot(point - start, val) / sqrMagnitude); Vector3 val2 = start + val * num; return Vector3.SqrMagnitude(point - val2); } private float GetHierarchyDistance(Transform source, Transform ancestor) { if ((Object)(object)source == (Object)null || (Object)(object)ancestor == (Object)null) { return float.MaxValue; } float num = 0f; Transform val = source; while ((Object)(object)val != (Object)null) { if ((Object)(object)val == (Object)(object)ancestor) { return num; } num += 1f; val = val.parent; } return float.MaxValue; } private float GetMinLimbHealthFloor(float avatarBase) { return Mathf.Max(8f, avatarBase * 0.15f); } private float GetMaxHealthForBone(RigManager rm, HumanBodyBones bone) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) float avatarHealthBase = GetAvatarHealthBase(rm); return Mathf.Max(GetMinLimbHealthFloor(avatarHealthBase), avatarHealthBase * GetBoneHealthScale(bone)); } private void InvalidateAvatarHealthCache(RigManager rm) { if (!((Object)(object)rm == (Object)null)) { _avatarHealthBaseCache.Remove(rm); _avatarHealthHashCache.Remove(rm); } } private float GetAvatarHealthBase(RigManager rm) { if ((Object)(object)rm == (Object)null) { return Mathf.Max(1f, MaxLimbHealth.Value); } int num = (((Object)(object)rm.avatar != (Object)null) ? ((Object)rm.avatar).GetHashCode() : 0); if (_avatarHealthBaseCache.TryGetValue(rm, out var value) && _avatarHealthHashCache.TryGetValue(rm, out var value2) && value2 == num && value > 0f) { return value; } float num2 = ResolveAvatarHealthBase(rm); _avatarHealthBaseCache[rm] = num2; _avatarHealthHashCache[rm] = num; return num2; } private float ResolveAvatarHealthBase(RigManager rm) { return AvatarHealthResolver.Resolve(rm, MaxLimbHealth.Value); } private void RefreshLimbMaxHealth(RigManager rm) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null || !_playersHealth.TryGetValue(rm, out var value)) { return; } HumanBodyBones[] damageBones = DamageBones; HumanBodyBones[] array = damageBones; foreach (HumanBodyBones val in array) { if (value.TryGetValue(val, out var value2) && value2 > 0f && !IsBoneGone(rm, val)) { value[val] = GetMaxHealthForBone(rm, val); } } } private void UpdateLimbPenaltyFlag(RigManager rm) { UpdateRigMissingLimbsFlag(rm); } public void TrackRig(RigManager rm) { if ((Object)(object)rm != (Object)null) { _trackedRigs.Add(rm); } } private void PruneTrackedRigs() { if (_trackedRigs.Count == 0) { return; } RigManager[] array = _trackedRigs.ToArray(); foreach (RigManager val in array) { if ((Object)(object)val == (Object)null) { _trackedRigs.Remove(val); _avatarHealthBaseCache.Remove(val); _avatarHealthHashCache.Remove(val); _rigWasDead.Remove(val); _playersHealth.Remove(val); _colliderBoneMap.Remove(val); _colliderBoneDistanceMap.Remove(val); _originalScales.Remove(val); _lastHitEffectTimes.Remove(val); _lastStumpBloodEffectTimes.Remove(val); _stumpBloodStartTimes.Remove(val); _lastAvatarHashes.Remove(val); _rigCache.Remove(val); } } } private RigRuntimeCache GetOrCreateRigCache(RigManager rm) { if (!_rigCache.TryGetValue(rm, out var value)) { value = new RigRuntimeCache(); _rigCache[rm] = value; } return value; } private void ResetLimbDamageBlockCache(RigManager rm) { if (!((Object)(object)rm == (Object)null) && _rigCache.TryGetValue(rm, out var value)) { value.LimbDamageBlocked = false; value.LimbDamageBlockFrame = -9999; } } private static int GetDamageBoneIndex(HumanBodyBones bone) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (BoneToIndexMap.TryGetValue(bone, out var value)) { return value; } return -1; } private void RebuildLimbGoneFlags(RigManager rm) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected I4, but got Unknown if ((Object)(object)rm == (Object)null) { return; } RigRuntimeCache orCreateRigCache = GetOrCreateRigCache(rm); LimbGoneMask limbGoneMask = LimbGoneMask.None; Transform[] boneTransforms = orCreateRigCache.BoneTransforms; if (boneTransforms == null) { orCreateRigCache.LimbGoneFlags = limbGoneMask; orCreateRigCache.HasMissingLimbs = false; return; } for (int i = 0; i < boneTransforms.Length; i++) { Transform val = boneTransforms[i]; if (!((Object)(object)val == (Object)null) && !(val.localScale != Vector3.zero)) { HumanBodyBones val2 = DamageBones[i]; HumanBodyBones val3 = val2; switch ((int)val3) { case 13: case 15: case 17: limbGoneMask |= LimbGoneMask.LeftArm; break; case 14: case 16: case 18: limbGoneMask |= LimbGoneMask.RightArm; break; case 1: case 3: case 5: limbGoneMask |= LimbGoneMask.LeftLeg; break; case 2: case 4: case 6: limbGoneMask |= LimbGoneMask.RightLeg; break; case 7: limbGoneMask |= LimbGoneMask.Spine; break; case 0: limbGoneMask |= LimbGoneMask.Hips; break; } } } orCreateRigCache.LimbGoneFlags = limbGoneMask; orCreateRigCache.HasMissingLimbs = (limbGoneMask & (LimbGoneMask.LeftArm | LimbGoneMask.RightArm | LimbGoneMask.LeftLeg | LimbGoneMask.RightLeg)) != 0; } private HumanBodyBones[] GetAvatarDamageBones(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return DamageBones; } List list = new List(DamageBones.Length); for (int i = 0; i < DamageBones.Length; i++) { Transform boneTransform = rm.avatar.animator.GetBoneTransform(DamageBones[i]); if ((Object)(object)boneTransform != (Object)null) { list.Add(DamageBones[i]); } } if (list.Count == 0) { return DamageBones; } return list.ToArray(); } private void RebuildBoneCache(RigManager rm) { if (!((Object)(object)rm == (Object)null) && !((Object)(object)rm.avatar == (Object)null) && !((Object)(object)rm.avatar.animator == (Object)null)) { RigRuntimeCache orCreateRigCache = GetOrCreateRigCache(rm); orCreateRigCache.AvatarHash = ((Object)rm.avatar).GetHashCode(); if (orCreateRigCache.BoneTransforms == null || orCreateRigCache.BoneTransforms.Length != DamageBones.Length) { orCreateRigCache.BoneTransforms = (Transform[])(object)new Transform[DamageBones.Length]; } for (int i = 0; i < DamageBones.Length; i++) { orCreateRigCache.BoneTransforms[i] = rm.avatar.animator.GetBoneTransform(DamageBones[i]); } RebuildLimbGoneFlags(rm); } } private Transform GetCachedBoneTransform(RigManager rm, HumanBodyBones bone) { //IL_0032: 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) if ((Object)(object)rm == (Object)null) { return null; } if (_rigCache.TryGetValue(rm, out var value) && value.BoneTransforms != null) { int damageBoneIndex = GetDamageBoneIndex(bone); if (damageBoneIndex >= 0) { Transform val = value.BoneTransforms[damageBoneIndex]; if ((Object)(object)val != (Object)null) { return val; } } } Avatar avatar = rm.avatar; object result; if (avatar == null) { result = null; } else { Animator animator = avatar.animator; result = ((animator != null) ? animator.GetBoneTransform(bone) : null); } return (Transform)result; } public bool IsRigLimbDamageBlocked(RigManager rm) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Invalid comparison between Unknown and I4 if ((Object)(object)rm == (Object)null || (Object)(object)rm.health == (Object)null) { return false; } RigRuntimeCache orCreateRigCache = GetOrCreateRigCache(rm); if (Time.frameCount - orCreateRigCache.LimbDamageBlockFrame < 30) { return orCreateRigCache.LimbDamageBlocked; } bool flag = (int)rm.health.healthMode == 0; float max_Health = rm.health.max_Health; if (!flag && (max_Health >= 9999f || float.IsPositiveInfinity(max_Health))) { flag = true; } orCreateRigCache.LimbDamageBlocked = flag; orCreateRigCache.LimbDamageBlockFrame = Time.frameCount; return flag; } private bool RigHasDismemberment(RigManager rm) { if ((Object)(object)rm == (Object)null) { return false; } if (_rigCache.TryGetValue(rm, out var value)) { return value.LimbGoneFlags != LimbGoneMask.None; } return false; } private void EnforceDismemberedBones() { //IL_00f1: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) if (_trackedRigs.Count == 0 || _rigCache.Count == 0) { return; } RigManager[] array = _trackedRigs.ToArray(); foreach (RigManager val in array) { if ((Object)(object)val == (Object)null || (Object)(object)val.avatar == (Object)null || (Object)(object)val.avatar.animator == (Object)null || !_rigCache.TryGetValue(val, out var value) || !value.HasMissingLimbs || !_playersHealth.TryGetValue(val, out var value2)) { continue; } Transform[] boneTransforms = value.BoneTransforms; if (boneTransforms == null) { continue; } for (int j = 0; j < boneTransforms.Length && j < DamageBones.Length; j++) { Transform val2 = boneTransforms[j]; if (!((Object)(object)val2 == (Object)null) && !(val2.localScale == Vector3.zero)) { HumanBodyBones key = DamageBones[j]; if (value2.TryGetValue(key, out var value3) && value3 <= 0f) { val2.localScale = Vector3.zero; } } } } } private void EnforceAppliedStates() { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) if (_appliedStateMasks.Count == 0) { return; } int num = 0; KeyValuePair[] array = _appliedStateMasks.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair keyValuePair = array[i]; byte key = keyValuePair.Key; uint value = keyValuePair.Value; if (value == 0 || !TryResolvePlayerRig(key, out var rigManager) || (Object)(object)rigManager == (Object)null || (Object)(object)rigManager.avatar == (Object)null || (Object)(object)rigManager.avatar.animator == (Object)null) { continue; } for (int j = 0; j < DamageBones.Length; j++) { if ((value & (uint)(1 << j)) != 0) { Transform cachedBoneTransform = GetCachedBoneTransform(rigManager, DamageBones[j]); if ((Object)(object)cachedBoneTransform != (Object)null && cachedBoneTransform.localScale != Vector3.zero) { cachedBoneTransform.localScale = Vector3.zero; num++; } } } } if (num > 0) { MelonLogger.Warning($"[DeadPiece] EnforceAppliedStates: re-applied {num} bone scales that were reset by external system"); } } private void EnforceInvincibleRigsForAllTracked() { if (_trackedRigs.Count == 0) { return; } RigManager[] array = _trackedRigs.ToArray(); foreach (RigManager val in array) { if (!((Object)(object)val == (Object)null) && IsRigLimbDamageBlocked(val) && RigHasDismemberment(val) && !IsRemotePlayerRig(val)) { ResetLimbStats(val, restoreBody: true); if ((Object)(object)val == (Object)(object)Player.RigManager) { UpdateLimbPenaltyFlag(val); SetLocalMetadata(""); SyncFullState(); } } } } private void InvalidateRigCache(RigManager rm) { if (!((Object)(object)rm == (Object)null) && _rigCache.TryGetValue(rm, out var value)) { value.Initialized = false; value.LimbDamageBlocked = false; value.LimbDamageBlockFrame = -9999; value.BoneTransforms = null; value.HasMissingLimbs = false; value.LimbGoneFlags = LimbGoneMask.None; value.VisualDamage = null; } } private void UpdateRigMissingLimbsFlag(RigManager rm) { if (!((Object)(object)rm == (Object)null)) { RebuildLimbGoneFlags(rm); } } private VisualDamageController GetVisualDamageController(RigManager rm) { if ((Object)(object)rm == (Object)null) { return null; } RigRuntimeCache orCreateRigCache = GetOrCreateRigCache(rm); if ((Object)(object)orCreateRigCache.VisualDamage != (Object)null) { return orCreateRigCache.VisualDamage; } if ((Object)(object)rm.avatar != (Object)null) { orCreateRigCache.VisualDamage = ((Component)rm.avatar).GetComponentInChildren(true); } return orCreateRigCache.VisualDamage; } private float GetBoneHealthScale(HumanBodyBones bone) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected I4, but got Unknown switch ((int)bone) { case 1: case 2: case 3: case 4: case 5: case 6: return 0.4f; case 10: case 13: case 14: case 15: case 16: case 17: case 18: return 0.5f; case 21: case 22: return 0.35f; case 0: case 7: return 1f; default: return 1f; } } public void OnBoneHit(RigManager rm, HumanBodyBones bone, float damage, Vector3 hitPoint) { //IL_0012: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) if (IsRigLimbDamageBlocked(rm)) { return; } if (IsTorsoBone(bone) && hitPoint != Vector3.zero && !IsPointNearBone(rm, bone, hitPoint, 0.4f)) { TryGetNearestExtremityBone(rm, hitPoint, out bone); } EnsureRigInitialized(rm); if (_playersHealth.TryGetValue(rm, out var value) && value.ContainsKey(bone) && !IsBoneGone(rm, bone)) { value[bone] = Mathf.Max(0f, value[bone] - damage); TryAddVisualHit(rm, hitPoint, damage); PlayHitEffects(rm, bone, hitPoint, damage); if (value[bone] <= 0f) { DismemberLimb(rm, bone, hitPoint); } else if (hitPoint != Vector3.zero) { TryDamageNearbyEyes(rm, hitPoint, damage); } } } private void TryDamageNearbyEyes(RigManager rm, Vector3 hitPoint, float damage) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rm == (Object)null) && !(damage <= 0f)) { float radiusSq = 0.0169f; TryDamageEyeIfNear(rm, (HumanBodyBones)21, hitPoint, damage, radiusSq); TryDamageEyeIfNear(rm, (HumanBodyBones)22, hitPoint, damage, radiusSq); } } private void TryDamageEyeIfNear(RigManager rm, HumanBodyBones eyeBone, Vector3 hitPoint, float damage, float radiusSq) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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) if (IsBoneGone(rm, eyeBone) || !_playersHealth.TryGetValue(rm, out var value) || !value.ContainsKey(eyeBone)) { return; } Transform cachedBoneTransform = GetCachedBoneTransform(rm, eyeBone); if (!((Object)(object)cachedBoneTransform == (Object)null) && !(Vector3.SqrMagnitude(hitPoint - cachedBoneTransform.position) > radiusSq)) { value[eyeBone] = Mathf.Max(0f, value[eyeBone] - damage * 1.25f); if (value[eyeBone] <= 0f) { DismemberLimb(rm, eyeBone, hitPoint); } } } private void DismemberLimb(RigManager rm, HumanBodyBones bone, Vector3 hitPoint) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Invalid comparison between Unknown and I4 //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Invalid comparison between Unknown and I4 //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Invalid comparison between Unknown and I4 //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Invalid comparison between Unknown and I4 //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //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_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0230: 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_0304: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_0316: 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_027a: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0333: 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_0352: Unknown result type (might be due to invalid IL or missing references) //IL_0353: 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_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: 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_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Invalid comparison between Unknown and I4 //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_0429: Unknown result type (might be due to invalid IL or missing references) //IL_053c: Unknown result type (might be due to invalid IL or missing references) //IL_053f: Invalid comparison between Unknown and I4 //IL_0523: Unknown result type (might be due to invalid IL or missing references) //IL_0526: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_0472: Invalid comparison between Unknown and I4 //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_0435: Unknown result type (might be due to invalid IL or missing references) //IL_0541: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Invalid comparison between Unknown and I4 //IL_0446: Unknown result type (might be due to invalid IL or missing references) //IL_0449: Unknown result type (might be due to invalid IL or missing references) //IL_0546: Unknown result type (might be due to invalid IL or missing references) //IL_0549: Invalid comparison between Unknown and I4 //IL_0565: Unknown result type (might be due to invalid IL or missing references) //IL_0568: Invalid comparison between Unknown and I4 //IL_056a: Unknown result type (might be due to invalid IL or missing references) //IL_056d: Invalid comparison between Unknown and I4 //IL_056f: Unknown result type (might be due to invalid IL or missing references) //IL_0572: Invalid comparison between Unknown and I4 if ((Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return; } bool wasLeftLegGone = IsLeftLegGone(rm); bool wasRightLegGone = IsRightLegGone(rm); Transform cachedBoneTransform = GetCachedBoneTransform(rm, bone); if ((Object)(object)cachedBoneTransform == (Object)null || cachedBoneTransform.localScale == Vector3.zero) { return; } Transform val = null; Transform val2 = null; Vector3 localScale = Vector3.one; Vector3 localScale2 = Vector3.one; if ((int)bone == 10) { val = rm.avatar.animator.GetBoneTransform((HumanBodyBones)21); val2 = rm.avatar.animator.GetBoneTransform((HumanBodyBones)22); if ((Object)(object)val != (Object)null) { localScale = val.localScale; } if ((Object)(object)val2 != (Object)null) { localScale2 = val2.localScale; } } if (!_originalScales.ContainsKey(rm)) { _originalScales[rm] = new Dictionary(); } if (!_originalScales[rm].ContainsKey(bone) || _originalScales[rm][bone] == Vector3.zero) { _originalScales[rm][bone] = cachedBoneTransform.localScale; } cachedBoneTransform.localScale = Vector3.zero; if ((Object)(object)val != (Object)null) { val.localScale = localScale; } if ((Object)(object)val2 != (Object)null) { val2.localScale = localScale2; } if ((int)bone == 21 || (int)bone == 22) { SpawnEyePatch(cachedBoneTransform.position, cachedBoneTransform.forward); } if ((int)bone == 10 && hitPoint != Vector3.zero) { Transform boneTransform = rm.avatar.animator.GetBoneTransform((HumanBodyBones)21); Transform boneTransform2 = rm.avatar.animator.GetBoneTransform((HumanBodyBones)22); if ((Object)(object)boneTransform != (Object)null && boneTransform.localScale != Vector3.zero && Vector3.Distance(hitPoint, boneTransform.position) < 0.15f) { boneTransform.localScale = Vector3.zero; SpawnEyePatch(boneTransform.position, boneTransform.forward); } if ((Object)(object)boneTransform2 != (Object)null && boneTransform2.localScale != Vector3.zero && Vector3.Distance(hitPoint, boneTransform2.position) < 0.15f) { boneTransform2.localScale = Vector3.zero; SpawnEyePatch(boneTransform2.position, boneTransform2.forward); } } MarkStumpBloodStarted(rm, bone); SpawnDamageVolume(rm, bone, (hitPoint == Vector3.zero) ? cachedBoneTransform.position : hitPoint); TryAddVisualCut(rm, (hitPoint == Vector3.zero) ? cachedBoneTransform.position : hitPoint); TryApplyBloodImpactAtBone(rm, bone, (hitPoint == Vector3.zero) ? cachedBoneTransform.position : hitPoint, Mathf.Max(5f, GetMaxHealthForBone(rm, bone) * 0.25f), GetBloodColor(rm)); PlayDismemberEffects((hitPoint == Vector3.zero) ? cachedBoneTransform.position : hitPoint, GetBloodColor(rm)); if (FatalBones.Contains(bone)) { SpawnBloodStream(rm, bone, (hitPoint == Vector3.zero) ? cachedBoneTransform.position : hitPoint); } else { SpawnBloodStream(rm, bone, cachedBoneTransform.position); } ApplySecondLegRagdoll(rm, bone, wasLeftLegGone, wasRightLegGone); RebuildLimbGoneFlags(rm); if ((Object)(object)rm == (Object)(object)Player.RigManager && (IsLeftLegBone(bone) || IsRightLegBone(bone)) && IsBothLegsGone(rm)) { AllowLocalNoLegRagdollFromCurrentSever(); } if (FatalBones.Contains(bone)) { if ((int)bone == 10) { ApplyHeadSeverEffects(rm, (hitPoint == Vector3.zero) ? cachedBoneTransform.position : hitPoint); SpawnHeadProp(cachedBoneTransform, hitPoint, GetBloodColor(rm)); } if ((Object)(object)rm == (Object)(object)Player.RigManager) { SyncFullState(); } if ((int)bone == 10 && (Object)(object)rm == (Object)(object)Player.RigManager) { if (AreAllLimbsGone(rm) && IsBoneGone(rm, (HumanBodyBones)7) && IsBoneGone(rm, (HumanBodyBones)0)) { KillRig(rm); } else { _delayedDeathRm = rm; _delayedDeathTime = Time.time + 2f; } } else if ((Object)(object)rm == (Object)(object)Player.RigManager) { KillRig(rm); } } else if ((Object)(object)rm == (Object)(object)Player.RigManager) { if (_playersHealth.TryGetValue(rm, out var value)) { value[bone] = 0f - GetMaxHealthForBone(rm, bone); } UpdateLimbPenaltyFlag(rm); if ((int)bone == 13 || (int)bone == 15 || (int)bone == 17) { SetHandUsable(Player.LeftHand, usable: false); } else if ((int)bone == 14 || (int)bone == 16 || (int)bone == 18) { SetHandUsable(Player.RightHand, usable: false); } SyncFullState(); } if ((Object)(object)rm == (Object)(object)Player.RigManager && AreAllLimbsGone(rm)) { KillRig(rm); } if ((Object)(object)rm == (Object)(object)Player.RigManager && EnableVrEyeBlindness.Value) { UpdateVrEyeBlindness(rm); } } private void RestoreRigMeshes(RigManager rm) { if ((Object)(object)rm == (Object)null) { return; } try { Il2CppArrayBase componentsInChildren = ((Component)rm.avatar).GetComponentsInChildren(true); foreach (Renderer item in componentsInChildren) { if ((Object)(object)item != (Object)null) { item.enabled = true; } } } catch (Exception ex) { MelonLogger.Warning("RestoreRigMeshes failed: " + ex.Message); } } private bool IsRemotePlayerRig(RigManager rm) { if (!NetworkInfo.HasServer || (Object)(object)rm == (Object)null) { return false; } NetworkPlayer val = default(NetworkPlayer); if (NetworkPlayerManager.TryGetPlayer(rm, ref val)) { return !val.NetworkEntity.IsOwner; } return (Object)(object)rm != (Object)(object)Player.RigManager; } public bool TryGetPlayerIdForRig(RigManager rm, out byte playerId) { playerId = 0; if ((Object)(object)rm == (Object)null) { return false; } if ((Object)(object)rm == (Object)(object)Player.RigManager && PlayerIDManager.LocalID != null) { playerId = PlayerIDManager.LocalSmallID; return true; } NetworkPlayer val = default(NetworkPlayer); if (NetworkPlayerManager.TryGetPlayer(rm, ref val) && ((val != null) ? val.PlayerID : null) != null) { playerId = val.PlayerID.SmallID; return true; } if (NetworkInfo.HasServer) { RigRefs val2 = default(RigRefs); foreach (PlayerID playerID in PlayerIDManager.PlayerIDs) { if (playerID != null) { if (playerID.IsMe && (Object)(object)rm == (Object)(object)Player.RigManager) { playerId = playerID.SmallID; return true; } if (PlayerRepUtilities.TryGetReferences(playerID.SmallID, ref val2) && (Object)(object)((val2 != null) ? val2.RigManager : null) != (Object)null && (Object)(object)val2.RigManager == (Object)(object)rm) { playerId = playerID.SmallID; return true; } } } } MelonLogger.Warning("[DeadPiece] TryGetPlayerIdForRig FAILED for rig " + ((rm != null) ? ((Object)rm).name : null) + " — no matching player found"); return false; } public bool TrySendLimbHitForLocalAttack(PlayerDamageReceiver receiver, Attack attack) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_0126: Unknown result type (might be due to invalid IL or missing references) if (!NetworkInfo.HasServer || (Object)(object)receiver == (Object)null || attack == null || attack.damage <= 0f) { return false; } Health health = receiver.health; RigManager val = ((health != null) ? health._rigManager : null); if ((Object)(object)val == (Object)null) { return false; } NetworkPlayer val2 = default(NetworkPlayer); if (NetworkPlayerManager.TryGetPlayer(val, ref val2) && val2.NetworkEntity.IsOwner) { return false; } if (!TryResolveAttackBone(val, receiver, attack, GetAttackPoint(receiver, attack), out var bone)) { return false; } float num = CalculateAttackDamage(attack, val, bone); if (num <= 0f) { num = attack.damage; } if (num <= 0f) { return false; } if (!BoneToIndexMap.TryGetValue(bone, out var value)) { return false; } if (!TryGetPlayerIdForRig(val, out var playerId)) { return false; } NetworkSync.SendLimbHit(playerId, (byte)value, num, GetAttackPoint(receiver, attack)); return true; } private void ProcessRemotePlayerAttack(RigManager rigManager, PlayerDamageReceiver receiver, Attack attack, float originalDamage) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rigManager == (Object)null || attack == null) { MelonLogger.Warning($"[DeadPiece] ProcessRemotePlayerAttack: null rig={(Object)(object)rigManager == (Object)null} attack={attack == null}"); return; } EnsureRigInitialized(rigManager); Vector3 attackPoint = GetAttackPoint(receiver, attack); HumanBodyBones bone; if (IsExplosionLikeAttack(attack)) { Vector3 blastOrigin = GetBlastOrigin(receiver, attack); ApplyExplosionDamage(rigManager, attack, blastOrigin); if (TryGetPlayerIdForRig(rigManager, out var playerId)) { BroadcastPredictedState(playerId, rigManager); } } else if (!TryResolveAttackBone(rigManager, receiver, attack, attackPoint, out bone)) { MelonLogger.Warning($"[DeadPiece] ProcessRemotePlayerAttack: TryResolveAttackBone FAILED rig={((Object)rigManager).name} bodyPart={receiver.bodyPart} collider={(Object)(object)attack.collider != (Object)null} attackPoint={attackPoint}"); } else { float num = CalculateAttackDamage(attack, rigManager, bone); if (num <= 0f) { num = originalDamage; } if (num <= 0f) { MelonLogger.Warning($"[DeadPiece] ProcessRemotePlayerAttack: damage=0 after fallback originalDamage={originalDamage}"); } else { ProcessRemoteLimbHit(rigManager, bone, num, attackPoint); } } } private bool TryResolveAttackBone(RigManager rigManager, PlayerDamageReceiver receiver, Attack attack, Vector3 attackPoint, out HumanBodyBones bone) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected I4, but got Unknown //IL_0033: 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_005f: Unknown result type (might be due to invalid IL or missing references) bone = (HumanBodyBones)(int)BodyPartToBone(receiver.bodyPart); if ((int)bone == 55 && (Object)(object)attack.collider != (Object)null) { TryGetBoneFromCollider(rigManager, attack.collider, attackPoint, out bone); } if ((int)bone == 55 && !TryGetNearestExtremityBone(rigManager, attackPoint, out bone)) { TryGetNearestBone(rigManager, attackPoint, out bone); } return (int)bone != 55; } private void ProcessRemoteLimbHit(RigManager rigManager, HumanBodyBones bone, float damage, Vector3 hitPoint) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) int value; if (!TryGetPlayerIdForRig(rigManager, out var playerId)) { MelonLogger.Warning("[DeadPiece] ProcessRemoteLimbHit: TryGetPlayerIdForRig FAILED for rig " + ((rigManager != null) ? ((Object)rigManager).name : null)); } else if (!BoneToIndexMap.TryGetValue(bone, out value)) { MelonLogger.Warning($"[DeadPiece] ProcessRemoteLimbHit: BoneToIndexMap FAILED bone={bone}"); } else { NetworkSync.SendLimbHit(playerId, (byte)value, damage, hitPoint); } } private void BroadcastPredictedState(byte targetPlayerId, RigManager rigManager) { if (!((Object)(object)rigManager == (Object)null) && NetworkInfo.IsHost) { uint stateMask = GetStateMask(rigManager); byte bloodColorIndexForRig = GetBloodColorIndexForRig(rigManager); NetworkSync.SendFullState(targetPlayerId, stateMask, bloodColorIndexForRig, 0); } } public uint GetStateMask(RigManager rm) { if ((Object)(object)rm == (Object)null) { return 0u; } uint num = 0u; for (int i = 0; i < DamageBones.Length; i++) { if (IsBoneGone(rm, DamageBones[i])) { num |= (uint)(1 << i); } } return num; } private static uint ParseGoneMaskFromString(string value) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) uint num = 0u; if (string.IsNullOrEmpty(value)) { return num; } string[] array = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (Enum.TryParse(array[i], out HumanBodyBones result) && BoneToIndexMap.TryGetValue(result, out var value2)) { num |= (uint)(1 << value2); } } return num; } private bool ShouldApplyNetworkSequence(byte playerId, ushort sequence) { if (sequence == 0) { return true; } if (!_lastAppliedNetworkSequence.TryGetValue(playerId, out var value)) { return true; } if (sequence == value) { return false; } return (ushort)(sequence - value) < 32768; } private bool ShouldReplacePendingNetworkState(byte playerId, ushort sequence) { if (!_pendingNetworkStates.TryGetValue(playerId, out var value)) { return true; } if (sequence == 0) { return value.Sequence == 0; } if (value.Sequence == 0) { return true; } if (sequence == value.Sequence) { return false; } return (ushort)(sequence - value.Sequence) < 32768; } private void QueuePendingNetworkState(byte playerId, ushort sequence, uint goneBoneMask, bool isFallen) { if (ShouldReplacePendingNetworkState(playerId, sequence)) { _pendingNetworkStates[playerId] = new PendingNetworkState { Sequence = sequence, GoneBoneMask = goneBoneMask, IsFallen = isFallen }; } } private void RemoveRigFromCaches(RigManager rm) { if (!((Object)(object)rm == (Object)null)) { _trackedRigs.Remove(rm); _avatarHealthBaseCache.Remove(rm); _avatarHealthHashCache.Remove(rm); _rigWasDead.Remove(rm); _playersHealth.Remove(rm); _colliderBoneMap.Remove(rm); _colliderBoneDistanceMap.Remove(rm); _originalScales.Remove(rm); _lastHitEffectTimes.Remove(rm); _lastStumpBloodEffectTimes.Remove(rm); _stumpBloodStartTimes.Remove(rm); _lastAvatarHashes.Remove(rm); _rigCache.Remove(rm); _bloodColorOverrides.Remove(rm); if (TryGetPlayerIdForRig(rm, out var playerId)) { _appliedStateMasks.Remove(playerId); } _bloodColorIndexOverrides.Remove(rm); } } private void LoadBloodColorOverrides() { //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) try { PropertyInfo property = typeof(MelonUtils).GetProperty("UserDataDirectory", BindingFlags.Static | BindingFlags.Public); string path = Path.Combine((string)property.GetValue(null), "DeadPiece", "BloodColors.txt"); if (!File.Exists(path)) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# DeadPiece Blood Color Overrides"); stringBuilder.AppendLine("# Format: AvatarName=color"); stringBuilder.AppendLine("# Colors: red, black, orange, purple, green, blue, pink, yellow, or R,G,B,A"); stringBuilder.AppendLine("# Examples:"); stringBuilder.AppendLine("# NullBody_Red=red"); stringBuilder.AppendLine("# MyRobotMod=black"); stringBuilder.AppendLine("# MyCustomAvatar=0.3,0.1,0.6,0.9"); stringBuilder.AppendLine("# Wildcards:"); stringBuilder.AppendLine("# *NullBody*=orange (contains \"NullBody\")"); stringBuilder.AppendLine("# MyMod_*=red (starts with \"MyMod_\")"); stringBuilder.AppendLine("# *Robot*=black (contains \"Robot\")"); File.WriteAllText(path, stringBuilder.ToString()); MelonLogger.Msg(ConsoleColor.Gray, "Created BloodColors.txt template"); return; } string[] array = File.ReadAllLines(path); string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim(); if (string.IsNullOrEmpty(text2) || text2.StartsWith("#")) { continue; } int num = text2.IndexOf('='); if (num < 0) { continue; } string text3 = text2.Substring(0, num).Trim().ToLowerInvariant(); string text4 = text2.Substring(num + 1).Trim().ToLowerInvariant(); if (!string.IsNullOrEmpty(text3) && !string.IsNullOrEmpty(text4)) { Color val = ParseBloodColorString(text4); if (val.a >= 0f) { _avatarBloodOverrides[text3] = val; } } } if (_avatarBloodOverrides.Count > 0) { MelonLogger.Msg($"Loaded {_avatarBloodOverrides.Count} blood color overrides"); } } catch (Exception ex) { MelonLogger.Warning("Blood color override loading failed: " + ex.Message); } } private Color ParseBloodColorString(string s) { //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031d: 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_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: 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_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) switch (s) { case "red": return new Color(0.7f, 0.02f, 0.02f, 0.9f); case "black": return new Color(0.05f, 0.05f, 0.05f, 0.9f); case "orange": return new Color(1f, 0.45f, 0.02f, 0.9f); case "purple": return new Color(0.5f, 0.02f, 0.6f, 0.9f); case "green": return new Color(0.02f, 0.55f, 0.12f, 0.9f); case "blue": return new Color(0.05f, 0.08f, 0.7f, 0.9f); case "pink": return new Color(0.95f, 0.08f, 0.55f, 0.9f); case "yellow": return new Color(0.9f, 0.85f, 0.05f, 0.9f); case "white": return Color.white; default: { string[] array = s.Split(','); if (array.Length >= 3) { float result = 0.9f; if (float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3) && float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4)) { if (array.Length >= 4) { float.TryParse(array[3], NumberStyles.Float, CultureInfo.InvariantCulture, out result); } return new Color(result2, result3, result4, result); } } return new Color(-1f, -1f, -1f, -1f); } } } private byte BloodColorToIndex(string colorName) { return colorName.ToLowerInvariant() switch { "red" => 1, "black" => 2, "white" => 3, "orange" => 4, "green" => 5, "blue" => 6, "pink" => 7, "purple" => 8, "yellow" => 9, _ => 0, }; } private Color IndexToBloodColor(byte index) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) return (Color)(index switch { 0 => new Color(-1f, -1f, -1f, -1f), 1 => new Color(0.7f, 0.02f, 0.02f, 0.9f), 2 => new Color(0.05f, 0.05f, 0.05f, 0.9f), 3 => Color.white, 4 => new Color(1f, 0.45f, 0.02f, 0.9f), 5 => new Color(0.02f, 0.55f, 0.12f, 0.9f), 6 => new Color(0.05f, 0.08f, 0.7f, 0.9f), 7 => new Color(0.95f, 0.08f, 0.55f, 0.9f), 8 => new Color(0.5f, 0.02f, 0.6f, 0.9f), 9 => new Color(0.9f, 0.85f, 0.05f, 0.9f), _ => new Color(-1f, -1f, -1f, -1f), }); } private Color GetBloodColor(RigManager rm) { //IL_04be: 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_001e: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_0096: 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_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0342: 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_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: 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_0405: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_043c: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_0498: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)rm != (Object)null && _bloodColorOverrides.TryGetValue(rm, out var value) && value.a >= 0f) { return value; } string text = BloodColorOverride?.Value; if (!string.IsNullOrEmpty(text) && !text.Equals("Auto", StringComparison.OrdinalIgnoreCase)) { Color val = ParseBloodColorString(text.ToLowerInvariant()); if (val.a >= 0f) { return val; } } } catch { } if ((Object)(object)rm != (Object)null && (Object)(object)rm.avatar != (Object)null) { try { string text2 = ((Object)rm.avatar).name?.ToLowerInvariant() ?? string.Empty; foreach (KeyValuePair avatarBloodOverride in _avatarBloodOverrides) { string key = avatarBloodOverride.Key; bool flag = false; if (key.StartsWith("*") && key.EndsWith("*") && key.Length > 2) { flag = text2.Contains(key.Substring(1, key.Length - 2)); } else if (key.EndsWith("*") && key.Length > 1) { flag = text2.StartsWith(key.Substring(0, key.Length - 1)); } else if (key.StartsWith("*") && key.Length > 1) { flag = text2.EndsWith(key.Substring(1)); } else if (text2 == key) { flag = true; } if (flag) { return avatarBloodOverride.Value; } } if ((text2.Contains("small") && text2.Contains("fast")) || (text2.Contains("tall") && text2.Contains("fast"))) { return new Color(0.05f, 0.05f, 0.05f, 0.9f); } if (text2.Contains("lightbody") || text2.Contains("heavybody") || text2.Contains("omni") || text2.Contains("proto") || text2.Contains("drone") || text2.Contains("robot") || text2.Contains("bot_")) { return new Color(0.05f, 0.05f, 0.05f, 0.9f); } if (text2.Contains("purple") || text2.Contains("violet")) { return new Color(0.5f, 0.02f, 0.6f, 0.9f); } if (text2.Contains("green")) { return new Color(0.02f, 0.55f, 0.12f, 0.9f); } if (text2.Contains("yellow")) { return new Color(0.9f, 0.85f, 0.05f, 0.9f); } if (text2.Contains("blue")) { return new Color(0.05f, 0.08f, 0.7f, 0.9f); } if (text2.Contains("pink")) { return new Color(0.95f, 0.08f, 0.55f, 0.9f); } if (text2.Contains("orange")) { return new Color(1f, 0.45f, 0.02f, 0.9f); } if (text2.Contains("red")) { return new Color(0.7f, 0.02f, 0.02f, 0.9f); } if (text2.Contains("null")) { return new Color(1f, 0.45f, 0.02f, 0.9f); } } catch { } } return new Color(0.7f, 0.02f, 0.02f, 0.9f); } private Color SampleAvatarColor(RigManager rm) { //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: 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_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013d: 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_017d: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) try { Renderer[] array = Il2CppArrayBase.op_Implicit(((Component)rm).GetComponentsInChildren(true)); if (array == null || array.Length == 0) { return Color.white; } Color val = Color.black; int num = 0; Renderer[] array2 = array; foreach (Renderer val2 in array2) { if ((Object)(object)val2 == (Object)null) { continue; } Material sharedMaterial = val2.sharedMaterial; if ((Object)(object)sharedMaterial == (Object)null) { continue; } Color val3 = Color.white; string[] array3 = new string[7] { "_Color", "_BaseColor", "_TintColor", "_EmissiveColor", "_MainColor", "_ColorTint", "_AlbedoColor" }; string[] array4 = array3; foreach (string text in array4) { if (sharedMaterial.HasProperty(text)) { val3 = sharedMaterial.GetColor(text); break; } } if (!(val3 == Color.white)) { float num2 = Mathf.Max(val3.r, Mathf.Max(val3.g, val3.b)); float num3 = Mathf.Min(val3.r, Mathf.Min(val3.g, val3.b)); if (!(num2 < 0.02f) && (!(num2 - num3 < 0.01f) || !(num2 > 0.98f))) { val += val3; num++; } } } if (num > 0) { Color val4 = val / (float)num; float num4 = (val4.r + val4.g + val4.b) / 3f; if (num4 > 0.05f) { return val4; } } } catch { } return Color.white; } private void PlayDismemberEffects(Vector3 position, Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) bool flag = TrySpawnGameBlood(position, 1.2f, color); if (EnableBloodEffects.Value && !flag) { if ((Object)(object)BloodPrefab != (Object)null) { ParticleSystem val = Object.Instantiate(BloodPrefab, position, Quaternion.identity); MainModule main = val.main; main.startColor = MinMaxGradient.op_Implicit(color); val.Play(); Object.Destroy((Object)(object)((Component)val).gameObject, 6f); } else { SpawnFallbackBlood(position, 1.5f, color); } } if (!EnableSoundEffects.Value) { return; } try { AudioClip val2 = DismemberSound; if ((Object)(object)val2 == (Object)null && _dismemberSounds != null && _dismemberSounds.Count > 0) { val2 = _dismemberSounds[Random.Range(0, _dismemberSounds.Count)]; } if ((Object)(object)val2 == (Object)null) { val2 = GenerateTestTone(); } if ((Object)(object)val2 != (Object)null) { GameObject val3 = new GameObject("DeadPiece_SoundEffect"); val3.transform.position = position; AudioSource val4 = val3.AddComponent(); val4.clip = val2; val4.spatialBlend = 1f; val4.Play(); Object.Destroy((Object)(object)val3, val2.length + 0.1f); } else { MelonLogger.Warning("Клип оказался null! Проверь целостность файлов в UserData."); } } catch (Exception ex) { MelonLogger.Warning("Sound playback failed: " + ex.Message); } } private void ApplyHeadSeverEffects(RigManager rm, Vector3 position) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!EnableHeadSever.Value || (Object)(object)rm == (Object)null) { return; } try { TryAddVisualCut(rm, position, 0.34f); Transform val = (((Object)(object)rm.avatar != (Object)null && (Object)(object)rm.avatar.animator != (Object)null) ? rm.avatar.animator.GetBoneTransform((HumanBodyBones)9) : null); if ((Object)(object)val != (Object)null) { TryAddVisualCut(rm, val.position, 0.28f); } } catch (Exception ex) { MelonLogger.Warning("Head sever effects failed: " + ex.Message); } } private void SpawnHeadProp(Transform headTransform, Vector3 hitPoint, Color bloodColor) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_00e8: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)val).name = "DeadPiece_SeveredHead"; val.transform.position = headTransform.position; val.transform.localScale = Vector3.one * 0.13f; val.transform.Rotate(0f, 0f, Random.Range(0f, 360f)); Object.Destroy((Object)(object)val.GetComponent()); MeshRenderer component = val.GetComponent(); ((Renderer)component).material = new Material(Shader.Find("Sprites/Default")) { color = bloodColor }; Rigidbody val2 = val.AddComponent(); val2.mass = 0.5f; val2.drag = 0.5f; Vector3 val4; if (!(hitPoint == Vector3.zero)) { Vector3 val3 = hitPoint - headTransform.position; val4 = ((Vector3)(ref val3)).normalized; } else { val4 = Vector3.up; } Vector3 val5 = val4; val2.AddForce(val5 * 7f + Vector3.up * 4f, (ForceMode)1); val2.AddTorque(new Vector3(Random.value - 0.5f, Random.value - 0.5f, Random.value - 0.5f) * 3f, (ForceMode)1); Object.Destroy((Object)(object)val, 10f); } catch { } } private bool IsBoneGone(RigManager rm, HumanBodyBones bone) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return false; } Transform cachedBoneTransform = GetCachedBoneTransform(rm, bone); return (Object)(object)cachedBoneTransform != (Object)null && cachedBoneTransform.localScale == Vector3.zero; } private void HandleRespawnRestore(RigManager rm) { HandleRigRespawnRestore(rm, syncNetwork: true); } private void HandleAllRigsRespawnRestore() { if (!NetworkInfo.HasServer || _trackedRigs.Count == 0) { return; } RigManager[] array = _trackedRigs.ToArray(); foreach (RigManager val in array) { if (!((Object)(object)val == (Object)null) && (Object)(object)val != (Object)(object)Player.RigManager) { HandleRigRespawnRestore(val, syncNetwork: false); } } } private void HandleRigRespawnRestore(RigManager rm, bool syncNetwork) { if ((Object)(object)rm == (Object)null || (Object)(object)rm.health == (Object)null) { return; } bool flag = !rm.health.alive; _rigWasDead.TryGetValue(rm, out var value); if (value && !flag) { if ((Object)(object)rm == (Object)(object)Player.RigManager) { SuppressNoLegRagdollForRespawn(); ResetLocalNoLegRagdollPermission(); StabilizeRespawnLocomotion(rm); RestoreDeadpieceLegUsage(rm); } ResetLimbStats(rm, restoreBody: true); if ((Object)(object)rm == (Object)(object)Player.RigManager) { StabilizeRespawnLocomotion(rm); _lastTrackedBodyHealth = -1f; UpdateLimbPenaltyFlag(rm); } if (syncNetwork) { SyncFullState(); } if ((Object)(object)rm != (Object)(object)Player.RigManager && NetworkInfo.HasServer && TryGetPlayerIdForRig(rm, out var playerId)) { uint stateMask = GetStateMask(rm); NetworkSync.SendFullState(playerId, stateMask, 0, 0); } if (syncNetwork) { EnforceInvincibleRigsForAllTracked(); } } _rigWasDead[rm] = flag; } public void SyncFullState() { if (PlayerIDManager.LocalID != null) { RigManager rigManager = Player.RigManager; if (!((Object)(object)rigManager == (Object)null)) { uint stateMask = GetStateMask(rigManager); SyncLocalState(stateMask); } } } private void ResyncLocalStateIfNeeded() { //IL_005d: 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_0062: Unknown result type (might be due to invalid IL or missing references) if (PlayerIDManager.LocalID != null && !((Object)(object)Player.RigManager == (Object)null)) { uint stateMask = GetStateMask(Player.RigManager); if (stateMask != _lastSentStateMask || !(Time.time - _lastStateSyncTime < 5f)) { MessageRoute val = (NetworkInfo.HasServer ? CommonMessageRoutes.ReliableToOtherClients : CommonMessageRoutes.ReliableToServer); SyncLocalState(stateMask); } } } private ushort NextLocalStateSequence() { _localStateSequence++; if (_localStateSequence == 0) { _localStateSequence = 1; } return _localStateSequence; } private void SyncLocalState(uint goneBoneMask) { if (PlayerIDManager.LocalID != null) { ushort sequence = NextLocalStateSequence(); byte bloodColorIndex = BloodColorToIndex(BloodColorOverride?.Value ?? "Auto"); NetworkSync.SendFullState(PlayerIDManager.LocalSmallID, goneBoneMask, bloodColorIndex, sequence); _lastSentStateMask = goneBoneMask; _lastStateSyncTime = Time.time; } } public void SetPlayerMetadata(byte playerId, string value) { value = value ?? string.Empty; try { foreach (PlayerID playerID in PlayerIDManager.PlayerIDs) { if (playerID != null && playerID.SmallID == playerId) { PlayerMetadata metadata = playerID.Metadata; if (((metadata != null) ? metadata.Metadata : null) != null) { playerID.Metadata.Metadata.TrySetMetadata("DeadPieceLimbs", value); break; } } } } catch { } } private byte GetBloodColorIndexForRig(RigManager rm) { if ((Object)(object)rm == (Object)null) { return 0; } if (_bloodColorIndexOverrides.TryGetValue(rm, out var value)) { return value; } return 0; } private bool TryResolvePlayerRig(byte playerId, out RigManager rigManager) { rigManager = null; try { if (PlayerIDManager.LocalID != null && playerId == PlayerIDManager.LocalSmallID && (Object)(object)Player.RigManager != (Object)null) { rigManager = Player.RigManager; return true; } RigRefs val = default(RigRefs); if (PlayerRepUtilities.TryGetReferences(playerId, ref val) && (Object)(object)((val != null) ? val.RigManager : null) != (Object)null) { rigManager = val.RigManager; return true; } } catch { } return false; } private void ApplyBloodColorToRig(RigManager rigManager, byte colorIndex) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rigManager == (Object)null) { return; } if (colorIndex == 0) { _bloodColorOverrides.Remove(rigManager); _bloodColorIndexOverrides.Remove(rigManager); return; } Color val = IndexToBloodColor(colorIndex); if (val.a >= 0f) { _bloodColorOverrides[rigManager] = val; _bloodColorIndexOverrides[rigManager] = colorIndex; } } private void OnPluginLimbHit(byte targetPlayerId, byte boneIndex, float damage, Vector3 hitPoint, bool applyDamage) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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_010f: Unknown result type (might be due to invalid IL or missing references) if (boneIndex >= DamageBones.Length || !TryResolvePlayerRig(targetPlayerId, out var rigManager)) { return; } EnsureRigInitialized(rigManager); HumanBodyBones val = DamageBones[boneIndex]; if (applyDamage) { if (_playersHealth.TryGetValue(rigManager, out var value) && value.ContainsKey(val) && !IsBoneGone(rigManager, val)) { value[val] = Mathf.Max(0f, value[val] - damage); TryAddVisualHit(rigManager, hitPoint, damage); PlayHitEffects(rigManager, val, hitPoint, damage); if (value[val] <= 0f) { DismemberLimb(rigManager, val, hitPoint); if ((Object)(object)rigManager != (Object)(object)Player.RigManager && IsRemotePlayerRig(rigManager)) { ApplyRemoteHandBlocking(rigManager); ApplyRemoteLegEffects(rigManager); } } else if (hitPoint != Vector3.zero) { TryDamageNearbyEyes(rigManager, hitPoint, damage); } } } else { TryAddVisualHit(rigManager, hitPoint, damage); PlayHitEffects(rigManager, val, hitPoint, damage); } TrackRig(rigManager); if (applyDamage && NetworkInfo.IsHost) { NetworkSync.SendFullState(targetPlayerId, GetStateMask(rigManager), GetBloodColorIndexForRig(rigManager), 0); } } private void OnPluginLimbSever(byte targetPlayerId, byte boneIndex, Vector3 hitPoint, Vector3 hitNormal, float damage) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (boneIndex < DamageBones.Length && TryResolvePlayerRig(targetPlayerId, out var rigManager)) { HumanBodyBones bone = DamageBones[boneIndex]; DismemberLimb(rigManager, bone, hitPoint); if ((Object)(object)rigManager != (Object)(object)Player.RigManager && IsRemotePlayerRig(rigManager)) { ApplyRemoteHandBlocking(rigManager); ApplyRemoteLegEffects(rigManager); } TrackRig(rigManager); if (NetworkInfo.IsHost) { NetworkSync.SendFullState(targetPlayerId, GetStateMask(rigManager), GetBloodColorIndexForRig(rigManager), 0); } } } private void OnPluginRespawn(byte playerId) { if (TryResolvePlayerRig(playerId, out var rigManager)) { ResetLimbStats(rigManager, restoreBody: true); TrackRig(rigManager); if (NetworkInfo.IsHost) { NetworkSync.SendFullState(playerId, GetStateMask(rigManager), GetBloodColorIndexForRig(rigManager), 0); } } } private void OnPluginBloodColor(byte playerId, byte colorIndex) { if (TryResolvePlayerRig(playerId, out var rigManager)) { ApplyBloodColorToRig(rigManager, colorIndex); } } private uint GetPluginStateMask(byte playerId) { RigManager rigManager; return TryResolvePlayerRig(playerId, out rigManager) ? GetStateMask(rigManager) : 0u; } private void OnPluginFullState(byte playerId, uint goneBoneMask, byte bloodColorIndex, ushort sequence) { ApplyNetworkState(playerId, sequence, goneBoneMask); if (TryResolvePlayerRig(playerId, out var rigManager)) { ApplyBloodColorToRig(rigManager, bloodColorIndex); } } private void OnPlayerJoined(PlayerID id) { SyncFullState(); if (id == null || id.IsMe) { return; } RigManager rigManager = Player.RigManager; if ((Object)(object)rigManager != (Object)null) { SyncLocalState(GetStateMask(rigManager)); } PlayerMetadata metadata = id.Metadata; string value = default(string); if (((metadata != null) ? metadata.Metadata : null) != null && id.Metadata.Metadata.TryGetMetadata("DeadPieceLimbs", ref value)) { ApplyNetworkState(id.SmallID, value); } RigRefs val = default(RigRefs); if (PlayerRepUtilities.TryGetReferences(id.SmallID, ref val) && (Object)(object)((val != null) ? val.RigManager : null) != (Object)null) { TrackRig(val.RigManager); } try { BroadcastBloodColor(); } catch { } } private void OnPlayerLeft(PlayerID id) { if (id != null) { byte smallID = id.SmallID; _pendingNetworkStates.Remove(smallID); _lastAppliedNetworkSequence.Remove(smallID); _appliedStateMasks.Remove(smallID); _remoteFallenPlayers.Remove(smallID); RigRefs val = default(RigRefs); if (PlayerRepUtilities.TryGetReferences(smallID, ref val) && (Object)(object)((val != null) ? val.RigManager : null) != (Object)null) { RemoveRigFromCaches(val.RigManager); } } } private void OnNetworkRigCreated(NetworkPlayer player, RigManager rig) { if (((player != null) ? player.PlayerID : null) == null || (Object)(object)rig == (Object)null) { return; } byte smallID = player.PlayerID.SmallID; if (_pendingNetworkStates.TryGetValue(smallID, out var value)) { if ((Object)(object)rig.avatar != (Object)null && (Object)(object)rig.avatar.animator != (Object)null && (value.Sequence == 0 || ShouldApplyNetworkSequence(smallID, value.Sequence))) { ApplyStateToRig(rig, value.GoneBoneMask); if (value.IsFallen) { ApplyNoLegFallenState(rig); } else { RestoreNoLegFallenState(rig); } if (value.Sequence > 0) { _lastAppliedNetworkSequence[smallID] = value.Sequence; } _pendingNetworkStates.Remove(smallID); } } else { PlayerMetadata metadata = player.PlayerID.Metadata; string value2 = default(string); if (((metadata != null) ? metadata.Metadata : null) != null && player.PlayerID.Metadata.Metadata.TryGetMetadata("DeadPieceLimbs", ref value2)) { ApplyNetworkState(smallID, value2); } } uint stateMask = GetStateMask(rig); if (stateMask != 0) { _appliedStateMasks[smallID] = stateMask; } TrackRig(rig); } private void OnMetadataChanged(PlayerID id, string key, string value) { if (!(key != "DeadPieceLimbs") && id != null && !id.IsMe && !_pluginCallbacksRegistered) { ApplyNetworkState(id.SmallID, value); } } private unsafe string GetStateString(RigManager rm) { if ((Object)(object)rm == (Object)null) { return string.Empty; } IEnumerable values = NetworkBones.Where((HumanBodyBones bone) => IsBoneGone(rm, bone)).Select(delegate(HumanBodyBones bone) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) HumanBodyBones val = bone; return ((object)(*(HumanBodyBones*)(&val))/*cast due to .constrained prefix*/).ToString(); }); return string.Join(",", values); } private void InitializeModules() { } private void RegisterFusionModules() { } public void ApplyNetworkState(byte playerId, ushort sequence, uint goneBoneMask, bool isFallen) { if (sequence > 0 && !ShouldApplyNetworkSequence(playerId, sequence)) { return; } if (!TryResolvePlayerRig(playerId, out var rigManager)) { QueuePendingNetworkState(playerId, sequence, goneBoneMask, isFallen); return; } if ((Object)(object)rigManager.avatar == (Object)null || (Object)(object)rigManager.avatar.animator == (Object)null) { QueuePendingNetworkState(playerId, sequence, goneBoneMask, isFallen); return; } ApplyStateToRig(rigManager, goneBoneMask); if (isFallen) { ApplyNoLegFallenState(rigManager); } else { RestoreNoLegFallenState(rigManager); } TrackRig(rigManager); if (sequence > 0) { _lastAppliedNetworkSequence[playerId] = sequence; } _pendingNetworkStates.Remove(playerId); } public void ApplyNetworkState(byte playerId, ushort sequence, uint goneBoneMask) { ApplyNetworkState(playerId, sequence, goneBoneMask, isFallen: false); } public void ApplyNetworkState(byte playerId, string value) { ApplyNetworkState(playerId, 0, ParseGoneMaskFromString(value)); } public void ApplyNetworkStateFromMask(byte playerId, uint goneBoneMask) { ApplyNetworkState(playerId, 0, goneBoneMask); } public void ApplyNetworkBloodColor(byte playerId, byte colorIndex) { if (TryResolvePlayerRig(playerId, out var rigManager)) { ApplyBloodColorToRig(rigManager, colorIndex); } } public void BroadcastBloodColor() { try { byte colorIndex = BloodColorToIndex(BloodColorOverride?.Value ?? "Auto"); if ((Object)(object)Player.RigManager != (Object)null) { ApplyBloodColorToRig(Player.RigManager, colorIndex); } if (NetworkInfo.HasServer && PlayerIDManager.LocalID != null) { NetworkSync.SendBloodColor(PlayerIDManager.LocalSmallID, colorIndex); } } catch (Exception ex) { MelonLogger.Warning("[DeadPiece] Blood color update failed: " + ex.Message); } } public static string BuildStateStringFromMask(uint goneBoneMask) { if (goneBoneMask == 0) { return string.Empty; } List list = new List(); for (int i = 0; i < DamageBones.Length; i++) { if ((goneBoneMask & (uint)(1 << i)) != 0) { list.Add(((object)Unsafe.As(ref DamageBones[i])/*cast due to .constrained prefix*/).ToString()); } } return string.Join(",", list); } private void ApplyPendingNetworkStates() { if (_pendingNetworkStates.Count > 0) { KeyValuePair[] array = _pendingNetworkStates.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair keyValuePair = array[i]; ApplyNetworkState(keyValuePair.Key, keyValuePair.Value.Sequence, keyValuePair.Value.GoneBoneMask, keyValuePair.Value.IsFallen); } } } private void ApplyStateToRig(RigManager rm, string value) { ApplyStateToRig(rm, ParseGoneMaskFromString(value)); } private void ApplyStateToRig(RigManager rm, uint goneBoneMask) { //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: 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_019e: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: 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_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return; } if (IsRigLimbDamageBlocked(rm) && !IsRemotePlayerRig(rm)) { ResetLimbStats(rm, restoreBody: true); return; } HashSet hashSet = new HashSet(); for (int i = 0; i < DamageBones.Length; i++) { if ((goneBoneMask & (uint)(1 << i)) != 0) { hashSet.Add(DamageBones[i]); } } if (hashSet.Count == 0) { ResetLimbStats(rm, restoreBody: true); return; } EnsureRigInitialized(rm); RestoreRigMeshes(rm); HumanBodyBones[] networkBones = NetworkBones; RebuildBoneCache(rm); HumanBodyBones[] array = networkBones; foreach (HumanBodyBones val in array) { Transform cachedBoneTransform = GetCachedBoneTransform(rm, val); if ((Object)(object)cachedBoneTransform == (Object)null) { continue; } if (!_originalScales[rm].ContainsKey(val) || _originalScales[rm][val] == Vector3.zero) { _originalScales[rm][val] = ((cachedBoneTransform.localScale == Vector3.zero) ? Vector3.one : cachedBoneTransform.localScale); } bool flag = cachedBoneTransform.localScale == Vector3.zero; bool flag2 = hashSet.Contains(val); if (flag2) { if (!flag || !HasStumpBloodStart(rm, val)) { MarkStumpBloodStarted(rm, val); } } else { ClearStumpBloodState(rm, val); } cachedBoneTransform.localScale = (flag2 ? Vector3.zero : _originalScales[rm][val]); if (_playersHealth.TryGetValue(rm, out var value)) { value[val] = (flag2 ? (0f - GetMaxHealthForBone(rm, val)) : GetMaxHealthForBone(rm, val)); } if (!flag && flag2) { TryAddVisualCut(rm, cachedBoneTransform.position); if (IsRemotePlayerRig(rm)) { Vector3 position = cachedBoneTransform.position; SpawnBloodStream(rm, val, position); PlayDismemberEffects(position, GetBloodColor(rm)); TryApplyBloodImpactAtBone(rm, val, position, Mathf.Max(5f, GetMaxHealthForBone(rm, val) * 0.25f), GetBloodColor(rm)); } } } RebuildLimbGoneFlags(rm); if ((Object)(object)rm == (Object)(object)Player.RigManager) { UpdateLimbPenaltyFlag(rm); SetHandUsable(Player.LeftHand, !IsLeftArmGone(rm)); SetHandUsable(Player.RightHand, !IsRightArmGone(rm)); if (IsBothLegsGone(rm)) { AllowLocalNoLegRagdollFromCurrentSever(); } } if ((Object)(object)rm != (Object)(object)Player.RigManager && IsRemotePlayerRig(rm)) { ApplyRemoteHandBlocking(rm); ApplyRemoteLegEffects(rm); } TrackRig(rm); if (TryGetPlayerIdForRig(rm, out var playerId)) { if (goneBoneMask != 0) { _appliedStateMasks[playerId] = goneBoneMask; } else { _appliedStateMasks.Remove(playerId); } } if ((Object)(object)rm == (Object)(object)Player.RigManager && EnableVrEyeBlindness.Value) { UpdateVrEyeBlindness(rm); } } private bool IsEyeGone(RigManager rm, HumanBodyBones eyeBone) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 return ((int)eyeBone == 21 || (int)eyeBone == 22) && IsBoneGone(rm, eyeBone); } private void ClearVrEyeCameraCache() { _vrEyeCamerasCached = false; _vrEyeCacheRig = null; _vrLeftEyeCameras.Clear(); _vrRightEyeCameras.Clear(); RestoreAllVrEyeCameras(); } private void RestoreAllVrEyeCameras() { foreach (KeyValuePair item in _vrCameraEnabledBackup) { if ((Object)(object)item.Key != (Object)null) { ((Behaviour)item.Key).enabled = item.Value; } } _vrCameraEnabledBackup.Clear(); foreach (KeyValuePair vrEyeBlackoutObject in _vrEyeBlackoutObjects) { if ((Object)(object)vrEyeBlackoutObject.Value != (Object)null) { Object.Destroy((Object)(object)vrEyeBlackoutObject.Value); } } _vrEyeBlackoutObjects.Clear(); } private void CacheVrEyeCameras(RigManager rm) { if (_vrEyeCamerasCached && (Object)(object)_vrEyeCacheRig == (Object)(object)rm) { return; } _vrLeftEyeCameras.Clear(); _vrRightEyeCameras.Clear(); _vrEyeCacheRig = rm; if ((Object)(object)((rm != null) ? rm.avatar : null) != (Object)null) { Il2CppArrayBase componentsInChildren = ((Component)rm.avatar).GetComponentsInChildren(true); foreach (Camera item in componentsInChildren) { ClassifyVrEyeCamera(item, _vrLeftEyeCameras, _vrRightEyeCameras); } } _vrEyeCamerasCached = true; } private static void ClassifyVrEyeCamera(Camera camera, List leftCameras, List rightCameras) { if ((Object)(object)camera == (Object)null) { return; } string text = ((Object)camera).name.ToLowerInvariant(); if (!text.Contains("center") && !text.Contains("spectator") && !text.Contains("overlay") && !text.Contains("mirror") && !text.Contains("ui")) { bool flag = text.Contains("left") || text.Contains("leye") || text.EndsWith("_l") || text.EndsWith("lf"); bool flag2 = text.Contains("right") || text.Contains("reye") || text.EndsWith("_r") || text.EndsWith("rt"); if (flag && !flag2) { AddUniqueCamera(leftCameras, camera); } else if (flag2 && !flag) { AddUniqueCamera(rightCameras, camera); } } } private static void AddUniqueCamera(List cameras, Camera camera) { if (!cameras.Contains(camera)) { cameras.Add(camera); } } private void UpdateVrEyeBlindness(RigManager rm) { if (EnableVrEyeBlindness.Value && !((Object)(object)rm != (Object)(object)Player.RigManager)) { bool flag = IsEyeGone(rm, (HumanBodyBones)21); bool flag2 = IsEyeGone(rm, (HumanBodyBones)22); CacheVrEyeCameras(rm); ApplyVrBlindnessToCameras(_vrLeftEyeCameras, flag); ApplyVrBlindnessToCameras(_vrRightEyeCameras, flag2); _lastAppliedLeftEyeBlind = flag; _lastAppliedRightEyeBlind = flag2; } } private void ApplyVrBlindnessToCameras(List cameras, bool blind) { for (int i = 0; i < cameras.Count; i++) { Camera val = cameras[i]; if ((Object)(object)val == (Object)null) { continue; } if (blind) { if (!_vrCameraEnabledBackup.ContainsKey(val)) { _vrCameraEnabledBackup[val] = ((Behaviour)val).enabled; } EnsureVrBlackoutOverlay(val); ((Behaviour)val).enabled = false; } else { if (_vrCameraEnabledBackup.TryGetValue(val, out var value)) { ((Behaviour)val).enabled = value; } RemoveVrBlackoutOverlay(val); } } } private void EnsureVrBlackoutOverlay(Camera camera) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_00f2: Expected O, but got Unknown //IL_0118: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Expected O, but got Unknown if (!((Object)(object)camera == (Object)null) && !_vrEyeBlackoutObjects.ContainsKey(camera)) { GameObject val = new GameObject("DeadPiece_VREyeBlackout"); val.layer = LayerMask.NameToLayer("Ignore Raycast"); val.transform.SetParent(((Component)camera).transform, false); float num = Mathf.Max(camera.nearClipPlane + 0.02f, 0.03f); val.transform.localPosition = new Vector3(0f, 0f, num); val.transform.localRotation = Quaternion.identity; float num2 = Mathf.Tan(camera.fieldOfView * 0.5f * ((float)Math.PI / 180f)) * num * 2.2f; float num3 = num2 * Mathf.Max(camera.aspect, 0.5f); val.transform.localScale = new Vector3(num3, num2, 1f); MeshFilter val2 = val.AddComponent(); Mesh val3 = new Mesh(); ((Object)val3).name = "DeadPiece_VRQuad"; val3.vertices = Il2CppStructArray.op_Implicit((Vector3[])(object)new Vector3[4] { new Vector3(-0.5f, -0.5f, 0f), new Vector3(0.5f, -0.5f, 0f), new Vector3(-0.5f, 0.5f, 0f), new Vector3(0.5f, 0.5f, 0f) }); val3.triangles = Il2CppStructArray.op_Implicit(new int[6] { 0, 1, 2, 2, 1, 3 }); val3.uv = Il2CppStructArray.op_Implicit((Vector2[])(object)new Vector2[4] { new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0f, 1f), new Vector2(1f, 1f) }); val2.sharedMesh = val3; MeshRenderer val4 = val.AddComponent(); Shader val5 = Shader.Find("Unlit/Color"); if ((Object)(object)val5 == (Object)null) { val5 = Shader.Find("Sprites/Default"); } if ((Object)(object)val5 != (Object)null) { ((Renderer)val4).material = new Material(val5) { color = Color.black }; } val.layer = ((Component)camera).gameObject.layer; _vrEyeBlackoutObjects[camera] = val; } } private void RemoveVrBlackoutOverlay(Camera camera) { if (!((Object)(object)camera == (Object)null)) { if (_vrEyeBlackoutObjects.TryGetValue(camera, out var value) && (Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } _vrEyeBlackoutObjects.Remove(camera); } } private void TryAddVisualHit(RigManager rm, Vector3 position, float damage) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if (!EnableVisualHitMarks.Value || (Object)(object)rm == (Object)null || position == Vector3.zero) { return; } try { float num = Mathf.Clamp(0.05f + damage / Mathf.Max(1f, GetAvatarHealthBase(rm)) * 0.12f, 0.05f, 0.22f); Matrix4x4 val = Matrix4x4.TRS(position, Quaternion.identity, Vector3.one * num); VisualDamageController visualDamageController = GetVisualDamageController(rm); if ((Object)(object)visualDamageController != (Object)null) { visualDamageController.AddToHitArray(val); visualDamageController.UpdateArray(); } else if ((Object)(object)rm.health != (Object)null) { rm.health.AddToHitArray(val); rm.health.UpdateArray(); } } catch (Exception ex) { MelonLogger.Warning("Visual hit failed: " + ex.Message); } } private void TryAddVisualCut(RigManager rm, Vector3 position) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) TryAddVisualCut(rm, position, 0.18f); } private void TryAddVisualCut(RigManager rm, Vector3 position, float scale) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) if (!EnableVisualCuts.Value || (Object)(object)rm == (Object)null) { return; } try { VisualDamageController visualDamageController = GetVisualDamageController(rm); Matrix4x4 val = Matrix4x4.TRS(position, Quaternion.identity, Vector3.one * Mathf.Max(0.01f, scale)); if ((Object)(object)visualDamageController != (Object)null) { visualDamageController.AddToCutArray(val); visualDamageController.UpdateArray(); } else if ((Object)(object)rm.health != (Object)null) { rm.health.AddToCutArray(val); rm.health.UpdateArray(); } } catch (Exception ex) { MelonLogger.Warning("Visual cut failed: " + ex.Message); } } private void ResetVisualDamage(RigManager rm) { if ((Object)(object)rm == (Object)null) { return; } try { VisualDamageController visualDamageController = GetVisualDamageController(rm); if ((Object)(object)visualDamageController != (Object)null) { visualDamageController.ResetHits(); visualDamageController.UpdateArray(); } if ((Object)(object)rm.health != (Object)null) { rm.health.ResetHits(); rm.health.UpdateArray(); } } catch (Exception ex) { MelonLogger.Warning("Visual damage reset failed: " + ex.Message); } } public void SetLocalMetadata(string value) { value = value ?? string.Empty; try { PlayerMetadata metadata = LocalPlayer.Metadata; if (((metadata != null) ? metadata.Metadata : null) != null) { LocalPlayer.Metadata.Metadata.TrySetMetadata("DeadPieceLimbs", value); return; } } catch { } PlayerID localID = PlayerIDManager.LocalID; object obj2; if (localID == null) { obj2 = null; } else { PlayerMetadata metadata2 = localID.Metadata; obj2 = ((metadata2 != null) ? metadata2.Metadata : null); } if (obj2 != null) { PlayerIDManager.LocalID.Metadata.Metadata.TrySetMetadata("DeadPieceLimbs", value); } } private void KillRig(RigManager rm) { if (!((Object)(object)rm == (Object)null) && !((Object)(object)rm.health == (Object)null)) { rm.health.Death(); } } private bool HasLimbGoneFlag(RigManager rm, LimbGoneMask mask) { if ((Object)(object)rm == (Object)null || !_rigCache.TryGetValue(rm, out var value)) { return false; } return (value.LimbGoneFlags & mask) != 0; } private bool IsLeftArmGone(RigManager rm) { return HasLimbGoneFlag(rm, LimbGoneMask.LeftArm); } private bool IsRightArmGone(RigManager rm) { return HasLimbGoneFlag(rm, LimbGoneMask.RightArm); } private bool IsLeftLegGone(RigManager rm) { return HasLimbGoneFlag(rm, LimbGoneMask.LeftLeg); } private bool IsRightLegGone(RigManager rm) { return HasLimbGoneFlag(rm, LimbGoneMask.RightLeg); } public bool IsBothLegsGone(RigManager rm) { if ((Object)(object)rm == (Object)null) { return false; } return IsLeftLegGone(rm) && IsRightLegGone(rm); } public bool AreAllLimbsGone(RigManager rm) { if ((Object)(object)rm == (Object)null) { return false; } return IsLeftArmGone(rm) && IsRightArmGone(rm) && IsLeftLegGone(rm) && IsRightLegGone(rm); } private void PlayHitEffects(RigManager rm, HumanBodyBones bone, Vector3 position, float damage) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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) if (position == Vector3.zero || !ShouldPlayHitEffect(rm, bone)) { return; } if (EnableBloodEffects.Value) { float intensity = Mathf.Clamp01(damage / Mathf.Max(1f, GetMaxHealthForBone(rm, bone))); TryApplyBloodImpactAtBone(rm, bone, position, Mathf.Max(1f, damage * 0.25f), GetBloodColor(rm)); if (!TrySpawnGameBlood(position, intensity, GetBloodColor(rm)) && (Object)(object)BloodPrefab == (Object)null) { SpawnFallbackBlood(position, intensity, GetBloodColor(rm)); } } if (IsBoneGone(rm, bone)) { float num = Mathf.Max(0f, SeveredLimbBleedDamagePerSecond.Value) * Time.deltaTime; if (num > 0f) { TryApplyBleedAtBone(rm, bone, num); } } } private bool ShouldPlayHitEffect(RigManager rm, HumanBodyBones bone) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (!_lastHitEffectTimes.TryGetValue(rm, out var value)) { value = new Dictionary(); _lastHitEffectTimes[rm] = value; } if (value.TryGetValue(bone, out var value2) && Time.time - value2 < 0.12f) { return false; } value[bone] = Time.time; return true; } private IEnumerator LoadDismemberSounds() { MelonLogger.Msg(ConsoleColor.Gray, "LoadDismemberSounds started, folder: " + _soundFolder); string[] files; try { if (!Directory.Exists(_soundFolder)) { MelonLogger.Warning("Sound folder does not exist: " + _soundFolder); yield break; } files = Directory.GetFiles(_soundFolder, "*.wav", SearchOption.TopDirectoryOnly); MelonLogger.Msg(ConsoleColor.Gray, "Found " + files.Length + " WAV files in " + _soundFolder); } catch (Exception ex) { Exception ex2 = ex; MelonLogger.Warning("Sound folder scan failed: " + ex2.Message); yield break; } string[] array = files; foreach (string file in array) { MelonLogger.Msg(ConsoleColor.Gray, "Loading sound file: " + file); AudioClip clip = null; try { clip = API.LoadAudioClip(file, true); } catch (Exception ex3) { MelonLogger.Warning("AudioImportLib failed to load " + Path.GetFileName(file) + ": " + ex3.Message); } if ((Object)(object)clip != (Object)null) { MelonLogger.Msg(ConsoleColor.Gray, "Loaded clip: " + ((Object)clip).name + " length=" + clip.length + " freq=" + clip.frequency + " channels=" + clip.channels); _dismemberSounds.Add(clip); } else { MelonLogger.Warning("AudioImportLib returned null for: " + Path.GetFileName(file)); } } MelonLogger.Msg(ConsoleColor.Gray, "Loaded " + _dismemberSounds.Count + " dismemberment sounds from " + _soundFolder); } private AudioClip GenerateTestTone() { int num = 44100; float num2 = 0.3f; int num3 = (int)((float)num * num2); float[] array = new float[num3]; for (int i = 0; i < num3; i++) { float num4 = (float)i / (float)num; array[i] = Mathf.Sin((float)Math.PI * 880f * num4) * 0.5f; } AudioClip val = AudioClip.Create("DeadPiece_TestTone", num3, 1, num, false); val.SetData(Il2CppStructArray.op_Implicit(array), 0); return val; } private void SetHandUsable(Hand hand, bool usable) { if (!((Object)(object)hand == (Object)null)) { if (usable) { hand.EnableCollider(); hand.SetGripStrength(1f); hand.HoverUnlock(); } else { hand.DetachObject(); hand.DetachIgnoreBodyJoints(); hand.SetGripStrength(0f); hand.HoverLock(); hand.DisableCollider(); } } } private void EnforceLocalHandUsability() { RigManager rigManager = Player.RigManager; if ((Object)(object)rigManager == (Object)null) { return; } bool flag = !IsLeftArmGone(rigManager); bool flag2 = !IsRightArmGone(rigManager); if ((Object)(object)Player.LeftHand != (Object)null) { if (!flag) { Player.LeftHand.DetachObject(); Player.LeftHand.DetachIgnoreBodyJoints(); Player.LeftHand.SetGripStrength(0f); Player.LeftHand.HoverLock(); Player.LeftHand.DisableCollider(); } else if (!_lastLeftArmUsable) { SetHandUsable(Player.LeftHand, usable: true); } } if ((Object)(object)Player.RightHand != (Object)null) { if (!flag2) { Player.RightHand.DetachObject(); Player.RightHand.DetachIgnoreBodyJoints(); Player.RightHand.SetGripStrength(0f); Player.RightHand.HoverLock(); Player.RightHand.DisableCollider(); } else if (!_lastRightArmUsable) { SetHandUsable(Player.RightHand, usable: true); } } _lastLeftArmUsable = flag; _lastRightArmUsable = flag2; } private void ApplyRemoteHandBlocking(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return; } bool flag = IsLeftArmGone(rm); bool flag2 = IsRightArmGone(rm); if (!flag && !flag2) { return; } Hand[] array = Il2CppArrayBase.op_Implicit(((Component)rm).GetComponentsInChildren(true)); if (array != null && array.Length != 0) { Transform boneTransform = rm.avatar.animator.GetBoneTransform((HumanBodyBones)17); Transform boneTransform2 = rm.avatar.animator.GetBoneTransform((HumanBodyBones)18); Hand[] array2 = array; foreach (Hand val in array2) { if ((Object)(object)val == (Object)null) { continue; } bool flag3 = false; if (flag && (Object)(object)boneTransform != (Object)null && ((Component)val).transform.IsChildOf(boneTransform)) { flag3 = true; } if (flag2 && (Object)(object)boneTransform2 != (Object)null && ((Component)val).transform.IsChildOf(boneTransform2)) { flag3 = true; } if (flag3) { try { val.DisableCollider(); val.SetGripStrength(0f); } catch { } } } return; } if (flag) { Transform boneTransform3 = rm.avatar.animator.GetBoneTransform((HumanBodyBones)17); if ((Object)(object)boneTransform3 != (Object)null) { DisableCollidersOnTransform(boneTransform3); } } if (flag2) { Transform boneTransform4 = rm.avatar.animator.GetBoneTransform((HumanBodyBones)18); if ((Object)(object)boneTransform4 != (Object)null) { DisableCollidersOnTransform(boneTransform4); } } } private void DisableCollidersOnTransform(Transform t) { if ((Object)(object)t == (Object)null) { return; } Collider[] array = Il2CppArrayBase.op_Implicit(((Component)t).GetComponentsInChildren(true)); if (array == null) { return; } Collider[] array2 = array; foreach (Collider val in array2) { if ((Object)(object)val != (Object)null && val.enabled) { val.enabled = false; } } } private void ApplyRemoteLegEffects(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm.physicsRig == (Object)null) { return; } if (IsBothLegsGone(rm)) { try { rm.physicsRig.SetKneePelvisLimit(0.15f, 0.45f); } catch { } try { if ((Object)(object)rm.health != (Object)null) { rm.health.SetUsage(1f, 1f, 0f, 0f, 1f, 1f); } } catch { } if (TryGetPlayerIdForRig(rm, out var playerId)) { _remoteFallenPlayers.Add(playerId); } return; } try { rm.physicsRig.SetKneePelvisLimit(0.45f, 1.8f); } catch { } try { if ((Object)(object)rm.health != (Object)null) { rm.health.SetUsage(1f, 1f, 1f, 1f, 1f, 1f); } } catch { } if (TryGetPlayerIdForRig(rm, out var playerId2)) { _remoteFallenPlayers.Remove(playerId2); } } private void EnforceRemoteFallenState() { //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_017b: 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_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) if (_remoteFallenPlayers.Count == 0) { return; } byte[] array = new byte[_remoteFallenPlayers.Count]; _remoteFallenPlayers.CopyTo(array); foreach (byte b in array) { if (!TryResolvePlayerRig(b, out var rigManager) || (Object)(object)rigManager == (Object)null || (Object)(object)rigManager.physicsRig == (Object)null) { continue; } if (!IsBothLegsGone(rigManager)) { _remoteFallenPlayers.Remove(b); continue; } try { rigManager.physicsRig.SetKneePelvisLimit(0.15f, 0.45f); } catch { } try { if ((Object)(object)rigManager.health != (Object)null) { rigManager.health.SetUsage(1f, 1f, 0f, 0f, 1f, 1f); } } catch { } try { float num = Mathf.Pow(0.01f, Time.deltaTime); Rigidbody rbKnee = rigManager.physicsRig.rbKnee; Rigidbody rbFeet = rigManager.physicsRig.rbFeet; if ((Object)(object)rbKnee != (Object)null) { rbKnee.velocity *= num; rbKnee.angularVelocity *= num; } if ((Object)(object)rbFeet != (Object)null) { rbFeet.velocity *= num; rbFeet.angularVelocity *= num; } } catch { } if ((Object)(object)rigManager.remapHeptaRig != (Object)null) { try { rigManager.remapHeptaRig._vcActive = true; } catch { } } } } private bool TrySpawnGameBlood(Vector3 position, float intensity) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) return TrySpawnGameBlood(position, intensity, Color.white, 10f); } private bool TrySpawnGameBlood(Vector3 position, float intensity, Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) return TrySpawnGameBlood(position, intensity, color, 10f); } private bool TrySpawnGameBlood(Vector3 position, float intensity, Color color, float lifetimeSeconds) { //IL_0019: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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_0127: Expected O, but got Unknown //IL_012a: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) if (!EnableBloodEffects.Value || !EnableGameBloodEffects.Value || position == Vector3.zero) { return false; } if (lifetimeSeconds <= 0.05f) { return false; } float num = Mathf.Min(10f, Mathf.Max(0.05f, lifetimeSeconds)); if (TrySpawnVanillaBloodSpawnable(position, intensity, stream: false, Random.rotation, color, num)) { return true; } if (TryCloneLoadedGameBlood(position, intensity, color)) { return true; } if (!EnableFallbackBloodEffects.Value) { return false; } TryCacheGameBloodSpawnables(); if (_gameBloodSpawnableBarcodes.Count <= 0) { return false; } try { AssetSpawner instance = AssetSpawner._instance; if ((Object)(object)instance == (Object)null) { return false; } string text = _gameBloodSpawnableBarcodes[Random.Range(0, _gameBloodSpawnableBarcodes.Count)]; Spawnable val = new Spawnable { crateRef = new SpawnableCrateReference(text) }; if (!val.IsValid()) { return false; } float num2 = Mathf.Lerp(0.75f, 1.35f, Mathf.Clamp01(intensity)); Nullable scale = new Nullable(Vector3.one * num2); MelonCoroutines.Start(RunAsyncSpawnBlood(val, position, Random.rotation, scale, color, num)); return true; } catch (Exception ex) { MelonLogger.Warning("Game blood spawn failed: " + ex.Message); return false; } } private bool TrySpawnVanillaBloodSpawnable(Vector3 position, float intensity) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) return TrySpawnVanillaBloodSpawnable(position, intensity, stream: false, Random.rotation, Color.white, 10f); } private bool TrySpawnVanillaBloodSpawnable(Vector3 position, float intensity, bool stream, Quaternion rotation) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) return TrySpawnVanillaBloodSpawnable(position, intensity, stream, rotation, Color.white, 10f); } private bool TrySpawnVanillaBloodSpawnable(Vector3 position, float intensity, bool stream, Quaternion rotation, Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) return TrySpawnVanillaBloodSpawnable(position, intensity, stream, rotation, color, 10f); } private bool TrySpawnVanillaBloodSpawnable(Vector3 position, float intensity, bool stream, Quaternion rotation, Color color, float lifetimeSeconds) { //IL_00b7: 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_00dd: 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) try { if (lifetimeSeconds <= 0.05f) { return false; } float clearDelay = Mathf.Min(10f, Mathf.Max(0.05f, lifetimeSeconds)); if (!TryRegisterVanillaBloodSpawnables()) { return false; } Spawnable val; string text; if (stream && _bloodBagBlasterSpawnable != null) { val = _bloodBagBlasterSpawnable; text = "c1534c5a-1ea0-4156-920b-f8a8426c6173"; } else { val = ((intensity >= 0.65f) ? _largeBloodSplatterSpawnable : _smallBloodSplatterSpawnable); text = ((intensity >= 0.65f) ? VanillaBloodSpawnableBarcodes[1] : VanillaBloodSpawnableBarcodes[0]); } if (val == null) { return false; } Nullable scale = new Nullable(Vector3.zero) { hasValue = false }; Nullable groupId = new Nullable(0) { hasValue = false }; MelonCoroutines.Start(RunAsyncSpawnVanillaBlood(val, position, rotation, scale, groupId, color, clearDelay)); if (!_loggedVanillaBloodSpawnable) { _loggedVanillaBloodSpawnable = true; MelonLogger.Msg("Using vanilla BONELAB blood spawnable via SpawnAsync: " + text); } return true; } catch (Exception ex) { MelonLogger.Warning("Vanilla blood spawnable failed: " + ex.Message); } return false; } private bool TryRegisterVanillaBloodSpawnables() { if (_vanillaBloodSpawnablesRegistered) { return true; } try { _smallBloodSplatterSpawnable = CreateVanillaBloodSpawnable(VanillaBloodSpawnableBarcodes[0]); _largeBloodSplatterSpawnable = CreateVanillaBloodSpawnable(VanillaBloodSpawnableBarcodes[1]); _bloodBagBlasterSpawnable = CreateVanillaBloodSpawnable("c1534c5a-1ea0-4156-920b-f8a8426c6173"); AssetSpawner.Register(_smallBloodSplatterSpawnable); AssetSpawner.Register(_largeBloodSplatterSpawnable); AssetSpawner.Register(_bloodBagBlasterSpawnable); _vanillaBloodSpawnablesRegistered = true; return true; } catch (Exception ex) { if (!_loggedVanillaBloodSpawnableFailure) { _loggedVanillaBloodSpawnableFailure = true; MelonLogger.Warning("Vanilla blood spawnable registration failed: " + ex.Message); } _smallBloodSplatterSpawnable = null; _largeBloodSplatterSpawnable = null; _bloodBagBlasterSpawnable = null; _vanillaBloodSpawnablesRegistered = false; } return false; } private Spawnable CreateVanillaBloodSpawnable(string barcode) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown return new Spawnable { crateRef = new SpawnableCrateReference(barcode), policyData = null }; } private bool TryCloneLoadedGameBlood(Vector3 position, float intensity) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) return TryCloneLoadedGameBlood(position, intensity, Color.white); } private bool TryCloneLoadedGameBlood(Vector3 position, float intensity, Color color) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) ParticleSystem val = FindLoadedGameBloodParticle(); if ((Object)(object)val == (Object)null) { return false; } try { ParticleSystem val2 = Object.Instantiate(val, position, Random.rotation); if ((Object)(object)val2 == (Object)null) { return false; } ((Object)val2).name = "DeadPiece_GameBlood_" + ((Object)val).name; ((Component)val2).gameObject.SetActive(true); ((Component)val2).transform.position = position; ((Component)val2).transform.localScale = Vector3.one * Mathf.Lerp(0.85f, 1.35f, Mathf.Clamp01(intensity)); ParticleSystem[] array = Il2CppArrayBase.op_Implicit(((Component)val2).GetComponentsInChildren(true)); int num = Mathf.RoundToInt(Mathf.Lerp(4f, 18f, Mathf.Clamp01(intensity))); foreach (ParticleSystem val3 in array) { if (!((Object)(object)val3 == (Object)null)) { ((Component)val3).gameObject.SetActive(true); MainModule main = val3.main; main.startColor = MinMaxGradient.op_Implicit(color); main.simulationSpace = (ParticleSystemSimulationSpace)1; val3.Clear(false); val3.Play(false); val3.Emit(num); } } Object.Destroy((Object)(object)((Component)val2).gameObject, GetParticleDestroyDelay(val2)); return true; } catch (Exception ex) { MelonLogger.Warning("Loaded game blood clone failed: " + ex.Message); _gameBloodParticlePrefab = null; return false; } } private ParticleSystem FindLoadedGameBloodParticle() { if ((Object)(object)_gameBloodParticlePrefab != (Object)null) { return _gameBloodParticlePrefab; } if (Time.time - _lastGameBloodParticleSearchTime < 5f) { return null; } _lastGameBloodParticleSearchTime = Time.time; try { ParticleSystem[] array = Il2CppArrayBase.op_Implicit(Resources.FindObjectsOfTypeAll()); ParticleSystem val = null; int num = 0; foreach (ParticleSystem val2 in array) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null)) { int num2 = ScoreLoadedGameBloodParticle(val2); if (num2 > num) { num = num2; val = val2; } } } if ((Object)(object)val != (Object)null && num >= 70) { _gameBloodParticlePrefab = val; MelonLogger.Msg($"Using loaded BONELAB blood VFX: {((Object)val).name} (score {num})"); return _gameBloodParticlePrefab; } if (!_loggedMissingGameBloodParticles) { _loggedMissingGameBloodParticles = true; MelonLogger.Warning("No loaded BONELAB blood ParticleSystem found yet; will retry later."); } } catch (Exception ex) { MelonLogger.Warning("Loaded game blood scan failed: " + ex.Message); } return null; } private int ScoreLoadedGameBloodParticle(ParticleSystem particle) { string text = BuildParticleSearchText(particle); if (string.IsNullOrEmpty(text)) { return 0; } int num = 0; for (int i = 0; i < GameBloodPositiveKeywords.Length; i++) { if (text.Contains(GameBloodPositiveKeywords[i])) { num += 30; } } if (text.Contains("blood")) { num += 80; } if (text.Contains("bleed") || text.Contains("gore")) { num += 40; } for (int j = 0; j < GameBloodNegativeKeywords.Length; j++) { if (text.Contains(GameBloodNegativeKeywords[j])) { num -= 120; } } try { if (particle.main.maxParticles < 4) { num -= 25; } if (((Component)particle).gameObject.activeInHierarchy) { num += 5; } } catch { } return Mathf.Max(0, num); } private string BuildParticleSearchText(ParticleSystem particle) { string text = string.Empty; try { text = text + " " + ((Object)particle).name; text = text + " " + ((Object)((Component)particle).gameObject).name; if ((Object)(object)((Component)particle).transform != (Object)null && (Object)(object)((Component)particle).transform.root != (Object)null) { text = text + " " + ((Object)((Component)particle).transform.root).name; } ParticleSystemRenderer component = ((Component)particle).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)((Renderer)component).sharedMaterial != (Object)null) { text = text + " " + ((Object)((Renderer)component).sharedMaterial).name; if ((Object)(object)((Renderer)component).sharedMaterial.shader != (Object)null) { text = text + " " + ((Object)((Renderer)component).sharedMaterial.shader).name; } } } catch { } return text.ToLowerInvariant(); } private float GetParticleDestroyDelay(ParticleSystem particle) { try { float duration = particle.main.duration; return Mathf.Clamp(duration + 1.5f, 2f, 8f); } catch { return 4f; } } private void TryCacheGameBloodSpawnables() { if (_bloodSpawnablesScanned) { return; } try { AssetWarehouse instance = AssetWarehouse.Instance; if (instance == null || !AssetWarehouse.ready) { return; } List crates = instance.GetCrates(); if (crates == null || crates.Count == 0) { return; } string[] array = new string[10] { "blood", "bloody", "gore", "splat", "spray", "burst", "drip", "bleed", "wound", "squirt" }; string[] array2 = new string[6] { "decal", "quad", "poster", "icon", "ui", "marker" }; int num = 0; Enumerator enumerator = crates.GetEnumerator(); while (enumerator.MoveNext()) { Crate current = enumerator.Current; if ((Object)(object)current == (Object)null) { continue; } num++; SpawnableCrate val = ((Il2CppObjectBase)current).TryCast(); if ((Object)(object)val == (Object)null) { continue; } string text = ((((Scannable)val).Barcode != (Barcode)null) ? ((Object)((Scannable)val).Barcode).ToString() : string.Empty); string text2 = ((Scannable)val).Title ?? string.Empty; string text3 = (text + " " + text2).ToLowerInvariant(); bool flag = false; for (int i = 0; i < array2.Length; i++) { if (text3.Contains(array2[i])) { flag = true; break; } } if (flag) { continue; } string[] array3 = array; string[] array4 = array3; foreach (string value in array4) { if (text3.Contains(value)) { if (!string.IsNullOrEmpty(text) && !_gameBloodSpawnableBarcodes.Contains(text)) { _gameBloodSpawnableBarcodes.Add(text); } break; } } } _bloodSpawnablesScanned = _gameBloodSpawnableBarcodes.Count > 0; MelonLogger.Msg($"Scanned {num} crates, cached {_gameBloodSpawnableBarcodes.Count} blood spawnables."); } catch (Exception ex) { MelonLogger.Warning("Game blood scan failed: " + ex.Message); } } private void SpawnFallbackBlood(Vector3 position, float intensity, Color color) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown try { GameObject val = new GameObject("DeadPiece_FallbackBlood"); val.transform.position = position; ParticleSystem val2 = val.AddComponent(); ParticleSystemRenderer component = val.GetComponent(); if ((Object)(object)component != (Object)null) { ((Renderer)component).material = new Material(Shader.Find("Sprites/Default")); } MainModule main = val2.main; main.startLifetime = MinMaxCurve.op_Implicit(0.45f); main.startSpeed = MinMaxCurve.op_Implicit(Mathf.Lerp(0.6f, 2.2f, intensity)); main.startSize = MinMaxCurve.op_Implicit(Mathf.Lerp(0.025f, 0.065f, intensity)); main.startColor = MinMaxGradient.op_Implicit(color); main.maxParticles = 28; main.simulationSpace = (ParticleSystemSimulationSpace)1; EmissionModule emission = val2.emission; emission.enabled = false; ShapeModule shape = val2.shape; shape.shapeType = (ParticleSystemShapeType)0; shape.radius = 0.035f; val2.Emit(Mathf.RoundToInt(Mathf.Lerp(8f, 24f, intensity))); Object.Destroy((Object)(object)val, 1.25f); } catch (Exception ex) { MelonLogger.Warning("Fallback blood failed: " + ex.Message); } } private void SpawnBloodStream(RigManager rm, HumanBodyBones bone, Vector3 position) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00d4: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Expected O, but got Unknown //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Expected O, but got Unknown //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown if (!EnableBloodEffects.Value || (Object)(object)rm == (Object)null || (Object)(object)rm.avatar == (Object)null || (Object)(object)rm.avatar.animator == (Object)null) { return; } try { Transform boneTransform = rm.avatar.animator.GetBoneTransform(bone); if ((Object)(object)boneTransform == (Object)null) { return; } Vector3 val = GetBoneStreamDirection(rm, bone, boneTransform); if (val == Vector3.zero) { val = boneTransform.up; } if (!TrySpawnGameBlood(position + ((Vector3)(ref val)).normalized * 0.03f, 0.85f, GetBloodColor(rm))) { GameObject val2 = new GameObject("DeadPiece_BloodStream"); val2.transform.position = position; val2.transform.rotation = Quaternion.LookRotation(val); ParticleSystem val3 = val2.AddComponent(); ParticleSystemRenderer component = val2.GetComponent(); if ((Object)(object)component != (Object)null) { ((Renderer)component).material = new Material(Shader.Find("Sprites/Default")); } MainModule main = val3.main; main.startLifetime = MinMaxCurve.op_Implicit(1.2f); main.startSpeed = MinMaxCurve.op_Implicit(3.5f); main.startSize = MinMaxCurve.op_Implicit(0.04f); main.startColor = MinMaxGradient.op_Implicit(GetBloodColor(rm)); main.maxParticles = 120; main.simulationSpace = (ParticleSystemSimulationSpace)1; main.gravityModifier = MinMaxCurve.op_Implicit(0.6f); main.duration = 2.5f; main.loop = false; main.playOnAwake = true; EmissionModule emission = val3.emission; emission.enabled = true; emission.rateOverTime = MinMaxCurve.op_Implicit(35f); emission.SetBursts(Il2CppReferenceArray.op_Implicit((Burst[])(object)new Burst[3] { new Burst(0f, MinMaxCurve.op_Implicit(12f)), new Burst(0.15f, MinMaxCurve.op_Implicit(8f)), new Burst(0.4f, MinMaxCurve.op_Implicit(6f)) })); ShapeModule shape = val3.shape; shape.shapeType = (ParticleSystemShapeType)4; shape.angle = 12f; shape.radius = 0.03f; val3.Play(); Object.Destroy((Object)(object)val2, 4.5f); } } catch (Exception ex) { MelonLogger.Warning("Blood stream failed: " + ex.Message); } } private void SpawnDamageVolume(RigManager rm, HumanBodyBones bone, Vector3 position) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null || !EnableImpactBlood.Value) { return; } try { GameObject val = new GameObject("DeadPiece_DamageVolume"); val.transform.position = position; SphereCollider val2 = val.AddComponent(); ((Collider)val2).isTrigger = true; val2.radius = 0.12f; DamageVolume damageVolume = val.AddComponent(); damageVolume.Initialize(2f, 8f); Object.Destroy((Object)(object)val, 8.5f); } catch (Exception ex) { MelonLogger.Warning("SpawnDamageVolume failed: " + ex.Message); } } private void CaptureLocomotionState(RigManager rm) { if (_locomotionStateSaved || (Object)(object)rm == (Object)null || (Object)(object)rm.remapHeptaRig == (Object)null) { return; } try { float maxVelocity = rm.remapHeptaRig.maxVelocity; float currentMaxVelocity = rm.remapHeptaRig.currentMaxVelocity; if (maxVelocity > 0.25f) { _savedLocomotionMaxVelocity = maxVelocity; } if (currentMaxVelocity > 0.25f) { _savedLocomotionCurrentMaxVelocity = currentMaxVelocity; } else { _savedLocomotionCurrentMaxVelocity = _savedLocomotionMaxVelocity; } _savedLocomotionJumpEnabled = rm.remapHeptaRig.jumpEnabled; _locomotionStateSaved = true; } catch (Exception ex) { MelonLogger.Warning("CaptureLocomotionState failed: " + ex.Message); } } private float GetBaseMaxVelocity(RigManager rm) { if (_locomotionStateSaved && _savedLocomotionMaxVelocity > 0.25f) { return _savedLocomotionMaxVelocity; } if ((Object)(object)rm != (Object)null && (Object)(object)rm.remapHeptaRig != (Object)null && rm.remapHeptaRig.maxVelocity > 0.25f) { return rm.remapHeptaRig.maxVelocity; } return 4.5f; } private void DisableDoubleJump(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm.remapHeptaRig == (Object)null) { return; } try { rm.remapHeptaRig.doubleJump = false; } catch { } } private void ApplyMovementConstraints(RigManager rm) { DisableDoubleJump(rm); ApplyDeadpieceLegUsage(rm); ClearStaleNoLegRagdollState(rm); } private void SuppressNoLegRagdollForRespawn() { _suppressNoLegRagdollUntil = Time.time + 1.25f; } private void ResetLocalNoLegRagdollPermission() { _lastLocalRespawnTime = Time.time; _lastLocalBothLegsSeveredTime = -999f; } private void AllowLocalNoLegRagdollFromCurrentSever() { _lastLocalBothLegsSeveredTime = Time.time; _suppressNoLegRagdollUntil = -999f; } public bool IsNoLegRagdollSuppressed() { return Time.time < _suppressNoLegRagdollUntil; } public bool IsCrouchForcingSuppressed() { return Time.time < _suppressCrouchForcingUntil; } private void SuppressCrouchForcingForRestoration() { _suppressCrouchForcingUntil = Time.time + 2f; } public bool ShouldApplyLocalNoLegEffects(RigManager rm) { return (Object)(object)rm != (Object)null && (Object)(object)rm == (Object)(object)Player.RigManager && !IsNoLegRagdollSuppressed() && IsBothLegsGone(rm) && _lastLocalBothLegsSeveredTime > _lastLocalRespawnTime; } private void ClearStaleNoLegRagdollState(RigManager rm) { if (!((Object)(object)rm == (Object)null) && !IsBothLegsGone(rm) && _deadpieceFallenStateApplied) { RestoreNoLegFallenState(rm); } } private void ApplyDeadpieceLegUsage(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm != (Object)(object)Player.RigManager || (Object)(object)rm.health == (Object)null) { return; } if (ShouldApplyLocalNoLegEffects(rm)) { try { rm.health.SetUsage(1f, 1f, 0f, 0f, 1f, 1f); _deadpieceNoLegUsageApplied = true; } catch (Exception ex) { MelonLogger.Warning("Apply no-leg usage failed: " + ex.Message); } BlockNoLegJump(rm); ApplyNoLegFallenState(rm); LockNoLegLocomotion(rm); return; } if (IsBothLegsGone(rm)) { ForceClearNoLegRagdollState(rm); if (IsNoLegRagdollSuppressed()) { StabilizeRespawnLocomotion(rm); } else { RestoreNoLegJump(rm); } RestoreDeadpieceLegUsage(rm); return; } if (_deadpieceNoLegUsageApplied) { RestoreDeadpieceLegUsage(rm); } if (_deadpieceJumpBlocked) { RestoreNoLegJump(rm); } if (_deadpieceFallenStateApplied) { RestoreNoLegFallenState(rm); } } private void RestoreDeadpieceLegUsage(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm != (Object)(object)Player.RigManager || (Object)(object)rm.health == (Object)null) { return; } try { rm.health.SetUsage(1f, 1f, 1f, 1f, 1f, 1f); _deadpieceNoLegUsageApplied = false; } catch (Exception ex) { MelonLogger.Warning("Restore leg usage failed: " + ex.Message); } } private void BlockNoLegJump(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm != (Object)(object)Player.RigManager || (Object)(object)rm.remapHeptaRig == (Object)null) { return; } try { if (!_deadpieceJumpBlocked) { _savedLocomotionJumpEnabled = rm.remapHeptaRig.jumpEnabled; _deadpieceJumpBlocked = true; } rm.remapHeptaRig.jumpEnabled = false; rm.remapHeptaRig.doubleJump = false; rm.remapHeptaRig._jumping = false; rm.remapHeptaRig._jumpStage = 0; rm.remapHeptaRig._jumpCycle = 0f; } catch (Exception ex) { MelonLogger.Warning("Block no-leg jump failed: " + ex.Message); } } private void RestoreNoLegJump(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm != (Object)(object)Player.RigManager || (Object)(object)rm.remapHeptaRig == (Object)null) { return; } try { _savedLocomotionJumpEnabled = true; rm.remapHeptaRig.jumpEnabled = true; rm.remapHeptaRig.doubleJump = false; _deadpieceJumpBlocked = false; } catch (Exception ex) { MelonLogger.Warning("Restore no-leg jump failed: " + ex.Message); } } private void ApplyNoLegFallenState(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm.physicsRig == (Object)null) { return; } try { rm.physicsRig.SetKneePelvisLimit(0.15f, 0.45f); _deadpieceFallenStateApplied = true; } catch (Exception ex) { MelonLogger.Warning("Apply no-leg fallen state failed: " + ex.Message); } } private void RestoreNoLegFallenState(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm.physicsRig == (Object)null) { return; } try { rm.physicsRig.SetKneePelvisLimit(0.45f, 1.8f); _deadpieceFallenStateApplied = false; } catch (Exception ex) { MelonLogger.Warning("Restore no-leg fallen state failed: " + ex.Message); } } private void ForceClearNoLegRagdollState(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm.physicsRig == (Object)null) { return; } try { rm.physicsRig.SetKneePelvisLimit(0.45f, 1.8f); _deadpieceFallenStateApplied = false; } catch (Exception ex) { MelonLogger.Warning("ForceClearNoLegRagdollState failed: " + ex.Message); } } private void StabilizeRespawnLocomotion(RigManager rm) { //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0180: 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_0198: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00df: 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_00f7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null || (Object)(object)rm != (Object)(object)Player.RigManager) { return; } try { RemapRig remapHeptaRig = rm.remapHeptaRig; if ((Object)(object)remapHeptaRig != (Object)null) { if (!_deadpieceJumpBlocked) { _savedLocomotionJumpEnabled = remapHeptaRig.jumpEnabled; _deadpieceJumpBlocked = true; } remapHeptaRig.jumpEnabled = false; remapHeptaRig.doubleJump = false; remapHeptaRig._jumping = false; remapHeptaRig._jumpStage = 0; remapHeptaRig._jumpCycle = 0f; remapHeptaRig._timeOfFlight = 0f; remapHeptaRig._currentVelocity = Vector2.zero; remapHeptaRig._currentAcceleration = Vector2.zero; remapHeptaRig._locoDebt = Vector2.zero; remapHeptaRig._locoApplied = Vector2.zero; remapHeptaRig._physDebt = Vector2.zero; remapHeptaRig._physApplied = Vector2.zero; remapHeptaRig._trackedDebt = Vector2.zero; remapHeptaRig._trackedApplied = Vector2.zero; remapHeptaRig._artificialDelta = Vector2.zero; remapHeptaRig.travState = (TraversalState)0; remapHeptaRig.vertState = (VertState)0; } PhysicsRig physicsRig = rm.physicsRig; if ((Object)(object)physicsRig != (Object)null) { physicsRig.groundVelocity = Vector3.zero; physicsRig.skidVelocity = Vector3.zero; physicsRig.skidSpeed = 0f; physicsRig.groundAngVelocity = 0f; physicsRig.wholeBodyVelocity = Vector3.zero; physicsRig.pelvisVelocity = Vector3.zero; physicsRig.pelvisAccel = Vector3.zero; physicsRig._stepDelta = Vector2.zero; physicsRig._stepVel = Vector2.zero; physicsRig._stepDeltaOverTimeBuffer = Vector2.zero; ClampFullVelocity(physicsRig.rbFeet); ClampFullVelocity(physicsRig.rbKnee); } } catch (Exception ex) { MelonLogger.Warning("Respawn locomotion stabilize failed: " + ex.Message); } } private void LockNoLegLocomotion(RigManager rm) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rm == (Object)null || (Object)(object)rm != (Object)(object)Player.RigManager || (Object)(object)rm.physicsRig == (Object)null) { return; } try { PhysicsRig physicsRig = rm.physicsRig; physicsRig.footSupported = 0f; physicsRig.groundVelocity = Vector3.zero; physicsRig.skidVelocity = Vector3.zero; physicsRig.skidSpeed = 0f; physicsRig.groundAngVelocity = 0f; physicsRig.wholeBodyVelocity = FlattenHorizontalVelocity(physicsRig.wholeBodyVelocity); physicsRig.pelvisVelocity = FlattenHorizontalVelocity(physicsRig.pelvisVelocity); physicsRig._stepDelta = Vector2.zero; physicsRig._stepVel = Vector2.zero; physicsRig._stepDeltaOverTimeBuffer = Vector2.zero; ClampPlanarVelocity(physicsRig.rbFeet); ClampPlanarVelocity(physicsRig.rbKnee); } catch (Exception ex) { MelonLogger.Warning("No-leg locomotion lock failed: " + ex.Message); } } private static Vector3 FlattenHorizontalVelocity(Vector3 velocity) { //IL_0019: 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_001d: Unknown result type (might be due to invalid IL or missing references) velocity.x = 0f; velocity.z = 0f; return velocity; } private static void ClampPlanarVelocity(Rigidbody rb) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rb == (Object)null)) { Vector3 velocity = rb.velocity; velocity.x = 0f; velocity.z = 0f; rb.velocity = velocity; rb.angularVelocity = Vector3.zero; } } private static void ClampFullVelocity(Rigidbody rb) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rb == (Object)null)) { rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } } private void SaveOriginalLimits(RigManager rm) { if (!((Object)(object)rm == (Object)null) && !((Object)(object)rm.physicsRig == (Object)null) && !_limitsSaved) { _limitsSaved = true; } } private void RestoreOriginalLimits(RigManager rm) { _limitsSaved = false; } private void RestoreLocomotion() { try { RigManager rigManager = Player.RigManager; if ((Object)(object)rigManager != (Object)null && (Object)(object)rigManager.remapHeptaRig != (Object)null) { rigManager.remapHeptaRig.doubleJump = false; rigManager.remapHeptaRig.jumpEnabled = true; rigManager.remapHeptaRig._spineCrouchOff = 0f; rigManager.remapHeptaRig._crouchTarget = 0f; rigManager.remapHeptaRig.vertState = (VertState)0; } } catch (Exception ex) { MelonLogger.Warning("RestoreLocomotion failed: " + ex.Message); } } private void EnforceBothLegsGoneState(RigManager rm) { if (!((Object)(object)rm == (Object)null) && !((Object)(object)rm.remapHeptaRig == (Object)null)) { rm.remapHeptaRig._vcActive = true; } } private bool IsLeftLegBone(HumanBodyBones bone) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 return (int)bone == 1 || (int)bone == 3 || (int)bone == 5; } private bool IsRightLegBone(HumanBodyBones bone) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 return (int)bone == 2 || (int)bone == 4 || (int)bone == 6; } private void ApplySecondLegRagdoll(RigManager rm, HumanBodyBones bone, bool wasLeftLegGone, bool wasRightLegGone) { } private void ResetLegRagdoll(RigManager rm) { } public void SyncLegState(RigManager rm, byte legState) { if (PlayerIDManager.LocalID != null && !((Object)(object)rm == (Object)null)) { NetworkSync.SetPlayerMetadata(PlayerIDManager.LocalSmallID, "LegState", legState.ToString()); } } public void ApplyRemoteLegState(byte playerId, byte legState) { RigRefs val = default(RigRefs); if (PlayerRepUtilities.TryGetReferences(playerId, ref val) && !((Object)(object)((val != null) ? val.RigManager : null) == (Object)null)) { RigManager rigManager = val.RigManager; bool flag = (legState & 3) == 3; if ((Object)(object)rigManager.physicsRig != (Object)null) { rigManager.physicsRig.SetKneePelvisLimit(flag ? 0.15f : 0.45f, flag ? 0.45f : 1.8f); } if ((Object)(object)rigManager.health != (Object)null) { rigManager.health.SetUsage(1f, 1f, flag ? 0f : 1f, flag ? 0f : 1f, 1f, 1f); } if (flag) { _remoteFallenPlayers.Add(playerId); } else { _remoteFallenPlayers.Remove(playerId); } } } static DeadPieceMod() { HumanBodyBones[] array = new HumanBodyBones[17]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); DamageBones = (HumanBodyBones[])(object)array; FatalBones = new HashSet { (HumanBodyBones)10, (HumanBodyBones)7, (HumanBodyBones)0 }; TorsoBones = new HashSet { (HumanBodyBones)10, (HumanBodyBones)7, (HumanBodyBones)0 }; CoreNearestExcludeBones = new HashSet { (HumanBodyBones)7, (HumanBodyBones)0, (HumanBodyBones)10, (HumanBodyBones)21, (HumanBodyBones)22 }; NetworkBones = DamageBones; BoneToIndexMap = BuildBoneToIndexMap(); GameBloodPositiveKeywords = new string[10] { "blood", "bleed", "gore", "wound", "flesh", "splat", "spray", "squirt", "hemo", "burst" }; GameBloodNegativeKeywords = new string[17] { "decal", "quad", "ui", "icon", "water", "muzzle", "spark", "smoke", "steam", "dust", "fire", "flame", "ash", "shell", "brass", "laser", "confetti" }; VanillaBloodSpawnableBarcodes = new string[2] { "c1534c5a-06ef-49a4-830a-256244656361", "c1534c5a-4a64-4e30-ac16-897944656361" }; } } internal static class ExplosivePatches { private static bool _registered; internal static void TryRegister(Harmony harmony) { if (_registered || harmony == null) { return; } try { int num = 0; if (num > 0) { MelonLogger.Msg("[DeadPiece] Explosive patches applied: " + num); } _registered = num > 0; } catch (Exception ex) { MelonLogger.Warning("[DeadPiece] Explosive patch registration failed: " + ex.Message); } } private static int TryPatchMethod(Harmony harmony, string typeName, string methodName, Type patchType, string postfixName) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown Type type = null; try { type = AccessTools.TypeByName(typeName); } catch { return 0; } if (type == null) { return 0; } MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null); if (methodInfo == null) { return 0; } MethodInfo methodInfo2 = AccessTools.Method(patchType, postfixName, (Type[])null, (Type[])null); if (methodInfo2 == null) { return 0; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return 1; } private static void RigidbodyProjectileBlowUpPostfix(Component __instance, Attack attack) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if (DeadPieceMod.EnableBlastLimbDamage.Value && DeadPieceMod.Instance != null && !((Object)(object)__instance == (Object)null)) { float blastRadius = ReadFloatMember(__instance, "BlastRadius"); float num = ReadFloatMember(__instance, "BlastDamage"); if (num <= 0f && attack.damage > 0f) { num = attack.damage; } Vector3 origin = __instance.transform.position; if (attack.origin != Vector3.zero) { origin = attack.origin; } DeadPieceMod.Instance.ApplyRadialBlast(origin, blastRadius, num); } } private static void SimpleExplosionForcePostfix(Component __instance) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (DeadPieceMod.EnableBlastLimbDamage.Value && DeadPieceMod.Instance != null && !((Object)(object)__instance == (Object)null)) { float blastRadius = ReadFloatMember(__instance, "radius"); float blastDamage = ReadFloatMember(__instance, "power"); DeadPieceMod.Instance.ApplyRadialBlast(__instance.transform.position, blastRadius, blastDamage); } } private static float ReadFloatMember(Component instance, string memberName) { if ((Object)(object)instance == (Object)null) { return 0f; } Type type = ((object)instance).GetType(); while (type != null) { FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { try { if (field.GetValue(instance) is float result) { return result; } } catch { } } PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanRead) { try { if (property.GetValue(instance) is float result2) { return result2; } } catch { } } type = type.BaseType; } return 0f; } } internal static class FusionRigLoadingFix { private static bool _registered; internal static void TryRegister(Harmony harmony) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown if (_registered || harmony == null) { return; } Type typeFromHandle = typeof(NetworkPlayer); if (typeFromHandle == null) { return; } MethodInfo methodInfo = typeFromHandle.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name.Contains("g__IsPlayerLoading")); if (methodInfo == null) { MelonLogger.Warning("[DeadPiece] Could not find Fusion's IsPlayerLoading method (NRE workaround skipped)"); return; } MethodInfo methodInfo2 = AccessTools.Method(typeof(FusionRigLoadingFix), "Prefix", (Type[])null, (Type[])null); if (!(methodInfo2 == null)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _registered = true; MelonLogger.Msg("[DeadPiece] Applied Fusion WaitAndCreateRig NRE workaround"); } } private static bool Prefix(NetworkPlayer __instance, ref bool __result) { if (__instance == null) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(Health), "SetAvatar", new Type[] { typeof(Avatar) })] public static class HealthSetAvatarPatch { [HarmonyPostfix] public static void Postfix(Health __instance, Avatar avatar) { DeadPieceMod.Instance?.OnHealthAvatarSet(__instance, avatar); } } [HarmonyPatch(typeof(Health), "SetFullHealth")] public static class HealthSetFullHealthPatch { [HarmonyPrefix] public static void Prefix(Health __instance, out float __state) { __state = (((Object)(object)__instance != (Object)null) ? __instance.curr_Health : (-1f)); } [HarmonyPostfix] public static void Postfix(Health __instance, float __state) { DeadPieceMod.Instance?.OnHealthSetFullHealth(__instance, __state); } } public static class NetworkSync { public static bool Initialize() { try { return FusionSyncManager.InitializeSingleton(); } catch (Exception ex) { MelonLogger.Error("[DeadPiece] Network transport initialization failed: " + ex.Message); return false; } } public static bool RegisterHandlers() { try { return FusionSyncManager.RegisterHandlers(); } catch (Exception ex) { MelonLogger.Error("[DeadPiece] Network handler registration failed: " + ex.Message); return false; } } public static bool RegisterCallbacks(Action onLimbHit, Action onLimbSever, Action onRespawn, Action onBloodColor, Action onFullState, Func getStateMask) { return FusionSyncManager.RegisterCallbacks(onLimbHit, onLimbSever, onRespawn, onBloodColor, onFullState, getStateMask); } public static void ProcessMainThreadQueue() { FusionSyncManager.ProcessMainThreadQueue(); } public static void ResetSessionState() { FusionSyncManager.ResetSessionState(); } public static void ForgetPlayer(byte playerId) { FusionSyncManager.ForgetPlayer(playerId); } public static void ClearCallbacks() { FusionSyncManager.ClearCallbacks(); } public static void SendLimbHit(byte targetPlayerId, byte boneIndex, float damage, Vector3 hitPoint) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) FusionSyncManager.Instance?.SendLimbHit(targetPlayerId, boneIndex, damage, hitPoint); } public static void SendLimbSever(byte targetPlayerId, byte boneIndex, Vector3 hitPoint, Vector3 hitNormal, float damage) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) FusionSyncManager.Instance?.SendLimbSever(targetPlayerId, boneIndex, hitPoint, hitNormal, damage); } public static void SendRespawn(byte playerId) { FusionSyncManager.Instance?.SendRespawn(playerId); } public static void SendBloodColor(byte playerId, byte colorIndex) { FusionSyncManager.Instance?.SendBloodColor(playerId, colorIndex); } public static void SendFullState(byte playerId, uint goneBoneMask, byte bloodColorIndex, ushort sequence = 0) { FusionSyncManager.Instance?.SendFullState(playerId, goneBoneMask, bloodColorIndex, sequence); } public static void SetPlayerMetadata(byte targetPlayerId, string key, string value) { } } [HarmonyPatch(typeof(RemapRig), "ApplyMovement")] internal static class NoLegLocomotionPatch { private static void Prefix(RemapRig __instance, ref Vector2 axis, ref bool inputPressed) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_002c: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0068: Unknown result type (might be due to invalid IL or missing references) if (ShouldBlock(__instance)) { axis = Vector2.zero; inputPressed = false; __instance._currentVelocity = Vector2.zero; __instance._currentAcceleration = Vector2.zero; __instance._locoDebt = Vector2.zero; __instance._locoApplied = Vector2.zero; __instance._trackedDebt = Vector2.zero; __instance._trackedApplied = Vector2.zero; __instance._artificialDelta = Vector2.zero; } } internal static bool ShouldBlock(RemapRig remapRig) { RigManager rigManager = Player.RigManager; if ((Object)(object)remapRig != (Object)null && (Object)(object)rigManager != (Object)null && (Object)(object)rigManager.remapHeptaRig == (Object)(object)remapRig && DeadPieceMod.Instance != null && DeadPieceMod.Instance.ShouldApplyLocalNoLegEffects(rigManager)) { if (DeadPieceMod.Instance.IsHoldingNimbusGun(rigManager)) { return false; } return true; } return false; } } [HarmonyPatch(typeof(RemapRig), "Jump")] internal static class NoLegJumpPatch { private static bool Prefix(RemapRig __instance) { return !NoLegLocomotionPatch.ShouldBlock(__instance); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(DeadPieceMod), "ApplyDeadpieceLegUsage")] internal static class NimbusBlockApplyDeadpieceUsage { [HarmonyPrefix] private static bool Prefix(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm != (Object)(object)Player.RigManager) { return true; } return !DeadPieceMod.Instance.IsHoldingNimbusGun(rm); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(DeadPieceMod), "LockNoLegLocomotion")] internal static class NimbusBlockLockNoLeg { [HarmonyPrefix] private static bool Prefix(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm != (Object)(object)Player.RigManager) { return true; } return !DeadPieceMod.Instance.IsHoldingNimbusGun(rm); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(DeadPieceMod), "ApplyNoLegFallenState")] internal static class NimbusBlockFallenState { [HarmonyPrefix] private static bool Prefix(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm != (Object)(object)Player.RigManager) { return true; } return !DeadPieceMod.Instance.IsHoldingNimbusGun(rm); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(DeadPieceMod), "EnforceBothLegsGoneState")] internal static class NimbusBlockEnforceBothLegs { [HarmonyPrefix] private static bool Prefix(RigManager rm) { if ((Object)(object)rm == (Object)null || (Object)(object)rm != (Object)(object)Player.RigManager) { return true; } return !DeadPieceMod.Instance.IsHoldingNimbusGun(rm); } } [HarmonyPriority(800)] [HarmonyPatch(typeof(DeadPieceMod), "OnUpdate")] internal static class NimbusVelocityRestore { private static Vector3 _savedKneeVel; private static Vector3 _savedKneeAngVel; private static Vector3 _savedFeetVel; private static Vector3 _savedFeetAngVel; private static bool _active; [HarmonyPrefix] private static void Prefix() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00c5: Unknown result type (might be due to invalid IL or missing references) _active = false; RigManager rigManager = Player.RigManager; if ((Object)(object)rigManager == (Object)null || !DeadPieceMod.Instance.IsBothLegsGone(rigManager) || !DeadPieceMod.Instance.IsHoldingNimbusGun(rigManager)) { return; } PhysicsRig physicsRig = rigManager.physicsRig; if (!((Object)(object)physicsRig == (Object)null)) { if ((Object)(object)physicsRig.rbKnee != (Object)null) { _savedKneeVel = physicsRig.rbKnee.velocity; _savedKneeAngVel = physicsRig.rbKnee.angularVelocity; } if ((Object)(object)physicsRig.rbFeet != (Object)null) { _savedFeetVel = physicsRig.rbFeet.velocity; _savedFeetAngVel = physicsRig.rbFeet.angularVelocity; } _active = true; } } [HarmonyPostfix] private static void Postfix() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_00ac: Unknown result type (might be due to invalid IL or missing references) if (!_active) { return; } RigManager rigManager = Player.RigManager; if ((Object)(object)rigManager == (Object)null) { _active = false; return; } PhysicsRig physicsRig = rigManager.physicsRig; if ((Object)(object)physicsRig == (Object)null) { _active = false; return; } if ((Object)(object)physicsRig.rbKnee != (Object)null) { physicsRig.rbKnee.velocity = _savedKneeVel; physicsRig.rbKnee.angularVelocity = _savedKneeAngVel; } if ((Object)(object)physicsRig.rbFeet != (Object)null) { physicsRig.rbFeet.velocity = _savedFeetVel; physicsRig.rbFeet.angularVelocity = _savedFeetAngVel; } _active = false; } } } namespace DeadPiece.Networking { public sealed class FusionSyncManager { public const byte RequestPhase = 0; public const byte AuthoritativePhase = 1; private const int TrackedBoneCount = 17; private const byte MaxBloodColorIndex = 9; private const float MaxAcceptedDamage = 100000f; private const int MaxQueueSize = 1024; private const int MaxRecentEvents = 4096; public static Action OnLimbHitCallback; public static Action OnLimbSeverCallback; public static Action OnRespawnCallback; public static Action OnBloodColorCallback; public static Action OnFullStateCallback; public static Func GetStateMaskCallback; private static readonly ConcurrentQueue MainThreadQueue = new ConcurrentQueue(); private static readonly HashSet RecentEventKeys = new HashSet(); private static readonly Queue RecentEventOrder = new Queue(); private static readonly Dictionary AuthoritativeStateSequences = new Dictionary(); private static readonly Dictionary AuthoritativeStateMasks = new Dictionary(); private static readonly Dictionary AuthoritativeBloodColors = new Dictionary(); private static readonly object EventLock = new object(); private static readonly object SequenceLock = new object(); private static bool _handlersRegistered; private static bool _initializedLogged; private static byte _localPlayerId = byte.MaxValue; private static uint _eventCounter; public static FusionSyncManager Instance { get; private set; } public static bool IsReady { get; private set; } private FusionSyncManager() { } public static bool InitializeSingleton() { if (Instance == null) { Instance = new FusionSyncManager(); } RefreshLocalPlayerId(); IsReady = true; if (!_initializedLogged) { _initializedLogged = true; MelonLogger.Msg(ConsoleColor.Gray, "[DeadPiece/Net] Host-authoritative Fusion transport initialized."); } return true; } public static bool RegisterCallbacks(Action onLimbHit, Action onLimbSever, Action onRespawn, Action onBloodColor, Action onFullState, Func getStateMask) { OnLimbHitCallback = onLimbHit; OnLimbSeverCallback = onLimbSever; OnRespawnCallback = onRespawn; OnBloodColorCallback = onBloodColor; OnFullStateCallback = onFullState; GetStateMaskCallback = getStateMask; bool flag = onLimbHit != null && onLimbSever != null && onRespawn != null && onBloodColor != null && onFullState != null && getStateMask != null; if (flag) { MelonLogger.Msg(ConsoleColor.Gray, "[DeadPiece/Net] Gameplay callbacks registered (6/6)."); } else { MelonLogger.Warning("[DeadPiece/Net] One or more gameplay callbacks are missing."); } return flag; } public static void ClearCallbacks() { OnLimbHitCallback = null; OnLimbSeverCallback = null; OnRespawnCallback = null; OnBloodColorCallback = null; OnFullStateCallback = null; GetStateMaskCallback = null; } public static bool RegisterHandlers() { if (_handlersRegistered) { return true; } InitializeSingleton(); try { RegisterHandlerIfMissing(); RegisterHandlerIfMissing(); RegisterHandlerIfMissing(); RegisterHandlerIfMissing(); RegisterHandlerIfMissing(); _handlersRegistered = true; MelonLogger.Msg(ConsoleColor.Gray, "[DeadPiece/Net] Fusion message handlers registered once."); return true; } catch (Exception ex) { MelonLogger.Error("[DeadPiece/Net] Failed to register Fusion handlers: " + ex.Message); return false; } } private static void RegisterHandlerIfMissing() where T : ModuleMessageHandler, new() { if (ModuleMessageManager.GetHandlerByType(typeof(T)) == null) { ModuleMessageManager.RegisterHandler(); } } public static void ProcessMainThreadQueue() { for (int i = 0; i < 1024; i++) { if (!MainThreadQueue.TryDequeue(out var result)) { break; } try { result?.Invoke(); } catch (Exception ex) { MelonLogger.Error("[DeadPiece/Net] Main-thread network action failed: " + ex); } } } public static void ResetSessionState() { lock (EventLock) { RecentEventKeys.Clear(); RecentEventOrder.Clear(); _eventCounter = 0u; } lock (SequenceLock) { AuthoritativeStateSequences.Clear(); AuthoritativeStateMasks.Clear(); AuthoritativeBloodColors.Clear(); } _localPlayerId = byte.MaxValue; Action result; while (MainThreadQueue.TryDequeue(out result)) { } } public static void ForgetPlayer(byte playerId) { lock (EventLock) { int count = RecentEventOrder.Count; for (int i = 0; i < count; i++) { ulong num = RecentEventOrder.Dequeue(); if ((byte)(num >> 32) == playerId) { RecentEventKeys.Remove(num); } else { RecentEventOrder.Enqueue(num); } } } lock (SequenceLock) { AuthoritativeStateSequences.Remove(playerId); AuthoritativeStateMasks.Remove(playerId); AuthoritativeBloodColors.Remove(playerId); } } private static void MarshalToMainThread(Action action) { if (action != null) { if (MainThreadQueue.Count >= 1024) { MelonLogger.Warning("[DeadPiece/Net] Main-thread queue is full; dropping a stale network action."); } else { MainThreadQueue.Enqueue(action); } } } private static void RefreshLocalPlayerId() { try { _localPlayerId = ((PlayerIDManager.LocalID != null) ? PlayerIDManager.LocalSmallID : byte.MaxValue); } catch { _localPlayerId = byte.MaxValue; } } private static byte GetLocalPlayerId() { RefreshLocalPlayerId(); return _localPlayerId; } private static bool IsKnownPlayer(byte playerId) { try { if (PlayerIDManager.LocalID != null && PlayerIDManager.LocalSmallID == playerId) { return true; } foreach (PlayerID playerID in PlayerIDManager.PlayerIDs) { if (playerID != null && playerID.SmallID == playerId) { return true; } } } catch { } return false; } private static bool RequestSenderMatches(byte? sender, byte claimedPlayerId) { if (!sender.HasValue) { return NetworkInfo.IsHost && claimedPlayerId == GetLocalPlayerId(); } return sender.Value == claimedPlayerId; } private static bool IsAuthoritativeSender(byte? sender) { if (NetworkInfo.IsHost) { return true; } try { return !sender.HasValue || sender.Value == 0; } catch { return !sender.HasValue; } } private static bool IsFinite(float value) { return !float.IsNaN(value) && !float.IsInfinity(value); } private static bool IsFinite(Vector3 value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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) return IsFinite(value.x) && IsFinite(value.y) && IsFinite(value.z); } private static uint NextEventId() { lock (EventLock) { _eventCounter++; if (_eventCounter == 0) { _eventCounter = 1u; } return _eventCounter; } } private static bool RememberEvent(byte sourcePlayerId, uint eventId) { ulong item = ((ulong)sourcePlayerId << 32) | eventId; lock (EventLock) { if (!RecentEventKeys.Add(item)) { return false; } RecentEventOrder.Enqueue(item); while (RecentEventOrder.Count > 4096) { RecentEventKeys.Remove(RecentEventOrder.Dequeue()); } return true; } } private static ushort NextAuthoritativeSequence(byte playerId) { lock (SequenceLock) { AuthoritativeStateSequences.TryGetValue(playerId, out var value); value++; if (value == 0) { value = 1; } AuthoritativeStateSequences[playerId] = value; return value; } } private static uint GetAuthoritativeStateMask(byte playerId) { lock (SequenceLock) { if (AuthoritativeStateMasks.TryGetValue(playerId, out var value)) { return value; } } return GetStateMaskCallback?.Invoke(playerId) ?? 0; } private static void StoreAuthoritativeState(byte playerId, uint goneBoneMask, byte bloodColorIndex) { lock (SequenceLock) { AuthoritativeStateMasks[playerId] = goneBoneMask & 0x1FFFF; AuthoritativeBloodColors[playerId] = bloodColorIndex; } } private static void StoreAuthoritativeBloodColor(byte playerId, byte bloodColorIndex) { lock (SequenceLock) { AuthoritativeBloodColors[playerId] = bloodColorIndex; } } private static bool ValidateHit(byte sourcePlayerId, byte targetPlayerId, byte boneIndex, float damage, Vector3 hitPoint) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) return sourcePlayerId != byte.MaxValue && targetPlayerId != byte.MaxValue && boneIndex < 17 && IsKnownPlayer(sourcePlayerId) && IsKnownPlayer(targetPlayerId) && IsFinite(damage) && damage > 0f && damage <= 100000f && IsFinite(hitPoint); } public void SendLimbHit(byte targetPlayerId, byte boneIndex, float damage, Vector3 hitPoint) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) if (!NetworkInfo.HasServer) { return; } byte localPlayerId = GetLocalPlayerId(); MelonLogger.Msg(ConsoleColor.DarkCyan, $"[DeadPiece/Net] SendLimbHit src={localPlayerId} tgt={targetPlayerId} bone={boneIndex} dmg={damage:F1} host={NetworkInfo.IsHost}"); LimbHitData limbHitData = new LimbHitData { Phase = 0, SourcePlayerId = localPlayerId, TargetPlayerId = targetPlayerId, BoneIndex = boneIndex, Damage = damage, HitPoint = hitPoint, EventId = NextEventId() }; try { if (NetworkInfo.IsHost) { OnLimbHitReceived(limbHitData, localPlayerId); } else { MessageRelay.RelayModule(limbHitData, CommonMessageRoutes.ReliableToServer); } } catch (Exception ex) { MelonLogger.Error("[DeadPiece/Net] SendLimbHit failed: " + ex.Message); } } public void OnLimbHitReceived(LimbHitData data, byte? sender) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (data == null || !ValidateHit(data.SourcePlayerId, data.TargetPlayerId, data.BoneIndex, data.Damage, data.HitPoint)) { MelonLogger.Warning("[DeadPiece/Net] Dropped invalid limb-hit packet."); } else if (data.Phase == 0) { if (!NetworkInfo.IsHost || !RequestSenderMatches(sender, data.SourcePlayerId) || !RememberEvent(data.SourcePlayerId, data.EventId)) { MelonLogger.Warning($"[DeadPiece/Net] OnLimbHitReceived: rejected request phase host={NetworkInfo.IsHost} sender={sender} src={data.SourcePlayerId}"); return; } MelonLogger.Msg(ConsoleColor.Green, $"[DeadPiece/Net] OnLimbHitReceived: processing request tgt={data.TargetPlayerId} bone={data.BoneIndex} dmg={data.Damage:F1}"); MarshalToMainThread(delegate { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) OnLimbHitCallback?.Invoke(data.TargetPlayerId, data.BoneIndex, data.Damage, data.HitPoint, arg5: true); data.Phase = 1; MessageRelay.RelayModule(data, CommonMessageRoutes.ReliableToClients); }); } else if (data.Phase == 1 && !NetworkInfo.IsHost && IsAuthoritativeSender(sender) && RememberEvent(data.SourcePlayerId, data.EventId)) { MelonLogger.Msg(ConsoleColor.Green, $"[DeadPiece/Net] OnLimbHitReceived: applying authoritative tgt={data.TargetPlayerId} bone={data.BoneIndex} dmg={data.Damage:F1}"); MarshalToMainThread(delegate { //IL_0032: Unknown result type (might be due to invalid IL or missing references) OnLimbHitCallback?.Invoke(data.TargetPlayerId, data.BoneIndex, data.Damage, data.HitPoint, arg5: false); }); } } public void SendLimbSever(byte targetPlayerId, byte boneIndex, Vector3 hitPoint, Vector3 hitNormal, float damage) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (!NetworkInfo.HasServer) { return; } byte localPlayerId = GetLocalPlayerId(); LimbSeverData limbSeverData = new LimbSeverData { Phase = 0, SourcePlayerId = localPlayerId, TargetPlayerId = targetPlayerId, BoneIndex = boneIndex, HitPoint = hitPoint, HitNormal = hitNormal, Damage = damage, EventId = NextEventId() }; try { if (NetworkInfo.IsHost) { OnLimbSeverReceived(limbSeverData, localPlayerId); } else { MessageRelay.RelayModule(limbSeverData, CommonMessageRoutes.ReliableToServer); } } catch (Exception ex) { MelonLogger.Error("[DeadPiece/Net] SendLimbSever failed: " + ex.Message); } } public void OnLimbSeverReceived(LimbSeverData data, byte? sender) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (data == null || !ValidateHit(data.SourcePlayerId, data.TargetPlayerId, data.BoneIndex, Math.Max(0.001f, data.Damage), data.HitPoint) || !IsFinite(data.HitNormal)) { MelonLogger.Warning("[DeadPiece/Net] Dropped invalid limb-sever packet."); } else if (data.Phase == 0) { if (NetworkInfo.IsHost && RequestSenderMatches(sender, data.SourcePlayerId) && RememberEvent(data.SourcePlayerId, data.EventId)) { MarshalToMainThread(delegate { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) OnLimbSeverCallback?.Invoke(data.TargetPlayerId, data.BoneIndex, data.HitPoint, data.HitNormal, data.Damage); data.Phase = 1; MessageRelay.RelayModule(data, CommonMessageRoutes.ReliableToClients); }); } } else if (data.Phase == 1 && !NetworkInfo.IsHost && IsAuthoritativeSender(sender) && RememberEvent(data.SourcePlayerId, data.EventId)) { MarshalToMainThread(delegate { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) OnLimbSeverCallback?.Invoke(data.TargetPlayerId, data.BoneIndex, data.HitPoint, data.HitNormal, data.Damage); }); } } public void SendRespawn(byte playerId) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (!NetworkInfo.HasServer) { return; } byte localPlayerId = GetLocalPlayerId(); if (playerId != localPlayerId) { MelonLogger.Warning("[DeadPiece/Net] Refused a state-reset request for another player."); return; } RespawnData respawnData = new RespawnData { Phase = 0, PlayerId = playerId, RequesterId = localPlayerId, EventId = NextEventId() }; try { if (NetworkInfo.IsHost) { OnRespawnReceived(respawnData, localPlayerId); } else { MessageRelay.RelayModule(respawnData, CommonMessageRoutes.ReliableToServer); } } catch (Exception ex) { MelonLogger.Error("[DeadPiece/Net] SendRespawn failed: " + ex.Message); } } public void OnRespawnReceived(RespawnData data, byte? sender) { if (data == null || !IsKnownPlayer(data.PlayerId) || !IsKnownPlayer(data.RequesterId)) { return; } if (data.Phase == 0) { if (NetworkInfo.IsHost && data.PlayerId == data.RequesterId && RequestSenderMatches(sender, data.RequesterId) && RememberEvent(data.RequesterId, data.EventId)) { MarshalToMainThread(delegate { //IL_0042: Unknown result type (might be due to invalid IL or missing references) StoreAuthoritativeState(data.PlayerId, 0u, 0); OnRespawnCallback?.Invoke(data.PlayerId); data.Phase = 1; MessageRelay.RelayModule(data, CommonMessageRoutes.ReliableToClients); }); } } else if (data.Phase == 1 && !NetworkInfo.IsHost && IsAuthoritativeSender(sender) && RememberEvent(data.RequesterId, data.EventId)) { MarshalToMainThread(delegate { OnRespawnCallback?.Invoke(data.PlayerId); }); } } public void SendBloodColor(byte playerId, byte colorIndex) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (!NetworkInfo.HasServer || colorIndex > 9) { return; } byte localPlayerId = GetLocalPlayerId(); BloodColorData bloodColorData = new BloodColorData { Phase = (byte)(NetworkInfo.IsHost ? 1 : 0), PlayerId = playerId, ColorIndex = colorIndex, EventId = NextEventId() }; try { if (NetworkInfo.IsHost) { if (playerId == localPlayerId || IsKnownPlayer(playerId)) { RememberEvent(localPlayerId, bloodColorData.EventId); StoreAuthoritativeBloodColor(playerId, colorIndex); MessageRelay.RelayModule(bloodColorData, CommonMessageRoutes.ReliableToClients); } } else if (playerId == localPlayerId) { MessageRelay.RelayModule(bloodColorData, CommonMessageRoutes.ReliableToServer); } } catch (Exception ex) { MelonLogger.Error("[DeadPiece/Net] SendBloodColor failed: " + ex.Message); } } public void OnBloodColorReceived(BloodColorData data, byte? sender) { if (data == null || data.ColorIndex > 9 || !IsKnownPlayer(data.PlayerId)) { return; } if (data.Phase == 0) { if (NetworkInfo.IsHost && RequestSenderMatches(sender, data.PlayerId) && RememberEvent(data.PlayerId, data.EventId)) { MarshalToMainThread(delegate { //IL_0056: Unknown result type (might be due to invalid IL or missing references) StoreAuthoritativeBloodColor(data.PlayerId, data.ColorIndex); OnBloodColorCallback?.Invoke(data.PlayerId, data.ColorIndex); data.Phase = 1; MessageRelay.RelayModule(data, CommonMessageRoutes.ReliableToClients); }); } } else if (data.Phase == 1 && !NetworkInfo.IsHost && IsAuthoritativeSender(sender) && RememberEvent(data.PlayerId, data.EventId)) { MarshalToMainThread(delegate { OnBloodColorCallback?.Invoke(data.PlayerId, data.ColorIndex); }); } } public void SendFullState(byte playerId, uint goneBoneMask, byte bloodColorIndex, ushort ignoredClientSequence = 0) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (!NetworkInfo.HasServer || bloodColorIndex > 9) { return; } goneBoneMask &= 0x1FFFF; byte localPlayerId = GetLocalPlayerId(); FullStateData fullStateData = new FullStateData { Phase = (byte)(NetworkInfo.IsHost ? 1 : 0), PlayerId = playerId, GoneBoneMask = goneBoneMask, BloodColorIndex = bloodColorIndex, Sequence = 0 }; try { if (NetworkInfo.IsHost) { if (IsKnownPlayer(playerId)) { fullStateData.Sequence = NextAuthoritativeSequence(playerId); StoreAuthoritativeState(playerId, goneBoneMask, bloodColorIndex); MessageRelay.RelayModule(fullStateData, CommonMessageRoutes.ReliableToClients); } } else if (playerId == localPlayerId) { MessageRelay.RelayModule(fullStateData, CommonMessageRoutes.ReliableToServer); } } catch (Exception ex) { MelonLogger.Error("[DeadPiece/Net] SendFullState failed: " + ex.Message); } } public void OnFullStateReceived(FullStateData data, byte? sender) { if (data == null || data.BloodColorIndex > 9 || !IsKnownPlayer(data.PlayerId)) { return; } data.GoneBoneMask &= 131071u; if (data.Phase == 0) { if (NetworkInfo.IsHost && RequestSenderMatches(sender, data.PlayerId)) { MarshalToMainThread(delegate { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) uint authoritativeStateMask = GetAuthoritativeStateMask(data.PlayerId); data.GoneBoneMask = (data.GoneBoneMask | authoritativeStateMask) & 0x1FFFF; data.Sequence = NextAuthoritativeSequence(data.PlayerId); StoreAuthoritativeState(data.PlayerId, data.GoneBoneMask, data.BloodColorIndex); OnFullStateCallback?.Invoke(data.PlayerId, data.GoneBoneMask, data.BloodColorIndex, data.Sequence); data.Phase = 1; MessageRelay.RelayModule(data, CommonMessageRoutes.ReliableToClients); }); } } else if (data.Phase == 1 && !NetworkInfo.IsHost && IsAuthoritativeSender(sender)) { MarshalToMainThread(delegate { OnFullStateCallback?.Invoke(data.PlayerId, data.GoneBoneMask, data.BloodColorIndex, data.Sequence); }); } } } } namespace DeadPiece.Networking.Messages { public class BloodColorData : INetSerializable { public byte Phase; public byte PlayerId; public byte ColorIndex; public uint EventId; public int? GetSize() { return 7; } public void Serialize(INetSerializer serializer) { serializer.SerializeValue(ref Phase); serializer.SerializeValue(ref PlayerId); serializer.SerializeValue(ref ColorIndex); serializer.SerializeValue(ref EventId); } } public class BloodColorMessage : ModuleMessageHandler { protected override void OnHandleMessage(ReceivedMessage received) { BloodColorData bloodColorData = ((ReceivedMessage)(ref received)).ReadData(); if (bloodColorData != null) { FusionSyncManager.Instance?.OnBloodColorReceived(bloodColorData, ((ReceivedMessage)(ref received)).Sender); } } } public class FullStateData : INetSerializable { public byte Phase; public byte PlayerId; public uint GoneBoneMask; public byte BloodColorIndex; public ushort Sequence; public int? GetSize() { return 9; } public void Serialize(INetSerializer serializer) { serializer.SerializeValue(ref Phase); serializer.SerializeValue(ref PlayerId); serializer.SerializeValue(ref GoneBoneMask); serializer.SerializeValue(ref BloodColorIndex); serializer.SerializeValue(ref Sequence); } } public class FullStateMessage : ModuleMessageHandler { protected override void OnHandleMessage(ReceivedMessage received) { FullStateData fullStateData = ((ReceivedMessage)(ref received)).ReadData(); if (fullStateData != null) { FusionSyncManager.Instance?.OnFullStateReceived(fullStateData, ((ReceivedMessage)(ref received)).Sender); } } } public class LimbHitData : INetSerializable { public byte Phase; public byte SourcePlayerId; public byte TargetPlayerId; public byte BoneIndex; public float Damage; public Vector3 HitPoint; public uint EventId; public int? GetSize() { return 24; } public void Serialize(INetSerializer serializer) { serializer.SerializeValue(ref Phase); serializer.SerializeValue(ref SourcePlayerId); serializer.SerializeValue(ref TargetPlayerId); serializer.SerializeValue(ref BoneIndex); serializer.SerializeValue(ref Damage); NetSerializerUnityExtensions.SerializeValue(serializer, ref HitPoint); serializer.SerializeValue(ref EventId); } } [SkipHandleWhileLoading] public class LimbHitMessage : ModuleMessageHandler { protected override void OnHandleMessage(ReceivedMessage received) { LimbHitData limbHitData = ((ReceivedMessage)(ref received)).ReadData(); if (limbHitData != null) { FusionSyncManager.Instance?.OnLimbHitReceived(limbHitData, ((ReceivedMessage)(ref received)).Sender); } } } public class LimbSeverData : INetSerializable { public byte Phase; public byte SourcePlayerId; public byte TargetPlayerId; public byte BoneIndex; public Vector3 HitPoint; public Vector3 HitNormal; public float Damage; public uint EventId; public int? GetSize() { return 36; } public void Serialize(INetSerializer serializer) { serializer.SerializeValue(ref Phase); serializer.SerializeValue(ref SourcePlayerId); serializer.SerializeValue(ref TargetPlayerId); serializer.SerializeValue(ref BoneIndex); NetSerializerUnityExtensions.SerializeValue(serializer, ref HitPoint); NetSerializerUnityExtensions.SerializeValue(serializer, ref HitNormal); serializer.SerializeValue(ref Damage); serializer.SerializeValue(ref EventId); } } [SkipHandleWhileLoading] public class LimbSeverMessage : ModuleMessageHandler { protected override void OnHandleMessage(ReceivedMessage received) { LimbSeverData limbSeverData = ((ReceivedMessage)(ref received)).ReadData(); if (limbSeverData != null) { FusionSyncManager.Instance?.OnLimbSeverReceived(limbSeverData, ((ReceivedMessage)(ref received)).Sender); } } } public class RespawnData : INetSerializable { public byte Phase; public byte PlayerId; public byte RequesterId; public uint EventId; public int? GetSize() { return 7; } public void Serialize(INetSerializer serializer) { serializer.SerializeValue(ref Phase); serializer.SerializeValue(ref PlayerId); serializer.SerializeValue(ref RequesterId); serializer.SerializeValue(ref EventId); } } [SkipHandleWhileLoading] public class RespawnMessage : ModuleMessageHandler { protected override void OnHandleMessage(ReceivedMessage received) { RespawnData respawnData = ((ReceivedMessage)(ref received)).ReadData(); if (respawnData != null) { FusionSyncManager.Instance?.OnRespawnReceived(respawnData, ((ReceivedMessage)(ref received)).Sender); } } } } namespace DeadPiece.Unity { public class BloodEffect : MonoBehaviour { public int particleCount = 30; public float particleLifetime = 3f; public float particleSpeed = 5f; public float particleGravity = 9.8f; public Color bloodColor = new Color(0.5f, 0f, 0f); public int decalCount = 5; public float decalLifetime = 10f; public float decalSize = 0.1f; public void Initialize(float damage) { Object.Destroy((Object)(object)((Component)this).gameObject, Mathf.Max(particleLifetime, decalLifetime) + 1f); } } }