Decompiled source of DeathHeadHopperFix v0.1.6
DeathHeadHopperFix.dll
Decompiled 2 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.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using DeathHeadHopper.DeathHead.Handlers; using DeathHeadHopperFix.Modules.Battery; using DeathHeadHopperFix.Modules.Config; using DeathHeadHopperFix.Modules.Gameplay; using DeathHeadHopperFix.Modules.Patches; using DeathHeadHopperFix.Modules.Utilities; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 DeathHeadHopperFix { [HarmonyPatch(typeof(SpectateCamera), "StateNormal")] internal static class SpectateCameraStateNormalPatchMarker { [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return SpectateCameraStateNormalPatch.Transpiler(instructions); } } [BepInPlugin("AdrenSnyder.DeathHeadHopperFix", "Death Head Hopper - Fix", "0.1.6")] public sealed class Plugin : BaseUnityPlugin { private readonly struct DiminishingReturnsResult { public float BaseValue { get; } public float IncreasePerLevel { get; } public int AppliedLevel { get; } public int ThresholdLevel { get; } public float DiminishingFactor { get; } public int LinearLevels { get; } public int ExtraLevels { get; } public float LinearContribution { get; } public float DiminishingContribution { get; } public float DiminishingComponent { get; } public float FinalValue { get; } public DiminishingReturnsResult(float baseValue, float increasePerLevel, int appliedLevel, int thresholdLevel, float diminishingFactor, int linearLevels, int extraLevels, float linearContribution, float diminishingContribution, float diminishingComponent, float finalValue) { BaseValue = baseValue; IncreasePerLevel = increasePerLevel; AppliedLevel = appliedLevel; ThresholdLevel = thresholdLevel; DiminishingFactor = diminishingFactor; LinearLevels = linearLevels; ExtraLevels = extraLevels; LinearContribution = linearContribution; DiminishingContribution = diminishingContribution; DiminishingComponent = diminishingComponent; FinalValue = finalValue; } } private const string TargetAssemblyName = "DeathHeadHopper"; private const string HopForceLogKey = "Fix:Hop.JumpForce"; private const string JumpForceLogKey = "Fix:Jump.HeadJumpForce"; private const string ChargeStrengthLogKey = "Fix:Charge.Strength"; private Harmony? _harmony; private bool _patched; private static ManualLogSource? _log; private static bool _guardMissingLocalCameraPosition; private static FieldInfo? _jumpHandlerJumpBufferField; private static FieldInfo? s_playerAvatarDeadSetField = AccessTools.Field(typeof(PlayerAvatar), "deadSet"); private static FieldInfo? s_abilityEnergyHandlerControllerField; private static FieldInfo? s_deathHeadControllerDeathHeadField; private static FieldInfo? s_playerDeathHeadAvatarField; private static FieldInfo? s_playerAvatarIsDisabledField = AccessTools.Field(typeof(PlayerAvatar), "isDisabled"); private static MethodInfo? s_hopHandlerPowerLevelGetter; private static MethodInfo? s_jumpHandlerPowerLevelGetter; private static FieldInfo? s_chargeHandlerChargeStrengthField; private static MethodInfo? s_chargeHandlerAbilityLevelGetter; private static FieldInfo? s_chargeHandlerImpactDetectorField; private static FieldInfo? s_impactDetectorPhysGrabObjectField; private static FieldInfo? s_cachedPhysGrabObjectGrabbedField; private void Awake() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown _log = ((BaseUnityPlugin)this).Logger; ConfigManager.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); _harmony = new Harmony("AdrenSnyder.DeathHeadHopperFix"); PatchSpectateCameraStateNormal(); _harmony.PatchAll(typeof(Plugin).Assembly); DetectGameApiChanges(); ApplyEarlyPatches(); AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly asm in assemblies) { TryPatchIfTargetAssembly(asm); } } private void OnDestroy() { AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad; } private void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args) { TryPatchIfTargetAssembly(args.LoadedAssembly); } private void ApplyEarlyPatches() { if (_harmony != null) { StatsModule.ApplyHooks(_harmony); ItemUpgradeModule.Apply(_harmony); } } private void PatchSpectateCameraStateNormal() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(typeof(SpectateCamera), "StateNormal", (Type[])null, (Type[])null); if (methodInfo == null) { return; } MethodInfo method = typeof(SpectateCameraStateNormalPatch).GetMethod("Transpiler", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { Harmony? harmony = _harmony; if (harmony != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null); } } } catch (Exception ex) { ManualLogSource? log = _log; if (log != null) { log.LogError((object)ex); } } } private void TryPatchIfTargetAssembly(Assembly asm) { if (_patched || asm == null) { return; } string name = asm.GetName().Name; if (!string.Equals(name, "DeathHeadHopper", StringComparison.OrdinalIgnoreCase)) { return; } try { ManualLogSource? log = _log; if (log != null) { log.LogInfo((object)"Detected DeathHeadHopper assembly load. Applying patches..."); } Harmony harmony = _harmony; if (harmony == null) { throw new InvalidOperationException("Harmony instance is null."); } PrefabModule.Apply(harmony, asm, _log); AudioModule.Apply(harmony, asm, _log); DHHShopModule.Apply(harmony, asm, _log); PatchDeathHeadControllerGuardsIfPossible(harmony, asm); PatchDeathHeadControllerModulesIfPossible(harmony, asm); PatchJumpHandlerUpdateIfPossible(harmony, asm); PatchChargeHandlerDamageModeIfPossible(harmony, asm); PatchJumpHandlerJumpForceIfPossible(harmony, asm); PatchHopHandlerJumpForceIfPossible(harmony, asm); InputModule.Apply(harmony, asm, _log); PatchAbilityEnergyHandlerRechargeSoundIfPossible(harmony, asm); AbilityModule.ApplyAbilitySpotLabelOverlay(harmony, asm); if (!FeatureFlags.DisableAbilityPatches) { AbilityModule.ApplyAbilityManagerHooks(harmony, asm); PatchChargeAbilityGettersIfPossible(harmony, asm); } _patched = true; ManualLogSource? log2 = _log; if (log2 != null) { log2.LogInfo((object)"Patches applied successfully."); } } catch (Exception ex) { ManualLogSource? log3 = _log; if (log3 != null) { log3.LogError((object)ex); } } } private static void PatchAbilityEnergyHandlerRechargeSoundIfPossible(Harmony harmony, Assembly asm) { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.AbilityEnergyHandler", throwOnError: false); if (type == null) { return; } if ((object)s_abilityEnergyHandlerControllerField == null) { s_abilityEnergyHandlerControllerField = type.GetField("controller", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } Type type2 = asm.GetType("DeathHeadHopper.DeathHead.DeathHeadController", throwOnError: false); if (type2 != null && (object)s_deathHeadControllerDeathHeadField == null) { s_deathHeadControllerDeathHeadField = type2.GetField("deathHead", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } Type type3 = asm.GetType("PlayerDeathHead", throwOnError: false); if (type3 != null && (object)s_playerDeathHeadAvatarField == null) { s_playerDeathHeadAvatarField = type3.GetField("playerAvatar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } MethodInfo methodInfo = AccessTools.Method(type, "PlayRechargeSound", Type.EmptyTypes, (Type[])null); if (!(methodInfo == null)) { MethodInfo method = typeof(Plugin).GetMethod("AbilityEnergyHandler_PlayRechargeSound_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static bool AbilityEnergyHandler_PlayRechargeSound_Prefix(object __instance) { if (SemiFunc.IsSpectating() || IsLocalPlayerDead()) { return false; } PlayerAvatar abilityEnergyHandlerPlayerAvatar = GetAbilityEnergyHandlerPlayerAvatar(__instance); if (IsAbilityPlayerDisabled(abilityEnergyHandlerPlayerAvatar)) { return false; } return true; } private static PlayerAvatar? GetAbilityEnergyHandlerPlayerAvatar(object? handler) { if (handler == null || s_abilityEnergyHandlerControllerField == null) { return null; } object value = s_abilityEnergyHandlerControllerField.GetValue(handler); if (value == null || s_deathHeadControllerDeathHeadField == null) { return null; } object value2 = s_deathHeadControllerDeathHeadField.GetValue(value); if (value2 == null || s_playerDeathHeadAvatarField == null) { return null; } object? value3 = s_playerDeathHeadAvatarField.GetValue(value2); return (PlayerAvatar?)((value3 is PlayerAvatar) ? value3 : null); } private static bool IsAbilityPlayerDisabled(PlayerAvatar? avatar) { if ((Object)(object)avatar == (Object)null || s_playerAvatarIsDisabledField == null) { return false; } object value = s_playerAvatarIsDisabledField.GetValue(avatar); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static bool IsLocalPlayerDead() { PlayerAvatar instance = PlayerAvatar.instance; if ((Object)(object)instance == (Object)null || s_playerAvatarDeadSetField == null) { return false; } object value = s_playerAvatarDeadSetField.GetValue(instance); bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static void PatchChargeAbilityGettersIfPossible(Harmony harmony, Assembly asm) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.Abilities.Charge.ChargeAbility", throwOnError: false); if (type == null) { return; } MethodInfo methodInfo = AccessTools.PropertyGetter(type, "EnergyCost"); MethodInfo methodInfo2 = AccessTools.PropertyGetter(type, "Cooldown"); if (methodInfo == null) { return; } MethodInfo method = typeof(Plugin).GetMethod("ChargeAbility_EnergyCost_Postfix", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method2 = typeof(Plugin).GetMethod("ChargeAbility_Cooldown_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null) && !(method2 == null)) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); if (methodInfo2 != null) { harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void ChargeAbility_EnergyCost_Postfix(Object __instance, ref float __result) { if (__instance == (Object)null) { return; } float num = Mathf.Max(0f, __result); float num2 = Mathf.Max(0f, (float)FeatureFlags.ChargeAbilityStaminaCost); if (num2 <= 0f) { __result = num; return; } __result = num2; if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("DHHCharge.Cost")) { Debug.Log((object)$"[Fix:DHHCharge] Charge cost override: custom={num2:F3} base={num:F3}"); } } private static bool ChargeAbility_Cooldown_Prefix(Object __instance, ref float __result) { if (__instance == (Object)null) { return true; } float num = (__result = Mathf.Max(0f, (float)FeatureFlags.ChargeAbilityCooldown)); if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("DHHCharge.Cooldown")) { Debug.Log((object)$"[Fix:DHHCharge] Cooldown override: custom={num:F3}"); } return false; } private static void DetectGameApiChanges() { try { Type type = AccessTools.TypeByName("PlayerAvatar"); if (type == null) { _guardMissingLocalCameraPosition = true; return; } FieldInfo field = type.GetField("localCameraPosition", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _guardMissingLocalCameraPosition = field == null; } catch { _guardMissingLocalCameraPosition = true; } } private static void PatchDeathHeadControllerGuardsIfPossible(Harmony harmony, Assembly asm) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown if (!_guardMissingLocalCameraPosition) { return; } Type type = asm.GetType("DeathHeadHopper.DeathHead.DeathHeadController", throwOnError: false); if (type == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "CancelReviveInCart", (Type[])null, (Type[])null); if (methodInfo != null) { MethodInfo method = typeof(Plugin).GetMethod("DeathHeadController_CancelReviveInCart_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (method != null) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } MethodInfo methodInfo2 = AccessTools.Method(type, "Update", (Type[])null, (Type[])null); if (methodInfo2 != null) { MethodInfo method2 = typeof(Plugin).GetMethod("DeathHeadController_Update_Finalizer", BindingFlags.Static | BindingFlags.NonPublic); if (method2 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null); } } } private static bool DeathHeadController_CancelReviveInCart_Prefix() { if (_guardMissingLocalCameraPosition) { return false; } return true; } private static Exception? DeathHeadController_Update_Finalizer(Exception? __exception) { if (__exception == null) { return null; } if (_guardMissingLocalCameraPosition && __exception is MissingFieldException) { return null; } return __exception; } private static void PatchDeathHeadControllerModulesIfPossible(Harmony harmony, Assembly asm) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.DeathHead.DeathHeadController", throwOnError: false); if (type == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "Start", (Type[])null, (Type[])null); if (!(methodInfo == null)) { MethodInfo method = typeof(Plugin).GetMethod("DeathHeadController_Start_Postfix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void DeathHeadController_Start_Postfix(object __instance) { MonoBehaviour val = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null); if (val != null) { GameObject gameObject = ((Component)val).gameObject; if (FeatureFlags.BatteryJumpEnabled && !FeatureFlags.DisableBatteryModule && (Object)(object)gameObject.GetComponent<BatteryModule>() == (Object)null) { gameObject.AddComponent<BatteryModule>(); } } } private static void PatchJumpHandlerUpdateIfPossible(Harmony harmony, Assembly asm) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.JumpHandler", throwOnError: false); if (type == null) { return; } _jumpHandlerJumpBufferField = AccessTools.Field(type, "jumpBufferTimer"); if (_jumpHandlerJumpBufferField == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "Update", (Type[])null, (Type[])null); if (!(methodInfo == null)) { MethodInfo method = typeof(Plugin).GetMethod("JumpHandler_Update_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void JumpHandler_Update_Prefix(MonoBehaviour __instance) { if (!FeatureFlags.BatteryJumpEnabled || (Object)(object)__instance == (Object)null || _jumpHandlerJumpBufferField == null) { return; } object value = _jumpHandlerJumpBufferField.GetValue(__instance); if (!(value is float)) { return; } float num = (float)value; if (num <= 0f) { return; } BatteryModule component = ((Component)__instance).gameObject.GetComponent<BatteryModule>(); if (!((Object)(object)component == (Object)null)) { (bool, bool?, float, float) tuple = DHHBatteryHelper.EvaluateJumpAllowance(); if (!tuple.Item1) { _jumpHandlerJumpBufferField.SetValue(__instance, 0f); component.NotifyJumpBlocked(tuple.Item4, tuple.Item3, tuple.Item2); } } } private static void PatchChargeHandlerDamageModeIfPossible(Harmony harmony, Assembly asm) { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.ChargeHandler", throwOnError: false); if (!(type == null)) { MethodInfo methodInfo = AccessTools.Method(type, "ChargeWindup", new Type[1] { typeof(Vector3) }, (Type[])null); MethodInfo method = typeof(Plugin).GetMethod("ChargeHandler_ChargeWindup_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo != null && method != null) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo2 = AccessTools.Method(type, "ResetState", Type.EmptyTypes, (Type[])null); if (s_chargeHandlerChargeStrengthField == null) { s_chargeHandlerChargeStrengthField = AccessTools.Field(type, "chargeStrength"); } if (s_chargeHandlerAbilityLevelGetter == null) { s_chargeHandlerAbilityLevelGetter = AccessTools.PropertyGetter(type, "AbilityLevel"); } MethodInfo method2 = typeof(Plugin).GetMethod("ChargeHandler_ResetState_Postfix", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo2 != null && method2 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void PatchJumpHandlerJumpForceIfPossible(Harmony harmony, Assembly asm) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.JumpHandler", throwOnError: false); if (type == null) { return; } MethodInfo methodInfo = AccessTools.PropertyGetter(type, "JumpForce"); if (!(methodInfo == null)) { if (s_jumpHandlerPowerLevelGetter == null) { s_jumpHandlerPowerLevelGetter = AccessTools.PropertyGetter(type, "PowerLevel"); } MethodInfo method = typeof(Plugin).GetMethod("JumpHandler_JumpForce_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static bool JumpHandler_JumpForce_Prefix(object __instance, ref float __result) { if (__instance == null || s_jumpHandlerPowerLevelGetter == null) { return true; } int num2 = ((s_jumpHandlerPowerLevelGetter.Invoke(__instance, null) is int num) ? num : 0); int num3 = num2 + 1; DiminishingReturnsResult stat = EvaluateStatWithDiminishingReturns(FeatureFlags.DHHJumpForceBaseValue, FeatureFlags.DHHJumpForceIncreasePerLevel, num3, FeatureFlags.DHHJumpForceThresholdLevel, FeatureFlags.DHHJumpForceDiminishingFactor); __result = stat.FinalValue; LogJumpForce(__instance, num2, num3, stat); return false; } private static bool ChargeHandler_ChargeWindup_Prefix(object __instance) { if (__instance == null) { return true; } if (IsChargeHandlerHeadGrabbed(__instance)) { if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:Charge.Grabbed", 30)) { Debug.Log((object)"[Fix:Charge] Charge windup blocked because the head is grabbed."); } return false; } return true; } private static bool IsChargeHandlerHeadGrabbed(object chargeHandler) { object chargeImpactDetector = GetChargeImpactDetector(chargeHandler); if (chargeImpactDetector == null) { return false; } object impactPhysGrabObject = GetImpactPhysGrabObject(chargeImpactDetector); if (impactPhysGrabObject == null) { return false; } FieldInfo fieldInfo = s_cachedPhysGrabObjectGrabbedField; if (fieldInfo == null || fieldInfo.DeclaringType != impactPhysGrabObject.GetType()) { fieldInfo = (s_cachedPhysGrabObjectGrabbedField = AccessTools.Field(impactPhysGrabObject.GetType(), "grabbed")); } bool flag = default(bool); int num; if (fieldInfo != null) { object value = fieldInfo.GetValue(impactPhysGrabObject); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static object? GetChargeImpactDetector(object chargeHandler) { FieldInfo fieldInfo = s_chargeHandlerImpactDetectorField; if (fieldInfo == null || fieldInfo.DeclaringType != chargeHandler.GetType()) { fieldInfo = (s_chargeHandlerImpactDetectorField = AccessTools.Field(chargeHandler.GetType(), "impactDetector")); } return fieldInfo?.GetValue(chargeHandler); } private static object? GetImpactPhysGrabObject(object impactDetector) { if (impactDetector == null) { return null; } FieldInfo fieldInfo = s_impactDetectorPhysGrabObjectField; if (fieldInfo == null || fieldInfo.DeclaringType != impactDetector.GetType()) { fieldInfo = (s_impactDetectorPhysGrabObjectField = AccessTools.Field(impactDetector.GetType(), "physGrabObject")); } return fieldInfo?.GetValue(impactDetector); } private static void ChargeHandler_ResetState_Postfix(object __instance) { if (__instance != null && !(s_chargeHandlerChargeStrengthField == null) && !(s_chargeHandlerAbilityLevelGetter == null)) { int currentLevel = ((s_chargeHandlerAbilityLevelGetter.Invoke(__instance, null) is int num) ? num : 0); DiminishingReturnsResult stat = EvaluateStatWithDiminishingReturns(FeatureFlags.DHHChargeStrengthBaseValue, FeatureFlags.DHHChargeStrengthIncreasePerLevel, currentLevel, FeatureFlags.DHHChargeStrengthThresholdLevel, FeatureFlags.DHHChargeStrengthDiminishingFactor); s_chargeHandlerChargeStrengthField.SetValue(__instance, stat.FinalValue); LogChargeStrength(__instance, stat); } } private static void PatchHopHandlerJumpForceIfPossible(Harmony harmony, Assembly asm) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.HopHandler", throwOnError: false); if (!(type == null)) { MethodInfo methodInfo = AccessTools.PropertyGetter(type, "JumpForce"); if (s_hopHandlerPowerLevelGetter == null) { s_hopHandlerPowerLevelGetter = AccessTools.PropertyGetter(type, "PowerLevel"); } MethodInfo method = typeof(Plugin).GetMethod("HopHandler_JumpForce_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo != null && method != null) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static bool HopHandler_JumpForce_Prefix(object __instance, ref float __result) { if (__instance == null || s_hopHandlerPowerLevelGetter == null) { return true; } int num2 = ((s_hopHandlerPowerLevelGetter.Invoke(__instance, null) is int num) ? num : 0); int num3 = num2 + 1; DiminishingReturnsResult stat = EvaluateStatWithDiminishingReturns(FeatureFlags.DHHHopJumpBaseValue, FeatureFlags.DHHHopJumpIncreasePerLevel, num3, FeatureFlags.DHHHopJumpThresholdLevel, FeatureFlags.DHHHopJumpDiminishingFactor); __result = stat.FinalValue; LogHopJumpForce(__instance, num2, num3, stat); return false; } private static float StatWithDiminishingReturns(float baseValue, float increasePerLevel, int currentLevel, int thresholdLevel, float diminishingFactor) { return EvaluateStatWithDiminishingReturns(baseValue, increasePerLevel, currentLevel, thresholdLevel, diminishingFactor).FinalValue; } private static DiminishingReturnsResult EvaluateStatWithDiminishingReturns(float baseValue, float increasePerLevel, int currentLevel, int thresholdLevel, float diminishingFactor) { int num = Math.Max(0, currentLevel - 1); int num2 = Math.Max(0, thresholdLevel - 1); int num3 = Mathf.Min(num, num2); int num4 = Mathf.Max(0, num - num2); float num5 = (float)num4 * Mathf.Pow(diminishingFactor, (float)num4); float num6 = increasePerLevel * (float)num3; float num7 = increasePerLevel * num5; float finalValue = baseValue + num6 + num7; return new DiminishingReturnsResult(baseValue, increasePerLevel, currentLevel, thresholdLevel, diminishingFactor, num3, num4, num6, num7, num5, finalValue); } private static void LogHopJumpForce(object hopHandler, int powerLevel, int appliedLevel, DiminishingReturnsResult stat) { if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:Hop.JumpForce", 30)) { string handlerLabel = GetHandlerLabel(hopHandler, "HopHandler"); string text = $"[Fix:Hop] {handlerLabel} JumpForce={stat.FinalValue:F3} powerLevel={powerLevel} appliedLevel={appliedLevel} base={stat.BaseValue:F3} inc={stat.IncreasePerLevel:F3} fullUpgrades={stat.LinearLevels} dimUpgrades={stat.ExtraLevels} linearDelta={stat.LinearContribution:F3} dimDelta={stat.DiminishingContribution:F3} thresh={stat.ThresholdLevel} dimFactor={stat.DiminishingFactor:F3}"; ManualLogSource? log = _log; if (log != null) { log.LogInfo((object)text); } Debug.Log((object)text); } } private static void LogJumpForce(object jumpHandler, int powerLevel, int appliedLevel, DiminishingReturnsResult stat) { if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:Jump.HeadJumpForce", 30)) { string handlerLabel = GetHandlerLabel(jumpHandler, "JumpHandler"); string text = $"[Fix:Jump] {handlerLabel} JumpForce={stat.FinalValue:F3} powerLevel={powerLevel} appliedLevel={appliedLevel} base={stat.BaseValue:F3} inc={stat.IncreasePerLevel:F3} fullUpgrades={stat.LinearLevels} dimUpgrades={stat.ExtraLevels} linearDelta={stat.LinearContribution:F3} dimDelta={stat.DiminishingContribution:F3} thresh={stat.ThresholdLevel} dimFactor={stat.DiminishingFactor:F3}"; ManualLogSource? log = _log; if (log != null) { log.LogInfo((object)text); } Debug.Log((object)text); } } private static string GetHandlerLabel(object? handler, string fallback) { Component val = (Component)((handler is Component) ? handler : null); if (val != null) { return ((Object)val).name ?? ((object)val).GetType().Name; } return handler?.GetType().Name ?? fallback; } private static void LogChargeStrength(object chargeHandler, DiminishingReturnsResult stat) { if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:Charge.Strength", 60)) { string handlerLabel = GetHandlerLabel(chargeHandler, "ChargeHandler"); string text = $"[Fix:Charge] {handlerLabel} Strength={stat.FinalValue:F3} base={stat.BaseValue:F3} inc={stat.IncreasePerLevel:F3} level={stat.AppliedLevel} fullUpgrades={stat.LinearLevels} dimUpgrades={stat.ExtraLevels} linearDelta={stat.LinearContribution:F3} dimDelta={stat.DiminishingContribution:F3} thresh={stat.ThresholdLevel} dimFactor={stat.DiminishingFactor:F3}"; ManualLogSource? log = _log; if (log != null) { log.LogInfo((object)text); } Debug.Log((object)text); } } private static void TryImpactEffect(object impactDetector, Vector3 contactPoint) { //IL_0072: 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) if (impactDetector == null) { return; } try { if (!SemiFunc.IsMultiplayer()) { MethodInfo methodInfo = AccessTools.Method(impactDetector.GetType(), "ImpactEffectRPC", (Type[])null, (Type[])null); if (methodInfo != null) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 2) { object obj = Activator.CreateInstance(parameters[1].ParameterType); methodInfo.Invoke(impactDetector, new object[2] { contactPoint, obj }); return; } } } object? obj2 = AccessTools.Field(impactDetector.GetType(), "photonView")?.GetValue(impactDetector); PhotonView val = (PhotonView)((obj2 is PhotonView) ? obj2 : null); if (val != null) { val.RPC("ImpactEffectRPC", (RpcTarget)0, new object[1] { contactPoint }); } } catch { } } private static Vector3 CalculateEnemyBounceNormal(Transform? self, Vector3 enemyCenterPoint) { //IL_0015: 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_0029: 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_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_0032: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_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_0049: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)self == (Object)null) { return Vector3.up; } Vector3 val = self.TransformPoint(Vector3.up * 0.3f); Vector3 val2 = val - enemyCenterPoint; Vector3 val3 = Vector3.ProjectOnPlane(val2, Vector3.up); return ((Vector3)(ref val3)).normalized; } } } namespace DeathHeadHopperFix.Modules.Utilities { internal static class ItemHelpers { internal static string? GetItemAssetName(Object? itemAsset) { if (itemAsset == (Object)null) { return null; } Type type = ((object)itemAsset).GetType(); PropertyInfo property = type.GetProperty("itemAssetName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(string)) { return ((string)property.GetValue(itemAsset, null)) ?? itemAsset.name; } FieldInfo field = type.GetField("itemAssetName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(string)) { return ((string)field.GetValue(itemAsset)) ?? itemAsset.name; } return itemAsset.name; } } internal static class LogLimiter { public const int DefaultFrameInterval = 120; private static readonly Dictionary<string, int> _lastFrameByKey = new Dictionary<string, int>(StringComparer.Ordinal); public static bool ShouldLog(string key, int frameInterval = 120) { if (string.IsNullOrEmpty(key)) { return true; } if (frameInterval <= 0) { return true; } int frameCount = Time.frameCount; if (_lastFrameByKey.TryGetValue(key, out var value) && frameCount - value < frameInterval) { return false; } _lastFrameByKey[key] = frameCount; return true; } public static void Reset(string key) { if (!string.IsNullOrEmpty(key)) { _lastFrameByKey.Remove(key); } } public static void Clear() { _lastFrameByKey.Clear(); } } internal static class ReflectionHelper { internal static object? GetStaticInstanceByName(string typeName) { Type type = AccessTools.TypeByName(typeName); if (type == null) { return null; } return GetStaticInstanceValue(type, "instance"); } internal static object? GetStaticInstanceValue(Type type, string name) { FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field.GetValue(null); } PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property.GetValue(null, null); } return null; } } } namespace DeathHeadHopperFix.Modules.Patches { [HarmonyPatch(typeof(PlayerDeathHead), "Update")] internal static class PlayerDeathHeadUpdatePatch { private static readonly FieldInfo s_triggeredField = AccessTools.Field(typeof(PlayerDeathHead), "triggered"); private static readonly FieldInfo s_spectatePlayerField = AccessTools.Field(typeof(SpectateCamera), "player"); private static float _jumpTimer = 1f; [HarmonyPrefix] private static void Prefix(PlayerDeathHead __instance, PhysGrabObject ___physGrabObject) { //IL_00a2: 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_0173: 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_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: 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_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0188: 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_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: 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_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: 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_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: 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_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021a: 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_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0203: 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) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)___physGrabObject == (Object)null) { return; } PlayerAvatar playerAvatar = __instance.playerAvatar; if ((Object)(object)playerAvatar == (Object)null || (Object)(object)playerAvatar.photonView == (Object)null || !playerAvatar.photonView.IsMine || s_triggeredField == null) { return; } object value = s_triggeredField.GetValue(__instance); if (!(value is bool) || !(bool)value) { return; } ((Component)playerAvatar).transform.position = ((Component)___physGrabObject).transform.position; if ((SemiFunc.InputMovementX() != 0f || SemiFunc.InputMovementY() != 0f) && s_spectatePlayerField != null && (Object)(object)SpectateCamera.instance != (Object)null) { s_spectatePlayerField.SetValue(SpectateCamera.instance, playerAvatar); } if (_jumpTimer > 0f) { _jumpTimer -= Time.deltaTime; } else { if (!SemiFunc.InputHold((InputKey)1)) { return; } _jumpTimer = 1f; Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return; } Vector3 val = Vector3.ProjectOnPlane(((Component)main).transform.forward, Vector3.up); Vector3 normalized = ((Vector3)(ref val)).normalized; Vector3 val2 = Vector3.Cross(Vector3.up, normalized); Vector3 val3 = Vector3.zero; float num = SemiFunc.InputMovementX(); float num2 = SemiFunc.InputMovementY(); if (num2 > 0f) { val3 += normalized; } if (num2 < 0f) { val3 -= normalized; } if (num < 0f) { val3 -= val2; } if (num > 0f) { val3 += val2; } val3 += Vector3.up; val3 = ((Vector3)(ref val3)).normalized * 4.8f; if (DHHBatteryHelper.EvaluateJumpAllowance().allowed) { PhysGrabber physGrabber = playerAvatar.physGrabber; if (!((Object)(object)physGrabber == (Object)null) && !((Object)(object)playerAvatar.photonView == (Object)null)) { ___physGrabObject.GrabLink(playerAvatar.photonView.ViewID, 0, physGrabber.physGrabPointPullerPosition - val3, Vector3.zero, Vector3.zero); ___physGrabObject.GrabStarted(physGrabber); ___physGrabObject.GrabEnded(physGrabber); } } } } } internal static class SpectateCameraStateNormalPatch { private static readonly MethodInfo s_inputDown = AccessTools.Method(typeof(SemiFunc), "InputDown", (Type[])null, (Type[])null); private static readonly MethodInfo s_playerSwitch = AccessTools.Method(typeof(SpectateCamera), "PlayerSwitch", (Type[])null, (Type[])null); internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = instructions.ToList(); int num = list.FindIndex((CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_inputDown)) - 1; if (num <= 0 || list[num].opcode != OpCodes.Ldc_I4_1) { return instructions; } int num2 = list.FindIndex(num, (CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, s_playerSwitch)); if (num2 == -1) { return instructions; } list[num].opcode = OpCodes.Nop; list.RemoveRange(num + 1, num2 - num); return list.AsEnumerable(); } } [HarmonyPatch(typeof(StunHandler), "HandleStun")] internal static class StunHandlerReleasePatch { [CompilerGenerated] private sealed class <Transpiler>d__2 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private IEnumerator<CodeInstruction> <>s__1; private CodeInstruction <instruction>5__2; private MethodInfo <target>5__3; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpiler>d__2(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>s__1 = null; <instruction>5__2 = null; <target>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>s__1 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; case 2: <>1__state = -3; <target>5__3 = null; <instruction>5__2 = null; break; } if (<>s__1.MoveNext()) { <instruction>5__2 = <>s__1.Current; if (<instruction>5__2.opcode == OpCodes.Call || <instruction>5__2.opcode == OpCodes.Callvirt) { object operand = <instruction>5__2.operand; <target>5__3 = operand as MethodInfo; if ((object)<target>5__3 != null && IsPhysObjectHurtCall(<target>5__3)) { <>2__current = new CodeInstruction(OpCodes.Call, (object)Replacement); <>1__state = 1; return true; } } <>2__current = <instruction>5__2; <>1__state = 2; return true; } <>m__Finally1(); <>s__1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>s__1 != null) { <>s__1.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <Transpiler>d__2 <Transpiler>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpiler>d__ = this; } else { <Transpiler>d__ = new <Transpiler>d__2(0); } <Transpiler>d__.instructions = <>3__instructions; return <Transpiler>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } private const int ReleaseObjectViewId = -1; private static readonly MethodInfo Replacement = AccessTools.Method(typeof(StunHandlerReleasePatch), "CustomPhysObjectHurt", (Type[])null, (Type[])null); [IteratorStateMachine(typeof(<Transpiler>d__2))] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Transpiler>d__2(-2) { <>3__instructions = instructions }; } private static bool IsPhysObjectHurtCall(MethodInfo target) { if (target == null || target.Name != "PhysObjectHurt") { return false; } ParameterInfo[] parameters = target.GetParameters(); if (parameters.Length != 3) { return false; } return parameters[0].ParameterType == typeof(PhysGrabObject) && parameters[1].ParameterType == typeof(BreakImpact) && parameters[2].ParameterType == typeof(float); } public static void CustomPhysObjectHurt(StunHandler self, PhysGrabObject physGrabObject, BreakImpact impact, float hitForce) { //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_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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected I4, but got Unknown if ((Object)(object)physGrabObject == (Object)null) { return; } switch (impact - 1) { case 0: physGrabObject.lightBreakImpulse = true; break; case 1: physGrabObject.mediumBreakImpulse = true; break; case 2: physGrabObject.heavyBreakImpulse = true; break; } if (!(hitForce >= 5f) || physGrabObject.playerGrabbing.Count <= 0) { return; } foreach (PhysGrabber item in physGrabObject.playerGrabbing.ToList()) { if (!((Object)(object)item == (Object)null)) { if (!SemiFunc.IsMultiplayer()) { item.ReleaseObjectRPC(true, 2f, -1); continue; } item.photonView.RPC("ReleaseObjectRPC", (RpcTarget)0, new object[3] { false, 1f, -1 }); } } } } } namespace DeathHeadHopperFix.Modules.Gameplay { internal static class AbilityModule { private static class AbilitySpotLabelOverlay { private static readonly Dictionary<object, Component> Labels = new Dictionary<object, Component>(); private static readonly Type? LabelType = AccessTools.TypeByName("TMPro.TextMeshProUGUI"); private static readonly Type? AlignmentType = AccessTools.TypeByName("TMPro.TextAlignmentOptions"); private static readonly PropertyInfo? TextProperty = LabelType?.GetProperty("text"); private static readonly PropertyInfo? ColorProperty = LabelType?.GetProperty("color"); private static readonly PropertyInfo? AlignmentProperty = LabelType?.GetProperty("alignment"); private static readonly PropertyInfo? FontSizeProperty = LabelType?.GetProperty("fontSize"); private static readonly PropertyInfo? AutoSizeProperty = LabelType?.GetProperty("enableAutoSizing"); private static readonly PropertyInfo? WordWrapProperty = LabelType?.GetProperty("enableWordWrapping"); private static readonly PropertyInfo? RichTextProperty = LabelType?.GetProperty("richText"); private static readonly object? CenterAlignment = ((AlignmentType != null) ? Enum.Parse(AlignmentType, "Center") : null); private static Type? SpotType; private static FieldInfo? SpotIndexField; internal static void EnsureLabel(object spot) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0085: 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_009d: 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_00b5: Unknown result type (might be due to invalid IL or missing references) if (spot != null && !(LabelType == null) && !Labels.ContainsKey(spot)) { Component val = (Component)((spot is Component) ? spot : null); if (val != null) { GameObject val2 = new GameObject("DHHAbilityLabel", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(val.transform, false); RectTransform component = val2.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; ((Transform)component).localScale = Vector3.one; ((Transform)component).SetAsLastSibling(); Component val3 = val2.AddComponent(LabelType); SetLabelDefaults(val3); Labels[spot] = val3; UpdateLabel(spot); } } } internal static void UpdateLabel(object spot) { if (spot != null) { Component label = GetLabel(spot); if (!((Object)(object)label == (Object)null)) { string slotTag = GetSlotTag(spot); SetLabelText(label, slotTag); } } } internal static void ClearLabel(object spot) { if (spot == null || !Labels.TryGetValue(spot, out Component value)) { return; } Labels.Remove(spot); if (value != null) { Component val = value; if (true) { Object.Destroy((Object)(object)val.gameObject); } } } private static Component? GetLabel(object spot) { Component value; return Labels.TryGetValue(spot, out value) ? value : null; } private static string GetSlotTag(object spot) { int abilityIndex = GetAbilityIndex(spot); if (1 == 0) { } string empty = string.Empty; if (1 == 0) { } return empty; } private static int GetAbilityIndex(object spot) { if (spot == null) { return -1; } Type type = spot.GetType(); if (SpotType == null || SpotType != type) { SpotType = type; SpotIndexField = type.GetField("abilitySpotIndex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (SpotIndexField == null) { return -1; } return (SpotIndexField.GetValue(spot) is int num) ? num : (-1); } private static void SetLabelDefaults(Component label) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)label == (Object)null)) { if (ColorProperty != null) { ColorProperty.SetValue(label, Color.white); } if (FontSizeProperty != null) { FontSizeProperty.SetValue(label, 10f); } if (AutoSizeProperty != null) { AutoSizeProperty.SetValue(label, false); } if (WordWrapProperty != null) { WordWrapProperty.SetValue(label, false); } if (RichTextProperty != null) { RichTextProperty.SetValue(label, false); } if (AlignmentProperty != null && CenterAlignment != null) { AlignmentProperty.SetValue(label, CenterAlignment); } SetLabelText(label, string.Empty); } } private static void SetLabelText(Component label, string text) { if (!((Object)(object)label == (Object)null)) { if (TextProperty != null) { TextProperty.SetValue(label, text); } Behaviour val = (Behaviour)(object)((label is Behaviour) ? label : null); if (val != null) { val.enabled = !string.IsNullOrEmpty(text); } } } } private static Type? s_abilityBaseType; private static MethodInfo? s_abilityCooldownGetter; private static MethodInfo? s_abilityEnergyCostGetter; private static MethodInfo? s_abilityNameGetter; private static Type? s_abilitySpotType; private static MethodInfo? s_abilitySpotSetCooldown; private static FieldInfo? s_abilitySpotsField; internal static void ApplyAbilitySpotLabelOverlay(Harmony harmony, Assembly asm) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.UI.AbilitySpot", throwOnError: false); if (!(type == null)) { MethodInfo methodInfo = AccessTools.Method(type, "Start", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(type, "UpdateUI", (Type[])null, (Type[])null); MethodInfo method = type.GetMethod("OnDestroy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo method2 = typeof(AbilityModule).GetMethod("AbilitySpot_Start_Postfix", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method3 = typeof(AbilityModule).GetMethod("AbilitySpot_UpdateUI_Postfix", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method4 = typeof(AbilityModule).GetMethod("AbilitySpot_OnDestroy_Postfix", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo != null && method2 != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodInfo2 != null && method3 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (method != null && method4 != null) { harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } internal static void ApplyAbilityManagerHooks(Harmony harmony, Assembly asm) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.Managers.DHHAbilityManager", throwOnError: false); if (type == null) { return; } EnsureAbilityReflection(); if (s_abilityBaseType == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "OnAbilityUsed", new Type[1] { s_abilityBaseType }, (Type[])null); if (!(methodInfo == null)) { MethodInfo method = typeof(AbilityModule).GetMethod("DHHAbilityManager_OnAbilityUsed_Postfix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void AbilitySpot_Start_Postfix(object? __instance) { if (__instance != null) { AbilitySpotLabelOverlay.EnsureLabel(__instance); } } private static void AbilitySpot_UpdateUI_Postfix(object? __instance) { if (__instance != null) { AbilitySpotLabelOverlay.UpdateLabel(__instance); } } private static void AbilitySpot_OnDestroy_Postfix(object? __instance) { if (__instance != null) { AbilitySpotLabelOverlay.ClearLabel(__instance); } } private static void EnsureAbilityReflection() { if (s_abilityBaseType == null) { s_abilityBaseType = AccessTools.TypeByName("DeathHeadHopper.Abilities.AbilityBase"); } if (s_abilityCooldownGetter == null && s_abilityBaseType != null) { s_abilityCooldownGetter = AccessTools.PropertyGetter(s_abilityBaseType, "Cooldown"); } if (s_abilityEnergyCostGetter == null && s_abilityBaseType != null) { s_abilityEnergyCostGetter = AccessTools.PropertyGetter(s_abilityBaseType, "EnergyCost"); } if (s_abilityNameGetter == null && s_abilityBaseType != null) { s_abilityNameGetter = AccessTools.PropertyGetter(s_abilityBaseType, "AbilityName"); } if (s_abilitySpotType == null) { s_abilitySpotType = AccessTools.TypeByName("DeathHeadHopper.UI.AbilitySpot"); } if (s_abilitySpotSetCooldown == null && s_abilitySpotType != null) { s_abilitySpotSetCooldown = AccessTools.Method(s_abilitySpotType, "SetCooldown", new Type[1] { typeof(float) }, (Type[])null); } } private static void DHHAbilityManager_OnAbilityUsed_Postfix(object __instance, object ability) { if (ability == null) { return; } EnsureAbilityReflection(); if (s_abilityCooldownGetter == null || s_abilitySpotSetCooldown == null) { return; } float num2 = ((s_abilityCooldownGetter.Invoke(ability, null) is float num) ? num : 0f); if (num2 <= 0f) { return; } FieldInfo fieldInfo = s_abilitySpotsField ?? (s_abilitySpotsField = __instance?.GetType().GetField("abilitySpots", BindingFlags.Instance | BindingFlags.NonPublic)); if (fieldInfo == null || !(fieldInfo.GetValue(__instance) is Array array)) { return; } foreach (object item in array) { if (item != null) { try { s_abilitySpotSetCooldown?.Invoke(item, new object[1] { num2 }); } catch { } } } } } internal static class AudioModule { [CompilerGenerated] private sealed class <AudioHandler_InitWhenReady>d__4 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public MonoBehaviour handler; private int <frames>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AudioHandler_InitWhenReady>d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <frames>5__1 = 0; break; case 1: <>1__state = -1; break; } if (<frames>5__1++ < 600) { if ((Object)(object)handler == (Object)null) { return false; } if (TryInitAudioHandlerSafe(handler)) { return false; } <>2__current = null; <>1__state = 1; return true; } ManualLogSource? log = _log; if (log != null) { log.LogWarning((object)"[Fix] AudioHandler init timed out; audio may be partially disabled."); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static readonly HashSet<int> AudioInitDone = new HashSet<int>(); private static ManualLogSource? _log; internal static void Apply(Harmony harmony, Assembly asm, ManualLogSource? log) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown _log = log; if (harmony == null || asm == null) { return; } Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.AudioHandler", throwOnError: false); if (type == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "Awake", Type.EmptyTypes, (Type[])null); if (!(methodInfo == null)) { MethodInfo method = typeof(AudioModule).GetMethod("AudioHandler_Awake_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static bool AudioHandler_Awake_Prefix(MonoBehaviour __instance) { try { int instanceID = ((Object)__instance).GetInstanceID(); if (AudioInitDone.Contains(instanceID)) { return false; } __instance.StartCoroutine(AudioHandler_InitWhenReady(__instance)); } catch (Exception ex) { ManualLogSource? log = _log; if (log != null) { log.LogError((object)ex); } } return false; } [IteratorStateMachine(typeof(<AudioHandler_InitWhenReady>d__4))] private static IEnumerator AudioHandler_InitWhenReady(MonoBehaviour handler) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AudioHandler_InitWhenReady>d__4(0) { handler = handler }; } private static bool TryInitAudioHandlerSafe(MonoBehaviour handler) { int instanceID = ((Object)handler).GetInstanceID(); if (AudioInitDone.Contains(instanceID)) { return true; } Type type = ((object)handler).GetType(); FieldInfo fieldInfo = AccessTools.Field(type, "controller"); object obj = fieldInfo?.GetValue(handler); if (obj == null) { Type type2 = type.Assembly.GetType("DeathHeadHopper.DeathHead.DeathHeadController", throwOnError: false); obj = ((type2 != null) ? ((Component)handler).GetComponent(type2) : null); if (obj == null) { return false; } fieldInfo?.SetValue(handler, obj); } object obj2 = ((obj == null) ? null : AccessTools.Field(obj.GetType(), "deathHead")?.GetValue(obj)); object obj3 = ((obj2 == null) ? null : AccessTools.Field(obj2.GetType(), "playerAvatar")?.GetValue(obj2)); object obj4 = TryGetAudioPreset(handler); if (obj4 == null && obj3 == null && obj2 == null) { return false; } if (!TryEnsureSound(handler, type, obj4, obj2, obj3)) { return false; } AudioInitDone.Add(instanceID); if (FeatureFlags.DebugLogging) { ManualLogSource? log = _log; if (log != null) { log.LogInfo((object)"[Fix] AudioHandler initialized safely (deferred)."); } } return true; } private static object? TryGetAudioPreset(MonoBehaviour handler) { try { Type type = AccessTools.TypeByName("NotValuableObject"); Component val = ((type != null) ? ((Component)handler).gameObject.GetComponent(type) : null); return (!((Object)(object)val != (Object)null)) ? null : AccessTools.Field(((object)val).GetType(), "audioPreset")?.GetValue(val); } catch { return null; } } private static bool TryEnsureSound(MonoBehaviour handler, Type t, object? audioPreset, object? deathHead, object? playerAvatar) { Type t2 = t; MonoBehaviour handler2 = handler; Type type = AccessTools.TypeByName("Sound"); if (type == null) { return false; } try { if (AccessTools.Field(t2, "jumpSound")?.GetValue(handler2) == null && audioPreset != null) { object soundLike2 = AccessTools.Field(audioPreset.GetType(), "impactMedium")?.GetValue(audioPreset); AudioClip[] clips2 = CloneClipsFromSoundLike(soundLike2); object obj = CreateSound(type, clips2, null, 0.12f, 0f, 0.8f, 0f); if (obj != null) { AccessTools.Field(t2, "jumpSound")?.SetValue(handler2, obj); } } } catch { } try { if (AccessTools.Field(t2, "anchorBreakSound")?.GetValue(handler2) == null && playerAvatar != null) { object soundLike3 = AccessTools.Field(playerAvatar.GetType(), "tumbleBreakFreeSound")?.GetValue(playerAvatar); AudioClip[] clips3 = CloneClipsFromSoundLike(soundLike3); object obj3 = CreateSound(type, clips3, CreateSrc(), 0.1f, 0f, 1f, 0f); if (obj3 != null) { AccessTools.Field(t2, "anchorBreakSound")?.SetValue(handler2, obj3); } } } catch { } try { if (AccessTools.Field(t2, "anchorAttachSound")?.GetValue(handler2) == null && deathHead != null) { object soundLike4 = AccessTools.Field(deathHead.GetType(), "eyeFlashNegativeSound")?.GetValue(deathHead); AudioClip[] clips4 = CloneClipsFromSoundLike(soundLike4); object obj5 = CreateSound(type, clips4, CreateSrc(), 0.5f, 0f, 0.3f, 0.03f); if (obj5 != null) { AccessTools.Field(t2, "anchorAttachSound")?.SetValue(handler2, obj5); } } } catch { } try { if (AccessTools.Field(t2, "windupSound")?.GetValue(handler2) == null) { Type type2 = AccessTools.TypeByName("PlayerAvatar"); object obj7 = null; if (type2 != null) { obj7 = ReflectionHelper.GetStaticInstanceValue(type2, "instance"); } object obj8 = ((obj7 == null) ? null : AccessTools.Field(obj7.GetType(), "tumble")?.GetValue(obj7)); object soundLike5 = ((obj8 == null) ? null : AccessTools.Field(obj8.GetType(), "tumbleMoveSound")?.GetValue(obj8)); AudioClip[] clips5 = CloneClipsFromSoundLike(soundLike5); object obj9 = CreateSound(type, clips5, CreateSrc(), 0.4f, 0.02f, 0.8f, 0f); if (obj9 != null) { AccessTools.Field(t2, "windupSound")?.SetValue(handler2, obj9); } } } catch { } try { if (AccessTools.Field(t2, "rechargeSound")?.GetValue(handler2) == null) { Type type3 = AccessTools.TypeByName("AssetManager"); object obj11 = null; if (type3 != null) { obj11 = ReflectionHelper.GetStaticInstanceValue(type3, "instance"); } object soundLike6 = ((obj11 == null) ? null : AccessTools.Field(obj11.GetType(), "batteryChargeSound")?.GetValue(obj11)); AudioClip[] clips6 = CloneClipsFromSoundLike(soundLike6); object obj12 = CreateSound(type, clips6, CreateSrc(), 0.2f, 0.01f, 1f, 0.02f); if (obj12 != null) { AccessTools.Field(t2, "rechargeSound")?.SetValue(handler2, obj12); } } } catch { } try { if (AccessTools.Field(t2, "unAnchoringSound")?.GetValue(handler2) == null) { Type type4 = AccessTools.TypeByName("MaterialPreset"); if (type4 != null) { Object[] array = Resources.FindObjectsOfTypeAll(type4); object obj14 = null; FieldInfo fieldInfo = AccessTools.Field(type4, "Type"); Object[] array2 = array; foreach (Object val in array2) { if (!(val == (Object)null) && fieldInfo?.GetValue(val) is int num && num == 2) { obj14 = val; break; } } if (obj14 != null) { object soundLike7 = AccessTools.Field(type4, "SlideOneShot")?.GetValue(obj14); AudioClip[] clips7 = CloneClipsFromSoundLike(soundLike7); object obj15 = CreateSound(type, clips7, CreateSrc(), 1f, 0f, 0.6f, 0f); if (obj15 != null) { AccessTools.Field(t2, "unAnchoringSound")?.SetValue(handler2, obj15); } } } } } catch { } return true; static AudioClip[]? CloneClipsFromSoundLike(object? soundLike) { if (soundLike == null) { return null; } object obj19 = AccessTools.Field(soundLike.GetType(), "Sounds")?.GetValue(soundLike); if (!(obj19 is AudioClip[] array3) || array3.Length == 0) { return null; } return array3.Clone() as AudioClip[]; } static object? CreateSound(Type tSound, AudioClip[]? clips, AudioSource? src, float vol, float volRand, float pitch, float pitchRand) { if (clips == null || clips.Length == 0) { return null; } object obj18 = Activator.CreateInstance(tSound); if (obj18 == null) { return null; } if ((Object)(object)src != (Object)null) { AccessTools.Field(tSound, "Source")?.SetValue(obj18, src); } AccessTools.Field(tSound, "Sounds")?.SetValue(obj18, clips); AccessTools.Field(tSound, "Volume")?.SetValue(obj18, vol); AccessTools.Field(tSound, "VolumeRandom")?.SetValue(obj18, volRand); AccessTools.Field(tSound, "Pitch")?.SetValue(obj18, pitch); AccessTools.Field(tSound, "PitchRandom")?.SetValue(obj18, pitchRand); return obj18; } AudioSource CreateSrc() { MethodInfo methodInfo = AccessTools.Method(t2, "CreateAudioSource", (Type[])null, (Type[])null); if (methodInfo == null) { throw new NullReferenceException("CreateAudioSource() not found."); } object obj17 = methodInfo.Invoke(handler2, Array.Empty<object>()); AudioSource val2 = (AudioSource)((obj17 is AudioSource) ? obj17 : null); if (val2 == null) { throw new NullReferenceException("CreateAudioSource() returned invalid type."); } return val2; } } } internal static class DHHShopModule { private static bool _hooksApplied; private static ManualLogSource? _log; private static FieldInfo? _itemVolumesField; private static FieldInfo? _potentialItemsField; private static MethodInfo? _spawnShopItemMethod; internal static void Apply(Harmony harmony, Assembly asm, ManualLogSource? log) { //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown _log = log; if (harmony == null || _hooksApplied) { return; } Type type = asm.GetType("DeathHeadHopper.Managers.DHHShopManager", throwOnError: false); if (type == null) { return; } if ((object)_itemVolumesField == null) { _itemVolumesField = AccessTools.Field(type, "itemVolumes"); } if ((object)_potentialItemsField == null) { _potentialItemsField = AccessTools.Field(type, "potentialItems"); } if ((object)_spawnShopItemMethod == null) { _spawnShopItemMethod = AccessTools.Method(typeof(PunManager), "SpawnShopItem", new Type[4] { typeof(ItemVolume), typeof(List<Item>), typeof(int).MakeByRefType(), typeof(bool) }, (Type[])null); } MethodInfo methodInfo = AccessTools.Method(type, "ShopPopulateItemVolumes", new Type[1] { typeof(PunManager) }, (Type[])null); if (methodInfo != null) { MethodInfo method = typeof(DHHShopModule).GetMethod("ShopPopulateItemVolumes_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (method != null) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } _hooksApplied = true; } private static bool ShopPopulateItemVolumes_Prefix(object punManager) { if (SemiFunc.IsNotMasterClient()) { return false; } IList<ItemVolume> list = _itemVolumesField?.GetValue(null) as IList<ItemVolume>; List<Item> list2 = _potentialItemsField?.GetValue(null) as List<Item>; if (list == null || list2 == null) { return true; } if (_spawnShopItemMethod == null) { return true; } int num = 0; int num2 = ((FeatureFlags.DHHShopMaxItems < 0) ? int.MaxValue : FeatureFlags.DHHShopMaxItems); float num3 = Mathf.Clamp01(FeatureFlags.DHHShopSpawnChance); float num4 = Mathf.Clamp01(FeatureFlags.ShopItemsSpawnChance); if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:DHHShop.Populate", 30)) { ManualLogSource? log = _log; if (log != null) { log.LogInfo((object)$"[Fix:DHHShop] Populate volumes={list.Count} items={list2.Count} limit={num2} slotChance={num3:F3} itemChance={num4:F3}"); } } foreach (ItemVolume item in list) { if ((Object)(object)item == (Object)null) { continue; } if (num >= num2) { break; } float num5 = 1f; if (num3 < 1f) { num5 = Random.value; if (num5 > num3) { if (FeatureFlags.DebugLogging) { ManualLogSource? log2 = _log; if (log2 != null) { log2.LogInfo((object)$"[Fix:DHHShop] Slot skip '{((Object)item).name}' slotRoll={num5:F3} slotChance={num3:F3} spawned={num}"); } } continue; } } float num6 = 1f; if (num4 < 1f) { num6 = Random.value; if (num6 > num4) { if (FeatureFlags.DebugLogging) { ManualLogSource? log3 = _log; if (log3 != null) { log3.LogInfo((object)$"[Fix:DHHShop] Item skip '{((Object)item).name}' itemRoll={num6:F3} itemChance={num4:F3} spawned={num}"); } } continue; } } if (FeatureFlags.DebugLogging) { ManualLogSource? log4 = _log; if (log4 != null) { log4.LogInfo((object)$"[Fix:DHHShop] Spawn '{((Object)item).name}' slotRoll={num5:F3} itemRoll={num6:F3} slotChance={num3:F3} itemChance={num4:F3} spawned={num}"); } } object[] array = new object[4] { item, list2, num, false }; object obj = _spawnShopItemMethod.Invoke(punManager, array); num = (int)array[2]; if (num2 == int.MaxValue || num < num2) { continue; } break; } return false; } } internal static class InputModule { [CompilerGenerated] private sealed class <DHHInputManager_WaitForHostVersion>d__5 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; private Type <tPun>5__1; private FieldInfo <fHost>5__2; private int <i>5__3; private string <host>5__4; private string <host>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DHHInputManager_WaitForHostVersion>d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <tPun>5__1 = null; <fHost>5__2 = null; <host>5__4 = null; <host>5__5 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <tPun>5__1 = AccessTools.TypeByName("DeathHeadHopper.Managers.DHHPunManager"); <fHost>5__2 = <tPun>5__1?.GetField("hostVersion", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); <i>5__3 = 0; break; case 1: <>1__state = -1; <host>5__4 = null; <i>5__3++; break; } if (<i>5__3 < 300) { <host>5__4 = <fHost>5__2?.GetValue(null) as string; if (!string.IsNullOrWhiteSpace(<host>5__4) && !string.Equals(<host>5__4, "pending", StringComparison.OrdinalIgnoreCase)) { return false; } <>2__current = null; <>1__state = 1; return true; } if (<fHost>5__2 != null) { <host>5__5 = <fHost>5__2.GetValue(null) as string; if (string.Equals(<host>5__5, "pending", StringComparison.OrdinalIgnoreCase)) { <fHost>5__2.SetValue(null, string.Empty); ManualLogSource? log = _log; if (log != null) { log.LogWarning((object)"Host does not have DeathHeadHopper installed!"); } } <host>5__5 = null; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static ManualLogSource? _log; internal static void Apply(Harmony harmony, Assembly asm, ManualLogSource? log) { _log = log; PatchDhhInputManagerAwakeIfPossible(harmony, asm); PatchDhhPunManagerAwakeIfPossible(harmony, asm); } private static void PatchDhhInputManagerAwakeIfPossible(Harmony harmony, Assembly asm) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown if (harmony == null || asm == null) { return; } Type type = asm.GetType("DeathHeadHopper.Managers.DHHInputManager", throwOnError: false); if (type == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null); if (!(methodInfo == null)) { MethodInfo method = typeof(InputModule).GetMethod("DHHInputManager_Awake_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void PatchDhhPunManagerAwakeIfPossible(Harmony harmony, Assembly asm) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown if (harmony == null || asm == null) { return; } Type type = asm.GetType("DeathHeadHopper.Managers.DHHPunManager", throwOnError: false); if (type == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "Awake", (Type[])null, (Type[])null); if (!(methodInfo == null)) { MethodInfo method = typeof(InputModule).GetMethod("DHHPunManager_Awake_Postfix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void DHHInputManager_Awake_Prefix(MonoBehaviour __instance) { try { Type type = AccessTools.TypeByName("DeathHeadHopper.Managers.DHHPunManager"); if (type == null) { return; } FieldInfo field = type.GetField("hostVersion", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field2 = type.GetField("localVersion", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { return; } string value = field.GetValue(null) as string; if (!string.IsNullOrWhiteSpace(value)) { return; } if (IsMasterClientOrSingleplayer()) { string value2 = field2?.GetValue(null) as string; if (string.IsNullOrWhiteSpace(value2)) { value2 = GetDeathHeadHopperVersionString(); } if (!string.IsNullOrWhiteSpace(value2)) { field.SetValue(null, value2); } } else { field.SetValue(null, "pending"); object staticInstanceByName = ReflectionHelper.GetStaticInstanceByName("DeathHeadHopper.Managers.DHHPunManager"); (staticInstanceByName?.GetType().GetMethod("VersionCheck", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.Invoke(staticInstanceByName, Array.Empty<object>()); __instance.StartCoroutine(DHHInputManager_WaitForHostVersion()); } } catch { } } [IteratorStateMachine(typeof(<DHHInputManager_WaitForHostVersion>d__5))] private static IEnumerator DHHInputManager_WaitForHostVersion() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DHHInputManager_WaitForHostVersion>d__5(0); } private static bool IsMasterClientOrSingleplayer() { try { MethodInfo methodInfo = AccessTools.TypeByName("SemiFunc")?.GetMethod("IsMasterClientOrSingleplayer", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (methodInfo != null) { object obj = methodInfo.Invoke(null, Array.Empty<object>()); if (obj is bool) { bool result = (bool)obj; if (true) { return result; } } } } catch { } return false; } private static string? GetDeathHeadHopperVersionString() { try { return ((AccessTools.TypeByName("DeathHeadHopper.DeathHeadHopper")?.GetProperty("Version", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null))?.ToString(); } catch { } return null; } private static void DHHPunManager_Awake_Postfix(MonoBehaviour __instance) { try { Object.DontDestroyOnLoad((Object)(object)((Component)__instance).gameObject); Type type = ((object)__instance).GetType(); AccessTools.Method(type, "EnsurePhotonView", (Type[])null, (Type[])null)?.Invoke(__instance, Array.Empty<object>()); object? obj = AccessTools.Field(type, "photonView")?.GetValue(__instance); PhotonView val = (PhotonView)((obj is PhotonView) ? obj : null); if (val != null && val.ViewID == 0) { val.ViewID = 745; } } catch { } } } internal static class ItemUpgradeModule { private const string DhhUpgradePowerTypeName = "DeathHeadHopper.Items.DHHItemUpgradePower"; private const string DhhUpgradeChargeTypeName = "DeathHeadHopper.Items.DHHItemUpgradeCharge"; private static Type? _dhhUpgradePowerType; private static Type? _dhhUpgradeChargeType; private static MethodInfo? _dhhUpgradePowerMethod; private static MethodInfo? _dhhUpgradeChargeMethod; internal static void Apply(Harmony harmony) { PatchItemToggleUpgradeHook(harmony); } private static void PatchItemToggleUpgradeHook(Harmony harmony) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown if (harmony == null) { return; } Type type = AccessTools.TypeByName("ItemToggle"); if (type == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "ToggleItemLogic", new Type[2] { typeof(bool), typeof(int) }, (Type[])null); if (!(methodInfo == null)) { MethodInfo method = typeof(ItemUpgradeModule).GetMethod("ItemToggle_ToggleItemLogic_Postfix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void ItemToggle_ToggleItemLogic_Postfix(ItemToggle __instance, bool toggle, int player) { if (toggle && !((Object)(object)__instance == (Object)null)) { bool flag = TryInvokeUpgrade(__instance, ref _dhhUpgradePowerType, ref _dhhUpgradePowerMethod, "DeathHeadHopper.Items.DHHItemUpgradePower"); bool flag2 = TryInvokeUpgrade(__instance, ref _dhhUpgradeChargeType, ref _dhhUpgradeChargeMethod, "DeathHeadHopper.Items.DHHItemUpgradeCharge"); if (flag || flag2) { PlayUpgradeFx(__instance, player); DestroyUpgradeItem(__instance); RegisterConsumedUpgrade(__instance); } } } private static bool TryInvokeUpgrade(ItemToggle toggle, ref Type? upgradeType, ref MethodInfo? upgradeMethod, string typeName) { Type type = upgradeType ?? (upgradeType = AccessTools.TypeByName(typeName)); if (type == null) { return false; } Component component = ((Component)toggle).GetComponent(type); if ((Object)(object)component == (Object)null) { return false; } MethodInfo methodInfo = upgradeMethod ?? (upgradeMethod = AccessTools.Method(type, "Upgrade", (Type[])null, (Type[])null)); if (methodInfo == null) { return false; } methodInfo.Invoke(component, Array.Empty<object>()); return true; } private static void DestroyUpgradeItem(ItemToggle toggle) { if (!((Object)(object)toggle == (Object)null)) { PhysGrabObjectImpactDetector val = ((Component)toggle).GetComponent<PhysGrabObjectImpactDetector>() ?? ((Component)toggle).GetComponentInChildren<PhysGrabObjectImpactDetector>(); if ((Object)(object)val == (Object)null) { val = ((Component)toggle).GetComponentInParent<PhysGrabObjectImpactDetector>(); } if (val != null) { val.DestroyObject(false); } } } private static void PlayUpgradeFx(ItemToggle toggle, int player) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) try { PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(player); if ((Object)(object)val == (Object)null) { return; } PhotonView photonView = val.photonView; if (!GameManager.Multiplayer() || ((Object)(object)photonView != (Object)null && photonView.IsMine)) { StatsUI instance = StatsUI.instance; if (instance != null) { instance.Fetch(); } StatsUI instance2 = StatsUI.instance; if (instance2 != null) { instance2.ShowStats(); } CameraGlitch instance3 = CameraGlitch.Instance; if (instance3 != null) { instance3.PlayUpgrade(); } } else { GameDirector instance4 = GameDirector.instance; if (instance4 != null) { CameraShake cameraImpact = instance4.CameraImpact; if (cameraImpact != null) { cameraImpact.ShakeDistance(5f, 1f, 6f, ((Component)toggle).transform.position, 0.2f); } } } if (!GameManager.Multiplayer() || PhotonNetwork.IsMasterClient) { PlayerHealth playerHealth = val.playerHealth; if (playerHealth != null) { playerHealth.MaterialEffectOverride((Effect)0); } } } catch { } } private static void RegisterConsumedUpgrade(ItemToggle toggle) { if ((Object)(object)toggle == (Object)null) { return; } string text = TryGetStatsItemName(toggle); if (!string.IsNullOrWhiteSpace(text)) { StatsModule.EnsureStatsManagerKey(text); StatsManager instance = StatsManager.instance; if (!((Object)(object)instance == (Object)null)) { instance.itemsPurchased[text] = Mathf.Max(instance.itemsPurchased[text] - 1, 0); } } } private static string? TryGetStatsItemName(ItemToggle toggle) { try { ItemAttributes val = ((Component)toggle).GetComponent<ItemAttributes>() ?? ((Component)toggle).GetComponentInChildren<ItemAttributes>() ?? ((Component)toggle).GetComponentInParent<ItemAttributes>(); if ((Object)(object)val?.item != (Object)null && !string.IsNullOrWhiteSpace(((Object)val.item).name)) { return ((Object)val.item).name; } } catch { } string text = ItemHelpers.GetItemAssetName((Object?)(object)toggle) ?? ((Object)toggle).name; return string.IsNullOrWhiteSpace(text) ? null : text; } } internal static class PrefabModule { private static readonly Dictionary<string, GameObject> PendingPool = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase); private static AssetBundle? _dhhBundle; private static ManualLogSource? _log; private static readonly HashSet<string> _knownPrefabKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase); internal static void Apply(Harmony harmony, Assembly asm, ManualLogSource? log) { _log = log; if (harmony != null && !(asm == null)) { PatchDhhAssetManagerIfPossible(harmony, asm); PatchDhhShopManagerIfPossible(harmony, asm); PatchRunManagerAwakeIfPossible(harmony); PatchPhotonDefaultPoolIfPossible(harmony); } } private static void PatchDhhAssetManagerIfPossible(Harmony harmony, Assembly asm) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.Managers.DHHAssetManager", throwOnError: false); if (type == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "LoadAssets", (Type[])null, (Type[])null); if (!(methodInfo == null)) { MethodInfo method = typeof(PrefabModule).GetMethod("DHHAssetManager_LoadAssets_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static bool DHHAssetManager_LoadAssets_Prefix() { try { string text = Path.Combine(Paths.PluginPath, "Cronchy-DeathHeadHopper", "deathheadhopper"); if (!File.Exists(text)) { ManualLogSource? log = _log; if (log != null) { log.LogError((object)("AssetBundle not found at: " + text)); } return false; } AssetBundle val = _dhhBundle; if ((Object)(object)val != (Object)null) { ManualLogSource? log2 = _log; if (log2 != null) { log2.LogInfo((object)"[Fix] Reusing already loaded AssetBundle instance."); } } else { string text2 = "Assets/DeathHeadHopper/Materials/Head Phase.mat"; foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { if ((Object)(object)allLoadedAssetBundle == (Object)null || (!string.Equals(((Object)allLoadedAssetBundle).name, "deathheadhopper", StringComparison.OrdinalIgnoreCase) && !string.Equals(((Object)allLoadedAssetBundle).name, Path.GetFileName(text), StringComparison.OrdinalIgnoreCase) && !allLoadedAssetBundle.Contains(text2) && !LooksLikeDhhBundle(allLoadedAssetBundle))) { continue; } val = allLoadedAssetBundle; break; } if ((Object)(object)val != (Object)null) { ManualLogSource? log3 = _log; if (log3 != null) { log3.LogInfo((object)"[Fix] Found already loaded DeathHeadHopper AssetBundle."); } } else { ManualLogSource? log4 = _log; if (log4 != null) { log4.LogInfo((object)("[Fix] Loading AssetBundle from: " + text)); } val = AssetBundle.LoadFromFile(text); if ((Object)(object)val == (Object)null) { ManualLogSource? log5 = _log; if (log5 != null) { log5.LogError((object)"[Fix] AssetBundle.LoadFromFile returned null."); } return false; } } if ((Object)(object)val == (Object)null) { ManualLogSource? log6 = _log; if (log6 != null) { log6.LogError((object)"[Fix] AssetBundle not available."); } return false; } _dhhBundle = val; } SetStaticFieldIfExists("DeathHeadHopper.Managers.DHHAssetManager", "headPhaseMaterial", val.LoadAsset<Material>("Assets/DeathHeadHopper/Materials/Head Phase.mat")); LoadItemsCompatible(val); InvokeStaticIfExists("DeathHeadHopper.Managers.DHHAssetManager", "LoadAbilities", val); InvokeStaticIfExists("DeathHeadHopper.Managers.DHHAssetManager", "LoadChargeAssets", val); SetStaticFieldIfExists("DeathHeadHopper.Managers.DHHShopManager", "shopAtticShelvesPrefab", val.LoadAsset<GameObject>("Assets/DeathHeadHopper/Shop Attic Shelves.prefab")); SetStaticFieldIfExists("DeathHeadHopper.Managers.DHHUIManager", "abilityUIPrefab", val.LoadAsset<GameObject>("Assets/DeathHeadHopper/Ability UI.prefab")); ManualLogSource? log7 = _log; if (log7 != null) { log7.LogInfo((object)"[Fix] LoadAssets compatible flow completed."); } } catch (Exception ex) { ManualLogSource? log8 = _log; if (log8 != null) { log8.LogError((object)ex); } } return false; } private static void LoadItemsCompatible(AssetBundle bundle) { Type type = AccessTools.TypeByName("DeathHeadHopper.Managers.DHHAssetManager"); if (type == null) { ManualLogSource? log = _log; if (log != null) { log.LogError((object)"[Fix] DHHAssetManager type not found."); } return; } FieldInfo fieldInfo = AccessTools.Field(type, "shopItems"); if (fieldInfo == null) { ManualLogSource? log2 = _log; if (log2 != null) { log2.LogError((object)"[Fix] DHHAssetManager.shopItems field not found."); } return; } if (!(fieldInfo.GetValue(null) is IDictionary dict)) { ManualLogSource? log3 = _log; if (log3 != null) { log3.LogError((object)"[Fix] DHHAssetManager.shopItems is not an IDictionary."); } return; } Type type2 = AccessTools.TypeByName("Item"); if (type2 == null) { ManualLogSource? log4 = _log; if (log4 != null) { log4.LogError((object)"[Fix] Game type Item not found."); } return; } FieldInfo fieldInfo2 = AccessTools.Field(type2, "prefab"); if (fieldInfo2 == null) { ManualLogSource? log5 = _log; if (log5 != null) { log5.LogError((object)"[Fix] Field Item.prefab not found."); } return; } MethodInfo methodInfo = AccessTools.Method(fieldInfo2.FieldType, "SetPrefab", new Type[2] { typeof(GameObject), typeof(string) }, (Type[])null); List<string> list = (from x in bundle.GetAllAssetNames() where x.EndsWith(".asset", StringComparison.OrdinalIgnoreCase) && x.IndexOf("/items/", StringComparison.OrdinalIgnoreCase) >= 0 select x).ToList(); ManualLogSource? log6 = _log; if (log6 != null) { log6.LogInfo((object)$"[Fix] Found {list.Count} item assets in bundle."); } foreach (string item in list) { Object val = null; try { val = bundle.LoadAsset(item, type2); } catch (Exception arg) { ManualLogSource? log7 = _log; if (log7 != null) { log7.LogError((object)$"[Fix] Exception loading item asset '{item}': {arg}"); } } if (val == (Object)null) { ManualLogSource? log8 = _log; if (log8 != null) { log8.LogError((object)("[Fix] Failed to load item asset: " + item)); } continue; } string text = item.Replace(".asset", ".prefab"); GameObject val2 = bundle.LoadAsset<GameObject>(text); if ((Object)(object)val2 == (Object)null) { ManualLogSource? log9 = _log; if (log9 != null) { log9.LogError((object)("[Fix] Failed to load item prefab: " + text)); } continue; } object obj = fieldInfo2.GetValue(val) ?? Activator.CreateInstance(fieldInfo2.FieldType); if (obj == null) { ManualLogSource? log10 = _log; if (log10 != null) { log10.LogError((object)"[Fix] Failed to create PrefabRef instance."); } continue; } fieldInfo2.SetValue(val, obj); methodInfo?.Invoke(obj, new object[2] { val2, text }); string name = val.name; string text2 = ItemHelpers.GetItemAssetName(val) ?? name; CachePrefabEntry(text, val2); string fileName = Path.GetFileName(text); if (!string.IsNullOrEmpty(fileName)) { CachePrefabEntry(fileName, val2); } if (!string.IsNullOrWhiteSpace(text2)) { CachePrefabEntry(text2, val2); CachePrefabEntry("Items/" + text2, val2); } CacheShopItemKey(dict, text2, val); CacheShopItemKey(dict, name, val); TryRegisterItemWithRepolib(val); StatsModule.EnsureStatsEntriesForItem(val); ManualLogSource? log11 = _log; if (log11 != null) { log11.LogInfo((object)("[Fix] Loaded item '" + name + "' from '" + item + "' and bound prefab '" + text + "'.")); } } } private static void PatchDhhShopManagerIfPossible(Harmony harmony, Assembly asm) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.Managers.DHHShopManager", throwOnError: false); if (type == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "LoadItems", (Type[])null, (Type[])null); if (!(methodInfo == null)) { MethodInfo method = typeof(PrefabModule).GetMethod("DHHShopManager_LoadItems_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static bool DHHShopManager_LoadItems_Prefix() { try { object staticInstanceByName = ReflectionHelper.GetStaticInstanceByName("ShopManager"); if (staticInstanceByName == null) { return false; } Type type = AccessTools.TypeByName("DeathHeadHopper.Managers.DHHAssetManager"); IDictionary shopItemsDict = ((type != null) ? (AccessTools.Field(type, "shopItems")?.GetValue(null) as IDictionary) : null); if (shopItemsDict == null) { return false; } Type type2 = AccessTools.TypeByName("DeathHeadHopper.Managers.DHHShopManager"); object obj = ((type2 != null) ? AccessTools.Field(type2, "potentialItems") : null)?.GetValue(null); IList dhhPotential = obj as IList; if (dhhPotential == null) { return false; } FieldInfo fieldInfo = AccessTools.Field(staticInstanceByName.GetType(), "potentialItemUpgrades"); FieldInfo fieldInfo2 = AccessTools.Field(staticInstanceByName.GetType(), "potentialItems"); IList list = fieldInfo?.GetValue(staticInstanceByName) as IList; IList list2 = fieldInfo2?.GetValue(staticInstanceByName) as IList; dhhPotential.Clear(); CollectAndRemove(list); CollectAndRemove(list2); ManualLogSource? log = _log; if (log != null) { log.LogInfo((object)$"[Fix] DHHShopManager potential list size {dhhPotential.Count} (upgrades left={list?.Count ?? 0}, items left={list2?.Count ?? 0})"); } void CollectAndRemove(IList? source) { if (source == null) { return; } List<object> list3 = new List<object>(); foreach (object item in source) { Object val = (Object)((item is Object) ? item : null); if (val != null) { string text = ItemHelpers.GetItemAssetName(val) ?? val.name; if (!string.IsNullOrWhiteSpace(text) && ShopItemsDictContains(shopItemsDict,