Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Hunter Enhancements v1.2.6
BepInEx/plugins/HunterModFork.dll
Decompiled 6 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; using UnityEngine.AI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(/*Could not decode attribute arguments.*/)] [assembly: AssemblyTitle("MakeHunterGreatAgain")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("MakeHunterGreatAgain")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e4e08037-2bc1-4999-9007-48f22736ae36")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(8, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(/*Could not decode attribute arguments.*/)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = (byte[])(object)new Byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(/*Could not decode attribute arguments.*/)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(/*Could not decode attribute arguments.*/)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace HunterMod { public enum AimMode : Enum { Default, MinigunAccuracy, SniperAccuracy } public enum State : Enum { None = 0, LeaveStart = 8, Leave = 9, Despawn = 10 } public class HunterAmmoTracker : MonoBehaviour { public ReloadSkill currentSkill = ReloadSkill.Medium; public float ConfiguredFastReloadTime = 2f; public float ConfiguredMediumReloadTime = 5f; public float ConfiguredSlowReloadTime = 7f; public bool ConfigEnableDamageInterrupt = true; public float ConfigDamageInterruptDelay = 5f; public int ConfigMinigunShots = 10; public float ConfigMinigunShotDelay = 0.1f; public bool ConfigEnableTotalAmmoLimit = false; public int ConfigTotalAmmoCount = 30; public bool ConfigRunAwayWhileReloading = true; private float currentReloadTimer = 0f; private float damageInterruptDelayTimer = 0f; private bool isReloading = false; public int currentTotalAmmo = 30; public bool isOutOfAmmoPermanently = false; public bool isMinigunBurstActive = false; public int minigunShotsRemaining = 0; public float minigunShotTimer = 0f; public bool IsReloading => isReloading; public bool IsInterrupted => damageInterruptDelayTimer > 0f; public bool HasTotalAmmo => !ConfigEnableTotalAmmoLimit || currentTotalAmmo > 0; private void Update() { if (damageInterruptDelayTimer > 0f) { damageInterruptDelayTimer -= Time.deltaTime; if (damageInterruptDelayTimer <= 0f) { damageInterruptDelayTimer = 0f; Plugin.LogInfoF(String.Concat("Hunter ", GetHunterName(), " damage interrupt delay finished.")); } } if (isReloading) { currentReloadTimer -= Time.deltaTime; if (currentReloadTimer <= 0f) { isReloading = false; currentReloadTimer = 0f; Plugin.LogInfoF(String.Format("Hunter {0} finished reloading (Skill: {1}).", (object)GetHunterName(), (object)currentSkill)); } } } public bool TryDecrementTotalAmmo() { if (!ConfigEnableTotalAmmoLimit) { return true; } if (currentTotalAmmo > 0) { currentTotalAmmo--; Plugin.LogInfoF(String.Format("Hunter {0} ammo decremented. Remaining: {1}", (object)GetHunterName(), (object)currentTotalAmmo)); if (currentTotalAmmo <= 0) { if (!Plugin.IsRepoLastStandActive()) { isOutOfAmmoPermanently = true; Plugin.LogErrorF(String.Concat("Hunter ", GetHunterName(), " HAS RUN OUT OF TOTAL AMMO! (Last Stand NOT Active). Perm Leave.")); CancelActions(); return false; } Plugin.LogWarningF(String.Concat("Hunter ", GetHunterName(), " ammo reached 0, but Last Stand IS Active. Not setting perm OOA flag.")); CancelActions(); } return true; } bool flag = Plugin.IsRepoLastStandActive(); if (!isOutOfAmmoPermanently && !flag) { isOutOfAmmoPermanently = true; Plugin.LogErrorF(String.Concat("Hunter ", GetHunterName(), " WAS ALREADY OOA & Last Stand inactive! Force Perm Leave state.")); } else if (!isOutOfAmmoPermanently && flag) { Plugin.LogWarningF(String.Concat("Hunter ", GetHunterName(), " ammo already at 0, Last Stand active. Not setting OOA flag.")); } return false; } public void StartReload() { if (isOutOfAmmoPermanently) { Plugin.LogDebugF(String.Concat("StartReload blocked: Hunter ", GetHunterName(), " permanently OOA.")); } else if (damageInterruptDelayTimer > 0f) { Plugin.LogDebugF(String.Format("StartReload blocked: Hunter {0} Interrupt Delay ({1:F1}s).", (object)GetHunterName(), (object)damageInterruptDelayTimer)); } else if (isMinigunBurstActive) { Plugin.LogWarningF(String.Concat("StartReload blocked: Hunter ", GetHunterName(), " Minigun Active.")); } else if (!isReloading) { isReloading = true; float num; switch (currentSkill) { case ReloadSkill.Fast: num = ConfiguredFastReloadTime; break; case ReloadSkill.Medium: num = ConfiguredMediumReloadTime; break; case ReloadSkill.Slow: num = ConfiguredSlowReloadTime; break; default: num = ConfiguredMediumReloadTime; Plugin.LogWarningF(String.Format("Hunter {0} unknown skill '{1}', defaulting Medium.", (object)GetHunterName(), (object)currentSkill)); break; } currentReloadTimer = num; Plugin.LogInfoF(String.Format("Hunter {0} started reload (Skill: {1}, Time: {2:F1}s).", (object)GetHunterName(), (object)currentSkill, (object)num)); } else { Plugin.LogWarningF(String.Concat("Hunter ", GetHunterName(), " tried StartReload but was already reloading.")); } } public void ApplyDamageInterrupt() { if (!isOutOfAmmoPermanently && ConfigEnableDamageInterrupt && isReloading) { isReloading = false; currentReloadTimer = 0f; damageInterruptDelayTimer = ConfigDamageInterruptDelay; Plugin.LogInfoF(String.Format("Hunter {0} hurt during reload! Reload cancelled, starting {1:F1}s interrupt delay.", (object)GetHunterName(), (object)ConfigDamageInterruptDelay)); } } public float GetRemainingReloadTime() { return (!isReloading) ? 0f : currentReloadTimer; } public void InitializeMinigunBurst() { if (!isMinigunBurstActive) { isMinigunBurstActive = true; minigunShotsRemaining = ConfigMinigunShots; minigunShotTimer = 0f; Plugin.LogInfoF(String.Format("Hunter {0} initializing minigun burst ({1} shots).", (object)GetHunterName(), (object)minigunShotsRemaining)); } } public void EndMinigunBurst() { if (isMinigunBurstActive) { isMinigunBurstActive = false; minigunShotsRemaining = 0; minigunShotTimer = 0f; Plugin.LogInfoF(String.Concat("Hunter ", GetHunterName(), " minigun burst ended/cancelled.")); } } private void CancelActions() { isReloading = false; currentReloadTimer = 0f; EndMinigunBurst(); } private string GetHunterName() { GameObject gameObject = ((Component)this).gameObject; return ((Object)(object)gameObject != (Object)null) ? ((Object)gameObject).name : "Unknown Hunter"; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class HunterPatches : Object { private static Dictionary<int, int> stateLeaveFailCounters = new Dictionary<int, int>(); private const int MAX_LEAVE_FAILURES_WHILE_RELOADING = 5; private static EnemyNavMeshAgent GetEnemyNavMeshAgent(EnemyHunter instance) { //IL_00ab: Expected O, but got Unknown if ((Object)(object)instance == (Object)null || (Object)(object)instance.enemy == (Object)null) { Plugin.LogErrorF("GetEnemyNavMeshAgent: Instance or instance.enemy is null!"); return null; } try { FieldInfo val = AccessTools.Field(typeof(Enemy), "NavMeshAgent"); if (val != (FieldInfo)null) { object value = val.GetValue((object)instance.enemy); return (EnemyNavMeshAgent)((value is EnemyNavMeshAgent) ? value : null); } object obj; if (instance == null) { obj = null; } else { GameObject gameObject = ((Component)instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } Plugin.LogErrorF(String.Concat("GetEnemyNavMeshAgent: Could not find Field 'NavMeshAgent' on type 'Enemy' for ", (string)obj, "!")); return null; } catch (Exception val2) { Exception val3 = val2; object obj2; if (instance == null) { obj2 = null; } else { GameObject gameObject2 = ((Component)instance).gameObject; obj2 = ((gameObject2 != null) ? ((Object)gameObject2).name : null); } if (obj2 == null) { obj2 = "Unknown"; } Plugin.LogErrorF(String.Concat("GetEnemyNavMeshAgent: Error accessing 'NavMeshAgent' field on ", (string)obj2, ": ", val3.Message)); return null; } } private static HunterAmmoTracker GetOrAddTracker(EnemyHunter instance) { if ((Object)(object)instance == (Object)null) { return null; } HunterAmmoTracker hunterAmmoTracker = ((Component)instance).GetComponent<HunterAmmoTracker>(); if ((Object)(object)hunterAmmoTracker == (Object)null) { hunterAmmoTracker = ((Component)instance).gameObject.AddComponent<HunterAmmoTracker>(); object obj; if (instance == null) { obj = null; } else { GameObject gameObject = ((Component)instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } Plugin.LogInfoF(String.Concat("Added HunterAmmoTracker to ", (string)obj, ". Initializing...")); hunterAmmoTracker.ConfiguredFastReloadTime = Plugin.FastReloadTimeConfig.Value; hunterAmmoTracker.ConfiguredMediumReloadTime = Plugin.MediumReloadTimeConfig.Value; hunterAmmoTracker.ConfiguredSlowReloadTime = Plugin.SlowReloadTimeConfig.Value; hunterAmmoTracker.ConfigEnableDamageInterrupt = Plugin.EnableDamageInterruptConfig.Value; hunterAmmoTracker.ConfigDamageInterruptDelay = Plugin.DamageInterruptDelayConfig.Value; hunterAmmoTracker.ConfigMinigunShots = Plugin.MinigunShots.Value; hunterAmmoTracker.ConfigMinigunShotDelay = Plugin.MinigunShotDelay.Value; hunterAmmoTracker.ConfigEnableTotalAmmoLimit = Plugin.EnableTotalAmmoLimitConfig.Value; hunterAmmoTracker.ConfigTotalAmmoCount = Plugin.TotalAmmoCountConfig.Value; hunterAmmoTracker.ConfigRunAwayWhileReloading = Plugin.RunAwayWhileReloadingConfig.Value; } return hunterAmmoTracker; } [HarmonyPatch("OnSpawn")] [HarmonyPostfix] private static void OnSpawnPostfix(EnemyHunter __instance) { HunterAmmoTracker orAddTracker = GetOrAddTracker(__instance); if ((Object)(object)orAddTracker != (Object)null) { int value = Plugin.FastSkillWeight.Value; int value2 = Plugin.MediumSkillWeight.Value; int value3 = Plugin.SlowSkillWeight.Value; int num = value + value2 + value3; if (num <= 0) { orAddTracker.currentSkill = ReloadSkill.Medium; } else { int num2 = Random.Range(0, num); if (num2 < value) { orAddTracker.currentSkill = ReloadSkill.Fast; } else if (num2 < value + value2) { orAddTracker.currentSkill = ReloadSkill.Medium; } else { orAddTracker.currentSkill = ReloadSkill.Slow; } } object obj; if (__instance == null) { obj = null; } else { GameObject gameObject = ((Component)__instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } Plugin.LogInfoF(String.Format("Hunter {0} spawned with Skill: {1}", obj, (object)orAddTracker.currentSkill)); orAddTracker.isOutOfAmmoPermanently = false; orAddTracker.currentTotalAmmo = (orAddTracker.ConfigEnableTotalAmmoLimit ? orAddTracker.ConfigTotalAmmoCount : 9999); object obj2; if (__instance == null) { obj2 = null; } else { GameObject gameObject2 = ((Component)__instance).gameObject; obj2 = ((gameObject2 != null) ? ((Object)gameObject2).name : null); } if (obj2 == null) { obj2 = "Unknown"; } Plugin.LogInfoF(String.Format("Hunter {0} initialized ammo: {1}", obj2, (object)orAddTracker.currentTotalAmmo)); orAddTracker.EndMinigunBurst(); stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID()); } else { object obj3; if (__instance == null) { obj3 = null; } else { GameObject gameObject3 = ((Component)__instance).gameObject; obj3 = ((gameObject3 != null) ? ((Object)gameObject3).name : null); } if (obj3 == null) { obj3 = "Unknown"; } string text = (string)obj3; Plugin.LogErrorF(String.Concat("Failed GetOrAddTracker for ", text, " in OnSpawnPostfix.")); } } [HarmonyPatch("StateIdle")] [HarmonyPrefix] private static bool StateIdlePrefix(EnemyHunter __instance, ref bool ___stateImpulse) { //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) HunterAmmoTracker orAddTracker = GetOrAddTracker(__instance); EnemyNavMeshAgent enemyNavMeshAgent = GetEnemyNavMeshAgent(__instance); if ((Object)(object)orAddTracker == (Object)null || (Object)(object)enemyNavMeshAgent == (Object)null) { return true; } if (orAddTracker.isOutOfAmmoPermanently) { object obj; if (__instance == null) { obj = null; } else { GameObject gameObject = ((Component)__instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } Plugin.LogDebugF(String.Concat("StateIdlePrefix: Hunter ", (string)obj, " OOA. Forcing Leave.")); Plugin.CallUpdateState(__instance, State.Leave); stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID()); return false; } if (Plugin.ShouldRunAwayWhileReloading() && orAddTracker.IsReloading) { object obj2; if (__instance == null) { obj2 = null; } else { GameObject gameObject2 = ((Component)__instance).gameObject; obj2 = ((gameObject2 != null) ? ((Object)gameObject2).name : null); } if (obj2 == null) { obj2 = "Unknown"; } Plugin.LogDebugF(String.Concat("StateIdlePrefix: Hunter ", (string)obj2, " reloading. Moving away.")); enemyNavMeshAgent.Warp(((Component)__instance).transform.position, false); enemyNavMeshAgent.ResetPath(); if (Plugin.FindRetreatPoint(__instance, out var retreatPoint)) { enemyNavMeshAgent.SetDestination(retreatPoint); } ___stateImpulse = false; return false; } return true; } [HarmonyPatch("StateRoam")] [HarmonyPrefix] private static bool StateRoamPrefix(EnemyHunter __instance, ref bool ___stateImpulse) { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) HunterAmmoTracker orAddTracker = GetOrAddTracker(__instance); EnemyNavMeshAgent enemyNavMeshAgent = GetEnemyNavMeshAgent(__instance); if ((Object)(object)orAddTracker == (Object)null || (Object)(object)enemyNavMeshAgent == (Object)null) { return true; } if (orAddTracker.isOutOfAmmoPermanently) { Plugin.CallUpdateState(__instance, State.Leave); stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID()); return false; } if (Plugin.ShouldRunAwayWhileReloading() && orAddTracker.IsReloading) { object obj; if (__instance == null) { obj = null; } else { GameObject gameObject = ((Component)__instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } Plugin.LogDebugF(String.Concat("StateRoamPrefix: Hunter ", (string)obj, " reloading. Moving away.")); enemyNavMeshAgent.ResetPath(); if (Plugin.FindRetreatPoint(__instance, out var retreatPoint)) { enemyNavMeshAgent.SetDestination(retreatPoint); } ___stateImpulse = false; return false; } return true; } [HarmonyPatch("StateAim")] [HarmonyPrefix] private static bool StateAimPrefix(EnemyHunter __instance, ref float ___stateTimer) { //IL_01bc: Unknown result type (might be due to invalid IL or missing references) HunterAmmoTracker orAddTracker = GetOrAddTracker(__instance); if ((Object)(object)orAddTracker == (Object)null) { return true; } if (orAddTracker.isOutOfAmmoPermanently) { object obj; if (__instance == null) { obj = null; } else { GameObject gameObject = ((Component)__instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } Plugin.LogDebugF(String.Concat("StateAimPrefix: Hunter ", (string)obj, " OOA. Forcing Leave.")); Plugin.CallUpdateState(__instance, State.Leave); stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID()); return false; } if (orAddTracker.IsReloading || orAddTracker.IsInterrupted || !orAddTracker.HasTotalAmmo) { string text = ((!orAddTracker.HasTotalAmmo) ? "OOA" : (orAddTracker.IsReloading ? String.Format("reload({0:F1}s)", (object)orAddTracker.GetRemainingReloadTime()) : String.Format("interrupt({0:F1}s)", (object)orAddTracker.ConfigDamageInterruptDelay))); String[] obj2 = new String[5] { "StateAimPrefix BLOCKED: ", default(String), default(String), default(String), default(String) }; object obj3; if (__instance == null) { obj3 = null; } else { GameObject gameObject2 = ((Component)__instance).gameObject; obj3 = ((gameObject2 != null) ? ((Object)gameObject2).name : null); } if (obj3 == null) { obj3 = "Unknown"; } obj2[1] = (String)obj3; obj2[2] = " is "; obj2[3] = text; obj2[4] = "."; Plugin.LogDebugF(String.Concat((string[])(object)obj2)); if (Plugin.ShouldRunAwayWhileReloading() && orAddTracker.IsReloading) { object obj4; if (__instance == null) { obj4 = null; } else { GameObject gameObject3 = ((Component)__instance).gameObject; obj4 = ((gameObject3 != null) ? ((Object)gameObject3).name : null); } if (obj4 == null) { obj4 = "Unknown"; } Plugin.LogDebugF(String.Concat("StateAimPrefix: ", (string)obj4, " running away.")); EnemyNavMeshAgent enemyNavMeshAgent = GetEnemyNavMeshAgent(__instance); if ((Object)(object)enemyNavMeshAgent != (Object)null) { enemyNavMeshAgent.ResetPath(); if (Plugin.FindRetreatPoint(__instance, out var retreatPoint)) { enemyNavMeshAgent.SetDestination(retreatPoint); } } else { Plugin.LogErrorF("StateAimPrefix: EnemyNavMeshAgent missing via reflection!"); } } else { Plugin.CallAimLogic(__instance); } if (___stateTimer <= Time.deltaTime) { ___stateTimer = 0.1f; } return false; } return true; } [HarmonyPatch("StateShoot")] [HarmonyPrefix] private static bool StateShootPrefix(EnemyHunter __instance, ref float ___stateTimer) { HunterAmmoTracker orAddTracker = GetOrAddTracker(__instance); if ((Object)(object)orAddTracker == (Object)null) { return true; } if (!orAddTracker.HasTotalAmmo) { object obj; if (__instance == null) { obj = null; } else { GameObject gameObject = ((Component)__instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } Plugin.LogErrorF(String.Concat("StateShootPrefix: ", (string)obj, " OOA! Forcing Leave.")); orAddTracker.isOutOfAmmoPermanently = true; Plugin.CallUpdateState(__instance, State.Leave); stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID()); return false; } if (!Plugin.IsMinigunModeEnabled()) { if (!orAddTracker.TryDecrementTotalAmmo()) { object obj2; if (__instance == null) { obj2 = null; } else { GameObject gameObject2 = ((Component)__instance).gameObject; obj2 = ((gameObject2 != null) ? ((Object)gameObject2).name : null); } if (obj2 == null) { obj2 = "Unknown"; } Plugin.LogInfoF(String.Concat("StateShootPrefix(N): ", (string)obj2, " OOA this shot. Forcing Leave.")); Plugin.CallUpdateState(__instance, State.Leave); stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID()); return false; } Plugin.LogDebugF("StateShootPrefix: Minigun OFF. Allow original."); return true; } if (orAddTracker.IsReloading || orAddTracker.IsInterrupted) { return false; } if (!orAddTracker.isMinigunBurstActive) { if (!orAddTracker.HasTotalAmmo) { object obj3; if (__instance == null) { obj3 = null; } else { GameObject gameObject3 = ((Component)__instance).gameObject; obj3 = ((gameObject3 != null) ? ((Object)gameObject3).name : null); } if (obj3 == null) { obj3 = "Unknown"; } Plugin.LogErrorF(String.Concat("StateShootPrefix(M-Init): ", (string)obj3, " OOA! Forcing Leave.")); orAddTracker.isOutOfAmmoPermanently = true; Plugin.CallUpdateState(__instance, State.Leave); stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID()); return false; } orAddTracker.InitializeMinigunBurst(); ___stateTimer = (float)orAddTracker.ConfigMinigunShots * orAddTracker.ConfigMinigunShotDelay + 1f; } orAddTracker.minigunShotTimer -= Time.deltaTime; if (orAddTracker.minigunShotTimer <= 0f && orAddTracker.minigunShotsRemaining > 0) { if (!orAddTracker.TryDecrementTotalAmmo()) { object obj4; if (__instance == null) { obj4 = null; } else { GameObject gameObject4 = ((Component)__instance).gameObject; obj4 = ((gameObject4 != null) ? ((Object)gameObject4).name : null); } if (obj4 == null) { obj4 = "Unknown"; } Plugin.LogInfoF(String.Concat("StateShootPrefix(M): ", (string)obj4, " OOA mid-burst. End & Leave.")); orAddTracker.EndMinigunBurst(); Plugin.CallUpdateState(__instance, State.Leave); stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID()); return false; } Plugin.LogDebugF(String.Format("StateShootPrefix: Fire minigun {0}/{1}. Ammo: {2}", (object)(orAddTracker.ConfigMinigunShots - orAddTracker.minigunShotsRemaining + 1), (object)orAddTracker.ConfigMinigunShots, (object)orAddTracker.currentTotalAmmo)); Plugin.CallShootRPC(__instance); orAddTracker.minigunShotsRemaining--; orAddTracker.minigunShotTimer = orAddTracker.ConfigMinigunShotDelay; } if (orAddTracker.minigunShotsRemaining <= 0 && orAddTracker.isMinigunBurstActive) { Plugin.LogInfoF("StateShootPrefix: Minigun burst done. LeaveStart & Reload."); orAddTracker.EndMinigunBurst(); Plugin.CallUpdateState(__instance, State.LeaveStart); orAddTracker.StartReload(); return false; } Plugin.CallAimLogic(__instance); return false; } [HarmonyPatch("OnHurt")] [HarmonyPostfix] private static void OnHurtPostfix(EnemyHunter __instance) { HunterAmmoTracker orAddTracker = GetOrAddTracker(__instance); if ((Object)(object)orAddTracker != (Object)null) { orAddTracker.ApplyDamageInterrupt(); } else { Plugin.LogErrorF("Failed GetOrAddTracker in OnHurtPostfix."); } } [HarmonyPatch("StateShootEnd")] [HarmonyPrefix] private static bool StateShootEndPrefix(EnemyHunter __instance, ref float ___stateTimer, ref int ___shotsFired, int ___shotsFiredMax) { if (Plugin.IsMinigunModeEnabled()) { return true; } HunterAmmoTracker orAddTracker = GetOrAddTracker(__instance); if ((Object)(object)orAddTracker == (Object)null) { return true; } if (orAddTracker.isOutOfAmmoPermanently) { Plugin.CallUpdateState(__instance, State.Leave); stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID()); return false; } if (___stateTimer <= Time.deltaTime) { Plugin.LogInfoF(String.Format("StateShootEndPrefix(N): Shot {0} done. LeaveStart & Reload.", (object)___shotsFired)); Plugin.CallUpdateState(__instance, State.LeaveStart); orAddTracker.StartReload(); return false; } return true; } private static bool PreventReEngagePrefix(EnemyHunter __instance) { HunterAmmoTracker hunterAmmoTracker = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent<HunterAmmoTracker>() : null); if ((Object)(object)hunterAmmoTracker != (Object)null && hunterAmmoTracker.isOutOfAmmoPermanently) { object obj; if (__instance == null) { obj = null; } else { GameObject gameObject = ((Component)__instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } Plugin.LogDebugF(String.Concat("PreventReEngagePrefix: ", (string)obj, " OOA. Prevent engage.")); return false; } return true; } [HarmonyPatch("OnInvestigate")] [HarmonyPrefix] private static bool OnInvestigatePrefix(EnemyHunter __instance) { return PreventReEngagePrefix(__instance); } [HarmonyPatch("OnTouchPlayer")] [HarmonyPrefix] private static bool OnTouchPlayerPrefix(EnemyHunter __instance) { return PreventReEngagePrefix(__instance); } [HarmonyPatch("OnTouchPlayerGrabbedObject")] [HarmonyPrefix] private static bool OnTouchPlayerGrabbedObjectPrefix(EnemyHunter __instance) { return PreventReEngagePrefix(__instance); } [HarmonyPatch("OnGrabbed")] [HarmonyPrefix] private static bool OnGrabbedPrefix(EnemyHunter __instance) { return PreventReEngagePrefix(__instance); } [HarmonyPatch("StateLeave")] [HarmonyPrefix] private static bool StateLeavePrefix(EnemyHunter __instance, ref float ___stateTimer, Vector3 ___leavePosition, ref bool ___stateImpulse) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) HunterAmmoTracker orAddTracker = GetOrAddTracker(__instance); EnemyNavMeshAgent enemyNavMeshAgent = GetEnemyNavMeshAgent(__instance); if ((Object)(object)orAddTracker == (Object)null || (Object)(object)enemyNavMeshAgent == (Object)null) { return true; } int instanceID = ((Object)__instance).GetInstanceID(); bool flag = Plugin.ShouldRunAwayWhileReloading() && orAddTracker.IsReloading; bool isOutOfAmmoPermanently = orAddTracker.isOutOfAmmoPermanently; if (!flag && !isOutOfAmmoPermanently) { stateLeaveFailCounters.Remove(instanceID); return true; } if (___stateTimer <= Time.deltaTime || Vector3.Distance(((Component)__instance).transform.position, ___leavePosition) < 1f) { if (isOutOfAmmoPermanently) { object obj; if (__instance == null) { obj = null; } else { GameObject gameObject = ((Component)__instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } Plugin.LogInfoF(String.Concat("StateLeavePrefix: Hunter ", (string)obj, " OOA and reached Leave destination/timer. Forcing Despawn.")); Plugin.CallUpdateState(__instance, State.Despawn); stateLeaveFailCounters.Remove(instanceID); return false; } object obj2; if (__instance == null) { obj2 = null; } else { GameObject gameObject2 = ((Component)__instance).gameObject; obj2 = ((gameObject2 != null) ? ((Object)gameObject2).name : null); } if (obj2 == null) { obj2 = "Unknown"; } Plugin.LogDebugF(String.Concat("StateLeavePrefix: ", (string)obj2, " reloading & reached dest/timer. Finding new retreat point.")); if (Plugin.FindRetreatPoint(__instance, out var retreatPoint)) { stateLeaveFailCounters.Remove(instanceID); FieldInfo val = AccessTools.Field(typeof(EnemyHunter), "leavePosition"); if (val != (FieldInfo)null) { val.SetValue((object)__instance, (object)retreatPoint); } else { Plugin.LogErrorF("No leavePosition field!"); } enemyNavMeshAgent.SetDestination(retreatPoint); ___stateTimer = 5f; ___stateImpulse = false; } else { int num = (stateLeaveFailCounters.ContainsKey(instanceID) ? stateLeaveFailCounters[instanceID] : 0); num++; stateLeaveFailCounters[instanceID] = num; object obj3; if (__instance == null) { obj3 = null; } else { GameObject gameObject3 = ((Component)__instance).gameObject; obj3 = ((gameObject3 != null) ? ((Object)gameObject3).name : null); } if (obj3 == null) { obj3 = "Unknown"; } Plugin.LogWarningF(String.Format("StateLeavePrefix: No new retreat point for {0} while reloading. Failure {1}/{2}", obj3, (object)num, (object)5)); ___stateTimer = 1f; if (num >= 5) { object obj4; if (__instance == null) { obj4 = null; } else { GameObject gameObject4 = ((Component)__instance).gameObject; obj4 = ((gameObject4 != null) ? ((Object)gameObject4).name : null); } if (obj4 == null) { obj4 = "Unknown"; } Plugin.LogErrorF(String.Format("StateLeavePrefix: Hunter {0} failed find retreat point {1} times WHILE RELOADING. Forcing Despawn.", obj4, (object)5)); Plugin.CallUpdateState(__instance, State.Despawn); stateLeaveFailCounters.Remove(instanceID); } } return false; } Plugin.LogDebugF(String.Format("StateLeavePrefix: Timer > deltaT ({0:F3}), allow original method.", (object)___stateTimer)); return true; } } [BepInPlugin("com.plusblankplus.huntermod", "Hunter Enhancements", "1.6.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private readonly Harmony harmony = new Harmony("com.plusblankplus.huntermod"); private static bool isRepoLastStandModPresent; private const string RepoLastStandGuid = "umbreon222.repo.laststand"; private static Type repoStateManagerType; private static PropertyInfo repoStateManagerInstanceProperty; private static FieldInfo repoLastStandActiveField; [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static Plugin Instance { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] internal static ManualLogSource Log { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<bool> EnableMinigunMode { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<int> MinigunShots { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<float> MinigunShotDelay { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<float> FastReloadTimeConfig { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<float> MediumReloadTimeConfig { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<float> SlowReloadTimeConfig { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<int> FastSkillWeight { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<int> MediumSkillWeight { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<int> SlowSkillWeight { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<bool> EnableDamageInterruptConfig { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<float> DamageInterruptDelayConfig { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<bool> EnableTotalAmmoLimitConfig { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<int> TotalAmmoCountConfig { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<bool> RunAwayWhileReloadingConfig { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<bool> EnableInfoLogs { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<bool> EnableDebugLogs { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<bool> EnableWarningLogs { [CompilerGenerated] get; [CompilerGenerated] private set; } [field: CompilerGenerated] [field: DebuggerBrowsable(/*Could not decode attribute arguments.*/)] public static ConfigEntry<bool> EnableErrorLogs { [CompilerGenerated] get; [CompilerGenerated] private set; } private void Awake() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Expected O, but got Unknown //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Expected O, but got Unknown //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Expected O, but got Unknown //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Expected O, but got Unknown if ((Object)(object)Instance == (Object)null) { Instance = this; Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"Loading configuration..."); EnableMinigunMode = ((BaseUnityPlugin)this).Config.Bind<bool>("A. General", "EnableMinigunMode", false, "Enable the Hunter's rapid-fire 'Minigun' mode."); MinigunShots = ((BaseUnityPlugin)this).Config.Bind<int>("A. General", "MinigunShots", 10, new ConfigDescription("Number of shots fired in one burst when Minigun Mode is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>())); MinigunShotDelay = ((BaseUnityPlugin)this).Config.Bind<float>("A. General", "MinigunShotDelay", 0.1f, new ConfigDescription("Delay in seconds between each shot during a Minigun burst.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 0.5f), Array.Empty<object>())); FastReloadTimeConfig = ((BaseUnityPlugin)this).Config.Bind<float>("B. ReloadTimes", "FastReloadTime", 2f, new ConfigDescription("Reload time (s) for Hunters with 'Fast' skill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 120f), Array.Empty<object>())); MediumReloadTimeConfig = ((BaseUnityPlugin)this).Config.Bind<float>("B. ReloadTimes", "MediumReloadTime", 5f, new ConfigDescription("Reload time (s) for Hunters with 'Medium' skill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 180f), Array.Empty<object>())); SlowReloadTimeConfig = ((BaseUnityPlugin)this).Config.Bind<float>("B. ReloadTimes", "SlowReloadTime", 7f, new ConfigDescription("Reload time (s) for Hunters with 'Slow' skill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1.5f, 300f), Array.Empty<object>())); FastSkillWeight = ((BaseUnityPlugin)this).Config.Bind<int>("C. SkillWeights", "FastSkillWeight", 5, new ConfigDescription("Probability weight for spawning with Fast reload skill.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); MediumSkillWeight = ((BaseUnityPlugin)this).Config.Bind<int>("C. SkillWeights", "MediumSkillWeight", 3, new ConfigDescription("Probability weight for spawning with Medium reload skill.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); SlowSkillWeight = ((BaseUnityPlugin)this).Config.Bind<int>("C. SkillWeights", "SlowSkillWeight", 1, new ConfigDescription("Probability weight for spawning with Slow reload skill.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); EnableDamageInterruptConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("D. DamageBehavior", "EnableDamageInterrupt", true, "If enabled, getting hurt while reloading cancels it and imposes a delay before reloading can start."); DamageInterruptDelayConfig = ((BaseUnityPlugin)this).Config.Bind<float>("D. DamageBehavior", "DamageInterruptDelay", 5f, new ConfigDescription("Delay (s) imposed after a reload is interrupted by damage.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 15f), Array.Empty<object>())); RunAwayWhileReloadingConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("D. DamageBehavior", "RunAwayWhileReloading", true, "If enabled, the Hunter will actively move away from players while reloading (enters Leave state)."); EnableTotalAmmoLimitConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("E. TotalAmmo", "EnableTotalAmmoLimit", false, "If enabled, the Hunter has a limited total number of shots before it runs away permanently."); TotalAmmoCountConfig = ((BaseUnityPlugin)this).Config.Bind<int>("E. TotalAmmo", "TotalAmmoCount", 30, new ConfigDescription("Total number of shots the Hunter has if the limit is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 200), Array.Empty<object>())); EnableInfoLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Z. Logging", "EnableInfoLogs", true, "Enable standard informational logs."); EnableDebugLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Z. Logging", "EnableDebugLogs", false, "Enable detailed debug logs (can be spammy)."); EnableWarningLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Z. Logging", "EnableWarningLogs", true, "Enable warning logs for potential issues."); EnableErrorLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Z. Logging", "EnableErrorLogs", true, "Enable error logs for critical failures."); LogInfoF("Configuration loaded."); DetectRepoLastStandMod(); LogInfoF("Applying Harmony patches for Hunter Enhancements..."); harmony.PatchAll(typeof(HunterPatches)); LogInfoF("Harmony patches applied successfully!"); LogInfoF("Plugin com.plusblankplus.huntermod v1.6.1 is loaded!"); } else { Object.Destroy((Object)(object)this); } } private static void DetectRepoLastStandMod() { //IL_017f: Expected O, but got Unknown isRepoLastStandModPresent = Chainloader.PluginInfos.ContainsKey("umbreon222.repo.laststand"); if (isRepoLastStandModPresent) { LogInfoF("RepoLastStandMod detected. Enabling compatibility logic."); try { string text = "RepoLastStandMod"; repoStateManagerType = Type.GetType(String.Concat("RepoLastStandMod.StateManager, ", text), false); PluginInfo val = default(PluginInfo); if (repoStateManagerType == (Type)null && Chainloader.PluginInfos.TryGetValue("umbreon222.repo.laststand", ref val) && (Object)(object)val.Instance != (Object)null) { text = ((Object)val.Instance).GetType().Assembly.FullName; repoStateManagerType = Type.GetType(String.Concat("RepoLastStandMod.StateManager, ", text), false); LogDebugF(String.Concat("Attempting to load StateManager from assembly: ", text)); } if (repoStateManagerType != (Type)null) { repoStateManagerInstanceProperty = AccessTools.Property(repoStateManagerType, "Instance"); repoLastStandActiveField = AccessTools.Field(repoStateManagerType, "LastStandActive"); if (repoStateManagerInstanceProperty == (PropertyInfo)null) { LogErrorF("Could not find 'Instance' property on StateManager."); } if (repoLastStandActiveField == (FieldInfo)null) { LogErrorF("Could not find 'LastStandActive' field on StateManager."); } if (repoStateManagerInstanceProperty == (PropertyInfo)null || repoLastStandActiveField == (FieldInfo)null) { LogErrorF("Failed reflection for RepoLastStandMod. Compatibility disabled."); isRepoLastStandModPresent = false; } } else { LogErrorF("Could not find type 'RepoLastStandMod.StateManager'. Compatibility disabled."); isRepoLastStandModPresent = false; } return; } catch (Exception val2) { Exception val3 = val2; LogErrorF(String.Format("Error during reflection for RepoLastStandMod compatibility: {0}", (object)val3)); isRepoLastStandModPresent = false; return; } } LogInfoF("RepoLastStandMod not detected."); } public static void LogInfoF(string message) { if (Log != null && EnableInfoLogs != null && EnableInfoLogs.Value) { Log.LogInfo((object)message); } } public static void LogDebugF(string message) { if (Log != null && EnableDebugLogs != null && EnableDebugLogs.Value) { Log.LogDebug((object)message); } } public static void LogWarningF(string message) { if (Log != null && EnableWarningLogs != null && EnableWarningLogs.Value) { Log.LogWarning((object)message); } } public static void LogErrorF(string message) { if (Log != null && EnableErrorLogs != null && EnableErrorLogs.Value) { Log.LogError((object)message); } } public static bool IsMinigunModeEnabled() { return EnableMinigunMode != null && EnableMinigunMode.Value; } public static bool ShouldRunAwayWhileReloading() { return RunAwayWhileReloadingConfig != null && RunAwayWhileReloadingConfig.Value; } public static void CallUpdateState(EnemyHunter instance, State newState) { MethodInfo val = AccessTools.Method(typeof(EnemyHunter), "UpdateState", (Type[])null, (Type[])null); if (val != (MethodInfo)null) { ParameterInfo[] parameters = ((MethodBase)val).GetParameters(); object obj = null; if (parameters.Length == 1) { Type parameterType = parameters[0].ParameterType; obj = ((!parameterType.IsEnum) ? Convert.ChangeType((object)newState, parameterType) : Enum.ToObject(parameterType, Convert.ToInt32((object)newState))); ((MethodBase)val).Invoke((object)instance, (object[])(object)new Object[1] { obj }); } else { ((MethodBase)val).Invoke((object)instance, (object[])(object)new Object[1] { (object)newState }); } } else { object obj2; if (instance == null) { obj2 = null; } else { GameObject gameObject = ((Component)instance).gameObject; obj2 = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj2 == null) { obj2 = "Unknown"; } string text = (string)obj2; LogErrorF(String.Concat("Could not find method 'UpdateState' on ", text, "!")); } } public static void CallAimLogic(EnemyHunter instance) { MethodInfo val = AccessTools.Method(typeof(EnemyHunter), "AimLogic", (Type[])null, (Type[])null); if (val != (MethodInfo)null) { ((MethodBase)val).Invoke((object)instance, (object[])null); return; } object obj; if (instance == null) { obj = null; } else { GameObject gameObject = ((Component)instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } string text = (string)obj; LogErrorF(String.Concat("Could not find method 'AimLogic' on ", text, "!")); } private static PhotonView GetPhotonView(EnemyHunter instance) { //IL_0089: Expected O, but got Unknown if ((Object)(object)instance == (Object)null) { return null; } try { FieldInfo val = AccessTools.Field(typeof(EnemyHunter), "photonView"); if (val != (FieldInfo)null) { object value = val.GetValue((object)instance); return (PhotonView)((value is PhotonView) ? value : null); } object obj; if (instance == null) { obj = null; } else { GameObject gameObject = ((Component)instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } LogErrorF(String.Concat("GetPhotonView: Could not find field 'photonView' on ", (string)obj, "!")); return null; } catch (Exception val2) { Exception val3 = val2; object obj2; if (instance == null) { obj2 = null; } else { GameObject gameObject2 = ((Component)instance).gameObject; obj2 = ((gameObject2 != null) ? ((Object)gameObject2).name : null); } if (obj2 == null) { obj2 = "Unknown"; } LogErrorF(String.Concat("GetPhotonView: Error accessing 'photonView' field on ", (string)obj2, ": ", val3.Message)); return null; } } public static void CallShootRPC(EnemyHunter instance) { //IL_029c: Expected O, but got Unknown //IL_0312: Expected O, but got Unknown //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_0300: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_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_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0125: 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_0132: 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_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0238: 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_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient && GameManager.Multiplayer()) { object obj; if (instance == null) { obj = null; } else { GameObject gameObject = ((Component)instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } string text = (string)obj; LogDebugF(String.Concat("CallShootRPC skipped on non-MasterClient for ", text)); return; } PhotonView photonView = GetPhotonView(instance); if ((Object)(object)photonView == (Object)null) { object obj2; if (instance == null) { obj2 = null; } else { GameObject gameObject2 = ((Component)instance).gameObject; obj2 = ((gameObject2 != null) ? ((Object)gameObject2).name : null); } if (obj2 == null) { obj2 = "Unknown"; } LogErrorF(String.Concat("CallShootRPC: PhotonView is null for ", (string)obj2, "! Cannot send RPC.")); return; } if ((Object)(object)instance == (Object)null || (Object)(object)instance.gunAimTransform == (Object)null) { LogErrorF("CallShootRPC: instance or gunAimTransform is null!"); return; } Vector3 val = instance.gunAimTransform.position + instance.gunAimTransform.forward * 50f; try { FieldInfo val2 = AccessTools.Field(typeof(EnemyHunter), "investigatePoint"); if (val2 != (FieldInfo)null) { Vector3 val3 = (Vector3)val2.GetValue((object)instance); float num = ((Vector3.Distance(((Component)instance).transform.position, val3) > 10f) ? 0.5f : 1f); int mask = LayerMask.GetMask((string[])(object)new String[4] { "Player", "Default", "PhysGrabObject", "Enemy" }); int mask2 = LayerMask.GetMask((string[])(object)new String[1] { "Default" }); RaycastHit val4 = default(RaycastHit); RaycastHit val5 = default(RaycastHit); if (Physics.SphereCast(instance.gunAimTransform.position, num, instance.gunAimTransform.forward, ref val4, 50f, mask)) { if (!Physics.Linecast(instance.gunAimTransform.position, ((RaycastHit)(ref val4)).point, mask2)) { val = ((RaycastHit)(ref val4)).point; } else if (Physics.Raycast(instance.gunAimTransform.position, instance.gunAimTransform.forward, ref val4, 50f, mask)) { val = ((RaycastHit)(ref val4)).point; } } else if (Physics.Raycast(instance.gunAimTransform.position, instance.gunAimTransform.forward, ref val5, 50f, mask)) { val = ((RaycastHit)(ref val5)).point; } } else { object obj3; if (instance == null) { obj3 = null; } else { GameObject gameObject3 = ((Component)instance).gameObject; obj3 = ((gameObject3 != null) ? ((Object)gameObject3).name : null); } if (obj3 == null) { obj3 = "Unknown"; } LogWarningF(String.Concat("Could not access investigatePoint field for ", (string)obj3, "!")); } } catch (Exception val6) { Exception val7 = val6; LogErrorF(String.Concat("Error calculating target position: ", val7.Message)); } try { object obj4; if (instance == null) { obj4 = null; } else { GameObject gameObject4 = ((Component)instance).gameObject; obj4 = ((gameObject4 != null) ? ((Object)gameObject4).name : null); } if (obj4 == null) { obj4 = "Unknown"; } LogDebugF(String.Format("Sending ShootRPC for {0} targeting {1}", obj4, (object)val)); photonView.RPC("ShootRPC", (RpcTarget)0, (object[])(object)new Object[1] { (object)val }); } catch (Exception val8) { Exception val9 = val8; object obj5; if (instance == null) { obj5 = null; } else { GameObject gameObject5 = ((Component)instance).gameObject; obj5 = ((gameObject5 != null) ? ((Object)gameObject5).name : null); } if (obj5 == null) { obj5 = "Unknown"; } LogErrorF(String.Format("Failed to send ShootRPC for {0}: {1}", obj5, (object)val9)); } } public static bool FindRetreatPoint(EnemyHunter instance, out Vector3 retreatPoint) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: 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_0167: 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_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) retreatPoint = Vector3.zero; if ((Object)(object)instance == (Object)null || (Object)(object)GameDirector.instance == (Object)null) { return false; } PlayerAvatar val = null; float num = 3.4028235E+38f; if (GameDirector.instance.PlayerList == null || GameDirector.instance.PlayerList.Count == 0) { LogWarningF("FindRetreatPoint: GameDirector.PlayerList is null or empty."); return false; } Enumerator<PlayerAvatar> enumerator = GameDirector.instance.PlayerList.GetEnumerator(); try { while (enumerator.MoveNext()) { PlayerAvatar current = enumerator.Current; if ((Object)(object)current != (Object)null && ((Component)current).gameObject.activeSelf) { float num2 = Vector3.Distance(((Component)instance).transform.position, ((Component)current).transform.position); if (num2 < num) { num = num2; val = current; } } } } finally { ((IDisposable)enumerator).Dispose(); } if ((Object)(object)val == (Object)null) { LogWarningF("FindRetreatPoint: Could not find an active player to run from."); return false; } Vector3 val2 = ((Component)instance).transform.position - ((Component)val).transform.position; val2 = ((Vector3)(ref val2)).normalized; val2.y = 0f; if (val2 == Vector3.zero) { val2 = ((Component)instance).transform.forward; } float num3 = 20f; float num4 = 15f; Vector3 val3 = ((Component)instance).transform.position + val2 * num3; NavMeshHit val4 = default(NavMeshHit); if (NavMesh.SamplePosition(val3, ref val4, num4, -1)) { retreatPoint = ((NavMeshHit)(ref val4)).position; object obj; if (instance == null) { obj = null; } else { GameObject gameObject = ((Component)instance).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "Unknown"; } LogDebugF(String.Format("Found retreat point for {0} at {1} (away from player {2})", obj, (object)retreatPoint, (object)((Object)val).GetInstanceID())); return true; } val3 = ((Component)instance).transform.position + val2 * 8f; if (NavMesh.SamplePosition(val3, ref val4, num4, -1)) { retreatPoint = ((NavMeshHit)(ref val4)).position; object obj2; if (instance == null) { obj2 = null; } else { GameObject gameObject2 = ((Component)instance).gameObject; obj2 = ((gameObject2 != null) ? ((Object)gameObject2).name : null); } if (obj2 == null) { obj2 = "Unknown"; } LogDebugF(String.Format("Found fallback retreat point (closer) for {0} at {1}", obj2, (object)retreatPoint)); return true; } object obj3; if (instance == null) { obj3 = null; } else { GameObject gameObject3 = ((Component)instance).gameObject; obj3 = ((gameObject3 != null) ? ((Object)gameObject3).name : null); } if (obj3 == null) { obj3 = "Unknown"; } LogWarningF(String.Concat("Could not find NavMesh retreat point for ", (string)obj3, " after searching.")); return false; } public static bool IsRepoLastStandActive() { //IL_0077: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected I4, but got Unknown if (!isRepoLastStandModPresent || repoStateManagerType == (Type)null || repoStateManagerInstanceProperty == (PropertyInfo)null || repoLastStandActiveField == (FieldInfo)null) { return false; } try { object value = repoStateManagerInstanceProperty.GetValue((object)null); if (value == null) { LogWarningF("RepoLastStandMod StateManager.Instance returned null."); return false; } object value2 = repoLastStandActiveField.GetValue(value); return (byte)(int)(Boolean)value2 != 0; } catch (Exception val) { Exception val2 = val; LogErrorF(String.Format("Error getting RepoLastStandMod state via reflection: {0}", (object)val2)); return false; } } } public static class PluginInfo : Object { public const string PLUGIN_GUID = "com.plusblankplus.huntermod"; public const string PLUGIN_NAME = "Hunter Enhancements"; public const string PLUGIN_VERSION = "1.6.1"; } public enum ReloadSkill : Enum { Fast, Medium, Slow } }