using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Photon.Pun;
using UnityEngine;
using UnityEngine.AI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[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: AssemblyVersion("1.0.0.0")]
namespace HunterMod;
public enum AimMode
{
Default,
MinigunAccuracy,
SniperAccuracy
}
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("Hunter " + GetHunterName() + " damage interrupt delay finished.");
}
}
if (isReloading)
{
currentReloadTimer -= Time.deltaTime;
if (currentReloadTimer <= 0f)
{
isReloading = false;
currentReloadTimer = 0f;
Plugin.LogInfoF($"Hunter {GetHunterName()} finished reloading (Skill: {currentSkill}).");
}
}
}
public bool TryDecrementTotalAmmo()
{
if (!ConfigEnableTotalAmmoLimit)
{
return true;
}
if (currentTotalAmmo > 0)
{
currentTotalAmmo--;
Plugin.LogInfoF($"Hunter {GetHunterName()} ammo decremented. Remaining: {currentTotalAmmo}");
if (currentTotalAmmo <= 0)
{
if (!Plugin.IsRepoLastStandActive())
{
isOutOfAmmoPermanently = true;
Plugin.LogErrorF("Hunter " + GetHunterName() + " HAS RUN OUT OF TOTAL AMMO! (Last Stand NOT Active). Perm Leave.");
CancelActions();
return false;
}
Plugin.LogWarningF("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("Hunter " + GetHunterName() + " WAS ALREADY OOA & Last Stand inactive! Force Perm Leave state.");
}
else if (!isOutOfAmmoPermanently && flag)
{
Plugin.LogWarningF("Hunter " + GetHunterName() + " ammo already at 0, Last Stand active. Not setting OOA flag.");
}
return false;
}
public void StartReload()
{
if (isOutOfAmmoPermanently)
{
Plugin.LogDebugF("StartReload blocked: Hunter " + GetHunterName() + " permanently OOA.");
}
else if (damageInterruptDelayTimer > 0f)
{
Plugin.LogDebugF($"StartReload blocked: Hunter {GetHunterName()} Interrupt Delay ({damageInterruptDelayTimer:F1}s).");
}
else if (isMinigunBurstActive)
{
Plugin.LogWarningF("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($"Hunter {GetHunterName()} unknown skill '{currentSkill}', defaulting Medium.");
break;
}
currentReloadTimer = num;
Plugin.LogInfoF($"Hunter {GetHunterName()} started reload (Skill: {currentSkill}, Time: {num:F1}s).");
}
else
{
Plugin.LogWarningF("Hunter " + GetHunterName() + " tried StartReload but was already reloading.");
}
}
public void ApplyDamageInterrupt()
{
if (!isOutOfAmmoPermanently && ConfigEnableDamageInterrupt && isReloading)
{
isReloading = false;
currentReloadTimer = 0f;
damageInterruptDelayTimer = ConfigDamageInterruptDelay;
Plugin.LogInfoF($"Hunter {GetHunterName()} hurt during reload! Reload cancelled, starting {ConfigDamageInterruptDelay:F1}s interrupt delay.");
}
}
public float GetRemainingReloadTime()
{
return (!isReloading) ? 0f : currentReloadTimer;
}
public void InitializeMinigunBurst()
{
if (!isMinigunBurstActive)
{
isMinigunBurstActive = true;
minigunShotsRemaining = ConfigMinigunShots;
minigunShotTimer = 0f;
Plugin.LogInfoF($"Hunter {GetHunterName()} initializing minigun burst ({minigunShotsRemaining} shots).");
}
}
public void EndMinigunBurst()
{
if (isMinigunBurstActive)
{
isMinigunBurstActive = false;
minigunShotsRemaining = 0;
minigunShotTimer = 0f;
Plugin.LogInfoF("Hunter " + GetHunterName() + " minigun burst ended/cancelled.");
}
}
private void CancelActions()
{
isReloading = false;
currentReloadTimer = 0f;
EndMinigunBurst();
}
private string GetHunterName()
{
GameObject gameObject = ((Component)this).gameObject;
return ((gameObject != null) ? ((Object)gameObject).name : null) ?? "Unknown Hunter";
}
}
[HarmonyPatch(typeof(EnemyHunter))]
internal static class HunterPatches
{
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)
{
if ((Object)(object)instance?.enemy == (Object)null)
{
Plugin.LogErrorF("GetEnemyNavMeshAgent: Instance or instance.enemy is null!");
return null;
}
try
{
FieldInfo fieldInfo = AccessTools.Field(typeof(Enemy), "NavMeshAgent");
if (fieldInfo != null)
{
object value = fieldInfo.GetValue(instance.enemy);
return (EnemyNavMeshAgent)((value is EnemyNavMeshAgent) ? value : null);
}
Plugin.LogErrorF("GetEnemyNavMeshAgent: Could not find Field 'NavMeshAgent' on type 'Enemy' for " + ((Object)((Component)instance).gameObject).name + "!");
return null;
}
catch (Exception ex)
{
Plugin.LogErrorF("GetEnemyNavMeshAgent: Error accessing 'NavMeshAgent' field on " + ((Object)((Component)instance).gameObject).name + ": " + ex.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>();
Plugin.LogInfoF("Added HunterAmmoTracker to " + ((Object)((Component)instance).gameObject).name + ". 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;
}
}
Plugin.LogInfoF($"Hunter {((Object)((Component)__instance).gameObject).name} spawned with Skill: {orAddTracker.currentSkill}");
orAddTracker.isOutOfAmmoPermanently = false;
if (orAddTracker.ConfigEnableTotalAmmoLimit)
{
orAddTracker.currentTotalAmmo = orAddTracker.ConfigTotalAmmoCount;
}
else
{
orAddTracker.currentTotalAmmo = 9999;
}
Plugin.LogInfoF($"Hunter {((Object)((Component)__instance).gameObject).name} initialized ammo: {orAddTracker.currentTotalAmmo}");
orAddTracker.EndMinigunBurst();
stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID());
}
else
{
object obj;
if (__instance == null)
{
obj = null;
}
else
{
GameObject gameObject = ((Component)__instance).gameObject;
obj = ((gameObject != null) ? ((Object)gameObject).name : null);
}
Plugin.LogErrorF("Failed GetOrAddTracker for " + (string?)obj + " in OnSpawnPostfix.");
}
}
[HarmonyPatch("StateIdle")]
[HarmonyPrefix]
private static bool StateIdlePrefix(EnemyHunter __instance, ref bool ___stateImpulse)
{
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: 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.LogDebugF("StateIdlePrefix: Hunter " + ((Object)((Component)__instance).gameObject).name + " OOA. Forcing Leave.");
Plugin.CallUpdateState(__instance, (State)9);
stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID());
return false;
}
if (Plugin.ShouldRunAwayWhileReloading() && orAddTracker.IsReloading)
{
Plugin.LogDebugF("StateIdlePrefix: Hunter " + ((Object)((Component)__instance).gameObject).name + " reloading. Moving away.");
enemyNavMeshAgent.Warp(((Component)__instance).transform.position);
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_00a5: 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)9);
stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID());
return false;
}
if (Plugin.ShouldRunAwayWhileReloading() && orAddTracker.IsReloading)
{
Plugin.LogDebugF("StateRoamPrefix: Hunter " + ((Object)((Component)__instance).gameObject).name + " 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_0177: 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)
{
Plugin.LogDebugF("StateAimPrefix: Hunter " + ((Object)((Component)__instance).gameObject).name + " OOA. Forcing Leave.");
Plugin.CallUpdateState(__instance, (State)9);
stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID());
return false;
}
if (orAddTracker.IsReloading || orAddTracker.IsInterrupted || !orAddTracker.HasTotalAmmo)
{
string text = ((!orAddTracker.HasTotalAmmo) ? "OOA" : (orAddTracker.IsReloading ? $"reload({orAddTracker.GetRemainingReloadTime():F1}s)" : $"interrupt({orAddTracker.ConfigDamageInterruptDelay:F1}s)"));
Plugin.LogDebugF("StateAimPrefix BLOCKED: " + ((Object)((Component)__instance).gameObject).name + " is " + text + ".");
if (Plugin.ShouldRunAwayWhileReloading() && orAddTracker.IsReloading)
{
Plugin.LogDebugF("StateAimPrefix: " + ((Object)((Component)__instance).gameObject).name + " 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)
{
Plugin.LogErrorF("StateShootPrefix: " + ((Object)((Component)__instance).gameObject).name + " OOA! Forcing Leave.");
orAddTracker.isOutOfAmmoPermanently = true;
Plugin.CallUpdateState(__instance, (State)9);
stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID());
return false;
}
if (!Plugin.IsMinigunModeEnabled())
{
if (!orAddTracker.TryDecrementTotalAmmo())
{
Plugin.LogInfoF("StateShootPrefix(N): " + ((Object)((Component)__instance).gameObject).name + " OOA this shot. Forcing Leave.");
Plugin.CallUpdateState(__instance, (State)9);
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)
{
Plugin.LogErrorF("StateShootPrefix(M-Init): " + ((Object)((Component)__instance).gameObject).name + " OOA! Forcing Leave.");
orAddTracker.isOutOfAmmoPermanently = true;
Plugin.CallUpdateState(__instance, (State)9);
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())
{
Plugin.LogInfoF("StateShootPrefix(M): " + ((Object)((Component)__instance).gameObject).name + " OOA mid-burst. End & Leave.");
orAddTracker.EndMinigunBurst();
Plugin.CallUpdateState(__instance, (State)9);
stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID());
return false;
}
Plugin.LogDebugF($"StateShootPrefix: Fire minigun {orAddTracker.ConfigMinigunShots - orAddTracker.minigunShotsRemaining + 1}/{orAddTracker.ConfigMinigunShots}. Ammo: {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)8);
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)9);
stateLeaveFailCounters.Remove(((Object)__instance).GetInstanceID());
return false;
}
if (___stateTimer <= Time.deltaTime)
{
Plugin.LogInfoF($"StateShootEndPrefix(N): Shot {___shotsFired} done. LeaveStart & Reload.");
Plugin.CallUpdateState(__instance, (State)8);
orAddTracker.StartReload();
return false;
}
return true;
}
private static bool PreventReEngagePrefix(EnemyHunter __instance)
{
HunterAmmoTracker hunterAmmoTracker = ((__instance != null) ? ((Component)__instance).GetComponent<HunterAmmoTracker>() : null);
if ((Object)(object)hunterAmmoTracker != (Object)null && hunterAmmoTracker.isOutOfAmmoPermanently)
{
Plugin.LogDebugF("PreventReEngagePrefix: " + ((Object)((Component)__instance).gameObject).name + " 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_0151: 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)
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)
{
Plugin.LogInfoF("StateLeavePrefix: Hunter " + ((Object)((Component)__instance).gameObject).name + " OOA and reached Leave destination/timer. Forcing Despawn.");
Plugin.CallUpdateState(__instance, (State)10);
stateLeaveFailCounters.Remove(instanceID);
return false;
}
Plugin.LogDebugF("StateLeavePrefix: " + ((Object)((Component)__instance).gameObject).name + " reloading & reached dest/timer. Finding new retreat point.");
if (Plugin.FindRetreatPoint(__instance, out var retreatPoint))
{
stateLeaveFailCounters.Remove(instanceID);
FieldInfo fieldInfo = AccessTools.Field(typeof(EnemyHunter), "leavePosition");
if (fieldInfo != null)
{
fieldInfo.SetValue(__instance, 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;
Plugin.LogWarningF($"StateLeavePrefix: No new retreat point for {((Object)((Component)__instance).gameObject).name} while reloading. Failure {num}/{5}");
___stateTimer = 1f;
if (num >= 5)
{
Plugin.LogErrorF($"StateLeavePrefix: Hunter {((Object)((Component)__instance).gameObject).name} failed find retreat point {5} times WHILE RELOADING. Forcing Despawn.");
Plugin.CallUpdateState(__instance, (State)10);
stateLeaveFailCounters.Remove(instanceID);
}
}
return false;
}
Plugin.LogDebugF($"StateLeavePrefix: Timer > deltaT ({___stateTimer:F3}), allow original method.");
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;
public static Plugin Instance { get; private set; }
internal static ManualLogSource Log { get; private set; }
public static ConfigEntry<bool> EnableMinigunMode { get; private set; }
public static ConfigEntry<int> MinigunShots { get; private set; }
public static ConfigEntry<float> MinigunShotDelay { get; private set; }
public static ConfigEntry<float> FastReloadTimeConfig { get; private set; }
public static ConfigEntry<float> MediumReloadTimeConfig { get; private set; }
public static ConfigEntry<float> SlowReloadTimeConfig { get; private set; }
public static ConfigEntry<int> FastSkillWeight { get; private set; }
public static ConfigEntry<int> MediumSkillWeight { get; private set; }
public static ConfigEntry<int> SlowSkillWeight { get; private set; }
public static ConfigEntry<bool> EnableDamageInterruptConfig { get; private set; }
public static ConfigEntry<float> DamageInterruptDelayConfig { get; private set; }
public static ConfigEntry<bool> EnableTotalAmmoLimitConfig { get; private set; }
public static ConfigEntry<int> TotalAmmoCountConfig { get; private set; }
public static ConfigEntry<bool> RunAwayWhileReloadingConfig { get; private set; }
public static ConfigEntry<bool> EnableInfoLogs { get; private set; }
public static ConfigEntry<bool> EnableDebugLogs { get; private set; }
public static ConfigEntry<bool> EnableWarningLogs { get; private set; }
public static ConfigEntry<bool> EnableErrorLogs { get; private set; }
private void Awake()
{
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Expected O, but got Unknown
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Expected O, but got Unknown
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_010f: Expected O, but got Unknown
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Expected O, but got Unknown
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_018b: Expected O, but got Unknown
//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
//IL_01be: Expected O, but got Unknown
//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
//IL_01f1: Expected O, but got Unknown
//IL_021a: Unknown result type (might be due to invalid IL or missing references)
//IL_0224: Expected O, but got Unknown
//IL_0279: Unknown result type (might be due to invalid IL or missing references)
//IL_0283: Expected O, but got Unknown
//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
//IL_02fc: 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()
{
isRepoLastStandModPresent = Chainloader.PluginInfos.ContainsKey("umbreon222.repo.laststand");
if (isRepoLastStandModPresent)
{
LogInfoF("RepoLastStandMod detected. Enabling compatibility logic.");
try
{
string text = "RepoLastStandMod";
repoStateManagerType = Type.GetType("RepoLastStandMod.StateManager, " + text, throwOnError: false);
if (repoStateManagerType == null && Chainloader.PluginInfos.TryGetValue("umbreon222.repo.laststand", out var value) && (Object)(object)value.Instance != (Object)null)
{
text = ((object)value.Instance).GetType().Assembly.FullName;
repoStateManagerType = Type.GetType("RepoLastStandMod.StateManager, " + text, throwOnError: false);
LogDebugF("Attempting to load StateManager from assembly: " + text);
}
if (repoStateManagerType != null)
{
repoStateManagerInstanceProperty = AccessTools.Property(repoStateManagerType, "Instance");
repoLastStandActiveField = AccessTools.Field(repoStateManagerType, "LastStandActive");
if (repoStateManagerInstanceProperty == null)
{
LogErrorF("Could not find 'Instance' property on StateManager.");
}
if (repoLastStandActiveField == null)
{
LogErrorF("Could not find 'LastStandActive' field on StateManager.");
}
if (repoStateManagerInstanceProperty == null || repoLastStandActiveField == 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 arg)
{
LogErrorF($"Error during reflection for RepoLastStandMod compatibility: {arg}");
isRepoLastStandModPresent = false;
return;
}
}
LogInfoF("RepoLastStandMod not detected.");
}
public static void LogInfoF(string message)
{
if (Log != null && EnableInfoLogs.Value)
{
Log.LogInfo((object)message);
}
}
public static void LogDebugF(string message)
{
if (Log != null && EnableDebugLogs.Value)
{
Log.LogDebug((object)message);
}
}
public static void LogWarningF(string message)
{
if (Log != null && EnableWarningLogs.Value)
{
Log.LogWarning((object)message);
}
}
public static void LogErrorF(string message)
{
if (Log != null && EnableErrorLogs.Value)
{
Log.LogError((object)message);
}
}
public static bool IsMinigunModeEnabled()
{
return EnableMinigunMode.Value;
}
public static bool ShouldRunAwayWhileReloading()
{
return RunAwayWhileReloadingConfig.Value;
}
public static void CallUpdateState(EnemyHunter instance, State newState)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
MethodInfo methodInfo = AccessTools.Method(typeof(EnemyHunter), "UpdateState", (Type[])null, (Type[])null);
if (methodInfo != null)
{
methodInfo.Invoke(instance, new object[1] { newState });
return;
}
object obj;
if (instance == null)
{
obj = null;
}
else
{
GameObject gameObject = ((Component)instance).gameObject;
obj = ((gameObject != null) ? ((Object)gameObject).name : null);
}
LogErrorF("Could not find method 'UpdateState' on " + (string?)obj + "!");
}
public static void CallAimLogic(EnemyHunter instance)
{
MethodInfo methodInfo = AccessTools.Method(typeof(EnemyHunter), "AimLogic", (Type[])null, (Type[])null);
if (methodInfo != null)
{
methodInfo.Invoke(instance, null);
return;
}
object obj;
if (instance == null)
{
obj = null;
}
else
{
GameObject gameObject = ((Component)instance).gameObject;
obj = ((gameObject != null) ? ((Object)gameObject).name : null);
}
LogErrorF("Could not find method 'AimLogic' on " + (string?)obj + "!");
}
private static PhotonView GetPhotonView(EnemyHunter instance)
{
if ((Object)(object)instance == (Object)null)
{
return null;
}
try
{
FieldInfo fieldInfo = AccessTools.Field(typeof(EnemyHunter), "photonView");
if (fieldInfo != null)
{
object? value = fieldInfo.GetValue(instance);
return (PhotonView)((value is PhotonView) ? value : null);
}
LogErrorF("GetPhotonView: Could not find field 'photonView' on " + ((Object)((Component)instance).gameObject).name + "!");
return null;
}
catch (Exception ex)
{
LogErrorF("GetPhotonView: Error accessing 'photonView' field on " + ((Object)((Component)instance).gameObject).name + ": " + ex.Message);
return null;
}
}
public static void CallShootRPC(EnemyHunter instance)
{
//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: 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_0105: 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_0159: 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_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
//IL_018d: Unknown result type (might be due to invalid IL or missing references)
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_0221: Unknown result type (might be due to invalid IL or missing references)
//IL_022c: 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_01b2: Unknown result type (might be due to invalid IL or missing references)
//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
//IL_01be: Unknown result type (might be due to invalid IL or missing references)
//IL_024d: Unknown result type (might be due to invalid IL or missing references)
//IL_0252: Unknown result type (might be due to invalid IL or missing references)
//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
//IL_01fc: 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_01db: Unknown result type (might be due to invalid IL or missing references)
//IL_0211: Unknown result type (might be due to invalid IL or missing references)
//IL_0216: Unknown result type (might be due to invalid IL or missing references)
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);
}
LogDebugF("CallShootRPC skipped on non-MasterClient for " + (string?)obj);
return;
}
PhotonView photonView = GetPhotonView(instance);
if ((Object)(object)photonView == (Object)null)
{
LogErrorF("CallShootRPC: PhotonView is null for " + ((Object)((Component)instance).gameObject).name + "! 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 fieldInfo = AccessTools.Field(typeof(EnemyHunter), "investigatePoint");
if (fieldInfo != null)
{
Vector3 val2 = (Vector3)fieldInfo.GetValue(instance);
float num = ((Vector3.Distance(((Component)instance).transform.position, val2) > 10f) ? 0.5f : 1f);
LayerMask val3 = LayerMask.op_Implicit(LayerMask.GetMask(new string[4] { "Player", "Default", "PhysGrabObject", "Enemy" }));
LayerMask val4 = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { "Default" }));
RaycastHit val5 = default(RaycastHit);
if (Physics.SphereCast(instance.gunAimTransform.position, num, instance.gunAimTransform.forward, ref val5, 50f, LayerMask.op_Implicit(val3)))
{
if (!Physics.Linecast(instance.gunAimTransform.position, ((RaycastHit)(ref val5)).point, LayerMask.op_Implicit(val4)))
{
val = ((RaycastHit)(ref val5)).point;
}
else if (Physics.Raycast(instance.gunAimTransform.position, instance.gunAimTransform.forward, ref val5, 50f, LayerMask.op_Implicit(val3)))
{
val = ((RaycastHit)(ref val5)).point;
}
}
else if (Physics.Raycast(instance.gunAimTransform.position, instance.gunAimTransform.forward, ref val5, 50f, LayerMask.op_Implicit(val3)))
{
val = ((RaycastHit)(ref val5)).point;
}
}
else
{
LogWarningF("Could not access investigatePoint field for " + ((Object)((Component)instance).gameObject).name + "!");
}
}
catch (Exception ex)
{
LogErrorF("Error calculating target position: " + ex.Message);
}
try
{
LogDebugF($"Sending ShootRPC for {((Object)((Component)instance).gameObject).name} targeting {val}");
photonView.RPC("ShootRPC", (RpcTarget)0, new object[1] { val });
}
catch (Exception arg)
{
LogErrorF($"Failed to send ShootRPC for {((Object)((Component)instance).gameObject).name}: {arg}");
}
}
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_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: 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_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: 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_0184: 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_018b: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: 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_01f7: Unknown result type (might be due to invalid IL or missing references)
//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0202: 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)
//IL_020c: 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_01ad: Unknown result type (might be due to invalid IL or missing references)
//IL_01b2: 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_0224: Unknown result type (might be due to invalid IL or missing references)
//IL_0229: Unknown result type (might be due to invalid IL or missing references)
//IL_023f: 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 = float.MaxValue;
if (GameDirector.instance.PlayerList == null || GameDirector.instance.PlayerList.Count == 0)
{
LogWarningF("FindRetreatPoint: GameDirector.PlayerList is null or empty.");
return false;
}
foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
{
if (!((Object)(object)player == (Object)null) && ((Component)player).gameObject.activeSelf)
{
float num2 = Vector3.Distance(((Component)instance).transform.position, ((Component)player).transform.position);
if (num2 < num)
{
num = num2;
val = player;
}
}
}
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;
Vector3 val3 = ((Vector3)(ref val2)).normalized;
val3.y = 0f;
if (val3 == Vector3.zero)
{
val3 = ((Component)instance).transform.forward;
}
float num3 = 20f;
float num4 = 15f;
Vector3 val4 = ((Component)instance).transform.position + val3 * num3;
NavMeshHit val5 = default(NavMeshHit);
if (NavMesh.SamplePosition(val4, ref val5, num4, -1))
{
retreatPoint = ((NavMeshHit)(ref val5)).position;
LogDebugF($"Found retreat point for {((Object)((Component)instance).gameObject).name} at {retreatPoint} (away from player {((Object)val).GetInstanceID()})");
return true;
}
val4 = ((Component)instance).transform.position + val3 * 8f;
if (NavMesh.SamplePosition(val4, ref val5, num4, -1))
{
retreatPoint = ((NavMeshHit)(ref val5)).position;
LogDebugF($"Found fallback retreat point (closer) for {((Object)((Component)instance).gameObject).name} at {retreatPoint}");
return true;
}
LogWarningF("Could not find NavMesh retreat point for " + ((Object)((Component)instance).gameObject).name + " after searching.");
return false;
}
public static bool IsRepoLastStandActive()
{
if (!isRepoLastStandModPresent || repoStateManagerType == null || repoStateManagerInstanceProperty == null || repoLastStandActiveField == null)
{
return false;
}
try
{
object value = repoStateManagerInstanceProperty.GetValue(null);
if (value == null)
{
LogWarningF("RepoLastStandMod StateManager.Instance returned null.");
return false;
}
object value2 = repoLastStandActiveField.GetValue(value);
return (bool)value2;
}
catch (Exception arg)
{
LogErrorF($"Error getting RepoLastStandMod state via reflection: {arg}");
return false;
}
}
}
public static class PluginInfo
{
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
{
Fast,
Medium,
Slow
}