Decompiled source of KillThemAll v0.1.2

KillThemAll.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using KillThemAll.Extras;
using KillThemAll.Hooks;
using KillThemAll.Managers;
using KillThemAll.Models;
using KillThemAll.Network;
using LethalBestiary.Modules;
using LethalLib.Modules;
using RuntimeNetcodeRPCValidator;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("KillThemAll")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("KillThemAll")]
[assembly: AssemblyTitle("KillThemAll")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace KillThemAll
{
	[BepInPlugin("KillThemAll.Main", "KillThemAll", "0.1.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class KillThemAll : BaseUnityPlugin
	{
		private const string modGUID = "KillThemAll.Main";

		private const string modName = "KillThemAll";

		private const string modVersion = "0.1.2";

		public static KillThemAll instance;

		public static AssetBundle hitMarkAsset;

		public static AssetBundle hitMarkSfxAsset;

		public static AssetBundle enemyExplosionEffectAsset;

		public static AssetBundle playerReactionsSfxAsset;

		public static AssetBundle notificationAsset;

		private readonly Harmony harmony = new Harmony("KillThemAll.Main");

		private NetcodeValidator netcodeValidator;

		private Dictionary<string, ConfigEntry<int>> enemyConfigEntries = new Dictionary<string, ConfigEntry<int>>();

		private void Awake()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			if ((Object)(object)instance == (Object)null)
			{
				instance = this;
			}
			Utilities.SetupLog();
			Utilities.DebugLog("Awaking");
			LoadAssetBundles();
			harmony.PatchAll(typeof(VanillaHook));
			netcodeValidator = new NetcodeValidator("KillThemAll.Main");
			netcodeValidator.PatchAll();
			netcodeValidator.BindToPreExistingObjectByBehaviour<KillableEnemyEmitter, PlayerControllerB>();
			netcodeValidator.BindToPreExistingObjectByBehaviour<UIEmitter, PlayerControllerB>();
			Utilities.DebugLog("Awaken");
		}

		public static List<Type> FindAllDerivedTypes<T>()
		{
			return FindAllDerivedTypes<T>(Assembly.GetAssembly(typeof(T)));
		}

		public static List<Type> FindAllDerivedTypes<T>(Assembly assembly)
		{
			Type baseType = typeof(T);
			return (from t in assembly.GetTypes()
				where t != baseType && baseType.IsAssignableFrom(t)
				select t).ToList();
		}

		public void Initialise()
		{
			AddKillThemAllBaseConfigs();
			AddBountyConfigs();
			Utilities.DebugLog("Finding all base enemies...");
			List<string> list = new List<string>();
			List<Type> list2 = FindAllDerivedTypes<EnemyAI>();
			foreach (Type item in list2)
			{
				if (!(item.Name == "TestEnemy") && !(item.Name == "LassoMan"))
				{
					string name = item.Name;
					name = name.Replace("Enemy", "");
					name = name.Replace("(Clone)", "");
					name = name.Replace(".prefab", "");
					name = name.Replace("AI", "");
					Utilities.DebugLog("Found enemy: " + name);
					list.Add(name);
				}
			}
			Utilities.DebugLog("Finding all LethalLib enemies...");
			foreach (SpawnableEnemy spawnableEnemy in Enemies.spawnableEnemies)
			{
				string enemyName = spawnableEnemy.enemy.enemyName;
				enemyName = enemyName.Replace("Enemy", "");
				enemyName = enemyName.Replace("(Clone)", "");
				enemyName = enemyName.Replace(".prefab", "");
				enemyName = enemyName.Replace("AI", "");
				Utilities.DebugLog("Found enemy from LethalLib: " + enemyName);
				list.Add(enemyName);
			}
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			directoryName.Replace("OLO-KillThemAll", "");
			directoryName += "TheWeavers-LethalBestiary/LethalBestiary/LethalBestiary.dll";
			Utilities.DebugLog("Finding all LethalBestiary enemies...");
			foreach (SpawnableEnemy spawnableEnemy2 in Enemies.spawnableEnemies)
			{
				string enemyName2 = spawnableEnemy2.enemy.enemyName;
				enemyName2 = enemyName2.Replace("Enemy", "");
				enemyName2 = enemyName2.Replace("(Clone)", "");
				enemyName2 = enemyName2.Replace(".prefab", "");
				enemyName2 = enemyName2.Replace("AI", "");
				Utilities.DebugLog("Found enemy from LethalBestiary: " + enemyName2);
				list.Add(enemyName2);
			}
			Utilities.DebugLog("Creating config entries based on enemies found...");
			foreach (string item2 in list)
			{
				string text = "Enemy Health";
				string text2 = item2 + " Health";
				int num = 0;
				ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>(text, text2, num, "Health points for " + item2 + "s");
				enemyConfigEntries.Add(item2, val);
				KillableEnemyManager.Instance.enemyHealthDictionary.Add(item2, val.Value);
				Utilities.DebugLog("Config entry created for: " + item2);
			}
			foreach (KeyValuePair<string, ConfigEntry<int>> entry in enemyConfigEntries)
			{
				entry.Value.SettingChanged += delegate(object sender, EventArgs value)
				{
					if (sender is ConfigEntry<int> val2)
					{
						KillableEnemyManager.Instance.SetEnemyHealth(entry.Key, val2.Value);
						Utilities.DebugLog("Saved health value for: " + entry.Key + " to: " + val2.Value);
					}
					else
					{
						Utilities.DebugLog("ERROR: Tried to save config entry but entry = NULL");
					}
				};
			}
			Utilities.DebugLog("Finished creating config entries based on enemies found!");
		}

		public void AddKillThemAllBaseConfigs()
		{
			ConfigEntry<bool> debugLogEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("KillThemAll", "Debug Log", true, " if checked, log from this mod is output in the console");
			ConfigEntry<bool> showHitmarkVfxEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("KillThemAll", "Hit Marker", true, "If enabled, show hitmarker effect when damaging an enemy");
			ConfigEntry<bool> playHitmarkSfxEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("KillThemAll", "Hit Marker Sound Effect", true, "If enabled, play hitmarker sound effect when damaging an enemy");
			ConfigEntry<bool> playerReactionAKSfxEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("KillThemAll", "Player Reaction", true, "If enabled, play random sound effect when you or others kill an enemy (Its random if it plays or not)");
			ConfigEntry<bool> showEnemyDeathEffectEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("KillThemAll", "Enemy Death Effect", true, "If enabled, play enemy death effect");
			ConfigEntry<int> baseKillRewardMultiplierEntry = ((BaseUnityPlugin)this).Config.Bind<int>("KillThemAll", "Base Reward Multiplier", 10, " This value determines the end reward value for a kill, Enemy Health * Base Reward Multiplier = Credit Reward");
			KillableEnemyManager.Instance.debugLog = debugLogEntry.Value;
			KillableEnemyManager.Instance.showHitmarkVfx = showHitmarkVfxEntry.Value;
			KillableEnemyManager.Instance.playHitmarkSfx = playHitmarkSfxEntry.Value;
			KillableEnemyManager.Instance.playerReactionAKSfx = playerReactionAKSfxEntry.Value;
			KillableEnemyManager.Instance.showEnemyDeathEffect = showEnemyDeathEffectEntry.Value;
			KillableEnemyManager.Instance.baseKillRewardMultiplier = baseKillRewardMultiplierEntry.Value;
			debugLogEntry.SettingChanged += delegate
			{
				KillableEnemyManager.Instance.debugLog = debugLogEntry.Value;
			};
			showHitmarkVfxEntry.SettingChanged += delegate
			{
				KillableEnemyManager.Instance.showHitmarkVfx = showHitmarkVfxEntry.Value;
			};
			playHitmarkSfxEntry.SettingChanged += delegate
			{
				KillableEnemyManager.Instance.playHitmarkSfx = playHitmarkSfxEntry.Value;
			};
			playerReactionAKSfxEntry.SettingChanged += delegate
			{
				KillableEnemyManager.Instance.playerReactionAKSfx = playerReactionAKSfxEntry.Value;
			};
			showEnemyDeathEffectEntry.SettingChanged += delegate
			{
				KillableEnemyManager.Instance.showEnemyDeathEffect = showEnemyDeathEffectEntry.Value;
			};
			baseKillRewardMultiplierEntry.SettingChanged += delegate
			{
				KillableEnemyManager.Instance.baseKillRewardMultiplier = baseKillRewardMultiplierEntry.Value;
			};
		}

		public void AddBountyConfigs()
		{
			ConfigEntry<int> chanceToSpawnPerRoundEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Bounty Settings", "Rarity per round", 75, " Chance to spawn a bounty that round, the number is used like a percentage, the higher it is the higher the chances!");
			ConfigEntry<int> chanceToSpawnPerHourEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Bounty Settings", "Rarity per hour", 50, " Chances to spawn a bounty every hour if one has not spawned yet, , the number is used like a percentage, the higher it is the higher the chances!");
			ConfigEntry<int> timeBetweenRetryingBountiesEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Bounty Settings", "Retry per failed bounty", 2, " How many hours should it wait before retrying to spawn a bounty that failed the rarity check, In-game hours.");
			ConfigEntry<int> timeBetweenSuccesfulBountiesEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Bounty Settings", "Time between next bounty", 4, " How many hours should it wait before spawning another bounty if possible, In-game hours.");
			ConfigEntry<int> bountiesPerRoundEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Bounty Settings", "Bounties per round", 2, " How many bounties can spawn per round if they pass the rarity checks");
			ConfigEntry<int> spawnAfterHourEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Bounty Settings", "Spawn after specific hour", 11, " Start spawning bounties after a specific hour, 0 = it will try and spawn from that start of the round, this uses a 24 hour clock.");
			ConfigEntry<int> rewardMultiplierEntry = ((BaseUnityPlugin)this).Config.Bind<int>("Bounty Settings", "Reward Multiplier", 4, " This value determines the end reward value for a bounty kill, (Enemy Health * Base Reward) * Reward Multiplier = Credit Reward");
			BountyManager.Instance.chanceToSpawnPerRound = chanceToSpawnPerRoundEntry.Value;
			BountyManager.Instance.chanceToSpawnPerHour = chanceToSpawnPerHourEntry.Value;
			BountyManager.Instance.timeBetweenRetryingBounties = timeBetweenRetryingBountiesEntry.Value;
			BountyManager.Instance.timeBetweenSuccesfulBounties = timeBetweenSuccesfulBountiesEntry.Value;
			BountyManager.Instance.bountiesPerRound = bountiesPerRoundEntry.Value;
			BountyManager.Instance.spawnAfterHour = spawnAfterHourEntry.Value;
			BountyManager.Instance.rewardMultiplier = rewardMultiplierEntry.Value;
			chanceToSpawnPerRoundEntry.SettingChanged += delegate
			{
				BountyManager.Instance.chanceToSpawnPerRound = chanceToSpawnPerRoundEntry.Value;
				Utilities.DebugLog("BM: chanceToSpawnPerRound to: " + chanceToSpawnPerRoundEntry.Value);
			};
			chanceToSpawnPerHourEntry.SettingChanged += delegate
			{
				BountyManager.Instance.chanceToSpawnPerHour = chanceToSpawnPerHourEntry.Value;
				Utilities.DebugLog("BM: chanceToSpawnPerHourEntry to: " + chanceToSpawnPerHourEntry.Value);
			};
			timeBetweenRetryingBountiesEntry.SettingChanged += delegate
			{
				BountyManager.Instance.timeBetweenRetryingBounties = timeBetweenRetryingBountiesEntry.Value;
				Utilities.DebugLog("BM: timeBetweenRetryingBountiesEntry to: " + timeBetweenRetryingBountiesEntry.Value);
			};
			timeBetweenSuccesfulBountiesEntry.SettingChanged += delegate
			{
				BountyManager.Instance.timeBetweenSuccesfulBounties = timeBetweenSuccesfulBountiesEntry.Value;
				Utilities.DebugLog("BM: timeBetweenSuccesfulBountiesEntry to: " + timeBetweenSuccesfulBountiesEntry.Value);
			};
			bountiesPerRoundEntry.SettingChanged += delegate
			{
				BountyManager.Instance.bountiesPerRound = bountiesPerRoundEntry.Value;
				Utilities.DebugLog("BM: bountiesPerRoundEntry to: " + bountiesPerRoundEntry.Value);
			};
			spawnAfterHourEntry.SettingChanged += delegate
			{
				BountyManager.Instance.spawnAfterHour = spawnAfterHourEntry.Value;
				Utilities.DebugLog("BM: spawnAfterHourEntry to: " + spawnAfterHourEntry.Value);
			};
			rewardMultiplierEntry.SettingChanged += delegate
			{
				BountyManager.Instance.rewardMultiplier = rewardMultiplierEntry.Value;
				Utilities.DebugLog("BM: rewardMultiplierEntry to: " + rewardMultiplierEntry.Value);
			};
		}

		private void LoadAssetBundles()
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			hitMarkAsset = AssetBundle.LoadFromFile(Path.Combine(directoryName, "hitmarkassetbundle"));
			if ((Object)(object)hitMarkAsset == (Object)null)
			{
				Utilities.DebugLog("ERROR: Failed to load hitMarkAsset asset bundles");
				return;
			}
			KillableEnemyManager.Instance.hitmarkHUD = hitMarkAsset.LoadAsset<GameObject>("HitmarkImg");
			if (Object.op_Implicit((Object)(object)KillableEnemyManager.Instance.hitmarkHUD))
			{
				Utilities.DebugLog("Successfully found object in assetbundle ( hitmark HUD obj) " + ((Object)KillableEnemyManager.Instance.hitmarkHUD).name);
			}
			else
			{
				Utilities.DebugLog("ERROR: Not found object in assetbundle ( hitmark HUD obj)");
			}
			hitMarkSfxAsset = AssetBundle.LoadFromFile(Path.Combine(directoryName, "hitmarksfxassetbundle"));
			if ((Object)(object)hitMarkSfxAsset == (Object)null)
			{
				Utilities.DebugLog("ERROR: Failed to load hit mark sfx asset bundles");
				return;
			}
			KillableEnemyManager.Instance.hitmarkSfx = new List<AudioClip>();
			KillableEnemyManager.Instance.hitmarkSfx = hitMarkSfxAsset.LoadAllAssets<AudioClip>().ToList();
			if (Object.op_Implicit((Object)(object)KillableEnemyManager.Instance.hitmarkSfx[0]))
			{
				Utilities.DebugLog("Successfully found object in assetbundle ( sfx hitmark )");
			}
			else
			{
				Utilities.DebugLog("ERROR: Not found object in assetbundle ( sfx hitmark )");
			}
			enemyExplosionEffectAsset = AssetBundle.LoadFromFile(Path.Combine(directoryName, "enemyexplosionassetbundle"));
			if ((Object)(object)enemyExplosionEffectAsset == (Object)null)
			{
				Utilities.DebugLog("ERROR: Failed to load enemyExplosionEffect asset bundles");
				return;
			}
			KillableEnemyManager.Instance.enemyExplosionEffect = enemyExplosionEffectAsset.LoadAsset<GameObject>("EnemyExplosion");
			if (Object.op_Implicit((Object)(object)KillableEnemyManager.Instance.enemyExplosionEffect))
			{
				Utilities.DebugLog("Successfully found object in assetbundle( enemy explosion effect )");
			}
			else
			{
				Utilities.DebugLog("ERROR: Not found object in assetbundle ( enemy explosion effect )");
			}
			playerReactionsSfxAsset = AssetBundle.LoadFromFile(Path.Combine(directoryName, "reactionsfxassetbundle"));
			if ((Object)(object)playerReactionsSfxAsset == (Object)null)
			{
				Utilities.DebugLog("ERROR: Failed to load hit mark sfx asset bundles");
				return;
			}
			KillableEnemyManager.Instance.playerReactionSfx = new List<AudioClip>();
			KillableEnemyManager.Instance.playerReactionSfx = playerReactionsSfxAsset.LoadAllAssets<AudioClip>().ToList();
			if (Object.op_Implicit((Object)(object)KillableEnemyManager.Instance.playerReactionSfx[0]))
			{
				Utilities.DebugLog("Successfully found object in assetbundle ( playerReactionsSfxAsset )");
			}
			else
			{
				Utilities.DebugLog("ERROR: Not found object in assetbundle ( playerReactionsSfxAsset )");
			}
			notificationAsset = AssetBundle.LoadFromFile(Path.Combine(directoryName, "notificationassetbundle"));
			if ((Object)(object)notificationAsset == (Object)null)
			{
				Utilities.DebugLog("ERROR: Failed to load notificationAsset bundles");
				return;
			}
			UIManager.Instance.notificationElementObj = notificationAsset.LoadAllAssets<GameObject>().ToList();
			if (Object.op_Implicit((Object)(object)UIManager.Instance.notificationElementObj[0]))
			{
				Utilities.DebugLog("Successfully found object in assetbundle ( notification element obj) " + ((Object)UIManager.Instance.notificationElementObj[0]).name);
			}
			else
			{
				Utilities.DebugLog("ERROR: Not found object in assetbundle ( notification element obj)");
			}
			if (Object.op_Implicit((Object)(object)UIManager.Instance.notificationElementObj[1]))
			{
				Utilities.DebugLog("Successfully found object in assetbundle ( notification top element obj) " + ((Object)UIManager.Instance.notificationElementObj[1]).name);
			}
			else
			{
				Utilities.DebugLog("ERROR: Not found object in assetbundle ( notification top element obj)");
			}
		}
	}
}
namespace KillThemAll.Network
{
	public class KillableEnemyEmitter : NetworkBehaviour
	{
		[ServerRpc(RequireOwnership = false)]
		public void DoDamageServerRpc(ulong enemyObjectId, ulong playerObjectId, int damage)
		{
			DoDamageClientRpc(enemyObjectId, playerObjectId, damage);
		}

		[ServerRpc(RequireOwnership = false)]
		public void DoKillServerRpc(ulong objectId, ulong playerObjectId)
		{
			DoKillClientRpc(objectId, playerObjectId);
		}

		[ClientRpc]
		public void DoDamageClientRpc(ulong objectId, ulong playerObjectId, int damage)
		{
			KillableEnemyManager.Instance.OnEnemyHit(objectId, playerObjectId, damage);
		}

		[ClientRpc]
		public void DoKillClientRpc(ulong objectId, ulong playerObjectId)
		{
			KillableEnemyManager.Instance.OnEnemyDeath(objectId, playerObjectId);
		}
	}
	internal class UIEmitter : NetworkBehaviour
	{
		[ServerRpc(RequireOwnership = false)]
		public void DoNotificationOnKillServerRpc(string enemyName, string playerThatKilledName, int rewardForKill, bool isBounty, int secondsOnScreen)
		{
			DoNotificationOnKillClientRpc(enemyName, playerThatKilledName, rewardForKill, isBounty, secondsOnScreen);
		}

		[ServerRpc(RequireOwnership = false)]
		public void DoNotificationOnBountyServerRpc(string enemyName, int rewardForKill, int secondsOnScreen)
		{
			DoNotificationOnBountyClientRpc(enemyName, rewardForKill, secondsOnScreen);
		}

		[ClientRpc]
		public void DoNotificationOnKillClientRpc(string enemyName, string playerThatKilledName, int rewardForKill, bool isBounty, int secondsOnScreen)
		{
			UIManager.Instance.ShowEnemyKilledNotfication(enemyName, playerThatKilledName, rewardForKill, isBounty, secondsOnScreen);
		}

		[ClientRpc]
		public void DoNotificationOnBountyClientRpc(string enemyName, int rewardForKill, int secondsOnScreen)
		{
			UIManager.Instance.ShowEnemyBountyNotfication(enemyName, rewardForKill, secondsOnScreen);
		}
	}
}
namespace KillThemAll.Models
{
	public class KillableEnemy : MonoBehaviour
	{
		private int startingHealth = 0;

		private int currentHealth = 0;

		private int reward = 0;

		private bool bounty = false;

		private ulong networkObjectId;

		private EnemyAI enemyAI;

		public EnemyAI EnemyAI
		{
			get
			{
				return enemyAI;
			}
			set
			{
				enemyAI = value;
			}
		}

		public ulong NetworkObjectId
		{
			get
			{
				return networkObjectId;
			}
			set
			{
				networkObjectId = value;
			}
		}

		public int CurrentHealth
		{
			get
			{
				return currentHealth;
			}
			set
			{
				currentHealth = value;
			}
		}

		public int StartingHealth
		{
			get
			{
				return startingHealth;
			}
			set
			{
				startingHealth = value;
			}
		}

		public int Reward
		{
			get
			{
				return reward;
			}
			set
			{
				reward = value;
			}
		}

		public bool isBounty
		{
			get
			{
				return bounty;
			}
			set
			{
				bounty = value;
			}
		}

		public void DoDamage(int amount, ulong playerThatKilled_Id)
		{
			if (currentHealth != 0)
			{
				currentHealth -= amount;
				if (currentHealth < 0)
				{
					currentHealth = 0;
				}
				if (currentHealth == 0 && (((NetworkBehaviour)enemyAI).IsHost || ((NetworkBehaviour)enemyAI).IsServer))
				{
					((Component)StartOfRound.Instance.allPlayerScripts[0]).gameObject.GetComponent<KillableEnemyEmitter>().DoKillServerRpc(((NetworkBehaviour)enemyAI).NetworkObjectId, playerThatKilled_Id);
					DoDeath(playerThatKilled_Id);
				}
				else if (((NetworkBehaviour)enemyAI).IsHost || ((NetworkBehaviour)enemyAI).IsServer)
				{
					((Component)StartOfRound.Instance.allPlayerScripts[0]).gameObject.GetComponent<KillableEnemyEmitter>().DoDamageServerRpc(((NetworkBehaviour)enemyAI).NetworkObjectId, playerThatKilled_Id, amount);
				}
			}
		}

		public void DoDeath(ulong playerThatKilled_Id)
		{
			if (KillableEnemyManager.Instance == null)
			{
				Utilities.DebugLog("ERROR: OnEnemyDeath() => KillableEnemyManager.Instance = NULL");
			}
			if (((NetworkBehaviour)enemyAI).IsHost || ((NetworkBehaviour)enemyAI).IsServer)
			{
				enemyAI.isEnemyDead = true;
				enemyAI.KillEnemy(false);
				BountyManager.Instance.SaveKilledEnemy(Utilities.GetEnemyName(enemyAI), Utilities.GetPlayerClassFromNetID(playerThatKilled_Id).playerUsername, isBounty, reward);
				UIManager.Instance.PrepareOnKillServerRPC_Notification(((NetworkBehaviour)enemyAI).NetworkObjectId, playerThatKilled_Id);
				((MonoBehaviour)this).StartCoroutine(DespawnEnemyOvertime());
			}
		}

		private IEnumerator DespawnEnemyOvertime()
		{
			yield return (object)new WaitForSeconds(0.1f);
			if (Object.op_Implicit((Object)(object)((NetworkBehaviour)enemyAI).NetworkObject))
			{
				((NetworkBehaviour)enemyAI).NetworkObject.Despawn(true);
			}
		}
	}
	public enum EnemyType
	{
		default_
	}
}
namespace KillThemAll.Managers
{
	internal class BountyManager
	{
		public struct EnemyKilled
		{
			public string name;

			public string killerName;

			public bool wasBounty;

			public int reward;
		}

		private const string modGUID = "KillThemAll.BManager";

		private static BountyManager _instance;

		public Terminal __terminal;

		public bool isRoundActive = false;

		public int chanceToSpawnPerRound = 100;

		public int chanceToSpawnPerHour = 100;

		public int timeBetweenRetryingBounties = 1;

		public int timeBetweenSuccesfulBounties = 3;

		public int bountiesPerRound = 1;

		public int spawnAfterHour = 12;

		public int rewardMultiplier = 16;

		public bool isHost = false;

		private int bountiesSpawnedThisRound = 0;

		private int retryAtThisHour = 0;

		private bool shouldSpawnThisRound = false;

		private bool checkedIfItShouldSpawn = false;

		public List<EnemyKilled> enemyKilledList = new List<EnemyKilled>();

		private bool once = false;

		public static BountyManager Instance => _instance ?? (_instance = new BountyManager());

		static BountyManager()
		{
		}

		public void ServerUpdateOnRoundStart()
		{
			if (!checkedIfItShouldSpawn)
			{
				if (CheckIfBountyShouldSpawnThisRound())
				{
					Utilities.DebugLog("Bounty will spawn this round!");
				}
				else
				{
					Utilities.DebugLog("Bounty will not spawn this round!");
				}
				checkedIfItShouldSpawn = true;
			}
			if (!shouldSpawnThisRound || retryAtThisHour >= 24 || bountiesPerRound == 0 || bountiesSpawnedThisRound >= bountiesPerRound || Utilities.GetTimeOfRound() < spawnAfterHour)
			{
				return;
			}
			if (Utilities.GetTimeOfRound() >= retryAtThisHour)
			{
				Utilities.DebugLog("Its time to try again and its: " + Utilities.GetTimeOfRound());
				once = false;
				int num = Random.Range(0, 100);
				Utilities.DebugLog("Chance = " + num + ", need below" + chanceToSpawnPerHour);
				if (num > chanceToSpawnPerHour)
				{
					retryAtThisHour = Utilities.GetTimeOfRound() + timeBetweenRetryingBounties;
					Utilities.DebugLog("Didnt pass rarity check retrying bounty at: " + retryAtThisHour);
				}
				else if (bountiesSpawnedThisRound < bountiesPerRound)
				{
					bountiesSpawnedThisRound++;
					retryAtThisHour = Utilities.GetTimeOfRound() + timeBetweenSuccesfulBounties;
					Utilities.DebugLog("Bounty spawned | count: " + bountiesSpawnedThisRound);
					Utilities.DebugLog("Next spawn try at: " + retryAtThisHour);
					OnSpawnBounty();
				}
			}
			else if (!once)
			{
				Utilities.DebugLog("Need to wait till " + retryAtThisHour + ", and its: " + Utilities.GetTimeOfRound());
				once = true;
			}
		}

		public void ServerUpdateOnRoundEnd()
		{
			once = false;
			checkedIfItShouldSpawn = false;
			shouldSpawnThisRound = false;
			bountiesSpawnedThisRound = 0;
			retryAtThisHour = 0;
			enemyKilledList.Clear();
			Utilities.DebugLog("ServerUpdateOnRoundEnd: resetting values");
		}

		public bool CheckIfBountyShouldSpawnThisRound()
		{
			int num = Random.Range(0, 100);
			return shouldSpawnThisRound = num <= chanceToSpawnPerRound;
		}

		public void OnSpawnBounty()
		{
			int reward = 0;
			string enemyName = SpawnEnemyManager.Instance.SpawnRandomEnemy(out reward);
			UIManager.Instance.PrepareOnBountyServerRPC_Notification(enemyName, reward);
		}

		public void SaveKilledEnemy(string name, string player, bool wasBounty, int reward)
		{
			EnemyKilled item = default(EnemyKilled);
			item.name = name;
			item.killerName = player;
			item.wasBounty = wasBounty;
			item.reward = reward;
			Utilities.DebugLog("Added killed enemy: " + item.name + " that died by: " + item.killerName + " for " + item.reward + (item.wasBounty ? " and was a bounty" : " and was not a bounty"));
			enemyKilledList.Add(item);
			GiveCreditsToCrew(reward);
		}

		private void GiveCreditsToCrew(int reward)
		{
			if (!Object.op_Implicit((Object)(object)__terminal))
			{
				Utilities.DebugLog("ERROR: Reference to terminal is null! Cant give credits");
				return;
			}
			Terminal _terminal = __terminal;
			_terminal.groupCredits += reward;
			__terminal.SyncGroupCreditsServerRpc(__terminal.groupCredits, __terminal.numberOfItemsInDropship);
		}
	}
	internal class KillableEnemyManager
	{
		private const string modGUID = "KillThemAll.KEManager";

		private static KillableEnemyManager _instance;

		public Dictionary<string, int> enemyHealthDictionary = new Dictionary<string, int>();

		public PlayerControllerB localPlayer;

		public bool debugLog = true;

		public bool showHitmarkVfx = true;

		public bool playHitmarkSfx = true;

		public bool showEnemyDeathEffect = true;

		public bool playerReactionAKSfx = true;

		public int baseKillRewardMultiplier = 10;

		public Animator playerHitmarkAnimator;

		private AudioSource playerAudioSource;

		public GameObject hitmarkHUD;

		public List<AudioClip> hitmarkSfx;

		public GameObject enemyExplosionEffect;

		public List<AudioClip> playerReactionSfx;

		private GameObject hitMarkerHud;

		public static KillableEnemyManager Instance => _instance ?? (_instance = new KillableEnemyManager());

		public Dictionary<ulong, EnemyAI> NetworkObjectIDToEnemyAI { get; } = new Dictionary<ulong, EnemyAI>();


		public Dictionary<EnemyAI, ulong> EnemyAIToNetworkObjectID { get; } = new Dictionary<EnemyAI, ulong>();


		static KillableEnemyManager()
		{
		}

		public void SetEnemyHealth(string enemyName, int newHealth)
		{
			if (enemyHealthDictionary.ContainsKey(enemyName))
			{
				enemyHealthDictionary[enemyName] = newHealth;
			}
		}

		public void SetupHitmarkerHUD(PlayerControllerB __instance)
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)__instance) || Object.op_Implicit((Object)(object)hitMarkerHud))
			{
				return;
			}
			localPlayer = __instance;
			Transform transform = GameObject.Find("Systems/UI/Canvas/PlayerCursor/Cursor").transform;
			if (!Object.op_Implicit((Object)(object)transform))
			{
				Utilities.DebugLog("ERROR: SetupHitmarkerHUD() => parentCanvas = NULL");
				return;
			}
			hitMarkerHud = Object.Instantiate<GameObject>(hitmarkHUD, transform.parent, false);
			if (!Object.op_Implicit((Object)(object)hitMarkerHud))
			{
				Utilities.DebugLog("ERROR: SetupHitmarkerHUD() => hitMarkerHudObject = NULL");
				return;
			}
			hitMarkerHud.SetActive(true);
			hitMarkerHud.transform.localScale = new Vector3(1f, 1f, 1f);
			playerHitmarkAnimator = hitMarkerHud.GetComponent<Animator>();
			if (!Object.op_Implicit((Object)(object)playerHitmarkAnimator))
			{
				Utilities.DebugLog("ERROR: SetupHitmarkerHUD() => playerHitmarkAnimator = NULL");
				return;
			}
			playerHitmarkAnimator.speed = 1.9f;
			Utilities.DebugLog("HUD Instantiated for local player: " + localPlayer.playerUsername);
		}

		public KillableEnemy AssignKillableClassToEnemy(EnemyAI __instance)
		{
			KillableEnemy component = ((Component)__instance).gameObject.GetComponent<KillableEnemy>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return component;
			}
			int num = 10000;
			string name = ((Object)__instance).name;
			name = name.Replace("Enemy", "");
			name = name.Replace("(Clone)", "");
			name = name.Replace(".prefab", "");
			double num2 = 0.0;
			string text = "null";
			if (enemyHealthDictionary.Count == 0)
			{
				Utilities.DebugLog("enemyHealthDictionary is empty");
			}
			foreach (KeyValuePair<string, int> item in enemyHealthDictionary)
			{
				double num3 = Utilities.SimilarityRatio(name, item.Key);
				if (num3 > num2)
				{
					num2 = num3;
					if (item.Value > 0)
					{
						num = item.Value;
					}
					text = item.Key;
					Utilities.DebugLog("Comparing name: " + name + ", against: " + item.Key + " | Similarity = " + num3);
				}
			}
			if (text == "null")
			{
				Utilities.DebugLog("Not found similar name for: " + name + "!!!");
				return null;
			}
			KillableEnemy killableEnemy = InitializeKillableData(__instance);
			killableEnemy.StartingHealth = num;
			killableEnemy.CurrentHealth = num;
			killableEnemy.Reward = num * baseKillRewardMultiplier;
			killableEnemy.EnemyAI = __instance;
			killableEnemy.NetworkObjectId = ((NetworkBehaviour)__instance).NetworkObjectId;
			Utilities.DebugLog("Registering enemy: " + ((Object)((Component)__instance).gameObject).name + ", new HP: " + num);
			return killableEnemy;
		}

		private KillableEnemy InitializeKillableData(EnemyAI enemyAI)
		{
			EnemyAIToNetworkObjectID[enemyAI] = ((NetworkBehaviour)enemyAI).NetworkObjectId;
			NetworkObjectIDToEnemyAI[((NetworkBehaviour)enemyAI).NetworkObjectId] = enemyAI;
			return ((Component)enemyAI).gameObject.AddComponent<KillableEnemy>();
		}

		public void OnEnemyHitPrepareServerRPC(ulong enemyHit_Id, ulong playerThatHit_Id, int damageHit)
		{
			EnemyAI enemyAIClassFromNetID = Utilities.GetEnemyAIClassFromNetID(enemyHit_Id);
			if (Object.op_Implicit((Object)(object)enemyAIClassFromNetID))
			{
				KillableEnemy component = ((Component)enemyAIClassFromNetID).gameObject.GetComponent<KillableEnemy>();
				if ((Object)(object)component != (Object)null)
				{
					((Component)enemyAIClassFromNetID).gameObject.GetComponent<KillableEnemy>().DoDamage(damageHit, playerThatHit_Id);
				}
			}
		}

		public void OnEnemyHit(ulong enemyHit_Id, ulong playerThatHit_Id, int damageHit)
		{
			EnemyAI enemyAIClassFromNetID = Utilities.GetEnemyAIClassFromNetID(enemyHit_Id);
			PlayerControllerB playerClassFromNetID = Utilities.GetPlayerClassFromNetID(playerThatHit_Id);
			if (!Object.op_Implicit((Object)(object)enemyAIClassFromNetID))
			{
				Utilities.DebugLog("ERROR: OnEnemyHit() => enemyAI = NULL");
				return;
			}
			if (!Object.op_Implicit((Object)(object)playerClassFromNetID))
			{
				Utilities.DebugLog("ERROR: OnEnemyHit() => playerThatHit = NULL");
				return;
			}
			Utilities.DebugLog("OnEnemyHit: " + ((Object)enemyAIClassFromNetID).name + " hit for " + damageHit + " damage! by: " + playerClassFromNetID.playerUsername);
		}

		public void OnEnemyDeath(ulong enemyKilled_Id, ulong playerThatKilled_Id)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			EnemyAI enemyAIClassFromNetID = Utilities.GetEnemyAIClassFromNetID(enemyKilled_Id);
			PlayerControllerB playerClassFromNetID = Utilities.GetPlayerClassFromNetID(playerThatKilled_Id);
			if (!Object.op_Implicit((Object)(object)enemyAIClassFromNetID))
			{
				Utilities.DebugLog("ERROR: OnEnemyDeath() => enemyAI = NULL");
				return;
			}
			if (!Object.op_Implicit((Object)(object)playerClassFromNetID))
			{
				Utilities.DebugLog("ERROR: OnEnemyDeath() => playerThatKilled = NULL");
				return;
			}
			if (Object.op_Implicit((Object)(object)enemyAIClassFromNetID.creatureSFX))
			{
				enemyAIClassFromNetID.creatureSFX.Stop();
			}
			if (Object.op_Implicit((Object)(object)enemyAIClassFromNetID.creatureVoice))
			{
				enemyAIClassFromNetID.creatureVoice.Stop();
			}
			if (showEnemyDeathEffect)
			{
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(((Component)enemyAIClassFromNetID).transform.position.x, ((Component)enemyAIClassFromNetID).transform.position.y + 2f, ((Component)enemyAIClassFromNetID).transform.position.z);
				GameObject val2 = Object.Instantiate<GameObject>(enemyExplosionEffect, val, enemyExplosionEffect.transform.rotation);
				val2.AddComponent<VfxDespawn>();
			}
			PlayReactionAfterKillLocal(playerClassFromNetID);
			Utilities.DebugLog("OnEnemyDeath: " + ((Object)enemyAIClassFromNetID).name + " Killed by " + playerClassFromNetID.playerUsername);
		}

		public void PlayHitmarkerLocal(PlayerControllerB playerController)
		{
			if (playHitmarkSfx)
			{
				if (!Object.op_Implicit((Object)(object)hitmarkSfx[0]))
				{
					Utilities.DebugLog("ERROR: PlayHitmarkerLocal() => hitmarkSfx[0] = NULL");
					return;
				}
				if (!Object.op_Implicit((Object)(object)playerAudioSource))
				{
					if (!Object.op_Implicit((Object)(object)playerController.movementAudio))
					{
						Utilities.DebugLog("ERROR: PlayHitmarkerLocal() => playerController.movementAudio = NULL");
						return;
					}
					playerAudioSource = playerController.movementAudio;
				}
				playerAudioSource.PlayOneShot(hitmarkSfx[0], 3f);
				Utilities.DebugLog("Play Hitmark sound effect on local client");
			}
			if (showHitmarkVfx)
			{
				if (!Object.op_Implicit((Object)(object)playerHitmarkAnimator))
				{
					Utilities.DebugLog("ERROR: PlayHitmarkerLocal() => playerHitmarkAnimator = NULL");
					return;
				}
				playerHitmarkAnimator.Play("HitmarkAnim", 0, 0f);
				Utilities.DebugLog("Play Hitmark effect on local client");
			}
		}

		public void PlayReactionAfterKillLocal(PlayerControllerB playerController)
		{
			if (playerReactionAKSfx)
			{
				if (!Object.op_Implicit((Object)(object)playerController))
				{
					Utilities.DebugLog("ERROR: PlayReactionAfterKillLocal() => playerController = NULL");
					return;
				}
				if (!Object.op_Implicit((Object)(object)playerReactionSfx[0]))
				{
					Utilities.DebugLog("ERROR: PlayReactionAfterKillLocal() => playerReactionSfx[0] = NULL");
					return;
				}
				if (!Object.op_Implicit((Object)(object)playerController.movementAudio))
				{
					Utilities.DebugLog("ERROR: PlayReactionAfterKillLocal() => playerController.movementAudio = NULL");
					return;
				}
				playerController.movementAudio.PlayOneShot(playerReactionSfx[0], 1f);
				Utilities.DebugLog("Play player reaction for killing an enemy: " + playerController.playerUsername);
			}
		}
	}
	internal class SpawnEnemyManager
	{
		public struct Enemy
		{
			public string name;

			public GameObject prefab;

			public bool isOutside;
		}

		private const string modGUID = "KillThemAll.SManager";

		private static SpawnEnemyManager _instance;

		public static List<Enemy> listOfSpawnableEnemies;

		public static SpawnEnemyManager Instance => _instance ?? (_instance = new SpawnEnemyManager());

		static SpawnEnemyManager()
		{
			listOfSpawnableEnemies = new List<Enemy>();
		}

		public string SpawnRandomEnemy(out int reward)
		{
			Enemy enemy = listOfSpawnableEnemies[Random.Range(0, listOfSpawnableEnemies.Count)];
			reward = SpawnEnemy(enemy);
			return enemy.name;
		}

		private int SpawnEnemy(Enemy enemy)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			Vector3 zero = Vector3.zero;
			zero = ((!enemy.isOutside) ? RoundManager.Instance.allEnemyVents[Random.Range(0, RoundManager.Instance.allEnemyVents.Length)].floorNode.position : RoundManager.Instance.outsideAINodes[Random.Range(0, RoundManager.Instance.outsideAINodes.Length)].transform.position);
			if (!Object.op_Implicit((Object)(object)enemy.prefab))
			{
				Utilities.DebugLog("enemy.prefab null");
			}
			GameObject val = Object.Instantiate<GameObject>(enemy.prefab, zero, Quaternion.identity);
			val.GetComponentInChildren<NetworkObject>().Spawn(true);
			if (!Object.op_Implicit((Object)(object)val.GetComponent<KillableEnemy>()))
			{
				if (Object.op_Implicit((Object)(object)val.GetComponent<EnemyAI>()))
				{
					Utilities.DebugLog("ERROR: Cant find EnemyAI Class on " + ((Object)val).name);
				}
				EnemyAI component = val.GetComponent<EnemyAI>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					Utilities.DebugLog("ERROR: Cant find EnemyAI Class on " + ((Object)val).name);
					return 0;
				}
				KillableEnemy killableEnemy = KillableEnemyManager.Instance.AssignKillableClassToEnemy(component);
				killableEnemy.isBounty = true;
				killableEnemy.Reward = killableEnemy.StartingHealth * KillableEnemyManager.Instance.baseKillRewardMultiplier * BountyManager.Instance.rewardMultiplier;
				Utilities.DebugLog("(had to attach KE class) spawned bounty: " + ((Object)val).name + ", reward: " + killableEnemy.Reward);
				return killableEnemy.Reward;
			}
			KillableEnemy component2 = val.GetComponent<KillableEnemy>();
			component2.isBounty = true;
			component2.Reward = component2.StartingHealth * KillableEnemyManager.Instance.baseKillRewardMultiplier * BountyManager.Instance.rewardMultiplier;
			Utilities.DebugLog("(class already attached) spawned bounty: " + ((Object)val).name + ", reward: " + component2.Reward);
			return component2.Reward;
		}
	}
	internal class UIManager
	{
		private const string modGUID = "KillThemAll.UIManager";

		private static UIManager _instance;

		public List<GameObject> notificationElementObj;

		private Transform topNotificationParent;

		private Transform sideNotificationParent;

		public static UIManager Instance => _instance ?? (_instance = new UIManager());

		static UIManager()
		{
		}

		public void PrepareOnKillServerRPC_Notification(ulong objectKilled_Id, ulong playerThatKilled_Id)
		{
			Utilities.DebugLog("Preparing server rpc call for notification");
			KillableEnemy component = ((Component)GeneralExtensions.GetValueSafe<ulong, EnemyAI>(KillableEnemyManager.Instance.NetworkObjectIDToEnemyAI, objectKilled_Id)).gameObject.GetComponent<KillableEnemy>();
			string name = ((Object)((Component)component).gameObject).name;
			string playerUsername = Utilities.GetPlayerClassFromNetID(playerThatKilled_Id).playerUsername;
			name = name.Replace("Enemy", "");
			name = name.Replace("(Clone)", "");
			name = name.Replace(".prefab", "");
			((Component)StartOfRound.Instance.allPlayerScripts[0]).GetComponent<UIEmitter>().DoNotificationOnKillServerRpc(name, playerUsername, component.Reward, component.isBounty, component.isBounty ? 6 : 4);
		}

		public void PrepareOnBountyServerRPC_Notification(string enemyName, int rewardAmount)
		{
			Utilities.DebugLog("Preparing server rpc call for bounty notification");
			((Component)StartOfRound.Instance.allPlayerScripts[0]).GetComponent<UIEmitter>().DoNotificationOnBountyServerRpc(enemyName, rewardAmount, 8);
		}

		public void Initialise()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Expected O, but got Unknown
			//IL_016f: 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)
			if (!Object.op_Implicit((Object)(object)sideNotificationParent))
			{
				GameObject val = new GameObject("SideNotificationParent");
				val.transform.SetParent(GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD/TopLeftCorner/Self").transform, false);
				VerticalLayoutGroup val2 = val.AddComponent<VerticalLayoutGroup>();
				((Component)val2).transform.localPosition = new Vector3(-30f, -75f, 0f);
				((Component)val2).transform.localScale = new Vector3(-0.2f, 0.2f, -0.2f);
				((HorizontalOrVerticalLayoutGroup)val2).spacing = 15f;
				((LayoutGroup)val2).childAlignment = (TextAnchor)4;
				((HorizontalOrVerticalLayoutGroup)val2).reverseArrangement = true;
				((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = false;
				((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = false;
				((HorizontalOrVerticalLayoutGroup)val2).childForceExpandHeight = false;
				((HorizontalOrVerticalLayoutGroup)val2).childForceExpandWidth = false;
				sideNotificationParent = val.transform;
				Utilities.DebugLog("sideNotificationParent added " + ((Object)sideNotificationParent).name + ", its parent is " + ((Object)((Component)sideNotificationParent).transform.parent).name);
			}
			if (!Object.op_Implicit((Object)(object)topNotificationParent))
			{
				GameObject val3 = new GameObject("topNotificationParent");
				Transform parent = ((Component)HUDManager.Instance.Inventory.canvasGroup).transform.parent;
				val3.transform.SetParent(parent, false);
				VerticalLayoutGroup val4 = val3.AddComponent<VerticalLayoutGroup>();
				((Component)val4).transform.localPosition = new Vector3(0f, 150f, 0f);
				((Component)val4).transform.localScale = new Vector3(0.3f, 0.3f, 0.3f);
				((HorizontalOrVerticalLayoutGroup)val4).spacing = 15f;
				((LayoutGroup)val4).childAlignment = (TextAnchor)4;
				((HorizontalOrVerticalLayoutGroup)val4).reverseArrangement = true;
				((HorizontalOrVerticalLayoutGroup)val4).childControlWidth = false;
				((HorizontalOrVerticalLayoutGroup)val4).childControlHeight = false;
				((HorizontalOrVerticalLayoutGroup)val4).childForceExpandHeight = false;
				((HorizontalOrVerticalLayoutGroup)val4).childForceExpandWidth = false;
				topNotificationParent = val3.transform;
				Utilities.DebugLog("topNotificationParent added " + ((Object)topNotificationParent).name + ", its parent is " + ((Object)((Component)topNotificationParent).transform.parent).name);
			}
		}

		public void ShowEnemyKilledNotfication(string enemyName, string playerThatKilledName, int rewardForKill, bool isBounty, int secondsOnScreen)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)sideNotificationParent))
			{
				Utilities.DebugLog("ERROR: UIManager() => sideNotificationParent = NULL");
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(notificationElementObj[0], sideNotificationParent, false);
			if (!Object.op_Implicit((Object)(object)val))
			{
				Utilities.DebugLog("ERROR: UIManager() => notificationElement = NULL");
				return;
			}
			val.SetActive(true);
			val.transform.localPosition = new Vector3(0f, 0f, 0f);
			if (!isBounty)
			{
				((Component)val.transform.GetChild(0)).gameObject.SetActive(false);
				((Component)val.transform.GetChild(1)).GetComponent<TMP_Text>().fontSize = 50f;
				((Component)val.transform.GetChild(2)).GetComponent<TMP_Text>().fontSize = 50f;
				((Component)val.transform.GetChild(1)).GetComponent<TMP_Text>().text = playerThatKilledName + " killed " + enemyName;
				((Component)val.transform.GetChild(2)).GetComponent<TMP_Text>().text = "Gained " + rewardForKill + " Credits!";
				((Component)val.transform.GetChild(1)).gameObject.SetActive(true);
				((Component)val.transform.GetChild(2)).gameObject.SetActive(true);
			}
			else
			{
				((Component)val.transform.GetChild(0)).GetComponent<TMP_Text>().fontSize = 55f;
				((Component)val.transform.GetChild(1)).GetComponent<TMP_Text>().fontSize = 45f;
				((Component)val.transform.GetChild(2)).GetComponent<TMP_Text>().fontSize = 38f;
				((Component)val.transform.GetChild(0)).GetComponent<TMP_Text>().text = "BOUNTY " + enemyName.ToUpper() + " KILLED";
				((Component)val.transform.GetChild(1)).GetComponent<TMP_Text>().text = playerThatKilledName + " gained " + rewardForKill + "!";
				((Component)val.transform.GetChild(2)).GetComponent<TMP_Text>().text = "The Company is in your debt";
				((Component)val.transform.GetChild(0)).gameObject.SetActive(true);
				((Component)val.transform.GetChild(1)).gameObject.SetActive(true);
				((Component)val.transform.GetChild(2)).gameObject.SetActive(true);
			}
			Animator component = val.GetComponent<Animator>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				Utilities.DebugLog("ERROR: UIManager() => notificationElementAnimator = NULL");
			}
			else
			{
				val.AddComponent<ElementDespawn>().StartTimer(secondsOnScreen, component);
			}
		}

		public void ShowEnemyBountyNotfication(string enemyName, int rewardForKill, int secondsOnScreen)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)topNotificationParent))
			{
				Utilities.DebugLog("ERROR: UIManager() => topNotificationParent = NULL");
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(notificationElementObj[1], topNotificationParent, false);
			if (!Object.op_Implicit((Object)(object)val))
			{
				Utilities.DebugLog("ERROR: UIManager() => notificationElement = NULL");
				return;
			}
			val.SetActive(true);
			val.transform.localPosition = new Vector3(0f, 0f, 0f);
			((Component)val.transform.GetChild(0)).GetComponent<TMP_Text>().fontSize = 80f;
			((Component)val.transform.GetChild(1)).GetComponent<TMP_Text>().fontSize = 50f;
			((Component)val.transform.GetChild(2)).GetComponent<TMP_Text>().fontSize = 50f;
			((Component)val.transform.GetChild(0)).GetComponent<TMP_Text>().text = "bounty Has Awoken".ToUpper();
			((Component)val.transform.GetChild(1)).GetComponent<TMP_Text>().text = "Find and kill " + enemyName;
			((Component)val.transform.GetChild(2)).GetComponent<TMP_Text>().text = "The Company will reward with " + rewardForKill + " Credits!";
			((Component)val.transform.GetChild(0)).gameObject.SetActive(true);
			((Component)val.transform.GetChild(1)).gameObject.SetActive(true);
			((Component)val.transform.GetChild(2)).gameObject.SetActive(true);
			Animator component = val.GetComponent<Animator>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				Utilities.DebugLog("ERROR: UIManager() => notificationElementAnimator = NULL");
			}
			else
			{
				val.AddComponent<ElementDespawn>().StartTimer(secondsOnScreen, component);
			}
		}
	}
}
namespace KillThemAll.Hooks
{
	internal class UnityHook
	{
		private const string modGUID = "KillThemAll.Unity";

		static UnityHook()
		{
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(NetworkManager), "DespawnObject")]
		private static void PrefixDespawn(NetworkSpawnManager __instance, NetworkObject networkObject, bool destroyObject)
		{
			if (Object.op_Implicit((Object)(object)networkObject))
			{
				EnemyAI component = ((Component)networkObject).GetComponent<EnemyAI>();
				if ((Object)(object)component != (Object)null)
				{
					KillableEnemyManager.Instance.EnemyAIToNetworkObjectID.Remove(component);
					KillableEnemyManager.Instance.NetworkObjectIDToEnemyAI.Remove(((NetworkBehaviour)component).NetworkObjectId);
					Utilities.DebugLog("Removed " + ((Object)component).name + "'s network object");
				}
			}
		}
	}
	internal class VanillaHook
	{
		private const string modGUID = "KillThemAll.Vanilla";

		static VanillaHook()
		{
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "Start")]
		private static void GameNetworkManagerPostStart(GameNetworkManager __instance)
		{
			KillThemAll.instance.Initialise();
		}

		[HarmonyPatch(typeof(RoundManager), "Start")]
		[HarmonyPrefix]
		private static void GetHost()
		{
			Utilities.isHost = ((NetworkBehaviour)RoundManager.Instance).NetworkManager.IsHost;
			Utilities.DebugLog("RoundManager start=> Round Started");
		}

		[HarmonyPatch(typeof(RoundManager), "Update")]
		[HarmonyPrefix]
		private static void OnRoundManagerUpdate()
		{
			if (Object.op_Implicit((Object)(object)StartOfRound.Instance) && Utilities.isHost && RoundManager.Instance.isSpawningEnemies && !StartOfRound.Instance.shipIsLeaving)
			{
				BountyManager.Instance.ServerUpdateOnRoundStart();
			}
		}

		[HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")]
		[HarmonyPrefix]
		private static void OnRoundManagerEnd()
		{
			if (Object.op_Implicit((Object)(object)StartOfRound.Instance) && Utilities.isHost)
			{
				BountyManager.Instance.ServerUpdateOnRoundEnd();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
		private static void PostfixStartPlayer(PlayerControllerB __instance)
		{
			if (Utilities.IsLocalPlayer(__instance))
			{
				KillableEnemyManager.Instance.SetupHitmarkerHUD(__instance);
				UIManager.Instance.Initialise();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(EnemyAI), "Start")]
		private static void PostfixStartEnemy(EnemyAI __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance) && Utilities.isHost && !Object.op_Implicit((Object)(object)((Component)__instance).gameObject.GetComponent<KillableEnemy>()))
			{
				KillableEnemyManager.Instance.AssignKillableClassToEnemy(__instance);
				Utilities.DebugLog("Assigned values on host?: " + Utilities.isHost);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(EnemyAI), "Update")]
		private static void PostfixUpdateEnemy(EnemyAI __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance) && Utilities.isHost && !Object.op_Implicit((Object)(object)((Component)__instance).gameObject.GetComponent<KillableEnemy>()))
			{
				KillableEnemyManager.Instance.AssignKillableClassToEnemy(__instance);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(EnemyAI), "HitEnemy")]
		private static void HitPostfix(EnemyAI __instance, int force = 1, PlayerControllerB playerWhoHit = null, bool playHitSFX = false)
		{
			if (Object.op_Implicit((Object)(object)playerWhoHit))
			{
				if (Utilities.IsLocalPlayer(playerWhoHit))
				{
					KillableEnemyManager.Instance.PlayHitmarkerLocal(playerWhoHit);
				}
				if (Utilities.isHost)
				{
					Utilities.DebugLog("Server hit prepare sRPC ");
					KillableEnemyManager.Instance.OnEnemyHitPrepareServerRPC(((NetworkBehaviour)__instance).NetworkObjectId, ((NetworkBehaviour)playerWhoHit).NetworkObjectId, force);
				}
			}
		}

		[HarmonyPatch(typeof(Terminal), "Start")]
		[HarmonyPostfix]
		private static void GetAllEnemies(ref SelectableLevel[] ___moonsCatalogueList, Terminal __instance)
		{
			SelectableLevel[] array = ___moonsCatalogueList;
			SpawnEnemyManager.Enemy item = default(SpawnEnemyManager.Enemy);
			SelectableLevel[] array2 = array;
			foreach (SelectableLevel level in array2)
			{
				int e;
				for (e = 0; e < level.Enemies.Count; e++)
				{
					if (!SpawnEnemyManager.listOfSpawnableEnemies.Any((SpawnEnemyManager.Enemy x) => x.name == level.Enemies[e].enemyType.enemyName) && !(level.Enemies[e].enemyType.enemyName == "Lasso"))
					{
						item.name = level.Enemies[e].enemyType.enemyName;
						item.prefab = level.Enemies[e].enemyType.enemyPrefab;
						item.isOutside = level.Enemies[e].enemyType.isOutsideEnemy;
						Utilities.DebugLog("Terminal start=> Enemy Found: " + item.name);
						SpawnEnemyManager.listOfSpawnableEnemies.Add(item);
					}
				}
				int i;
				for (i = 0; i < level.OutsideEnemies.Count; i++)
				{
					if (!SpawnEnemyManager.listOfSpawnableEnemies.Any((SpawnEnemyManager.Enemy x) => x.name == level.OutsideEnemies[i].enemyType.enemyName) && !(level.Enemies[i].enemyType.enemyName == "Lasso"))
					{
						item.name = level.OutsideEnemies[i].enemyType.enemyName;
						item.prefab = level.OutsideEnemies[i].enemyType.enemyPrefab;
						item.isOutside = level.OutsideEnemies[i].enemyType.isOutsideEnemy;
						Utilities.DebugLog("Terminal start=> Enemy Found: " + item.name);
						SpawnEnemyManager.listOfSpawnableEnemies.Add(item);
					}
				}
			}
			BountyManager.Instance.__terminal = __instance;
			Utilities.DebugLog("server BountyManager.Instance.__terminal " + (object)BountyManager.Instance.__terminal);
		}
	}
}
namespace KillThemAll.Extras
{
	internal class ElementDespawn : MonoBehaviour
	{
		private float waittimer = 3f;

		private Animator animator;

		private bool isPlayingEnd = false;

		public void StartTimer(float time, Animator animator)
		{
			Utilities.DebugLog("StartTimer for despawn ui " + ((Object)this).name);
			waittimer = time;
			this.animator = animator;
		}

		private void Update()
		{
			waittimer -= Time.deltaTime;
			if (waittimer <= 0f && !isPlayingEnd)
			{
				animator.Play("NotificationEnd", 0);
				isPlayingEnd = true;
				waittimer = 1f;
			}
			else if (isPlayingEnd && waittimer <= 0f)
			{
				Utilities.DebugLog("Destroying notificationElement");
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
	internal class Utilities
	{
		public static bool isHost;

		private static ManualLogSource mls;

		private const string modGUID = "KillThemAll";

		public static void SetupLog()
		{
			mls = Logger.CreateLogSource("KillThemAll");
		}

		public static void DebugLog(string log)
		{
			if (KillableEnemyManager.Instance.debugLog)
			{
				mls.LogInfo((object)("--KillThemAll | " + log));
			}
		}

		public static bool IsLocalPlayer(PlayerControllerB playerControllerClass)
		{
			return (Object)(object)StartOfRound.Instance.localPlayerController == (Object)(object)playerControllerClass;
		}

		internal static void DebugLog(object p)
		{
			throw new NotImplementedException();
		}

		public static PlayerControllerB GetPlayerClassFromNetID(ulong clientID)
		{
			if (clientID < 0 || !Object.op_Implicit((Object)(object)NetworkManager.Singleton) || !Object.op_Implicit((Object)(object)((Component)NetworkManager.Singleton.SpawnManager.SpawnedObjects[clientID]).gameObject))
			{
				return null;
			}
			return ((Component)NetworkManager.Singleton.SpawnManager.SpawnedObjects[clientID]).gameObject.GetComponent<PlayerControllerB>();
		}

		public static EnemyAI GetEnemyAIClassFromNetID(ulong enemyID)
		{
			if (enemyID < 0 || !Object.op_Implicit((Object)(object)NetworkManager.Singleton) || !Object.op_Implicit((Object)(object)((Component)NetworkManager.Singleton.SpawnManager.SpawnedObjects[enemyID]).gameObject))
			{
				return null;
			}
			return ((Component)NetworkManager.Singleton.SpawnManager.SpawnedObjects[enemyID]).gameObject.GetComponent<EnemyAI>();
		}

		public static string GetEnemyName(ulong enemyID)
		{
			if (enemyID < 0 || !Object.op_Implicit((Object)(object)NetworkManager.Singleton) || !Object.op_Implicit((Object)(object)((Component)NetworkManager.Singleton.SpawnManager.SpawnedObjects[enemyID]).gameObject))
			{
				return null;
			}
			EnemyAI component = ((Component)NetworkManager.Singleton.SpawnManager.SpawnedObjects[enemyID]).gameObject.GetComponent<EnemyAI>();
			string name = ((Object)component).name;
			name = name.Replace("Enemy", "");
			name = name.Replace("(Clone)", "");
			return name.Replace(".prefab", "");
		}

		public static string GetEnemyName(EnemyAI enemyClass)
		{
			string name = ((Object)enemyClass).name;
			name = name.Replace("Enemy", "");
			name = name.Replace("(Clone)", "");
			return name.Replace(".prefab", "");
		}

		public static double SimilarityRatio(string str1, string str2)
		{
			int num = LevenshteinDistance(str1, str2);
			int num2 = Math.Max(str1.Length, str2.Length);
			return 1.0 - (double)num / (double)num2;
		}

		public static int LevenshteinDistance(string str1, string str2)
		{
			int[,] array = new int[str1.Length + 1, str2.Length + 1];
			for (int i = 0; i <= str1.Length; i++)
			{
				for (int j = 0; j <= str2.Length; j++)
				{
					if (i == 0)
					{
						array[i, j] = j;
						continue;
					}
					if (j == 0)
					{
						array[i, j] = i;
						continue;
					}
					int num = ((str1[i - 1] != str2[j - 1]) ? 1 : 0);
					array[i, j] = Math.Min(array[i - 1, j] + 1, Math.Min(array[i, j - 1] + 1, array[i - 1, j - 1] + num));
				}
			}
			return array[str1.Length, str2.Length];
		}

		public static int GetTimeOfRound()
		{
			int num = (int)(TimeOfDay.Instance.normalizedTimeOfDay * (60f * (float)TimeOfDay.Instance.numberOfHours)) + 360;
			return (int)Mathf.Floor((float)(num / 60));
		}
	}
	public class VfxDespawn : MonoBehaviour
	{
		private float waittimer = 3f;

		private void Start()
		{
			waittimer = 3f;
		}

		private void Update()
		{
			waittimer -= Time.deltaTime;
			if (waittimer <= 0f)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
}