Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of DeathHeadHopperFix v0.2.1
plugins\DeathHeadHopperFix.dll
Decompiled 3 weeks 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.Globalization; 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.Core.Abilities; using DeathHeadHopperFix.Modules.Gameplay.Core.Audio; using DeathHeadHopperFix.Modules.Gameplay.Core.Input; using DeathHeadHopperFix.Modules.Gameplay.Core.Interop; using DeathHeadHopperFix.Modules.Gameplay.Core.Runtime; using DeathHeadHopperFix.Modules.Gameplay.Stun; using DeathHeadHopperFix.Modules.Stamina; using DeathHeadHopperFix.Modules.Utilities; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; [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 { [BepInPlugin("AdrenSnyder.DeathHeadHopperFix", "Death Head Hopper - Fix", "0.2.0")] public sealed class Plugin : BaseUnityPlugin { private const string TargetAssemblyName = "DeathHeadHopper"; private Harmony? _harmony; private bool _patched; private Assembly? _targetAssembly; private static ManualLogSource? _log; private void Awake() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown _log = ((BaseUnityPlugin)this).Logger; ConfigManager.Initialize(((BaseUnityPlugin)this).Config); WarnUnsafeDebugFlagsInRelease(); _harmony = new Harmony("AdrenSnyder.DeathHeadHopperFix"); _harmony.PatchAll(typeof(Plugin).Assembly); DHHApiGuardModule.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 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); _targetAssembly = asm; DHHApiGuardModule.Apply(harmony, asm); BatteryJumpPatchModule.Apply(harmony, asm); JumpForceModule.Apply(harmony, asm, _log); ChargeAbilityTuningModule.Apply(harmony, asm); ChargeHoldReleaseModule.Apply(harmony, asm, _log); InputModule.Apply(harmony, asm, _log); AbilityModule.ApplyAbilitySpotLabelOverlay(harmony, asm); AbilityModule.ApplyAbilityManagerHooks(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 void WarnUnsafeDebugFlagsInRelease() { if (!Debug.isDebugBuild && (InternalDebugFlags.DisableBatteryModule || InternalDebugFlags.DisableAbilityPatches || InternalDebugFlags.DisableSpectateChecks)) { ManualLogSource? log = _log; if (log != null) { log.LogWarning((object)("[DebugSafety] Internal debug bypass flags are enabled in a non-debug build. " + $"DisableBatteryModule={InternalDebugFlags.DisableBatteryModule}, " + $"DisableAbilityPatches={InternalDebugFlags.DisableAbilityPatches}, " + $"DisableSpectateChecks={InternalDebugFlags.DisableSpectateChecks}")); } } } } } 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 LastChanceInteropBridge { private const BindingFlags StaticAny = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private static Type? s_timerControllerType; private static Type? s_spectateHelperType; private static Type? s_featureFlagsType; private static Type? s_imageAssetLoaderType; private static PropertyInfo? s_isActiveProperty; private static PropertyInfo? s_directionUiVisibleProperty; private static MethodInfo? s_isDirectionEnergySufficientMethod; private static MethodInfo? s_getDirectionPenaltyPreviewMethod; private static MethodInfo? s_getDirectionEnergyDebugSnapshotMethod; private static MethodInfo? s_isPlayerSurrenderedForDataMethod; private static MethodInfo? s_allPlayersDisabledMethod; private static MethodInfo? s_resetForceStateMethod; private static MethodInfo? s_shouldForceLocalDeathHeadSpectateMethod; private static MethodInfo? s_ensureSpectatePlayerLocalMethod; private static MethodInfo? s_forceDeathHeadSpectateIfPossibleMethod; private static MethodInfo? s_debugLogStateMethod; private static MethodInfo? s_isManualSwitchInputDownMethod; private static FieldInfo? s_lastChanceModeField; private static FieldInfo? s_spectateDeadPlayersField; private static FieldInfo? s_spectateDeadPlayersModeField; private static FieldInfo? s_lastChanceIndicatorsField; private static MethodInfo? s_tryLoadSpriteMethod; internal static bool IsLastChanceActive() { return TryGetBoolProperty(ref s_isActiveProperty, "DeathHeadHopperFix.Modules.Gameplay.LastChance.Runtime.LastChanceTimerController", "IsActive"); } internal static bool IsDirectionIndicatorUiVisible() { return TryGetBoolProperty(ref s_directionUiVisibleProperty, "DeathHeadHopperFix.Modules.Gameplay.LastChance.Runtime.LastChanceTimerController", "IsDirectionIndicatorUiVisible"); } internal static bool IsDirectionIndicatorEnergySufficientPreview() { ResolveMembers(); if (s_isDirectionEnergySufficientMethod == null) { return false; } return (s_isDirectionEnergySufficientMethod.Invoke(null, null) as bool?).GetValueOrDefault(); } internal static float GetDirectionIndicatorPenaltySecondsPreview() { ResolveMembers(); if (s_getDirectionPenaltyPreviewMethod == null) { return 0f; } return (s_getDirectionPenaltyPreviewMethod.Invoke(null, null) as float?).GetValueOrDefault(); } internal static void GetDirectionIndicatorEnergyDebugSnapshot(out bool visible, out float timerRemaining, out float penaltyPreview, out bool hasEnoughEnergy) { visible = false; timerRemaining = 0f; penaltyPreview = 0f; hasEnoughEnergy = false; ResolveMembers(); if (!(s_getDirectionEnergyDebugSnapshotMethod == null)) { object[] array = new object[4] { false, 0f, 0f, false }; s_getDirectionEnergyDebugSnapshotMethod.Invoke(null, array); visible = (array[0] as bool?).GetValueOrDefault(); timerRemaining = (array[1] as float?).GetValueOrDefault(); penaltyPreview = (array[2] as float?).GetValueOrDefault(); hasEnoughEnergy = (array[3] as bool?).GetValueOrDefault(); } } internal static bool IsPlayerSurrenderedForData(PlayerAvatar? player) { ResolveMembers(); if (s_isPlayerSurrenderedForDataMethod == null) { return false; } return (s_isPlayerSurrenderedForDataMethod.Invoke(null, new object[1] { player }) as bool?).GetValueOrDefault(); } internal static bool AllPlayersDisabled() { ResolveMembers(); if (s_allPlayersDisabledMethod == null) { return false; } return (s_allPlayersDisabledMethod.Invoke(null, null) as bool?).GetValueOrDefault(); } internal static void ResetSpectateForceState() { ResolveMembers(); s_resetForceStateMethod?.Invoke(null, null); } internal static bool ShouldForceLocalDeathHeadSpectate() { ResolveMembers(); if (s_shouldForceLocalDeathHeadSpectateMethod == null) { return false; } return (s_shouldForceLocalDeathHeadSpectateMethod.Invoke(null, null) as bool?).GetValueOrDefault(); } internal static void EnsureSpectatePlayerLocal(SpectateCamera? spectate) { ResolveMembers(); s_ensureSpectatePlayerLocalMethod?.Invoke(null, new object[1] { spectate }); } internal static void ForceDeathHeadSpectateIfPossible() { ResolveMembers(); s_forceDeathHeadSpectateIfPossibleMethod?.Invoke(null, null); } internal static void DebugLogState(SpectateCamera? spectate) { ResolveMembers(); s_debugLogStateMethod?.Invoke(null, new object[1] { spectate }); } internal static bool IsManualSwitchInputDown() { ResolveMembers(); if (s_isManualSwitchInputDownMethod == null) { return false; } return (s_isManualSwitchInputDownMethod.Invoke(null, null) as bool?).GetValueOrDefault(); } internal static bool IsLastChanceModeEnabled() { ResolveMembers(); if (s_lastChanceModeField == null) { return false; } return (s_lastChanceModeField.GetValue(null) as bool?).GetValueOrDefault(); } internal static bool IsSpectateDeadPlayersEnabled() { ResolveMembers(); if (s_spectateDeadPlayersField == null) { return false; } return (s_spectateDeadPlayersField.GetValue(null) as bool?).GetValueOrDefault(); } internal static string GetSpectateDeadPlayersMode() { ResolveMembers(); if (s_spectateDeadPlayersModeField == null) { return string.Empty; } return (s_spectateDeadPlayersModeField.GetValue(null) as string) ?? string.Empty; } internal static string GetLastChanceIndicatorsMode() { ResolveMembers(); if (s_lastChanceIndicatorsField == null) { return string.Empty; } return (s_lastChanceIndicatorsField.GetValue(null) as string) ?? string.Empty; } internal static bool TryGetDirectionSlotSprite(out Sprite? sprite) { sprite = null; ResolveMembers(); if (s_tryLoadSpriteMethod == null) { return false; } object[] array = new object[5] { "Direction.png", null, null, string.Empty, 100f }; if (!(s_tryLoadSpriteMethod.Invoke(null, array) as bool?).GetValueOrDefault()) { return false; } object obj = array[2]; sprite = (Sprite?)((obj is Sprite) ? obj : null); return (Object)(object)sprite != (Object)null; } private static bool TryGetBoolProperty(ref PropertyInfo? property, string typeName, string propertyName) { ResolveMembers(); if (property == null) { property = ResolveType(typeName)?.GetProperty(propertyName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } return (property?.GetValue(null) as bool?).GetValueOrDefault(); } private static void ResolveMembers() { if ((object)s_timerControllerType == null) { s_timerControllerType = ResolveType("DeathHeadHopperFix.Modules.Gameplay.LastChance.Runtime.LastChanceTimerController"); } if ((object)s_spectateHelperType == null) { s_spectateHelperType = ResolveType("DeathHeadHopperFix.Modules.Gameplay.LastChance.Spectate.LastChanceSpectateHelper"); } if ((object)s_featureFlagsType == null) { s_featureFlagsType = ResolveType("DHHFLastChanceMode.Modules.Config.FeatureFlags"); } if ((object)s_imageAssetLoaderType == null) { s_imageAssetLoaderType = ResolveType("DeathHeadHopperFix.Modules.Utilities.ImageAssetLoader"); } if (s_timerControllerType != null) { if ((object)s_isDirectionEnergySufficientMethod == null) { s_isDirectionEnergySufficientMethod = s_timerControllerType.GetMethod("IsDirectionIndicatorEnergySufficientPreview", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if ((object)s_getDirectionPenaltyPreviewMethod == null) { s_getDirectionPenaltyPreviewMethod = s_timerControllerType.GetMethod("GetDirectionIndicatorPenaltySecondsPreview", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if ((object)s_getDirectionEnergyDebugSnapshotMethod == null) { s_getDirectionEnergyDebugSnapshotMethod = s_timerControllerType.GetMethod("GetDirectionIndicatorEnergyDebugSnapshot", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if ((object)s_isPlayerSurrenderedForDataMethod == null) { s_isPlayerSurrenderedForDataMethod = s_timerControllerType.GetMethod("IsPlayerSurrenderedForData", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } } if (s_spectateHelperType != null) { if ((object)s_allPlayersDisabledMethod == null) { s_allPlayersDisabledMethod = s_spectateHelperType.GetMethod("AllPlayersDisabled", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if ((object)s_resetForceStateMethod == null) { s_resetForceStateMethod = s_spectateHelperType.GetMethod("ResetForceState", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if ((object)s_shouldForceLocalDeathHeadSpectateMethod == null) { s_shouldForceLocalDeathHeadSpectateMethod = s_spectateHelperType.GetMethod("ShouldForceLocalDeathHeadSpectate", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if ((object)s_ensureSpectatePlayerLocalMethod == null) { s_ensureSpectatePlayerLocalMethod = s_spectateHelperType.GetMethod("EnsureSpectatePlayerLocal", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if ((object)s_forceDeathHeadSpectateIfPossibleMethod == null) { s_forceDeathHeadSpectateIfPossibleMethod = s_spectateHelperType.GetMethod("ForceDeathHeadSpectateIfPossible", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if ((object)s_debugLogStateMethod == null) { s_debugLogStateMethod = s_spectateHelperType.GetMethod("DebugLogState", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if ((object)s_isManualSwitchInputDownMethod == null) { s_isManualSwitchInputDownMethod = s_spectateHelperType.GetMethod("IsManualSwitchInputDown", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } } if (s_featureFlagsType != null) { if ((object)s_lastChanceModeField == null) { s_lastChanceModeField = s_featureFlagsType.GetField("LastChangeMode", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if ((object)s_spectateDeadPlayersField == null) { s_spectateDeadPlayersField = s_featureFlagsType.GetField("SpectateDeadPlayers", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if ((object)s_spectateDeadPlayersModeField == null) { s_spectateDeadPlayersModeField = s_featureFlagsType.GetField("SpectateDeadPlayersMode", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if ((object)s_lastChanceIndicatorsField == null) { s_lastChanceIndicatorsField = s_featureFlagsType.GetField("LastChanceIndicators", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } } if (s_imageAssetLoaderType != null && (object)s_tryLoadSpriteMethod == null) { s_tryLoadSpriteMethod = s_imageAssetLoaderType.GetMethod("TryLoadSprite", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } } private static Type? ResolveType(string fullName) { Type type = Type.GetType(fullName, throwOnError: false); if (type != null) { return type; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType(fullName, throwOnError: false); if (type != null) { return type; } } return null; } } internal static class LogLimiter { public const int DefaultFrameInterval = 240; private static readonly Dictionary<string, int> _lastFrameByKey = new Dictionary<string, int>(StringComparer.Ordinal); public static bool ShouldLog(string key, int frameInterval = 240) { 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 NetworkProtocol { internal const string ModId = "DeathHeadHopperFix"; internal const int ProtocolVersion = 1; internal const string RoomKeyPrefix = "DeathHeadHopperFix.Room."; internal static string BuildRoomKey(string localKey) { return string.IsNullOrWhiteSpace(localKey) ? "DeathHeadHopperFix.Room." : ("DeathHeadHopperFix.Room." + localKey.Trim()); } } internal readonly struct NetworkEnvelope { internal string ModId { get; } internal int ProtocolVersion { get; } internal string MessageType { get; } internal int MessageSeq { get; } internal object? Payload { get; } internal NetworkEnvelope(string modId, int protocolVersion, string messageType, int messageSeq, object? payload) { ModId = (string.IsNullOrWhiteSpace(modId) ? string.Empty : modId.Trim()); ProtocolVersion = protocolVersion; MessageType = (string.IsNullOrWhiteSpace(messageType) ? string.Empty : messageType.Trim()); MessageSeq = messageSeq; Payload = payload; } internal object?[] ToEventPayload() { return new object[5] { ModId, ProtocolVersion, MessageType, MessageSeq, Payload }; } internal bool IsExpectedSource() { return ModId == "DeathHeadHopperFix" && ProtocolVersion == 1 && !string.IsNullOrWhiteSpace(MessageType); } internal static bool TryParse(object? customData, out NetworkEnvelope envelope) { envelope = default(NetworkEnvelope); if (!(customData is object[] array) || array.Length < 5) { return false; } if (array[0] is string modId && array[1] is int protocolVersion && array[2] is string messageType) { object obj = array[3]; int messageSeq = default(int); int num; if (obj is int) { messageSeq = (int)obj; num = 1; } else { num = 0; } if (num != 0) { envelope = new NetworkEnvelope(modId, protocolVersion, messageType, messageSeq, array[4]); return true; } } return false; } } internal static class PhotonEventCodes { internal const byte ConfigSync = 79; } internal static class PlayerStateExtractionHelper { internal readonly struct PlayerStateSnapshot { internal int ActorNumber { get; } internal int SteamIdShort { get; } internal string Name { get; } internal Color Color { get; } internal bool IsAlive { get; } internal bool IsDead { get; } internal bool IsInTruck { get; } internal bool IsSurrendered { get; } internal int SourceOrder { get; } internal PlayerStateSnapshot(int actorNumber, int steamIdShort, string name, Color color, bool isAlive, bool isDead, bool isInTruck, bool isSurrendered, int sourceOrder) { //IL_0017: 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) ActorNumber = actorNumber; SteamIdShort = steamIdShort; Name = name; Color = color; IsAlive = isAlive; IsDead = isDead; IsInTruck = isInTruck; IsSurrendered = isSurrendered; SourceOrder = sourceOrder; } } private static readonly FieldInfo? s_playerNameField = AccessTools.Field(typeof(PlayerAvatar), "playerName"); private static readonly FieldInfo? s_playerDeadSetField = AccessTools.Field(typeof(PlayerAvatar), "deadSet"); private static readonly FieldInfo? s_playerIsDisabledField = AccessTools.Field(typeof(PlayerAvatar), "isDisabled"); private static readonly FieldInfo? s_playerRoomVolumeCheckField = AccessTools.Field(typeof(PlayerAvatar), "RoomVolumeCheck"); private static readonly FieldInfo? s_playerSteamIdShortField = AccessTools.Field(typeof(PlayerAvatar), "steamIDshort"); private static readonly FieldInfo? s_visualColorField = AccessTools.Field(typeof(PlayerAvatarVisuals), "color"); private static FieldInfo? s_roomVolumeCheckInTruckField; private static FieldInfo? s_deathHeadInTruckField; private static FieldInfo? s_deathHeadRoomVolumeCheckField; internal static List<PlayerStateSnapshot> GetPlayersStateSnapshot() { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) List<PlayerStateSnapshot> list = new List<PlayerStateSnapshot>(); GameDirector instance = GameDirector.instance; if ((Object)(object)instance == (Object)null || instance.PlayerList == null || instance.PlayerList.Count == 0) { return list; } for (int i = 0; i < instance.PlayerList.Count; i++) { PlayerAvatar val = instance.PlayerList[i]; if (!((Object)(object)val == (Object)null)) { PhotonView photonView = val.photonView; int? obj; if (photonView == null) { obj = null; } else { Player owner = photonView.Owner; obj = ((owner != null) ? new int?(owner.ActorNumber) : null); } int? num = obj; int valueOrDefault = num.GetValueOrDefault(); int steamIdShort = GetSteamIdShort(val); string playerName = GetPlayerName(val); Color playerColor = GetPlayerColor(val); bool flag = IsDeadSet(val); bool flag2 = IsDisabled(val); bool flag3 = flag || flag2; bool isAlive = !flag3; bool isInTruck = IsPlayerInTruck(val, flag2); bool isSurrendered = LastChanceInteropBridge.IsPlayerSurrenderedForData(val); list.Add(new PlayerStateSnapshot(valueOrDefault, steamIdShort, playerName, playerColor, isAlive, flag3, isInTruck, isSurrendered, i)); } } list.Sort(CompareSnapshotOrder); return list; } internal static List<PlayerStateSnapshot> GetPlayersStillInLastChance() { List<PlayerStateSnapshot> playersStateSnapshot = GetPlayersStateSnapshot(); List<PlayerStateSnapshot> list = new List<PlayerStateSnapshot>(playersStateSnapshot.Count); for (int i = 0; i < playersStateSnapshot.Count; i++) { PlayerStateSnapshot item = playersStateSnapshot[i]; if (!item.IsSurrendered) { list.Add(item); } } return list; } private static int CompareSnapshotOrder(PlayerStateSnapshot left, PlayerStateSnapshot right) { if (left.ActorNumber > 0 && right.ActorNumber > 0) { return left.ActorNumber.CompareTo(right.ActorNumber); } return left.SourceOrder.CompareTo(right.SourceOrder); } private static string GetPlayerName(PlayerAvatar player) { if (s_playerNameField != null && s_playerNameField.GetValue(player) is string text && !string.IsNullOrWhiteSpace(text)) { return text; } return "unknown"; } private static Color GetPlayerColor(PlayerAvatar player) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) PlayerAvatarVisuals playerAvatarVisuals = player.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals == (Object)null) { return Color.black; } if (s_visualColorField != null && s_visualColorField.GetValue(playerAvatarVisuals) is Color result) { return result; } return Color.black; } private static bool IsDeadSet(PlayerAvatar player) { bool flag = default(bool); int num; if (s_playerDeadSetField != null) { object value = s_playerDeadSetField.GetValue(player); 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 bool IsDisabled(PlayerAvatar player) { bool flag = default(bool); int num; if (s_playerIsDisabledField != null) { object value = s_playerIsDisabledField.GetValue(player); 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 bool IsPlayerInTruck(PlayerAvatar player, bool isDisabled) { if (!isDisabled) { object roomVolumeCheck = GetRoomVolumeCheck(player); return roomVolumeCheck != null && IsRoomVolumeInTruck(roomVolumeCheck); } PlayerDeathHead playerDeathHead = player.playerDeathHead; if ((Object)(object)playerDeathHead == (Object)null) { return false; } object deathHeadRoomVolumeCheck = GetDeathHeadRoomVolumeCheck(playerDeathHead); if (deathHeadRoomVolumeCheck != null) { return IsRoomVolumeInTruck(deathHeadRoomVolumeCheck); } FieldInfo deathHeadInTruckField = GetDeathHeadInTruckField(((object)playerDeathHead).GetType()); bool flag = default(bool); int num; if (deathHeadInTruckField != null) { object value = deathHeadInTruckField.GetValue(playerDeathHead); 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? GetRoomVolumeCheck(PlayerAvatar player) { if (s_playerRoomVolumeCheckField == null) { return null; } return s_playerRoomVolumeCheckField.GetValue(player); } private static bool IsRoomVolumeInTruck(object roomVolumeCheck) { if (roomVolumeCheck == null) { return false; } FieldInfo fieldInfo = s_roomVolumeCheckInTruckField; if (fieldInfo == null || fieldInfo.DeclaringType != roomVolumeCheck.GetType()) { fieldInfo = (s_roomVolumeCheckInTruckField = AccessTools.Field(roomVolumeCheck.GetType(), "inTruck")); } bool flag = default(bool); int num; if (fieldInfo != null) { object value = fieldInfo.GetValue(roomVolumeCheck); 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 FieldInfo? GetDeathHeadInTruckField(Type deathHeadType) { FieldInfo fieldInfo = s_deathHeadInTruckField; if (fieldInfo == null || fieldInfo.DeclaringType != deathHeadType) { fieldInfo = (s_deathHeadInTruckField = AccessTools.Field(deathHeadType, "inTruck")); } return fieldInfo; } private static object? GetDeathHeadRoomVolumeCheck(PlayerDeathHead deathHead) { FieldInfo fieldInfo = s_deathHeadRoomVolumeCheckField; if (fieldInfo == null || fieldInfo.DeclaringType != ((object)deathHead).GetType()) { fieldInfo = (s_deathHeadRoomVolumeCheckField = AccessTools.Field(((object)deathHead).GetType(), "roomVolumeCheck")); } return fieldInfo?.GetValue(deathHead); } private static int GetSteamIdShort(PlayerAvatar player) { return (s_playerSteamIdShortField != null && s_playerSteamIdShortField.GetValue(player) is int num) ? num : 0; } } internal static class PlayerTruckDistanceHelper { [Flags] internal enum DistanceQueryFields { None = 0, Height = 1, NavMeshDistance = 2, RoomPath = 4, All = 7 } internal readonly struct PlayerTruckDistance { internal PlayerAvatar PlayerAvatar { get; } internal float NavMeshDistance { get; } internal float HeightDelta { get; } internal int ShortestRoomPathToTruck { get; } internal int TotalMapRooms { get; } internal bool HasValidPath { get; } internal PlayerTruckDistance(PlayerAvatar playerAvatar, float navMeshDistance, float heightDelta, int shortestRoomPathToTruck, int totalMapRooms, bool hasValidPath) { PlayerAvatar = playerAvatar; NavMeshDistance = navMeshDistance; HeightDelta = heightDelta; ShortestRoomPathToTruck = shortestRoomPathToTruck; TotalMapRooms = totalMapRooms; HasValidPath = hasValidPath; } } private sealed class CachedPlayerDistance { internal float NavMeshDistance = -1f; internal float HeightDelta; internal int ShortestRoomPathToTruck = -1; internal int TotalMapRooms = -1; internal bool HasValidPath; internal int RoomHash; internal float HeightUpdatedAt = float.NegativeInfinity; internal int LevelStamp; internal Vector3 LastKnownWorldPosition; } private readonly struct RemotePlayerHint { internal int RoomHash { get; } internal float HeightDelta { get; } internal int LevelStamp { get; } internal float UpdatedAt { get; } internal RemotePlayerHint(int roomHash, float heightDelta, int levelStamp, float updatedAt) { RoomHash = roomHash; HeightDelta = heightDelta; LevelStamp = levelStamp; UpdatedAt = updatedAt; } } private struct ActivationProfileStats { internal int Calls; internal int PlayersProcessed; internal int NavRefreshCount; internal int RoomRefreshCount; internal int RemoteHintUsedCount; internal float TotalMs; internal float SetupMs; internal float LoopMs; internal float MaxCallMs; } private const float HeightCacheTtlSeconds = 2f; private static readonly Type? s_levelGeneratorType = AccessTools.TypeByName("LevelGenerator"); private static readonly FieldInfo? s_levelGeneratorInstanceField = ((s_levelGeneratorType == null) ? null : AccessTools.Field(s_levelGeneratorType, "Instance")); private static readonly FieldInfo? s_levelPathTruckField = ((s_levelGeneratorType == null) ? null : AccessTools.Field(s_levelGeneratorType, "LevelPathTruck")); private static readonly FieldInfo? s_levelPathPointsField = ((s_levelGeneratorType == null) ? null : AccessTools.Field(s_levelGeneratorType, "LevelPathPoints")); private static readonly Type? s_levelPointType = AccessTools.TypeByName("LevelPoint"); private static readonly FieldInfo? s_levelPointTruckField = ((s_levelPointType == null) ? null : AccessTools.Field(s_levelPointType, "Truck")); private static readonly FieldInfo? s_levelPointRoomField = ((s_levelPointType == null) ? null : AccessTools.Field(s_levelPointType, "Room")); private static readonly FieldInfo? s_levelPointConnectedPointsField = ((s_levelPointType == null) ? null : AccessTools.Field(s_levelPointType, "ConnectedPoints")); private static readonly Type? s_roomVolumeType = AccessTools.TypeByName("RoomVolume"); private static readonly FieldInfo? s_roomVolumeTruckField = ((s_roomVolumeType == null) ? null : AccessTools.Field(s_roomVolumeType, "Truck")); private static readonly FieldInfo? s_playerLastNavmeshField = AccessTools.Field(typeof(PlayerAvatar), "LastNavmeshPosition"); private static readonly FieldInfo? s_playerRoomVolumeCheckField = AccessTools.Field(typeof(PlayerAvatar), "RoomVolumeCheck"); private static readonly Type? s_playerDeathHeadType = AccessTools.TypeByName("PlayerDeathHead"); private static readonly FieldInfo? s_playerDeathHeadRoomVolumeCheckField = ((s_playerDeathHeadType == null) ? null : AccessTools.Field(s_playerDeathHeadType, "roomVolumeCheck")); private static readonly FieldInfo? s_playerDeathHeadPhysGrabObjectField = ((s_playerDeathHeadType == null) ? null : AccessTools.Field(s_playerDeathHeadType, "physGrabObject")); private static readonly Type? s_physGrabObjectType = AccessTools.TypeByName("PhysGrabObject"); private static readonly FieldInfo? s_physGrabObjectCenterPointField = ((s_physGrabObjectType == null) ? null : AccessTools.Field(s_physGrabObjectType, "centerPoint")); private static readonly Type? s_roomVolumeCheckType = AccessTools.TypeByName("RoomVolumeCheck"); private static readonly FieldInfo? s_roomVolumeCheckCurrentRoomsField = ((s_roomVolumeCheckType == null) ? null : AccessTools.Field(s_roomVolumeCheckType, "CurrentRooms")); private static readonly Type? s_navMeshType = AccessTools.TypeByName("UnityEngine.AI.NavMesh"); private static readonly Type? s_navMeshHitType = AccessTools.TypeByName("UnityEngine.AI.NavMeshHit"); private static readonly Type? s_navMeshPathType = AccessTools.TypeByName("UnityEngine.AI.NavMeshPath"); private static readonly MethodInfo? s_navMeshSamplePositionMethod = s_navMeshType?.GetMethod("SamplePosition", BindingFlags.Static | BindingFlags.Public, null, (s_navMeshHitType == null) ? null : new Type[4] { typeof(Vector3), s_navMeshHitType.MakeByRefType(), typeof(float), typeof(int) }, null); private static readonly PropertyInfo? s_navMeshHitPositionProperty = s_navMeshHitType?.GetProperty("position", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo? s_navMeshHitPositionField = s_navMeshHitType?.GetField("position", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo? s_navMeshCalculatePathMethod = s_navMeshType?.GetMethod("CalculatePath", BindingFlags.Static | BindingFlags.Public, null, new Type[4] { typeof(Vector3), typeof(Vector3), typeof(int), s_navMeshPathType }, null); private static readonly PropertyInfo? s_navMeshPathCornersProperty = s_navMeshPathType?.GetProperty("corners"); private static object? s_cachedGraphLevelGenerator; private static int s_cachedGraphPointCount; private static Dictionary<object, HashSet<object>>? s_cachedRoomGraph; private static readonly Dictionary<int, CachedPlayerDistance> s_playerCache = new Dictionary<int, CachedPlayerDistance>(); private static readonly Dictionary<int, RemotePlayerHint> s_remoteHints = new Dictionary<int, RemotePlayerHint>(); private static object? s_cachedLevelGeneratorForPlayers; private static Vector3 s_cachedTruckPosition; private static bool s_hasCachedTruckPosition; private static int s_cachedLevelPointsCount; private static bool s_activationProfilingEnabled; private static ActivationProfileStats s_activationProfileStats; internal static void PrimeDistancesCache() { GetDistancesFromTruck(DistanceQueryFields.NavMeshDistance | DistanceQueryFields.RoomPath); } internal static PlayerTruckDistance[] GetDistancesFromTruck() { return GetDistancesFromTruck(DistanceQueryFields.All); } internal static PlayerTruckDistance[] GetDistancesFromTruck(DistanceQueryFields fields, ICollection<PlayerAvatar>? players = null, bool forceRefresh = false) { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_04af: Unknown result type (might be due to invalid IL or missing references) //IL_04ba: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_0475: Unknown result type (might be due to invalid IL or missing references) try { bool debugLogging = FeatureFlags.DebugLogging; float num = (debugLogging ? Time.realtimeSinceStartup : 0f); float num2 = num; float num3 = num; int num4 = 0; int num5 = 0; int num6 = 0; int num7 = 0; if (fields == DistanceQueryFields.None || s_levelGeneratorInstanceField == null) { return Array.Empty<PlayerTruckDistance>(); } object value = s_levelGeneratorInstanceField.GetValue(null); if (value == null) { return Array.Empty<PlayerTruckDistance>(); } List<object> allLevelPoints = GetAllLevelPoints(value); if (!TryGetTruckTarget(value, allLevelPoints, out Vector3 truckPosition, out object truckPoint)) { return Array.Empty<PlayerTruckDistance>(); } GameDirector instance = GameDirector.instance; if (instance?.PlayerList == null || instance.PlayerList.Count == 0) { return Array.Empty<PlayerTruckDistance>(); } int num8 = allLevelPoints?.Count ?? 0; if (s_cachedLevelGeneratorForPlayers != value || !s_hasCachedTruckPosition || Vector3.SqrMagnitude(s_cachedTruckPosition - truckPosition) > 0.0001f || s_cachedLevelPointsCount != num8) { s_playerCache.Clear(); s_remoteHints.Clear(); s_cachedLevelGeneratorForPlayers = value; s_cachedTruckPosition = truckPosition; s_cachedLevelPointsCount = num8; s_hasCachedTruckPosition = true; } HashSet<int> hashSet = null; if (players != null) { hashSet = new HashSet<int>(); foreach (PlayerAvatar player in players) { if (!((Object)(object)player == (Object)null)) { hashSet.Add(GetPlayerKey(player)); } } if (hashSet.Count == 0) { return Array.Empty<PlayerTruckDistance>(); } } bool flag = (fields & DistanceQueryFields.RoomPath) != 0; bool flag2 = (fields & DistanceQueryFields.NavMeshDistance) != 0; bool flag3 = (fields & DistanceQueryFields.Height) != 0; Dictionary<object, HashSet<object>> dictionary = ((flag || flag2) ? GetOrBuildRoomGraph(value, allLevelPoints) : null); int totalMapRooms = ((dictionary != null && dictionary.Count > 0) ? dictionary.Count : (-1)); int num9 = (((Object)(object)RunManager.instance != (Object)null) ? RunManager.instance.levelsCompleted : 0); if (debugLogging) { num2 = Time.realtimeSinceStartup; num3 = num2; } List<PlayerTruckDistance> list = new List<PlayerTruckDistance>(instance.PlayerList.Count); foreach (PlayerAvatar player2 in instance.PlayerList) { if ((Object)(object)player2 == (Object)null) { continue; } int playerKey = GetPlayerKey(player2); if (hashSet != null && !hashSet.Contains(playerKey)) { continue; } if (!s_playerCache.TryGetValue(playerKey, out CachedPlayerDistance value2)) { value2 = new CachedPlayerDistance(); s_playerCache[playerKey] = value2; } Vector3 val = (value2.LastKnownWorldPosition = GetPlayerWorldPosition(player2)); PhotonView photonView = player2.photonView; int? obj; if (photonView == null) { obj = null; } else { Player owner = photonView.Owner; obj = ((owner != null) ? new int?(owner.ActorNumber) : null); } int? num10 = obj; int valueOrDefault = num10.GetValueOrDefault(); s_remoteHints.TryGetValue(valueOrDefault, out var value3); bool flag4 = SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.IsMultiplayer() && valueOrDefault > 0 && PhotonNetwork.LocalPlayer != null && valueOrDefault != PhotonNetwork.LocalPlayer.ActorNumber && value3.LevelStamp == num9; List<object> list2 = null; int num11 = value2.RoomHash; if (flag4) { num11 = value3.RoomHash; num6++; } else if (flag || flag2) { list2 = GetPlayerRooms(player2); num11 = ComputeRoomsHash(list2); } bool flag5 = num11 != value2.RoomHash; bool flag6 = value2.LevelStamp != num9; if (flag3) { float num12 = Time.unscaledTime - value2.HeightUpdatedAt; if (forceRefresh || flag6 || num12 < 0f || num12 > 2f) { if (flag4 && Time.unscaledTime - value3.UpdatedAt <= 2f) { value2.HeightDelta = value3.HeightDelta; value2.HeightUpdatedAt = value3.UpdatedAt; } else { value2.HeightDelta = val.y - truckPosition.y; value2.HeightUpdatedAt = Time.unscaledTime; } } } if (flag2 && (forceRefresh || flag6 || flag5)) { float navMeshDistance = -1f; Vector3 navMeshPosition; bool flag7 = TryGetPlayerNavMeshPosition(player2, val, out navMeshPosition) && TryCalculatePathDistance(navMeshPosition, truckPosition, out navMeshDistance); value2.NavMeshDistance = (flag7 ? navMeshDistance : (-1f)); value2.HasValidPath = flag7; num4++; } if (flag && (forceRefresh || flag6 || flag5)) { if (list2 == null) { list2 = GetPlayerRooms(player2); } value2.ShortestRoomPathToTruck = ResolveShortestRoomPathToTruck(list2 ?? new List<object>(), truckPoint, dictionary); num5++; } if (flag || flag2) { value2.TotalMapRooms = totalMapRooms; } value2.RoomHash = num11; value2.LevelStamp = num9; list.Add(new PlayerTruckDistance(player2, value2.NavMeshDistance, value2.HeightDelta, value2.ShortestRoomPathToTruck, value2.TotalMapRooms, value2.HasValidPath)); num7++; } if (debugLogging && s_activationProfilingEnabled) { float realtimeSinceStartup = Time.realtimeSinceStartup; float num13 = (realtimeSinceStartup - num) * 1000f; float num14 = (num2 - num) * 1000f; float num15 = (realtimeSinceStartup - num3) * 1000f; s_activationProfileStats.Calls++; s_activationProfileStats.PlayersProcessed += num7; s_activationProfileStats.NavRefreshCount += num4; s_activationProfileStats.RoomRefreshCount += num5; s_activationProfileStats.RemoteHintUsedCount += num6; s_activationProfileStats.TotalMs += num13; s_activationProfileStats.SetupMs += num14; s_activationProfileStats.LoopMs += num15; s_activationProfileStats.MaxCallMs = Mathf.Max(s_activationProfileStats.MaxCallMs, num13); } return list.ToArray(); } catch (Exception ex) { LogReflectionHotPathException("GetDistancesFromTruck", ex); return Array.Empty<PlayerTruckDistance>(); } } internal static void ApplyRemotePlayerHint(int actorNumber, int roomHash, float heightDelta, int levelStamp) { if (actorNumber > 0) { s_remoteHints[actorNumber] = new RemotePlayerHint(roomHash, heightDelta, levelStamp, Time.unscaledTime); } } internal static bool TryBuildLocalPlayerTruckHint(out int roomHash, out float heightDelta, out int levelStamp) { //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) roomHash = 0; heightDelta = 0f; levelStamp = (((Object)(object)RunManager.instance != (Object)null) ? RunManager.instance.levelsCompleted : 0); try { if (!PhotonNetwork.InRoom || PhotonNetwork.LocalPlayer == null || s_levelGeneratorInstanceField == null) { return false; } object value = s_levelGeneratorInstanceField.GetValue(null); if (value == null) { return false; } List<object> allLevelPoints = GetAllLevelPoints(value); if (!TryGetTruckTarget(value, allLevelPoints, out Vector3 truckPosition, out object _)) { return false; } GameDirector instance = GameDirector.instance; if (instance?.PlayerList == null || instance.PlayerList.Count == 0) { return false; } int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; PlayerAvatar val = null; for (int i = 0; i < instance.PlayerList.Count; i++) { PlayerAvatar val2 = instance.PlayerList[i]; if (!((Object)(object)val2 == (Object)null)) { PhotonView photonView = val2.photonView; int? obj; if (photonView == null) { obj = null; } else { Player owner = photonView.Owner; obj = ((owner != null) ? new int?(owner.ActorNumber) : null); } int? num = obj; if (num.GetValueOrDefault() == actorNumber) { val = val2; break; } } } if ((Object)(object)val == (Object)null) { return false; } List<object> playerRooms = GetPlayerRooms(val); roomHash = ComputeRoomsHash(playerRooms); Vector3 playerWorldPosition = GetPlayerWorldPosition(val); heightDelta = playerWorldPosition.y - truckPosition.y; return true; } catch (Exception ex) { LogReflectionHotPathException("TryBuildLocalPlayerTruckHint", ex); return false; } } private static void LogReflectionHotPathException(string context, Exception ex) { if (FeatureFlags.DebugLogging) { string key = "LastChance.Reflection.PlayerTruckDistance." + context; if (LogLimiter.ShouldLog(key, 600)) { Debug.LogWarning((object)("[LastChance] Reflection hot-path failed in " + context + ": " + ex.GetType().Name + ": " + ex.Message)); } } } internal static void BeginActivationProfiling() { s_activationProfileStats = default(ActivationProfileStats); s_activationProfilingEnabled = true; } internal static string EndActivationProfilingSummary() { s_activationProfilingEnabled = false; return $"calls={s_activationProfileStats.Calls} total={s_activationProfileStats.TotalMs:F1}ms setup={s_activationProfileStats.SetupMs:F1}ms loop={s_activationProfileStats.LoopMs:F1}ms maxCall={s_activationProfileStats.MaxCallMs:F1}ms players={s_activationProfileStats.PlayersProcessed} navRefresh={s_activationProfileStats.NavRefreshCount} roomRefresh={s_activationProfileStats.RoomRefreshCount} remoteHints={s_activationProfileStats.RemoteHintUsedCount}"; } private static int GetPlayerKey(PlayerAvatar player) { PhotonView photonView = player.photonView; int? obj; if (photonView == null) { obj = null; } else { Player owner = photonView.Owner; obj = ((owner != null) ? new int?(owner.ActorNumber) : null); } int? num = obj; int valueOrDefault = num.GetValueOrDefault(); if (valueOrDefault != 0) { return valueOrDefault; } return ((Object)player).GetInstanceID(); } private static int ComputeRoomsHash(List<object> rooms) { int num = 17; for (int i = 0; i < rooms.Count; i++) { num = num * 31 + RuntimeHelpers.GetHashCode(rooms[i]); } return num; } private static Dictionary<object, HashSet<object>> GetOrBuildRoomGraph(object levelGenerator, List<object>? allLevelPoints) { int num = allLevelPoints?.Count ?? 0; if (s_cachedRoomGraph != null && levelGenerator == s_cachedGraphLevelGenerator && s_cachedGraphPointCount == num) { return s_cachedRoomGraph; } Dictionary<object, HashSet<object>> result = BuildRoomGraph(allLevelPoints); s_cachedGraphLevelGenerator = levelGenerator; s_cachedGraphPointCount = num; s_cachedRoomGraph = result; return result; } private static bool TryGetTruckTarget(object levelGenerator, List<object>? allLevelPoints, out Vector3 truckPosition, out object? truckPoint) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) truckPosition = Vector3.zero; truckPoint = null; if (s_levelPathTruckField != null) { object value = s_levelPathTruckField.GetValue(levelGenerator); if (TryGetLevelPointPosition(value, out truckPosition)) { truckPoint = value; return true; } } if (allLevelPoints == null) { return false; } foreach (object allLevelPoint in allLevelPoints) { if (allLevelPoint == null || !TryIsTruckPoint(allLevelPoint) || !TryGetLevelPointPosition(allLevelPoint, out truckPosition)) { continue; } truckPoint = allLevelPoint; return true; } return false; } private static List<object>? GetAllLevelPoints(object levelGenerator) { if (s_levelPathPointsField == null) { return null; } if (!(s_levelPathPointsField.GetValue(levelGenerator) is IEnumerable enumerable)) { return null; } List<object> list = new List<object>(); foreach (object item in enumerable) { if (item != null) { list.Add(item); } } return (list.Count > 0) ? list : null; } private static bool TryIsTruckPoint(object point) { if (point == null) { return false; } bool flag = default(bool); int num; if (s_levelPointTruckField != null) { object value = s_levelPointTruckField.GetValue(point); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return true; } if (s_levelPointRoomField != null && s_roomVolumeTruckField != null) { object value2 = s_levelPointRoomField.GetValue(point); bool flag2 = default(bool); int num2; if (value2 != null) { object value = s_roomVolumeTruckField.GetValue(value2); if (value is bool) { flag2 = (bool)value; num2 = 1; } else { num2 = 0; } } else { num2 = 0; } if (((uint)num2 & (flag2 ? 1u : 0u)) != 0) { return true; } } return false; } private static int ResolveShortestRoomPathToTruck(List<object> playerRooms, object? truckPoint, Dictionary<object, HashSet<object>>? roomGraph) { if (truckPoint == null || roomGraph == null || roomGraph.Count == 0) { return -1; } object levelPointRoom = GetLevelPointRoom(truckPoint); if (levelPointRoom == null || !roomGraph.ContainsKey(levelPointRoom)) { return -1; } if (playerRooms.Count == 0) { return -1; } HashSet<object> hashSet = new HashSet<object>(); Queue<(object, int)> queue = new Queue<(object, int)>(); foreach (object playerRoom in playerRooms) { if (playerRoom != null && roomGraph.ContainsKey(playerRoom) && hashSet.Add(playerRoom)) { queue.Enqueue((playerRoom, 0)); } } while (queue.Count > 0) { var (obj, num) = queue.Dequeue(); if (obj == levelPointRoom) { return num; } if (!roomGraph.TryGetValue(obj, out HashSet<object> value)) { continue; } foreach (object item in value) { if (item != null && hashSet.Add(item)) { queue.Enqueue((item, num + 1)); } } } return -1; } private static List<object> GetPlayerRooms(PlayerAvatar player) { List<object> list = new List<object>(); if ((Object)(object)player == (Object)null || s_playerRoomVolumeCheckField == null || s_roomVolumeCheckCurrentRoomsField == null) { return list; } object obj = null; PlayerDeathHead playerDeathHead = player.playerDeathHead; if ((Object)(object)playerDeathHead != (Object)null && s_playerDeathHeadRoomVolumeCheckField != null) { obj = s_playerDeathHeadRoomVolumeCheckField.GetValue(playerDeathHead); } if (obj == null) { obj = s_playerRoomVolumeCheckField.GetValue(player); } if (obj == null) { return list; } if (!(s_roomVolumeCheckCurrentRoomsField.GetValue(obj) is IEnumerable enumerable)) { return list; } foreach (object item in enumerable) { if (item != null) { list.Add(item); } } return list; } private static Dictionary<object, HashSet<object>> BuildRoomGraph(List<object>? allLevelPoints) { Dictionary<object, HashSet<object>> dictionary = new Dictionary<object, HashSet<object>>(); if (allLevelPoints == null || s_levelPointRoomField == null) { return dictionary; } foreach (object allLevelPoint in allLevelPoints) { if (allLevelPoint == null) { continue; } object levelPointRoom = GetLevelPointRoom(allLevelPoint); if (levelPointRoom == null) { continue; } if (!dictionary.ContainsKey(levelPointRoom)) { dictionary[levelPointRoom] = new HashSet<object>(); } IEnumerable<object> connectedPoints = GetConnectedPoints(allLevelPoint); if (connectedPoints == null) { continue; } foreach (object item in connectedPoints) { if (item == null) { continue; } object levelPointRoom2 = GetLevelPointRoom(item); if (levelPointRoom2 != null) { if (!dictionary.ContainsKey(levelPointRoom2)) { dictionary[levelPointRoom2] = new HashSet<object>(); } if (levelPointRoom != levelPointRoom2) { dictionary[levelPointRoom].Add(levelPointRoom2); dictionary[levelPointRoom2].Add(levelPointRoom); } } } } return dictionary; } private static object? GetLevelPointRoom(object levelPoint) { if (levelPoint == null || s_levelPointRoomField == null) { return null; } return s_levelPointRoomField.GetValue(levelPoint); } private static IEnumerable<object>? GetConnectedPoints(object levelPoint) { if (levelPoint == null || s_levelPointConnectedPointsField == null) { return null; } if (s_levelPointConnectedPointsField.GetValue(levelPoint) is IEnumerable enumerable) { List<object> list = new List<object>(); foreach (object item in enumerable) { if (item != null) { list.Add(item); } } return (list.Count > 0) ? list : null; } return null; } private static bool TryGetLevelPointPosition(object? levelPoint, out Vector3 position) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; if (levelPoint == null) { return false; } Component val = (Component)((levelPoint is Component) ? levelPoint : null); if (val != null && (Object)(object)val != (Object)null) { position = val.transform.position; return true; } PropertyInfo property = levelPoint.GetType().GetProperty("transform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { object? value = property.GetValue(levelPoint); Transform val2 = (Transform)((value is Transform) ? value : null); if (val2 != null) { position = val2.position; return true; } } return false; } private static Vector3 GetPlayerWorldPosition(PlayerAvatar player) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return Vector3.zero; } PlayerDeathHead playerDeathHead = player.playerDeathHead; if ((Object)(object)playerDeathHead != (Object)null) { return ((Component)playerDeathHead).transform.position; } if ((Object)(object)player.playerTransform != (Object)null) { return player.playerTransform.position; } return ((Component)player).transform.position; } private static bool TryGetPlayerNavMeshPosition(PlayerAvatar player, Vector3 worldPosition, out Vector3 navMeshPosition) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0157: 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_016d: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) navMeshPosition = Vector3.zero; if ((Object)(object)player == (Object)null) { return false; } if (TrySamplePosition(worldPosition, 8f, out var navMeshPosition2)) { navMeshPosition = navMeshPosition2; return true; } PlayerDeathHead playerDeathHead = player.playerDeathHead; if ((Object)(object)playerDeathHead != (Object)null) { Vector3 val = ((Component)playerDeathHead).transform.position; if (s_playerDeathHeadPhysGrabObjectField != null && s_physGrabObjectCenterPointField != null) { object value = s_playerDeathHeadPhysGrabObjectField.GetValue(playerDeathHead); if (value != null && s_physGrabObjectCenterPointField.GetValue(value) is Vector3 val2) { val = val2; } } if (TrySamplePosition(val, 12f, out navMeshPosition2) || TrySamplePosition(val - Vector3.up * 0.5f, 18f, out navMeshPosition2) || TrySamplePosition(val, 30f, out navMeshPosition2)) { navMeshPosition = navMeshPosition2; return true; } return false; } if (s_playerLastNavmeshField != null && s_playerLastNavmeshField.GetValue(player) is Vector3 val3 && val3 != Vector3.zero) { navMeshPosition = val3; return true; } return false; } private static bool TrySamplePosition(Vector3 worldPosition, float maxDistance, out Vector3 navMeshPosition) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) navMeshPosition = Vector3.zero; if (s_navMeshType == null || s_navMeshHitType == null || s_navMeshSamplePositionMethod == null) { return false; } object obj = Activator.CreateInstance(s_navMeshHitType); if (obj == null) { return false; } object[] array = new object[4] { worldPosition, obj, maxDistance, -1 }; if (!(s_navMeshSamplePositionMethod.Invoke(null, array) is bool flag) || !flag) { return false; } if (!TryGetNavMeshHitPosition(array[1], out var position)) { return false; } navMeshPosition = position; return true; } private static bool TryGetNavMeshHitPosition(object? navHitBoxed, out Vector3 position) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; if (navHitBoxed == null) { return false; } if (s_navMeshHitPositionProperty != null && s_navMeshHitPositionProperty.GetValue(navHitBoxed) is Vector3 val) { position = val; return true; } if (s_navMeshHitPositionField != null && s_navMeshHitPositionField.GetValue(navHitBoxed) is Vector3 val2) { position = val2; return true; } return false; } private static bool TryCalculatePathDistance(Vector3 from, Vector3 to, out float navMeshDistance) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: 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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) navMeshDistance = 0f; if (s_navMeshType == null || s_navMeshPathType == null || s_navMeshCalculatePathMethod == null || s_navMeshPathCornersProperty == null) { return false; } object obj = Activator.CreateInstance(s_navMeshPathType); if (obj == null) { return false; } object[] parameters = new object[4] { from, to, -1, obj }; if (!(s_navMeshCalculatePathMethod.Invoke(null, parameters) is bool flag) || !flag) { return false; } if (!(s_navMeshPathCornersProperty.GetValue(obj) is Vector3[] array) || array.Length == 0) { navMeshDistance = Vector3.Distance(from, to); return true; } Vector3 val = from; float num = 0f; Vector3[] array2 = array; foreach (Vector3 val2 in array2) { num += Vector3.Distance(val, val2); val = val2; } navMeshDistance = num; return true; } } 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; } } internal static class SpectateContextHelper { private static readonly FieldInfo? s_spectatePlayerField = AccessTools.Field(typeof(SpectateCamera), "player"); private static readonly FieldInfo? s_playerDeathHeadSpectatedField = AccessTools.Field(typeof(PlayerDeathHead), "spectated"); internal static bool IsSpectatingLocalPlayerTarget() { SpectateCamera instance = SpectateCamera.instance; PlayerAvatar instance2 = PlayerAvatar.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || s_spectatePlayerField == null) { return false; } object? value = s_spectatePlayerField.GetValue(instance); PlayerAvatar val = (PlayerAvatar)((value is PlayerAvatar) ? value : null); return (Object)(object)val != (Object)null && val == instance2; } internal static bool IsSpectatingLocalDeathHead() { SpectateCamera instance = SpectateCamera.instance; if ((Object)(object)instance == (Object)null || !instance.CheckState((State)2)) { return false; } PlayerDeathHead val = PlayerController.instance?.playerAvatarScript?.playerDeathHead; if ((Object)(object)val == (Object)null || s_playerDeathHeadSpectatedField == null) { return false; } return (s_playerDeathHeadSpectatedField.GetValue(val) as bool?).GetValueOrDefault(); } internal static bool IsLocalDeathHeadSpectated() { PlayerDeathHead val = PlayerController.instance?.playerAvatarScript?.playerDeathHead; if ((Object)(object)val == (Object)null || s_playerDeathHeadSpectatedField == null) { return false; } return (s_playerDeathHeadSpectatedField.GetValue(val) as bool?).GetValueOrDefault(); } } } namespace DeathHeadHopperFix.Modules.Stamina { internal sealed class StaminaRechargeModule : MonoBehaviour { private static readonly Type? s_deathHeadControllerType = AccessTools.TypeByName("DeathHeadHopper.DeathHead.DeathHeadController"); private object? _controllerInstance; private PhotonView? _photonView; private bool _isOwner; private float _rechargeAccumulator; private Rigidbody? _rb; private void Awake() { if (s_deathHeadControllerType == null) { ((Behaviour)this).enabled = false; return; } _controllerInstance = ((Component)this).GetComponent(s_deathHeadControllerType); if (_controllerInstance == null) { ((Behaviour)this).enabled = false; return; } _photonView = ((Component)this).GetComponent<PhotonView>(); _isOwner = !SemiFunc.IsMultiplayer() || ((Object)(object)_photonView != (Object)null && _photonView.IsMine); _rb = ((Component)this).GetComponent<Rigidbody>(); } private void Update() { if (!_isOwner) { return; } if (!FeatureFlags.RechargeWithStamina) { _rechargeAccumulator = 0f; } else { if (_controllerInstance == null) { return; } _rechargeAccumulator += Time.deltaTime; if (!(_rechargeAccumulator < FeatureFlags.RechargeTickInterval)) { bool flag = !FeatureFlags.RechargeStaminaOnlyStationary || IsHeadStationary(); (bool, bool?, float, float) tuple = DHHBatteryHelper.EvaluateJumpAllowance(); if (flag || !tuple.Item1) { DHHBatteryHelper.RechargeDhhAbilityEnergy(_controllerInstance, _rechargeAccumulator); } _rechargeAccumulator = 0f; } } } private bool IsHeadStationary() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_rb == (Object)null) { return true; } Vector3 velocity = _rb.velocity; return ((Vector3)(ref velocity)).sqrMagnitude < FeatureFlags.HeadStationaryVelocitySqrThreshold; } } } namespace DeathHeadHopperFix.Modules.Gameplay.Stun { internal static class ChargeHoldReleaseModule { private sealed class ChargeHoldState { public float StartTime; public bool IsHolding; public float LaunchScale = 1f; } 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 ChargeStrengthLogKey = "Fix:Charge.Strength"; private const string ChargePermissiveFallbackLogKey = "Fix:Charge.PermissiveFallback"; private const float RemoteReleaseCommandTag = -777f; private const float RemoteCancelCommandTag = -778f; private static ManualLogSource? s_log; private static FieldInfo? s_chargeHandlerChargeStrengthField; private static MethodInfo? s_chargeHandlerAbilityLevelGetter; private static FieldInfo? s_chargeHandlerImpactDetectorField; private static FieldInfo? s_chargeHandlerControllerField; private static FieldInfo? s_chargeHandlerMaxBouncesField; private static FieldInfo? s_chargeHandlerWindupTimerField; private static FieldInfo? s_chargeHandlerWindupTimeField; private static FieldInfo? s_chargeHandlerEnemiesHitField; private static MethodInfo? s_chargeHandlerEndChargeMethod; private static MethodInfo? s_chargeHandlerCancelChargeMethod; private static MethodInfo? s_chargeHandlerStateGetter; private static FieldInfo? s_deathHeadControllerAudioHandlerField; private static MethodInfo? s_audioHandlerStopWindupMethod; private static FieldInfo? s_impactDetectorPhysGrabObjectField; private static FieldInfo? s_cachedPhysGrabObjectGrabbedField; private static MethodInfo? s_chargeAbilityOnAbilityUpPrefixMethod; private static MethodInfo? s_chargeAbilityOnAbilityDownPostfixMethod; private static MethodInfo? s_chargeAbilityOnAbilityCancelPostfixMethod; private static MethodInfo? s_stunHandlerStunDurationGetter; private static FieldInfo? s_stunHandlerChargeHandlerField; private static Type? s_dhhStatsManagerType; private static MethodInfo? s_dhhStatsGetHeadChargeUpgradeMethod; private static readonly Dictionary<int, ChargeHoldState> s_chargeHoldStates = new Dictionary<int, ChargeHoldState>(); private static float s_lastLocalHoldInputStartTime; private static bool s_localHoldUiActive; private static bool s_localHoldInputPending; internal static void Apply(Harmony harmony, Assembly asm, ManualLogSource? log) { s_log = log; PatchChargeHandlerDamageModeIfPossible(harmony, asm); PatchChargeAbilityHoldReleaseIfPossible(harmony, asm); PatchStunHandlerHoldScalingIfPossible(harmony, asm); } 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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Expected O, but got Unknown //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Expected O, but got Unknown //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Expected O, but got Unknown //IL_0364: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Expected O, but got Unknown //IL_03aa: Unknown result type (might be due to invalid IL or missing references) //IL_03b8: Expected O, but got Unknown //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: 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(ChargeHoldReleaseModule).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 method2 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_ChargeWindup_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); } MethodInfo methodInfo2 = AccessTools.Method(type, "ResetState", Type.EmptyTypes, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(type, "FixedUpdate", Type.EmptyTypes, (Type[])null); MethodInfo methodInfo4 = AccessTools.Method(type, "CancelCharge", Type.EmptyTypes, (Type[])null); MethodInfo methodInfo5 = AccessTools.Method(type, "EnemyHit", (Type[])null, (Type[])null); MethodInfo methodInfo6 = AccessTools.Method(type, "UpdateWindupDirection", new Type[1] { typeof(Vector3) }, (Type[])null); if (s_chargeHandlerChargeStrengthField == null) { s_chargeHandlerChargeStrengthField = AccessTools.Field(type, "chargeStrength"); } if (s_chargeHandlerAbilityLevelGetter == null) { s_chargeHandlerAbilityLevelGetter = AccessTools.PropertyGetter(type, "AbilityLevel"); } if (s_chargeHandlerControllerField == null) { s_chargeHandlerControllerField = AccessTools.Field(type, "controller"); } if ((object)s_chargeHandlerMaxBouncesField == null) { s_chargeHandlerMaxBouncesField = AccessTools.Field(type, "maxBounces"); } if ((object)s_chargeHandlerWindupTimerField == null) { s_chargeHandlerWindupTimerField = AccessTools.Field(type, "windupTimer"); } if ((object)s_chargeHandlerWindupTimeField == null) { s_chargeHandlerWindupTimeField = AccessTools.Field(type, "windupTime"); } if ((object)s_chargeHandlerEnemiesHitField == null) { s_chargeHandlerEnemiesHitField = AccessTools.Field(type, "enemiesHit"); } if ((object)s_chargeHandlerEndChargeMethod == null) { s_chargeHandlerEndChargeMethod = AccessTools.Method(type, "EndCharge", Type.EmptyTypes, (Type[])null); } if ((object)s_chargeHandlerCancelChargeMethod == null) { s_chargeHandlerCancelChargeMethod = AccessTools.Method(type, "CancelCharge", Type.EmptyTypes, (Type[])null); } if ((object)s_chargeHandlerStateGetter == null) { s_chargeHandlerStateGetter = AccessTools.PropertyGetter(type, "State"); } MethodInfo method3 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_ResetState_Postfix", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo2 != null && method3 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo7 = AccessTools.Method(type, "EndCharge", Type.EmptyTypes, (Type[])null); MethodInfo method4 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_EndCharge_Postfix", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo7 != null && method4 != null) { harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo method5 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_FixedUpdate_Postfix", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo3 != null && method5 != null) { harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(method5), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo method6 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_CancelCharge_Postfix", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo4 != null && method6 != null) { harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(method6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo method7 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_EnemyHit_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo5 != null && method7 != null) { harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(method7), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo method8 = typeof(ChargeHoldReleaseModule).GetMethod("ChargeHandler_UpdateWindupDirection_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (methodInfo6 != null && method8 != null) { harmony.Patch((MethodBase)methodInfo6, new HarmonyMethod(method8), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } 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 void ChargeHandler_ChargeWindup_Postfix(object __instance) { if (__instance != null && IsChargeState(__instance, "Windup")) { int unityObjectInstanceId = GetUnityObjectInstanceId(__instance); if (unityObjectInstanceId != 0) { ChargeHoldState orCreateChargeHoldState = GetOrCreateChargeHoldState(unityObjectInstanceId); orCreateChargeHoldState.StartTime = Time.time; orCreateChargeHoldState.IsHolding = true; orCreateChargeHoldState.LaunchScale = 1f; s_localHoldUiActive = true; AbilityModule.SetChargeSlotActivationProgress(0f); } } } private static void ChargeHandler_FixedUpdate_Postfix(object __instance) { if (__instance == null) { return; } int unityObjectInstanceId = GetUnityObjectInstanceId(__instance); if (unityObjectInstanceId == 0) { return; } if (!IsLocalChargeHandler(__instance)) { if (s_chargeHoldStates.TryGetValue(unityObjectInstanceId, out ChargeHoldState value)) { if (!IsChargeState(__instance, "Windup")) { s_chargeHoldStates.Remove(unityObjectInstanceId); } else if (value.IsHolding && s_chargeHandlerWindupTimerField != null && s_chargeHandlerWindupTimeField != null) { float num2 = ((s_chargeHandlerWindupTimeField.GetValue(__instance) is float num) ? num : 1.8f); s_chargeHandlerWindupTimerField.SetValue(__instance, Mathf.Max(0.01f, num2)); } } return; } if (!s_chargeHoldStates.TryGetValue(unityObjectInstanceId, out ChargeHoldState value2)) { if (!IsChargeState(__instance, "Windup") || !s_localHoldInputPending) { if (!s_localHoldUiActive) { AbilityModule.SetChargeSlotActivationProgress(0f); } return; } value2 = GetOrCreateChargeHoldState(unityObjectInstanceId); value2.StartTime = ((s_lastLocalHoldInputStartTime > 0f) ? s_lastLocalHoldInputStartTime : Time.time); value2.IsHolding = true; value2.LaunchScale = 1f; s_localHoldUiActive = true; AbilityModule.SetChargeSlotActivationProgress(0f); } if (!IsChargeState(__instance, "Windup")) { s_chargeHoldStates.Remove(unityObjectInstanceId); s_localHoldUiActive = false; AbilityModule.SetChargeSlotActivationProgress(0f); if (!s_localHoldUiActive) { AbilityModule.SetChargeSlotActivationProgress(0f); } return; } if (s_localHoldUiActive && value2.IsHolding) { float num3 = Mathf.Max(0.2f, FeatureFlags.ChargeAbilityHoldSeconds); float progress = Mathf.Clamp01((Time.time - value2.StartTime) / num3); float minimumChargeReleaseScale = GetMinimumChargeReleaseScale(__instance); AbilityModule.SetChargeSlotActivationProgress(progress, minimumChargeReleaseScale); } else { if (!value2.IsHolding) { if (!s_localHoldUiActive) { AbilityModule.SetChargeSlotActivationProgress(0f); } if (!IsChargeState(__instance, "Windup")) { s_chargeHoldStates.Remove(unityObjectInstanceId); } return; } if (!IsChargeState(__instance, "Windup")) { s_chargeHoldStates.Remove(unityObjectInstanceId); AbilityModule.SetChargeSlotActivationProgress(0f); return; } float num4 = Mathf.Max(0.2f, FeatureFlags.ChargeAbilityHoldSeconds); float progress2 = Mathf.Clamp01((Time.time - value2.StartTime) / num4); float minimumChargeReleaseScale2 = GetMinimumChargeReleaseScale(__instance); AbilityModule.SetChargeSlotActivationProgress(progress2, minimumChargeReleaseScale2); } if (value2.IsHolding && s_chargeHandlerWindupTimerField != null && s_chargeHandlerWindupTimeField != null) { float num6 = ((s_chargeHandlerWindupTimeField.GetValue(__instance) is float num5) ? num5 : 1.8f); s_chargeHandlerWindupTimerField.SetValue(__instance, Mathf.Max(0.01f, num6)); } } private static void PatchChargeAbilityHoldReleaseIfPossible(Harmony harmony, Assembly asm) { //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.Abilities.Charge.ChargeAbility", throwOnError: false); if (type == null) { return; } MethodInfo methodInfo = AccessTools.Method(type, "OnAbilityDown", Type.EmptyTypes, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(type, "OnAbilityUp", Type.EmptyTypes, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(type, "OnAbilityCancel", Type.EmptyTypes, (Type[])null); if (methodInfo2 == null) { return; } if ((object)s_chargeAbilityOnAbilityUpPrefixMethod == null) { s_chargeAbilityOnAbilityUpPrefixMethod = typeof(ChargeHoldReleaseModule).GetMethod("ChargeAbility_OnAbilityUp_Prefix", BindingFlags.Static | BindingFlags.NonPublic); } if (!(s_chargeAbilityOnAbilityUpPrefixMethod == null)) { if ((object)s_chargeAbilityOnAbilityDownPostfixMethod == null) { s_chargeAbilityOnAbilityDownPostfixMethod = typeof(ChargeHoldReleaseModule).GetMethod("ChargeAbility_OnAbilityDown_Postfix", BindingFlags.Static | BindingFlags.NonPublic); } if ((object)s_chargeAbilityOnAbilityCancelPostfixMethod == null) { s_chargeAbilityOnAbilityCancelPostfixMethod = typeof(ChargeHoldReleaseModule).GetMethod("ChargeAbility_OnAbilityCancel_Postfix", BindingFlags.Static | BindingFlags.NonPublic); } if (methodInfo != null && s_chargeAbilityOnAbilityDownPostfixMethod != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(s_chargeAbilityOnAbilityDownPostfixMethod), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(s_chargeAbilityOnAbilityUpPrefixMethod), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); if (methodInfo3 != null && s_chargeAbilityOnAbilityCancelPostfixMethod != null) { harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(s_chargeAbilityOnAbilityCancelPostfixMethod), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void PatchStunHandlerHoldScalingIfPossible(Harmony harmony, Assembly asm) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown Type type = asm.GetType("DeathHeadHopper.DeathHead.Handlers.StunHandler", throwOnError: false); if (type == null) { return; } if ((object)s_stunHandlerChargeHandlerField == null) { s_stunHandlerChargeHandlerField = AccessTools.Field(type, "chargeHandler"); } if ((object)s_stunHandlerStunDurationGetter == null) { s_stunHandlerStunDurationGetter = AccessTools.PropertyGetter(type, "StunDuration"); } if (!(s_stunHandlerStunDurationGetter == null)) { MethodInfo method = typeof(ChargeHoldReleaseModule).GetMethod("StunHandler_StunDuration_Prefix", BindingFlags.Static | BindingFlags.NonPublic); if (!(method == null)) { harmony.Patch((MethodBase)s_stunHandlerStunDurationGetter, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void ChargeHandler_CancelCharge_Postfix(object __instance) { ClearChargeHoldState(__instance); } private static bool ChargeHandler_EnemyHit_Prefix(object __instance) { if (__instance == null) { return true; } if (s_chargeHandlerEnemiesHitField == null || s_chargeHandlerEndChargeMethod == null || s_chargeHandlerAbilityLevelGetter == null) { return true; } int unityObjectInstanceId = GetUnityObjectInstanceId(__instance); if (unityObjectInstanceId == 0 || !s_chargeHoldStates.TryGetValue(unityObjectInstanceId, out ChargeHoldState value)) { return true; } if (!(s_chargeHandlerEnemiesHitField.GetValue(__instance) is int num) || 1 == 0) { return true; } int num2 = num + 1; s_chargeHandlerEnemiesHitField.SetValue(__instance, num2); int currentLevel = ((s_chargeHandlerAbilityLevelGetter.Invoke(__instance, null) is int num3) ? num3 : 0); int num4 = Mathf.FloorToInt(EvaluateStatWithDiminishingReturns(1f, 0.5f, currentLevel, 20, 0.9f).FinalValue); int num5 = Mathf.Max(1, Mathf.RoundToInt((float)num4 * Mathf.Clamp01(value.LaunchScale))); if (num2 >= num5) { s_chargeHandlerEndChargeMethod.Invoke(__instance, null); } return false; } private static bool StunHandler_StunDuration_Prefix(object __instance, ref float __result) { if (__instance == null) { return true; } if (s_stunHandlerChargeHandlerField == null || s_chargeHandlerAbilityLevelGetter == null) { return true; } object value = s_stunHandlerChargeHandlerField.GetValue(__instance); if (value == null) { return true; } int unityObjectInstanceId = GetUnityObjectInstanceId(value); if (unityObjectInstanceId == 0 || !s_chargeHoldStates.TryGetValue(unityObjectInstanceId, out ChargeHoldState value2)) { return true; } int num2 = ((s_chargeHandlerAbilityLevelGetter.Invoke(value, null) is int num) ? num : 0); float num3 = 5f + 1f * (float)num2; __result = num3 * Mathf.Clamp01(value2.LaunchScale); return false; } private static bool ChargeAbility_OnAbilityUp_Prefix() { return TryReleaseHeldCharge(); } private static void ChargeAbility_OnAbilityDown_Postfix() { s_lastLocalHoldInputStartTime = Time.time; s_localHoldInputPending = true; AbilityModule.SetChargeSlotActivationProgress(0f); object localChargeHandler = GetLocalChargeHandler(); if (localChargeHandler != null && !IsChargeState(localChargeHandler, "Windup")) { ClearChargeHoldState(localChargeHandler); } } private static void ChargeAbility_OnAbilityCancel_Postfix() { s_localHoldInputPending = false; s_localHoldUiActive = false; AbilityModule.SetChargeSlotActivationProgress(0f); object localChargeHandler = GetLocalChargeHandler(); if (localChargeHandler != null) { ClearChargeHoldState(localChargeHandler); } } private static bool TryReleaseHeldCharge() { object localChargeHandler = GetLocalChargeHandler(); if (localChargeHandler == null) { s_localHoldInputPending = false; s_localHoldUiActive = false; AbilityModule.SetChargeSlotActivationProgress(0f); return true; } if (!IsChargeState(localChargeHandler, "Windup")) { s_localHoldInputPending = false; s_localHoldUiActive = false; AbilityModule.SetChargeSlotActivationProgress(0f); return true; } int unityObjectInstanceId = GetUnityObjectInstanceId(localChargeHandler); if (unityObjectInstanceId == 0) { s_localHoldInputPending = false; s_localHoldUiActive = false; AbilityModule.SetChargeSlotActivationProgress(0f); return true; } if (!s_chargeHoldStates.TryGetValue(unityObjectInstanceId, out ChargeHoldState value)) { value = GetOrCreateChargeHoldState(unityObjectInstanceId); value.StartTime = ((s_lastLocalHoldInputStartTime > 0f) ? s_lastLocalHoldInputStartTime : Time.time); value.IsHolding = true; value.LaunchScale = 1f; } if (!value.IsHolding) { return true; } if (SemiFunc.IsMultiplayer() && !SemiFunc.IsMasterClientOrSingleplayer()) { if (!ConfigSyncManager.IsRemoteHostFixCompatible()) { s_localHoldInputPending = false; s_localHoldUiActive = false; AbilityModule.SetChargeSlotActivationProgress(0f); if (FeatureFlags.DebugLogging && LogLimiter.ShouldLog("Fix:Charge.PermissiveFallback", 120)) { Debug.Log((object)"[Fix:DHHCharge][PermissiveGate] Host fix marker missing. Falling back to vanilla release path."); } return true; } value.IsHolding = false; s_localHoldInputPending = false; s_localHoldUiActive = false; AbilityModule.SetChargeSlotActivationProgress(0f); SendRemoteReleaseCommand(localChargeHandler); return false; } float num = Mathf.Max(0.2f, FeatureFlags.ChargeAbilityHoldSeconds); float num2 = Mathf.Clamp01((Time.time - value.StartTime) / num); float minimumChargeReleaseScale = GetMinimumChargeReleaseScale(localChargeHandler); if (num2 < minimumChargeReleaseScale) { value.IsHolding = false; value.LaunchScale = 0f; s_localHoldInputPending = false; s_localHoldUiActive = false; AbilityModule.SetChargeSlotActivationProgress(0f); StopChargeWindupLoop(localChargeHandler); s_chargeHandlerCancelChargeMethod?.Invoke(localChargeHandler, null); return false; } value.IsHolding = false; value.LaunchScale = num2; if (s_chargeHandlerChargeStrengthField != null && s_chargeHandlerChargeStrengthField.GetValue(localChargeHandler) is float num3) { s_chargeHandlerChargeStrengthField.SetValue(localChargeHandler, num3 * num2); } if (s_chargeHandlerMaxBouncesField != null && s_chargeHandlerMaxBouncesField.GetValue(localChargeHandler) is float num4) { s_chargeHandlerMaxBouncesField.SetValue(localChargeHandler, Mathf.Max(0f, num4 * num2)); } if (s_chargeHandlerWindupTimerField != null) { s_chargeHandlerWindupTimerField.SetValue(localChargeHandler, -1f); } s_localHoldInputPending = false; s_localHoldUiActive = false; AbilityModule.SetChargeSlotActivationProgress(0f); return true; } private static bool ChargeHandler_UpdateWindupDirection_Prefix(object __instance, Vector3 chargeDirection) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (__instance == null) { return true; } if (!SemiFunc.IsMasterClientOrSingleplayer()) { return true; } if (Mathf.Abs(chargeDirection.x - -778f) < 0.001f) { s_chargeHandlerCancelChargeMethod?.Invoke(__instance, null); return false; } if (Mathf.Abs(chargeDirection.x - -777f) > 0.001f) { return true; } int unityObjectInstanceId = GetUnityObjectInstanceId(__instance); if (unityObjectInstanceId == 0 || !s_chargeHoldStates.TryGetValue(unityObjectInstanceId, out ChargeHoldState value)) { return false; } if (!IsChargeState(__instance, "Windup")) { return false; } float num = Mathf.Max(0.2f, FeatureFlags.ChargeAbilityHoldSeconds); float num2 = Mathf.Clamp01((Time.time - value.StartTime) / num); float minimumChargeReleaseScale = GetMinimumChargeReleaseScale(__instance); value.IsHolding = false; if (num2 < minimumChargeReleaseScale) { value.LaunchScale = 0f; s_chargeHandlerCancelChargeMethod?.Invoke(__instance, null); return false; } value.LaunchScale = num2; if (s_chargeHandlerChargeStrengthField != null && s_chargeHandlerChargeStrengthField.GetValue(__instance) is float num3) { s_chargeHandlerChargeStrengthField.SetValue(__instance, num3 * num2); } if (s_chargeHandlerMaxBouncesField != null && s_chargeHandlerMaxBouncesField.GetValue(__instance) is float num4) { s_chargeHandlerMaxBouncesField.SetValue(__instance, Mathf.Max(0f, num4 * num2)); } if (s_chargeHandlerWindupTimerField != null) { s_chargeHandlerWindupTimerField.SetValue(__instance, -1f); } return false; } private static void SendRemoteReleaseCommand(object chargeHandler) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) PhotonView val = GetDhhInputManagerHeadPhotonView(); if ((Object)(object)val == (Object)null || val.ViewID <= 0) { Component val2 = (Component)((chargeHandler is Component) ? chargeHandler : null); if (val2 != null) { val = val2.GetComponent<PhotonView>(); } } if (!((Object)(object)val == (Object)null) && val.ViewID > 0 && PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient) { val.RPC("UpdateWindupDirection", (RpcTarget)2, new object[1] { (object)new Vector3(-777f, 0f, 0f) }); } } private static void SendRemoteCancelCommand(object chargeHandler) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) PhotonView val = GetDhhInputManagerHeadPhotonView(); if ((Object)(object)val == (Object)null || val.ViewID <= 0) { Component val2 = (Component)((chargeHandler is Component) ? chargeHandler : null); if (val2 != null) { val = val2.GetComponent<PhotonView>(); } } if (!((Object)(object)val == (Object)null) && val.ViewID > 0 && PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient) { val.RPC("UpdateWindupDirection", (RpcTarget)2, new object[1] { (object)new Vector3(-778f, 0f, 0f) }); } } private static PhotonView? GetDhhInputManagerHeadPhotonView() { try { Type type = AccessTools.TypeByName("DeathHeadHopper.Managers.DHHInputManager"); if (type == null) { return null; } object? obj = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null); MonoBehaviour val = (MonoBehaviour)((obj is MonoBehaviour) ? obj : null); if ((Object)(object)val == (Object)null) { return null; } object? obj2 = type.GetField("headPhotonView", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val); return (PhotonView?)((obj2 is PhotonView) ? obj2 : null); } catch { return null; } } private static float GetMinimumChargeReleaseScale(object chargeHandler) { if (chargeHandler == null) { return 0f; } float num = 0f; if (s_chargeHandlerChargeStrengthField?.GetValue(chargeHandler) is float baseValue) { num = Mathf.Max(num, RequiredScaleForMinimumOne(baseValue)); } if (s_chargeHandlerMaxBouncesField?.GetValue(chargeHandler) is float baseValue2) { num = Mathf.Max(num, RequiredScaleForMinimumOne(baseValue2)); } if (TryGetEffectiveChargeAbilityLevel(chargeHandler, out var abilityLevel)) { int num2 = Mathf.FloorToInt(EvaluateStatWithDiminishingReturns(1f, 0.5f, abilityLevel, 20, 0.9f).FinalValue); float baseValue3 = 5f + 1f * (float)abilityLevel; num = Mathf.Max(num, RequiredScaleForMinimumOne(num2)); num = Mathf.Max(num, RequiredScaleForMinimumOne(baseValu