using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using Configgy;
using HarmonyLib;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("GabrielAlly")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GabrielAlly")]
[assembly: AssemblyTitle("GabrielAlly")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace GabrielAlly;
[BepInPlugin("GabrielAlly.adry.ultrakill", "GabrielAlly", "1.3.1")]
public class GabrielAlly : BaseUnityPlugin
{
public static ManualLogSource Log;
public static bool IsRespawning = false;
private static GameObject allyInstance;
private Harmony harmonyInstance;
private readonly string[] specialScenes = new string[3] { "intro", "main menu", "bootstrap" };
public static string IntendedSceneName = null;
public static string currentAllyPath = "";
private static bool hasLoggedPlayerDeath = false;
public static GabrielAlly Instance { get; private set; }
public static GameObject DefaultPrefab { get; private set; }
private void Awake()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Expected O, but got Unknown
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
Instance = this;
harmonyInstance = new Harmony("GabrielAlly.adry.ultrakill");
harmonyInstance.PatchAll();
Log = ((BaseUnityPlugin)this).Logger;
Log.LogInfo((object)"GabrielAlly mod has been enabled!");
GameObject defaultPrefab = Addressables.LoadAssetAsync<GameObject>((object)"Assets/Prefabs/Enemies/Gabriel.prefab").WaitForCompletion();
DefaultPrefab = defaultPrefab;
((Component)this).gameObject.AddComponent<GabrielAllyConfig>();
}
private void OnEnable()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
SceneManager.sceneLoaded += OnSceneLoaded;
Application.logMessageReceived += new LogCallback(HandleLog);
}
private void OnDisable()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
SceneManager.sceneLoaded -= OnSceneLoaded;
Application.logMessageReceived -= new LogCallback(HandleLog);
}
private void HandleLog(string logString, string stackTrace, LogType type)
{
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
//IL_01da: Unknown result type (might be due to invalid IL or missing references)
//IL_01df: Unknown result type (might be due to invalid IL or missing references)
//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0203: Unknown result type (might be due to invalid IL or missing references)
//IL_0240: Unknown result type (might be due to invalid IL or missing references)
//IL_0241: Unknown result type (might be due to invalid IL or missing references)
//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
if (!((ConfigValueElement<bool>)(object)GabrielAllyConfig.enableMod).Value)
{
Log.LogInfo((object)"Mod is disabled. Removing any existing ally instance.");
if ((Object)(object)allyInstance != (Object)null)
{
Object.Destroy((Object)(object)allyInstance);
allyInstance = null;
}
return;
}
string text = (IntendedSceneName ?? ((Scene)(ref scene)).name).Trim().ToLower();
if (text.Equals("intro") || text.Equals("main menu") || text.Equals("bootstrap"))
{
Log.LogInfo((object)("Scene '" + text + "' is special. Not spawning ally."));
if ((Object)(object)allyInstance != (Object)null)
{
Object.Destroy((Object)(object)allyInstance);
allyInstance = null;
}
return;
}
if ((Object)(object)allyInstance != (Object)null && currentAllyPath == ((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value)
{
Log.LogInfo((object)"Ally instance already exists. Not spawning a duplicate.");
return;
}
Log.LogInfo((object)("Scene '" + ((Scene)(ref scene)).name + "' allowed (intended: '" + text + "'). Spawning " + GabrielAllyConfig.selectAlly.GetSelectedIndexName() + "."));
if ((Object)(object)allyInstance != (Object)null)
{
Object.Destroy((Object)(object)allyInstance);
allyInstance = null;
}
NewMovement instance = MonoSingleton<NewMovement>.Instance;
if ((Object)(object)instance == (Object)null)
{
Log.LogWarning((object)"Player (NewMovement.Instance) not found.");
return;
}
Vector3 val = ((Component)instance).transform.position - ((Component)instance).transform.forward * 15f + Vector3.up * 1.25f;
GameObject val2 = Addressables.LoadAssetAsync<GameObject>((object)((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value).WaitForCompletion();
if ((Object)(object)val2 == (Object)null)
{
Log.LogWarning((object)("Failed to load ally prefab from path: " + ((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value));
return;
}
allyInstance = Object.Instantiate<GameObject>(val2, val, Quaternion.identity);
allyInstance.AddComponent<GabrielAllyController>();
currentAllyPath = ((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value;
EnemyIdentifier component = allyInstance.GetComponent<EnemyIdentifier>();
if ((Object)(object)component != (Object)null)
{
component.ignorePlayer = true;
component.attackEnemies = true;
component.fallbackTarget = null;
component.Bless(true);
Log.LogInfo((object)(GabrielAllyConfig.selectAlly.GetSelectedIndexName() + " EnemyIdentifier configured: ignorePlayer=true, attackEnemies=true, Blessed applied."));
}
Log.LogInfo((object)$"{GabrielAllyConfig.selectAlly.GetSelectedIndexName()} spawned in scene '{((Scene)(ref scene)).name}' at position {val}.");
}
private void Update()
{
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
if (!((ConfigValueElement<bool>)(object)GabrielAllyConfig.enableMod).Value)
{
if ((Object)(object)allyInstance != (Object)null)
{
Log.LogInfo((object)"Mod disabled via config. Removing ally instance.");
Object.Destroy((Object)(object)allyInstance);
allyInstance = null;
}
return;
}
NewMovement instance = MonoSingleton<NewMovement>.Instance;
if ((Object)(object)instance != (Object)null && instance.hp <= 0)
{
if (!hasLoggedPlayerDeath)
{
Log.LogInfo((object)"Player is dead; removing ally instance.");
hasLoggedPlayerDeath = true;
}
if ((Object)(object)allyInstance != (Object)null)
{
Object.Destroy((Object)(object)allyInstance);
allyInstance = null;
}
return;
}
hasLoggedPlayerDeath = false;
Scene activeScene;
if ((Object)(object)allyInstance == (Object)null)
{
string text = IntendedSceneName;
if (text == null)
{
activeScene = SceneManager.GetActiveScene();
text = ((Scene)(ref activeScene)).name;
}
string value = text.Trim().ToLower();
if (!specialScenes.Contains(value))
{
UpdateAllyInstance();
}
}
if (GabrielAllyConfig.resetAllyKey.WasPeformed())
{
string text2 = IntendedSceneName;
if (text2 == null)
{
activeScene = SceneManager.GetActiveScene();
text2 = ((Scene)(ref activeScene)).name;
}
string value2 = text2.Trim().ToLower();
if (specialScenes.Contains(value2))
{
Log.LogInfo((object)"Reset key pressed in a special scene. Reset is not allowed.");
}
else
{
Instance.ResetAlly();
}
}
}
public static IEnumerator RespawnAllyCoroutine(float delay)
{
Log.LogInfo((object)(GabrielAllyConfig.selectAlly.GetSelectedIndexName() + " died. Scheduling respawn in 5 seconds."));
yield return (object)new WaitForSeconds(delay);
if ((Object)(object)allyInstance != (Object)null && currentAllyPath == ((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value)
{
Log.LogInfo((object)"Ally instance already exists during respawn. Aborting duplicate respawn.");
IsRespawning = false;
yield break;
}
NewMovement player = MonoSingleton<NewMovement>.Instance;
if ((Object)(object)player == (Object)null)
{
Log.LogWarning((object)"Respawn not executed - player not found.");
IsRespawning = false;
yield break;
}
Vector3 spawnPos = ((Component)player).transform.position - ((Component)player).transform.forward * 15f + Vector3.up * 1.25f;
GameObject prefab = Addressables.LoadAssetAsync<GameObject>((object)((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value).WaitForCompletion();
if ((Object)(object)prefab == (Object)null)
{
Log.LogWarning((object)"Respawn not executed - ally prefab is not defined.");
IsRespawning = false;
yield break;
}
GameObject newAlly = Object.Instantiate<GameObject>(prefab, spawnPos, Quaternion.identity);
newAlly.AddComponent<GabrielAllyController>();
currentAllyPath = ((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value;
EnemyIdentifier enemyId = newAlly.GetComponent<EnemyIdentifier>();
if ((Object)(object)enemyId != (Object)null)
{
enemyId.ignorePlayer = true;
enemyId.attackEnemies = true;
enemyId.fallbackTarget = null;
enemyId.Bless(true);
Log.LogInfo((object)("Respawn - EnemyIdentifier configured for " + GabrielAllyConfig.selectAlly.GetSelectedIndexName() + ": ignorePlayer=true, attackEnemies=true, Blessed applied."));
}
allyInstance = newAlly;
IsRespawning = false;
Log.LogInfo((object)$"{GabrielAllyConfig.selectAlly.GetSelectedIndexName()} respawned at position {spawnPos}.");
}
public void ResetAlly()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: 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_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: 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)
string text = IntendedSceneName;
if (text == null)
{
Scene activeScene = SceneManager.GetActiveScene();
text = ((Scene)(ref activeScene)).name;
}
string value = text.Trim().ToLower();
if (specialScenes.Contains(value))
{
Log.LogInfo((object)"Reset key pressed in a special scene. Reset is not allowed.");
return;
}
Log.LogWarning((object)(GabrielAllyConfig.selectAlly.GetSelectedIndexName() + " instance reset due to reset key press or forced checkpoint."));
if ((Object)(object)allyInstance != (Object)null)
{
Object.Destroy((Object)(object)allyInstance);
allyInstance = null;
}
NewMovement instance = MonoSingleton<NewMovement>.Instance;
if ((Object)(object)instance == (Object)null)
{
Log.LogWarning((object)"Cannot reset ally - player not found.");
return;
}
Vector3 val = ((Component)instance).transform.position - ((Component)instance).transform.forward * 15f + Vector3.up * 1.25f;
GameObject val2 = Addressables.LoadAssetAsync<GameObject>((object)((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value).WaitForCompletion();
if ((Object)(object)val2 == (Object)null)
{
Log.LogWarning((object)"Cannot reset ally - failed to load prefab.");
return;
}
allyInstance = Object.Instantiate<GameObject>(val2, val, Quaternion.identity);
allyInstance.AddComponent<GabrielAllyController>();
currentAllyPath = ((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value;
EnemyIdentifier component = allyInstance.GetComponent<EnemyIdentifier>();
if ((Object)(object)component != (Object)null)
{
component.ignorePlayer = true;
component.attackEnemies = true;
component.fallbackTarget = null;
component.Bless(true);
}
Log.LogInfo((object)$"{GabrielAllyConfig.selectAlly.GetSelectedIndexName()} instance has been reset at position {val}.");
}
public void UpdateAllyInstance()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_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_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_014b: Unknown result type (might be due to invalid IL or missing references)
//IL_0150: 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_018e: Unknown result type (might be due to invalid IL or missing references)
//IL_0208: Unknown result type (might be due to invalid IL or missing references)
string text = IntendedSceneName;
if (text == null)
{
Scene activeScene = SceneManager.GetActiveScene();
text = ((Scene)(ref activeScene)).name;
}
string text2 = text.Trim().ToLower();
if (specialScenes.Contains(text2))
{
Log.LogInfo((object)("Current scene '" + text2 + "' is special. Not updating ally instance."));
return;
}
if ((Object)(object)allyInstance != (Object)null && currentAllyPath == ((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value)
{
Log.LogInfo((object)"Ally instance already exists with the selected prefab. No update needed.");
return;
}
Log.LogInfo((object)("Ally selection changed to: " + GabrielAllyConfig.selectAlly.GetSelectedIndexName() + ". Updating ally instance."));
if ((Object)(object)allyInstance != (Object)null)
{
Object.Destroy((Object)(object)allyInstance);
allyInstance = null;
}
NewMovement instance = MonoSingleton<NewMovement>.Instance;
if ((Object)(object)instance == (Object)null)
{
Log.LogWarning((object)"UpdateAllyInstance: Player (NewMovement.Instance) not found.");
return;
}
Vector3 val = ((Component)instance).transform.position - ((Component)instance).transform.forward * 15f + Vector3.up * 1.25f;
GameObject val2 = Addressables.LoadAssetAsync<GameObject>((object)((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value).WaitForCompletion();
if ((Object)(object)val2 == (Object)null)
{
Log.LogWarning((object)("UpdateAllyInstance: Failed to load ally prefab from path: " + ((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value));
return;
}
allyInstance = Object.Instantiate<GameObject>(val2, val, Quaternion.identity);
allyInstance.AddComponent<GabrielAllyController>();
currentAllyPath = ((ConfigValueElement<string>)(object)GabrielAllyConfig.selectAlly).Value;
EnemyIdentifier component = allyInstance.GetComponent<EnemyIdentifier>();
if ((Object)(object)component != (Object)null)
{
component.ignorePlayer = true;
component.attackEnemies = true;
component.fallbackTarget = null;
component.Bless(true);
}
Log.LogInfo((object)$"Ally instance updated: {GabrielAllyConfig.selectAlly.GetSelectedIndexName()} spawned at position {val}.");
}
}
[HarmonyPatch(typeof(SceneHelper), "LoadSceneAsync")]
public static class SceneHelper_LoadSceneAsync_Patch
{
private static void Prefix(string sceneName, bool noSplash)
{
GabrielAlly.IntendedSceneName = sceneName.Trim();
Debug.Log((object)("[Patch] Intended scene name set to: " + GabrielAlly.IntendedSceneName));
}
}
[HarmonyPatch(typeof(OptionsManager), "RestartCheckpoint")]
public static class OptionsManager_RestartCheckpoint_Patch
{
private static void Postfix()
{
if ((Object)(object)GabrielAlly.Instance != (Object)null && ((ConfigValueElement<bool>)(object)GabrielAllyConfig.enableMod).Value)
{
GabrielAlly.Instance.ResetAlly();
GabrielAlly.Log.LogInfo((object)"Ally instance reset due to forced checkpoint via menu.");
}
}
}
public class GabrielAllyController : MonoBehaviour
{
private enum Mode
{
Follow,
Attack
}
public bool hasDied = false;
private Mode currentMode;
private EnemyIdentifier enemyId;
private float timer;
private float followCooldownTimer;
private float updateInterval = 0.5f;
private Vector3 followOffset = Vector3.up * 1.25f;
private float followCooldown => ((ConfigValueElement<float>)(object)GabrielAllyConfig.followCooldown).Value;
private float followDistance => ((ConfigValueElement<float>)(object)GabrielAllyConfig.followDistance).Value;
private float maxDistanceFromPlayer => ((ConfigValueElement<float>)(object)GabrielAllyConfig.maxDistanceFromPlayer).Value;
private float maxFollowOffsetDistance => ((ConfigValueElement<float>)(object)GabrielAllyConfig.maxFollowOffsetDistance).Value;
private float attackDistance => ((ConfigValueElement<float>)(object)GabrielAllyConfig.attackDistance).Value;
private void Awake()
{
enemyId = ((Component)this).GetComponent<EnemyIdentifier>();
currentMode = Mode.Follow;
hasDied = false;
if ((Object)(object)enemyId != (Object)null)
{
enemyId.ignorePlayer = true;
enemyId.attackEnemies = true;
enemyId.fallbackTarget = null;
}
}
private void Update()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_014a: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: 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_0243: Unknown result type (might be due to invalid IL or missing references)
//IL_0248: 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_025b: Unknown result type (might be due to invalid IL or missing references)
//IL_0260: Unknown result type (might be due to invalid IL or missing references)
//IL_026d: Unknown result type (might be due to invalid IL or missing references)
//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0402: Unknown result type (might be due to invalid IL or missing references)
//IL_0406: Unknown result type (might be due to invalid IL or missing references)
//IL_040b: Unknown result type (might be due to invalid IL or missing references)
//IL_0414: Unknown result type (might be due to invalid IL or missing references)
//IL_0419: Unknown result type (might be due to invalid IL or missing references)
//IL_0420: Unknown result type (might be due to invalid IL or missing references)
//IL_042a: Unknown result type (might be due to invalid IL or missing references)
//IL_042f: Unknown result type (might be due to invalid IL or missing references)
//IL_043a: Unknown result type (might be due to invalid IL or missing references)
//IL_043c: Unknown result type (might be due to invalid IL or missing references)
//IL_0441: Unknown result type (might be due to invalid IL or missing references)
//IL_044f: Unknown result type (might be due to invalid IL or missing references)
//IL_0454: Unknown result type (might be due to invalid IL or missing references)
//IL_0461: Unknown result type (might be due to invalid IL or missing references)
//IL_033e: Unknown result type (might be due to invalid IL or missing references)
//IL_034a: Unknown result type (might be due to invalid IL or missing references)
NewMovement instance = MonoSingleton<NewMovement>.Instance;
if ((Object)(object)instance == (Object)null)
{
return;
}
if (Vector3.Distance(((Component)this).transform.position, ((Component)instance).transform.position) > maxDistanceFromPlayer)
{
Vector3 position = ((Component)instance).transform.position - ((Component)instance).transform.forward * followDistance + followOffset;
((Component)this).transform.position = position;
currentMode = Mode.Follow;
if ((Object)(object)enemyId != (Object)null)
{
enemyId.target = null;
}
followCooldownTimer = 0f;
GabrielAlly.Log.LogDebug((object)"Player is too far; teleporting ally behind the player.");
return;
}
if (currentMode == Mode.Follow)
{
Vector3 val = ((Component)instance).transform.position - ((Component)instance).transform.forward * followDistance + followOffset;
if (Vector3.Distance(((Component)this).transform.position, val) > maxFollowOffsetDistance)
{
((Component)this).transform.position = val;
}
else
{
((Component)this).transform.position = Vector3.Lerp(((Component)this).transform.position, val, Time.deltaTime * 5f);
}
followCooldownTimer = 0f;
}
List<EnemyIdentifier> list = (from e in Object.FindObjectsOfType<EnemyIdentifier>()
where (Object)(object)((Component)e).GetComponent<GabrielAllyController>() == (Object)null && !e.dead && (int)e.enemyType != 21 && Vector3.Distance(((Component)this).transform.position, ((Component)e).transform.position) <= attackDistance
select e).ToList();
if (list.Count > 0)
{
currentMode = Mode.Attack;
followCooldownTimer = 0f;
}
else if (currentMode == Mode.Attack)
{
followCooldownTimer += Time.deltaTime;
if (followCooldownTimer >= followCooldown)
{
currentMode = Mode.Follow;
}
}
else
{
currentMode = Mode.Follow;
followCooldownTimer = 0f;
}
GabrielAlly.Log.LogDebug((object)$"Current mode is {currentMode}.");
if (currentMode == Mode.Follow)
{
Quaternion val2 = Quaternion.LookRotation(((Component)instance).transform.forward);
((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, val2, Time.deltaTime * 5f);
if ((Object)(object)enemyId != (Object)null)
{
enemyId.target = null;
}
}
else
{
if (currentMode != Mode.Attack)
{
return;
}
timer += Time.deltaTime;
if (timer >= updateInterval)
{
timer = 0f;
List<EnemyIdentifier> list2 = (from e in Object.FindObjectsOfType<EnemyIdentifier>()
where (Object)(object)((Component)e).GetComponent<GabrielAllyController>() == (Object)null && !e.dead && (int)e.enemyType != 21 && Vector3.Distance(((Component)this).transform.position, ((Component)e).transform.position) <= attackDistance
select e).ToList();
if (list2.Count > 0)
{
EnemyIdentifier val3 = null;
float num = float.MaxValue;
foreach (EnemyIdentifier item in list2)
{
float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)item).transform.position);
if (num2 < num)
{
num = num2;
val3 = item;
}
}
if ((Object)(object)val3 != (Object)null)
{
EnemyTarget component = ((Component)val3).GetComponent<EnemyTarget>();
if (component != null)
{
enemyId.target = component;
}
}
}
else
{
enemyId.target = null;
}
}
if (enemyId.target != null)
{
Vector3 val4 = enemyId.target.headPosition - ((Component)this).transform.position;
Vector3 normalized = ((Vector3)(ref val4)).normalized;
Transform transform = ((Component)this).transform;
transform.position += normalized * 10f * Time.deltaTime;
Quaternion val5 = Quaternion.LookRotation(normalized);
((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, val5, Time.deltaTime * 10f);
}
}
}
}
[HarmonyPatch(typeof(EnemyIdentifier), "DeliverDamage")]
public class EnemyIdentifier_DeliverDamage_Patch
{
private static bool Prefix(EnemyIdentifier __instance, GameObject target, Vector3 force, Vector3 hitPoint, float multiplier, bool tryForExplode, float critMultiplier, GameObject sourceWeapon, bool ignoreTotalDamageTakenMultiplier, bool fromExplosion)
{
if ((Object)(object)((Component)__instance).GetComponent<GabrielAllyController>() != (Object)null)
{
return false;
}
return true;
}
}
[HarmonyPatch(typeof(EnemyIdentifier), "IsTypeFriendly")]
public class EnemyIdentifier_IsTypeFriendly_Patch
{
private static bool Prefix(EnemyIdentifier __instance, EnemyIdentifier owner, ref bool __result)
{
if ((Object)(object)((Component)__instance).GetComponent<GabrielAllyController>() != (Object)null)
{
__result = false;
return false;
}
return true;
}
}
[HarmonyPatch(typeof(EnemyIdentifier), "Death", new Type[] { })]
public class EnemyIdentifier_Death_Patch
{
private static void Postfix(EnemyIdentifier __instance)
{
GabrielAllyController component = ((Component)__instance).GetComponent<GabrielAllyController>();
if ((Object)(object)component != (Object)null && !component.hasDied)
{
component.hasDied = true;
string text = __instance.hitter ?? "unknown";
GabrielAlly.Log.LogInfo((object)(GabrielAllyConfig.selectAlly.GetSelectedIndexName() + " died. Cause: " + text));
if (!GabrielAlly.IsRespawning)
{
GabrielAlly.IsRespawning = true;
((MonoBehaviour)GabrielAlly.Instance).StartCoroutine(GabrielAlly.RespawnAllyCoroutine(5f));
}
}
}
}
[HarmonyPatch(typeof(DeathZone), "GotHit")]
public class DeathZone_GabrielImmune_Patch
{
private static bool Prefix(DeathZone __instance, Collider other)
{
if ((Object)(object)((Component)other).gameObject.GetComponentInParent<GabrielAllyController>() != (Object)null)
{
return false;
}
return true;
}
}
[HarmonyPatch(typeof(OutOfBounds), "OnTriggerEnter")]
public class OutOfBounds_GabrielImmunity_Patch
{
private static bool Prefix(OutOfBounds __instance, Collider other)
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)((Component)other).gameObject.GetComponentInParent<GabrielAllyController>() != (Object)null)
{
GabrielAlly.Log.LogInfo((object)(GabrielAllyConfig.selectAlly.GetSelectedIndexName() + " detected in OutOfBounds; teleporting it back behind the player."));
NewMovement instance = MonoSingleton<NewMovement>.Instance;
if ((Object)(object)instance != (Object)null)
{
Vector3 position = ((Component)instance).transform.position - ((Component)instance).transform.forward * 15f + Vector3.up * 1.25f;
((Component)other).transform.position = position;
}
return false;
}
return true;
}
}
public class GabrielAllyConfig : MonoBehaviour
{
[Configgable("General", "Enable Mod", 0, "Enable or disable the GabrielAlly mod. When disabled, the mod will remove any ally instance.")]
public static ConfigToggle enableMod = new ConfigToggle(true);
[Configgable("General", "Select Ally", 1, "Select which ally prefab to use as your ally.")]
public static ConfigDropdown<string> selectAlly = new ConfigDropdown<string>(new string[6] { "Assets/Prefabs/Enemies/Gabriel.prefab", "Assets/Prefabs/Enemies/Gabriel 2nd Variant.prefab", "Assets/Prefabs/Enemies/V2.prefab", "Assets/Prefabs/Enemies/V2 Green Arm Variant.prefab", "Assets/Prefabs/Enemies/MinosPrime.prefab", "Assets/Prefabs/Enemies/SisyphusPrime.prefab" }, new string[6] { "Gabriel", "Gabriel 2nd Variant", "V2", "V2 Green Arm Variant", "MinosPrime", "SisyphusPrime" }, 0);
[Configgable("General", "Reset Ally Key", 2, "Key to reset the ally instance when pressed (default: G)")]
public static ConfigKeybind resetAllyKey = new ConfigKeybind((KeyCode)103);
[Configgable("Advanced", "Follow Distance", 3, "Distance behind the player when following (default: 10, max: 1000)")]
public static ConfigInputField<float> followDistance = new ConfigInputField<float>(10f, (Func<float, bool>)((float x) => x <= 1000f), (Func<string, ValueTuple<bool, float>>)null);
[Configgable("Advanced", "Max Distance From Player", 4, "Maximum allowed distance from the player (default: 80, max: 1000)")]
public static ConfigInputField<float> maxDistanceFromPlayer = new ConfigInputField<float>(80f, (Func<float, bool>)((float x) => x <= 1000f), (Func<string, ValueTuple<bool, float>>)null);
[Configgable("Advanced", "Max Follow Offset Distance", 5, "Maximum offset distance from the follow position (default: 50, max: 1000)")]
public static ConfigInputField<float> maxFollowOffsetDistance = new ConfigInputField<float>(50f, (Func<float, bool>)((float x) => x <= 1000f), (Func<string, ValueTuple<bool, float>>)null);
[Configgable("Advanced", "Attack Distance", 6, "Distance within which the ally detects enemies (default: 80, max: 1000)")]
public static ConfigInputField<float> attackDistance = new ConfigInputField<float>(80f, (Func<float, bool>)((float x) => x <= 1000f), (Func<string, ValueTuple<bool, float>>)null);
[Configgable("Advanced", "Follow Cooldown", 7, "Cooldown in seconds before ally returns to follow mode (default: 5, max: 1000)")]
public static ConfigInputField<float> followCooldown = new ConfigInputField<float>(5f, (Func<float, bool>)((float x) => x <= 1000f), (Func<string, ValueTuple<bool, float>>)null);
public static GameObject defaultPrefab;
private void Awake()
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
ConfigBuilder val = new ConfigBuilder("GabrielAlly.GabrielAllyConfig", "GabrielAlly");
val.BuildAll();
ConfigDropdown<string> obj = selectAlly;
((ConfigValueElement<string>)(object)obj).OnValueChanged = (Action<string>)Delegate.Combine(((ConfigValueElement<string>)(object)obj).OnValueChanged, (Action<string>)delegate
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)GabrielAlly.Instance != (Object)null)
{
string text = GabrielAlly.IntendedSceneName;
if (text == null)
{
Scene activeScene = SceneManager.GetActiveScene();
text = ((Scene)(ref activeScene)).name;
}
string text2 = text.Trim().ToLower();
if (!text2.Equals("intro") && !text2.Equals("main menu") && !text2.Equals("bootstrap"))
{
GabrielAlly.Instance.UpdateAllyInstance();
}
else
{
GabrielAlly.Log.LogInfo((object)("Current scene '" + text2 + "' is special. Not updating ally instance."));
}
}
});
}
}