Decompiled source of RoR2BaseDefense v2.5.1

RoR2BaseDefense.dll

Decompiled a week ago
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.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using KinematicCharacterController;
using Microsoft.CodeAnalysis;
using On.RoR2;
using On.RoR2.UI;
using R2API.Networking;
using R2API.Networking.Interfaces;
using R2API.Utils;
using RoR2;
using RoR2.CharacterAI;
using RoR2.Navigation;
using RoR2.Orbs;
using RoR2.Projectile;
using RoR2.UI;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RoR2BaseDefense")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RoR2BaseDefense")]
[assembly: AssemblyTitle("RoR2BaseDefense")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, 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(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RoR2BaseDefense
{
	public enum EnemyArchetype
	{
		Swarm,
		Titan,
		Demolition,
		Basic,
		Destroyer
	}
	public enum WaveMutatorType
	{
		None,
		AerialAssault,
		EliteVanguard,
		Siege
	}
	public class PlayerMatchStats
	{
		public int Kills;

		public float DamageDealt;

		public int StructuresBuilt;

		public int StructuresDemolished;

		public int TotalMoneyEarned;

		public int DeathsCount;
	}
	public class WaveEnemyMarker : MonoBehaviour
	{
		public EnemyArchetype Archetype;

		private BaseAI ai;

		private CharacterMaster master;

		private float retargetTimer;

		private bool basicTargetCoreAssigned;

		private bool basicTargetsCore;

		private bool destroyerRoleAssigned;

		private bool destroyerTargetsCore;

		private void Awake()
		{
			master = ((Component)this).GetComponent<CharacterMaster>();
			ai = ((Component)this).GetComponent<BaseAI>();
		}

		private void FixedUpdate()
		{
			if (NetworkServer.active && !((Object)(object)ai == (Object)null) && !((Object)(object)BaseDefenseManager.Instance == (Object)null))
			{
				retargetTimer -= Time.fixedDeltaTime;
				if (retargetTimer <= 0f)
				{
					retargetTimer = 0.8f;
					UpdateTargetPriority();
				}
			}
		}

		private void UpdateTargetPriority()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_0150: Unknown result type (might be due to invalid IL or missing references)
			GameObject energyCoreBodyObject = BaseDefenseManager.Instance.EnergyCoreBodyObject;
			if ((Object)(object)energyCoreBodyObject == (Object)null)
			{
				return;
			}
			Vector3 fromPos = (((Object)(object)ai.body != (Object)null) ? ai.body.corePosition : ((Component)this).transform.position);
			switch (Archetype)
			{
			case EnemyArchetype.Titan:
				ai.neverRetaliateFriendlies = true;
				SetAITarget(energyCoreBodyObject);
				break;
			case EnemyArchetype.Demolition:
			{
				GameObject val3 = BaseDefenseManager.Instance.FindNearestStructure(fromPos, 120f);
				SetAITarget(((Object)(object)val3 != (Object)null) ? val3 : energyCoreBodyObject);
				break;
			}
			case EnemyArchetype.Swarm:
			{
				GameObject val2 = BaseDefenseManager.Instance.FindNearestPlayer(fromPos);
				SetAITarget(((Object)(object)val2 != (Object)null) ? val2 : energyCoreBodyObject);
				break;
			}
			case EnemyArchetype.Basic:
			{
				if (!basicTargetCoreAssigned)
				{
					basicTargetCoreAssigned = true;
					basicTargetsCore = Random.value >= 0.5f;
				}
				if (basicTargetsCore)
				{
					SetAITarget(energyCoreBodyObject);
					break;
				}
				GameObject val4 = BaseDefenseManager.Instance.FindNearestPlayer(fromPos);
				SetAITarget(((Object)(object)val4 != (Object)null) ? val4 : energyCoreBodyObject);
				break;
			}
			case EnemyArchetype.Destroyer:
			{
				if (!destroyerRoleAssigned)
				{
					destroyerRoleAssigned = true;
					destroyerTargetsCore = Random.value < 0.8f;
				}
				if (destroyerTargetsCore)
				{
					SetAITarget(energyCoreBodyObject);
					break;
				}
				GameObject val = BaseDefenseManager.Instance.FindNearestPlayer(fromPos);
				SetAITarget(((Object)(object)val != (Object)null) ? val : energyCoreBodyObject);
				break;
			}
			}
		}

		private void SetAITarget(GameObject targetBodyObj)
		{
			if (!((Object)(object)targetBodyObj == (Object)null) && ai.currentEnemy != null && (Object)(object)ai.currentEnemy.gameObject != (Object)(object)targetBodyObj)
			{
				ai.currentEnemy.gameObject = targetBodyObj;
				CharacterBody component = targetBodyObj.GetComponent<CharacterBody>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.mainHurtBox != (Object)null)
				{
					ai.currentEnemy.bestHurtBox = component.mainHurtBox;
				}
			}
		}
	}
	public class CoreShieldController : MonoBehaviour
	{
		public float MaxCustomShield;

		public float CurrentCustomShield;

		public float RechargeDelay = 30f;

		public float RechargeTimer;

		public bool IsBroken;

		private static GameObject cachedShieldHitEffect;

		public void Init(float maxShield, float delay)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			MaxCustomShield = maxShield;
			CurrentCustomShield = maxShield;
			RechargeDelay = delay;
			IsBroken = false;
			RechargeTimer = 0f;
			if ((Object)(object)cachedShieldHitEffect == (Object)null)
			{
				try
				{
					cachedShieldHitEffect = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Common/VFX/Hitspark1.prefab").WaitForCompletion();
				}
				catch
				{
				}
			}
		}

		public void AddBonusShieldFromUpgrade(float bonusShield)
		{
			MaxCustomShield += bonusShield;
			if (!IsBroken)
			{
				CurrentCustomShield = Mathf.Min(MaxCustomShield, CurrentCustomShield + bonusShield);
			}
		}

		public void ProcessIncomingDamage(DamageInfo damageInfo)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Invalid comparison between Unknown and I4
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if (damageInfo.rejected || damageInfo.damage <= 0f)
			{
				return;
			}
			if ((Object)(object)damageInfo.attacker != (Object)null && (int)TeamComponent.GetObjectTeam(damageInfo.attacker) == 1)
			{
				damageInfo.damage = 0f;
				damageInfo.rejected = true;
			}
			else
			{
				if (IsBroken || !(CurrentCustomShield > 0f))
				{
					return;
				}
				if (CurrentCustomShield >= damageInfo.damage)
				{
					CurrentCustomShield -= damageInfo.damage;
					damageInfo.damage = 0f;
					damageInfo.rejected = true;
					if ((Object)(object)cachedShieldHitEffect != (Object)null)
					{
						EffectManager.SimpleImpactEffect(cachedShieldHitEffect, damageInfo.position, Vector3.up, true);
					}
				}
				else
				{
					damageInfo.damage -= CurrentCustomShield;
					CurrentCustomShield = 0f;
					IsBroken = true;
					RechargeTimer = RechargeDelay;
					Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
					{
						baseToken = $"<color=#FF4444>[ТРЕВОГА] Щит Энергетического Ядра пробит! Перезарядка щита: {RechargeDelay:0} сек!</color>"
					});
				}
			}
		}

		private void FixedUpdate()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			if (NetworkServer.active && IsBroken)
			{
				RechargeTimer -= Time.fixedDeltaTime;
				if (RechargeTimer <= 0f)
				{
					IsBroken = false;
					RechargeTimer = 0f;
					CurrentCustomShield = MaxCustomShield;
					Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
					{
						baseToken = "<color=#33DDFF>[ЯДРО] Энергетический щит полностью перезаряжен!</color>"
					});
				}
			}
		}
	}
	public class BaseDefenseManager : MonoBehaviour
	{
		public List<BuildableStructure> ActiveStructures = new List<BuildableStructure>();

		public int CurrentWave;

		public bool IsWaveActive;

		public bool WaitingForManualStart = true;

		public bool IsMatchEnded;

		public WaveMutatorType ActiveWaveMutator;

		public const float CorePulseCooldownDuration = 90f;

		public float CorePulseCooldownTimer;

		private bool manualWaveStartTriggered;

		private List<CharacterMaster> aliveWaveEnemies = new List<CharacterMaster>();

		private HashSet<CharacterBody> serverWallhackIndicatedBodies = new HashSet<CharacterBody>();

		private bool lastFiveHighlightActive;

		private Dictionary<NetworkInstanceId, PlayerMatchStats> playerStats = new Dictionary<NetworkInstanceId, PlayerMatchStats>();

		private HashSet<NetworkInstanceId> currentlyRespawningPlayers = new HashSet<NetworkInstanceId>();

		private Vector3 mapCenterPosition;

		private float hudSyncTimer;

		public static BaseDefenseManager Instance { get; private set; }

		public GameObject EnergyCoreBodyObject { get; private set; }

		public CoreShieldController CoreShield { get; private set; }

		public int MaxWaves => BaseDefensePlugin.MaxWavesToWin.Value;

		private void Awake()
		{
			Instance = this;
			GameOverStatsUI.ResetState();
			ClientHudState.HighlightedEnemyBodyNetIds.Clear();
			ClientHudState.ActiveMutator = WaveMutatorType.None;
			ClientHudState.CorePulseCooldownTimer = 0f;
		}

		private void OnDestroy()
		{
			GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeathGlobal;
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private IEnumerator Start()
		{
			if (NetworkServer.active)
			{
				yield return (object)new WaitForSeconds(2.5f);
				NetMessageExtensions.Send((INetMessage)(object)NetSyncLobbyConfig.CreateFromCurrentConfig(), (NetworkDestination)1);
				DisableVanillaDirectors();
				mapCenterPosition = FindPlayableMapCenter();
				SpawnEnergyCore(mapCenterPosition);
				TeleportPlayersAroundCore(mapCenterPosition);
				GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeathGlobal;
				((MonoBehaviour)this).StartCoroutine(WaveLoopCoroutine());
			}
		}

		private void FixedUpdate()
		{
			if (NetworkServer.active)
			{
				if (CorePulseCooldownTimer > 0f)
				{
					CorePulseCooldownTimer = Mathf.Max(0f, CorePulseCooldownTimer - Time.fixedDeltaTime);
				}
				hudSyncTimer -= Time.fixedDeltaTime;
				if (hudSyncTimer <= 0f)
				{
					hudSyncTimer = 0.2f;
					DisableVanillaDirectors();
					CheckAndUpdateLastFiveEnemiesHighlight();
					BroadcastHudState();
				}
			}
		}

		private void CheckAndUpdateLastFiveEnemiesHighlight()
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			aliveWaveEnemies.RemoveAll((CharacterMaster m) => (Object)(object)m == (Object)null || !m.hasBody || (Object)(object)m.GetBody().healthComponent == (Object)null || !m.GetBody().healthComponent.alive);
			if (IsWaveActive && aliveWaveEnemies.Count > 0 && aliveWaveEnemies.Count <= 5)
			{
				List<NetworkInstanceId> list = new List<NetworkInstanceId>();
				NetworkIdentity val = default(NetworkIdentity);
				foreach (CharacterMaster aliveWaveEnemy in aliveWaveEnemies)
				{
					CharacterBody body = aliveWaveEnemy.GetBody();
					if (!((Object)(object)body == (Object)null))
					{
						if (((Component)body).TryGetComponent<NetworkIdentity>(ref val))
						{
							list.Add(val.netId);
						}
						if (!serverWallhackIndicatedBodies.Contains(body) && (Object)(object)body.teamComponent != (Object)null)
						{
							serverWallhackIndicatedBodies.Add(body);
							body.teamComponent.RequestDefaultIndicator(LegacyResourcesAPI.Load<GameObject>("Prefabs/PositionIndicators/PoiPositionIndicator"));
						}
					}
				}
				if (!lastFiveHighlightActive)
				{
					lastFiveHighlightActive = true;
					Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
					{
						baseToken = $"<color=#FF5555>[СКАНЕР ЯДРА] Осталось всего {aliveWaveEnemies.Count} врагов! Последние цели подсвечены сквозь стены!</color>"
					});
				}
				ClientHudState.ApplyHighlightedEnemies(list);
				NetMessageExtensions.Send((INetMessage)(object)new NetSyncHighlightedEnemies(list), (NetworkDestination)1);
			}
			else if (lastFiveHighlightActive || ClientHudState.HighlightedEnemyBodyNetIds.Count > 0)
			{
				lastFiveHighlightActive = false;
				serverWallhackIndicatedBodies.Clear();
				ClientHudState.ApplyHighlightedEnemies(new List<NetworkInstanceId>());
				NetMessageExtensions.Send((INetMessage)(object)new NetSyncHighlightedEnemies(new List<NetworkInstanceId>()), (NetworkDestination)1);
			}
		}

		public void ServerTriggerCorePulse()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: 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_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: 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_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: 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)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: 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_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: 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_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Expected O, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || IsMatchEnded || (Object)(object)EnergyCoreBodyObject == (Object)null || CorePulseCooldownTimer > 0f)
			{
				return;
			}
			CorePulseCooldownTimer = 90f;
			Vector3 val = EnergyCoreBodyObject.transform.position + Vector3.up * 1.6f;
			float num = 40f;
			CorePulseVisualEffect.SpawnPulseVisual(val, num);
			NetMessageExtensions.Send((INetMessage)(object)new NetSyncCorePulseEffect(val, num), (NetworkDestination)1);
			GameObject val2 = LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/OmniEffect/OmniExplosionVFX");
			if ((Object)(object)val2 != (Object)null)
			{
				EffectManager.SpawnEffect(val2, new EffectData
				{
					origin = val,
					scale = 6f
				}, true);
			}
			BullseyeSearch val3 = new BullseyeSearch
			{
				teamMaskFilter = TeamMask.GetEnemyTeams((TeamIndex)1),
				searchOrigin = val,
				maxDistanceFilter = num,
				filterByLoS = false,
				sortMode = (SortMode)1
			};
			val3.RefreshCandidates();
			HashSet<HealthComponent> hashSet = new HashSet<HealthComponent>();
			int num2 = 0;
			foreach (HurtBox result in val3.GetResults())
			{
				if (!((Object)(object)result == (Object)null) && !((Object)(object)result.healthComponent == (Object)null) && result.healthComponent.alive && !hashSet.Contains(result.healthComponent))
				{
					hashSet.Add(result.healthComponent);
					CharacterBody body = result.healthComponent.body;
					Vector3 val4 = (((Object)(object)body != (Object)null) ? body.corePosition : ((Component)result).transform.position);
					Vector3 val5 = val4 - val;
					val5.y = 0f;
					if (((Vector3)(ref val5)).sqrMagnitude < 0.01f)
					{
						val5 = Vector3.forward;
					}
					((Vector3)(ref val5)).Normalize();
					Vector3 val6 = val5 + Vector3.up * 0.35f;
					Vector3 force = ((Vector3)(ref val6)).normalized * 1600f;
					DamageInfo val7 = new DamageInfo
					{
						attacker = EnergyCoreBodyObject,
						inflictor = EnergyCoreBodyObject,
						damage = 30f,
						force = force,
						position = val4,
						crit = false,
						damageColorIndex = (DamageColorIndex)3,
						damageType = DamageTypeCombo.op_Implicit((DamageType)32),
						procCoefficient = 0f
					};
					result.healthComponent.TakeDamage(val7);
					if ((Object)(object)body != (Object)null && (Object)(object)body.characterMotor != (Object)null)
					{
						((BaseCharacterController)body.characterMotor).Motor.ForceUnground(0.1f);
						body.characterMotor.velocity = val5 * 16f + Vector3.up * 7.5f;
					}
					else if ((Object)(object)body != (Object)null && (Object)(object)body.rigidbody != (Object)null)
					{
						body.rigidbody.AddForce(val5 * 14f + Vector3.up * 6f, (ForceMode)2);
					}
					num2++;
				}
			}
			Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
			{
				baseToken = $"<color=#33EEFF>[ИМПУЛЬС ЯДРА] Выпущена энергетическая волна (40м)! Отброшено и поражено врагов: <b>{num2}</b> (30 ед. урона)!</color>"
			});
			BroadcastHudState();
		}

		private PlayerMatchStats GetOrCreateStats(CharacterMaster master)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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)
			if ((Object)(object)master == (Object)null)
			{
				return null;
			}
			NetworkInstanceId netId = ((Component)master).GetComponent<NetworkIdentity>().netId;
			if (!playerStats.TryGetValue(netId, out var value))
			{
				value = new PlayerMatchStats();
				playerStats[netId] = value;
			}
			return value;
		}

		public void RecordPlayerDamage(CharacterMaster playerMaster, float dmg)
		{
			PlayerMatchStats orCreateStats = GetOrCreateStats(playerMaster);
			if (orCreateStats != null)
			{
				orCreateStats.DamageDealt += dmg;
			}
		}

		public void RecordStructureBuilt(CharacterMaster playerMaster)
		{
			PlayerMatchStats orCreateStats = GetOrCreateStats(playerMaster);
			if (orCreateStats != null)
			{
				orCreateStats.StructuresBuilt++;
			}
		}

		public void RecordStructureDemolished(CharacterMaster playerMaster)
		{
			PlayerMatchStats orCreateStats = GetOrCreateStats(playerMaster);
			if (orCreateStats != null)
			{
				orCreateStats.StructuresDemolished++;
			}
		}

		public void RecordPlayerMoneyEarned(CharacterMaster playerMaster, int amount)
		{
			PlayerMatchStats orCreateStats = GetOrCreateStats(playerMaster);
			if (orCreateStats != null)
			{
				orCreateStats.TotalMoneyEarned += amount;
			}
		}

		public void TriggerStartNextWave()
		{
			if (NetworkServer.active && !IsMatchEnded && WaitingForManualStart && !IsWaveActive)
			{
				manualWaveStartTriggered = true;
			}
		}

		public void ServerRestartMatch()
		{
			if (NetworkServer.active)
			{
				GameOverStatsUI.ResetState();
				if ((Object)(object)Run.instance != (Object)null && (Object)(object)SceneCatalog.mostRecentSceneDef != (Object)null)
				{
					Run.instance.AdvanceStage(SceneCatalog.mostRecentSceneDef);
				}
			}
		}

		private void BroadcastHudState()
		{
			float coreHealth = 0f;
			float coreMaxHealth = BaseDefensePlugin.CoreBaseHealth.Value;
			float coreShield = 0f;
			float coreMaxShield = BaseDefensePlugin.CoreBaseShield.Value;
			float shieldRechargeTimer = 0f;
			bool isShieldBroken = false;
			if ((Object)(object)EnergyCoreBodyObject != (Object)null)
			{
				HealthComponent component = EnergyCoreBodyObject.GetComponent<HealthComponent>();
				if ((Object)(object)component != (Object)null)
				{
					coreHealth = component.health;
					coreMaxHealth = component.fullHealth;
				}
				if ((Object)(object)CoreShield != (Object)null)
				{
					coreShield = CoreShield.CurrentCustomShield;
					coreMaxShield = CoreShield.MaxCustomShield;
					shieldRechargeTimer = CoreShield.RechargeTimer;
					isShieldBroken = CoreShield.IsBroken;
				}
			}
			ClientHudState.CurrentWave = CurrentWave;
			ClientHudState.MaxWaves = MaxWaves;
			ClientHudState.AliveEnemiesCount = aliveWaveEnemies.Count;
			ClientHudState.IsWaveActive = IsWaveActive;
			ClientHudState.WaitingForManualStart = WaitingForManualStart;
			ClientHudState.CoreHealth = coreHealth;
			ClientHudState.CoreMaxHealth = coreMaxHealth;
			ClientHudState.CoreShield = coreShield;
			ClientHudState.CoreMaxShield = coreMaxShield;
			ClientHudState.ShieldRechargeTimer = shieldRechargeTimer;
			ClientHudState.IsShieldBroken = isShieldBroken;
			ClientHudState.ActiveMutator = ActiveWaveMutator;
			ClientHudState.CorePulseCooldownTimer = CorePulseCooldownTimer;
			NetMessageExtensions.Send((INetMessage)(object)new NetSyncCoreAndWaveState
			{
				CurrentWave = CurrentWave,
				MaxWaves = MaxWaves,
				AliveEnemiesCount = aliveWaveEnemies.Count,
				IsWaveActive = IsWaveActive,
				WaitingForManualStart = WaitingForManualStart,
				CoreHealth = coreHealth,
				CoreMaxHealth = coreMaxHealth,
				CoreShield = coreShield,
				CoreMaxShield = coreMaxShield,
				ShieldRechargeTimer = shieldRechargeTimer,
				IsShieldBroken = isShieldBroken,
				ActiveMutatorInt = (int)ActiveWaveMutator,
				CorePulseCooldownTimer = CorePulseCooldownTimer
			}, (NetworkDestination)1);
		}

		private void DisableVanillaDirectors()
		{
			foreach (CombatDirector item in new List<CombatDirector>(CombatDirector.instancesList))
			{
				if ((Object)(object)item != (Object)null)
				{
					item.monsterCredit = 0f;
					((Behaviour)item).enabled = false;
				}
			}
		}

		private Vector3 FindPlayableMapCenter()
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_007a: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			NodeGraph val = (((Object)(object)SceneInfo.instance != (Object)null) ? SceneInfo.instance.groundNodes : null);
			if ((Object)(object)val != (Object)null && val.GetNodeCount() > 0)
			{
				int nodeCount = val.GetNodeCount();
				Vector3 val2 = Vector3.zero;
				Vector3 val3 = default(Vector3);
				for (int i = 0; i < nodeCount; i++)
				{
					val.GetNodePosition(new NodeIndex(i), ref val3);
					val2 += val3;
				}
				Vector3 val4 = val2 / (float)nodeCount;
				NodeIndex val5 = val.FindClosestNode(val4, (HullClassification)1, float.PositiveInfinity);
				Vector3 val6 = default(Vector3);
				if (val.GetNodePosition(val5, ref val6))
				{
					RaycastHit val7 = default(RaycastHit);
					if (Physics.Raycast(val6 + Vector3.up * 8f, Vector3.down, ref val7, 30f, LayerMask.op_Implicit(((LayerIndex)(ref LayerIndex.world)).mask)))
					{
						return ((RaycastHit)(ref val7)).point;
					}
					return val6;
				}
			}
			return Vector3.zero;
		}

		private void SpawnEnergyCore(Vector3 position)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			GameObject masterPrefab = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Engi/EngiTurretMaster.prefab").WaitForCompletion();
			CharacterMaster val = new MasterSummon
			{
				masterPrefab = masterPrefab,
				position = position,
				rotation = Quaternion.identity,
				teamIndexOverride = (TeamIndex)1,
				ignoreTeamMemberLimit = true
			}.Perform();
			if (!((Object)(object)val != (Object)null))
			{
				return;
			}
			CharacterBody body = val.GetBody();
			if ((Object)(object)body != (Object)null)
			{
				EnergyCoreBodyObject = ((Component)body).gameObject;
				body.baseNameToken = "ЭНЕРГЕТИЧЕСКОЕ ЯДРО";
				body.baseMaxHealth = BaseDefensePlugin.CoreBaseHealth.Value;
				body.levelMaxHealth = 0f;
				body.baseRegen = 0f;
				body.levelRegen = 0f;
				body.baseArmor = 15f;
				body.levelArmor = 0f;
				body.RecalculateStats();
				body.healthComponent.health = body.maxHealth;
				CoreShield = ((Component)body).gameObject.AddComponent<CoreShieldController>();
				CoreShield.Init(BaseDefensePlugin.CoreBaseShield.Value, BaseDefensePlugin.CoreShieldRechargeDelay.Value);
				BuildableStructure buildableStructure = ((Component)body).gameObject.AddComponent<BuildableStructure>();
				buildableStructure.IsEnergyCore = true;
				buildableStructure.OriginalCost = 200;
				buildableStructure.Body = body;
				buildableStructure.UpgradeLevel = 1;
				VanillaVisualBuilder.StripTurretMechanicsAndHideMesh(((Component)body).gameObject, disableVanillaGun: true);
				VanillaVisualBuilder.ApplyEnergyCoreVisuals(((Component)body).gameObject);
				NetworkIdentity component = ((Component)body).GetComponent<NetworkIdentity>();
				if ((Object)(object)component != (Object)null)
				{
					NetMessageExtensions.Send((INetMessage)(object)new NetSyncStructureMetadata(component.netId, NetworkInstanceId.Invalid, BuildableId.LightBarricade, 200, position, Quaternion.identity, isCore: true), (NetworkDestination)1);
				}
			}
		}

		private void TeleportPlayersAroundCore(Vector3 center)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			int count = PlayerCharacterMasterController.instances.Count;
			int num = 0;
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				if ((Object)(object)instance.master != (Object)null)
				{
					instance.master.money = (uint)BaseDefensePlugin.StartingMoney.Value;
					RecordPlayerMoneyEarned(instance.master, BaseDefensePlugin.StartingMoney.Value);
					CharacterBody body = instance.master.GetBody();
					if ((Object)(object)body != (Object)null)
					{
						float num2 = (float)num * (360f / (float)Mathf.Max(1, count)) * (MathF.PI / 180f);
						Vector3 val = center + new Vector3(Mathf.Cos(num2) * 6.5f, 2f, Mathf.Sin(num2) * 6.5f);
						TeleportHelper.TeleportBody(body, val);
						num++;
					}
				}
			}
		}

		private IEnumerator WaveLoopCoroutine()
		{
			while (CurrentWave < MaxWaves && !IsMatchEnded)
			{
				IsWaveActive = false;
				WaitingForManualStart = true;
				manualWaveStartTriggered = false;
				ActiveWaveMutator = WaveMutatorType.None;
				CheckAndUpdateLastFiveEnemiesHighlight();
				int num = CurrentWave + 1;
				string text = ((num % 10 == 0) ? " <color=#FF3333><b>[ВНИМАНИЕ: СЛЕДУЮЩАЯ ВОЛНА — БОСС «УНИЧТОЖИТЕЛЬ»!]</b></color>" : "");
				SimpleChatMessage val = new SimpleChatMessage();
				val.baseToken = $"<color=#FFEE44>[ФАЗА ПОДГОТОВКИ] Постройте/почините оборону [{BaseDefensePlugin.ToggleBuildMenuKey.Value}] и прокачайте постройки [{BaseDefensePlugin.UpgradeStructureKey.Value}]! Нажмите [{BaseDefensePlugin.StartNextWaveKey.Value}] для старта Волны {num}/{MaxWaves}.{text}</color>";
				Chat.SendBroadcastChat((ChatMessageBase)(object)val);
				while (!manualWaveStartTriggered && !IsMatchEnded)
				{
					yield return null;
				}
				if (IsMatchEnded)
				{
					yield break;
				}
				WaitingForManualStart = false;
				CurrentWave++;
				IsWaveActive = true;
				HealCoreBetweenWaves();
				yield return ((MonoBehaviour)this).StartCoroutine(SpawnWaveEnemiesCoroutine(CurrentWave));
				while (aliveWaveEnemies.Count > 0 && !IsMatchEnded)
				{
					aliveWaveEnemies.RemoveAll((CharacterMaster m) => (Object)(object)m == (Object)null || !m.hasBody || !m.GetBody().healthComponent.alive);
					yield return (object)new WaitForSeconds(0.5f);
				}
				if (IsMatchEnded)
				{
					yield break;
				}
				IsWaveActive = false;
				ActiveWaveMutator = WaveMutatorType.None;
				CheckAndUpdateLastFiveEnemiesHighlight();
				RewardPlayersAfterWave(CurrentWave);
				SpawnWaveItemDropsFromCore(CurrentWave);
			}
			if (!IsMatchEnded)
			{
				IsMatchEnded = true;
				Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
				{
					baseToken = $"<color=#00FF66>[ПОБЕДА!] Все {MaxWaves} волн успешно отражены! Энергетическое Ядро в безопасности!</color>"
				});
				BroadcastFinalStatsToAllPlayers(isVictory: true);
			}
		}

		private void HealCoreBetweenWaves()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)EnergyCoreBodyObject == (Object)null || CurrentWave <= 1)
			{
				return;
			}
			float value = BaseDefensePlugin.CoreHealBetweenWavesFraction.Value;
			if (!(value <= 0f))
			{
				CharacterBody component = EnergyCoreBodyObject.GetComponent<CharacterBody>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.healthComponent != (Object)null)
				{
					BuildableStructure.AllowRepairStationHeal = true;
					component.healthComponent.HealFraction(value, default(ProcChainMask));
					BuildableStructure.AllowRepairStationHeal = false;
				}
			}
		}

		private void RewardPlayersAfterWave(int clearedWave)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			uint num = (uint)(BaseDefensePlugin.BaseWaveMoneyReward.Value + clearedWave * 30);
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				if ((Object)(object)instance.master != (Object)null)
				{
					instance.master.GiveMoney(num);
					RecordPlayerMoneyEarned(instance.master, (int)num);
				}
			}
			Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
			{
				baseToken = $"<color=#55FF55>[ВОЛНА {clearedWave} ЗАЧИЩЕНА!] Каждый игрок получил +{num}$ и награду предметами у Ядра!</color>"
			});
		}

		private void SpawnWaveItemDropsFromCore(int clearedWave)
		{
			//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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_00f1: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || (Object)(object)Run.instance == (Object)null)
			{
				return;
			}
			int num = Mathf.Max(1, PlayerCharacterMasterController.instances.Count);
			int num2 = ((clearedWave <= 5) ? 1 : ((clearedWave <= 20) ? 2 : 3));
			int num3 = num * num2;
			Vector3 val = (((Object)(object)EnergyCoreBodyObject != (Object)null) ? (EnergyCoreBodyObject.transform.position + Vector3.up * 3.6f) : (mapCenterPosition + Vector3.up * 3.6f));
			Vector3 val3 = default(Vector3);
			for (int i = 0; i < num3; i++)
			{
				PickupIndex val2 = RollRandomRunItem();
				if (val2 != PickupIndex.none)
				{
					float num4 = ((float)i * (360f / (float)Mathf.Max(1, num3)) + Random.Range(-12f, 12f)) * (MathF.PI / 180f);
					((Vector3)(ref val3))..ctor(Mathf.Cos(num4) * 8.5f, 15f, Mathf.Sin(num4) * 8.5f);
					PickupDropletController.CreatePickupDroplet(val2, val, val3);
				}
			}
			Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
			{
				baseToken = $"<color=#55EEFF>[ЯДРО] Выброшено предметов: {num3} шт. (по {num2} на каждого игрока)!</color>"
			});
		}

		private void SpawnYellowBossDropsFromCore()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0074: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || (Object)(object)Run.instance == (Object)null)
			{
				return;
			}
			int num = Mathf.Max(1, PlayerCharacterMasterController.instances.Count);
			Vector3 val = (((Object)(object)EnergyCoreBodyObject != (Object)null) ? (EnergyCoreBodyObject.transform.position + Vector3.up * 4f) : (mapCenterPosition + Vector3.up * 4f));
			Vector3 val3 = default(Vector3);
			for (int i = 0; i < num; i++)
			{
				PickupIndex val2 = RollGuaranteedYellowBossItem();
				if (val2 != PickupIndex.none)
				{
					float num2 = ((float)i * (360f / (float)Mathf.Max(1, num)) + Random.Range(-10f, 10f)) * (MathF.PI / 180f);
					((Vector3)(ref val3))..ctor(Mathf.Cos(num2) * 9f, 17f, Mathf.Sin(num2) * 9f);
					PickupDropletController.CreatePickupDroplet(val2, val, val3);
				}
			}
			Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
			{
				baseToken = $"<color=#FFEE00>[НАГРАДА ЗА УНИЧТОЖИТЕЛЯ!] У Энергетического Ядра выброшено {num} шт. ЖЕЛТЫХ (Босс) предметов!</color>"
			});
		}

		private PickupIndex RollGuaranteedYellowBossItem()
		{
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Run.instance != (Object)null && Run.instance.availableBossDropList != null && Run.instance.availableBossDropList.Count > 0)
			{
				return Run.instance.availableBossDropList[Random.Range(0, Run.instance.availableBossDropList.Count)];
			}
			List<ItemDef> list = new List<ItemDef>
			{
				Items.Knurl,
				Items.BeetleGland,
				Items.TitanGoldDuringTP,
				Items.SprintWisp,
				Items.SiphonOnLowHealth,
				Items.FireballsOnHit,
				Items.LightningStrikeOnHit,
				Items.NovaOnLowHealth
			};
			list.RemoveAll((ItemDef item) => (Object)(object)item == (Object)null);
			if (list.Count > 0)
			{
				return PickupCatalog.FindPickupIndex(list[Random.Range(0, list.Count)].itemIndex);
			}
			return RollRandomRunItem();
		}

		private PickupIndex RollRandomRunItem()
		{
			//IL_000d: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Run.instance == (Object)null)
			{
				return PickupIndex.none;
			}
			List<PickupIndex> list = null;
			float value = Random.value;
			if (value < 0.65f && Run.instance.availableTier1DropList != null && Run.instance.availableTier1DropList.Count > 0)
			{
				list = Run.instance.availableTier1DropList;
			}
			else if (value < 0.93f && Run.instance.availableTier2DropList != null && Run.instance.availableTier2DropList.Count > 0)
			{
				list = Run.instance.availableTier2DropList;
			}
			else if (Run.instance.availableTier3DropList != null && Run.instance.availableTier3DropList.Count > 0)
			{
				list = Run.instance.availableTier3DropList;
			}
			if ((list == null || list.Count == 0) && Run.instance.availableTier1DropList != null)
			{
				list = Run.instance.availableTier1DropList;
			}
			if (list != null && list.Count > 0)
			{
				return list[Random.Range(0, list.Count)];
			}
			return PickupIndex.none;
		}

		private WaveMutatorType RollWaveMutator()
		{
			if (Random.value <= 0.2f)
			{
				return (WaveMutatorType)Random.Range(1, 4);
			}
			return WaveMutatorType.None;
		}

		public static string GetMutatorDisplayName(WaveMutatorType mutator)
		{
			return mutator switch
			{
				WaveMutatorType.AerialAssault => "ВОЗДУШНЫЙ НАЛЁТ (Все враги летающие)", 
				WaveMutatorType.EliteVanguard => "ЭЛИТНЫЙ АВАНГАРД (Врагов x0.5, ВСЕ Элитные)", 
				WaveMutatorType.Siege => "ОСАДА (Количество Титанов x1.5)", 
				_ => "Без мутатора", 
			};
		}

		private IEnumerator SpawnWaveEnemiesCoroutine(int wave)
		{
			ActiveWaveMutator = RollWaveMutator();
			BroadcastHudState();
			if (ActiveWaveMutator != WaveMutatorType.None)
			{
				Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
				{
					baseToken = "<color=#FF44FF>⚡ [МУТАТОР ВОЛНЫ АКТИВИРОВАН]: <b>" + GetMutatorDisplayName(ActiveWaveMutator) + "</b>!</color>"
				});
			}
			int num = Mathf.Max(1, PlayerCharacterMasterController.instances.Count);
			int num2 = Mathf.RoundToInt((float)(10 + wave * 5) * (1f + (float)(num - 1) * 0.35f));
			if (ActiveWaveMutator == WaveMutatorType.EliteVanguard)
			{
				num2 = Mathf.Max(3, Mathf.RoundToInt((float)num2 * 0.5f));
			}
			List<EnemyArchetype> list = new List<EnemyArchetype>();
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			int num6 = 0;
			int num7 = 0;
			for (int i = 0; i < num2; i++)
			{
				EnemyArchetype enemyArchetype = ChooseWaveArchetype(wave);
				if (enemyArchetype == EnemyArchetype.Swarm)
				{
					int num8 = Random.Range(2, 4);
					if (ActiveWaveMutator == WaveMutatorType.EliteVanguard)
					{
						num8 = Mathf.Max(1, num8 / 2);
					}
					for (int j = 0; j < num8; j++)
					{
						list.Add(EnemyArchetype.Swarm);
						num3++;
					}
					continue;
				}
				list.Add(enemyArchetype);
				switch (enemyArchetype)
				{
				case EnemyArchetype.Basic:
					num4++;
					break;
				case EnemyArchetype.Demolition:
					num5++;
					break;
				case EnemyArchetype.Titan:
					num6++;
					break;
				}
			}
			if (ActiveWaveMutator == WaveMutatorType.Siege)
			{
				if (num6 == 0)
				{
					num6 = 2;
				}
				int num9 = Mathf.CeilToInt((float)num6 * 1.5f);
				int num10 = Mathf.Max(1, num9 - num6);
				for (int k = 0; k < num10; k++)
				{
					list.Add(EnemyArchetype.Titan);
					num6++;
				}
			}
			if (wave % 10 == 0)
			{
				list.Add(EnemyArchetype.Destroyer);
				num7 = 1;
				Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
				{
					baseToken = $"<color=#FF2222>⚠ [ВНИМАНИЕ! БОСС-ВОЛНА {wave}] На поле боя выходит <b>УНИЧТОЖИТЕЛЬ</b> (Приоритет атаки: 80% Ядро / 20% Игроки)!</color>"
				});
			}
			string text = ((wave % 10 == 0) ? " [БОСС-ВОЛНА: УНИЧТОЖИТЕЛЬ!]" : "");
			SimpleChatMessage val = new SimpleChatMessage();
			val.baseToken = $"<color=#FF6600>=== ВОЛНА {wave}/{MaxWaves}{text} НАЧАЛАСЬ! Всего врагов: {list.Count} ===</color>";
			Chat.SendBroadcastChat((ChatMessageBase)(object)val);
			string text2 = ((num7 > 0) ? $" | <color=#FF3333>Уничтожитель: <b>{num7}</b></color>" : "");
			val = new SimpleChatMessage();
			val.baseToken = $"<color=#FFCC66>[СОСТАВ ВОЛНЫ] Рой: <b>{num3}</b> | Обычные: <b>{num4}</b> | Демонтажники: <b>{num5}</b> | Титаны: <b>{num6}</b>{text2}</color>";
			Chat.SendBroadcastChat((ChatMessageBase)(object)val);
			foreach (EnemyArchetype item in list)
			{
				if (!IsMatchEnded)
				{
					SpawnSingleWaveEnemy(item, wave, ActiveWaveMutator);
					yield return (object)new WaitForSeconds(Mathf.Max(0.22f, 0.75f - (float)wave * 0.025f));
					continue;
				}
				yield break;
			}
		}

		private EnemyArchetype ChooseWaveArchetype(int wave)
		{
			float value = Random.value;
			if (value < 0.38f)
			{
				return EnemyArchetype.Swarm;
			}
			if (value < 0.68f)
			{
				return EnemyArchetype.Basic;
			}
			if (value < 0.86f && wave >= 2)
			{
				return EnemyArchetype.Demolition;
			}
			if (wave < 3)
			{
				return EnemyArchetype.Basic;
			}
			return EnemyArchetype.Titan;
		}

		private string GetRandomBossDestroyerAddress()
		{
			string[] array = new string[7] { "RoR2/Base/Titan/TitanMaster.prefab", "RoR2/Base/Titan/TitanGoldMaster.prefab", "RoR2/Base/Beetle/BeetleQueenMaster.prefab", "RoR2/Base/Vagrant/VagrantMaster.prefab", "RoR2/Base/ClayBoss/ClayBossMaster.prefab", "RoR2/Base/RoboBallBoss/RoboBallBossMaster.prefab", "RoR2/Base/MagmaWorm/MagmaWormMaster.prefab" };
			return array[Random.Range(0, array.Length)];
		}

		private string GetHeavyNonBossTitanAddress(int wave)
		{
			if (wave >= 8 && Random.value < 0.35f)
			{
				return "RoR2/Base/Parent/ParentMaster.prefab";
			}
			if (wave >= 6 && Random.value < 0.45f)
			{
				return "RoR2/Base/LemurianBruiser/LemurianBruiserMaster.prefab";
			}
			return "RoR2/Base/Golem/GolemMaster.prefab";
		}

		private string GetAerialEnemyAddress(EnemyArchetype archetype)
		{
			return archetype switch
			{
				EnemyArchetype.Swarm => (Random.value > 0.45f) ? "RoR2/Base/Wisp/WispMaster.prefab" : "RoR2/Base/Jellyfish/JellyfishMaster.prefab", 
				EnemyArchetype.Demolition => "RoR2/Base/Vulture/VultureMaster.prefab", 
				EnemyArchetype.Titan => "RoR2/Base/GreaterWisp/GreaterWispMaster.prefab", 
				_ => (Random.value > 0.5f) ? "RoR2/Base/Wisp/WispMaster.prefab" : "RoR2/Base/Vulture/VultureMaster.prefab", 
			};
		}

		private void ApplyRandomEliteAffix(Inventory inv)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)inv == (Object)null))
			{
				EquipmentDef[] array = (EquipmentDef[])(object)new EquipmentDef[4]
				{
					Equipment.AffixRed,
					Equipment.AffixBlue,
					Equipment.AffixWhite,
					Equipment.AffixPoison
				};
				EquipmentDef val = array[Random.Range(0, array.Length)];
				if ((Object)(object)val != (Object)null)
				{
					inv.SetEquipmentIndex(val.equipmentIndex);
				}
			}
		}

		private void SpawnSingleWaveEnemy(EnemyArchetype archetype, int wave, WaveMutatorType mutator)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: 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_0109: 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)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: 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_012f: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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)
			string text = ((archetype == EnemyArchetype.Destroyer) ? GetRandomBossDestroyerAddress() : ((mutator != WaveMutatorType.AerialAssault) ? (archetype switch
			{
				EnemyArchetype.Swarm => (Random.value > 0.45f) ? "RoR2/Base/Beetle/BeetleMaster.prefab" : "RoR2/Base/Lemurian/LemurianMaster.prefab", 
				EnemyArchetype.Demolition => (wave >= 5 && Random.value > 0.5f) ? "RoR2/Base/ClayBruiser/ClayBruiserMaster.prefab" : ((Random.value > 0.5f) ? "RoR2/Base/BeetleGland/BeetleGuardMaster.prefab" : "RoR2/Base/Bison/BisonMaster.prefab"), 
				EnemyArchetype.Titan => GetHeavyNonBossTitanAddress(wave), 
				_ => (Random.value > 0.5f) ? "RoR2/Base/Wisp/WispMaster.prefab" : "RoR2/Base/Imp/ImpMaster.prefab", 
			}) : GetAerialEnemyAddress(archetype)));
			GameObject val = Addressables.LoadAssetAsync<GameObject>((object)text).WaitForCompletion();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			bool num = mutator == WaveMutatorType.AerialAssault && archetype != EnemyArchetype.Destroyer;
			Vector3 val2 = FindPerimeterSpawnPoint(42f, 72f);
			if (num)
			{
				val2 += Vector3.up * 6.5f;
			}
			CharacterMaster val3 = new MasterSummon
			{
				masterPrefab = val,
				position = val2 + Vector3.up * 1f,
				rotation = Quaternion.identity,
				teamIndexOverride = (TeamIndex)2,
				ignoreTeamMemberLimit = true
			}.Perform();
			if (!((Object)(object)val3 != (Object)null))
			{
				return;
			}
			int num2 = wave * 2;
			int num3 = Mathf.Max(1, Mathf.RoundToInt((float)wave * 1.2f));
			switch (archetype)
			{
			case EnemyArchetype.Swarm:
				val3.inventory.GiveItem(Items.Hoof, 2);
				break;
			case EnemyArchetype.Titan:
				num2 += 16 + wave * 2;
				val3.inventory.GiveItem(Items.ArmorPlate, 3);
				break;
			case EnemyArchetype.Demolition:
				val3.inventory.GiveItem(Items.Syringe, 3);
				break;
			case EnemyArchetype.Destroyer:
				num2 += 25 + wave * 3;
				num3 += 4 + wave / 2;
				val3.inventory.GiveItem(Items.AdaptiveArmor, 1);
				val3.inventory.GiveItem(Items.ArmorPlate, 5);
				break;
			}
			if (mutator == WaveMutatorType.EliteVanguard)
			{
				ApplyRandomEliteAffix(val3.inventory);
				num2 += 10;
				num3 += 3;
			}
			val3.inventory.GiveItem(Items.BoostHp, num2);
			val3.inventory.GiveItem(Items.BoostDamage, num3);
			CharacterBody body = val3.GetBody();
			if ((Object)(object)body != (Object)null)
			{
				switch (archetype)
				{
				case EnemyArchetype.Destroyer:
					body.baseNameToken = "[УНИЧТОЖИТЕЛЬ] " + body.GetDisplayName();
					break;
				case EnemyArchetype.Titan:
					body.baseMoveSpeed *= 0.65f;
					body.baseNameToken = "[ТИТАН] " + body.GetDisplayName();
					break;
				case EnemyArchetype.Demolition:
					body.baseNameToken = "[ДЕМОНТАЖ] " + body.GetDisplayName();
					break;
				case EnemyArchetype.Swarm:
					body.baseMaxHealth *= 0.65f;
					body.baseNameToken = "[РОЙ] " + body.GetDisplayName();
					break;
				}
				body.RecalculateStats();
			}
			((Component)val3).gameObject.AddComponent<WaveEnemyMarker>().Archetype = archetype;
			aliveWaveEnemies.Add(val3);
		}

		private Vector3 FindPerimeterSpawnPoint(float minRadius, float maxRadius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_0070: 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)
			Vector2 insideUnitCircle = Random.insideUnitCircle;
			Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized * Random.Range(minRadius, maxRadius);
			Vector3 val2 = mapCenterPosition + new Vector3(val.x, 4f, val.y);
			NodeGraph val3 = (((Object)(object)SceneInfo.instance != (Object)null) ? SceneInfo.instance.groundNodes : null);
			if ((Object)(object)val3 != (Object)null)
			{
				NodeIndex val4 = val3.FindClosestNode(val2, (HullClassification)1, float.PositiveInfinity);
				Vector3 result = default(Vector3);
				if (val3.GetNodePosition(val4, ref result))
				{
					return result;
				}
			}
			return val2;
		}

		private void OnCharacterDeathGlobal(DamageReport report)
		{
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Invalid comparison between Unknown and I4
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_011d: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || report == null || IsMatchEnded)
			{
				return;
			}
			if ((Object)(object)EnergyCoreBodyObject != (Object)null && (Object)(object)report.victimBody != (Object)null && (Object)(object)((Component)report.victimBody).gameObject == (Object)(object)EnergyCoreBodyObject)
			{
				IsMatchEnded = true;
				IsWaveActive = false;
				WaitingForManualStart = false;
				Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
				{
					baseToken = "<color=#FF1111>[ПОРАЖЕНИЕ] Энергетическое Ядро уничтожено натиском врагов! Вывод итоговой статистики...</color>"
				});
				foreach (CharacterMaster aliveWaveEnemy in aliveWaveEnemies)
				{
					if ((Object)(object)aliveWaveEnemy != (Object)null && aliveWaveEnemy.hasBody)
					{
						aliveWaveEnemy.TrueKill();
					}
				}
				aliveWaveEnemies.Clear();
				BroadcastFinalStatsToAllPlayers(isVictory: false);
			}
			else if ((Object)(object)report.victimMaster != (Object)null && (Object)(object)report.victimMaster.playerCharacterMasterController != (Object)null)
			{
				PlayerMatchStats orCreateStats = GetOrCreateStats(report.victimMaster);
				if (orCreateStats != null)
				{
					orCreateStats.DeathsCount++;
				}
				NetworkInstanceId netId = ((Component)report.victimMaster).GetComponent<NetworkIdentity>().netId;
				if (!currentlyRespawningPlayers.Contains(netId))
				{
					((MonoBehaviour)this).StartCoroutine(RespawnPlayerAfterDelayCoroutine(report.victimMaster, netId));
				}
			}
			else
			{
				if ((int)report.victimTeamIndex != 2)
				{
					return;
				}
				if ((Object)(object)report.victimMaster != (Object)null)
				{
					WaveEnemyMarker component = ((Component)report.victimMaster).GetComponent<WaveEnemyMarker>();
					if ((Object)(object)component != (Object)null && component.Archetype == EnemyArchetype.Destroyer)
					{
						SpawnYellowBossDropsFromCore();
					}
				}
				if ((Object)(object)report.attackerMaster != (Object)null)
				{
					CharacterMaster val = report.attackerMaster;
					if ((Object)(object)val.playerCharacterMasterController == (Object)null && (Object)(object)report.attackerBody != (Object)null)
					{
						BuildableStructure component2 = ((Component)report.attackerBody).GetComponent<BuildableStructure>();
						if ((Object)(object)component2 != (Object)null && (Object)(object)component2.OwnerMaster != (Object)null)
						{
							val = component2.OwnerMaster;
						}
					}
					if ((Object)(object)val != (Object)null && (Object)(object)val.playerCharacterMasterController != (Object)null)
					{
						PlayerMatchStats orCreateStats2 = GetOrCreateStats(val);
						if (orCreateStats2 != null)
						{
							orCreateStats2.Kills++;
						}
					}
				}
				uint num = (uint)Mathf.Max(3, 5 + CurrentWave);
				foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
				{
					if ((Object)(object)instance.master != (Object)null)
					{
						instance.master.GiveMoney(num);
						RecordPlayerMoneyEarned(instance.master, (int)num);
					}
				}
			}
		}

		private IEnumerator RespawnPlayerAfterDelayCoroutine(CharacterMaster playerMaster, NetworkInstanceId playerNetId)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			currentlyRespawningPlayers.Add(playerNetId);
			float timer = BaseDefensePlugin.PlayerRespawnDelay.Value;
			while (timer > 0f && !IsMatchEnded && !((Object)(object)playerMaster == (Object)null))
			{
				if ((Object)(object)playerMaster.playerCharacterMasterController != (Object)null && (Object)(object)playerMaster.playerCharacterMasterController.networkUser != (Object)null && ((NetworkBehaviour)playerMaster.playerCharacterMasterController.networkUser).isLocalPlayer)
				{
					ClientHudState.LocalRespawnMasterNetId = playerNetId;
					ClientHudState.LocalRespawnTimer = timer;
				}
				NetMessageExtensions.Send((INetMessage)(object)new NetSyncPlayerRespawnTimer(playerNetId, timer), (NetworkDestination)1);
				yield return (object)new WaitForSeconds(0.2f);
				timer -= 0.2f;
			}
			NetMessageExtensions.Send((INetMessage)(object)new NetSyncPlayerRespawnTimer(playerNetId, 0f), (NetworkDestination)1);
			if (ClientHudState.LocalRespawnMasterNetId == playerNetId)
			{
				ClientHudState.LocalRespawnTimer = 0f;
			}
			if (!IsMatchEnded && (Object)(object)playerMaster != (Object)null && (!playerMaster.hasBody || !playerMaster.GetBody().healthComponent.alive))
			{
				Vector3 val = mapCenterPosition + new Vector3(Random.Range(-5f, 5f), 2.5f, Random.Range(-5f, 5f));
				playerMaster.Respawn(val, Quaternion.identity, false);
				Chat.SendBroadcastChat((ChatMessageBase)new SimpleChatMessage
				{
					baseToken = "<color=#66FFAA>[ВОЗРОЖДЕНИЕ] Защитник возрожден у Энергетического Ядра!</color>"
				});
			}
			currentlyRespawningPlayers.Remove(playerNetId);
		}

		private void BroadcastFinalStatsToAllPlayers(bool isVictory)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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)
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				if ((Object)(object)instance != (Object)null && (Object)(object)instance.master != (Object)null)
				{
					NetworkInstanceId netId = ((Component)instance.master).GetComponent<NetworkIdentity>().netId;
					PlayerMatchStats orCreateStats = GetOrCreateStats(instance.master);
					NetSyncGameOverStats obj = new NetSyncGameOverStats
					{
						TargetMasterNetId = netId,
						IsVictory = isVictory,
						ReachedWave = CurrentWave,
						Kills = (orCreateStats?.Kills ?? 0),
						DamageDealt = (orCreateStats?.DamageDealt ?? 0f),
						StructuresBuilt = (orCreateStats?.StructuresBuilt ?? 0),
						StructuresDemolished = (orCreateStats?.StructuresDemolished ?? 0),
						TotalMoneyEarned = (orCreateStats?.TotalMoneyEarned ?? 0),
						DeathsCount = (orCreateStats?.DeathsCount ?? 0)
					};
					GameOverStatsUI.ReceiveStatsPacket(obj);
					NetMessageExtensions.Send((INetMessage)(object)obj, (NetworkDestination)1);
				}
			}
		}

		public GameObject FindNearestStructure(Vector3 fromPos, float maxRadius)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			BuildableStructure buildableStructure = null;
			float num = maxRadius * maxRadius;
			foreach (BuildableStructure activeStructure in ActiveStructures)
			{
				if (!((Object)(object)activeStructure == (Object)null) && !activeStructure.IsEnergyCore && !((Object)(object)activeStructure.Body == (Object)null) && activeStructure.Body.healthComponent.alive)
				{
					Vector3 val = activeStructure.Body.corePosition - fromPos;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						buildableStructure = activeStructure;
					}
				}
			}
			if (!((Object)(object)buildableStructure != (Object)null))
			{
				return null;
			}
			return ((Component)buildableStructure.Body).gameObject;
		}

		public GameObject FindNearestPlayer(Vector3 fromPos)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			GameObject result = null;
			float num = float.MaxValue;
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				if (!((Object)(object)instance.master != (Object)null) || !instance.master.hasBody)
				{
					continue;
				}
				CharacterBody body = instance.master.GetBody();
				if ((Object)(object)body != (Object)null && (Object)(object)body.healthComponent != (Object)null && body.healthComponent.alive)
				{
					Vector3 val = body.corePosition - fromPos;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						result = ((Component)body).gameObject;
					}
				}
			}
			return result;
		}
	}
	public class CorePulseVisualEffect : MonoBehaviour
	{
		private float maxRadius = 40f;

		private float duration = 0.85f;

		private float elapsed;

		private Transform ringTransform;

		public static void SpawnPulseVisual(Vector3 center, float radius)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("CorePulseWaveVFX");
			val.transform.position = center;
			GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)2);
			Object.Destroy((Object)(object)val2.GetComponent<Collider>());
			val2.transform.SetParent(val.transform, false);
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localScale = new Vector3(1f, 0.25f, 1f);
			Material sharedMaterial = VanillaVisualBuilder.CreateGlowingMaterial(new Color(0.15f, 0.9f, 1f, 0.65f), 3.5f);
			val2.GetComponent<Renderer>().sharedMaterial = sharedMaterial;
			CorePulseVisualEffect corePulseVisualEffect = val.AddComponent<CorePulseVisualEffect>();
			corePulseVisualEffect.maxRadius = radius;
			corePulseVisualEffect.ringTransform = val2.transform;
		}

		private void Update()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			elapsed += Time.deltaTime;
			float num = Mathf.Clamp01(elapsed / duration);
			float num2 = Mathf.Lerp(2f, maxRadius * 2f, Mathf.SmoothStep(0f, 1f, num));
			float num3 = Mathf.Lerp(1.6f, 0.05f, num);
			if ((Object)(object)ringTransform != (Object)null)
			{
				ringTransform.localScale = new Vector3(num2, num3, num2);
			}
			if (elapsed >= duration)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.daniil.ror2basedefense", "RoR2 Base Defense Mode", "2.5.1")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class BaseDefensePlugin : BaseUnityPlugin
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static hook_Awake <>9__85_0;

			public static hook_Start <>9__85_1;

			public static hook_Start <>9__85_2;

			public static hook_OnEnable <>9__85_3;

			public static hook_OnDeath <>9__85_4;

			public static hook_Awake <>9__85_5;

			public static hook_OnEnable <>9__85_6;

			public static hook_BeginGameOver <>9__85_7;

			public static hook_PollButtonInput <>9__85_8;

			internal void <HooksInit>b__85_0(orig_Awake orig, CharacterSelectController self)
			{
				orig.Invoke(self);
				if ((Object)(object)((Component)self).gameObject.GetComponent<LobbyConfiguratorUI>() == (Object)null)
				{
					((Component)self).gameObject.AddComponent<LobbyConfiguratorUI>();
				}
			}

			internal IEnumerator <HooksInit>b__85_1(orig_Start orig, Stage self)
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				IEnumerator result = orig.Invoke(self);
				if (EnableMode.Value && (Object)(object)BaseDefenseManager.Instance == (Object)null)
				{
					new GameObject("BaseDefenseManager_Singleton").AddComponent<BaseDefenseManager>();
				}
				return result;
			}

			internal void <HooksInit>b__85_2(orig_Start orig, SceneDirector self)
			{
				if (EnableMode.Value)
				{
					self.teleporterSpawnCard = null;
					self.interactableCredit = Mathf.RoundToInt((float)self.interactableCredit * 0.25f);
				}
				orig.Invoke(self);
			}

			internal void <HooksInit>b__85_3(orig_OnEnable orig, CombatDirector self)
			{
				orig.Invoke(self);
				if (EnableMode.Value && (Object)(object)self != (Object)null)
				{
					self.monsterCredit = 0f;
					((Behaviour)self).enabled = false;
				}
			}

			internal void <HooksInit>b__85_4(orig_OnDeath orig, CharacterDeathBehavior self)
			{
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: 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_006f: Expected O, but got Unknown
				if (EnableMode.Value && (Object)(object)self != (Object)null && (Object)(object)((Component)self).GetComponent<SpawnedByDroneStationMarker>() != (Object)null)
				{
					if (NetworkServer.active)
					{
						GameObject val = LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/OmniEffect/OmniExplosionVFX");
						if ((Object)(object)val != (Object)null)
						{
							EffectManager.SpawnEffect(val, new EffectData
							{
								origin = ((Component)self).transform.position,
								scale = 1.5f
							}, true);
						}
						CharacterBody component = ((Component)self).GetComponent<CharacterBody>();
						if ((Object)(object)component != (Object)null && (Object)(object)component.master != (Object)null)
						{
							Object.Destroy((Object)(object)((Component)component.master).gameObject, 0.05f);
						}
						NetworkServer.Destroy(((Component)self).gameObject);
					}
				}
				else
				{
					orig.Invoke(self);
				}
			}

			internal void <HooksInit>b__85_5(orig_Awake orig, PlayerCharacterMasterController self)
			{
				orig.Invoke(self);
				if ((Object)(object)self.master != (Object)null && EnableMode.Value)
				{
					self.master.preventGameOver = true;
				}
				if ((Object)(object)((Component)self).gameObject.GetComponent<PlayerBuildController>() == (Object)null)
				{
					((Component)self).gameObject.AddComponent<PlayerBuildController>();
				}
			}

			internal void <HooksInit>b__85_6(orig_OnEnable orig, AllyCardManager self)
			{
				orig.Invoke(self);
				if (EnableMode.Value && (Object)(object)self != (Object)null)
				{
					CanvasGroup val = ((Component)self).GetComponent<CanvasGroup>();
					if ((Object)(object)val == (Object)null)
					{
						val = ((Component)self).gameObject.AddComponent<CanvasGroup>();
					}
					val.alpha = 0f;
					val.blocksRaycasts = false;
					val.interactable = false;
				}
			}

			internal void <HooksInit>b__85_7(orig_BeginGameOver orig, Run self, GameEndingDef gameEndingDef)
			{
				if (!EnableMode.Value || !((Object)(object)BaseDefenseManager.Instance != (Object)null) || BaseDefenseManager.Instance.IsMatchEnded)
				{
					orig.Invoke(self, gameEndingDef);
				}
			}

			internal void <HooksInit>b__85_8(orig_PollButtonInput orig, PlayerCharacterMasterController self)
			{
				orig.Invoke(self);
				if (EnableMode.Value && !((Object)(object)self == (Object)null))
				{
					PlayerBuildController component = ((Component)self).GetComponent<PlayerBuildController>();
					if ((Object)(object)component != (Object)null && component.ShouldBlockCombatSkills() && (Object)(object)self.bodyInputs != (Object)null)
					{
						((ButtonState)(ref self.bodyInputs.skill1)).PushState(false);
						((ButtonState)(ref self.bodyInputs.skill2)).PushState(false);
						((ButtonState)(ref self.bodyInputs.skill3)).PushState(false);
						((ButtonState)(ref self.bodyInputs.skill4)).PushState(false);
					}
				}
			}
		}

		public const string PluginGUID = "com.daniil.ror2basedefense";

		public const string PluginName = "RoR2 Base Defense Mode";

		public const string PluginVersion = "2.5.1";

		public static ConfigEntry<bool> EnableMode;

		public static ConfigEntry<int> MaxWavesToWin;

		public static ConfigEntry<int> StartingMoney;

		public static ConfigEntry<int> BaseWaveMoneyReward;

		public static ConfigEntry<float> CoreHealBetweenWavesFraction;

		public static ConfigEntry<float> PlayerRespawnDelay;

		public static ConfigEntry<float> CoreBaseHealth;

		public static ConfigEntry<float> CoreHealthPerWave;

		public static ConfigEntry<float> CoreBaseShield;

		public static ConfigEntry<float> CoreShieldPerWave;

		public static ConfigEntry<float> CoreShieldRechargeDelay;

		public static ConfigEntry<KeyCode> ToggleBuildMenuKey;

		public static ConfigEntry<KeyCode> DemolishKey;

		public static ConfigEntry<KeyCode> UpgradeStructureKey;

		public static ConfigEntry<KeyCode> StartNextWaveKey;

		public static ConfigEntry<KeyCode> InteractDoorKey;

		public static ConfigEntry<KeyCode> CorePulseSkillKey;

		public static ConfigEntry<float> RefundPercentage;

		public static ConfigEntry<int> LimitHealStation;

		public static ConfigEntry<int> LimitMoneyGenerator;

		public static ConfigEntry<int> LimitRepairStation;

		public static ConfigEntry<int> LimitDroneStation;

		public static ConfigEntry<int> LimitPerTurretType;

		public static ConfigEntry<int> LimitTotalTurretsPerPlayer;

		public static ConfigEntry<float> EnemyStructureDamagePerWave;

		public static ConfigEntry<float> DemolitionDamageMultiplier;

		public static ConfigEntry<float> DroneMaxHealth;

		public static ConfigEntry<int> MaxDronesPerStation;

		public static ConfigEntry<int> MoneyGenTickAmount;

		public static ConfigEntry<float> HealStationPercentPerSec;

		public static ConfigEntry<float> RepairStationPercentPerSec;

		public static ConfigEntry<int> CostLightBarricade;

		public static ConfigEntry<int> CostHeavyBlock;

		public static ConfigEntry<int> CostWallBlock;

		public static ConfigEntry<int> CostHighWallBlock;

		public static ConfigEntry<int> CostPillarBlock;

		public static ConfigEntry<int> CostRampBlock;

		public static ConfigEntry<int> CostRamp60Block;

		public static ConfigEntry<int> CostWindowBlock;

		public static ConfigEntry<int> CostDoorBlock;

		public static ConfigEntry<int> CostLongWallBlock;

		public static ConfigEntry<int> CostSpikePlatform;

		public static ConfigEntry<int> CostSpringTrap;

		public static ConfigEntry<int> CostMachineGunTurret;

		public static ConfigEntry<int> CostFlameTurret;

		public static ConfigEntry<int> CostTeslaTurret;

		public static ConfigEntry<int> CostRocketTurret;

		public static ConfigEntry<int> CostLaserTurret;

		public static ConfigEntry<int> CostMortarTurret;

		public static ConfigEntry<int> CostHealStation;

		public static ConfigEntry<int> CostMoneyGen;

		public static ConfigEntry<int> CostDroneStation;

		public static ConfigEntry<int> CostRepairStation;

		public static ConfigEntry<float> TurretMGDamage;

		public static ConfigEntry<float> TurretMGHealth;

		public static ConfigEntry<float> TurretMGArmor;

		public static ConfigEntry<float> TurretFlameDamage;

		public static ConfigEntry<float> TurretFlameHealth;

		public static ConfigEntry<float> TurretFlameArmor;

		public static ConfigEntry<float> TurretTeslaDamage;

		public static ConfigEntry<float> TurretTeslaHealth;

		public static ConfigEntry<float> TurretTeslaArmor;

		public static ConfigEntry<float> TurretRocketDamage;

		public static ConfigEntry<float> TurretRocketHealth;

		public static ConfigEntry<float> TurretRocketArmor;

		public static ConfigEntry<float> TurretLaserDamage;

		public static ConfigEntry<float> TurretLaserHealth;

		public static ConfigEntry<float> TurretLaserArmor;

		public static ConfigEntry<float> TurretMortarDamage;

		public static ConfigEntry<float> TurretMortarHealth;

		public static ConfigEntry<float> TurretMortarArmor;

		public static BaseDefensePlugin Instance { get; private set; }

		public static ManualLogSource ModLogger { get; private set; }

		private void Awake()
		{
			Instance = this;
			ModLogger = ((BaseUnityPlugin)this).Logger;
			InitConfig();
			NetworkMessages.RegisterMessages();
			BuildableCatalog.InitCatalog();
			HooksInit();
			ModLogger.LogInfo((object)"RoR2 Base Defense Mode v2.5.1 успешно загружен!");
		}

		private void InitConfig()
		{
			EnableMode = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "EnableBaseDefenseMode", true, "Включить режим Защиты Базы.");
			MaxWavesToWin = ((BaseUnityPlugin)this).Config.Bind<int>("1. General", "WavesToWin", 15, "Количество волн для победы.");
			StartingMoney = ((BaseUnityPlugin)this).Config.Bind<int>("1. General", "StartingMoney", 200, "Стартовое золото каждого игрока.");
			BaseWaveMoneyReward = ((BaseUnityPlugin)this).Config.Bind<int>("1. General", "BaseWaveMoneyReward", 85, "Базовая награда золотом за волну.");
			CoreHealBetweenWavesFraction = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "CoreHealBetweenWaves", 0.08f, "Доля восстановления ХП Ядра между волнами (0.08 = 8%).");
			PlayerRespawnDelay = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "PlayerRespawnSeconds", 10f, "Время возрождения игрока возле Ядра после смерти.");
			CoreBaseHealth = ((BaseUnityPlugin)this).Config.Bind<float>("2. Energy Core", "CoreBaseHealth", 3500f, "Базовое здоровье Энергетического Ядра.");
			CoreHealthPerWave = ((BaseUnityPlugin)this).Config.Bind<float>("2. Energy Core", "CoreHealthPerUpgrade", 500f, "Прирост макс. здоровья Ядра за каждую прокачку.");
			CoreBaseShield = ((BaseUnityPlugin)this).Config.Bind<float>("2. Energy Core", "CoreBaseShield", 1500f, "Базовый дополнительный щит Ядра.");
			CoreShieldPerWave = ((BaseUnityPlugin)this).Config.Bind<float>("2. Energy Core", "CoreShieldPerUpgrade", 250f, "Прирост макс. щита Ядра за каждую прокачку.");
			CoreShieldRechargeDelay = ((BaseUnityPlugin)this).Config.Bind<float>("2. Energy Core", "ShieldRechargeTime", 30f, "Время перезарядки пробитого щита (в секундах).");
			ToggleBuildMenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3. Controls", "BuildMenuKey", (KeyCode)98, "Кнопка открытия магазина строительства.");
			DemolishKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3. Controls", "DemolishKey", (KeyCode)120, "Кнопка сноса постройки (возврат 50%).");
			UpgradeStructureKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3. Controls", "UpgradeKey", (KeyCode)117, "Кнопка прокачки выбранной постройки за деньги.");
			StartNextWaveKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3. Controls", "StartWaveKey", (KeyCode)103, "Кнопка запуска следующей волны.");
			InteractDoorKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3. Controls", "DoorToggleKey", (KeyCode)102, "Кнопка открытия двери / переключения видимости радиуса станции.");
			CorePulseSkillKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3. Controls", "CorePulseKey", (KeyCode)104, "Кнопка активации навыка Ядра «Импульс» (кд 90 сек).");
			RefundPercentage = ((BaseUnityPlugin)this).Config.Bind<float>("3. Controls", "RefundPercentage", 0.5f, "Процент возврата при сносе (0.5 = 50%).");
			LimitHealStation = ((BaseUnityPlugin)this).Config.Bind<int>("4. Build Limits", "MaxHealStations", 2, "Максимум Хил-станций на игрока.");
			LimitMoneyGenerator = ((BaseUnityPlugin)this).Config.Bind<int>("4. Build Limits", "MaxMoneyGeneratorsV2", 1, "Максимум Денежных генераторов на игрока (по умолчанию 1).");
			LimitRepairStation = ((BaseUnityPlugin)this).Config.Bind<int>("4. Build Limits", "MaxRepairStations", 2, "Максимум Ремонтных станций на игрока.");
			LimitDroneStation = ((BaseUnityPlugin)this).Config.Bind<int>("4. Build Limits", "MaxDroneStations", 2, "Максимум Дрон-станций на игрока.");
			LimitPerTurretType = ((BaseUnityPlugin)this).Config.Bind<int>("4. Build Limits", "MaxPerTurretType", 4, "Максимум турелей одного вида на игрока.");
			LimitTotalTurretsPerPlayer = ((BaseUnityPlugin)this).Config.Bind<int>("4. Build Limits", "MaxTotalTurrets", 10, "Общий лимит боевых турелей на одного игрока.");
			EnemyStructureDamagePerWave = ((BaseUnityPlugin)this).Config.Bind<float>("5. Balance", "EnemyStructureDamageBonusPerWave", 0f, "Не используется (урон и статы построек зависят от прокачки).");
			DemolitionDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("5. Balance", "DemolitionDamageMultiplier", 2f, "Доп. множитель урона врагов класса 'Демонтаж' по постройкам.");
			DroneMaxHealth = ((BaseUnityPlugin)this).Config.Bind<float>("5. Balance", "SpawnedDroneHealth", 45f, "Базовое здоровье дронов Дрон-станции.");
			MaxDronesPerStation = ((BaseUnityPlugin)this).Config.Bind<int>("5. Balance", "MaxDronesPerStation", 3, "Максимум живых дронов от одной Дрон-станции.");
			MoneyGenTickAmount = ((BaseUnityPlugin)this).Config.Bind<int>("5. Balance", "MoneyGenAmountPerTick", 6, "Базовое золото за тик (2 сек) от Денежного генератора.");
			HealStationPercentPerSec = ((BaseUnityPlugin)this).Config.Bind<float>("5. Balance", "HealStationPercentPerSec", 0.06f, "Базовое исцеление игроков от Хил-станции в сек (0.06 = 6%).");
			RepairStationPercentPerSec = ((BaseUnityPlugin)this).Config.Bind<float>("5. Balance", "RepairStationPercentPerSec", 0.025f, "Базовое лечение построек от Ремонтной станции в сек (0.025 = 2.5%).");
			CostLightBarricade = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "LightBarricadeCost", 20, "Цена: Низкая баррикада.");
			CostWallBlock = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "WallBlockCost", 30, "Цена: Стена.");
			CostHighWallBlock = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "HighWallBlockCost", 48, "Цена: Высокая стена.");
			CostPillarBlock = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "PillarBlockCost", 25, "Цена: Колонна.");
			CostRampBlock = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "RampBlockCost", 30, "Цена: Уклон (Рампа 30°).");
			CostRamp60Block = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "Ramp60BlockCost", 35, "Цена: Крутая Рампа (60°).");
			CostWindowBlock = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "WindowBlockCost", 35, "Цена: Стена с окном для стрельбы.");
			CostDoorBlock = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "DoorBlockCost", 45, "Цена: Функциональная дверь.");
			CostLongWallBlock = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "LongWallBlockCost", 55, "Цена: Длинная стена.");
			CostHeavyBlock = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "HeavyBlockCost", 65, "Цена: Силовой куб-бастион.");
			CostSpikePlatform = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "SpikePlatformCost", 45, "Цена: Шипастая платформа.");
			CostSpringTrap = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "SpringTrapCost", 40, "Цена: Пружинная установка (5 срабатываний).");
			CostMachineGunTurret = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "MachineGunTurretCost", 60, "Цена: Пулеметная турель.");
			CostFlameTurret = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "FlameTurretCost", 85, "Цена: Турель-огнемет.");
			CostTeslaTurret = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "TeslaTurretCost", 100, "Цена: Электро-турель.");
			CostRocketTurret = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "RocketTurretCost", 120, "Цена: Ракетная турель.");
			CostLaserTurret = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "LaserTurretCost", 150, "Цена: Лазерная турель.");
			CostMortarTurret = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "MortarTurretCost", 135, "Цена: Артиллерийская Мортира.");
			CostHealStation = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "HealStationCost", 90, "Цена: Хил-станция (только для игроков).");
			CostRepairStation = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "RepairStationCost", 95, "Цена: Ремонтная станция (только для построек).");
			CostMoneyGen = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "MoneyGeneratorCost", 110, "Цена: Денежный генератор.");
			CostDroneStation = ((BaseUnityPlugin)this).Config.Bind<int>("6. Costs", "DroneStationCost", 130, "Цена: Дрон-станция.");
			TurretMGDamage = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "MGTurretBaseDamage", 14f, "Пулеметная турель: Базовый урон.");
			TurretMGHealth = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "MGTurretBaseHealth", 480f, "Пулеметная турель: Базовое здоровье.");
			TurretMGArmor = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "MGTurretBaseArmor", 10f, "Пулеметная турель: Базовая броня.");
			TurretFlameDamage = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "FlameTurretBaseDamage", 14f, "Турель-огнемет: Базовый урон.");
			TurretFlameHealth = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "FlameTurretBaseHealth", 700f, "Турель-огнемет: Базовое здоровье.");
			TurretFlameArmor = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "FlameTurretBaseArmor", 20f, "Турель-огнемет: Базовая броня.");
			TurretTeslaDamage = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "TeslaTurretBaseDamage", 17f, "Электро-турель: Базовый урон.");
			TurretTeslaHealth = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "TeslaTurretBaseHealth", 500f, "Электро-турель: Базовое здоровье.");
			TurretTeslaArmor = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "TeslaTurretBaseArmor", 10f, "Электро-турель: Базовая броня.");
			TurretRocketDamage = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "RocketTurretBaseDamage", 22f, "Ракетная турель: Базовый урон.");
			TurretRocketHealth = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "RocketTurretBaseHealth", 540f, "Ракетная турель: Базовое здоровье.");
			TurretRocketArmor = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "RocketTurretBaseArmor", 15f, "Ракетная турель: Базовая броня.");
			TurretLaserDamage = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "LaserTurretBaseDamage", 26f, "Лазерная турель: Базовый урон.");
			TurretLaserHealth = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "LaserTurretBaseHealth", 500f, "Лазерная турель: Базовое здоровье.");
			TurretLaserArmor = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "LaserTurretBaseArmor", 10f, "Лазерная турель: Базовая броня.");
			TurretMortarDamage = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "MortarTurretBaseDamage", 34f, "Мортира: Базовый урон снаряда.");
			TurretMortarHealth = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "MortarTurretBaseHealth", 580f, "Мортира: Базовое здоровье.");
			TurretMortarArmor = ((BaseUnityPlugin)this).Config.Bind<float>("7. Turret Stats", "MortarTurretBaseArmor", 18f, "Мортира: Базовая броня.");
		}

		public static void RefreshPricesInCatalog()
		{
			BuildableCatalog.UpdateFromConfig();
		}

		private void HooksInit()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			object obj = <>c.<>9__85_0;
			if (obj == null)
			{
				hook_Awake val = delegate(orig_Awake orig, CharacterSelectController self)
				{
					orig.Invoke(self);
					if ((Object)(object)((Component)self).gameObject.GetComponent<LobbyConfiguratorUI>() == (Object)null)
					{
						((Component)self).gameObject.AddComponent<LobbyConfiguratorUI>();
					}
				};
				<>c.<>9__85_0 = val;
				obj = (object)val;
			}
			CharacterSelectController.Awake += (hook_Awake)obj;
			object obj2 = <>c.<>9__85_1;
			if (obj2 == null)
			{
				hook_Start val2 = delegate(orig_Start orig, Stage self)
				{
					//IL_0025: Unknown result type (might be due to invalid IL or missing references)
					IEnumerator result = orig.Invoke(self);
					if (EnableMode.Value && (Object)(object)BaseDefenseManager.Instance == (Object)null)
					{
						new GameObject("BaseDefenseManager_Singleton").AddComponent<BaseDefenseManager>();
					}
					return result;
				};
				<>c.<>9__85_1 = val2;
				obj2 = (object)val2;
			}
			Stage.Start += (hook_Start)obj2;
			object obj3 = <>c.<>9__85_2;
			if (obj3 == null)
			{
				hook_Start val3 = delegate(orig_Start orig, SceneDirector self)
				{
					if (EnableMode.Value)
					{
						self.teleporterSpawnCard = null;
						self.interactableCredit = Mathf.RoundToInt((float)self.interactableCredit * 0.25f);
					}
					orig.Invoke(self);
				};
				<>c.<>9__85_2 = val3;
				obj3 = (object)val3;
			}
			SceneDirector.Start += (hook_Start)obj3;
			object obj4 = <>c.<>9__85_3;
			if (obj4 == null)
			{
				hook_OnEnable val4 = delegate(orig_OnEnable orig, CombatDirector self)
				{
					orig.Invoke(self);
					if (EnableMode.Value && (Object)(object)self != (Object)null)
					{
						self.monsterCredit = 0f;
						((Behaviour)self).enabled = false;
					}
				};
				<>c.<>9__85_3 = val4;
				obj4 = (object)val4;
			}
			CombatDirector.OnEnable += (hook_OnEnable)obj4;
			object obj5 = <>c.<>9__85_4;
			if (obj5 == null)
			{
				hook_OnDeath val5 = delegate(orig_OnDeath orig, CharacterDeathBehavior self)
				{
					//IL_0048: Unknown result type (might be due to invalid IL or missing references)
					//IL_004d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0054: 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_006f: Expected O, but got Unknown
					if (EnableMode.Value && (Object)(object)self != (Object)null && (Object)(object)((Component)self).GetComponent<SpawnedByDroneStationMarker>() != (Object)null)
					{
						if (NetworkServer.active)
						{
							GameObject val10 = LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/OmniEffect/OmniExplosionVFX");
							if ((Object)(object)val10 != (Object)null)
							{
								EffectManager.SpawnEffect(val10, new EffectData
								{
									origin = ((Component)self).transform.position,
									scale = 1.5f
								}, true);
							}
							CharacterBody component = ((Component)self).GetComponent<CharacterBody>();
							if ((Object)(object)component != (Object)null && (Object)(object)component.master != (Object)null)
							{
								Object.Destroy((Object)(object)((Component)component.master).gameObject, 0.05f);
							}
							NetworkServer.Destroy(((Component)self).gameObject);
						}
					}
					else
					{
						orig.Invoke(self);
					}
				};
				<>c.<>9__85_4 = val5;
				obj5 = (object)val5;
			}
			CharacterDeathBehavior.OnDeath += (hook_OnDeath)obj5;
			object obj6 = <>c.<>9__85_5;
			if (obj6 == null)
			{
				hook_Awake val6 = delegate(orig_Awake orig, PlayerCharacterMasterController self)
				{
					orig.Invoke(self);
					if ((Object)(object)self.master != (Object)null && EnableMode.Value)
					{
						self.master.preventGameOver = true;
					}
					if ((Object)(object)((Component)self).gameObject.GetComponent<PlayerBuildController>() == (Object)null)
					{
						((Component)self).gameObject.AddComponent<PlayerBuildController>();
					}
				};
				<>c.<>9__85_5 = val6;
				obj6 = (object)val6;
			}
			PlayerCharacterMasterController.Awake += (hook_Awake)obj6;
			object obj7 = <>c.<>9__85_6;
			if (obj7 == null)
			{
				hook_OnEnable val7 = delegate(orig_OnEnable orig, AllyCardManager self)
				{
					orig.Invoke(self);
					if (EnableMode.Value && (Object)(object)self != (Object)null)
					{
						CanvasGroup val10 = ((Component)self).GetComponent<CanvasGroup>();
						if ((Object)(object)val10 == (Object)null)
						{
							val10 = ((Component)self).gameObject.AddComponent<CanvasGroup>();
						}
						val10.alpha = 0f;
						val10.blocksRaycasts = false;
						val10.interactable = false;
					}
				};
				<>c.<>9__85_6 = val7;
				obj7 = (object)val7;
			}
			AllyCardManager.OnEnable += (hook_OnEnable)obj7;
			objec