Decompiled source of HomigradLight v5.0.0
HomigradLight.dll
Decompiled 10 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using Homigrad; using LabFusion.Marrow; using LabFusion.Network; using LabFusion.Player; using LabFusion.SDK.Gamemodes; using LabFusion.Senders; using LabFusion.Utilities; using MelonLoader; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(HomigradLightMod), "Homigrad Light", "5.0.0", "Homigrad", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("HomigradLight")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("HomigradLight")] [assembly: AssemblyTitle("HomigradLight")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 Homigrad { internal static class DeadPieceBridge { private static readonly string[] LimbBones = new string[14] { "LeftShoulder", "RightShoulder", "LeftUpperArm", "RightUpperArm", "LeftLowerArm", "RightLowerArm", "LeftHand", "RightHand", "LeftUpperLeg", "RightUpperLeg", "LeftLowerLeg", "RightLowerLeg", "LeftFoot", "RightFoot" }; private static bool _resolved; private static bool _loggedMissing; private static bool _loggedOk; private static object? _mod; private static MethodInfo? _onBoneHit; private static Type? _humanBodyBones; private static Type? _vector3Type; private static MethodInfo? _opEquality; private static bool _tearLimbs = true; private static float _tearSpeed = 12f; private static float _limbDamage = 9999f; public static bool TearLimbsOnFall { get { return _tearLimbs; } set { _tearLimbs = value; } } public static bool TearLegsOnFall { get { return _tearLimbs; } set { _tearLimbs = value; } } public static float TearSpeed { get { return _tearSpeed; } set { _tearSpeed = Math.Clamp(value, 5f, 40f); } } public static bool IsDeadPieceLoaded() { Ensure(); if (_mod != null) { return _onBoneHit != null; } return false; } public static void TryTearLegsFromFall(float fallVelocityY, object? physicsRig, object? rigManager) { TryTearLimbsFromFall(fallVelocityY, physicsRig, rigManager); } public static void TryTearLimbsFromFall(float fallVelocityY, object? physicsRig, object? rigManager) { if (!_tearLimbs || fallVelocityY > 0f - _tearSpeed) { return; } Ensure(); if (_mod == null || _onBoneHit == null || rigManager == null || IsUnityNull(rigManager)) { if (!_loggedMissing) { _loggedMissing = true; MelonLogger.Warning("[Homigrad] DeadPiece.dll not found — fall won't tear limbs. Install Deadpiece.dll in Mods."); } return; } try { object bodyHitPoint = GetBodyHitPoint(physicsRig); string[] limbBones = LimbBones; foreach (string boneName in limbBones) { HitBone(rigManager, boneName, bodyHitPoint); } if (!_loggedOk) { _loggedOk = true; MelonLogger.Msg("[Homigrad] DeadPiece 0.7.7+: hard falls tear all limbs."); } } catch (Exception ex) { MelonLogger.Warning("[Homigrad] DeadPiece limb tear failed: " + ex.Message); } } private static void HitBone(object rigManager, string boneName, object hitPoint) { if (_humanBodyBones == null || _onBoneHit == null) { return; } try { if (Enum.IsDefined(_humanBodyBones, boneName)) { object obj = Enum.Parse(_humanBodyBones, boneName); _onBoneHit.Invoke(_mod, new object[4] { rigManager, obj, _limbDamage, hitPoint }); } } catch { } } private static object GetBodyHitPoint(object? physicsRig) { try { if (physicsRig != null) { string[] array = new string[5] { "m_chest", "chest", "m_pelvis", "pelvis", "feet" }; foreach (string name in array) { object obj = physicsRig.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(physicsRig) ?? physicsRig.GetType().GetProperty(name)?.GetValue(physicsRig); object obj2 = obj?.GetType().GetProperty("transform")?.GetValue(obj); object obj3 = obj2?.GetType().GetProperty("position")?.GetValue(obj2); if (obj3 != null) { return obj3; } } } } catch { } return Activator.CreateInstance(_vector3Type, 0f, 0f, 0f); } private static void Ensure() { if (_resolved) { return; } _resolved = true; try { _vector3Type = Type.GetType("UnityEngine.Vector3, UnityEngine.CoreModule") ?? FindType("UnityEngine.Vector3"); _humanBodyBones = FindType("UnityEngine.HumanBodyBones") ?? Type.GetType("UnityEngine.HumanBodyBones, UnityEngine.AnimationModule") ?? Type.GetType("UnityEngine.HumanBodyBones, UnityEngine.CoreModule"); _opEquality = (Type.GetType("UnityEngine.Object, UnityEngine.CoreModule") ?? FindType("UnityEngine.Object"))?.GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public); Type type = FindType("MelonLoader.MelonBase") ?? FindType("MelonLoader.MelonMod"); Type type2 = FindType("DeadPiece.DeadPieceMod"); if (type2 == null) { return; } object obj = (type?.GetProperty("RegisteredMelons", BindingFlags.Static | BindingFlags.Public))?.GetValue(null); if (obj != null) { foreach (object item in (IEnumerable)obj) { if (item != null && type2.IsInstanceOfType(item)) { _mod = item; break; } } } if (_mod == null) { _mod = (type2.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public) ?? type2.BaseType?.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy))?.GetValue(null); } if (_mod == null) { return; } MethodInfo[] methods = type2.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "OnBoneHit" && methodInfo.GetParameters().Length == 4) { _onBoneHit = methodInfo; break; } } if (!(_onBoneHit == null)) { return; } methods = type2.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo2 in methods) { if (methodInfo2.Name == "ApplyBoneHit" && methodInfo2.GetParameters().Length >= 4) { _onBoneHit = methodInfo2; break; } } } catch (Exception ex) { MelonLogger.Warning("[Homigrad] DeadPiece bridge init: " + ex.Message); } } private static bool IsUnityNull(object? obj) { if (obj == null) { return true; } try { if (_opEquality != null) { return (bool)_opEquality.Invoke(null, new object[2] { obj, null }); } } catch { } return false; } private static Type? FindType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(fullName); if (type != null) { return type; } } catch { } } return null; } } internal static class FallDamage { private static bool _enabled = true; private static float _threshold = 7f; private static float _multiplier = 1.5f; private static float _ragdollHealthPercentage = 25f; private static bool _ragdollFromFallDamage = true; private static bool _ragdollFlingingFix = true; private static bool _sceneReady; private static bool _previousGrounded; private static bool _hasRagdolledFromCrumble; private static bool _previousLegsKinematic; private static bool _loggedReady; private static bool _loggedFail; private static Type? _playerType; private static Type? _vector3Type; private static MethodInfo? _opEquality; private static bool _typesResolved; public static bool Enabled { get { return _enabled; } set { _enabled = value; } } public static float MinSpeed { get { return _threshold; } set { _threshold = Math.Clamp(value, 0f, 100f); } } public static float Threshold { get { return _threshold; } set { _threshold = Math.Clamp(value, 0f, 100f); } } public static float Multiplier { get { return _multiplier; } set { _multiplier = Math.Clamp(value, 0f, 100f); } } public static float DamagePerMs { get { return _multiplier; } set { _multiplier = Math.Clamp(value, 0f, 100f); } } public static float RagdollHealthPercentage { get { return _ragdollHealthPercentage; } set { _ragdollHealthPercentage = Math.Clamp(value, 0f, 100f); } } public static bool RagdollFromFallDamage { get { return _ragdollFromFallDamage; } set { _ragdollFromFallDamage = value; } } public static bool RagdollFlingingFix { get { return _ragdollFlingingFix; } set { _ragdollFlingingFix = value; } } public static void Reset() { _sceneReady = false; _previousGrounded = false; _hasRagdolledFromCrumble = false; _previousLegsKinematic = true; } public static void Tick(bool active) { if (!_enabled || !active) { return; } EnsureTypes(); if (_playerType == null) { return; } try { if (!TryGetPhysicsRig(out object physicsRig) || !TryGetRigManager(out object rigManager)) { return; } if (!_sceneReady) { if (TryGetGrounded(physicsRig, out var grounded)) { _previousGrounded = grounded; _previousLegsKinematic = GetLegsKinematic(physicsRig); _sceneReady = true; if (!_loggedReady) { _loggedReady = true; MelonLogger.Msg("[Homigrad] Crumble-style fall damage ready."); } } return; } object health = GetHealth(rigManager); if (health == null) { return; } float floatProp = GetFloatProp(health, "curr_Health"); float num = GetFloatProp(health, "max_Health"); if (num <= 0.01f) { num = 1f; } float num2 = floatProp / num * 100f; bool legsKinematic = GetLegsKinematic(physicsRig); if (num2 >= _ragdollHealthPercentage && !legsKinematic && floatProp > 0f && _hasRagdolledFromCrumble) { Invoke(physicsRig, "UnRagdollRig"); legsKinematic = GetLegsKinematic(physicsRig); } if (_hasRagdolledFromCrumble && legsKinematic) { _hasRagdolledFromCrumble = false; } if (!_previousLegsKinematic && legsKinematic && _ragdollFlingingFix) { TryTeleportAboveFeet(physicsRig, rigManager); } _previousLegsKinematic = legsKinematic; if (!TryGetGrounded(physicsRig, out var grounded2)) { return; } if (grounded2 && !_previousGrounded) { float wholeBodyVelocityY = GetWholeBodyVelocityY(physicsRig); if (wholeBodyVelocityY < 0f - _threshold) { float num3 = Math.Abs(wholeBodyVelocityY + _threshold) * _multiplier; TakeDamage(health, num3); DeadPieceBridge.TryTearLimbsFromFall(wholeBodyVelocityY, physicsRig, GetRigManager()); if (GetFloatProp(health, "curr_Health") / Math.Max(0.01f, GetFloatProp(health, "max_Health")) * 100f <= _ragdollHealthPercentage && _ragdollFromFallDamage) { RagdollUtil.SafeRagdoll(physicsRig); _hasRagdolledFromCrumble = true; try { HomigradSounds.OnFallImpact(num3, Math.Abs(wholeBodyVelocityY), fractured: true); PainOverlay.NotifyDamage(num3, fractured: true); } catch { } } else { try { HomigradSounds.OnFallImpact(num3, Math.Abs(wholeBodyVelocityY), fractured: false); PainOverlay.NotifyDamage(num3); } catch { } } } } _previousGrounded = grounded2; } catch (Exception ex) { if (!_loggedFail) { _loggedFail = true; MelonLogger.Warning("[Homigrad] Crumble fall damage error: " + ex.Message); } } } private static void EnsureTypes() { if (!_typesResolved) { _typesResolved = true; _playerType = FindType("BoneLib.Player"); _vector3Type = Type.GetType("UnityEngine.Vector3, UnityEngine.CoreModule") ?? FindType("UnityEngine.Vector3"); _opEquality = (Type.GetType("UnityEngine.Object, UnityEngine.CoreModule") ?? FindType("UnityEngine.Object"))?.GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public); } } private static bool TryGetPhysicsRig(out object physicsRig) { physicsRig = null; try { object obj = _playerType.GetField("physicsRig", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) ?? _playerType.GetProperty("physicsRig", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) ?? _playerType.GetProperty("PhysicsRig", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null || IsUnityNull(obj)) { return false; } physicsRig = obj; return true; } catch { return false; } } private static object? GetRigManager() { if (!TryGetRigManager(out object rigManager)) { return null; } return rigManager; } private static bool TryGetRigManager(out object rigManager) { rigManager = null; try { object obj = _playerType.GetField("rigManager", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) ?? _playerType.GetProperty("rigManager", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) ?? _playerType.GetProperty("RigManager", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null || IsUnityNull(obj)) { return false; } rigManager = obj; return true; } catch { return false; } } private static object? GetHealth(object rigManager) { object obj = rigManager.GetType().GetField("health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(rigManager); if (obj == null) { PropertyInfo? property = rigManager.GetType().GetProperty("health"); if ((object)property == null) { return null; } obj = property.GetValue(rigManager); } return obj; } private static bool TryGetGrounded(object physicsRig, out bool grounded) { grounded = false; try { object obj = physicsRig.GetType().GetField("feet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(physicsRig) ?? physicsRig.GetType().GetProperty("feet")?.GetValue(physicsRig); if (obj == null) { return false; } object componentByName = GetComponentByName(obj, "PhysGrounder"); if (componentByName == null) { return false; } if ((componentByName.GetType().GetField("isGrounded", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(componentByName) ?? componentByName.GetType().GetProperty("isGrounded")?.GetValue(componentByName)) is bool flag) { grounded = flag; return true; } } catch { } return false; } private static float GetWholeBodyVelocityY(object physicsRig) { try { object obj = physicsRig.GetType().GetProperty("wholeBodyVelocity")?.GetValue(physicsRig) ?? physicsRig.GetType().GetField("wholeBodyVelocity", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(physicsRig); if (obj == null) { return 0f; } return Convert.ToSingle(obj.GetType().GetField("y")?.GetValue(obj) ?? obj.GetType().GetProperty("y")?.GetValue(obj)); } catch { return 0f; } } private static bool GetLegsKinematic(object physicsRig) { try { object obj = physicsRig.GetType().GetField("_legsKinematic", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(physicsRig) ?? physicsRig.GetType().GetProperty("_legsKinematic")?.GetValue(physicsRig) ?? physicsRig.GetType().GetProperty("legsKinematic")?.GetValue(physicsRig); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return true; } } private static void TakeDamage(object health, float damage) { MethodInfo[] methods = health.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (!string.Equals(methodInfo.Name, "TAKEDAMAGE", StringComparison.OrdinalIgnoreCase) && !string.Equals(methodInfo.Name, "TakeDamage", StringComparison.OrdinalIgnoreCase)) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 0 || parameters[0].ParameterType != typeof(float)) { continue; } object[] array = new object[parameters.Length]; array[0] = damage; for (int j = 1; j < parameters.Length; j++) { Type parameterType = parameters[j].ParameterType; if (parameterType == typeof(bool)) { array[j] = false; } else if (parameterType.IsValueType) { array[j] = Activator.CreateInstance(parameterType); } else { array[j] = null; } } methodInfo.Invoke(health, array); break; } } private static void TryTeleportAboveFeet(object physicsRig, object rigManager) { try { object obj = physicsRig.GetType().GetField("feet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(physicsRig) ?? physicsRig.GetType().GetProperty("feet")?.GetValue(physicsRig); object obj2 = obj?.GetType().GetProperty("transform")?.GetValue(obj); object obj3 = obj2?.GetType().GetProperty("position")?.GetValue(obj2); if (obj3 == null || _vector3Type == null) { return; } float num = GetFloat(obj3, "x"); float num2 = GetFloat(obj3, "y") + 0.5f; float num3 = GetFloat(obj3, "z"); object obj4 = Activator.CreateInstance(_vector3Type, num, num2, num3); MethodInfo method = rigManager.GetType().GetMethod("Teleport", new Type[1] { _vector3Type }); if (method != null) { method.Invoke(rigManager, new object[1] { obj4 }); return; } MethodInfo[] methods = rigManager.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "Teleport") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length < 1 || !(parameters[0].ParameterType == _vector3Type)) { continue; } object[] array = new object[parameters.Length]; array[0] = obj4; for (int j = 1; j < parameters.Length; j++) { if (parameters[j].ParameterType == typeof(bool)) { array[j] = false; } else if (parameters[j].ParameterType.IsValueType) { array[j] = Activator.CreateInstance(parameters[j].ParameterType); } else { array[j] = null; } } methodInfo.Invoke(rigManager, array); break; } } catch { } } private static object? GetComponentByName(object host, string typeName) { try { object obj = host.GetType().GetProperty("gameObject")?.GetValue(host) ?? host; MethodInfo method = obj.GetType().GetMethod("GetComponents", new Type[1] { typeof(Type) }); MethodInfo[] methods = obj.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "GetComponent") && methodInfo.GetParameters().Length == 1 && !(methodInfo.GetParameters()[0].ParameterType != typeof(string))) { object obj2 = methodInfo.Invoke(obj, new object[1] { typeName }); if (obj2 != null && !IsUnityNull(obj2)) { return obj2; } } } Type type = FindType("UnityEngine.Component") ?? Type.GetType("UnityEngine.Component, UnityEngine.CoreModule"); if (type != null && method != null && method.Invoke(obj, new object[1] { type }) is Array array) { foreach (object item in array) { if (item != null && item.GetType().Name.IndexOf(typeName, StringComparison.OrdinalIgnoreCase) >= 0) { return item; } } } } catch { } return null; } private static void Invoke(object target, string method) { try { target.GetType().GetMethod(method, Type.EmptyTypes)?.Invoke(target, null); } catch { } } private static float GetFloatProp(object target, string name) { try { object obj = target.GetType().GetProperty(name)?.GetValue(target) ?? target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(target); return (obj == null) ? 0f : Convert.ToSingle(obj); } catch { return 0f; } } private static float GetFloat(object v, string name) { return Convert.ToSingle(v.GetType().GetField(name)?.GetValue(v) ?? v.GetType().GetProperty(name).GetValue(v)); } private static bool IsUnityNull(object? obj) { if (obj == null) { return true; } try { if (_opEquality != null) { return (bool)_opEquality.Invoke(null, new object[2] { obj, null }); } } catch { } return false; } private static Type? FindType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(fullName); if (type != null) { return type; } } catch { } } return null; } } internal static class HolsterHiderBridge { private static bool _applied; private static object?[]? _savedVisibilities; private static bool _loggedMissing; public static bool IsHolsterHiderLoaded() { return FindType("HolsterHider.HolsterHiderMod") != null; } public static bool IsSyncLoaded() { if (!(FindType("HolsterHiderSync.HolsterHiderSync") != null)) { return FindType("HolsterHiderModule.HolsterHiderModule") != null; } return true; } public static void ApplyInvisibleForHomigrad() { try { Type type = FindType("HolsterHider.HolsterHiderMod"); Type type2 = FindType("HolsterHider.HolsterVisibility"); if (type == null || type2 == null) { if (!_loggedMissing) { _loggedMissing = true; MelonLogger.Warning("[Homigrad] Holster Hider not loaded — install HolsterHider.dll (and HolsterHiderSync.dll) into Mods."); } return; } object obj = type.GetField("LocalBodyConfig", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null || !(obj.GetType().GetProperty("HolsterConfigs")?.GetValue(obj) is Array { Length: not 0 } array)) { return; } object value = Enum.Parse(type2, "INVISIBLE"); _savedVisibilities = new object[array.Length]; for (int i = 0; i < array.Length; i++) { object value2 = array.GetValue(i); if (value2 != null) { FieldInfo field = value2.GetType().GetField("Visibility"); if (!(field == null)) { _savedVisibilities[i] = field.GetValue(value2); field.SetValue(value2, value); } } } type.GetMethod("UpdateHolsters", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null); _applied = true; MelonLogger.Msg("[Homigrad] Holster Hider → all slots INVISIBLE for this round."); } catch (Exception ex) { MelonLogger.Warning("[Homigrad] HolsterHiderBridge apply failed: " + ex.Message); } } public static void Restore() { if (!_applied) { return; } try { Type type = FindType("HolsterHider.HolsterHiderMod"); if (type == null || _savedVisibilities == null) { _applied = false; return; } object obj = type.GetField("LocalBodyConfig", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if ((obj?.GetType().GetProperty("HolsterConfigs"))?.GetValue(obj) is Array array) { for (int i = 0; i < array.Length && i < _savedVisibilities.Length; i++) { object value = array.GetValue(i); object obj2 = _savedVisibilities[i]; if (value != null && obj2 != null) { value.GetType().GetField("Visibility")?.SetValue(value, obj2); } } } type.GetMethod("UpdateHolsters", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, null); MelonLogger.Msg("[Homigrad] Holster Hider settings restored."); } catch (Exception ex) { MelonLogger.Warning("[Homigrad] HolsterHiderBridge restore failed: " + ex.Message); } finally { _applied = false; _savedVisibilities = null; } } private static Type? FindType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(fullName); if (type != null) { return type; } } catch { } } return null; } } public sealed class HomigradLightMod : MelonMod { private Harmony? _harmony; public override void OnInitializeMelon() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown try { HomigradServerGate.Init(); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Warning("Server gate init: " + ex.Message); } try { _harmony = new Harmony("HomigradLight.Features"); SelfHarmFeature.InitHarmony(_harmony); } catch (Exception ex2) { ((MelonBase)this).LoggerInstance.Warning("Harmony features: " + ex2.Message); } try { HomigradSounds.Init(); } catch (Exception ex3) { ((MelonBase)this).LoggerInstance.Warning("Sounds init: " + ex3.Message); } try { PainOverlay.Init(); } catch (Exception ex4) { ((MelonBase)this).LoggerInstance.Warning("Pain overlay init: " + ex4.Message); } ((MelonBase)this).LoggerInstance.Msg("Homigrad Light 5.0.0 — client build, official server only."); } public override void OnLateInitializeMelon() { if (!HomigradServerGate.IsActive) { ((MelonBase)this).LoggerInstance.Msg("Homigrad Light idle: " + HomigradServerGate.BlockReason); return; } if (DeadPieceBridge.IsDeadPieceLoaded()) { ((MelonBase)this).LoggerInstance.Msg("DeadPiece detected (0.7.7+) - hard falls tear all limbs."); } if (SelfHarmFeature.Enabled) { try { SelfHarmFeature.Apply(); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Warning("SelfHarm apply: " + ex.Message); } } if (WallClimbFeature.Enabled) { ((MelonBase)this).LoggerInstance.Msg("Wall climb enabled — squeeze grip near walls to climb."); } } public override void OnUpdate() { try { HomigradServerGate.Tick(); } catch { } if (!HomigradServerGate.IsActive) { return; } try { FallDamage.Tick(active: true); } catch { } try { HomigradSounds.Tick(); } catch { } try { PainOverlay.Tick(); } catch { } try { SelfHarmFeature.Tick(active: true); } catch { } try { WallClimbFeature.Tick(active: true); } catch { } } } internal static class HomigradOfficial { public const string MetaKey = "hg_official"; public const string MetaToken = "HG2026"; } internal static class HomigradServerGate { [CompilerGenerated] private static class <>O { public static ServerEvent <0>__OnSessionChanged; public static ServerEvent <1>__OnDisconnected; public static UpdateEvent <2>__Refresh; public static Action <3>__Refresh; } public const string OfficialMetaKey = "hg_official"; public const string DefaultMetaToken = "HG2026"; private static readonly HashSet<ulong> HostIds = new HashSet<ulong>(); private static string _metaToken = "HG2026"; private static bool _hooks; private static bool _loggedState; private static float _nextRefresh; public static bool IsActive { get; private set; } public static string BlockReason { get; private set; } = "Not on official Homigrad server."; public static void Init() { //IL_0023: 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_002e: Expected O, but got Unknown //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_004e: Expected O, but got Unknown //IL_0063: 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_006e: Expected O, but got Unknown //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_008e: Expected O, but got Unknown LoadConfig(); if (_hooks) { return; } _hooks = true; try { object obj = <>O.<0>__OnSessionChanged; if (obj == null) { ServerEvent val = OnSessionChanged; <>O.<0>__OnSessionChanged = val; obj = (object)val; } MultiplayerHooking.OnJoinedServer += (ServerEvent)obj; object obj2 = <>O.<0>__OnSessionChanged; if (obj2 == null) { ServerEvent val2 = OnSessionChanged; <>O.<0>__OnSessionChanged = val2; obj2 = (object)val2; } MultiplayerHooking.OnStartedServer += (ServerEvent)obj2; object obj3 = <>O.<1>__OnDisconnected; if (obj3 == null) { ServerEvent val3 = OnDisconnected; <>O.<1>__OnDisconnected = val3; obj3 = (object)val3; } MultiplayerHooking.OnDisconnected += (ServerEvent)obj3; object obj4 = <>O.<2>__Refresh; if (obj4 == null) { UpdateEvent val4 = Refresh; <>O.<2>__Refresh = val4; obj4 = (object)val4; } MultiplayerHooking.OnMainSceneInitialized += (UpdateEvent)obj4; LobbyInfoManager.OnLobbyInfoChanged += Refresh; GamemodeManager.OnGamemodeStarted += Refresh; GamemodeManager.OnGamemodeStopped += Refresh; } catch (Exception ex) { MelonLogger.Warning("[Homigrad Light] Gate hooks: " + ex.Message); } Refresh(); MelonLogger.Msg("[Homigrad Light] Official-host config: " + ConfigPath()); } public static void Tick() { if (Time.realtimeSinceStartup >= _nextRefresh) { _nextRefresh = Time.realtimeSinceStartup + 1f; Refresh(); } } public static bool CanHostOfficial() { if (!NetworkInfo.HasServer) { return false; } return HostIds.Contains(GetSessionHostId()); } public static void StampOfficialGamemode(Gamemode? gm) { if (((gm != null) ? gm.Metadata : null) == null || !NetworkInfo.IsHost || !CanHostOfficial()) { return; } try { gm.Metadata.TrySetMetadata("hg_official", _metaToken); } catch (Exception ex) { MelonLogger.Warning("[Homigrad Light] Stamp metadata: " + ex.Message); } } public static bool RequireActive(string feature) { if (IsActive) { return true; } MelonLogger.Msg("[Homigrad Light] Blocked (" + feature + "): " + BlockReason); return false; } private static void OnSessionChanged() { _loggedState = false; Refresh(); } private static void OnDisconnected() { _loggedState = false; IsActive = false; BlockReason = "Not connected to a server."; } private static void Refresh() { bool isActive = IsActive; if (!NetworkInfo.HasServer) { IsActive = false; BlockReason = "Homigrad Light works only on the official Homigrad server."; LogStateIfChanged(isActive); return; } ulong sessionHostId = GetSessionHostId(); if (sessionHostId == 0L) { IsActive = false; BlockReason = "Waiting for lobby info..."; LogStateIfChanged(isActive); return; } if (HostIds.Contains(sessionHostId)) { IsActive = true; BlockReason = string.Empty; LogStateIfChanged(isActive); return; } if (TryReadOfficialMetadata(out string _)) { IsActive = true; BlockReason = string.Empty; LogStateIfChanged(isActive); return; } IsActive = false; if (NetworkInfo.IsHost) { BlockReason = "Own server is not official. Join the Homigrad server instead."; } else { BlockReason = "This server is not the official Homigrad server."; } if (!_loggedState) { MelonLogger.Msg($"[Homigrad Light] Inactive — host Steam ID {sessionHostId}. Official hosts file: {ConfigPath()}"); } LogStateIfChanged(isActive); } private static void LogStateIfChanged(bool wasActive) { if (wasActive != IsActive || !_loggedState) { _loggedState = true; if (IsActive) { MelonLogger.Msg("[Homigrad Light] Active — official Homigrad server."); } else { MelonLogger.Msg("[Homigrad Light] Inactive — " + BlockReason); } } } private static bool TryReadOfficialMetadata(out string value) { value = string.Empty; try { Gamemode val = default(Gamemode); string text = default(string); if (GamemodeManager.TryGetGamemode<Gamemode>(ref val) && ((val != null) ? val.Metadata : null) != null && val.Metadata.TryGetMetadata("hg_official", ref text) && text == _metaToken) { value = text; return true; } Gamemode activeGamemode = GamemodeManager.ActiveGamemode; string text2 = default(string); if (((activeGamemode != null) ? activeGamemode.Metadata : null) != null && GamemodeManager.ActiveGamemode.Metadata.TryGetMetadata("hg_official", ref text2) && text2 == _metaToken) { value = text2; return true; } } catch { } return false; } private static ulong GetSessionHostId() { try { ulong lobbyID = LobbyInfoManager.LobbyInfo.LobbyID; if (lobbyID != 0L) { return lobbyID; } } catch { } try { PlayerID hostID = PlayerIDManager.GetHostID(); if (hostID != null && hostID.PlatformID != 0L) { return hostID.PlatformID; } } catch { } return 0uL; } private static string ConfigPath() { return Path.Combine(MelonEnvironment.UserDataDirectory, "Homigrad", "official_hosts.json"); } private static void LoadConfig() { HostIds.Clear(); _metaToken = "HG2026"; string path = ConfigPath(); try { Directory.CreateDirectory(Path.GetDirectoryName(path)); if (!File.Exists(path)) { File.WriteAllText(path, "{\n \"officialHostIds\": [],\n \"metadataToken\": \"HG2026\"\n}\n"); return; } string json = File.ReadAllText(path); foreach (ulong item in ParseIds(json, "officialHostIds")) { HostIds.Add(item); } string text = ParseString(json, "metadataToken"); if (!string.IsNullOrWhiteSpace(text)) { _metaToken = text.Trim(); } } catch (Exception ex) { MelonLogger.Warning("[Homigrad Light] Config load: " + ex.Message); } } private static IEnumerable<ulong> ParseIds(string json, string key) { int num = json.IndexOf(key, StringComparison.OrdinalIgnoreCase); if (num < 0) { yield break; } int num2 = json.IndexOf('[', num); int num3 = json.IndexOf(']', num2 + 1); if (num2 < 0 || num3 <= num2) { yield break; } string text = json.Substring(num2 + 1, num3 - num2 - 1); string[] array = text.Split(',', StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (ulong.TryParse(array[i].Trim().Trim('"'), out var result) && result != 0L) { yield return result; } } } private static string? ParseString(string json, string key) { int num = json.IndexOf(key, StringComparison.OrdinalIgnoreCase); if (num < 0) { return null; } int num2 = json.IndexOf(':', num); if (num2 < 0) { return null; } int num3 = json.IndexOf('"', num2 + 1); if (num3 < 0) { return null; } int num4 = json.IndexOf('"', num3 + 1); if (num4 <= num3) { return null; } return json.Substring(num3 + 1, num4 - num3 - 1); } } internal static class HomigradSounds { [CompilerGenerated] private static class <>O { public static PlayerAction <0>__OnPlayerAction; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UpdateEvent <>9__49_0; internal void <Init>b__49_0() { ResetScene(); } } private static bool _ready; private static bool _hooks; private static float _nextFoot; private static float _nextBreathPulse; private static float _lastHealth = -1f; private static float _lastMaxHealth = 100f; private static Vector3 _lastPos; private static bool _hasLastPos; private static float _painCooldown; private static object? _clipBreath; private static object? _clipPain; private static object? _clipDeath; private static object? _clipFracture; private static object? _clipFoot; private static object? _clipHit; private static object? _breathSource; private static object? _breathGo; public static bool Enabled { get; set; } = true; public static bool BreathEnabled { get; set; } = true; public static bool PainEnabled { get; set; } = true; public static bool DeathEnabled { get; set; } = true; public static bool FractureEnabled { get; set; } = true; public static bool FootstepEnabled { get; set; } = true; public static bool HitEnabled { get; set; } = true; public static float Volume { get; set; } = 0.85f; public static void Init() { //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_0029: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if (_hooks) { return; } _hooks = true; try { object obj = <>O.<0>__OnPlayerAction; if (obj == null) { PlayerAction val = OnPlayerAction; <>O.<0>__OnPlayerAction = val; obj = (object)val; } MultiplayerHooking.OnPlayerAction += (PlayerAction)obj; object obj2 = <>c.<>9__49_0; if (obj2 == null) { UpdateEvent val2 = delegate { ResetScene(); }; <>c.<>9__49_0 = val2; obj2 = (object)val2; } MultiplayerHooking.OnMainSceneInitialized += (UpdateEvent)obj2; } catch (Exception ex) { MelonLogger.Warning("[HomigradSounds] Hook: " + ex.Message); } EnsureClips(); } public static void Tick() { if (!Enabled) { return; } EnsureClips(); if (!_ready) { return; } if (!TryGetHealth(out var hp, out var maxHp)) { StopBreathLoop(); return; } if (_lastHealth >= 0f && hp < _lastHealth - 0.5f && PainEnabled) { float num = _lastHealth - hp; if ((float)Environment.TickCount / 1000f >= _painCooldown) { _painCooldown = (float)Environment.TickCount / 1000f + 0.35f; PlayPain(Mathf.Clamp(num / 8f, 0.35f, 1f)); try { PainOverlay.NotifyDamage(num); } catch { } } } _lastHealth = hp; _lastMaxHealth = maxHp; UpdateBreath(hp, maxHp); UpdateFootsteps(); } public static void OnFallImpact(float damage, float impactSpeed, bool fractured) { if (Enabled) { if (PainEnabled && damage > 0.5f) { PlayPain(Mathf.Clamp(damage / 12f, 0.4f, 1f)); } if (fractured && FractureEnabled) { PlayFracture(); } else if (HitEnabled && impactSpeed > 4f) { PlayHit(Mathf.Clamp(impactSpeed / 14f, 0.3f, 1f)); } } } private static void OnPlayerAction(PlayerID id, PlayerActionType type, PlayerID? other = null) { //IL_0013: 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_0033: Expected I4, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || id == null || !id.IsMe) { return; } switch (type - 2) { case 0: case 5: if (DeathEnabled) { PlayDeath(); } StopBreathLoop(); break; case 1: case 3: if (PainEnabled) { PlayPain(0.75f); } break; case 2: if (HitEnabled) { PlayHit(0.55f, GetPlayerHead(other)); } break; case 4: break; } } private static void ResetScene() { _hasLastPos = false; _lastHealth = -1f; StopBreathLoop(); } private static void EnsureClips() { if (_ready) { return; } try { _clipBreath = MakeNoiseLoop("HG_Breath", 1.2f, 0.08f, 90f, 0.35f); _clipPain = MakeToneBurst("HG_Pain", 0.35f, 420f, 880f, 0.55f); _clipDeath = MakeToneBurst("HG_Death", 0.9f, 320f, 80f, 0.7f); _clipFracture = MakeCrack("HG_Fracture", 0.18f); _clipFoot = MakeNoiseBurst("HG_Foot", 0.12f, 0.25f, 180f); _clipHit = MakeToneBurst("HG_Hit", 0.14f, 160f, 60f, 0.65f); _ready = _clipBreath != null && _clipPain != null; if (_ready) { MelonLogger.Msg("[Homigrad] Immersive sounds ready (breath/pain/death/fracture/foot/hit)."); } } catch (Exception ex) { MelonLogger.Warning("[HomigradSounds] Clip init: " + ex.Message); } } private static void UpdateBreath(float hp, float maxHp) { if (!BreathEnabled) { StopBreathLoop(); return; } float num = ((maxHp > 0.01f) ? (hp / maxHp) : 1f); if (!(num < 0.72f) || !(hp > 0.01f)) { StopBreathLoop(); return; } float num2 = Mathf.Clamp01((0.72f - num) / 0.55f); EnsureBreathSource(); if (_breathSource == null) { return; } try { Type type = _breathSource.GetType(); object obj = type.GetProperty("isPlaying")?.GetValue(_breathSource); if (!(obj is bool) || !(bool)obj) { type.GetProperty("loop")?.SetValue(_breathSource, true); type.GetProperty("clip")?.SetValue(_breathSource, _clipBreath); type.GetMethod("Play")?.Invoke(_breathSource, null); } float num3 = Volume * (0.15f + num2 * 0.55f); type.GetProperty("volume")?.SetValue(_breathSource, num3); type.GetProperty("pitch")?.SetValue(_breathSource, 0.85f + num2 * 0.35f); TrySetMixerReflect(_breathSource, "InHead"); } catch { } } private static void UpdateFootsteps() { //IL_0033: 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_0044: 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_006d: 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_0026: 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_00c8: Unknown result type (might be due to invalid IL or missing references) if (!FootstepEnabled || !TryGetFeetPos(out var pos)) { return; } float num = (float)Environment.TickCount / 1000f; if (!_hasLastPos) { _lastPos = pos; _hasLastPos = true; return; } float num2 = Vector3.Distance(new Vector3(pos.x, 0f, pos.z), new Vector3(_lastPos.x, 0f, _lastPos.z)); _lastPos = pos; if (!(num < _nextFoot) && !(num2 < 0.35f) && TryGetGrounded(out var grounded) && grounded && TryGetSpeed(out var speed) && !(speed < 1.1f)) { _nextFoot = num + Mathf.Clamp(0.55f - speed * 0.04f, 0.28f, 0.55f); PlayFoot(pos); } } public static void PlayPain(float intensity) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) PlayOneShot(_clipPain, GetLocalHead(), inHead: true, 0.5f + intensity * 0.5f, 0.9f + intensity * 0.25f); } public static void PlayDeath() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) PlayOneShot(_clipDeath, GetLocalHead(), inHead: true, Volume, 0.95f); } public static void PlayFracture() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) PlayOneShot(_clipFracture, GetLocalHead(), inHead: false, Volume, Random.Range(0.92f, 1.08f)); } public static void PlayFoot(Vector3 pos) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) PlayOneShot(_clipFoot, pos, inHead: false, Volume * 0.45f, Random.Range(0.88f, 1.12f)); } public static void PlayHit(float intensity, Vector3? at = null) { //IL_0019: 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) PlayOneShot(_clipHit, (Vector3)(((??)at) ?? GetLocalHead()), inHead: false, Volume * (0.35f + intensity * 0.45f), Random.Range(0.85f, 1.15f)); } private static void StopBreathLoop() { if (_breathSource == null) { return; } try { _breathSource.GetType().GetMethod("Stop")?.Invoke(_breathSource, null); } catch { } } private static void EnsureBreathSource() { if (_breathSource != null) { return; } try { Type typeFromHandle = typeof(GameObject); _breathGo = Activator.CreateInstance(typeFromHandle, "Homigrad_BreathLoop"); typeFromHandle.GetProperty("hideFlags")?.SetValue(_breathGo, (object)(HideFlags)61); Type type = Type.GetType("UnityEngine.AudioSource, UnityEngine.AudioModule") ?? typeof(Component).Assembly.GetType("UnityEngine.AudioSource"); if (!(type == null)) { _breathSource = typeFromHandle.GetMethod("AddComponent", new Type[1] { typeof(Type) })?.Invoke(_breathGo, new object[1] { type }); if (_breathSource != null) { type.GetProperty("spatialBlend")?.SetValue(_breathSource, 0f); type.GetProperty("playOnAwake")?.SetValue(_breathSource, false); } } } catch (Exception ex) { MelonLogger.Warning("[HomigradSounds] Breath source: " + ex.Message); } } private static void PlayOneShot(object? clip, Vector3 pos, bool inHead, float volScale, float pitch) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_00ea: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || clip == null) { return; } try { AudioPlayerSettings val = new AudioPlayerSettings { Volume = volScale * Volume, Pitch = pitch, SpatialBlend = (inHead ? 0f : 1f) }; TrySetSettingsMixer(val, inHead ? "InHead" : "HardInteraction"); Type typeFromHandle = typeof(LocalAudioPlayer); if (inHead) { typeFromHandle.GetMethod("Play2dOneShot", new Type[2] { clip.GetType(), typeof(AudioPlayerSettings) })?.Invoke(null, new object[2] { clip, val }); } else { typeFromHandle.GetMethod("PlayAtPoint", new Type[3] { clip.GetType(), typeof(Vector3), typeof(AudioPlayerSettings) })?.Invoke(null, new object[3] { clip, pos, val }); } } catch (Exception ex) { MelonLogger.Warning("[HomigradSounds] Play: " + ex.Message); } } private static void TrySetSettingsMixer(AudioPlayerSettings settings, string mixerProp) { try { object obj = typeof(LocalAudioPlayer).GetProperty(mixerProp, BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj != null) { typeof(AudioPlayerSettings).GetProperty("Mixer")?.SetValue(settings, obj); } } catch { } } private static void TrySetMixerReflect(object source, string mixerProp) { try { object obj = typeof(LocalAudioPlayer).GetProperty(mixerProp, BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj != null) { source.GetType().GetProperty("outputAudioMixerGroup")?.SetValue(source, obj); } } catch { } } private static object? MakeNoiseLoop(string name, float sec, float amp, float freq, float lfo) { int num = 44100; int num2 = Math.Max(1, (int)((float)num * sec)); float[] array = new float[num2]; float num3 = 0f; for (int i = 0; i < num2; i++) { float num4 = (float)i / (float)num; num3 += freq / (float)num; float num5 = 0.5f + 0.5f * Mathf.Sin(num4 * lfo * (float)Math.PI * 2f); array[i] = (Random.value * 2f - 1f) * amp * num5 * Mathf.Sin(num3 * (float)Math.PI * 2f); } return CreateClip(name, array, num); } private static object? MakeNoiseBurst(string name, float sec, float amp, float freq) { int num = 44100; int num2 = Math.Max(1, (int)((float)num * sec)); float[] array = new float[num2]; for (int i = 0; i < num2; i++) { float num3 = (float)i / (float)num2; float num4 = 1f - num3; array[i] = (Random.value * 2f - 1f) * amp * num4 * num4; } return CreateClip(name, array, num); } private static object? MakeToneBurst(string name, float sec, float f0, float f1, float amp) { int num = 44100; int num2 = Math.Max(1, (int)((float)num * sec)); float[] array = new float[num2]; for (int i = 0; i < num2; i++) { float num3 = (float)i / (float)num2; float num4 = Mathf.Lerp(f0, f1, num3); float num5 = (1f - num3) * (1f - num3); array[i] = Mathf.Sin((float)i / (float)num * num4 * (float)Math.PI * 2f) * amp * num5; } return CreateClip(name, array, num); } private static object? MakeCrack(string name, float sec) { int num = 44100; int num2 = Math.Max(1, (int)((float)num * sec)); float[] array = new float[num2]; for (int i = 0; i < num2; i++) { float num3 = (float)i / (float)num2; float num4 = (1f - num3) * (1f - num3) * (1f - num3); array[i] = ((Random.value * 2f - 1f) * 0.9f + Mathf.Sin((float)i * 0.37f) * 0.4f) * num4; } return CreateClip(name, array, num); } private static object? CreateClip(string name, float[] data, int rate) { Type type = Type.GetType("UnityEngine.AudioClip, UnityEngine.AudioModule"); if (type == null) { return null; } object obj = type.GetMethod("Create", new Type[5] { typeof(string), typeof(int), typeof(int), typeof(int), typeof(bool) })?.Invoke(null, new object[5] { name, data.Length, 1, rate, false }); type.GetMethod("SetData", new Type[2] { typeof(float[]), typeof(int) })?.Invoke(obj, new object[2] { data, 0 }); return obj; } private static bool TryGetHealth(out float hp, out float maxHp) { hp = (maxHp = 0f); try { Type type = Type.GetType("LabFusion.Data.RigData, LabFusion"); object obj = type?.GetProperty("HasPlayer")?.GetValue(null); if (!(obj is bool) || !(bool)obj) { return false; } object obj2 = type.GetProperty("Refs")?.GetValue(null); object obj3 = obj2?.GetType().GetProperty("RigManager")?.GetValue(obj2); object obj4 = obj3?.GetType().GetProperty("health")?.GetValue(obj3) ?? obj3?.GetType().GetField("health")?.GetValue(obj3); if (obj4 == null) { return false; } hp = Convert.ToSingle(obj4.GetType().GetProperty("curr_Health")?.GetValue(obj4) ?? obj4.GetType().GetField("curr_Health")?.GetValue(obj4)); maxHp = Convert.ToSingle(obj4.GetType().GetProperty("max_Health")?.GetValue(obj4) ?? obj4.GetType().GetField("max_Health")?.GetValue(obj4)); if (maxHp < 0.01f) { maxHp = 100f; } return true; } catch { return false; } } private static bool TryGetFeetPos(out Vector3 pos) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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_0137: Unknown result type (might be due to invalid IL or missing references) pos = default(Vector3); try { Type type = Type.GetType("LabFusion.Data.RigData, LabFusion"); object obj = type?.GetProperty("HasPlayer")?.GetValue(null); if (!(obj is bool) || !(bool)obj) { return false; } object obj2 = type.GetProperty("Refs")?.GetValue(null); object obj3 = obj2?.GetType().GetProperty("RigManager")?.GetValue(obj2); object obj4 = obj3?.GetType().GetProperty("physicsRig")?.GetValue(obj3); object obj5 = obj4?.GetType().GetProperty("feet")?.GetValue(obj4); object obj6 = obj5?.GetType().GetProperty("transform")?.GetValue(obj5); if (obj6?.GetType().GetProperty("position")?.GetValue(obj6) is Vector3 val) { pos = val; return true; } } catch { } return false; } private static bool TryGetGrounded(out bool grounded) { grounded = false; try { object obj = Type.GetType("LabFusion.Data.RigData, LabFusion")?.GetProperty("Refs")?.GetValue(null); object obj2 = obj?.GetType().GetProperty("RigManager")?.GetValue(obj); object obj3 = obj2?.GetType().GetProperty("physicsRig")?.GetValue(obj2); object obj4 = obj3?.GetType().GetProperty("feet")?.GetValue(obj3); if (obj4 == null) { return false; } object obj5 = null; MethodInfo method = obj4.GetType().GetMethod("GetComponent", new Type[1] { typeof(Type) }); if (method != null) { Type type = Type.GetType("SLZ.Marrow.PhysGrounder, Il2CppSLZ.Marrow") ?? Type.GetType("SLZ.Marrow.PhysGrounder, SLZ.Marrow"); if (type != null) { obj5 = method.Invoke(obj4, new object[1] { type }); } } if (obj5 == null) { return false; } object obj6 = obj5.GetType().GetProperty("isGrounded")?.GetValue(obj5); int num; if (!(obj6 is bool) || !(bool)obj6) { obj6 = obj5.GetType().GetField("isGrounded")?.GetValue(obj5); num = ((obj6 is bool && (bool)obj6) ? 1 : 0); } else { num = 1; } grounded = (byte)num != 0; return true; } catch { return false; } } private static bool TryGetSpeed(out float speed) { //IL_001f: 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) speed = 0f; if (!_hasLastPos) { return false; } try { if (!TryGetFeetPos(out var pos)) { return false; } speed = Vector3.Distance(pos, _lastPos) / Mathf.Max(Time.deltaTime, 0.016f); return true; } catch { return false; } } private static Vector3 GetLocalHead() { //IL_00b2: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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_00c8: 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_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_009a: Unknown result type (might be due to invalid IL or missing references) try { object obj = Type.GetType("LabFusion.Data.RigData, LabFusion")?.GetProperty("Refs")?.GetValue(null); object obj2 = obj?.GetType().GetProperty("Headset")?.GetValue(obj); Transform val = (Transform)((obj2 is Transform) ? obj2 : null); if (val != null) { return val.position; } if (obj2?.GetType().GetProperty("position")?.GetValue(obj2) is Vector3 result) { return result; } } catch { } if (!TryGetFeetPos(out var pos)) { return Vector3.zero; } return pos + Vector3.up * 1.6f; } private static Vector3 GetPlayerHead(PlayerID? id) { //IL_0003: 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_0158: 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_015f: 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_017d: Unknown result type (might be due to invalid IL or missing references) if (id == null) { return GetLocalHead(); } try { MethodInfo[] methods = Type.GetType("LabFusion.Representation.PlayerRepUtilities, LabFusion").GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "TryGetReferences") && methodInfo.GetParameters().Length == 2) { object[] array = new object[2] { id.SmallID, null }; object obj = methodInfo.Invoke(null, array); if (!(obj is bool) || !(bool)obj || array[1] == null) { break; } object value = array[1].GetType().GetProperty("RigManager").GetValue(array[1]); object obj2 = value.GetType().GetProperty("physicsRig")?.GetValue(value)?.GetType().GetProperty("head")?.GetValue(value.GetType().GetProperty("physicsRig").GetValue(value)); if (obj2 == null) { break; } object obj3 = obj2.GetType().GetProperty("transform")?.GetValue(obj2); obj = obj3?.GetType().GetProperty("position")?.GetValue(obj3); if (obj is Vector3) { return (Vector3)obj; } } } } catch { } return GetLocalHead(); } } internal static class PainOverlay { private sealed class BarUi { public Image? Bg; public Image? Fill; public Text? Label; } [CompilerGenerated] private static class <>O { public static PlayerAction <0>__OnPlayerAction; public static UpdateEvent <1>__OnSceneInit; } private static float _lastHp = -1f; private static float _flash; private static float _pulse; private static float _painSpike; private static bool _hooks; private static GameObject? _root; private static RawImage? _darkImage; private static RawImage? _vignetteImage; private static RawImage? _flashImage; private static RawImage? _painImage; private static GameObject? _hudRoot; private static Text? _statusText; private static readonly BarUi[] _bars = new BarUi[4]; private static Texture2D? _vignetteTex; private static Font? _font; private static Transform? _headset; public static bool Enabled { get; set; } = true; public static bool ShowIndicators { get; set; } = true; public static bool ShowVignette { get; set; } = true; public static float Intensity { get; set; } = 1f; public static float Blood { get; private set; } = 100f; public static float Pain { get; private set; } public static float Shock { get; private set; } public static int Fractures { get; private set; } public static void Init() { //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_0029: Expected O, but got Unknown //IL_003e: 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_0049: Expected O, but got Unknown if (_hooks) { return; } _hooks = true; try { object obj = <>O.<0>__OnPlayerAction; if (obj == null) { PlayerAction val = OnPlayerAction; <>O.<0>__OnPlayerAction = val; obj = (object)val; } MultiplayerHooking.OnPlayerAction += (PlayerAction)obj; object obj2 = <>O.<1>__OnSceneInit; if (obj2 == null) { UpdateEvent val2 = OnSceneInit; <>O.<1>__OnSceneInit = val2; obj2 = (object)val2; } MultiplayerHooking.OnMainSceneInitialized += (UpdateEvent)obj2; } catch (Exception ex) { MelonLogger.Warning("[PainOverlay] Hook: " + ex.Message); } } private static void OnSceneInit() { DestroyUi(); ResetAll(); } public static void Tick() { if (!Enabled) { SetUiActive(active: false); return; } float num = Mathf.Max(Time.deltaTime, 0.016f); if (!TryGetHealth(out var hp, out var maxHp)) { _lastHp = -1f; SetUiActive(active: false); return; } Blood = Mathf.Clamp((maxHp > 0.01f) ? (hp / maxHp * 100f) : 100f, 0f, 100f); if (_lastHp >= 0f && hp < _lastHp - 0.25f) { ApplyDamage(_lastHp - hp, fractured: false); } _lastHp = hp; Pain = Mathf.MoveTowards(Pain, 0f, num * (8f + Pain * 0.04f)); Shock = Mathf.MoveTowards(Shock, 0f, num * (14f + Shock * 0.08f)); _flash = Mathf.MoveTowards(_flash, 0f, num * 3.5f); _painSpike = Mathf.MoveTowards(_painSpike, 0f, num * 2.2f); _pulse = (Mathf.Sin(Time.realtimeSinceStartup * (4f + Pain * 0.05f)) * 0.5f + 0.5f) * (Pain / 100f); if (!EnsureUi()) { SetUiActive(active: false); } else { UpdateVisuals(); } } public static void NotifyDamage(float amount, bool fractured = false) { if (Enabled && !(amount <= 0f)) { ApplyDamage(amount, fractured); } } public static void Reset() { ResetAll(); } private static void ApplyDamage(float amount, bool fractured) { float num = Mathf.Clamp(amount / 6f, 0.15f, 1f); Pain = Mathf.Clamp(Pain + amount * (4.5f + num * 6f), 0f, 100f); Shock = Mathf.Clamp(Shock + amount * (2.5f + num * 5f), 0f, 100f); _flash = Mathf.Clamp(_flash + num * 0.85f, 0f, 1f); _painSpike = Mathf.Clamp(_painSpike + num, 0f, 1f); if (fractured) { Fractures = Mathf.Min(Fractures + 1, 8); Pain = Mathf.Clamp(Pain + 18f, 0f, 100f); Shock = Mathf.Clamp(Shock + 22f, 0f, 100f); _flash = 1f; } } private static void OnPlayerAction(PlayerID id, PlayerActionType type, PlayerID? other = null) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 if (Enabled && id != null && id.IsMe) { if ((int)type == 3 || (int)type == 5) { ApplyDamage(12f, fractured: false); } if ((int)type == 2 || (int)type == 7) { Pain = 100f; Shock = 100f; Blood = 0f; _flash = 1f; } } } private static void ResetAll() { Blood = 100f; Pain = (Shock = 0f); Fractures = 0; _lastHp = -1f; _flash = (_pulse = (_painSpike = 0f)); } private static bool EnsureUi() { Transform val = TryGetHeadset(); if ((Object)(object)val == (Object)null) { DestroyUi(); return false; } if ((Object)(object)_root != (Object)null && (Object)(object)_headset == (Object)(object)val) { return true; } if ((Object)(object)_root != (Object)null && (Object)(object)_headset != (Object)(object)val) { DestroyUi(); } _headset = val; CreateUi(val); return (Object)(object)_root != (Object)null; } private static void CreateUi(Transform headset) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_00e7: 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_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Expected O, but got Unknown //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0249: 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_0277: Unknown result type (might be due to invalid IL or missing references) //IL_028c: 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) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: 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_03c8: Unknown result type (might be due to invalid IL or missing references) try { EnsureVignetteTex(); EnsureFont(); _root = new GameObject("Homigrad_PainOverlay"); Object.DontDestroyOnLoad((Object)(object)_root); Type type = Type.GetType("UnityEngine.Canvas, UnityEngine.UIModule") ?? FindType("UnityEngine.Canvas"); if (type == null) { throw new InvalidOperationException("Canvas type not found"); } object obj = AddComp(_root, type); if (obj == null) { throw new InvalidOperationException("Canvas add failed"); } type.GetProperty("renderMode")?.SetValue(obj, 2); type.GetProperty("overrideSorting")?.SetValue(obj, true); type.GetProperty("sortingOrder")?.SetValue(obj, 30000); RectTransform component = _root.GetComponent<RectTransform>(); ((Transform)component).SetParent(headset, false); ((Transform)component).localPosition = new Vector3(0f, 0f, 0.045f); ((Transform)component).localRotation = Quaternion.Euler(0f, 180f, 0f); ((Transform)component).localScale = Vector3.one * 0.00072f; component.sizeDelta = new Vector2(900f, 900f); _darkImage = CreateStretchRaw(_root.transform, "Dark", 0); _vignetteImage = CreateStretchRaw(_root.transform, "Vignette", 1); _vignetteImage.texture = (Texture)(object)_vignetteTex; _flashImage = CreateStretchRaw(_root.transform, "Flash", 2); _painImage = CreateStretchRaw(_root.transform, "PainPulse", 3); _hudRoot = new GameObject("Hud"); RectTransform val = _hudRoot.AddComponent<RectTransform>(); ((Transform)val).SetParent(_root.transform, false); val.anchorMin = new Vector2(0f, 0f); val.anchorMax = new Vector2(0f, 0f); val.pivot = new Vector2(0f, 0f); val.anchoredPosition = new Vector2(24f, 24f); val.sizeDelta = new Vector2(360f, 170f); GameObject val2 = new GameObject("Status"); RectTransform obj2 = val2.AddComponent<RectTransform>(); ((Transform)obj2).SetParent((Transform)(object)val, false); obj2.anchorMin = new Vector2(0f, 1f); obj2.anchorMax = new Vector2(1f, 1f); obj2.pivot = new Vector2(0f, 1f); obj2.anchoredPosition = new Vector2(0f, 8f); obj2.sizeDelta = new Vector2(0f, 36f); _statusText = val2.AddComponent<Text>(); SetupText(_statusText, 28, (FontStyle)1); _statusText.alignment = (TextAnchor)6; ((Graphic)_statusText).color = new Color(1f, 0.3f, 0.25f, 0f); string[] array = new string[4] { "Blood", "Pain", "Shock", "Fractures" }; Color[] array2 = (Color[])(object)new Color[4] { new Color(0.75f, 0.08f, 0.08f, 0.92f), new Color(0.95f, 0.35f, 0.05f, 0.92f), new Color(0.55f, 0.15f, 0.85f, 0.92f), new Color(0.85f, 0.82f, 0.2f, 0.92f) }; for (int i = 0; i < 4; i++) { _bars[i] = CreateBar(val, array[i], array2[i], (float)i * 34f); } SetUiActive(active: true); } catch (Exception ex) { MelonLogger.Warning("[PainOverlay] VR UI create: " + ex.Message); DestroyUi(); } } private static BarUi CreateBar(RectTransform parent, string name, Color fillColor, float y) { //IL_0001: 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_0034: 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_005a: 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_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_00b1: 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_00e5: 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_010f: 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_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0149: 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_0160: 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_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) RectTransform val = new GameObject(name).AddComponent<RectTransform>(); ((Transform)val).SetParent((Transform)(object)parent, false); val.anchorMin = new Vector2(0f, 0f); val.anchorMax = new Vector2(1f, 0f); val.pivot = new Vector2(0f, 0f); val.anchoredPosition = new Vector2(0f, y); val.sizeDelta = new Vector2(0f, 28f); GameObject val2 = new GameObject("Bg"); RectTransform obj = val2.AddComponent<RectTransform>(); ((Transform)obj).SetParent((Transform)(object)val, false); StretchFull(obj); Image val3 = val2.AddComponent<Image>(); ((Graphic)val3).color = new Color(0f, 0f, 0f, 0.55f); ((Graphic)val3).raycastTarget = false; GameObject val4 = new GameObject("Fill"); RectTransform obj2 = val4.AddComponent<RectTransform>(); ((Transform)obj2).SetParent((Transform)(object)val, false); obj2.anchorMin = new Vector2(0f, 0f); obj2.anchorMax = new Vector2(0f, 1f); obj2.pivot = new Vector2(0f, 0.5f); obj2.anchoredPosition = new Vector2(3f, 0f); obj2.sizeDelta = new Vector2(0f, -6f); Image val5 = val4.AddComponent<Image>(); ((Graphic)val5).color = fillColor; ((Graphic)val5).raycastTarget = false; GameObject val6 = new GameObject("Label"); RectTransform obj3 = val6.AddComponent<RectTransform>(); ((Transform)obj3).SetParent((Transform)(object)val, false); StretchFull(obj3); obj3.offsetMin = new Vector2(8f, 0f); obj3.offsetMax = new Vector2(-8f, 0f); Text val7 = val6.AddComponent<Text>(); SetupText(val7, 22, (FontStyle)1); val7.alignment = (TextAnchor)3; ((Graphic)val7).color = Color.white; return new BarUi { Bg = val3, Fill = val5, Label = val7 }; } private static RawImage CreateStretchRaw(Transform parent, string name, int sibling) { //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_0019: 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) GameObject val = new GameObject(name); RectTransform obj = val.AddComponent<RectTransform>(); ((Transform)obj).SetParent(parent, false); StretchFull(obj); val.transform.SetSiblingIndex(sibling); RawImage obj2 = val.AddComponent<RawImage>(); ((Graphic)obj2).color = new Color(1f, 1f, 1f, 0f); ((Graphic)obj2).raycastTarget = false; return obj2; } private static void StretchFull(RectTransform rt) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0022: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one; rt.offsetMin = Vector2.zero; rt.offsetMax = Vector2.zero; } private static void SetupText(Text t, int size, FontStyle style) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) t.font = _font; t.fontSize = size; t.fontStyle = style; t.horizontalOverflow = (HorizontalWrapMode)1; t.verticalOverflow = (VerticalWrapMode)1; t.supportRichText = false; ((Graphic)t).raycastTarget = false; } private static void UpdateVisuals() { //IL_00f6: 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_0154: 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_0392: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root == (Object)null) { return; } float num = 1f - Blood / 100f; float num2 = Mathf.Clamp01(Pain / 100f * 0.55f + Shock / 100f * 0.45f + num * 0.65f); float num3 = 0f; float num4 = 0f; if (ShowVignette) { num3 = Mathf.Clamp01((num * 0.55f + num2 * 0.35f + _pulse * 0.15f) * Intensity) * 0.72f; if (Shock > 25f) { num3 += Mathf.Clamp01((Shock - 25f) / 120f) * 0.25f * Intensity; } num4 = Mathf.Clamp01(0.25f + num2 * 0.55f) * Intensity * 0.78f; } SetRawAlpha(_darkImage, new Color(0f, 0f, 0f, num3)); SetRawAlpha(_vignetteImage, new Color(0f, 0f, 0f, num4)); float num5 = (_flash + _painSpike * 0.6f) * Intensity * 0.45f; SetRawAlpha(_flashImage, new Color(0.55f, 0.02f, 0.02f, num5)); float num6 = 0f; if (Pain > 35f) { num6 = (Pain - 35f) / 65f * _pulse * 0.22f * Intensity; } SetRawAlpha(_painImage, new Color(0.35f, 0f, 0f, num6)); bool showIndicators = ShowIndicators; if ((Object)(object)_hudRoot != (Object)null) { _hudRoot.SetActive(showIndicators); } if (showIndicators && !((Object)(object)_statusText == (Object)null)) { SetBar(_bars[0], Blood / 100f, "Blood", $"{Blood:0}%"); SetBar(_bars[1], Pain / 100f, "Pain", $"{Pain:0}%"); SetBar(_bars[2], Shock / 100f, "Shock", $"{Shock:0}%"); float num7 = ((Fractures > 0) ? Mathf.Clamp01((float)Fractures / 4f) : 0f); SetBar(_bars[3], Mathf.Max(num7, (Fractures > 0) ? 0.15f : 0f), "Fractures", Fractures.ToString()); bool flag = Blood < 35f || Pain > 70f || Shock > 60f; _statusText.text = (flag ? GetStatusText() : string.Empty); ((Graphic)_statusText).color = new Color(1f, 0.25f, 0.2f, flag ? (0.85f + _pulse * 0.15f) : 0f); } } private static void SetBar(BarUi bar, float fill, string name, string value) { //IL_0049: 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_0071: 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 (!((Object)(object)bar.Fill == (Object)null) && !((Object)(object)bar.Label == (Object)null)) { RectTransform rectTransform = ((Graphic)bar.Fill).rectTransform; float num; if (!((Object)(object)bar.Bg != (Object)null)) { num = 300f; } else { Rect rect = ((Graphic)bar.Bg).rectTransform.rect; num = ((Rect)(ref rect)).width - 6f; } float num2 = num; rectTransform.sizeDelta = new Vector2(Mathf.Max(0f, num2 * Mathf.Clamp01(fill)), rectTransform.sizeDelta.y); bar.Label.text = name + " " + value; } } private static void SetRawAlpha(RawImage? img, Color c) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)img == (Object)null)) { ((Graphic)img).color = c; } } private static string GetStatusText() { if (Blood < 20f) { return "CRITICAL — blood loss"; } if (Shock > 75f) { return "SHOCK"; } if (Pain > 85f) { return "SEVERE PAIN"; } if (Fractures >= 3) { return "MULTIPLE FRACTURES"; } if (Blood < 35f) { return "Heavy bleeding"; } if (Pain > 70f) { return "Intense pain"; } if (Shock > 60f) { return "Shock"; } return "Injured"; } private static void SetUiActive(bool active) { if ((Object)(object)_root != (Object)null) { _root.SetActive(active); } } private static void DestroyUi() { if ((Object)(object)_root != (Object)null) { try { Object.Destroy((Object)(object)_root); } catch { } _root = null; } _darkImage = (_vignetteImage = (_flashImage = (_painImage = null))); _hudRoot = null; _statusText = null; for (int i = 0; i < _bars.Length; i++) { _bars[i] = new BarUi(); } _headset = null; } private static void EnsureVignetteTex() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_vignetteTex != (Object)null) { return; } _vignetteTex = new Texture2D(256, 256, (TextureFormat)4, false); float num = 127.5f; for (int i = 0; i < 256; i++) { for (int j = 0; j < 256; j++) { float num2 = ((float)j - num) / num; float num3 = ((float)i - num) / num; float num4 = Mathf.Clamp01((Mathf.Sqrt(num2 * num2 + num3 * num3) - 0.35f) / 0.65f); num4 *= num4; _vignetteTex.SetPixel(j, i, new Color(0f, 0f, 0f, num4)); } } _vignetteTex.Apply(); } private static void EnsureFont() { if (!((Object)(object)_font != (Object)null)) { _font = Resources.GetBuiltinResource<Font>("Arial.ttf"); if ((Object)(object)_font == (Object)null) { _font = Font.CreateDynamicFontFromOSFont("Arial", 24); } } } private static Transform? TryGetHeadset() { try { Type type = Type.GetType("LabFusion.Data.RigData, LabFusion"); object obj = type?.GetProperty("HasPlayer")?.GetValue(null); if (!(obj is bool) || !(bool)obj) { return null; } object obj2 = type.GetProperty("Refs")?.GetValue(null); object? obj3 = obj2?.GetType().GetProperty("Headset")?.GetValue(obj2); Transform val = (Transform)((obj3 is Transform) ? obj3 : null); if (val != null && (Object)(object)val != (Object)null) { return val; } } catch { } return null; } private static bool TryGetHealth(out float hp, out float maxHp) { hp = (maxHp = 0f); try { Type type = Type.GetType("LabFusion.Data.RigData, LabFusion"); object obj = type?.GetProperty("HasPlayer")?.GetValue(null); if (!(obj is bool) || !(bool)obj) { return false; } object obj2 = type.GetProperty("Refs")?.GetValue(null); object obj3 = obj2?.GetType().GetProperty("RigManager")?.GetValue(obj2); object obj4 = obj3?.GetType().GetProperty("health")?.GetValue(obj3) ?? obj3?.GetType().GetField("health")?.GetValue(obj3); if (obj4 == null) { return false; } hp = Convert.ToSingle(obj4.GetType().GetProperty("curr_Health")?.GetValue(obj4) ?? obj4.GetType().GetField("curr_Health")?.GetValue(obj4)); maxHp = Convert.ToSingle(obj4.GetType().GetProperty("max_Health")?.GetValue(obj4) ?? obj4.GetType().GetField("max_Health")?.GetValue(obj4)); if (maxHp < 0.01f) { maxHp = 100f; } return true; } catch { return false; } } private static Type? FindType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(fullName); if (type != null) { return type; } } catch { } } return null; } private static object? AddComp(GameObject go, Type componentType) { try { MethodInfo method = typeof(GameObject).GetMethod("AddComponent", new Type[1] { typeof(Type) }); if (method != null) { return method.Invoke(go, new object[1] { componentType }); } MethodInfo[] methods = typeof(GameObject).GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "AddComponent") && methodInfo.GetParameters().Length == 1) { object obj = ToIl2CppType(componentType); if (obj != null) { return methodInfo.Invoke(go, new object[1] { obj }); } } } } catch { } return null; } private static object? ToIl2CppType(Type t) { try { Type type = FindType("Il2CppInterop.Runtime.Il2CppType"); MethodInfo methodInfo = type?.GetMethod("Of", BindingFlags.Static | BindingFlags.Public); if (methodInfo != null) { return methodInfo.MakeGenericMethod(t).Invoke(null, null); } return type?.GetMethod("From", new Type[1] { typeof(Type) })?.Invoke(null, new object[1] { t }); } catch { return null; } } } internal static class RagdollUtil { public static void SafeRagdoll(object physicsRig) { try { physicsRig.GetType().GetMethod("RagdollRig", Type.EmptyTypes)?.Invoke(physicsRig, null); TryZeroVelocity(physicsRig); } catch (Exception ex) { MelonLogger.Warning("[Homigrad] SafeRagdoll: " + ex.Message); } } public static bool IsRagdolled(object physicsRig) { try { object obj = physicsRig.GetType().GetField("shutdown", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(physicsRig) ?? physicsRig.GetType().GetProperty("shutdown")?.GetValue(physicsRig); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static void TryZeroVelocity(object physicsRig) { try { Type type = Type.GetType("UnityEngine.Vector3, UnityEngine.CoreModule") ?? Type.GetType("UnityEngine.Vector3, UnityEngine"); if (type == null) { return; } object value = Activator.CreateInstance(type, 0f, 0f, 0f); string[] array = new string[3] { "wholeBodyVelocity", "_velocity", "velocity" }; foreach (string name in array) { PropertyInfo property = physicsRig.GetType().GetProperty(name); if (property != null && property.CanWrite && property.PropertyType == type) { property.SetValue(physicsRig, value); continue; } FieldInfo field = physicsRig.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == type) { field.SetValue(physicsRig, value); } } } catch { } } } internal static class SelfHarmFeature { private static bool _enabled = true; private static bool _harmonyPatched; private static bool _typesResolved; private static bool _loggedReady; private static bool _loggedFail; private static float _reapplyTimer; private static Type? _playerType; private static Type? _impactPropertiesType; private static Type? _rigidbodyType; private static Type? _objectType; private static Type? _componentType; private static Type? _dataCardRefOpen; private static Type? _surfaceDataCardType; private static Type? _decalType; private static MethodInfo? _opEquality; private static MethodInfo? _opImplicit; private static MethodInfo? _getComponentsInChildren; private static MethodInfo? _getComponent; private static MethodInfo? _addComponent; private static MethodInfo? _destroy; private static MethodInfo? _getInstanceId; private static PropertyInfo? _gameObjectProp; private static PropertyInfo? _surfaceDataCardProp; private static PropertyInfo? _decalTypeProp; private static PropertyInfo? _testVisualDamage; public static bool Enabled { get { return _enabled; } set { if (_enabled == value) { return; } _enabled = value; try { if (_enabled) { Apply(); } else { Remove(); } } catch (Exception ex) { MelonLogger.Warning("[Homigrad] SelfHarm toggle: " + ex.Message); } } } public static void InitHarmony(Harmony harmony) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown if (_harmonyPatched) { return; } try { MethodInfo methodInfo = FindType("Il2CppSLZ.Bonelab.UIRig")?.GetMethod("Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(methodInfo == null)) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(SelfHarmFeature), "OnUiRigAwake", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _harmonyPatched = true; } } catch (Exception ex) { MelonLogger.Warning("[Homigrad] SelfHarm Harmony: " + ex.Message); } } private static void OnUiRigAwake() { if (!_enabled) { return; } try { Apply(); } catch { } } public static void Tick(bool active) { if (!_enabled || !active) { return; } _reapplyTimer -= 1f / 60f; if (_reapplyTimer > 0f) { return; } _reapplyTimer = 2f; try { Apply(); } catch { } } public static void Apply() { EnsureTypes(); if (_impactPropertiesType == null || _playerType == null) { LogFailOnce("types missing"); } else { if (!TryGetRigManager(out object rigManager) || !TryGetPhysicsRig(rigManager, out object physicsRig)) { return; } SetTestVisualDamage(rigManager, value: true); object obj = CreateBloodSurfaceCard(); object fieldOrProp = GetFieldOrProp(physicsRig, "feet"); object? fieldOrProp2 = GetFieldOrProp(physicsRig, "knee"); int instanceId = GetInstanceId(fieldOrProp); int instanceId2 = GetInstanceId(fieldOrProp2); object componentsInChildren = GetComponentsInChildren(physicsRig, _rigidbodyType); if (componentsInChildren == null) { return; } int num = 0; foreach (object item in (IEnumerable)componentsInChildren) { if (item == null || IsUnityNull(item)) { continue; } object obj2 = _gameObjectProp?.GetValue(item); if (obj2 == null || IsUnityNull(obj2)) { continue; } int instanceId3 = GetInstanceId(obj2); if ((instanceId3 != 0 && (instanceId3 == instanceId || instanceId3 == instanceId2)) || HasImpactProperties(obj2)) { continue; } object obj3 = AddImpactProperties(obj2); if (obj3 == null) { continue; } if (obj != null && _surfaceDataCardProp != null) { try { _surfaceDataCardProp.SetValue(obj3, obj); } catch { } } if (_decalTypeProp != null && _decalType != null) { try { _decalTypeProp.SetValue(obj3, Enum.ToObject(_decalType, -1)); } catch { } } num++; } if (!_loggedReady) { _loggedReady = true; MelonLogger.Msg("[Homigrad] SelfHarm active — you can hurt yourself with weapons."); } if (num > 0) { MelonLogger.Msg($"[Homigrad] SelfHarm: added ImpactProperties x{num}"); } } } public static void Remove() { EnsureTypes(); if (_impactPropertiesType == null || _playerType == null || _destroy == null || !TryGetRigManager(out object rigManager) || !TryGetPhysicsRig(rigManager, out object physicsRig)) { return; } object componentsInChildren = GetComponentsInChildren(physicsRig, _rigidbodyType); if (componentsInChildren == null) { return; } foreach (object item in (IEnumerable)componentsInChildren) { if (item == null || IsUnityNull(item)) { continue; } object obj = _gameObjectProp?.GetValue(item); if (obj == null || IsUnityNull(obj)) { continue; } object impactProperties = GetImpactProperties(obj); if (impactProperties != null && !IsUnityNull(impactProperties)) { try { _destroy.Invoke(null, new object[1] { impactProperties }); } catch { } } } } private static void EnsureTypes() { if (_typesResolved) { return; } _typesResolved = true; try { _playerType = FindType("BoneLib.Player"); _impactPropertiesType = FindType("Il2CppSLZ.Marrow.ImpactProperties"); _rigidbodyType = Type.GetType("UnityEngine.Rigidbody, UnityEngine.PhysicsModule") ?? FindType("UnityEngine.Rigidbody"); _objectType = Type.GetType("UnityEngine.Object, UnityEngine.CoreModule") ?? FindType("UnityEngine.Object"); _componentType = Type.GetType("UnityEngine.Component, UnityEngine.CoreModule") ?? FindType("UnityEngine.Component"); _dataCardRefOpen = FindType("Il2CppSLZ.Marrow.Warehouse.DataCardReference`1"); _surfaceDataCardType = FindType("Il2CppSLZ.Marrow.Warehouse.SurfaceDataCard"); _decalType = FindType("DecalType") ?? FindType("Il2CppSLZ.Marrow.DecalType"); _opEquality = _objectType?.GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public); _opImplicit = null; if (_objectType != null) { MethodInfo[] methods = _objectType.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "op_Implicit" && methodInfo.ReturnType == typeof(bool)) { _opImplicit = methodInfo; break; } } } if (_objectType != null) { MethodInfo[] methods = _objectType.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo2 in methods) { if (!(methodInfo2.Name != "Destroy") && methodInfo2.GetParameters().Length == 1) { _destroy = methodInfo2; break; } } } _getInstanceId = _objectType?.GetMethod("GetInstanceID", BindingFlags.Instance | BindingFlags.Public); _gameObjectProp = _componentType?.GetProperty("gameObject"); if (_componentType != null && _rigidbodyType != null) { MethodInfo[] methods = _componentType.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo3 in methods) { if (methodInfo3.Name == "GetComponentsInChildren" && methodInfo3.IsGenericMethodDefinition && methodInfo3.GetParameters().Length == 0) { _getComponentsInChildren = methodInfo3.MakeGenericMethod(_rigidbodyType); break; } } if (_getComponentsInChildren == null) { methods = _componentType.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo4 in methods) { ParameterInfo[] parameters = methodInfo4.GetParameters(); if (methodInfo4.Name == "GetComponentsInChildren" && parameters.Length == 1 && parameters[0].ParameterType == typeof(Type)) { _getComponentsInChildren = methodInfo4; break; } } } } Type type = Type.GetType("UnityEngine.GameObject, UnityEngine.CoreModule") ?? FindType("UnityEngine.GameObject"); if (type != null && _impactPropertiesType != null) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo5 in methods) { if (methodInfo5.Name == "GetComponent" && methodInfo5.IsGenericMethodDefinition && methodInfo5.GetParameters().Length == 0) { _getComponent = methodInfo5.MakeGenericMethod(_impactPropertiesType); break; } } methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo6 in methods) { if (methodInfo6.Name == "AddComponent" && methodInfo6.IsGenericMethodDefinition && methodInfo6.GetParameters().Length == 0) { _addComponent = methodInfo6.MakeGenericMethod(_impactPropertiesType); break; } } if (_addComponent == null) { Type type2 = FindType("Il2CppSystem.Type"); if (type2 != null) { _addComponent = type.GetMethod("AddComponent", new Type[1] { type2 }); } } } _surfaceDataCardProp = _impactPropertiesType?.GetProperty("SurfaceDataCard"); _decalTypeProp = _impactPropertiesType?.GetProperty("decalType"); _testVisualDamage = FindType("Il2CppSLZ.Marrow.Health")?.GetProperty("_testVisualDamage"); } catch (Exception ex) { MelonLogger.Warning("[Homigrad] SelfHarm init: " + ex.Message); } } private static object? CreateBloodSurfaceCard() { try { if (_dataCardRefOpen != null && _surfaceDataCardType != null) { Type type = _dataCardRefOpen.MakeGenericType(_surfaceDataCardType); ConstructorInfo constructor = type.GetConstructor(new Type[1] { typeof(string) }); if (constructor != null) { return constructor.Invoke(new object[1] { "SLZ.Backlot.SurfaceDataCard.Blood" }); } return Activator.CreateInstance(type, "SLZ.Backlot.SurfaceDataCard.Blood"); } return (FindType("Il2CppSLZ.Marrow.Warehouse.DataCardReference")?.GetConstructor(new Type[1] { typeof(string) }))?.Invoke(new object[1] { "SLZ.Backlot.SurfaceDataCard.Blood" }); } catch (Exception ex) { LogFailOnce("surface card: " + ex.Message); return null; } } private static object? GetComponentsInChildren(object component, Type elementType) { if (_getComponentsInChildren == null) { return null; } try { if (_getComponentsInChildren.IsGenericMethod) { return _getComponentsInChildren.Invoke(component, null); } return _getComponentsInChildren.Invoke(component, new object[1] { elementType }); } catch { return null; } } private static bool HasImpactProperties(object go) { if (GetImpactProperties(go) != null) { return !IsUnityNull(GetImpactProperties(go)); } return false; } private static object? GetImpactProperties(object go) { try { if (_getComponent != null) { return _getComponent.Invoke(go, null); } } catch { } return null; } private static object? AddImpactProperties(object go) { try { if (_addComponent == null) { return null; } if (_addComponent.IsGenericMethod) { return _addComponent.Invoke(go, null); } MethodInfo methodInfo = FindType("Il2CppSystem.Type")?.GetMethod("internal_from_handle", BindingFlags.Static | BindingFlags.Public) ?? FindType("Il2CppInterop.Runtime.Il2CppType")?.GetMethod("From", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Type) }, null); object obj = null; if (methodInfo != null && methodInfo.GetParameters().Length == 1 && methodInfo.GetParameters()[0].ParameterType == typeof(Type)) { obj = methodInfo.Invoke(null, new object[1] { _impactPropertiesType }); } else { Type type = FindType("Il2CppInterop.Runtime.Il2CppType"); obj = type?.GetMethod("Of", BindingFlags.Static | BindingFlags.Public)?.MakeGenericMethod(_impactPropertiesType).Invoke(null, null) ?? type?.GetMethod("From", new Type[1] { typeof(Type) })?.Invoke(null, new object[1] { _impactPropertiesType }); } if (obj == null) { return null; } return _addComponent.Invoke(go, new object[1] { obj }); } catch (Exception ex) { LogFailOnce("AddComponent: " + ex.Message); return null; } } private static void SetTestVisualDamage(object rigManager, bool value) { try { object fieldOrProp = GetFieldOrProp(rigManager, "health"); if (fieldOrProp != null && !(_testVisualDamage == null)) { _testVisualDamage.SetValue(fieldOrProp, value); } } catch { } } private static bool TryGetRigManager(out object rigManager) { rigManager = null; try { object obj = _playerType.GetField("rigManager", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) ?? _playerType.GetProperty("rigManager", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) ?? _playerType.GetProperty("RigManager", BindingFlags.Static | BindingFlags.Public)?.GetValue(null); if (obj == null || IsUnityNull(obj)) { return false; } rigManager = obj; return true; } catch { return false; } }