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 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
}
}