Decompiled source of DeathHeadHopperFix v0.1.9
plugins\DeathHeadHopperFix.dll
Decompiled 3 days 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.1.9")] 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 = (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(baseValue3)); } if (float.IsNaN(n