using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using HotbarPlus.Config; using HotbarPlus.Input; using HotbarPlus.Networking; using HotbarPlus.Patches; using LGUCustomUpgrades.HUD; using LGUCustomUpgrades.Patches; using LGUCustomUpgrades.Upgrades; using LethalHands; using Microsoft.CodeAnalysis; using MoreShipUpgrades.Managers; using MoreShipUpgrades.Misc.Upgrades; using MoreShipUpgrades.UI.TerminalNodes; using MoreShipUpgrades.UpgradeComponents.TierUpgrades; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("HotbarPlus")] [assembly: IgnoresAccessChecksTo("LethalHands")] [assembly: IgnoresAccessChecksTo("MoreShipUpgrades")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LGUCustomUpgrades")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Custom upgrades for LateGameUpgrades")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0+3423ac2532854e1dd50557f43abe79469809b434")] [assembly: AssemblyProduct("LGUCustomUpgrades")] [assembly: AssemblyTitle("LGUCustomUpgrades")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LGUCustomUpgrades { internal class PipeBombProjectile : MonoBehaviour { [CompilerGenerated] private sealed class d__29 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PipeBombProjectile <>4__this; private float 5__2; private float 5__3; private float 5__4; private float 5__5; private bool 5__6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__29(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; PipeBombProjectile pipeBombProjectile = <>4__this; switch (num) { default: return false; case 0: { <>1__state = -1; GameObject val = new GameObject("LGU_PipeBomb_BlinkLight"); val.transform.SetParent(((Component)pipeBombProjectile).transform, false); pipeBombProjectile._blinkLight = val.AddComponent(); pipeBombProjectile._blinkLight.type = (LightType)2; pipeBombProjectile._blinkLight.color = Color.red; pipeBombProjectile._blinkLight.intensity = 2f; pipeBombProjectile._blinkLight.range = 5f; pipeBombProjectile._blinkLight.shadows = (LightShadows)0; pipeBombProjectile._beepSource = ((Component)pipeBombProjectile).gameObject.AddComponent(); pipeBombProjectile._beepSource.spatialBlend = 1f; pipeBombProjectile._beepSource.minDistance = 1f; pipeBombProjectile._beepSource.maxDistance = 30f; pipeBombProjectile._beepSource.playOnAwake = false; 5__2 = Time.time; pipeBombProjectile._detonationTime = 5__2 + pipeBombProjectile._lureDuration; 5__3 = 0f; 5__4 = 0f; 5__5 = 0f; 5__6 = (Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsHost; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[PipeBomb] Lure started, duration={pipeBombProjectile._lureDuration}s, lure radius={pipeBombProjectile._lureRadius}"); } break; } case 1: <>1__state = -1; break; } if (Time.time < pipeBombProjectile._detonationTime) { float num2 = Mathf.Clamp01((Time.time - 5__2) / pipeBombProjectile._lureDuration); if (Time.time >= 5__4) { if ((Object)(object)pipeBombProjectile._blinkLight != (Object)null) { ((Behaviour)pipeBombProjectile._blinkLight).enabled = !((Behaviour)pipeBombProjectile._blinkLight).enabled; } 5__4 = Time.time + 0.3f; } if (Time.time >= 5__3) { if ((Object)(object)pipeBombProjectile._beepSource != (Object)null && (Object)(object)BeepClip != (Object)null) { pipeBombProjectile._beepSource.PlayOneShot(BeepClip); } float num3 = Mathf.Lerp(0.6f, 0.2f, num2); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)$"[PipeBomb] Beep played at interval {num3:F2}s"); } 5__3 = Time.time + num3; } if (5__6 && Time.time >= 5__5) { pipeBombProjectile.LureNearbyEnemies(); 5__5 = Time.time + 0.2f; } <>2__current = null; <>1__state = 1; return true; } pipeBombProjectile.Detonate(); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const float MAX_AIRBORNE_TIME = 5f; private const float LURE_POLL_INTERVAL = 0.2f; private const float BLINK_INTERVAL = 0.3f; private const float BEEP_START_INTERVAL = 0.6f; private const float BEEP_END_INTERVAL = 0.2f; internal static readonly List ActiveBombs = new List(); internal static AudioClip BeepClip; private static Mesh _cachedMesh; private static Material _cachedMaterial; private static bool _meshScanned; private Rigidbody _rb; private Light _blinkLight; private AudioSource _beepSource; private bool _hasLanded; private bool _detonated; private float _spawnTime; private Vector3 _bombPosition; internal float _detonationTime; private float _lureRadius; private float _lureDuration; private float _blastRadius; private int _enemyDamage; private int _playerDamage; public static GameObject Spawn(Vector3 position, Vector3 direction, float throwForce) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0011: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("LGU_PipeBomb"); val.transform.position = position; SphereCollider obj = val.AddComponent(); obj.radius = 0.15f; ((Collider)obj).isTrigger = false; Rigidbody val2 = val.AddComponent(); val2.useGravity = true; val2.mass = 0.3f; val2.drag = 0.1f; val2.collisionDetectionMode = (CollisionDetectionMode)2; AttachVisual(val.transform); PipeBombProjectile pipeBombProjectile = val.AddComponent(); pipeBombProjectile._rb = val2; pipeBombProjectile._spawnTime = Time.time; pipeBombProjectile._lureRadius = Plugin.PipeBombLureRadius.Value; pipeBombProjectile._lureDuration = Plugin.PipeBombLureDuration.Value; pipeBombProjectile._blastRadius = Plugin.PipeBombBlastRadius.Value; pipeBombProjectile._enemyDamage = Plugin.PipeBombEnemyDamage.Value; pipeBombProjectile._playerDamage = Plugin.PipeBombPlayerDamage.Value; val2.AddForce(((Vector3)(ref direction)).normalized * throwForce, (ForceMode)2); ActiveBombs.Add(pipeBombProjectile); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[PipeBomb] Projectile spawned at ({position.x:F2},{position.y:F2},{position.z:F2}) with force ({((Vector3)(ref direction)).normalized.x * throwForce:F2},{((Vector3)(ref direction)).normalized.y * throwForce:F2},{((Vector3)(ref direction)).normalized.z * throwForce:F2})"); } return val; } private static void AttachVisual(Transform parent) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) EnsureMeshCached(); GameObject val = new GameObject("Visual"); val.transform.SetParent(parent, false); val.transform.localScale = Vector3.one * 0.6f; if ((Object)(object)_cachedMesh != (Object)null && (Object)(object)_cachedMaterial != (Object)null) { val.AddComponent().sharedMesh = _cachedMesh; ((Renderer)val.AddComponent()).sharedMaterial = _cachedMaterial; } } private static void EnsureMeshCached() { if (_meshScanned) { return; } _meshScanned = true; StunGrenadeItem[] array = Resources.FindObjectsOfTypeAll(); foreach (StunGrenadeItem val in array) { if ((Object)(object)val == (Object)null) { continue; } MeshFilter componentInChildren = ((Component)val).GetComponentInChildren(true); MeshRenderer componentInChildren2 = ((Component)val).GetComponentInChildren(true); if (!((Object)(object)componentInChildren == (Object)null) && !((Object)(object)componentInChildren2 == (Object)null) && !((Object)(object)componentInChildren.sharedMesh == (Object)null) && !((Object)(object)((Renderer)componentInChildren2).sharedMaterial == (Object)null)) { _cachedMesh = componentInChildren.sharedMesh; _cachedMaterial = ((Renderer)componentInChildren2).sharedMaterial; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[PipeBomb] Borrowed mesh '" + ((Object)_cachedMesh).name + "' from StunGrenadeItem.")); } return; } } ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)"[PipeBomb] Could not borrow stun grenade mesh — projectile will be invisible mid-flight."); } } private void Update() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!_hasLanded && Time.time - _spawnTime >= 5f) { Land(((Component)this).transform.position); } } private void OnCollisionEnter(Collision collision) { //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_0036: Unknown result type (might be due to invalid IL or missing references) if (!_hasLanded && (!((Object)(object)collision.collider != (Object)null) || !((Object)(object)((Component)collision.collider).GetComponentInParent() != (Object)null))) { ContactPoint contact = collision.GetContact(0); Land(((ContactPoint)(ref contact)).point); } } private void Land(Vector3 position) { //IL_0011: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) if (!_hasLanded) { _hasLanded = true; _bombPosition = position; ((Component)this).transform.position = position; if ((Object)(object)_rb != (Object)null) { _rb.velocity = Vector3.zero; _rb.angularVelocity = Vector3.zero; _rb.isKinematic = true; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[PipeBomb] Projectile landed at ({position.x:F2},{position.y:F2},{position.z:F2})"); } ((MonoBehaviour)this).StartCoroutine(LureLoop()); } } [IteratorStateMachine(typeof(d__29))] private IEnumerator LureLoop() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__29(0) { <>4__this = this }; } private void LureNearbyEnemies() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) Collider[] array = Physics.OverlapSphere(_bombPosition, _lureRadius); HashSet hashSet = new HashSet(); foreach (Collider val in array) { if ((Object)(object)val == (Object)null) { continue; } EnemyAI componentInParent = ((Component)val).GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null || componentInParent.isEnemyDead || !hashSet.Add(componentInParent)) { continue; } try { componentInParent.targetPlayer = null; componentInParent.movingTowardsTargetPlayer = false; componentInParent.SetDestinationToPosition(_bombPosition, false); if ((Object)(object)componentInParent.agent != (Object)null && componentInParent.agent.isOnNavMesh) { componentInParent.agent.SetDestination(_bombPosition); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[PipeBomb] Lure call failed on " + ((object)componentInParent).GetType().Name + ": " + ex.Message)); } } } ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)$"[PipeBomb] Lure pulse: found {hashSet.Count} enemies in radius"); } } private void Detonate() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (_detonated) { return; } _detonated = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[PipeBomb] Detonation at ({_bombPosition.x:F2},{_bombPosition.y:F2},{_bombPosition.z:F2})"); } try { float num = _blastRadius * 0.5f; float blastRadius = _blastRadius; Landmine.SpawnExplosion(_bombPosition, true, num, blastRadius, _playerDamage, 80f, (GameObject)null, false); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)$"[PipeBomb] Landmine.SpawnExplosion called (killRange={num}, damageRange={blastRadius}, nonLethalDamage={_playerDamage})"); } } catch (Exception arg) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogError((object)$"[PipeBomb] Landmine.SpawnExplosion threw: {arg}"); } } ActiveBombs.Remove(this); Object.Destroy((Object)(object)((Component)this).gameObject); ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogInfo((object)"[PipeBomb] Cleanup complete"); } } private void OnDestroy() { ActiveBombs.Remove(this); } public static void DestroyAllActive() { PipeBombProjectile[] array = ActiveBombs.ToArray(); for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && (Object)(object)((Component)array[i]).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)array[i]).gameObject); } } ActiveBombs.Clear(); } } [BepInPlugin("LGUCustomUpgrades", "LGU Custom Upgrades", "1.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private const string MOD_GUID = "LGUCustomUpgrades"; private const string MOD_NAME = "LGU Custom Upgrades"; private const string MOD_VERSION = "1.4.0"; public static ManualLogSource Log; internal static List NetworkPrefabs = new List(); private readonly Harmony harmony = new Harmony("LGUCustomUpgrades"); public static ConfigEntry FlareBurstKeybind; public static ConfigEntry ShadowStepKeybind; public static ConfigEntry EscapeProtocolKeybind; public static ConfigEntry PipeBombKeybind; public static ConfigEntry PipeBombEnabled; public static ConfigEntry PipeBombPriceT1; public static ConfigEntry PipeBombPriceT2; public static ConfigEntry PipeBombPriceT3; public static ConfigEntry PipeBombChargesT1; public static ConfigEntry PipeBombChargesT2; public static ConfigEntry PipeBombChargesT3; public static ConfigEntry PipeBombLureRadius; public static ConfigEntry PipeBombLureDuration; public static ConfigEntry PipeBombBlastRadius; public static ConfigEntry PipeBombEnemyDamage; public static ConfigEntry PipeBombPlayerDamage; public static ConfigEntry PipeBombCooldown; public static ConfigEntry PipeBombThrowForce; private static Key? _flareBurstKey; private static Key? _shadowStepKey; private static Key? _escapeProtocolKey; private static Key? _pipeBombKey; private static bool _keysResolved = false; private static readonly HashSet ReservedHashes = new HashSet { 0u, 581939109u }; private static readonly HashSet AssignedHashes = new HashSet(); private void Awake() { Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"LGU Custom Upgrades loading..."); FlareBurstKeybind = ((BaseUnityPlugin)this).Config.Bind("Keybinds", "Flare Burst Key", "v", "Key to activate Flare Burst. Use Unity InputSystem Key names: v, g, b, f, t, r, x, c, z, q, capslock, tab, etc."); ShadowStepKeybind = ((BaseUnityPlugin)this).Config.Bind("Keybinds", "Shadow Step Key", "g", "Key to activate Shadow Step invisibility. Use Unity InputSystem Key names: v, g, b, f, t, r, x, c, z, q, capslock, tab, etc."); EscapeProtocolKeybind = ((BaseUnityPlugin)this).Config.Bind("Keybinds", "Escape Protocol Key", "h", "Key to toggle Escape Protocol exit markers. Use Unity InputSystem Key names: v, g, b, f, t, r, x, c, z, q, capslock, tab, etc."); PipeBombKeybind = ((BaseUnityPlugin)this).Config.Bind("Keybinds", "Pipe Bomb Key", "g", "Key to throw a Pipe Bomb. Use Unity InputSystem Key names: v, g, b, f, t, r, x, c, z, q, capslock, tab, etc."); PipeBombEnabled = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Enabled", true, "Enable the Pipe Bomb upgrade."); PipeBombPriceT1 = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Price Tier 1", 80, "BXP cost for Tier 1."); PipeBombPriceT2 = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Price Tier 2", 120, "BXP cost for Tier 2."); PipeBombPriceT3 = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Price Tier 3", 160, "BXP cost for Tier 3."); PipeBombChargesT1 = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Charges Tier 1", 1, "Charges per round at Tier 1."); PipeBombChargesT2 = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Charges Tier 2", 2, "Charges per round at Tier 2."); PipeBombChargesT3 = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Charges Tier 3", 3, "Charges per round at Tier 3."); PipeBombLureRadius = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Lure Radius", 25f, "Radius in units for attracting enemies."); PipeBombLureDuration = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Lure Duration", 4.5f, "Seconds before detonation."); PipeBombBlastRadius = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Blast Radius", 8f, "Radius in units for detonation damage."); PipeBombEnemyDamage = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Enemy Damage", 3, "Damage dealt to enemies (HitEnemy hit count)."); PipeBombPlayerDamage = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Player Damage", 60, "Damage dealt to players (HP, 0-100)."); PipeBombCooldown = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Cooldown", 10f, "Seconds between throws."); PipeBombThrowForce = ((BaseUnityPlugin)this).Config.Bind("Pipe Bomb", "Throw Force", 18f, "Projectile launch force."); _flareBurstKey = ParseKey(FlareBurstKeybind.Value); _shadowStepKey = ParseKey(ShadowStepKeybind.Value); _escapeProtocolKey = ParseKey(EscapeProtocolKeybind.Value); _pipeBombKey = ParseKey(PipeBombKeybind.Value); _keysResolved = true; Log.LogInfo((object)("Keybinds: Flare Burst=[" + FlareBurstKeybind.Value + "] ShadowStep=[" + ShadowStepKeybind.Value + "] EscapeProtocol=[" + EscapeProtocolKeybind.Value + "] PipeBomb=[" + PipeBombKeybind.Value + "]")); Plugin.CreateUpgradePrefab("Spatial Awareness"); Plugin.CreateUpgradePrefab("Lone Wolf"); Plugin.CreateUpgradePrefab("Salvager"); Plugin.CreateUpgradePrefab("Lethal Hands Training"); Plugin.CreateUpgradePrefab("Retaliation"); Plugin.CreateUpgradePrefab("Flare Burst"); Plugin.CreateUpgradePrefab("Predator Instinct"); Plugin.CreateUpgradePrefab("Shadow Step"); Plugin.CreateUpgradePrefab("Adrenaline Rush"); Plugin.CreateUpgradePrefab("Squad Sight"); Plugin.CreateUpgradePrefab("Glow in the Dark"); Plugin.CreateUpgradePrefab("Escape Protocol"); Plugin.CreateUpgradePrefab("Extra Inventory Slot"); if (PipeBombEnabled.Value) { Plugin.CreateUpgradePrefab("Pipe Bomb"); } UpgradeBus.Instance.upgradeTypes.Add(typeof(SpatialAwarenessUpgrade)); UpgradeBus.Instance.upgradeTypes.Add(typeof(LoneWolfUpgrade)); UpgradeBus.Instance.upgradeTypes.Add(typeof(SalvagerUpgrade)); UpgradeBus.Instance.upgradeTypes.Add(typeof(LethalHandsUpgrade)); UpgradeBus.Instance.upgradeTypes.Add(typeof(RetaliationUpgrade)); UpgradeBus.Instance.upgradeTypes.Add(typeof(FlareBurstUpgrade)); UpgradeBus.Instance.upgradeTypes.Add(typeof(PredatorInstinctUpgrade)); UpgradeBus.Instance.upgradeTypes.Add(typeof(ShadowStepUpgrade)); UpgradeBus.Instance.upgradeTypes.Add(typeof(AdrenalineRushUpgrade)); UpgradeBus.Instance.upgradeTypes.Add(typeof(SquadSightUpgrade)); UpgradeBus.Instance.upgradeTypes.Add(typeof(GlowInTheDarkUpgrade)); UpgradeBus.Instance.upgradeTypes.Add(typeof(EscapeProtocolUpgrade)); UpgradeBus.Instance.upgradeTypes.Add(typeof(ExtraSlotUpgrade)); if (PipeBombEnabled.Value) { UpgradeBus.Instance.upgradeTypes.Add(typeof(PipeBombUpgrade)); } harmony.PatchAll(); Log.LogInfo((object)"LGU Custom Upgrades loaded successfully!"); } public static Key? GetFlareBurstKey() { return _flareBurstKey; } public static Key? GetShadowStepKey() { return _shadowStepKey; } public static Key? GetEscapeProtocolKey() { return _escapeProtocolKey; } public static Key? GetPipeBombKey() { return _pipeBombKey; } private static Key? ParseKey(string keyName) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(keyName)) { return null; } if (Enum.TryParse(keyName, ignoreCase: true, out Key result)) { return result; } switch (keyName.ToLower().Trim()) { case "a": return (Key)15; case "b": return (Key)16; case "c": return (Key)17; case "d": return (Key)18; case "e": return (Key)19; case "f": return (Key)20; case "g": return (Key)21; case "h": return (Key)22; case "i": return (Key)23; case "j": return (Key)24; case "k": return (Key)25; case "l": return (Key)26; case "m": return (Key)27; case "n": return (Key)28; case "p": return (Key)30; case "q": return (Key)31; case "r": return (Key)32; case "s": return (Key)33; case "t": return (Key)34; case "u": return (Key)35; case "v": return (Key)36; case "w": return (Key)37; case "x": return (Key)38; case "y": return (Key)39; case "z": return (Key)40; case "capslock": case "caps": return (Key)72; case "tab": return (Key)3; case "space": return (Key)1; case "f1": return (Key)94; case "f2": return (Key)95; case "f3": return (Key)96; case "f4": return (Key)97; case "f5": return (Key)98; case "f6": return (Key)99; case "f7": return (Key)100; case "f8": return (Key)101; default: { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("ParseKey: unrecognised key name '" + keyName + "'. Ability will use its default key.")); } return null; } } } internal static void CreateUpgradePrefab(string name) where T : BaseUpgrade { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown GameObject val = new GameObject(name); NetworkObject netObj = val.AddComponent(); val.AddComponent(); ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); uint num = GenerateUniqueHash(name); AssignGlobalObjectIdHash(netObj, num); NetworkPrefabs.Add(val); if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey(name)) { UpgradeBus.Instance.UpgradeObjects.Add(name, val); } ManualLogSource log = Log; if (log != null) { log.LogInfo((object)$"Registered upgrade prefab '{name}' with GlobalObjectIdHash={num}"); } } private static uint GenerateUniqueHash(string prefabName) { string name = Assembly.GetExecutingAssembly().GetName().Name; uint num = ComputeHash(name + ":" + prefabName); int num2 = 0; while (ReservedHashes.Contains(num) || AssignedHashes.Contains(num)) { num2++; num = ComputeHash($"{name}:{prefabName}:{num2}"); if (num2 > 1000) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("GenerateUniqueHash: could not find unique hash for '" + prefabName + "' after 1000 salts.")); } break; } } AssignedHashes.Add(num); return num; } private static uint ComputeHash(string input) { using MD5 mD = MD5.Create(); return BitConverter.ToUInt32(mD.ComputeHash(Encoding.UTF8.GetBytes(input)), 0); } private static void AssignGlobalObjectIdHash(NetworkObject netObj, uint hash) { Type typeFromHandle = typeof(NetworkObject); PropertyInfo property = typeFromHandle.GetProperty("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanWrite) { property.SetValue(netObj, hash); return; } FieldInfo field = typeFromHandle.GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(netObj, hash); return; } FieldInfo field2 = typeFromHandle.GetField("k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); if (field2 != null) { field2.SetValue(netObj, hash); return; } ManualLogSource log = Log; if (log != null) { log.LogError((object)"Could not find NetworkObject.GlobalObjectIdHash via reflection. Multiplayer spawn will fail."); } } } [HarmonyPatch(typeof(GameNetworkManager), "Start")] internal static class GameNetworkManagerStartPatch { [HarmonyPostfix] private static void RegisterNetworkPrefabs() { foreach (GameObject networkPrefab in Plugin.NetworkPrefabs) { if (!NetworkManager.Singleton.NetworkConfig.Prefabs.Contains(networkPrefab)) { NetworkManager.Singleton.AddNetworkPrefab(networkPrefab); } } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "LGUCustomUpgrades"; public const string PLUGIN_NAME = "LGUCustomUpgrades"; public const string PLUGIN_VERSION = "1.1.0"; } } namespace LGUCustomUpgrades.Upgrades { internal class AdrenalineRushUpgrade : TierUpgrade { public const string UPGRADE_NAME = "Adrenaline Rush"; public const int INITIAL_PRICE = 20; public static readonly int[] TIER_PRICES = new int[1] { 30 }; public const int LOW_HP_THRESHOLD = 20; public const float SPEED_MULTIPLIER = 1.3f; public const float INVINCIBILITY_SECONDS = 2f; public static bool IsAdrenalineActive = false; public static bool InsuranceUsedThisRound = false; public static bool IsInvincible = false; public static float InvincibilityEndTime = 0f; public static float OriginalSpeed = 0f; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Adrenaline Rush"; ((BaseUpgrade)this).overridenUpgradeName = "Adrenaline Rush"; } public override string GetDisplayInfo(int initialPrice = -1, int maxLevels = -1, int[] incrementalPrices = null) { string text = ""; text += $"${initialPrice} - Level 1: Below 20 HP, gain +30% movement speed and a danger vignette.\n"; if (incrementalPrices != null && incrementalPrices.Length != 0) { text += $"${incrementalPrices[0]} - Level 2: Survive one lethal hit per round at 1HP + 2s invincibility (enemy/trap only).\n"; } return text; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Adrenaline Rush", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Adrenaline Rush")) { return null; } return UpgradeBus.Instance.SetupMultiplePurchasableTerminalNode("Adrenaline Rush", false, true, 20, TIER_PRICES, "", UpgradeBus.Instance.UpgradeObjects["Adrenaline Rush"], true, (PurchaseMode)0, false, 1f); } public static bool IsUnlocked() { return BaseUpgrade.GetActiveUpgrade("Adrenaline Rush"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return BaseUpgrade.GetUpgradeLevel("Adrenaline Rush") + 1; } public static bool HasInsurance() { return GetTier() >= 2; } public override void __initializeVariables() { ((TierUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((TierUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "AdrenalineRushUpgrade"; } } internal class EscapeProtocolUpgrade : OneTimeUpgrade { public const string UPGRADE_NAME = "Escape Protocol"; public const int PRICE = 25; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Escape Protocol"; ((BaseUpgrade)this).overridenUpgradeName = "Escape Protocol"; } public override string GetDisplayInfo(int price = -1) { return $"${price} - Toggle to reveal all exits through walls with real-time distance readouts."; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Escape Protocol", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Escape Protocol")) { return null; } return UpgradeBus.Instance.SetupOneTimeTerminalNode("Escape Protocol", false, true, 25, "", UpgradeBus.Instance.UpgradeObjects["Escape Protocol"], true, (PurchaseMode)0, false, 1f); } public static bool IsUnlocked() { return BaseUpgrade.GetActiveUpgrade("Escape Protocol"); } public override void __initializeVariables() { ((OneTimeUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((OneTimeUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "EscapeProtocolUpgrade"; } } internal class ExtraSlotUpgrade : TierUpgrade { public const string UPGRADE_NAME = "Extra Inventory Slot"; public const int INITIAL_PRICE = 25; public static readonly int[] TIER_PRICES = new int[2] { 25, 25 }; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Extra Inventory Slot"; ((BaseUpgrade)this).overridenUpgradeName = "Extra Inventory Slot"; } public override void Load() { ((BaseUpgrade)this).Load(); try { int num = BaseUpgrade.GetUpgradeLevel("Extra Inventory Slot") + 1; PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null) { ExtraSlotManager.BroadcastBonusSlots(val.actualClientId, num); Plugin.Log.LogInfo((object)$"ExtraSlot: Load() — broadcasting tier {num} for local player"); } } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlot: Load() failed: {arg}"); } } public override void Increment() { ((TierUpgrade)this).Increment(); try { int num = BaseUpgrade.GetUpgradeLevel("Extra Inventory Slot") + 1; PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null) { ExtraSlotManager.BroadcastBonusSlots(val.actualClientId, num); Plugin.Log.LogInfo((object)$"ExtraSlot: Increment() — broadcasting tier {num} for local player"); } } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlot: Increment() failed: {arg}"); } } public override void Unwind() { ((TierUpgrade)this).Unwind(); try { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null) { ExtraSlotManager.BroadcastBonusSlots(val.actualClientId, 0); Plugin.Log.LogInfo((object)"ExtraSlot: Unwind() — clearing bonus for local player"); } } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlot: Unwind() failed: {arg}"); } } public override string GetDisplayInfo(int initialPrice = -1, int maxLevels = -1, int[] incrementalPrices = null) { string text = "EXTRA INVENTORY SLOT\nExpands your suit's carrying capacity with modular storage compartments.\n\n"; text += $"${initialPrice} - Tier 1: +1 inventory slot.\n"; if (incrementalPrices != null && incrementalPrices.Length != 0) { text += $"${incrementalPrices[0]} - Tier 2: +1 inventory slot (total +2).\n"; } if (incrementalPrices != null && incrementalPrices.Length > 1) { text += $"${incrementalPrices[1]} - Tier 3: +1 inventory slot (total +3).\n"; } return text + "\n\"More pockets, more problems -- but mostly more pockets.\"\n"; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Extra Inventory Slot", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Extra Inventory Slot")) { return null; } return UpgradeBus.Instance.SetupMultiplePurchasableTerminalNode("Extra Inventory Slot", false, true, 25, TIER_PRICES, "", UpgradeBus.Instance.UpgradeObjects["Extra Inventory Slot"], true, (PurchaseMode)0, false, 1f); } public override void __initializeVariables() { ((TierUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((TierUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "ExtraSlotUpgrade"; } } internal class FlareBurstUpgrade : TierUpgrade { public const string UPGRADE_NAME = "Flare Burst"; public const int INITIAL_PRICE = 15; public static readonly int[] TIER_PRICES = new int[2] { 22, 30 }; public static readonly float[] RADIUS_BY_LEVEL = new float[3] { 15f, 25f, 25f }; public static readonly float[] STUN_BY_LEVEL = new float[3] { 3f, 5f, 5f }; public const float TIER3_FLEE_SECONDS = 4f; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Flare Burst"; ((BaseUpgrade)this).overridenUpgradeName = "Flare Burst"; } public override string GetDisplayInfo(int initialPrice = -1, int maxLevels = -1, int[] incrementalPrices = null) { string text = ""; text += $"${initialPrice} - Level 1: Press [V] to flash a 15m AOE that stuns enemies for 3s. One use per round.\n"; if (incrementalPrices != null && incrementalPrices.Length != 0) { text += $"${incrementalPrices[0]} - Level 2: Radius increases to 25m, stun to 5s.\n"; } if (incrementalPrices != null && incrementalPrices.Length > 1) { text += $"${incrementalPrices[1]} - Level 3: After the stun, hit enemies flee for 4s.\n"; } return text; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Flare Burst", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Flare Burst")) { return null; } return UpgradeBus.Instance.SetupMultiplePurchasableTerminalNode("Flare Burst", false, true, 15, TIER_PRICES, "", UpgradeBus.Instance.UpgradeObjects["Flare Burst"], true, (PurchaseMode)0, false, 1f); } public static bool IsUnlocked() { return BaseUpgrade.GetActiveUpgrade("Flare Burst"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return BaseUpgrade.GetUpgradeLevel("Flare Burst") + 1; } public static float GetRadius() { int tier = GetTier(); if (tier <= 0) { return 0f; } return RADIUS_BY_LEVEL[tier - 1]; } public static float GetStunSeconds() { int tier = GetTier(); if (tier <= 0) { return 0f; } return STUN_BY_LEVEL[tier - 1]; } public static bool ShouldFlee() { return GetTier() >= 3; } public static bool IsMaxTier() { return GetTier() >= 3; } public override void __initializeVariables() { ((TierUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((TierUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "FlareBurstUpgrade"; } } internal class GlowInTheDarkUpgrade : OneTimeUpgrade { public const string UPGRADE_NAME = "Glow in the Dark"; public const int PRICE = 25; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Glow in the Dark"; ((BaseUpgrade)this).overridenUpgradeName = "Glow in the Dark"; } public override string GetDisplayInfo(int price = -1) { return $"${price} - A soft ambient glow radiates from your body, illuminating the area around you."; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Glow in the Dark", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Glow in the Dark")) { return null; } return UpgradeBus.Instance.SetupOneTimeTerminalNode("Glow in the Dark", false, true, 25, "", UpgradeBus.Instance.UpgradeObjects["Glow in the Dark"], true, (PurchaseMode)0, false, 1f); } public static bool IsUnlocked() { return BaseUpgrade.GetActiveUpgrade("Glow in the Dark"); } public override void __initializeVariables() { ((OneTimeUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((OneTimeUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "GlowInTheDarkUpgrade"; } } internal class LethalHandsUpgrade : TierUpgrade { public const string UPGRADE_NAME = "Lethal Hands Training"; public const int INITIAL_PRICE = 15; public static readonly int[] TIER_PRICES = new int[2] { 22, 30 }; private const float TIER_1_DAMAGE = 0.5f; private const float TIER_2_DAMAGE = 1f; private const float TIER_3_DAMAGE = 1.5f; public const float TIER_3_STUN_SECONDS = 1f; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Lethal Hands Training"; ((BaseUpgrade)this).overridenUpgradeName = "Lethal Hands Training"; } public override string GetDisplayInfo(int initialPrice = -1, int maxLevels = -1, int[] incrementalPrices = null) { string text = ""; text += $"${initialPrice} - Tier 1: Unlocks empty-handed punching (LMB / RMB). 50% shovel damage.\n"; if (incrementalPrices != null && incrementalPrices.Length != 0) { text += $"${incrementalPrices[0]} - Tier 2: Punch damage increased to 100% shovel damage.\n"; } if (incrementalPrices != null && incrementalPrices.Length > 1) { text += $"${incrementalPrices[1]} - Tier 3: 150% shovel damage and stuns enemies on hit.\n"; } return text; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Lethal Hands Training", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Lethal Hands Training")) { return null; } return UpgradeBus.Instance.SetupMultiplePurchasableTerminalNode("Lethal Hands Training", false, true, 15, TIER_PRICES, "", UpgradeBus.Instance.UpgradeObjects["Lethal Hands Training"], true, (PurchaseMode)0, false, 1f); } public static float GetCurrentDamageMultiplier() { if (!BaseUpgrade.GetActiveUpgrade("Lethal Hands Training")) { return 0f; } return BaseUpgrade.GetUpgradeLevel("Lethal Hands Training") switch { 0 => 0.5f, 1 => 1f, 2 => 1.5f, _ => 1.5f, }; } public static bool ShouldStun() { if (!BaseUpgrade.GetActiveUpgrade("Lethal Hands Training")) { return false; } return BaseUpgrade.GetUpgradeLevel("Lethal Hands Training") >= 2; } public static bool IsUnlocked() { return BaseUpgrade.GetActiveUpgrade("Lethal Hands Training"); } public override void __initializeVariables() { ((TierUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((TierUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "LethalHandsUpgrade"; } } internal class LoneWolfUpgrade : TierUpgrade { [CompilerGenerated] private sealed class d__21 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PlayerControllerB player; private List 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: { <>1__state = -1; EnemyAI[] array = Object.FindObjectsOfType(); 5__2 = new List(); EnemyAI[] array2 = array; foreach (EnemyAI val in array2) { if (!((Object)(object)val == (Object)null) && !val.isEnemyDead && !(Vector3.Distance(((Component)val).transform.position, ((Component)player).transform.position) > 30f)) { Light val2 = ((Component)val).gameObject.AddComponent(); val2.type = (LightType)2; val2.color = new Color(1f, 0.2f, 0.2f); val2.intensity = 4f; val2.range = 10f; 5__2.Add(val2); } } if (5__2.Count > 0) { Plugin.Log.LogDebug((object)$"Lone Wolf Level 3: Revealed {5__2.Count} nearby enemies."); } <>2__current = (object)new WaitForSeconds(5f); <>1__state = 1; return true; } case 1: <>1__state = -1; foreach (Light item in 5__2) { if ((Object)(object)item != (Object)null) { Object.Destroy((Object)(object)item); } } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string UPGRADE_NAME = "Lone Wolf"; public const int INITIAL_PRICE = 15; public static readonly int[] TIER_PRICES = new int[2] { 22, 30 }; private const float SPEED_MULTIPLIER = 0.3f; private const float STAMINA_RECOVERY_RATE = 0.015f; private const float ENEMY_REVEAL_RANGE = 30f; private const float ENEMY_REVEAL_DURATION = 5f; internal static bool LoneWolfActive = false; internal static int ActiveLevel = 0; private static float speedBonus = 0f; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Lone Wolf"; ((BaseUpgrade)this).overridenUpgradeName = "Lone Wolf"; } public override string GetDisplayInfo(int initialPrice = -1, int maxLevels = -1, int[] incrementalPrices = null) { string text = ""; text += $"${initialPrice} - Level 1: When last surviving player on moon, +30% movement speed.\n"; if (incrementalPrices != null && incrementalPrices.Length != 0) { text += $"${incrementalPrices[0]} - Level 2: Also reduces stamina drain significantly.\n"; } if (incrementalPrices != null && incrementalPrices.Length > 1) { text += $"${incrementalPrices[1]} - Level 3: Also briefly reveals nearby enemy positions.\n"; } return text; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Lone Wolf", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Lone Wolf")) { return null; } return UpgradeBus.Instance.SetupMultiplePurchasableTerminalNode("Lone Wolf", false, true, 15, TIER_PRICES, "", UpgradeBus.Instance.UpgradeObjects["Lone Wolf"], true, (PurchaseMode)0, false, 1f); } internal static void CheckAndActivate() { if (!BaseUpgrade.GetActiveUpgrade("Lone Wolf") || LoneWolfActive) { return; } PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null || localPlayerController.isPlayerDead || localPlayerController.isInHangarShipRoom) { return; } int num = 0; for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++) { PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[i]; if (val.isPlayerControlled && !val.isPlayerDead && !val.isInHangarShipRoom) { num++; } } if (num == 1) { int level = BaseUpgrade.GetUpgradeLevel("Lone Wolf") + 1; ActivateLoneWolf(localPlayerController, level); } } private static void ActivateLoneWolf(PlayerControllerB player, int level) { speedBonus = player.movementSpeed * 0.3f; player.movementSpeed += speedBonus; LoneWolfActive = true; ActiveLevel = level; Plugin.Log.LogInfo((object)$"Lone Wolf activated! Level {level}, speed bonus: {speedBonus:F2}"); HUDManager.Instance.DisplayTip("LONE WOLF", GetActivationMessage(level), false, false, "LC_Tip1"); if (level >= 3) { ((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(RevealNearbyEnemies(player)); } } private static string GetActivationMessage(int level) { return level switch { 1 => "You're the last one standing. Movement speed increased.", 2 => "You're the last one standing. Speed and stamina enhanced.", 3 => "You're the last one standing. Full survival mode activated.", _ => "Lone Wolf activated.", }; } internal static void Deactivate() { if (!LoneWolfActive) { return; } PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if ((Object)(object)localPlayerController != (Object)null) { localPlayerController.movementSpeed -= speedBonus; if (localPlayerController.movementSpeed < 4f) { localPlayerController.movementSpeed = 4.6f; } } speedBonus = 0f; LoneWolfActive = false; ActiveLevel = 0; Plugin.Log.LogDebug((object)"Lone Wolf deactivated."); } [IteratorStateMachine(typeof(d__21))] private static IEnumerator RevealNearbyEnemies(PlayerControllerB player) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__21(0) { player = player }; } internal static void ApplyStaminaBonus(PlayerControllerB player) { if (LoneWolfActive && ActiveLevel >= 2 && !((Object)(object)player == (Object)null) && !player.isPlayerDead) { player.sprintMeter = Mathf.Clamp01(player.sprintMeter + Time.deltaTime * 0.015f); } } public override void __initializeVariables() { ((TierUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((TierUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "LoneWolfUpgrade"; } } internal class PipeBombUpgrade : TierUpgrade { public const string UPGRADE_NAME = "Pipe Bomb"; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Pipe Bomb"; ((BaseUpgrade)this).overridenUpgradeName = "Pipe Bomb"; } public override string GetDisplayInfo(int initialPrice = -1, int maxLevels = -1, int[] incrementalPrices = null) { string arg = Plugin.PipeBombKeybind?.Value?.ToUpperInvariant() ?? "G"; string text = ""; text += $"${initialPrice} - Level 1: Press [{arg}] to throw a pipe bomb that lures enemies, then detonates. 1 charge per round.\n"; if (incrementalPrices != null && incrementalPrices.Length != 0) { text += $"${incrementalPrices[0]} - Level 2: 2 charges per round.\n"; } if (incrementalPrices != null && incrementalPrices.Length > 1) { text += $"${incrementalPrices[1]} - Level 3: 3 charges per round.\n"; } return text; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Pipe Bomb", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Pipe Bomb")) { return null; } int value = Plugin.PipeBombPriceT1.Value; int[] array = new int[2] { Plugin.PipeBombPriceT2.Value, Plugin.PipeBombPriceT3.Value }; return UpgradeBus.Instance.SetupMultiplePurchasableTerminalNode("Pipe Bomb", false, true, value, array, "", UpgradeBus.Instance.UpgradeObjects["Pipe Bomb"], true, (PurchaseMode)0, false, 1f); } public static bool IsUnlocked() { return BaseUpgrade.GetActiveUpgrade("Pipe Bomb"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return BaseUpgrade.GetUpgradeLevel("Pipe Bomb") + 1; } public static int GetMaxCharges() { return GetTier() switch { 1 => Plugin.PipeBombChargesT1.Value, 2 => Plugin.PipeBombChargesT2.Value, 3 => Plugin.PipeBombChargesT3.Value, _ => 0, }; } public override void __initializeVariables() { ((TierUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((TierUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "PipeBombUpgrade"; } } internal class PredatorInstinctUpgrade : TierUpgrade { public const string UPGRADE_NAME = "Predator Instinct"; public const int INITIAL_PRICE = 15; public static readonly int[] TIER_PRICES = new int[2] { 22, 30 }; public static readonly float[] RANGE_BY_LEVEL = new float[3] { 10f, 20f, 30f }; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Predator Instinct"; ((BaseUpgrade)this).overridenUpgradeName = "Predator Instinct"; } public override string GetDisplayInfo(int initialPrice = -1, int maxLevels = -1, int[] incrementalPrices = null) { string text = ""; text += $"${initialPrice} - Level 1: Reveals enemies within 10m as red point lights.\n"; if (incrementalPrices != null && incrementalPrices.Length != 0) { text += $"${incrementalPrices[0]} - Level 2: Sense range expands to 20m.\n"; } if (incrementalPrices != null && incrementalPrices.Length > 1) { text += $"${incrementalPrices[1]} - Level 3: Range becomes 30m and a heartbeat speeds up as enemies close.\n"; } return text; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Predator Instinct", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Predator Instinct")) { return null; } return UpgradeBus.Instance.SetupMultiplePurchasableTerminalNode("Predator Instinct", false, true, 15, TIER_PRICES, "", UpgradeBus.Instance.UpgradeObjects["Predator Instinct"], true, (PurchaseMode)0, false, 1f); } public static bool IsUnlocked() { return BaseUpgrade.GetActiveUpgrade("Predator Instinct"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return BaseUpgrade.GetUpgradeLevel("Predator Instinct") + 1; } public static float GetRange() { int tier = GetTier(); if (tier <= 0) { return 0f; } return RANGE_BY_LEVEL[tier - 1]; } public static bool ShouldHeartbeat() { return GetTier() >= 3; } public override void __initializeVariables() { ((TierUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((TierUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "PredatorInstinctUpgrade"; } } internal class RetaliationUpgrade : TierUpgrade { public const string UPGRADE_NAME = "Retaliation"; public const int INITIAL_PRICE = 20; public static readonly int[] TIER_PRICES = new int[1] { 30 }; public const float TIER1_REFLECT_CHANCE = 0.5f; public const float TIER2_STUN_SECONDS = 1f; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Retaliation"; ((BaseUpgrade)this).overridenUpgradeName = "Retaliation"; } public override string GetDisplayInfo(int initialPrice = -1, int maxLevels = -1, int[] incrementalPrices = null) { string text = ""; text += $"${initialPrice} - Level 1: When an enemy damages you, 50% chance to reflect a shovel hit back.\n"; if (incrementalPrices != null && incrementalPrices.Length != 0) { text += $"${incrementalPrices[0]} - Level 2: Always reflects, plus a 1s stagger on the attacker.\n"; } return text; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Retaliation", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Retaliation")) { return null; } return UpgradeBus.Instance.SetupMultiplePurchasableTerminalNode("Retaliation", false, true, 20, TIER_PRICES, "", UpgradeBus.Instance.UpgradeObjects["Retaliation"], true, (PurchaseMode)0, false, 1f); } public override void __initializeVariables() { ((TierUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((TierUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "RetaliationUpgrade"; } } internal class SalvagerUpgrade : TierUpgrade { public const string UPGRADE_NAME = "Salvager"; public const int INITIAL_PRICE = 25; public static readonly int[] TIER_PRICES = new int[2] { 25, 25 }; public const int TIER_GLOW = 1; public const int TIER_BEACON = 2; public const int TIER_TRAIL = 3; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Salvager"; ((BaseUpgrade)this).overridenUpgradeName = "Salvager"; } public override string GetDisplayInfo(int initialPrice = -1, int maxLevels = -1, int[] incrementalPrices = null) { string text = "Recovery and death-handling implants for the unlucky and the unlucky-adjacent.\n"; text += $"${initialPrice} - Tier 1: Items dropped by dead players glow with a soft light.\n"; if (incrementalPrices != null && incrementalPrices.Length != 0) { text += $"${incrementalPrices[0]} - Tier 2: On death, drops a pulsing beacon and a HUD skull marker.\n"; } if (incrementalPrices != null && incrementalPrices.Length > 1) { text += $"${incrementalPrices[1]} - Tier 3: Also paints a ghost trail from the entrance to your body.\n"; } return text; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Salvager", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Salvager")) { return null; } return UpgradeBus.Instance.SetupMultiplePurchasableTerminalNode("Salvager", false, true, 25, TIER_PRICES, "", UpgradeBus.Instance.UpgradeObjects["Salvager"], true, (PurchaseMode)0, false, 1f); } public static bool IsUnlocked() { return BaseUpgrade.GetActiveUpgrade("Salvager"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return BaseUpgrade.GetUpgradeLevel("Salvager") + 1; } public static bool HasTier(int requiredTier) { return GetTier() >= requiredTier; } public override void __initializeVariables() { ((TierUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((TierUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "SalvagerUpgrade"; } } internal class ShadowStepUpgrade : TierUpgrade { public const string UPGRADE_NAME = "Shadow Step"; public const int INITIAL_PRICE = 15; public static readonly int[] TIER_PRICES = new int[2] { 22, 30 }; public const float INVISIBILITY_DURATION = 6f; public const float COOLDOWN_DURATION = 120f; public const float REDUCED_DETECTION_MULTIPLIER = 0.75f; public static bool IsInvisible = false; public static float InvisibilityEndTime = 0f; public static float CooldownEndTime = 0f; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Shadow Step"; ((BaseUpgrade)this).overridenUpgradeName = "Shadow Step"; } public override string GetDisplayInfo(int initialPrice = -1, int maxLevels = -1, int[] incrementalPrices = null) { string text = ""; text += $"${initialPrice} - Level 1: -25% enemy detection range while crouching.\n"; if (incrementalPrices != null && incrementalPrices.Length != 0) { text += $"${incrementalPrices[0]} - Level 2: -25% detection range while crouching OR walking (not sprinting).\n"; } if (incrementalPrices != null && incrementalPrices.Length > 1) { text += $"${incrementalPrices[1]} - Level 3: Press [G] for 6s of full invisibility (120s cooldown).\n"; } return text; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Shadow Step", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Shadow Step")) { return null; } return UpgradeBus.Instance.SetupMultiplePurchasableTerminalNode("Shadow Step", false, true, 15, TIER_PRICES, "", UpgradeBus.Instance.UpgradeObjects["Shadow Step"], true, (PurchaseMode)0, false, 1f); } public static bool IsUnlocked() { return BaseUpgrade.GetActiveUpgrade("Shadow Step"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return BaseUpgrade.GetUpgradeLevel("Shadow Step") + 1; } public static bool HasActiveAbility() { return GetTier() >= 3; } public override void __initializeVariables() { ((TierUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((TierUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "ShadowStepUpgrade"; } } internal class SpatialAwarenessUpgrade : TierUpgrade { public const string UPGRADE_NAME = "Spatial Awareness"; public const int INITIAL_PRICE = 25; public static readonly int[] TIER_PRICES = new int[3] { 25, 25, 25 }; public const int TIER_LIGHT_FEET = 1; public const int TIER_DONT_SHOOT = 2; public const int TIER_GROUNDED = 3; public const int TIER_NPC = 4; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Spatial Awareness"; ((BaseUpgrade)this).overridenUpgradeName = "Spatial Awareness"; } public override string GetDisplayInfo(int initialPrice = -1, int maxLevels = -1, int[] incrementalPrices = null) { string text = "Heightened environmental awareness implants that let you sense and avoid hazards.\n"; text += $"${initialPrice} - Tier 1: Landmines no longer trigger when you walk over them.\n"; if (incrementalPrices != null && incrementalPrices.Length != 0) { text += $"${incrementalPrices[0]} - Tier 2: Turrets can no longer detect you.\n"; } if (incrementalPrices != null && incrementalPrices.Length > 1) { text += $"${incrementalPrices[1]} - Tier 3: Lightning can no longer strike you.\n"; } if (incrementalPrices != null && incrementalPrices.Length > 2) { text += $"${incrementalPrices[2]} - Tier 4: Masked enemies ignore your presence.\n"; } return text + "\n\"See everything. Touch nothing.\""; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Spatial Awareness", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Spatial Awareness")) { return null; } return UpgradeBus.Instance.SetupMultiplePurchasableTerminalNode("Spatial Awareness", false, true, 25, TIER_PRICES, "", UpgradeBus.Instance.UpgradeObjects["Spatial Awareness"], true, (PurchaseMode)0, false, 1f); } public static bool IsUnlocked() { return BaseUpgrade.GetActiveUpgrade("Spatial Awareness"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return BaseUpgrade.GetUpgradeLevel("Spatial Awareness") + 1; } public static bool HasTier(int requiredTier) { return GetTier() >= requiredTier; } public override void __initializeVariables() { ((TierUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((TierUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "SpatialAwarenessUpgrade"; } } internal class SquadSightUpgrade : TierUpgrade { public const string UPGRADE_NAME = "Squad Sight"; public const int INITIAL_PRICE = 15; public static readonly int[] TIER_PRICES = new int[2] { 22, 30 }; public override bool CanInitializeOnStart => false; private void Awake() { ((BaseUpgrade)this).upgradeName = "Squad Sight"; ((BaseUpgrade)this).overridenUpgradeName = "Squad Sight"; } public override string GetDisplayInfo(int initialPrice = -1, int maxLevels = -1, int[] incrementalPrices = null) { string text = ""; text += $"${initialPrice} - Level 1: See teammates within 30m through walls and in darkness.\n"; if (incrementalPrices != null && incrementalPrices.Length != 0) { text += $"${incrementalPrices[0]} - Level 2: Range increased to 60m, indicators are brighter.\n"; } if (incrementalPrices != null && incrementalPrices.Length > 1) { text += $"${incrementalPrices[1]} - Level 3: Unlimited range, all teammates always visible.\n"; } return text; } public static void RegisterUpgrade() { } public static (string, string[]) RegisterScrapToUpgrade() { return ("Squad Sight", Array.Empty()); } public static CustomTerminalNode RegisterTerminalNode() { if (!UpgradeBus.Instance.UpgradeObjects.ContainsKey("Squad Sight")) { return null; } return UpgradeBus.Instance.SetupMultiplePurchasableTerminalNode("Squad Sight", false, true, 15, TIER_PRICES, "", UpgradeBus.Instance.UpgradeObjects["Squad Sight"], true, (PurchaseMode)0, false, 1f); } public static bool IsUnlocked() { return BaseUpgrade.GetActiveUpgrade("Squad Sight"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return BaseUpgrade.GetUpgradeLevel("Squad Sight") + 1; } public static float GetRange() { return GetTier() switch { 1 => 30f, 2 => 60f, 3 => -1f, _ => 0f, }; } public static float GetVisibilityMultiplier() { return GetTier() switch { 1 => 0.6f, 2 => 0.85f, 3 => 1f, _ => 0f, }; } public override void __initializeVariables() { ((TierUpgrade)this).__initializeVariables(); } public override void __initializeRpcs() { ((TierUpgrade)this).__initializeRpcs(); } public override string __getTypeName() { return "SquadSightUpgrade"; } } } namespace LGUCustomUpgrades.Patches { [HarmonyPatch] internal static class AdrenalineRushPatch { private const float VIGNETTE_ALPHA_BASE = 0.1f; private const float VIGNETTE_ALPHA_AMP = 0.06f; private const float VIGNETTE_PULSE_HZ = 3f; private static readonly Color VIGNETTE_TINT_NORMAL = new Color(0.8f, 0.15f, 0.05f, 0f); private static readonly Color VIGNETTE_TINT_INVULN = new Color(1f, 0.95f, 0.95f, 0f); private static RawImage _vignette; private static float _pulseTime; [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPrefix] private static bool PreDamagePlayer(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)GameNetworkManager.Instance == (Object)null) { return true; } if ((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance.localPlayerController) { return true; } if (!AdrenalineRushUpgrade.IsInvincible) { return true; } return false; } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPostfix] private static void PostDamagePlayer(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)GameNetworkManager.Instance == (Object)null) && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance.localPlayerController) && AdrenalineRushUpgrade.IsUnlocked() && !__instance.isPlayerDead && __instance.health > 0 && __instance.health <= 20 && !AdrenalineRushUpgrade.IsAdrenalineActive) { ActivateAdrenaline(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPrefix] private static bool PreKillPlayer(PlayerControllerB __instance, Vector3 bodyVelocity, bool spawnBody, CauseOfDeath causeOfDeath, int deathAnimation) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)GameNetworkManager.Instance == (Object)null) { return true; } if ((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance.localPlayerController) { return true; } if (!AdrenalineRushUpgrade.HasInsurance()) { return true; } if (AdrenalineRushUpgrade.InsuranceUsedThisRound) { return true; } if (!IsEnemyOrTrapDeath(causeOfDeath)) { return true; } __instance.health = 1; AdrenalineRushUpgrade.InsuranceUsedThisRound = true; __instance.isPlayerDead = false; if (!AdrenalineRushUpgrade.IsAdrenalineActive) { ActivateAdrenaline(__instance); } StartInvincibility(__instance, 2f); HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("ADRENALINE SURGE", "Survival insurance triggered — 2s of invincibility.", true, false, "LC_Tip1"); } return false; } private static bool IsEnemyOrTrapDeath(CauseOfDeath cause) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected I4, but got Unknown switch ((int)cause) { case 0: case 1: case 3: case 4: case 6: case 7: case 8: case 11: case 12: case 13: case 14: case 15: case 17: return true; default: return false; } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostLateUpdate(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)null || (Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)__instance != (Object)(object)GameNetworkManager.Instance.localPlayerController) { return; } if (AdrenalineRushUpgrade.IsInvincible && Time.time >= AdrenalineRushUpgrade.InvincibilityEndTime) { AdrenalineRushUpgrade.IsInvincible = false; } if (AdrenalineRushUpgrade.IsAdrenalineActive) { if (__instance.isPlayerDead || __instance.health > 20) { DeactivateAdrenaline(__instance); } else { UpdateVignette(); } } } [HarmonyPatch(typeof(StartOfRound), "StartGame")] [HarmonyPostfix] private static void PostStartGame() { AdrenalineRushUpgrade.InsuranceUsedThisRound = false; AdrenalineRushUpgrade.IsInvincible = false; AdrenalineRushUpgrade.InvincibilityEndTime = 0f; AdrenalineRushUpgrade.IsAdrenalineActive = false; HideVignette(); } private static void ActivateAdrenaline(PlayerControllerB player) { if (!((Object)(object)player == (Object)null) && !AdrenalineRushUpgrade.IsAdrenalineActive) { AdrenalineRushUpgrade.OriginalSpeed = player.movementSpeed; player.movementSpeed = AdrenalineRushUpgrade.OriginalSpeed * 1.3f; AdrenalineRushUpgrade.IsAdrenalineActive = true; HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("ADRENALINE", "Heart pounding — speed surge engaged.", true, false, "LC_Tip1"); } } } private static void DeactivateAdrenaline(PlayerControllerB player) { if (AdrenalineRushUpgrade.IsAdrenalineActive) { if ((Object)(object)player != (Object)null && AdrenalineRushUpgrade.OriginalSpeed > 0f) { player.movementSpeed = AdrenalineRushUpgrade.OriginalSpeed; } AdrenalineRushUpgrade.IsAdrenalineActive = false; HideVignette(); } } private static void StartInvincibility(PlayerControllerB player, float seconds) { AdrenalineRushUpgrade.IsInvincible = true; AdrenalineRushUpgrade.InvincibilityEndTime = Time.time + seconds; } private static void UpdateVignette() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) EnsureVignette(); if (!((Object)(object)_vignette == (Object)null)) { ((Component)_vignette).gameObject.SetActive(true); _pulseTime += Time.deltaTime * 3f; if (AdrenalineRushUpgrade.IsInvincible) { float a = 0.18f + 0.1f * Mathf.Abs(Mathf.Sin(Time.time * 8f)); Color vIGNETTE_TINT_INVULN = VIGNETTE_TINT_INVULN; vIGNETTE_TINT_INVULN.a = a; ((Graphic)_vignette).color = vIGNETTE_TINT_INVULN; } else { float a2 = 0.1f + 0.06f * Mathf.Sin(_pulseTime); Color vIGNETTE_TINT_NORMAL = VIGNETTE_TINT_NORMAL; vIGNETTE_TINT_NORMAL.a = a2; ((Graphic)_vignette).color = vIGNETTE_TINT_NORMAL; } } } private static void EnsureVignette() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_vignette != (Object)null) && !((Object)(object)HUDManager.Instance == (Object)null) && !((Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null)) { Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if (!((Object)(object)canvas == (Object)null)) { GameObject val = new GameObject("AdrenalineVignette"); val.transform.SetParent(((Component)canvas).transform, false); RectTransform obj = val.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; _vignette = val.AddComponent(); ((Graphic)_vignette).raycastTarget = false; ((Graphic)_vignette).color = new Color(0f, 0f, 0f, 0f); } } } private static void HideVignette() { if ((Object)(object)_vignette != (Object)null) { ((Component)_vignette).gameObject.SetActive(false); } _pulseTime = 0f; } } [HarmonyPatch(typeof(ItemProgressionManager), "AssignConfiguredScrap")] internal static class AssignConfiguredScrapPatch { [HarmonyPrefix] private static bool SafeAssignConfiguredScrap() { try { UpgradeBus instance = UpgradeBus.Instance; if ((Object)(object)instance == (Object)null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[LGUCustomUpgrades] AssignConfiguredScrap skipped: UpgradeBus.Instance is null."); } return false; } if (instance.scrapToCollectionUpgrade == null) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)"[LGUCustomUpgrades] AssignConfiguredScrap: scrapToCollectionUpgrade dict was null; skipping Clear()."); } } else { instance.scrapToCollectionUpgrade.Clear(); } if (instance.upgradeTypes == null) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)"[LGUCustomUpgrades] AssignConfiguredScrap: upgradeTypes list is null; nothing to assign."); } return false; } foreach (Type upgradeType in instance.upgradeTypes) { if (upgradeType == null) { ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogWarning((object)"[LGUCustomUpgrades] AssignConfiguredScrap: encountered null upgrade type, skipping."); } continue; } MethodInfo method; try { method = upgradeType.GetMethod("RegisterScrapToUpgrade", BindingFlags.Static | BindingFlags.Public); } catch (AmbiguousMatchException ex) { ManualLogSource log5 = Plugin.Log; if (log5 != null) { log5.LogWarning((object)("[LGUCustomUpgrades] AssignConfiguredScrap: ambiguous RegisterScrapToUpgrade on '" + upgradeType.FullName + "', skipping. " + ex.Message)); } continue; } if (method == null) { ManualLogSource log6 = Plugin.Log; if (log6 != null) { log6.LogWarning((object)("[LGUCustomUpgrades] Upgrade type '" + upgradeType.FullName + "' has no static RegisterScrapToUpgrade() method; skipping it in AssignConfiguredScrap.")); } continue; } object obj; try { obj = method.Invoke(null, null); } catch (Exception ex2) { ManualLogSource log7 = Plugin.Log; if (log7 != null) { log7.LogWarning((object)("[LGUCustomUpgrades] RegisterScrapToUpgrade on '" + upgradeType.FullName + "' threw " + ex2.GetType().Name + ": " + ex2.Message + "; skipping.")); } continue; } if (obj == null) { ManualLogSource log8 = Plugin.Log; if (log8 != null) { log8.LogInfo((object)("[LGUCustomUpgrades] RegisterScrapToUpgrade on '" + upgradeType.FullName + "' returned null; skipping.")); } continue; } if (!(obj is (string, string[]) tuple)) { ManualLogSource log9 = Plugin.Log; if (log9 != null) { log9.LogWarning((object)("[LGUCustomUpgrades] RegisterScrapToUpgrade on '" + upgradeType.FullName + "' returned unexpected type '" + obj.GetType().FullName + "'; skipping.")); } continue; } var (text, array) = tuple; if (string.IsNullOrWhiteSpace(text)) { ManualLogSource log10 = Plugin.Log; if (log10 != null) { log10.LogWarning((object)("[LGUCustomUpgrades] RegisterScrapToUpgrade on '" + upgradeType.FullName + "' returned null/empty upgrade name; skipping.")); } } else { if (array == null || array.Length == 0) { continue; } string[] array2 = array; foreach (string text2 in array2) { if (string.IsNullOrWhiteSpace(text2)) { ManualLogSource log11 = Plugin.Log; if (log11 != null) { log11.LogWarning((object)("[LGUCustomUpgrades] Skipping null/empty scrap name for upgrade '" + text + "'.")); } continue; } try { ItemProgressionManager.AddScrapToUpgrade(text, text2); } catch (Exception ex3) { ManualLogSource log12 = Plugin.Log; if (log12 != null) { log12.LogWarning((object)("[LGUCustomUpgrades] AddScrapToUpgrade('" + text + "', '" + text2 + "') threw " + ex3.GetType().Name + ": " + ex3.Message + "; skipping.")); } } } } } } catch (Exception arg) { ManualLogSource log13 = Plugin.Log; if (log13 != null) { log13.LogError((object)$"[LGUCustomUpgrades] Unhandled exception in SafeAssignConfiguredScrap: {arg}"); } } return false; } } [HarmonyPatch(typeof(DepositItemsDesk))] internal class DepositItemsDeskPatch { [HarmonyPatch("UpdateEffects")] [HarmonyPrefix] private static bool UpdateEffectsPrefix(DepositItemsDesk __instance) { if ((Object)(object)__instance.deskAudio == (Object)null || (Object)(object)__instance.deskObjectsContainer == (Object)null || (Object)(object)__instance.speakerAudio == (Object)null) { return false; } return true; } } [HarmonyPatch] internal static class EscapeProtocolPatch { private struct ExitMarker { public EntranceTeleport Exit; public GameObject Root; public TMP_Text Label; public Image Background; public Image Border; public bool IsMainEntrance; } private const float ACTIVE_DURATION = 5f; private const float COOLDOWN_DURATION = 60f; private static bool _isActive = false; private static float _activeUntil = 0f; private static float _cooldownUntil = 0f; private static bool _keyWasDown = false; private static bool _wasInsideAtActivation = false; private static EntranceTeleport[] _cachedExits; private static GameObject _overlayCanvas; private static readonly List _markers = new List(); private const string HUD_SPRITE = "escape_hud"; private const int HUD_STACK_POSITION = 0; [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerControlled || (Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return; } UpdateStatusHUD(__instance); if (!EscapeProtocolUpgrade.IsUnlocked()) { return; } if (__instance.isPlayerDead) { if (_isActive) { Deactivate(); } return; } if (_isActive && Time.time >= _activeUntil) { Deactivate(); _cooldownUntil = Time.time + 60f; HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("ESCAPE PROTOCOL", "Signal lost. Recharging...", false, false, "LC_Tip1"); } } if (!__instance.isTypingChat && !__instance.inTerminalMenu && ((Object)(object)__instance.quickMenuManager == (Object)null || !__instance.quickMenuManager.isMenuOpen) && !__instance.inSpecialInteractAnimation) { PollKeybind(__instance); } if (_isActive) { UpdateMarkers(__instance); } } private static void PollKeybind(PlayerControllerB player) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (current == null) { return; } Key? escapeProtocolKey = Plugin.GetEscapeProtocolKey(); bool flag = (escapeProtocolKey.HasValue ? ((ButtonControl)current[escapeProtocolKey.Value]).isPressed : ((ButtonControl)current.hKey).isPressed); bool num = flag && !_keyWasDown; _keyWasDown = flag; if (!num || _isActive) { return; } if (Time.time < _cooldownUntil) { float num2 = _cooldownUntil - Time.time; HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("ESCAPE PROTOCOL", $"Cooldown: {num2:F0}s", true, false, "LC_Tip1"); } } else { Activate(player); } } private static void Activate(PlayerControllerB player) { _wasInsideAtActivation = player.isInsideFactory; CacheExits(_wasInsideAtActivation); if (_cachedExits == null || _cachedExits.Length == 0) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("ESCAPE PROTOCOL", "No exits detected.", true, false, "LC_Tip1"); } } else { _isActive = true; _activeUntil = Time.time + 5f; EnsureOverlayCanvas(); BuildMarkers(); } } private static void Deactivate() { _isActive = false; DestroyMarkers(); } private static void CacheExits(bool playerIsInside) { EntranceTeleport[] array = Object.FindObjectsOfType(); List list = new List(); bool flag = !playerIsInside; for (int i = 0; i < array.Length; i++) { if (!((Object)(object)array[i] == (Object)null) && array[i].isEntranceToBuilding == flag) { list.Add(array[i]); } } _cachedExits = list.ToArray(); } private static void EnsureOverlayCanvas() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_overlayCanvas != (Object)null)) { _overlayCanvas = new GameObject("LGU_EscapeProtocol_Canvas"); Canvas obj = _overlayCanvas.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 60; CanvasScaler obj2 = _overlayCanvas.AddComponent(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); _overlayCanvas.AddComponent(); Object.DontDestroyOnLoad((Object)(object)_overlayCanvas); } } private static void BuildMarkers() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) DestroyMarkers(); if (_cachedExits == null || (Object)(object)_overlayCanvas == (Object)null) { return; } Color color = HexColor("00C800"); Color color2 = default(Color); ((Color)(ref color2))..ctor(0.02f, 0.02f, 0.02f, 0.9f); for (int i = 0; i < _cachedExits.Length; i++) { EntranceTeleport val = _cachedExits[i]; if ((Object)(object)val == (Object)null) { continue; } bool flag = IsMainEntrance(val, i); GameObject val2 = new GameObject($"ExitMarker_{i}"); val2.transform.SetParent(_overlayCanvas.transform, false); val2.AddComponent().sizeDelta = new Vector2(220f, 36f); Image val3 = val2.AddComponent(); ((Graphic)val3).color = color; ((Graphic)val3).raycastTarget = false; GameObject val4 = new GameObject("Inner"); val4.transform.SetParent(val2.transform, false); RectTransform obj = val4.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = new Vector2(1f, 1f); obj.offsetMax = new Vector2(-1f, -1f); Image val5 = val4.AddComponent(); ((Graphic)val5).color = color2; ((Graphic)val5).raycastTarget = false; GameObject val6 = new GameObject("Text"); val6.transform.SetParent(val4.transform, false); RectTransform obj2 = val6.AddComponent(); obj2.anchorMin = Vector2.zero; obj2.anchorMax = Vector2.one; obj2.offsetMin = new Vector2(6f, 0f); obj2.offsetMax = new Vector2(-6f, 0f); TMP_Text val7 = (TMP_Text)(object)val6.AddComponent(); val7.fontSize = 13f; val7.alignment = (TextAlignmentOptions)514; ((Graphic)val7).color = color; ((Graphic)val7).raycastTarget = false; val7.enableWordWrapping = false; val7.overflowMode = (TextOverflowModes)0; val7.text = (flag ? "ENTRANCE" : "EXIT"); Terminal val8 = Object.FindObjectOfType(); if ((Object)(object)val8 != (Object)null) { TMP_Text componentInChildren = ((Component)val8).GetComponentInChildren(); if ((Object)(object)((componentInChildren != null) ? componentInChildren.font : null) != (Object)null) { val7.font = componentInChildren.font; } } _markers.Add(new ExitMarker { Exit = val, Root = val2, Label = val7, Background = val5, Border = val3, IsMainEntrance = flag }); } } private static bool IsMainEntrance(EntranceTeleport exit, int index) { if (index == 0) { return true; } string text = ((Object)((Component)exit).gameObject).name.ToLowerInvariant(); if ((text.Contains("main") || text.Contains("entrance")) && !text.Contains("fire") && !text.Contains("exit")) { return true; } return false; } private static void UpdateMarkers(PlayerControllerB player) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) if (player.isInsideFactory != _wasInsideAtActivation) { _wasInsideAtActivation = player.isInsideFactory; CacheExits(_wasInsideAtActivation); BuildMarkers(); } if (_cachedExits == null || _cachedExits.Length == 0) { return; } Camera gameplayCamera = player.gameplayCamera; if ((Object)(object)gameplayCamera == (Object)null) { return; } for (int i = 0; i < _markers.Count; i++) { ExitMarker exitMarker = _markers[i]; if ((Object)(object)exitMarker.Exit == (Object)null || (Object)(object)exitMarker.Root == (Object)null) { if ((Object)(object)exitMarker.Root != (Object)null) { exitMarker.Root.SetActive(false); } continue; } Vector3 val = ((Component)exitMarker.Exit).transform.position + Vector3.up * 2f; Vector3 val2 = gameplayCamera.WorldToViewportPoint(val); if (val2.z < 0f) { exitMarker.Root.SetActive(false); continue; } exitMarker.Root.SetActive(true); float num = val2.x * (float)Screen.width; float num2 = val2.y * (float)Screen.height; num = Mathf.Clamp(num, 30f, (float)Screen.width - 30f); num2 = Mathf.Clamp(num2, 30f, (float)Screen.height - 30f); ((Transform)exitMarker.Root.GetComponent()).position = new Vector3(num, num2, 0f); float num3 = Vector3.Distance(((Component)player).transform.position, ((Component)exitMarker.Exit).transform.position); string arg = (exitMarker.IsMainEntrance ? "ENTRANCE" : "EXIT"); exitMarker.Label.text = $"{arg} — {num3:F0}m"; } } private static void DestroyMarkers() { for (int i = 0; i < _markers.Count; i++) { if ((Object)(object)_markers[i].Root != (Object)null) { Object.Destroy((Object)(object)_markers[i].Root); } } _markers.Clear(); } private static void EnsureSpriteHUD() { if (!((Object)(object)UpgradeHUDManager.GetHUDElement("escape_hud") != (Object)null) && !((Object)(object)HUDManager.Instance == (Object)null) && !((Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null)) { Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if (!((Object)(object)canvas == (Object)null)) { UpgradeHUDManager.CreateHUDElement("escape_hud", 0, ((Component)canvas).transform); } } } private static void UpdateStatusHUD(PlayerControllerB localPlayer) { if (!EscapeProtocolUpgrade.IsUnlocked()) { GameObject hUDElement = UpgradeHUDManager.GetHUDElement("escape_hud"); if ((Object)(object)hUDElement != (Object)null) { hUDElement.SetActive(false); } return; } if ((Object)(object)localPlayer == (Object)null || localPlayer.inTerminalMenu || localPlayer.isTypingChat || ((Object)(object)localPlayer.quickMenuManager != (Object)null && localPlayer.quickMenuManager.isMenuOpen)) { GameObject hUDElement2 = UpgradeHUDManager.GetHUDElement("escape_hud"); if ((Object)(object)hUDElement2 != (Object)null) { hUDElement2.SetActive(false); } return; } EnsureSpriteHUD(); GameObject hUDElement3 = UpgradeHUDManager.GetHUDElement("escape_hud"); if (!((Object)(object)hUDElement3 == (Object)null)) { hUDElement3.SetActive(true); if (_isActive) { UpgradeHUDManager.SetCooldownActive("escape_hud", active: false); } else if (Time.time < _cooldownUntil) { UpgradeHUDManager.SetCooldownActive("escape_hud", active: true); float num = _cooldownUntil - Time.time; UpgradeHUDManager.UpdateFillBar("escape_hud", num / 60f); } else { UpgradeHUDManager.SetCooldownActive("escape_hud", active: false); } } } [HarmonyPatch(typeof(StartOfRound), "StartGame")] [HarmonyPostfix] private static void PostStartGame() { Deactivate(); _cachedExits = null; _keyWasDown = false; _activeUntil = 0f; _cooldownUntil = 0f; } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { Deactivate(); _cachedExits = null; _activeUntil = 0f; _cooldownUntil = 0f; UpgradeHUDManager.DestroyHUDElement("escape_hud"); if ((Object)(object)_overlayCanvas != (Object)null) { Object.Destroy((Object)(object)_overlayCanvas); } _overlayCanvas = null; } private static Color HexColor(string hex) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); ColorUtility.TryParseHtmlString("#" + hex, ref result); return result; } } internal static class ExtraSlotManager { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnSetBonusSlotsServerRpc; public static HandleNamedMessageDelegate <1>__OnRequestAllBonusSlotsServerRpc; public static HandleNamedMessageDelegate <2>__OnSetBonusSlotsClientRpc; public static HandleNamedMessageDelegate <3>__OnSyncAllBonusSlotsClientRpc; } private static readonly Dictionary playerBonusSlots = new Dictionary(); private static bool handlersRegistered = false; private const string MSG_SET_SERVER = "LGUExtraSlot.SetBonusSlotsServerRpc"; private const string MSG_SET_CLIENT = "LGUExtraSlot.SetBonusSlotsClientRpc"; private const string MSG_REQUEST_ALL_SERVER = "LGUExtraSlot.RequestAllServerRpc"; private const string MSG_SYNC_ALL_CLIENT = "LGUExtraSlot.SyncAllClientRpc"; public static int GetPlayerBonusSlots(ulong clientId) { if (!playerBonusSlots.TryGetValue(clientId, out var value)) { return 0; } return value; } public static int GetLocalPlayerBonusSlots() { PlayerControllerB val = StartOfRound.Instance?.localPlayerController; if (!((Object)(object)val != (Object)null)) { return 0; } return GetPlayerBonusSlots(val.actualClientId); } public static short GetEffectiveHotbarSize() { return (short)(SyncManager.currentHotbarSize + GetLocalPlayerBonusSlots()); } public static void BroadcastBonusSlots(ulong clientId, int bonusSlots) { if (!SyncManager.isSynced) { playerBonusSlots[clientId] = bonusSlots; Plugin.Log.LogInfo((object)$"ExtraSlot: Stored bonus {bonusSlots} for client {clientId} (pre-sync, will apply on sync)"); } else if (NetworkManager.Singleton.IsServer) { SetPlayerBonusSlotsLocal(clientId, bonusSlots); SendSetBonusSlotsToAllClients(clientId, bonusSlots); } else { SendSetBonusSlotsToServer(clientId, bonusSlots); } } public static void ApplyBonusInventorySlots() { try { if ((Object)(object)StartOfRound.Instance == (Object)null) { return; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (val.isPlayerControlled || !((Object)(object)val != (Object)(object)StartOfRound.Instance.localPlayerController)) { int num = GetPlayerBonusSlots(val.actualClientId); if (num > 0) { int targetSize = SyncManager.currentHotbarSize + num; ResizePlayerInventory(val, targetSize); } } } } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlot: ApplyBonusInventorySlots failed: {arg}"); } } public static void ApplyBonusHUDSlots() { try { PlayerControllerB val = StartOfRound.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null)) { int num = GetPlayerBonusSlots(val.actualClientId); if (num > 0) { ResizeLocalHUD(SyncManager.currentHotbarSize + num); } } } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlot: ApplyBonusHUDSlots failed: {arg}"); } } public static void RegisterNetworkHandlers() { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //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_006c: Expected O, but got Unknown if (handlersRegistered) { return; } handlersRegistered = true; CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; if (NetworkManager.Singleton.IsServer) { object obj = <>O.<0>__OnSetBonusSlotsServerRpc; if (obj == null) { HandleNamedMessageDelegate val = OnSetBonusSlotsServerRpc; <>O.<0>__OnSetBonusSlotsServerRpc = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("LGUExtraSlot.SetBonusSlotsServerRpc", (HandleNamedMessageDelegate)obj); object obj2 = <>O.<1>__OnRequestAllBonusSlotsServerRpc; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnRequestAllBonusSlotsServerRpc; <>O.<1>__OnRequestAllBonusSlotsServerRpc = val2; obj2 = (object)val2; } customMessagingManager.RegisterNamedMessageHandler("LGUExtraSlot.RequestAllServerRpc", (HandleNamedMessageDelegate)obj2); } object obj3 = <>O.<2>__OnSetBonusSlotsClientRpc; if (obj3 == null) { HandleNamedMessageDelegate val3 = OnSetBonusSlotsClientRpc; <>O.<2>__OnSetBonusSlotsClientRpc = val3; obj3 = (object)val3; } customMessagingManager.RegisterNamedMessageHandler("LGUExtraSlot.SetBonusSlotsClientRpc", (HandleNamedMessageDelegate)obj3); object obj4 = <>O.<3>__OnSyncAllBonusSlotsClientRpc; if (obj4 == null) { HandleNamedMessageDelegate val4 = OnSyncAllBonusSlotsClientRpc; <>O.<3>__OnSyncAllBonusSlotsClientRpc = val4; obj4 = (object)val4; } customMessagingManager.RegisterNamedMessageHandler("LGUExtraSlot.SyncAllClientRpc", (HandleNamedMessageDelegate)obj4); Plugin.Log.LogInfo((object)"ExtraSlot: Network handlers registered."); } public static void ClearAllBonusSlots() { playerBonusSlots.Clear(); handlersRegistered = false; Plugin.Log.LogInfo((object)"ExtraSlot: All bonus slots cleared."); } public static void RequestAllBonusSlotsFromServer() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)NetworkManager.Singleton == (Object)null) && SyncManager.isSynced) { if (NetworkManager.Singleton.IsServer) { ApplyAllBonusSlots(); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(0, (Allocator)2, -1); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LGUExtraSlot.RequestAllServerRpc", 0uL, val, (NetworkDelivery)4); } } private static void SetPlayerBonusSlotsLocal(ulong clientId, int bonusSlots) { playerBonusSlots[clientId] = bonusSlots; Plugin.Log.LogInfo((object)$"ExtraSlot: Set bonus {bonusSlots} for client {clientId}"); if ((Object)(object)StartOfRound.Instance == (Object)null || !SyncManager.isSynced) { return; } PlayerControllerB val = FindPlayerByClientId(clientId); if (!((Object)(object)val == (Object)null)) { int targetSize = SyncManager.currentHotbarSize + bonusSlots; ResizePlayerInventory(val, targetSize); if ((Object)(object)val == (Object)(object)StartOfRound.Instance.localPlayerController) { ResizeLocalHUD(targetSize); } } } private static void ApplyAllBonusSlots() { if ((Object)(object)StartOfRound.Instance == (Object)null || !SyncManager.isSynced) { return; } foreach (KeyValuePair playerBonusSlot in playerBonusSlots) { if (playerBonusSlot.Value > 0) { PlayerControllerB val = FindPlayerByClientId(playerBonusSlot.Key); if (!((Object)(object)val == (Object)null)) { int targetSize = SyncManager.currentHotbarSize + playerBonusSlot.Value; ResizePlayerInventory(val, targetSize); } } } PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController; if ((Object)(object)localPlayerController != (Object)null) { int num = GetPlayerBonusSlots(localPlayerController.actualClientId); if (num > 0) { ResizeLocalHUD(SyncManager.currentHotbarSize + num); } } } private static void ResizePlayerInventory(PlayerControllerB player, int targetSize) { if (player.ItemSlots.Length < targetSize) { GrabbableObject[] array = (GrabbableObject[])(object)new GrabbableObject[targetSize]; Array.Copy(player.ItemSlots, array, player.ItemSlots.Length); player.ItemSlots = array; Plugin.Log.LogDebug((object)$"ExtraSlot: Resized {player.playerUsername} inventory to {targetSize}"); } } private static void ResizeLocalHUD(int targetSize) { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)HUDManager.Instance == (Object)null) { return; } Image[] itemSlotIconFrames = HUDManager.Instance.itemSlotIconFrames; Image[] itemSlotIcons = HUDManager.Instance.itemSlotIcons; if (itemSlotIconFrames.Length < targetSize && itemSlotIconFrames.Length != 0) { List list = new List(itemSlotIconFrames); List list2 = new List(itemSlotIcons); Image val = list[0]; for (int i = list.Count; i < targetSize; i++) { Image val2 = Object.Instantiate(val, ((Component)val).transform.parent); ((Object)val2).name = $"Slot{i}"; ((Component)val2).transform.SetSiblingIndex(((Component)list[i - 1]).transform.GetSiblingIndex() + 1); Image component = ((Component)((Component)val2).transform.GetChild(0)).GetComponent(); component.sprite = null; ((Behaviour)component).enabled = false; ((Object)component).name = "Icon"; val2.fillMethod = val.fillMethod; val2.sprite = val.sprite; ((Graphic)val2).material = ((Graphic)val).material; list.Add(val2); list2.Add(component); } HUDManager.Instance.itemSlotIconFrames = list.ToArray(); HUDManager.Instance.itemSlotIcons = list2.ToArray(); RepositionAllHUDSlots(targetSize); Plugin.Log.LogDebug((object)$"ExtraSlot: Resized local HUD to {targetSize} slots"); } } private static void RepositionAllHUDSlots(int totalSlots) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) Image[] itemSlotIconFrames = HUDManager.Instance.itemSlotIconFrames; Image[] itemSlotIcons = HUDManager.Instance.itemSlotIcons; float num = ConfigSettings.overrideHotbarSpacingConfig.Value; float value = ConfigSettings.overrideHotbarHudSizeConfig.Value; float num2 = (HUDPatcher.hotbarSlotSize + num) * value; float num3 = HUDPatcher.defaultItemSlotPosY + 36f * ((value - 1f) / 2f); float num4 = num2 * (float)(totalSlots - 1) / 2f; for (int i = 0; i < totalSlots && i < itemSlotIconFrames.Length; i++) { float num5 = (float)i * num2 - num4; ((Graphic)itemSlotIconFrames[i]).rectTransform.anchoredPosition = new Vector2(num5, num3); ((Graphic)itemSlotIconFrames[i]).rectTransform.sizeDelta = HUDPatcher.defaultItemFrameSize * value; ((Graphic)itemSlotIcons[i]).rectTransform.sizeDelta = HUDPatcher.defaultItemIconSize * value; } } private static void SendSetBonusSlotsToServer(ulong clientId, int bonusSlots) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(12, (Allocator)2, -1); ((FastBufferWriter)(ref val)).WriteValueSafe(ref clientId, default(ForPrimitives)); short num = (short)bonusSlots; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LGUExtraSlot.SetBonusSlotsServerRpc", 0uL, val, (NetworkDelivery)4); } private static void SendSetBonusSlotsToAllClients(ulong clientId, int bonusSlots) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(12, (Allocator)2, -1); ((FastBufferWriter)(ref val)).WriteValueSafe(ref clientId, default(ForPrimitives)); short num = (short)bonusSlots; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("LGUExtraSlot.SetBonusSlotsClientRpc", val, (NetworkDelivery)4); } private static void OnSetBonusSlotsServerRpc(ulong senderId, FastBufferReader reader) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (!NetworkManager.Singleton.IsServer) { return; } try { ulong num = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); short num2 = default(short); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); Plugin.Log.LogInfo((object)$"ExtraSlot Server: Received bonus {num2} for client {num} from sender {senderId}"); playerBonusSlots[num] = num2; PlayerControllerB val = FindPlayerByClientId(num); if ((Object)(object)val != (Object)null && SyncManager.isSynced) { ResizePlayerInventory(val, SyncManager.currentHotbarSize + num2); } SendSetBonusSlotsToAllClients(num, num2); } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlot Server: OnSetBonusSlots failed: {arg}"); } } private static void OnSetBonusSlotsClientRpc(ulong senderId, FastBufferReader reader) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (NetworkManager.Singleton.IsServer) { return; } try { ulong num = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); short num2 = default(short); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); Plugin.Log.LogInfo((object)$"ExtraSlot Client: Received bonus {num2} for client {num}"); SetPlayerBonusSlotsLocal(num, num2); } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlot Client: OnSetBonusSlots failed: {arg}"); } } private static void OnRequestAllBonusSlotsServerRpc(ulong senderId, FastBufferReader reader) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) if (!NetworkManager.Singleton.IsServer) { return; } try { int count = playerBonusSlots.Count; int num = 2 + count * 10; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num, (Allocator)2, -1); short num2 = (short)count; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num2, default(ForPrimitives)); foreach (KeyValuePair playerBonusSlot in playerBonusSlots) { ulong key = playerBonusSlot.Key; ((FastBufferWriter)(ref val)).WriteValueSafe(ref key, default(ForPrimitives)); num2 = (short)playerBonusSlot.Value; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num2, default(ForPrimitives)); } NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("LGUExtraSlot.SyncAllClientRpc", senderId, val, (NetworkDelivery)4); Plugin.Log.LogInfo((object)$"ExtraSlot Server: Sent {count} bonus entries to client {senderId}"); } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlot Server: OnRequestAllBonusSlots failed: {arg}"); } } private static void OnSyncAllBonusSlotsClientRpc(ulong senderId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) try { short num = default(short); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); Plugin.Log.LogInfo((object)$"ExtraSlot Client: Receiving {num} bonus entries from server"); ulong key = default(ulong); short value = default(short); for (int i = 0; i < num; i++) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref key, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref value, default(ForPrimitives)); playerBonusSlots[key] = value; } ApplyAllBonusSlots(); } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlot Client: OnSyncAllBonusSlots failed: {arg}"); } } private static PlayerControllerB FindPlayerByClientId(ulong clientId) { if ((Object)(object)StartOfRound.Instance == (Object)null) { return null; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (val.actualClientId == clientId) { return val; } } return null; } } [HarmonyPatch] internal static class ExtraSlotPatch { [CompilerGenerated] private sealed class d__9 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable instructions; public IEnumerable <>3__instructions; private string methodName; public string <>3__methodName; private MethodInfo 5__2; private MethodInfo 5__3; private bool 5__4; private IEnumerator <>7__wrap4; CodeInstruction IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__9(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } 5__2 = null; 5__3 = null; <>7__wrap4 = null; <>1__state = -2; } private bool MoveNext() { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = AccessTools.PropertyGetter(typeof(SyncManager), "currentHotbarSize"); 5__3 = AccessTools.Method(typeof(ExtraSlotManager), "GetEffectiveHotbarSize", (Type[])null, (Type[])null); 5__4 = false; <>7__wrap4 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; 5__4 = true; break; case 2: <>1__state = -3; break; } if (<>7__wrap4.MoveNext()) { CodeInstruction current = <>7__wrap4.Current; if (CodeInstructionExtensions.Calls(current, 5__2)) { <>2__current = new CodeInstruction(OpCodes.Call, (object)5__3); <>1__state = 1; return true; } <>2__current = current; <>1__state = 2; return true; } <>m__Finally1(); <>7__wrap4 = null; if (5__4) { Plugin.Log.LogDebug((object)("ExtraSlotPatch: Patched currentHotbarSize in " + methodName)); } else { Plugin.Log.LogWarning((object)("ExtraSlotPatch: Failed to find currentHotbarSize getter in " + methodName + ". Number key hotkeys may not work for bonus slots.")); } return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap4 != null) { <>7__wrap4.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__9 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__9(0); } d__.instructions = <>3__instructions; d__.methodName = <>3__methodName; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [HarmonyPatch(typeof(PlayerPatcher), "ResizeInventory")] [HarmonyPostfix] private static void AfterResizeInventory() { try { ExtraSlotManager.ApplyBonusInventorySlots(); } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlotPatch.AfterResizeInventory: {arg}"); } } [HarmonyPatch(typeof(HUDPatcher), "ResizeHotbarSlotsHUD")] [HarmonyPostfix] private static void AfterResizeHotbarSlotsHUD() { try { ExtraSlotManager.ApplyBonusHUDSlots(); } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlotPatch.AfterResizeHotbarSlotsHUD: {arg}"); } } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void AfterConnectClientToPlayerObject() { try { ExtraSlotManager.RegisterNetworkHandlers(); } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlotPatch.AfterConnectClientToPlayerObject: {arg}"); } } [HarmonyPatch(typeof(SyncManager), "OnSyncedWithServer")] [HarmonyPostfix] private static void AfterOnSyncedWithServer() { try { ExtraSlotManager.RequestAllBonusSlotsFromServer(); } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlotPatch.AfterOnSyncedWithServer: {arg}"); } } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] [HarmonyPostfix] private static void AfterResetShip() { try { ExtraSlotManager.ClearAllBonusSlots(); } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlotPatch.AfterResetShip: {arg}"); } } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void AfterDisconnect() { try { ExtraSlotManager.ClearAllBonusSlots(); } catch (Exception arg) { Plugin.Log.LogError((object)$"ExtraSlotPatch.AfterDisconnect: {arg}"); } } [HarmonyPatch(typeof(Keybinds), "OnPressItemSlotHotkeyAction")] [HarmonyTranspiler] private static IEnumerable PatchKeybindHotbarSizeCheck(IEnumerable instructions) { return ReplaceCurrentHotbarSizeGetter(instructions, "Keybinds.OnPressItemSlotHotkeyAction"); } [HarmonyPatch(typeof(SyncManager), "SwapHotbarSlot")] [HarmonyTranspiler] private static IEnumerable PatchSwapHotbarSizeCheck(IEnumerable instructions) { return ReplaceCurrentHotbarSizeGetter(instructions, "SyncManager.SwapHotbarSlot"); } [HarmonyPatch(typeof(SyncManager), "CallSwitchToItemSlotMethod")] [HarmonyTranspiler] private static IEnumerable PatchCallSwitchHotbarSizeCheck(IEnumerable instructions) { return ReplaceCurrentHotbarSizeGetter(instructions, "SyncManager.CallSwitchToItemSlotMethod"); } [IteratorStateMachine(typeof(d__9))] private static IEnumerable ReplaceCurrentHotbarSizeGetter(IEnumerable instructions, string methodName) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__9(-2) { <>3__instructions = instructions, <>3__methodName = methodName }; } } [HarmonyPatch] internal static class FlareBurstPatch { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnReceiveFlareEvent; } [CompilerGenerated] private sealed class d__16 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float initialStun; public List stunned; public float fleeSeconds; public PlayerControllerB player; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__16(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(initialStun + 0.05f); <>1__state = 1; return true; case 1: { <>1__state = -1; for (int i = 0; i < stunned.Count; i++) { EnemyAI val = stunned[i]; if (!((Object)(object)val == (Object)null) && !val.isEnemyDead) { val.SetEnemyStunned(true, fleeSeconds, player); } } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__22 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Light light; public float duration; public GameObject holder; private float 5__2; private float 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__22(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = 0f; 5__3 = light.intensity; break; case 1: <>1__state = -1; break; } if (5__2 < duration) { if ((Object)(object)light == (Object)null) { return false; } float num = 5__2 / duration; light.intensity = 5__3 * (1f - num * num); 5__2 += Time.deltaTime; <>2__current = null; <>1__state = 1; return true; } if ((Object)(object)holder != (Object)null) { Object.Destroy((Object)(object)holder); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__23 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private GameObject 5__2; private Image 5__3; private float 5__4; private float 5__5; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__23(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_00ed: 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_0115: 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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: { <>1__state = -1; if ((Object)(object)HUDManager.Instance == (Object)null || (Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null) { return false; } Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if ((Object)(object)canvas == (Object)null) { return false; } 5__2 = new GameObject("LGU_FlareFlashCanvas"); 5__2.transform.SetParent(((Component)canvas).transform, false); Canvas obj = 5__2.AddComponent(); obj.overrideSorting = true; obj.sortingOrder = 500; 5__2.AddComponent(); GameObject val = new GameObject("FlashPanel"); val.transform.SetParent(5__2.transform, false); 5__3 = val.AddComponent(); ((Graphic)5__3).color = new Color(1f, 1f, 0.95f, 0.9f); ((Graphic)5__3).raycastTarget = false; RectTransform component = val.GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; 5__4 = 0f; 5__5 = 0.5f; break; } case 1: <>1__state = -1; break; } if (5__4 < 5__5) { if ((Object)(object)5__3 == (Object)null) { return false; } float num = 5__4 / 5__5; ((Graphic)5__3).color = new Color(1f, 1f, 0.95f, 0.9f * (1f - num * num)); 5__4 += Time.deltaTime; <>2__current = null; <>1__state = 1; return true; } if ((Object)(object)5__2 != (Object)null) { Object.Destroy((Object)(object)5__2); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string MSG_FLARE_SYNC = "FlareBurst_FlashSync"; private const float MAX_TIER_COOLDOWN = 45f; private static bool _usedThisRound = false; private static bool _keyWasDown = false; private static float _cooldownEndTime = 0f; private static bool _networkHandlersRegistered = false; private const string HUD_SPRITE = "flare_hud"; private const int HUD_STACK_POSITION = 1; private static AudioClip _cachedFlashClip; private static bool _flashClipScanned = false; private static readonly string[] FlashKeywords = new string[9] { "flash", "flashbang", "bang", "stun", "explos", "blast", "boom", "spark", "zap" }; [HarmonyPatch(typeof(StartOfRound), "StartGame")] [HarmonyPostfix] private static void PostStartGame() { _usedThisRound = false; _keyWasDown = false; _cooldownEndTime = 0f; } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { UpgradeHUDManager.DestroyHUDElement("flare_hud"); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerControlled || (Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return; } UpdateHUD(__instance); if (__instance.isPlayerDead || ((Object)(object)__instance.quickMenuManager != (Object)null && __instance.quickMenuManager.isMenuOpen) || __instance.isTypingChat || __instance.inTerminalMenu) { return; } Keyboard current = Keyboard.current; if (current != null) { Key? flareBurstKey = Plugin.GetFlareBurstKey(); bool flag = (flareBurstKey.HasValue ? ((ButtonControl)current[flareBurstKey.Value]).isPressed : ((ButtonControl)current.vKey).isPressed); bool num = flag && !_keyWasDown; _keyWasDown = flag; if (num) { TryFireFlare(__instance); } } } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } private static void RegisterNetworkHandlers() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if (_networkHandlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnReceiveFlareEvent; if (obj == null) { HandleNamedMessageDelegate val = OnReceiveFlareEvent; <>O.<0>__OnReceiveFlareEvent = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("FlareBurst_FlashSync", (HandleNamedMessageDelegate)obj); _networkHandlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("FlareBurstPatch: RegisterNamedMessageHandler failed: " + ex.Message)); } } } private static void EnsureSpriteHUD() { if (!((Object)(object)UpgradeHUDManager.GetHUDElement("flare_hud") != (Object)null) && !((Object)(object)HUDManager.Instance == (Object)null) && !((Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null)) { Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if (!((Object)(object)canvas == (Object)null)) { UpgradeHUDManager.CreateHUDElement("flare_hud", 1, ((Component)canvas).transform); } } } private static void UpdateHUD(PlayerControllerB localPlayer) { if (!FlareBurstUpgrade.IsUnlocked()) { GameObject hUDElement = UpgradeHUDManager.GetHUDElement("flare_hud"); if ((Object)(object)hUDElement != (Object)null) { hUDElement.SetActive(false); } return; } if ((Object)(object)localPlayer == (Object)null || localPlayer.inTerminalMenu || localPlayer.isTypingChat || ((Object)(object)localPlayer.quickMenuManager != (Object)null && localPlayer.quickMenuManager.isMenuOpen)) { GameObject hUDElement2 = UpgradeHUDManager.GetHUDElement("flare_hud"); if ((Object)(object)hUDElement2 != (Object)null) { hUDElement2.SetActive(false); } return; } EnsureSpriteHUD(); GameObject hUDElement3 = UpgradeHUDManager.GetHUDElement("flare_hud"); if (!((Object)(object)hUDElement3 == (Object)null)) { hUDElement3.SetActive(true); bool flag = FlareBurstUpgrade.IsMaxTier(); if (flag && _cooldownEndTime > Time.time) { UpgradeHUDManager.SetCooldownActive("flare_hud", active: true); float num = _cooldownEndTime - Time.time; UpgradeHUDManager.UpdateFillBar("flare_hud", num / 45f); } else if (!flag && _usedThisRound) { UpgradeHUDManager.SetCooldownActive("flare_hud", active: true); UpgradeHUDManager.UpdateFillBar("flare_hud", 1f); } else { UpgradeHUDManager.SetCooldownActive("flare_hud", active: false); } } } private static void TryFireFlare(PlayerControllerB player) { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) if (!FlareBurstUpgrade.IsUnlocked()) { return; } bool flag = FlareBurstUpgrade.IsMaxTier(); if (flag) { if (_cooldownEndTime > Time.time) { float num = _cooldownEndTime - Time.time; HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("FLARE BURST", $"Cooldown: {num:F0}s", true, false, "LC_Tip1"); } return; } } else if (_usedThisRound) { HUDManager instance2 = HUDManager.Instance; if (instance2 != null) { instance2.DisplayTip("FLARE BURST", "Already used this round.", true, false, "LC_Tip1"); } return; } float radius = FlareBurstUpgrade.GetRadius(); float stunSeconds = FlareBurstUpgrade.GetStunSeconds(); if (radius <= 0f || stunSeconds <= 0f) { return; } if (flag) { _cooldownEndTime = Time.time + 45f; } else { _usedThisRound = true; } int tier = FlareBurstUpgrade.GetTier(); int num2 = 0; EnemyAI[] array = Object.FindObjectsOfType(); List list = new List(); foreach (EnemyAI val in array) { if (!((Object)(object)val == (Object)null) && !val.isEnemyDead && !(Vector3.Distance(((Component)val).transform.position, ((Component)player).transform.position) > radius)) { val.SetEnemyStunned(true, stunSeconds, player); list.Add(val); num2++; } } if (FlareBurstUpgrade.ShouldFlee() && list.Count > 0) { ((MonoBehaviour)player).StartCoroutine(ApplyFleeBump(list, stunSeconds, 4f, player)); } SpawnVisualBurst(player, radius); BroadcastFlareEvent(player); string arg = (flag ? " Recharging..." : ""); HUDManager instance3 = HUDManager.Instance; if (instance3 != null) { instance3.DisplayTip("FLARE BURST", $"Tier {tier} flare fired. {num2} enemies stunned.{arg}", false, false, "LC_Tip1"); } } [IteratorStateMachine(typeof(d__16))] private static IEnumerator ApplyFleeBump(List stunned, float initialStun, float fleeSeconds, PlayerControllerB player) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__16(0) { stunned = stunned, initialStun = initialStun, fleeSeconds = fleeSeconds, player = player }; } private static void SpawnVisualBurst(PlayerControllerB player, float radius) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) AudioClip val = ResolveFlashClip(); if ((Object)(object)val != (Object)null) { AudioSource.PlayClipAtPoint(val, ((Component)player).transform.position, 1f); } GameObject val2 = new GameObject("LGU_FlareBurst_Light"); val2.transform.position = ((Component)player).transform.position + Vector3.up * 1.2f; Light val3 = val2.AddComponent(); val3.type = (LightType)2; val3.color = new Color(1f, 0.98f, 0.9f); val3.intensity = 30f; val3.range = 50f; val3.shadows = (LightShadows)0; ((MonoBehaviour)player).StartCoroutine(FadeFlashLight(val2, val3, 0.6f)); ((MonoBehaviour)player).StartCoroutine(SpawnScreenFlash(player)); } private static AudioClip ResolveFlashClip() { if (_flashClipScanned) { return _cachedFlashClip; } _flashClipScanned = true; StunGrenadeItem[] array = Resources.FindObjectsOfTypeAll(); foreach (StunGrenadeItem val in array) { if ((Object)(object)val == (Object)null || (Object)(object)val.explodeSFX == (Object)null) { continue; } AudioClip explodeSFX = val.explodeSFX; if (!(explodeSFX.length > 2f) && !ShadowStepPatch.IsAudioBlocked(((Object)explodeSFX).name.ToLowerInvariant())) { _cachedFlashClip = explodeSFX; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[Flare Burst] Resolved flash clip: {((Object)explodeSFX).name} ({explodeSFX.length:F2}s)"); } return _cachedFlashClip; } } AudioClip[] array2 = Resources.FindObjectsOfTypeAll(); foreach (AudioClip val2 in array2) { if ((Object)(object)val2 == (Object)null || val2.length > 2f) { continue; } string nameLower = ((Object)val2).name.ToLowerInvariant(); if (!ShadowStepPatch.IsAudioBlocked(nameLower) && ShadowStepPatch.MatchesAnyKeyword(nameLower, FlashKeywords)) { _cachedFlashClip = val2; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)$"[Flare Burst] Resolved flash clip: {((Object)val2).name} ({val2.length:F2}s)"); } return _cachedFlashClip; } } ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)"[Flare Burst] No suitable flash clip found."); } return null; } [IteratorStateMachine(typeof(d__22))] private static IEnumerator FadeFlashLight(GameObject holder, Light light, float duration) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__22(0) { holder = holder, light = light, duration = duration }; } [IteratorStateMachine(typeof(d__23))] private static IEnumerator SpawnScreenFlash(PlayerControllerB player) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__23(0); } private static void BroadcastFlareEvent(PlayerControllerB player) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsClient || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); try { int num = (int)player.playerClientId; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("FlareBurst_FlashSync", val, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveFlareEvent(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) int num = default(int); try { ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("FlareBurstPatch: malformed flash sync: " + ex.Message)); } return; } int num2 = (((Object)(object)GameNetworkManager.Instance != (Object)null && (Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null) ? ((int)GameNetworkManager.Instance.localPlayerController.playerClientId) : (-1)); if (num != num2 && !((Object)(object)StartOfRound.Instance == (Object)null) && num >= 0 && num < StartOfRound.Instance.allPlayerScripts.Length) { PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[num]; if (!((Object)(object)val == (Object)null)) { SpawnRemoteFlash(((Component)val).transform.position); } } } private static void SpawnRemoteFlash(Vector3 position) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0011: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("LGU_FlareBurst_RemoteFlash"); val.transform.position = position + Vector3.up * 1.2f; Light val2 = val.AddComponent(); val2.type = (LightType)2; val2.color = Color.white; val2.intensity = 4f; val2.range = 18f; val2.shadows = (LightShadows)0; PlayerControllerB val3 = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val3 != (Object)null) { ((MonoBehaviour)val3).StartCoroutine(FadeFlashLight(val, val2, 0.4f)); } else { Object.Destroy((Object)(object)val, 0.4f); } AudioClip val4 = ResolveFlashClip(); if ((Object)(object)val4 != (Object)null) { AudioSource.PlayClipAtPoint(val4, position, 0.7f); } } } [HarmonyPatch] internal static class GlowInTheDarkPatch { private static GameObject _glowLight; [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { if (!GlowInTheDarkUpgrade.IsUnlocked()) { DestroyGlow(); } else if (__instance.isPlayerDead) { DestroyGlow(); } else if (!__instance.isInsideFactory) { DestroyGlow(); } else { EnsureGlow(__instance); } } } private static void EnsureGlow(PlayerControllerB player) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_glowLight != (Object)null) { return; } try { _glowLight = new GameObject("LGU_GlowInTheDark"); _glowLight.transform.SetParent(((Component)player).transform, false); _glowLight.transform.localPosition = new Vector3(0f, 1.5f, 0f); Light obj = _glowLight.AddComponent(); obj.type = (LightType)2; obj.range = 30f; obj.intensity = 0.15f; obj.color = new Color(0.8f, 0.9f, 1f); obj.shadows = (LightShadows)0; obj.bounceIntensity = 0f; Plugin.Log.LogInfo((object)"[LGUCustomUpgrades] Glow in the Dark light attached to local player."); } catch (Exception arg) { Plugin.Log.LogError((object)$"[LGUCustomUpgrades] Failed to create Glow in the Dark light: {arg}"); if ((Object)(object)_glowLight != (Object)null) { Object.Destroy((Object)(object)_glowLight); _glowLight = null; } } } private static void DestroyGlow() { if (!((Object)(object)_glowLight == (Object)null)) { Object.Destroy((Object)(object)_glowLight); _glowLight = null; } } [HarmonyPatch(typeof(StartOfRound), "StartGame")] [HarmonyPostfix] private static void PostStartGame() { DestroyGlow(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { DestroyGlow(); } } [HarmonyPatch(typeof(Landmine))] internal static class LandminePatch { [HarmonyPrefix] [HarmonyPatch("TriggerMineOnLocalClientByExiting")] private static bool PreventMineExplosion() { try { if (SpatialAwarenessUpgrade.HasTier(1)) { Plugin.Log.LogDebug((object)"Spatial Awareness T1: Prevented landmine explosion for local player."); return false; } } catch (Exception arg) { Plugin.Log.LogError((object)$"LandminePatch.PreventMineExplosion failed: {arg}"); } return true; } } [HarmonyPatch] internal static class LastWillPatch { private class BeaconPulse : MonoBehaviour { private Light _light; private float _min; private float _max; private float _period; private float _startTime; public void Init(Light light, float min, float max, float period) { _light = light; _min = min; _max = max; _period = Mathf.Max(0.05f, period); _startTime = Time.time; } private void Update() { if (!((Object)(object)_light == (Object)null)) { float num = (Time.time - _startTime) / _period; float num2 = 0.5f + 0.5f * Mathf.Sin(num * 2f * MathF.PI); _light.intensity = Mathf.Lerp(_min, _max, num2); } } } private class HudMarkerDriver : MonoBehaviour { private Vector3 _worldPos; private string _glyph; private GUIStyle _style; public void Init(Vector3 worldPos, string glyph) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) _worldPos = worldPos; _glyph = glyph; } private void OnGUI() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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) if (_style == null) { _style = new GUIStyle(GUI.skin.label); _style.fontSize = 22; _style.fontStyle = (FontStyle)1; _style.alignment = (TextAnchor)4; _style.normal.textColor = new Color(1f, 0.25f, 0.25f, 0.9f); } Camera main = Camera.main; if (!((Object)(object)main == (Object)null)) { Vector3 val = main.WorldToScreenPoint(_worldPos); if (!(val.z <= 0f)) { float num = val.x - 16f; float num2 = (float)Screen.height - val.y - 16f; GUI.Label(new Rect(num, num2, 32f, 32f), _glyph, _style); } } } } private class TrailDriver : MonoBehaviour { private Vector3 _start; private Vector3 _end; private LineRenderer _line; private float _nextRepathAt; private bool _repathed; public void Init(Vector3 start, Vector3 end) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) _start = start; _end = end; BuildLine(); Repath(); _nextRepathAt = Time.time + 30f; } private void BuildLine() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("LGU_LastWill_Trail"); val.transform.SetParent(((Component)this).transform, false); _line = val.AddComponent(); _line.startWidth = 0.18f; _line.endWidth = 0.18f; _line.useWorldSpace = true; ((Renderer)_line).material = new Material(Shader.Find("Sprites/Default")); _line.startColor = new Color(0.3f, 0.5f, 1f, 0.9f); _line.endColor = new Color(0.3f, 0.5f, 1f, 0.4f); _line.numCornerVertices = 2; } private void Update() { if (!_repathed && !(Time.time < _nextRepathAt)) { Repath(); _repathed = true; } } private void Repath() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_line == (Object)null) { return; } NavMeshPath val = new NavMeshPath(); NavMeshHit val2 = default(NavMeshHit); if (!NavMesh.SamplePosition(_start, ref val2, 5f, -1)) { Fallback(); return; } NavMeshHit val3 = default(NavMeshHit); if (!NavMesh.SamplePosition(_end, ref val3, 5f, -1)) { Fallback(); return; } if (!NavMesh.CalculatePath(((NavMeshHit)(ref val2)).position, ((NavMeshHit)(ref val3)).position, -1, val) || (int)val.status != 0) { Fallback(); return; } Vector3[] corners = val.corners; _line.positionCount = corners.Length; for (int i = 0; i < corners.Length; i++) { _line.SetPosition(i, corners[i] + Vector3.up * 0.1f); } } private void Fallback() { //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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) _line.positionCount = 2; _line.SetPosition(0, _start + Vector3.up * 0.1f); _line.SetPosition(1, _end + Vector3.up * 0.1f); } } private static GameObject _activeBeacon; private const float BEACON_PULSE_PERIOD = 1.4f; private const float BEACON_INTENSITY_MIN = 2f; private const float BEACON_INTENSITY_MAX = 9f; private const float BEACON_RANGE = 14f; private const float TRAIL_REFRESH_AFTER = 30f; private const float TRAIL_WIDTH = 0.18f; [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPostfix] private static void PostKillPlayer(PlayerControllerB __instance) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsOwner || (Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController || !SalvagerUpgrade.HasTier(2) || __instance.isInHangarShipRoom || !__instance.isInsideFactory) { return; } Vector3 position = ((Component)__instance).transform.position; SpawnBeacon(position); if (SalvagerUpgrade.HasTier(3)) { Vector3 val = ResolveEntrancePosition(position); if (val != Vector3.zero && (Object)(object)_activeBeacon != (Object)null) { _activeBeacon.AddComponent().Init(val, position); } } HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("SALVAGER", "Beacon dropped. Teammates can find your body.", false, false, "LC_Tip1"); } } catch (Exception arg) { Plugin.Log.LogError((object)$"LastWillPatch.PostKillPlayer failed: {arg}"); } } private static void SpawnBeacon(Vector3 pos) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown if ((Object)(object)_activeBeacon != (Object)null) { Object.Destroy((Object)(object)_activeBeacon); } GameObject val = new GameObject("LGU_LastWill_Beacon"); val.transform.position = pos + Vector3.up * 0.4f; Light val2 = val.AddComponent(); val2.type = (LightType)2; val2.color = new Color(1f, 0.2f, 0.2f); val2.intensity = 2f; val2.range = 14f; val2.shadows = (LightShadows)0; val.AddComponent().Init(val2, 2f, 9f, 1.4f); val.AddComponent().Init(pos, "X"); _activeBeacon = val; } private static Vector3 ResolveEntrancePosition(Vector3 deathPos) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) EntranceTeleport[] array = Object.FindObjectsOfType(); if (array == null || array.Length == 0) { return Vector3.zero; } EntranceTeleport val = null; float num = float.MaxValue; foreach (EntranceTeleport val2 in array) { if (!((Object)(object)val2 == (Object)null) && !val2.isEntranceToBuilding) { float num2 = Vector3.Distance(((Object)(object)val2.entrancePoint != (Object)null) ? val2.entrancePoint.position : ((Component)val2).transform.position, deathPos); if (num2 < num) { num = num2; val = val2; } } } if ((Object)(object)val == (Object)null) { return Vector3.zero; } if (!((Object)(object)val.entrancePoint != (Object)null)) { return ((Component)val).transform.position; } return val.entrancePoint.position; } } [HarmonyPatch] internal static class LethalHandsPatch { private static bool _inputsHooked; private static InputAction _activateItemAction; private static bool _isLeftPunch = true; private static float _lastPunchTime = 0f; private static bool _isSquaredUp = false; private const float AUTO_SQUARE_DOWN_DELAY = 5f; [HarmonyPatch(typeof(LethalHands), "SquareUpPerformed")] [HarmonyPrefix] private static bool PreSquareUpPerformed() { return false; } [HarmonyPatch(typeof(LethalHands), "RightPunchPerformed")] [HarmonyPrefix] private static bool PreRightPunchPerformed() { return false; } [HarmonyPatch(typeof(LethalHands), "LeftPunchPerformed")] [HarmonyPrefix] private static bool PreLeftPunchPerformed() { return false; } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void PostStartOfRoundAwake() { if (!_inputsHooked && !((Object)(object)IngamePlayerSettings.Instance?.playerInput == (Object)null)) { _activateItemAction = IngamePlayerSettings.Instance.playerInput.actions.FindAction("ActivateItem", false); if (_activateItemAction == null) { Plugin.Log.LogWarning((object)"LethalHandsPatch: could not find ActivateItem input action; punch input will not work."); return; } _activateItemAction.performed += OnActivateItemPerformed; _inputsHooked = true; Plugin.Log.LogInfo((object)"LethalHandsPatch: bound auto-punch handler to ActivateItem (LMB only)."); } } [HarmonyPatch(typeof(StartOfRound), "StartGame")] [HarmonyPostfix] private static void PostStartGame() { ResetLocalPunchState(); } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPostfix] private static void PostKillPlayer(PlayerControllerB __instance) { if (!((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { LethalHands instance = LethalHands.Instance; if ((Object)(object)instance != (Object)null && (_isSquaredUp || instance.isSquaredUp)) { instance.SquareDown(false); } ResetLocalPunchState(); } } private static void ResetLocalPunchState() { _isLeftPunch = true; _lastPunchTime = 0f; _isSquaredUp = false; } private static void OnActivateItemPerformed(CallbackContext ctx) { try { if (!((CallbackContext)(ref ctx)).performed || !LethalHandsUpgrade.IsUnlocked()) { return; } LethalHands instance = LethalHands.Instance; if ((Object)(object)instance == (Object)null) { return; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { return; } instance.playerControllerInstance = val; if (((NetworkBehaviour)val).IsOwner && val.isPlayerControlled && !val.isPlayerDead && (!((Object)(object)val.quickMenuManager != (Object)null) || !val.quickMenuManager.isMenuOpen) && !val.isTypingChat && !val.inSpecialInteractAnimation && !val.inTerminalMenu && !((Object)(object)val.currentlyHeldObjectServer != (Object)null) && !val.isHoldingObject && instance.punchingCoroutine == null && !(val.sprintMeter < instance.punchStaminaRequirement)) { instance.enemyPunchDamage = LethalHandsUpgrade.GetCurrentDamageMultiplier(); if (!_isSquaredUp) { int upgradeLevel = BaseUpgrade.GetUpgradeLevel("Lethal Hands Training"); instance.allowItems = upgradeLevel >= 2; instance.SquareUp(); _isSquaredUp = true; } IEnumerator enumerator = (_isLeftPunch ? instance.LeftPunch() : instance.RightPunch()); instance.punchingCoroutine = ((MonoBehaviour)instance).StartCoroutine(enumerator); _isLeftPunch = !_isLeftPunch; _lastPunchTime = Time.time; } } catch (Exception arg) { Plugin.Log.LogError((object)$"LethalHandsPatch.OnActivateItemPerformed threw: {arg}"); } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostPlayerLateUpdate(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) && _isSquaredUp) { LethalHands instance = LethalHands.Instance; if (!((Object)(object)instance == (Object)null) && instance.punchingCoroutine == null && Time.time - _lastPunchTime > 5f) { instance.SquareDown(true); _isSquaredUp = false; _isLeftPunch = true; } } } [HarmonyPatch(typeof(PlayerControllerB), "GrabObject")] [HarmonyPrefix] private static void PreGrabObject(PlayerControllerB __instance) { if (!((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { LethalHands instance = LethalHands.Instance; if (!((Object)(object)instance == (Object)null) && (_isSquaredUp || instance.isSquaredUp)) { instance.SquareDown(false); _isSquaredUp = false; _isLeftPunch = true; } } } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] [HarmonyPrefix] private static bool PreBeginGrabObject(PlayerControllerB __instance) { if ((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return true; } if ((Object)(object)LethalHands.Instance == (Object)null) { return true; } if (LethalHands.Instance.punchingCoroutine == null) { return true; } return false; } [HarmonyPatch(typeof(LethalHands), "LoadConfigValues")] [HarmonyPostfix] private static void PostLoadConfigValues(LethalHands __instance) { if (LethalHandsUpgrade.IsUnlocked()) { __instance.enemyPunchDamage = LethalHandsUpgrade.GetCurrentDamageMultiplier(); } } [HarmonyPatch(typeof(EnemyAI), "HitEnemyOnLocalClient")] [HarmonyPostfix] private static void PostHitEnemyOnLocalClient(EnemyAI __instance, int force, PlayerControllerB playerWhoHit) { if (!((Object)(object)__instance == (Object)null) && force == -22 && !((Object)(object)playerWhoHit == (Object)null) && !((Object)(object)GameNetworkManager.Instance == (Object)null) && !((Object)(object)playerWhoHit != (Object)(object)GameNetworkManager.Instance.localPlayerController) && !__instance.isEnemyDead && LethalHandsUpgrade.ShouldStun()) { __instance.SetEnemyStunned(true, 1f, playerWhoHit); } } } [HarmonyPatch] internal static class MaskedPatch { private static bool LocalPlayerIsInvisibleToMasked() { return SpatialAwarenessUpgrade.HasTier(4); } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyAI), "CheckLineOfSightForClosestPlayer")] private static void PreventMaskedTargeting(EnemyAI __instance, ref PlayerControllerB __result) { try { if (__instance is MaskedPlayerEnemy && (Object)(object)__result != (Object)null && (Object)(object)__result == (Object)(object)GameNetworkManager.Instance.localPlayerController && LocalPlayerIsInvisibleToMasked()) { __result = null; } } catch (Exception arg) { Plugin.Log.LogError((object)$"MaskedPatch.PreventMaskedTargeting failed: {arg}"); } } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyAI), "GetClosestPlayer")] private static void PreventMaskedProximityTarget(EnemyAI __instance, ref PlayerControllerB __result) { try { if (__instance is MaskedPlayerEnemy && (Object)(object)__result != (Object)null && (Object)(object)__result == (Object)(object)GameNetworkManager.Instance.localPlayerController && LocalPlayerIsInvisibleToMasked()) { __result = null; } } catch (Exception arg) { Plugin.Log.LogError((object)$"MaskedPatch.PreventMaskedProximityTarget failed: {arg}"); } } [HarmonyPrefix] [HarmonyPatch(typeof(MaskedPlayerEnemy), "OnCollideWithPlayer")] private static bool PreventMaskedKill(Collider other) { try { PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component == (Object)(object)GameNetworkManager.Instance.localPlayerController && LocalPlayerIsInvisibleToMasked()) { return false; } } catch (Exception arg) { Plugin.Log.LogError((object)$"MaskedPatch.PreventMaskedKill failed: {arg}"); } return true; } [HarmonyPostfix] [HarmonyPatch(typeof(MaskedPlayerEnemy), "DoAIInterval")] private static void ClearMaskedTarget(MaskedPlayerEnemy __instance) { try { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && (Object)(object)((EnemyAI)__instance).targetPlayer == (Object)(object)GameNetworkManager.Instance.localPlayerController && LocalPlayerIsInvisibleToMasked()) { ((EnemyAI)__instance).targetPlayer = null; ((EnemyAI)__instance).movingTowardsTargetPlayer = false; } } catch (Exception arg) { Plugin.Log.LogError((object)$"MaskedPatch.ClearMaskedTarget failed: {arg}"); } } } [HarmonyPatch] internal static class PipeBombPatch { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnReceiveThrowEvent; } [CompilerGenerated] private sealed class d__19 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public bool isLocalThrower; public ulong playerNetObjId; public Vector3 pos; public Vector3 dir; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__19(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!isLocalThrower) { TriggerRemoteThrowAnim(playerNetObjId); } <>2__current = (object)new WaitForSeconds(0.3f); <>1__state = 1; return true; case 1: <>1__state = -1; PipeBombProjectile.Spawn(pos, dir, Plugin.PipeBombThrowForce.Value); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string MSG_THROW_SYNC = "PipeBomb_Throw"; private const float THROW_RELEASE_DELAY = 0.3f; private const int HUD_STACK_POSITION = 3; private static string _hudSpriteName; private static TextMeshProUGUI _hudOverlayText; private static int _chargesRemaining; private static float _cooldownTimer; private static bool _keyWasDown; private static bool _handlersRegistered; private static AudioClip _pinPullClip; private static bool _audioInitialized; [HarmonyPatch(typeof(StartOfRound), "StartGame")] [HarmonyPostfix] private static void PostStartGame() { try { _chargesRemaining = PipeBombUpgrade.GetMaxCharges(); _cooldownTimer = 0f; _keyWasDown = false; } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[PipeBomb] PostStartGame failed: {arg}"); } } } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { try { PipeBombProjectile.DestroyAllActive(); DestroyHUD(); _chargesRemaining = 0; _cooldownTimer = 0f; } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[PipeBomb] PostEndOfGame failed: {arg}"); } } } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); EnsureAudioInitialized(); } private static void RegisterNetworkHandlers() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if (_handlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnReceiveThrowEvent; if (obj == null) { HandleNamedMessageDelegate val = OnReceiveThrowEvent; <>O.<0>__OnReceiveThrowEvent = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("PipeBomb_Throw", (HandleNamedMessageDelegate)obj); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[PipeBomb] RegisterNamedMessageHandler failed: " + ex.Message)); } } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerControlled || (Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return; } if (_cooldownTimer > 0f) { _cooldownTimer = Mathf.Max(0f, _cooldownTimer - Time.deltaTime); } UpdateHUD(__instance); if (__instance.isPlayerDead || ((Object)(object)__instance.quickMenuManager != (Object)null && __instance.quickMenuManager.isMenuOpen) || __instance.isTypingChat || __instance.inTerminalMenu || __instance.inSpecialInteractAnimation) { return; } Keyboard current = Keyboard.current; if (current != null) { Key? pipeBombKey = Plugin.GetPipeBombKey(); bool flag = (pipeBombKey.HasValue ? ((ButtonControl)current[pipeBombKey.Value]).isPressed : ((ButtonControl)current.gKey).isPressed); bool num = flag && !_keyWasDown; _keyWasDown = flag; if (num) { TryThrow(__instance); } } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[PipeBomb] PostPlayerUpdate failed: {arg}"); } } } private static void TryThrow(PlayerControllerB player) { //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013f: 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_00e5: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)StartOfRound.Instance == (Object)null) && PipeBombUpgrade.IsUnlocked() && !player.isInHangarShipRoom && !StartOfRound.Instance.inShipPhase && !(_cooldownTimer > 0f) && _chargesRemaining > 0) { _chargesRemaining--; _cooldownTimer = Plugin.PipeBombCooldown.Value; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[PipeBomb] Keybind pressed, throwing (charges remaining: {_chargesRemaining})"); } PlayPipeBombThrowAnim(player.playerBodyAnimator); if ((Object)(object)_pinPullClip != (Object)null && (Object)(object)HUDManager.Instance != (Object)null && (Object)(object)HUDManager.Instance.UIAudio != (Object)null) { HUDManager.Instance.UIAudio.PlayOneShot(_pinPullClip, 0.7f); } Vector3 val = (((Object)(object)player.gameplayCamera != (Object)null) ? (((Component)player.gameplayCamera).transform.position + ((Component)player.gameplayCamera).transform.forward * 0.4f) : (((Component)player).transform.position + ((Component)player).transform.forward * 0.4f + Vector3.up * 1.2f)); Vector3 dir = (((Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform.forward : ((Component)player).transform.forward); ulong networkObjectId = ((NetworkBehaviour)player).NetworkObjectId; Vector3 val2 = ((Vector3)(ref dir)).normalized * Plugin.PipeBombThrowForce.Value; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)$"[PipeBomb] Projectile spawn requested at ({val.x:F2},{val.y:F2},{val.z:F2}) with force ({val2.x:F2},{val2.y:F2},{val2.z:F2})"); } BroadcastThrow(networkObjectId, val, dir); ((MonoBehaviour)player).StartCoroutine(DelayedSpawn(networkObjectId, val, dir, isLocalThrower: true)); } } private static void BroadcastThrow(ulong playerNetObjId, Vector3 pos, Vector3 dir) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsClient || NetworkManager.Singleton.CustomMessagingManager == null) { return; } int num = 32; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerNetObjId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref pos.x, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref pos.y, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref pos.z, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref dir.x, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref dir.y, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref dir.z, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("PipeBomb_Throw", val, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveThrowEvent(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) try { ulong num = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); float num4 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num4, default(ForPrimitives)); float num5 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num5, default(ForPrimitives)); float num6 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num6, default(ForPrimitives)); float num7 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num7, default(ForPrimitives)); Vector3 pos = default(Vector3); ((Vector3)(ref pos))..ctor(num2, num3, num4); Vector3 dir = default(Vector3); ((Vector3)(ref dir))..ctor(num5, num6, num7); PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val != (Object)null) || ((NetworkBehaviour)val).NetworkObjectId != num) { MonoBehaviour val2 = (MonoBehaviour)(((Object)(object)HUDManager.Instance != (Object)null) ? ((object)HUDManager.Instance) : ((object)Object.FindObjectOfType())); if ((Object)(object)val2 == (Object)null) { SpawnRemoteAnimAndProjectile(num, pos, dir); } else { val2.StartCoroutine(DelayedSpawn(num, pos, dir, isLocalThrower: false)); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[PipeBomb] malformed throw sync: " + ex.Message)); } } } [IteratorStateMachine(typeof(d__19))] private static IEnumerator DelayedSpawn(ulong playerNetObjId, Vector3 pos, Vector3 dir, bool isLocalThrower) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__19(0) { playerNetObjId = playerNetObjId, pos = pos, dir = dir, isLocalThrower = isLocalThrower }; } private static void SpawnRemoteAnimAndProjectile(ulong playerNetObjId, Vector3 pos, Vector3 dir) { //IL_0006: 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) TriggerRemoteThrowAnim(playerNetObjId); PipeBombProjectile.Spawn(pos, dir, Plugin.PipeBombThrowForce.Value); } private static void TriggerRemoteThrowAnim(ulong playerNetObjId) { if ((Object)(object)StartOfRound.Instance == (Object)null) { return; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (!((Object)(object)val == (Object)null) && ((NetworkBehaviour)val).NetworkObjectId == playerNetObjId) { PlayPipeBombThrowAnim(val.playerBodyAnimator); break; } } } private static string ResolveHudSpriteName() { if (_hudSpriteName != null) { return _hudSpriteName; } UpgradeHUDManager.LoadBundle(); _hudSpriteName = UpgradeHUDManager.ResolveSpriteName("pipebomb_hud", "pipe_hud", "pipe_bomb_hud"); return _hudSpriteName; } private static void EnsureSpriteHUD() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) string text = ResolveHudSpriteName(); if (text == null || (Object)(object)UpgradeHUDManager.GetHUDElement(text) != (Object)null || (Object)(object)HUDManager.Instance == (Object)null || (Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null) { return; } Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if (!((Object)(object)canvas == (Object)null)) { GameObject val = UpgradeHUDManager.CreateHUDElement(text, 3, ((Component)canvas).transform); if (!((Object)(object)val == (Object)null)) { GameObject val2 = new GameObject("ChargeText"); val2.transform.SetParent(val.transform, false); RectTransform obj = val2.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = new Vector2(4f, 0f); obj.offsetMax = new Vector2(-4f, 0f); _hudOverlayText = val2.AddComponent(); ((TMP_Text)_hudOverlayText).fontSize = 12f; ((Graphic)_hudOverlayText).color = Color32.op_Implicit(new Color32((byte)0, (byte)200, (byte)0, byte.MaxValue)); ((TMP_Text)_hudOverlayText).alignment = (TextAlignmentOptions)516; ((TMP_Text)_hudOverlayText).text = string.Empty; ((Graphic)_hudOverlayText).raycastTarget = false; } } } private static void UpdateHUD(PlayerControllerB player) { string text = ResolveHudSpriteName(); if (text == null) { return; } if (!PipeBombUpgrade.IsUnlocked()) { GameObject hUDElement = UpgradeHUDManager.GetHUDElement(text); if ((Object)(object)hUDElement != (Object)null) { hUDElement.SetActive(false); } return; } if ((Object)(object)player == (Object)null || player.isInHangarShipRoom || ((Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.inShipPhase) || ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen)) { GameObject hUDElement2 = UpgradeHUDManager.GetHUDElement(text); if ((Object)(object)hUDElement2 != (Object)null) { hUDElement2.SetActive(false); } return; } EnsureSpriteHUD(); GameObject hUDElement3 = UpgradeHUDManager.GetHUDElement(text); if ((Object)(object)hUDElement3 == (Object)null) { return; } hUDElement3.SetActive(true); int maxCharges = PipeBombUpgrade.GetMaxCharges(); PipeBombProjectile activeLandedBomb = GetActiveLandedBomb(); if ((Object)(object)activeLandedBomb != (Object)null) { float num = Mathf.Max(0f, activeLandedBomb._detonationTime - Time.time); float num2 = Mathf.Max(0.01f, Plugin.PipeBombLureDuration.Value); UpgradeHUDManager.SetCooldownActive(text, active: true); UpgradeHUDManager.UpdateFillBar(text, num / num2); if ((Object)(object)_hudOverlayText != (Object)null) { ((TMP_Text)_hudOverlayText).text = $"{num:F1}s"; } } else if (_cooldownTimer > 0f) { float num3 = Mathf.Max(0.01f, Plugin.PipeBombCooldown.Value); UpgradeHUDManager.SetCooldownActive(text, active: true); UpgradeHUDManager.UpdateFillBar(text, _cooldownTimer / num3); if ((Object)(object)_hudOverlayText != (Object)null) { ((TMP_Text)_hudOverlayText).text = $"{_chargesRemaining}/{maxCharges}"; } } else if (_chargesRemaining <= 0) { UpgradeHUDManager.SetCooldownActive(text, active: true); UpgradeHUDManager.UpdateFillBar(text, 1f); if ((Object)(object)_hudOverlayText != (Object)null) { ((TMP_Text)_hudOverlayText).text = "0"; } } else { UpgradeHUDManager.SetCooldownActive(text, active: false); if ((Object)(object)_hudOverlayText != (Object)null) { ((TMP_Text)_hudOverlayText).text = $"{_chargesRemaining}/{maxCharges}"; } } } private static PipeBombProjectile GetActiveLandedBomb() { for (int i = 0; i < PipeBombProjectile.ActiveBombs.Count; i++) { PipeBombProjectile pipeBombProjectile = PipeBombProjectile.ActiveBombs[i]; if (!((Object)(object)pipeBombProjectile == (Object)null) && pipeBombProjectile._detonationTime > 0f && Time.time < pipeBombProjectile._detonationTime) { return pipeBombProjectile; } } return null; } private static void DestroyHUD() { if (_hudSpriteName != null) { UpgradeHUDManager.DestroyHUDElement(_hudSpriteName); } _hudOverlayText = null; } private static void PlayPipeBombThrowAnim(Animator animator) { if ((Object)(object)animator == (Object)null) { return; } try { animator.Play("PullGrenadePinHomemade", 3, 0f); animator.SetTrigger("PullGrenadePin"); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[PipeBomb] PlayPipeBombThrowAnim failed: " + ex.Message)); } } } private static void EnsureAudioInitialized() { if (_audioInitialized) { return; } _audioInitialized = true; try { _pinPullClip = GenerateSineBeep("LGU_PipeBomb_PinPull", 2000f, 0.05f); PipeBombProjectile.BeepClip = GenerateSineBeep("LGU_PipeBomb_Beep", 800f, 0.05f); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[PipeBomb] Procedural beep/pin-pull clips initialized"); } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[PipeBomb] Procedural audio gen failed: " + ex.Message)); } } } private static AudioClip GenerateSineBeep(string name, float frequency, float duration) { int num = (int)(44100f * duration); float[] array = new float[num]; for (int i = 0; i < num; i++) { float num2 = (float)i / 44100f; array[i] = Mathf.Sin(MathF.PI * 2f * frequency * num2) * 0.7f; } AudioClip obj = AudioClip.Create(name, num, 1, 44100, false); obj.SetData(array, 0); return obj; } } [HarmonyPatch(typeof(PlayerControllerB))] internal static class PlayerControllerBPatch { [CompilerGenerated] private sealed class d__8 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Vector3 deathPosition; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.8f); <>1__state = 1; return true; case 1: { <>1__state = -1; if (!BaseUpgrade.GetActiveUpgrade("Salvager")) { return false; } GrabbableObject[] array = Object.FindObjectsOfType(); int num = 0; GrabbableObject[] array2 = array; foreach (GrabbableObject val in array2) { if (!((Object)(object)val == (Object)null) && !val.isHeld && !val.isInShipRoom && !(Vector3.Distance(((Component)val).transform.position, deathPosition) > 12f) && !((Object)(object)((Component)val).gameObject.GetComponent() != (Object)null)) { ((Component)val).gameObject.AddComponent().Initialize(); num++; } } if (num > 0) { Plugin.Log.LogDebug((object)$"Salvager fallback: Added glow to {num} items near death position."); } return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static bool isDeathDrop = false; private static readonly List capturedDeathItems = new List(); [HarmonyPrefix] [HarmonyPatch("KillPlayer")] private static void KillPlayerPrefix() { isDeathDrop = true; } [HarmonyPostfix] [HarmonyPatch("KillPlayer")] private static void KillPlayerPostfix() { isDeathDrop = false; } [HarmonyPrefix] [HarmonyPatch("KillPlayerClientRpc")] private static void KillPlayerClientRpcPrefix() { isDeathDrop = true; } [HarmonyPostfix] [HarmonyPatch("KillPlayerClientRpc")] private static void KillPlayerClientRpcPostfix(PlayerControllerB __instance, int playerId) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) isDeathDrop = false; LoneWolfUpgrade.CheckAndActivate(); if (BaseUpgrade.GetActiveUpgrade("Salvager")) { Vector3 position = ((Component)StartOfRound.Instance.allPlayerScripts[playerId]).transform.position; ((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(AddDeathItemGlow(position)); } } [HarmonyPrefix] [HarmonyPatch("DropAllHeldItems")] private static void DropAllHeldItemsPrefix(PlayerControllerB __instance) { capturedDeathItems.Clear(); if (!isDeathDrop || !BaseUpgrade.GetActiveUpgrade("Salvager")) { return; } for (int i = 0; i < __instance.ItemSlots.Length; i++) { if ((Object)(object)__instance.ItemSlots[i] != (Object)null) { capturedDeathItems.Add(__instance.ItemSlots[i]); } } } [HarmonyPostfix] [HarmonyPatch("DropAllHeldItems")] private static void DropAllHeldItemsPostfix() { if (capturedDeathItems.Count == 0) { return; } foreach (GrabbableObject capturedDeathItem in capturedDeathItems) { if ((Object)(object)capturedDeathItem != (Object)null && (Object)(object)((Component)capturedDeathItem).gameObject.GetComponent() == (Object)null) { ((Component)capturedDeathItem).gameObject.AddComponent().Initialize(); } } Plugin.Log.LogDebug((object)$"Salvager: Added glow to {capturedDeathItems.Count} death-dropped items."); capturedDeathItems.Clear(); } [IteratorStateMachine(typeof(d__8))] private static IEnumerator AddDeathItemGlow(Vector3 deathPosition) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__8(0) { deathPosition = deathPosition }; } [HarmonyPostfix] [HarmonyPatch("Update")] private static void UpdatePostfix(PlayerControllerB __instance) { if (((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance.localPlayerController) && LoneWolfUpgrade.LoneWolfActive) { if (__instance.isInHangarShipRoom) { LoneWolfUpgrade.Deactivate(); } else { LoneWolfUpgrade.ApplyStaminaBonus(__instance); } } } } [HarmonyPatch(typeof(StartOfRound))] internal static class StartOfRoundPatch { [HarmonyPostfix] [HarmonyPatch("ShipLeave")] private static void ShipLeavePostfix() { LoneWolfUpgrade.Deactivate(); } [HarmonyPostfix] [HarmonyPatch("ReviveDeadPlayers")] private static void ReviveDeadPlayersPostfix() { LoneWolfUpgrade.Deactivate(); } } internal class SalvagerGlow : MonoBehaviour { private Light glowLight; private GrabbableObject item; public void Initialize() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) item = ((Component)this).GetComponent(); glowLight = ((Component)this).gameObject.AddComponent(); glowLight.type = (LightType)2; glowLight.color = new Color(0.3f, 0.9f, 0.5f); glowLight.intensity = 1.5f; glowLight.range = 5f; glowLight.shadows = (LightShadows)0; } private void Update() { if ((Object)(object)item != (Object)null && (item.isHeld || item.isInShipRoom)) { if ((Object)(object)glowLight != (Object)null) { Object.Destroy((Object)(object)glowLight); } Object.Destroy((Object)(object)this); } } private void OnDestroy() { if ((Object)(object)glowLight != (Object)null) { Object.Destroy((Object)(object)glowLight); } } } [HarmonyPatch] internal static class PredatorInstinctPatch { private const string MARKER_NAME = "LGU_PredatorInstinct_Marker"; private const float HEARTBEAT_INTERVAL_AT_FAR = 1.6f; private const float HEARTBEAT_INTERVAL_AT_CLOSE = 0.45f; private static AudioClip _heartbeatClip; private static AudioSource _heartbeatSource; private static float _nextHeartbeatTime; private static EnemyAI[] _cachedEnemies = Array.Empty(); private static float _nextEnemyScanTime; private const float ENEMY_SCAN_INTERVAL = 0.5f; private static readonly Dictionary _markerCache = new Dictionary(); [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerControlled || (Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return; } if (__instance.isPlayerDead) { ClearAllMarkers(); StopHeartbeat(); return; } if (!PredatorInstinctUpgrade.IsUnlocked()) { ClearAllMarkers(); StopHeartbeat(); return; } float range = PredatorInstinctUpgrade.GetRange(); if (range <= 0f) { return; } if (Time.time >= _nextEnemyScanTime) { _cachedEnemies = Object.FindObjectsOfType(); _nextEnemyScanTime = Time.time + 0.5f; } float num = range * range; float num2 = float.MaxValue; EnemyAI[] cachedEnemies = _cachedEnemies; foreach (EnemyAI val in cachedEnemies) { if ((Object)(object)val == (Object)null) { continue; } if (val.isEnemyDead) { if (_markerCache.TryGetValue(val, out var value)) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } _markerCache.Remove(val); } continue; } Vector3 val2 = ((Component)val).transform.position - ((Component)__instance).transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; Light value2; bool flag = _markerCache.TryGetValue(val, out value2) && (Object)(object)value2 != (Object)null; if (sqrMagnitude <= num) { if (!flag) { AddMarker(val); } if (sqrMagnitude < num2) { num2 = sqrMagnitude; } } else if (flag) { Object.Destroy((Object)(object)((Component)value2).gameObject); _markerCache.Remove(val); } } if (PredatorInstinctUpgrade.ShouldHeartbeat() && num2 < float.MaxValue) { EnsureHeartbeatSource(__instance); float num3 = Mathf.Clamp01(Mathf.Sqrt(num2) / range); float num4 = Mathf.Lerp(0.45f, 1.6f, num3); if (Time.time >= _nextHeartbeatTime) { _heartbeatSource.PlayOneShot(_heartbeatClip); _nextHeartbeatTime = Time.time + num4; } } else { StopHeartbeat(); } } private static void AddMarker(EnemyAI enemy) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("LGU_PredatorInstinct_Marker"); val.transform.SetParent(((Component)enemy).transform, false); val.transform.localPosition = Vector3.up * 0.6f; Light val2 = val.AddComponent(); val2.type = (LightType)2; val2.color = new Color(1f, 0.15f, 0.15f); val2.intensity = 4f; val2.range = 6f; val2.shadows = (LightShadows)0; _markerCache[enemy] = val2; } private static void ClearAllMarkers() { foreach (KeyValuePair item in _markerCache) { if ((Object)(object)item.Value != (Object)null) { Object.Destroy((Object)(object)((Component)item.Value).gameObject); } } _markerCache.Clear(); _cachedEnemies = Array.Empty(); _nextEnemyScanTime = 0f; } private static void EnsureHeartbeatSource(PlayerControllerB player) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_heartbeatClip == (Object)null) { _heartbeatClip = BuildHeartbeatClip(); } if ((Object)(object)_heartbeatSource == (Object)null || (Object)(object)((Component)_heartbeatSource).gameObject == (Object)null) { Camera val = (((Object)(object)player.gameplayCamera != (Object)null) ? player.gameplayCamera : Camera.main); Transform val2 = (((Object)(object)val != (Object)null) ? ((Component)val).transform : ((Component)player).transform); GameObject val3 = new GameObject("LGU_PredatorInstinct_HeartbeatSrc"); val3.transform.SetParent(val2, false); _heartbeatSource = val3.AddComponent(); _heartbeatSource.spatialBlend = 0f; _heartbeatSource.volume = 0.55f; _heartbeatSource.playOnAwake = false; _nextHeartbeatTime = 0f; } } private static void StopHeartbeat() { if (!((Object)(object)_heartbeatSource == (Object)null)) { _heartbeatSource.Stop(); Object.Destroy((Object)(object)((Component)_heartbeatSource).gameObject); _heartbeatSource = null; _nextHeartbeatTime = 0f; } } private static AudioClip BuildHeartbeatClip() { int num = Mathf.CeilToInt(7717.5f); float[] array = new float[num]; float num2 = 0f; float num3 = 0.13f; float num4 = 55f; float num5 = 70f; float num6 = 18f; for (int i = 0; i < num; i++) { float num7 = (float)i / 22050f; float num8 = ((num7 >= num2) ? (Mathf.Sin(MathF.PI * 2f * num4 * (num7 - num2)) * Mathf.Exp((0f - num6) * (num7 - num2))) : 0f); float num9 = ((num7 >= num3) ? (Mathf.Sin(MathF.PI * 2f * num5 * (num7 - num3)) * Mathf.Exp((0f - num6) * (num7 - num3)) * 0.85f) : 0f); array[i] = Mathf.Clamp(num8 + num9, -1f, 1f); } AudioClip obj = AudioClip.Create("LGU_PredatorInstinct_Heartbeat", num, 1, 22050, false); obj.SetData(array, 0); return obj; } } [HarmonyPatch] internal static class ProteinPowderFix { private const string PROTEIN_POWDER_NAME = "Protein Powder"; private const int LETHAL_HANDS_PUNCH_FORCE = -22; [HarmonyPatch(typeof(EnemyAI), "HitEnemyOnLocalClient")] [HarmonyPrefix] private static void PreHitEnemyOnLocalClient(ref int force, PlayerControllerB playerWhoHit) { if (force == -22 || force <= 0 || (Object)(object)playerWhoHit == (Object)null || (Object)(object)playerWhoHit != (Object)(object)GameNetworkManager.Instance?.localPlayerController || !BaseUpgrade.GetActiveUpgrade("Protein Powder")) { return; } GrabbableObject currentlyHeldObjectServer = playerWhoHit.currentlyHeldObjectServer; if (!((Object)(object)currentlyHeldObjectServer == (Object)null) && !(currentlyHeldObjectServer is Shovel) && !(currentlyHeldObjectServer is KnifeItem)) { int num = force; int shovelHitForce = ProteinPowder.GetShovelHitForce(force); if (shovelHitForce != num) { force = shovelHitForce; Plugin.Log.LogDebug((object)$"ProteinPowderFix: buffed {((object)currentlyHeldObjectServer).GetType().Name} hit from {num} to {force}."); } } } } [HarmonyPatch] internal static class RetaliationPatch { private const float MELEE_RANGE = 8f; private const float TRACKER_VALIDITY_RANGE = 15f; private const float TRACKER_VALIDITY_WINDOW = 0.5f; private const float SPARK_DURATION_T1 = 0.15f; private const float SPARK_DURATION_T2 = 0.3f; private static AudioClip _sparkClip; private static bool _sparkClipSearched; private static EnemyAI _lastAttacker; private static float _lastAttackerTime = -1f; private static void RecordAttacker(EnemyAI enemy) { if (!((Object)(object)enemy == (Object)null)) { _lastAttacker = enemy; _lastAttackerTime = Time.time; } } [HarmonyPatch(typeof(EnemyAI), "OnCollideWithPlayer")] [HarmonyPrefix] private static void PreEnemyAIOnCollideWithPlayer(EnemyAI __instance, Collider other) { if (!((Object)(object)other == (Object)null)) { PlayerControllerB component = ((Component)other).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { RecordAttacker(__instance); } } } private static EnemyAI GetRecentAttacker(PlayerControllerB player) { //IL_0037: 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) if ((Object)(object)_lastAttacker == (Object)null) { return null; } if (Time.time - _lastAttackerTime > 0.5f) { return null; } if (_lastAttacker.isEnemyDead) { return null; } if (Vector3.Distance(((Component)player).transform.position, ((Component)_lastAttacker).transform.position) > 15f) { return null; } return _lastAttacker; } private static EnemyAI FindClosestEnemy(PlayerControllerB player) { //IL_0030: 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) EnemyAI result = null; float num = 8f; EnemyAI[] array = Object.FindObjectsOfType(); foreach (EnemyAI val in array) { if (!((Object)(object)val == (Object)null) && !val.isEnemyDead) { float num2 = Vector3.Distance(((Component)player).transform.position, ((Component)val).transform.position); if (num2 < num) { num = num2; result = val; } } } return result; } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPostfix] private static void PostDamagePlayer(PlayerControllerB __instance, int damageNumber, bool fallDamage, CauseOfDeath causeOfDeath) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController || fallDamage || damageNumber <= 0 || __instance.isPlayerDead || !IsEnemyCause(causeOfDeath) || !BaseUpgrade.GetActiveUpgrade("Retaliation")) { return; } EnemyAI val = GetRecentAttacker(__instance) ?? FindClosestEnemy(__instance); if (!((Object)(object)val == (Object)null)) { int upgradeLevel = BaseUpgrade.GetUpgradeLevel("Retaliation"); if (upgradeLevel >= 1 || Random.value < 0.5f) { val.HitEnemyOnLocalClient(1, ((Component)__instance).transform.forward, __instance, false, -1); } if (upgradeLevel >= 1 && !val.isEnemyDead) { val.SetEnemyStunned(true, 1f, __instance); } float duration = ((upgradeLevel >= 1) ? 0.3f : 0.15f); SpawnSparkEffect(val, upgradeLevel >= 1, duration); } } private static bool IsEnemyCause(CauseOfDeath cause) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected I4, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 switch (cause - 1) { default: if ((int)cause != 14) { break; } goto case 0; case 0: case 3: case 4: case 5: case 7: return true; case 1: case 2: case 6: break; } return false; } private static void SpawnSparkEffect(EnemyAI enemy, bool tier2, float duration) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_006c: 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_00ac: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)enemy).transform.position + Vector3.up * 1f; GameObject val2 = new GameObject("LGU_RetaliationFlash"); val2.transform.position = val; Light obj = val2.AddComponent(); obj.type = (LightType)2; obj.color = (tier2 ? new Color(1f, 0.9f, 0.6f) : new Color(1f, 0.7f, 0.2f)); obj.intensity = (tier2 ? 12f : 8f); obj.range = (tier2 ? 7f : 5f); obj.shadows = (LightShadows)0; Object.Destroy((Object)val2, duration); AudioClip val3 = ResolveSparkClip(); if ((Object)(object)val3 != (Object)null) { AudioSource.PlayClipAtPoint(val3, val, tier2 ? 0.8f : 0.6f); } } private static AudioClip ResolveSparkClip() { if (_sparkClipSearched) { return _sparkClip; } _sparkClipSearched = true; AudioClip[] array = Resources.FindObjectsOfTypeAll(); AudioClip[] array2 = array; foreach (AudioClip val in array2) { if (!((Object)(object)val == (Object)null)) { string text = ((Object)val).name.ToLowerInvariant(); if (text.Contains("shock") || text.Contains("zap") || text.Contains("spark") || text.Contains("electric")) { _sparkClip = val; return _sparkClip; } } } array2 = array; foreach (AudioClip val2 in array2) { if (!((Object)(object)val2 == (Object)null)) { string text2 = ((Object)val2).name.ToLowerInvariant(); if (text2.Contains("impact") || text2.Contains("hit") || text2.Contains("zap")) { _sparkClip = val2; return _sparkClip; } } } return null; } } [HarmonyPatch] internal static class ShadowStepPatch { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnReceiveInvisibilityState; } private const string MSG_INVIS_SYNC = "ShadowStep_InvisSync"; private const float CLOSEST_PLAYER_BASELINE_RANGE = 40f; private static bool _keyWasDown = false; private static bool _handlersRegistered = false; private const string HUD_SPRITE = "shadow_hud"; private const int HUD_STACK_POSITION = 2; private static Dictionary _originalMaterials = new Dictionary(); private static Dictionary _ghostedRenderers = new Dictionary(); internal static readonly string[] AudioBlocklist = new string[12] { "music", "song", "track", "bgm", "ost", "theme", "ambient", "ambience", "synth", "loop", "score", "radio" }; private static AudioClip _activationClip; private static AudioClip _deactivationClip; private static float _originalAudioVolume = 1f; private static AudioSource _hissSource; private static AudioClip _hissClip; private static bool _cloakEffectsActive = false; private static GameObject _cloakVignetteObj; private static RawImage _cloakVignette; private static Texture2D _vignetteTexture; private static AudioClip GetActivationClip() { if ((Object)(object)_activationClip != (Object)null) { return _activationClip; } int num = 44100; float num2 = 0.25f; int num3 = (int)((float)num * num2); float[] array = new float[num3]; for (int i = 0; i < num3; i++) { float num4 = (float)i / (float)num; float num5 = num4 / num2; float num6 = Mathf.Lerp(1200f, 200f, num5); float num7 = Mathf.Exp((0f - num4) * 6f); float num8 = Mathf.Sin(MathF.PI * 2f * num6 * num4) * num7 * 1.5f; float num9 = Random.Range(-1f, 1f) * num7 * 0.3f; array[i] = Mathf.Clamp(num8 + num9, -1f, 1f); } _activationClip = AudioClip.Create("LGU_ShadowStep_PhaseOut", num3, 1, num, false); bool flag = _activationClip.SetData(array, 0); Plugin.Log.LogInfo((object)$"[Shadow Step] Generated activation clip: samples={num3}, SetData={flag}"); return _activationClip; } private static AudioClip GetDeactivationClip() { if ((Object)(object)_deactivationClip != (Object)null) { return _deactivationClip; } int num = 44100; float num2 = 0.12f; int num3 = (int)((float)num * num2); float[] array = new float[num3]; for (int i = 0; i < num3; i++) { float num4 = (float)i / (float)num; float num5 = num4 / num2; float num6 = Mathf.Lerp(200f, 800f, num5); float num7 = Mathf.Exp((0f - num4) * 10f); array[i] = Mathf.Clamp(Mathf.Sin(MathF.PI * 2f * num6 * num4) * num7 * 1.5f, -1f, 1f); } _deactivationClip = AudioClip.Create("LGU_ShadowStep_SnapOff", num3, 1, num, false); bool flag = _deactivationClip.SetData(array, 0); Plugin.Log.LogInfo((object)$"[Shadow Step] Generated deactivation clip: samples={num3}, SetData={flag}"); return _deactivationClip; } private static AudioClip GetHissClip() { if ((Object)(object)_hissClip != (Object)null) { return _hissClip; } int num = 44100; float num2 = 2f; int num3 = (int)((float)num * num2); float[] array = new float[num3]; Random random = new Random(42); for (int i = 0; i < num3; i++) { array[i] = (float)(random.NextDouble() * 2.0 - 1.0) * 0.12f; } _hissClip = AudioClip.Create("LGU_ShadowStep_Hiss", num3, 1, num, false); _hissClip.SetData(array, 0); return _hissClip; } [HarmonyPatch(typeof(EnemyAI), "CheckLineOfSightForPlayer")] [HarmonyPostfix] private static void PostCheckLineOfSightForPlayer(EnemyAI __instance, ref PlayerControllerB __result, float width, int range, int proximityAwareness) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__result == (Object)null || (Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)__result != (Object)(object)GameNetworkManager.Instance.localPlayerController || !ShadowStepUpgrade.IsUnlocked()) { return; } float detectionMultiplier = GetDetectionMultiplier(); if (detectionMultiplier >= 1f) { return; } if (detectionMultiplier <= 0f) { __result = null; return; } float num = (float)range * detectionMultiplier; if (Vector3.Distance(((Component)__instance).transform.position, ((Component)__result).transform.position) > num) { __result = null; } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] CheckLineOfSight patch error: {arg}"); } } [HarmonyPatch(typeof(EnemyAI), "GetClosestPlayer")] [HarmonyPostfix] private static void PostGetClosestPlayer(EnemyAI __instance, ref PlayerControllerB __result, bool requireLineOfSight) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__result == (Object)null || (Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)__result != (Object)(object)GameNetworkManager.Instance.localPlayerController || !ShadowStepUpgrade.IsUnlocked()) { return; } float detectionMultiplier = GetDetectionMultiplier(); if (detectionMultiplier >= 1f) { return; } if (detectionMultiplier <= 0f) { __result = null; return; } float num = 40f * detectionMultiplier; if (Vector3.Distance(((Component)__instance).transform.position, ((Component)__result).transform.position) > num) { __result = null; } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] GetClosestPlayer patch error: {arg}"); } } [HarmonyPatch(typeof(EnemyAI), "PlayerIsTargetable")] [HarmonyPostfix] private static void PostPlayerIsTargetable(EnemyAI __instance, ref bool __result, PlayerControllerB playerScript) { try { if (__result && !((Object)(object)playerScript != (Object)(object)GameNetworkManager.Instance.localPlayerController) && ShadowStepUpgrade.IsInvisible) { __result = false; } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] PlayerIsTargetable patch error: {arg}"); } } private static float GetDetectionMultiplier() { if (!ShadowStepUpgrade.IsUnlocked()) { return 1f; } if (ShadowStepUpgrade.IsInvisible) { return 0f; } int tier = ShadowStepUpgrade.GetTier(); PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null || val.isPlayerDead) { return 1f; } bool isSprinting = val.isSprinting; bool isCrouching = val.isCrouching; switch (tier) { case 1: if (!isCrouching) { return 1f; } return 0.75f; case 2: case 3: if (!isSprinting) { return 0.75f; } return 1f; default: return 1f; } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { PollKeybind(__instance); UpdateInvisibilityTimer(__instance); UpdateHUD(); UpdateCloakVignette(); } } private static void PollKeybind(PlayerControllerB player) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) if (!ShadowStepUpgrade.HasActiveAbility() || player.isPlayerDead || ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen) || player.isTypingChat || player.inSpecialInteractAnimation || player.inTerminalMenu) { return; } Keyboard current = Keyboard.current; if (current != null) { Key? shadowStepKey = Plugin.GetShadowStepKey(); bool flag = (shadowStepKey.HasValue ? ((ButtonControl)current[shadowStepKey.Value]).isPressed : ((ButtonControl)current.gKey).isPressed); bool num = flag && !_keyWasDown; _keyWasDown = flag; if (num) { ActivateInvisibility(player); } } } private static void ActivateInvisibility(PlayerControllerB player) { if (!ShadowStepUpgrade.HasActiveAbility() || ShadowStepUpgrade.IsInvisible) { return; } if (Time.time < ShadowStepUpgrade.CooldownEndTime) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("SHADOW STEP", "Still on cooldown.", true, false, "LC_Tip1"); } return; } ShadowStepUpgrade.IsInvisible = true; ShadowStepUpgrade.InvisibilityEndTime = Time.time + 6f; ShadowStepUpgrade.CooldownEndTime = ShadowStepUpgrade.InvisibilityEndTime + 120f; ForceDeaggroAllEnemies(); BroadcastInvisibilityState(invisible: true); AudioClip activationClip = GetActivationClip(); AudioSource val = HUDManager.Instance?.UIAudio; Plugin.Log.LogInfo((object)$"[Shadow Step] Playing activation clip: {((activationClip != null) ? ((Object)activationClip).name : null)}, length={((activationClip != null) ? new float?(activationClip.length) : null)}, samples={((activationClip != null) ? new int?(activationClip.samples) : null)}"); Plugin.Log.LogInfo((object)$"[Shadow Step] UIAudio null={(Object)(object)val == (Object)null}, enabled={((val != null) ? new bool?(((Behaviour)val).enabled) : null)}, volume={((val != null) ? new float?(val.volume) : null)}, mute={((val != null) ? new bool?(val.mute) : null)}"); if (val != null) { val.PlayOneShot(activationClip); } StartCloakEffects(); Plugin.Log.LogInfo((object)$"[Shadow Step] Invisibility ACTIVATED — duration={6f}s, IsInvisible={ShadowStepUpgrade.IsInvisible}"); } private static void UpdateInvisibilityTimer(PlayerControllerB player) { if (!ShadowStepUpgrade.IsInvisible || Time.time < ShadowStepUpgrade.InvisibilityEndTime) { return; } ShadowStepUpgrade.IsInvisible = false; BroadcastInvisibilityState(invisible: false); HUDManager instance = HUDManager.Instance; if (instance != null) { AudioSource uIAudio = instance.UIAudio; if (uIAudio != null) { uIAudio.PlayOneShot(GetDeactivationClip()); } } StopCloakEffects(); Plugin.Log.LogInfo((object)"[Shadow Step] Invisibility ENDED — cooldown active."); } private static void ForceDeaggroAllEnemies() { try { PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null) { return; } EnemyAI[] array = Object.FindObjectsOfType(); int num = 0; EnemyAI[] array2 = array; foreach (EnemyAI val in array2) { if (!((Object)(object)val == (Object)null) && !val.isEnemyDead && !((Object)(object)val.targetPlayer != (Object)(object)localPlayerController)) { val.targetPlayer = null; val.movingTowardsTargetPlayer = false; if (val.currentBehaviourStateIndex != 0) { val.SwitchToBehaviourStateOnLocalClient(0); } num++; } } if (num > 0) { Plugin.Log.LogInfo((object)$"[Shadow Step] Force de-aggroed {num} enemies on activation."); } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] ForceDeaggro error: {arg}"); } } private static void EnsureSpriteHUD() { if (!((Object)(object)UpgradeHUDManager.GetHUDElement("shadow_hud") != (Object)null) && !((Object)(object)HUDManager.Instance == (Object)null)) { Canvas val = (((Object)(object)HUDManager.Instance.playerScreenTexture != (Object)null) ? ((Graphic)HUDManager.Instance.playerScreenTexture).canvas : null); if (!((Object)(object)val == (Object)null)) { UpgradeHUDManager.CreateHUDElement("shadow_hud", 2, ((Component)val).transform); } } } private static void UpdateHUD() { if (!ShadowStepUpgrade.IsUnlocked() || !ShadowStepUpgrade.HasActiveAbility()) { GameObject hUDElement = UpgradeHUDManager.GetHUDElement("shadow_hud"); if ((Object)(object)hUDElement != (Object)null) { hUDElement.SetActive(false); } return; } EnsureSpriteHUD(); GameObject hUDElement2 = UpgradeHUDManager.GetHUDElement("shadow_hud"); if (!((Object)(object)hUDElement2 == (Object)null)) { hUDElement2.SetActive(true); if (ShadowStepUpgrade.IsInvisible) { UpgradeHUDManager.SetCooldownActive("shadow_hud", active: false); } else if (Time.time < ShadowStepUpgrade.CooldownEndTime) { UpgradeHUDManager.SetCooldownActive("shadow_hud", active: true); float num = ShadowStepUpgrade.CooldownEndTime - Time.time; UpgradeHUDManager.UpdateFillBar("shadow_hud", num / 120f); } else { UpgradeHUDManager.SetCooldownActive("shadow_hud", active: false); } } } private static void StartCloakEffects() { _cloakEffectsActive = true; _originalAudioVolume = AudioListener.volume; Plugin.Log.LogInfo((object)$"[Shadow Step] StartCloakEffects: AudioListener.volume BEFORE={AudioListener.volume}"); AudioListener.volume = 0.3f; Plugin.Log.LogInfo((object)$"[Shadow Step] StartCloakEffects: AudioListener.volume AFTER={AudioListener.volume}"); PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if ((Object)(object)localPlayerController != (Object)null) { _hissSource = ((Component)localPlayerController).gameObject.AddComponent(); _hissSource.clip = GetHissClip(); _hissSource.loop = true; _hissSource.volume = 0.35f; _hissSource.spatialBlend = 0f; _hissSource.Play(); Plugin.Log.LogInfo((object)$"[Shadow Step] Hiss source created: playing={_hissSource.isPlaying}, volume={_hissSource.volume}"); } CreateCloakVignette(); } private static void StopCloakEffects() { _cloakEffectsActive = false; AudioListener.volume = _originalAudioVolume; if ((Object)(object)_hissSource != (Object)null) { _hissSource.Stop(); Object.Destroy((Object)(object)_hissSource); _hissSource = null; } DestroyCloakVignette(); } private static Texture2D GetVignetteTexture() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_vignetteTexture != (Object)null) { return _vignetteTexture; } int num = 256; _vignetteTexture = new Texture2D(num, num, (TextureFormat)4, false); Color[] array = (Color[])(object)new Color[num * num]; float num2 = (float)num / 2f; for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { float num3 = ((float)j - num2) / num2; float num4 = ((float)i - num2) / num2; float num5 = Mathf.Clamp01((Mathf.Sqrt(num3 * num3 + num4 * num4) - 0.5f) / 0.5f); num5 *= num5; array[i * num + j] = new Color(0.02f, 0.06f, 0.02f, num5); } } _vignetteTexture.SetPixels(array); _vignetteTexture.Apply(); return _vignetteTexture; } private static void CreateCloakVignette() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_cloakVignetteObj != (Object)null)) { Canvas componentInParent = ((Component)HUDManager.Instance.playerScreenTexture).GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null) { Plugin.Log.LogWarning((object)"[Shadow Step] Could not find playerScreenTexture canvas for vignette."); return; } _cloakVignetteObj = new GameObject("ShadowStepCloakVignette"); _cloakVignetteObj.transform.SetParent(((Component)componentInParent).transform, false); RectTransform obj = _cloakVignetteObj.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; _cloakVignette = _cloakVignetteObj.AddComponent(); _cloakVignette.texture = (Texture)(object)GetVignetteTexture(); ((Graphic)_cloakVignette).color = new Color(1f, 1f, 1f, 0.2f); ((Graphic)_cloakVignette).raycastTarget = false; Plugin.Log.LogInfo((object)"[Shadow Step] Cloak vignette created."); } } private static void DestroyCloakVignette() { if ((Object)(object)_cloakVignetteObj != (Object)null) { Object.Destroy((Object)(object)_cloakVignetteObj); _cloakVignetteObj = null; _cloakVignette = null; } } private static void UpdateCloakVignette() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) if (_cloakEffectsActive && !((Object)(object)_cloakVignette == (Object)null)) { float num = ShadowStepUpgrade.InvisibilityEndTime - Time.time; float num2 = 2f; float num3 = 0.05f; float num4 = 0.2f; if (num < 2f) { num2 = 6f; num3 = 0.1f; num4 = 0.3f; } float num5 = num4 + Mathf.Sin(Time.time * num2) * num3; ((Graphic)_cloakVignette).color = new Color(1f, 1f, 1f, num5); } } private static void BroadcastInvisibilityState(bool invisible) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsClient || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(5, (Allocator)2, -1); try { int num = (int)GameNetworkManager.Instance.localPlayerController.playerClientId; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref invisible, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("ShadowStep_InvisSync", val, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void RegisterNetworkHandlers() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if (_handlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnReceiveInvisibilityState; if (obj == null) { HandleNamedMessageDelegate val = OnReceiveInvisibilityState; <>O.<0>__OnReceiveInvisibilityState = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("ShadowStep_InvisSync", (HandleNamedMessageDelegate)obj); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("ShadowStepPatch: RegisterNamedMessageHandler failed: " + ex.Message)); } } } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } private static void OnReceiveInvisibilityState(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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) int num = default(int); bool flag = default(bool); try { ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref flag, default(ForPrimitives)); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("ShadowStepPatch: malformed invis sync: " + ex.Message)); } return; } int num2 = (((Object)(object)GameNetworkManager.Instance != (Object)null && (Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null) ? ((int)GameNetworkManager.Instance.localPlayerController.playerClientId) : (-1)); if (num == num2 || (Object)(object)StartOfRound.Instance == (Object)null || num < 0 || num >= StartOfRound.Instance.allPlayerScripts.Length) { return; } PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[num]; if (!((Object)(object)val == (Object)null)) { if (flag) { ApplyGhostEffect(val); SpawnSmokePoof(((Component)val).transform.position); } else { RemoveGhostEffect(val); SpawnSmokePoof(((Component)val).transform.position); } } } private static void ApplyGhostEffect(PlayerControllerB player) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || _ghostedRenderers.ContainsKey(player)) { return; } SkinnedMeshRenderer[] componentsInChildren = ((Component)player).GetComponentsInChildren(); if (componentsInChildren == null || componentsInChildren.Length == 0) { return; } Material[][] array = new Material[componentsInChildren.Length][]; for (int i = 0; i < componentsInChildren.Length; i++) { SkinnedMeshRenderer val = componentsInChildren[i]; if ((Object)(object)val == (Object)null) { array[i] = null; continue; } Material[] array2 = (array[i] = ((Renderer)val).materials); Material[] array3 = (Material[])(object)new Material[array2.Length]; for (int j = 0; j < array2.Length; j++) { Material val2 = array2[j]; if ((Object)(object)val2 == (Object)null) { array3[j] = null; continue; } Material val3 = new Material(val2); if (val3.HasProperty("_Surface")) { val3.SetFloat("_Surface", 1f); } if (val3.HasProperty("_AlphaCutoffEnable")) { val3.SetFloat("_AlphaCutoffEnable", 0f); } val3.SetOverrideTag("RenderType", "Transparent"); val3.renderQueue = 3000; if (val3.HasProperty("_Color")) { Color color = val3.color; color.a = 0.25f; val3.color = color; } val3.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); val3.EnableKeyword("_BLENDMODE_ALPHA"); array3[j] = val3; } ((Renderer)val).materials = array3; } _originalMaterials[player] = array; _ghostedRenderers[player] = componentsInChildren; } private static void RemoveGhostEffect(PlayerControllerB player) { if ((Object)(object)player == (Object)null || !_originalMaterials.TryGetValue(player, out var value)) { return; } if (!_ghostedRenderers.TryGetValue(player, out var value2)) { _originalMaterials.Remove(player); return; } for (int i = 0; i < value2.Length; i++) { SkinnedMeshRenderer val = value2[i]; if (!((Object)(object)val == (Object)null) && value[i] != null) { ((Renderer)val).materials = value[i]; } } _originalMaterials.Remove(player); _ghostedRenderers.Remove(player); } private static void SpawnSmokePoof(Vector3 position) { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: 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_0133: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) GameObject val = FindSmokeParticleSystem(); if ((Object)(object)val != (Object)null) { GameObject obj = Object.Instantiate(val, position + Vector3.up, Quaternion.identity); obj.transform.localScale = Vector3.one * 0.4f; ParticleSystem component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { MainModule main = component.main; ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(0.6f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(1.5f); ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.3f, 0.3f, 0.3f, 0.5f)); ((MainModule)(ref main)).duration = 0.3f; ((MainModule)(ref main)).loop = false; component.Play(); } Object.Destroy((Object)(object)obj, 2f); } else { GameObject val2 = new GameObject("LGU_ShadowStep_PoofLight"); val2.transform.position = position + Vector3.up; Light obj2 = val2.AddComponent(); obj2.type = (LightType)2; obj2.color = new Color(0.4f, 0.4f, 0.4f); obj2.intensity = 5f; obj2.range = 4f; obj2.shadows = (LightShadows)0; Object.Destroy((Object)val2, 0.25f); } AudioSource.PlayClipAtPoint(GetActivationClip(), position, 0.5f); } private static GameObject FindSmokeParticleSystem() { ParticleSystem[] array = Resources.FindObjectsOfTypeAll(); foreach (ParticleSystem val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null)) { string text = ((Object)((Component)val).gameObject).name.ToLowerInvariant(); if (text.Contains("smoke") || text.Contains("poof") || text.Contains("stun")) { return ((Component)val).gameObject; } } } return null; } [HarmonyPatch(typeof(StartOfRound), "StartGame")] [HarmonyPostfix] private static void PostStartGame() { ShadowStepUpgrade.IsInvisible = false; ShadowStepUpgrade.CooldownEndTime = 0f; ShadowStepUpgrade.InvisibilityEndTime = 0f; _keyWasDown = false; StopCloakEffects(); DestroyCloakVignette(); AudioListener.volume = 1f; } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { Cleanup(); } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPostfix] private static void PostKillPlayer(PlayerControllerB __instance) { try { if (!((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { ShadowStepUpgrade.IsInvisible = false; StopCloakEffects(); } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] KillPlayer cleanup error: {arg}"); } } private static void Cleanup() { UpgradeHUDManager.DestroyHUDElement("shadow_hud"); StopCloakEffects(); DestroyCloakVignette(); AudioListener.volume = 1f; ShadowStepUpgrade.IsInvisible = false; ShadowStepUpgrade.CooldownEndTime = 0f; ShadowStepUpgrade.InvisibilityEndTime = 0f; List list = new List(_originalMaterials.Keys); for (int i = 0; i < list.Count; i++) { if ((Object)(object)list[i] != (Object)null) { RemoveGhostEffect(list[i]); } } _originalMaterials.Clear(); _ghostedRenderers.Clear(); } internal static bool IsAudioBlocked(string nameLower) { for (int i = 0; i < AudioBlocklist.Length; i++) { if (nameLower.Contains(AudioBlocklist[i])) { return true; } } return false; } internal static bool MatchesAnyKeyword(string nameLower, string[] keywords) { foreach (string text in keywords) { if (nameLower == text) { return true; } if (nameLower.StartsWith(text)) { return true; } if (nameLower.EndsWith(text)) { return true; } } return false; } } [HarmonyPatch] internal static class SpeedBlurPatch { private const float SPEED_THRESHOLD = 7.5f; private const float SPEED_MAX = 13f; private const float MAX_ALPHA = 0.28f; private const float LERP_SPEED = 8f; private const int VIGNETTE_TEX_SIZE = 256; private static GameObject _vignetteRoot; private static RawImage _vignetteImage; private static Texture2D _vignetteTexture; private static float _currentAlpha = 0f; private static bool _debugLoggedOnce = false; private static Vector3 _lastPosition; private static float _lastSampleTime = -1f; [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostLateUpdate(PlayerControllerB __instance) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return; } EnsureVignetteUI(); if ((Object)(object)_vignetteImage == (Object)null) { return; } float num; if ((Object)(object)__instance.thisController != (Object)null) { Vector3 velocity = __instance.thisController.velocity; velocity.y = 0f; num = ((Vector3)(ref velocity)).magnitude; } else { Vector3 position = ((Component)__instance).transform.position; if (_lastSampleTime < 0f) { num = 0f; } else { Vector3 val = position - _lastPosition; val.y = 0f; float num2 = Mathf.Max(Time.deltaTime, 0.0001f); num = ((Vector3)(ref val)).magnitude / num2; } _lastPosition = position; _lastSampleTime = Time.time; } float num3 = Mathf.InverseLerp(7.5f, 13f, num) * 0.28f; _currentAlpha = Mathf.Lerp(_currentAlpha, num3, Time.deltaTime * 8f); ((Graphic)_vignetteImage).color = new Color(0f, 0f, 0f, _currentAlpha); if (!_debugLoggedOnce && num > 7.5f) { _debugLoggedOnce = true; ManualLogSource log = Plugin.Log; string[] obj = new string[6] { "[LGUCustomUpgrades] SpeedBlur first trigger: ", $"GO.active={_vignetteRoot.activeSelf}, ", $"RawImage.enabled={((Behaviour)_vignetteImage).enabled}, ", $"alpha={_currentAlpha:F3}, ", "parentCanvas=", null }; Transform parent = _vignetteRoot.transform.parent; obj[5] = ((parent != null) ? ((Object)parent).name : null) ?? "NULL"; log.LogInfo((object)string.Concat(obj)); } } private static void EnsureVignetteUI() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_vignetteImage != (Object)null && (Object)(object)_vignetteRoot != (Object)null) { return; } HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerScreenTexture == (Object)null) { return; } Canvas canvas = ((Graphic)instance.playerScreenTexture).canvas; if (!((Object)(object)canvas == (Object)null)) { Transform transform = ((Component)canvas).transform; if ((Object)(object)_vignetteTexture == (Object)null) { _vignetteTexture = GenerateVignetteTexture(256); } _vignetteRoot = new GameObject("LGU_SpeedBlurVignette"); _vignetteRoot.transform.SetParent(transform, false); RectTransform obj = _vignetteRoot.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; ((Transform)obj).localScale = Vector3.one; _vignetteImage = _vignetteRoot.AddComponent(); _vignetteImage.texture = (Texture)(object)_vignetteTexture; ((Graphic)_vignetteImage).color = new Color(0f, 0f, 0f, 0f); ((Graphic)_vignetteImage).raycastTarget = false; _vignetteRoot.transform.SetAsLastSibling(); Plugin.Log.LogInfo((object)"SpeedBlurPatch: vignette UI created."); } } private static Texture2D GenerateVignetteTexture(int size) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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) Texture2D val = new Texture2D(size, size, (TextureFormat)4, false) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; float num = (float)size * 0.5f; float num2 = num * 0.6f; float num3 = num - num2; Color val2 = default(Color); ((Color)(ref val2))..ctor(0f, 0f, 0f, 0f); Color[] array = (Color[])(object)new Color[size * size]; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { float num4 = (float)j - num; float num5 = (float)i - num; float num6 = Mathf.Sqrt(num4 * num4 + num5 * num5); if (num6 <= num2) { array[i * size + j] = val2; continue; } float num7 = Mathf.Clamp01((num6 - num2) / num3); num7 *= num7; array[i * size + j] = new Color(0f, 0f, 0f, num7); } } val.SetPixels(array); val.Apply(false, false); return val; } } [HarmonyPatch] internal static class SquadSightPatch { private const float NEAR_FADE_INNER = 4f; private const float NEAR_FADE_OUTER = 8f; private const float SCREEN_EDGE_MARGIN = 30f; private static readonly Dictionary _chestLights = new Dictionary(); private static readonly Dictionary _indicators = new Dictionary(); private static Canvas _overlayCanvas; [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostLateUpdate(PlayerControllerB __instance) { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)__instance != (Object)(object)GameNetworkManager.Instance.localPlayerController) { return; } if (!SquadSightUpgrade.IsUnlocked()) { if (_chestLights.Count > 0 || _indicators.Count > 0) { ClearAll(); } return; } float range = SquadSightUpgrade.GetRange(); float visibilityMultiplier = SquadSightUpgrade.GetVisibilityMultiplier(); EnsureCanvas(); Camera gameplayCamera = __instance.gameplayCamera; if ((Object)(object)gameplayCamera == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null) { return; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)__instance)) { if (!val.isPlayerControlled || val.isPlayerDead) { SetTeammateVisible(val, visible: false, 0f, 0f, visibilityMultiplier, gameplayCamera); continue; } float num = Vector3.Distance(((Component)__instance).transform.position, ((Component)val).transform.position); bool visible = range < 0f || num <= range; SetTeammateVisible(val, visible, num, range, visibilityMultiplier, gameplayCamera); } } } private static void SetTeammateVisible(PlayerControllerB teammate, bool visible, float distance, float maxRange, float visMul, Camera cam) { UpdateChestLight(teammate, visible, distance, maxRange, visMul); UpdateIndicator(teammate, visible, distance, maxRange, visMul, cam); } private static void UpdateChestLight(PlayerControllerB teammate, bool visible, float distance, float maxRange, float visMul) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (!_chestLights.TryGetValue(teammate, out var value) || (Object)(object)value == (Object)null) { if (!visible) { return; } GameObject val = new GameObject("SquadSight_ChestLight"); val.transform.SetParent(((Component)teammate).transform, false); val.transform.localPosition = new Vector3(0f, 1.5f, 0f); value = val.AddComponent(); value.type = (LightType)2; value.color = new Color(0.25f, 0.6f, 1f); value.range = 3f; value.shadows = (LightShadows)0; value.intensity = 0f; _chestLights[teammate] = value; } float num = 0f; if (visible) { num = 2.5f * visMul; if (maxRange > 0f) { float num2 = maxRange * 0.7f; if (distance > num2) { num *= 1f - Mathf.InverseLerp(num2, maxRange, distance); } } } value.intensity = Mathf.Lerp(value.intensity, num, Time.deltaTime * 8f); } private static void UpdateIndicator(PlayerControllerB teammate, bool visible, float distance, float maxRange, float visMul, Camera cam) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) if (!_indicators.TryGetValue(teammate, out var value) || (Object)(object)value == (Object)null) { if (!visible) { return; } GameObject val = new GameObject("SquadSight_Indicator_" + teammate.playerUsername); val.transform.SetParent(((Component)_overlayCanvas).transform, false); value = val.AddComponent(); value.sizeDelta = new Vector2(14f, 14f); ((Transform)value).localRotation = Quaternion.Euler(0f, 0f, 45f); Image obj = val.AddComponent(); ((Graphic)obj).color = new Color(0.3f, 0.7f, 1f, 0f); ((Graphic)obj).raycastTarget = false; _indicators[teammate] = value; } if (!visible) { ((Component)value).gameObject.SetActive(false); return; } Vector3 val2 = ((Component)teammate).transform.position + Vector3.up * 2.2f; Vector3 val3 = cam.WorldToScreenPoint(val2); if (val3.z <= 0f) { val3.x = (float)Screen.width - val3.x; val3.y = (float)Screen.height - val3.y; } val3.x = Mathf.Clamp(val3.x, 30f, (float)Screen.width - 30f); val3.y = Mathf.Clamp(val3.y, 30f, (float)Screen.height - 30f); ((Component)value).gameObject.SetActive(true); ((Transform)value).position = new Vector3(val3.x, val3.y, 0f); float num = 0.7f * visMul; if (maxRange > 0f) { float num2 = maxRange * 0.7f; if (distance > num2) { num *= 1f - Mathf.InverseLerp(num2, maxRange, distance); } } if (distance < 8f) { num *= Mathf.InverseLerp(4f, 8f, distance); } Image component = ((Component)value).GetComponent(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = new Color(0.3f, 0.7f, 1f, Mathf.Clamp01(num)); } } private static void EnsureCanvas() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown if (!((Object)(object)_overlayCanvas != (Object)null)) { GameObject val = new GameObject("SquadSightCanvas"); _overlayCanvas = val.AddComponent(); _overlayCanvas.renderMode = (RenderMode)0; _overlayCanvas.sortingOrder = 50; val.AddComponent(); Object.DontDestroyOnLoad((Object)val); } } private static void ClearAll() { foreach (KeyValuePair chestLight in _chestLights) { if ((Object)(object)chestLight.Value != (Object)null) { Object.Destroy((Object)(object)((Component)chestLight.Value).gameObject); } } _chestLights.Clear(); foreach (KeyValuePair indicator in _indicators) { if ((Object)(object)indicator.Value != (Object)null) { Object.Destroy((Object)(object)((Component)indicator.Value).gameObject); } } _indicators.Clear(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { ClearAll(); } [HarmonyPatch(typeof(StartOfRound), "StartGame")] [HarmonyPostfix] private static void PostStartGame() { ClearAll(); } } [HarmonyPatch] internal static class StormyWeatherPatch { internal static bool IsLightningStrike; [HarmonyPrefix] [HarmonyPatch(typeof(StormyWeather), "LightningStrike")] private static void LightningStrikePrefix() { IsLightningStrike = true; } [HarmonyPostfix] [HarmonyPatch(typeof(StormyWeather), "LightningStrike")] private static void LightningStrikePostfix() { IsLightningStrike = false; } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] private static bool PreventLightningKill(PlayerControllerB __instance) { try { if (IsLightningStrike && (Object)(object)__instance == (Object)(object)GameNetworkManager.Instance.localPlayerController && SpatialAwarenessUpgrade.HasTier(3)) { Plugin.Log.LogDebug((object)"Spatial Awareness T3: Prevented lightning kill on local player."); return false; } } catch (Exception arg) { Plugin.Log.LogError((object)$"StormyWeatherPatch.PreventLightningKill failed: {arg}"); } return true; } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] private static bool PreventLightningDamage(PlayerControllerB __instance) { try { if (IsLightningStrike && (Object)(object)__instance == (Object)(object)GameNetworkManager.Instance.localPlayerController && SpatialAwarenessUpgrade.HasTier(3)) { Plugin.Log.LogDebug((object)"Spatial Awareness T3: Prevented lightning damage on local player."); return false; } } catch (Exception arg) { Plugin.Log.LogError((object)$"StormyWeatherPatch.PreventLightningDamage failed: {arg}"); } return true; } } [HarmonyPatch(typeof(Turret))] internal static class TurretPatch { [HarmonyPostfix] [HarmonyPatch("CheckForPlayersInLineOfSight")] private static void DontShootPostfix(ref PlayerControllerB __result) { try { if ((Object)(object)__result != (Object)null && (Object)(object)__result == (Object)(object)GameNetworkManager.Instance.localPlayerController && SpatialAwarenessUpgrade.HasTier(2)) { __result = null; } } catch (Exception arg) { Plugin.Log.LogError((object)$"TurretPatch.DontShootPostfix failed: {arg}"); } } } } namespace LGUCustomUpgrades.HUD { internal static class UpgradeHUDManager { private static AssetBundle _bundle; private static bool _bundleLoadAttempted; private static bool _bundleLoadFailed; private static readonly Dictionary _spriteCache = new Dictionary(); private static readonly Dictionary _hudElements = new Dictionary(); private static readonly Dictionary _hudImages = new Dictionary(); private static readonly Dictionary _fillBars = new Dictionary(); private static Sprite _whiteFillSprite; private const float ELEMENT_WIDTH = 105f; private const float ELEMENT_HEIGHT = 32f; private const float RIGHT_MARGIN = 10f; private const float BOTTOM_MARGIN = 10f; private const float STACK_STRIDE = 35f; private const string BUNDLE_NAME = "lgucustomupgrades.lethalbundle"; public static void LoadBundle() { if (_bundleLoadAttempted) { return; } _bundleLoadAttempted = true; foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { if (!((Object)(object)allLoadedAssetBundle == (Object)null) && (Object)(object)allLoadedAssetBundle.LoadAsset("shadow_hud") != (Object)null) { _bundle = allLoadedAssetBundle; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[LGUCustomUpgrades] Found preloaded HUD bundle: " + ((Object)allLoadedAssetBundle).name)); } break; } } if ((Object)(object)_bundle == (Object)null) { string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "lgucustomupgrades.lethalbundle"); if (!File.Exists(text)) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[LGUCustomUpgrades] HUD bundle not found at " + text)); } _bundleLoadFailed = true; return; } _bundle = AssetBundle.LoadFromFile(text); if ((Object)(object)_bundle == (Object)null) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogError((object)("[LGUCustomUpgrades] Failed to load HUD bundle at " + text)); } _bundleLoadFailed = true; return; } } try { string[] allAssetNames = _bundle.GetAllAssetNames(); ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogInfo((object)$"[LGUCustomUpgrades] Bundle '{((Object)_bundle).name}' contains {allAssetNames.Length} assets:"); } for (int i = 0; i < allAssetNames.Length; i++) { ManualLogSource log5 = Plugin.Log; if (log5 != null) { log5.LogInfo((object)$"[LGUCustomUpgrades] asset[{i}] = {allAssetNames[i]}"); } } } catch { } CacheSprite("shadow_hud"); CacheSprite("flare_hud"); CacheSprite("escape_hud"); CacheSprite("pipebomb_hud"); CacheSprite("pipe_hud"); CacheSprite("pipe_bomb_hud"); ManualLogSource log6 = Plugin.Log; if (log6 != null) { log6.LogInfo((object)"[LGUCustomUpgrades] HUD bundle loaded successfully."); } } public static Sprite GetCachedSprite(string spriteName) { _spriteCache.TryGetValue(spriteName, out var value); return value; } public static string ResolveSpriteName(params string[] candidates) { for (int i = 0; i < candidates.Length; i++) { if (_spriteCache.ContainsKey(candidates[i])) { return candidates[i]; } } return null; } private static Sprite GetWhiteFillSprite() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown if ((Object)(object)_whiteFillSprite != (Object)null) { return _whiteFillSprite; } Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false); val.SetPixel(0, 0, Color.white); val.Apply(); _whiteFillSprite = Sprite.Create(val, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f)); return _whiteFillSprite; } private static void CacheSprite(string name) { if ((Object)(object)_bundle == (Object)null) { return; } Sprite val = _bundle.LoadAsset(name); if ((Object)(object)val != (Object)null) { _spriteCache[name] = val; return; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LGUCustomUpgrades] Sprite '" + name + "' not found in bundle.")); } } public static GameObject CreateHUDElement(string spriteName, int stackPosition, Transform parentCanvas) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0075: 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_009f: 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_00d1: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) if (_bundleLoadFailed || (Object)(object)parentCanvas == (Object)null) { return null; } LoadBundle(); if (!_spriteCache.TryGetValue(spriteName, out var value)) { return null; } if (_hudElements.TryGetValue(spriteName, out var value2) && (Object)(object)value2 != (Object)null) { Object.Destroy((Object)(object)value2); } GameObject val = new GameObject("UpgradeHUD_" + spriteName); val.transform.SetParent(parentCanvas, false); RectTransform obj = val.AddComponent(); obj.anchorMin = new Vector2(1f, 0f); obj.anchorMax = new Vector2(1f, 0f); obj.pivot = new Vector2(1f, 0f); obj.sizeDelta = new Vector2(105f, 32f); obj.anchoredPosition = new Vector2(-10f, 10f + (float)stackPosition * 35f); Image val2 = val.AddComponent(); val2.sprite = value; val2.type = (Type)0; val2.preserveAspect = true; ((Graphic)val2).raycastTarget = false; GameObject val3 = new GameObject("CooldownFill"); val3.transform.SetParent(val.transform, false); RectTransform obj2 = val3.AddComponent(); obj2.anchorMin = Vector2.zero; obj2.anchorMax = Vector2.one; obj2.offsetMin = Vector2.zero; obj2.offsetMax = Vector2.zero; Image val4 = val3.AddComponent(); val4.sprite = GetWhiteFillSprite(); ((Graphic)val4).color = new Color(0f, 0.8f, 0f, 0.25f); val4.type = (Type)3; val4.fillMethod = (FillMethod)0; val4.fillOrigin = 0; val4.fillAmount = 0f; ((Graphic)val4).raycastTarget = false; val3.SetActive(false); _hudElements[spriteName] = val; _hudImages[spriteName] = val2; _fillBars[spriteName] = val4; return val; } public static void SetCooldownActive(string spriteName, bool active) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (_hudImages.TryGetValue(spriteName, out var value) && (Object)(object)value != (Object)null) { Color color = ((Graphic)value).color; color.a = (active ? 0.35f : 1f); ((Graphic)value).color = color; } if (_fillBars.TryGetValue(spriteName, out var value2) && (Object)(object)value2 != (Object)null) { ((Component)value2).gameObject.SetActive(active); } } public static void UpdateFillBar(string spriteName, float normalizedTimeRemaining) { if (_fillBars.TryGetValue(spriteName, out var value) && (Object)(object)value != (Object)null) { value.fillAmount = Mathf.Clamp01(normalizedTimeRemaining); } } public static GameObject GetHUDElement(string spriteName) { _hudElements.TryGetValue(spriteName, out var value); return value; } public static void DestroyHUDElement(string spriteName) { if (_hudElements.TryGetValue(spriteName, out var value) && (Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } _hudElements.Remove(spriteName); _hudImages.Remove(spriteName); _fillBars.Remove(spriteName); } public static void DestroyAllHUDElements() { foreach (KeyValuePair hudElement in _hudElements) { if ((Object)(object)hudElement.Value != (Object)null) { Object.Destroy((Object)(object)hudElement.Value); } } _hudElements.Clear(); _hudImages.Clear(); _fillBars.Clear(); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }