Decompiled source of H3TVR v1.1.8

H3TVR.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Steamworks;
using UnityEngine;
using UnityEngine.UI;
using Valve.VR;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace H3TVR
{
	public enum SpawnPriority
	{
		Low,
		Normal,
		High,
		Immediate
	}
	public class AdvancedChatSosigSpawner : MonoBehaviour
	{
		public struct ChatSosigStats
		{
			public int ActiveAllies;

			public int ActiveEnemies;

			public int QueueLength;

			public int TotalSpawned;
		}

		public struct SosigStats
		{
			public int Allies;

			public int Enemies;

			public int Queued;

			public int TotalActive;

			public bool ChatWatcherActive;
		}

		[CompilerGenerated]
		private sealed class <CleanupCoroutine>d__73 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public AdvancedChatSosigSpawner <>4__this;

			private WaitForSeconds <wait>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <CleanupCoroutine>d__73(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<wait>5__1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<wait>5__1 = new WaitForSeconds(10f);
					break;
				case 1:
					<>1__state = -1;
					<>4__this.CleanupDeadSosigs();
					break;
				}
				<>2__current = <wait>5__1;
				<>1__state = 1;
				return true;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <DelayedInitialization>d__50 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public AdvancedChatSosigSpawner <>4__this;

			private float <timeout>5__1;

			private float <elapsed>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <DelayedInitialization>d__50(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<timeout>5__1 = 10f;
					<elapsed>5__2 = 0f;
					goto IL_007a;
				case 1:
					<>1__state = -1;
					<elapsed>5__2 += 0.5f;
					goto IL_007a;
				case 2:
					{
						<>1__state = -1;
						<>4__this.BuildTemplateCache();
						ManualLogSource logger = <>4__this.logger;
						if (logger != null)
						{
							logger.LogInfo((object)"Delayed initialization complete - Template cache ready");
						}
						return false;
					}
					IL_007a:
					if ((Object)(object)ManagerSingleton<IM>.Instance == (Object)null && <elapsed>5__2 < <timeout>5__1)
					{
						<>2__current = (object)new WaitForSeconds(0.5f);
						<>1__state = 1;
						return true;
					}
					if ((Object)(object)ManagerSingleton<IM>.Instance == (Object)null)
					{
						ManualLogSource logger2 = <>4__this.logger;
						if (logger2 != null)
						{
							logger2.LogError((object)"IM.Instance failed to initialize within timeout");
						}
						return false;
					}
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <InitializeChatWatcher>d__48 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public AdvancedChatSosigSpawner <>4__this;

			private GameObject <chatWatcherGO>5__1;

			private Exception <ex>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <InitializeChatWatcher>d__48(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<chatWatcherGO>5__1 = null;
				<ex>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(0.5f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					try
					{
						<>4__this.chatWatcher = Object.FindObjectOfType<ChatWatcher>();
						if ((Object)(object)<>4__this.chatWatcher == (Object)null)
						{
							<chatWatcherGO>5__1 = new GameObject("H3TVR_ChatWatcher");
							<>4__this.chatWatcher = <chatWatcherGO>5__1.AddComponent<ChatWatcher>();
							<>4__this.chatWatcher.Initialize(<>4__this.plugin, <>4__this.logger, <>4__this);
							Object.DontDestroyOnLoad((Object)(object)<chatWatcherGO>5__1);
							<>4__this.chatWatcherEnabled = true;
							ManualLogSource logger = <>4__this.logger;
							if (logger != null)
							{
								logger.LogInfo((object)"ChatWatcher integration enabled - file-based chat spawning active");
							}
							<chatWatcherGO>5__1 = null;
						}
						else
						{
							<>4__this.chatWatcherEnabled = true;
							ManualLogSource logger2 = <>4__this.logger;
							if (logger2 != null)
							{
								logger2.LogInfo((object)"ChatWatcher already exists - using existing instance");
							}
						}
					}
					catch (Exception ex)
					{
						<ex>5__2 = ex;
						ManualLogSource logger3 = <>4__this.logger;
						if (logger3 != null)
						{
							logger3.LogError((object)("Failed to initialize ChatWatcher: " + <ex>5__2.Message));
						}
						<>4__this.chatWatcherEnabled = false;
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <LinkSteamFriendsIntegration>d__49 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public AdvancedChatSosigSpawner <>4__this;

			private SteamFriendsIntegration <steamIntegration>5__1;

			private Exception <ex>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LinkSteamFriendsIntegration>d__49(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<steamIntegration>5__1 = null;
				<ex>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					try
					{
						<steamIntegration>5__1 = <>4__this.plugin?.GetSteamFriendsIntegration();
						if ((Object)(object)<steamIntegration>5__1 != (Object)null && <steamIntegration>5__1.IsAvailable())
						{
							<>4__this.steamFriends = <steamIntegration>5__1;
							ManualLogSource logger = <>4__this.logger;
							if (logger != null)
							{
								logger.LogInfo((object)"Steam Friends integration linked successfully");
							}
						}
						else
						{
							ManualLogSource logger2 = <>4__this.logger;
							if (logger2 != null)
							{
								logger2.LogInfo((object)"Steam Friends integration not available");
							}
						}
						<steamIntegration>5__1 = null;
					}
					catch (Exception ex)
					{
						<ex>5__2 = ex;
						ManualLogSource logger3 = <>4__this.logger;
						if (logger3 != null)
						{
							logger3.LogWarning((object)("Failed to link Steam Friends integration: " + <ex>5__2.Message));
						}
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <LoadTemplatesDelayed>d__54 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public AdvancedChatSosigSpawner <>4__this;

			private SosigEnemyTemplate[] <sosigObjects>5__1;

			private SosigEnemyTemplate[] <>s__2;

			private int <>s__3;

			private SosigEnemyTemplate <template>5__4;

			private Exception <ex>5__5;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadTemplatesDelayed>d__54(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<sosigObjects>5__1 = null;
				<>s__2 = null;
				<template>5__4 = null;
				<ex>5__5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					try
					{
						<sosigObjects>5__1 = Resources.FindObjectsOfTypeAll<SosigEnemyTemplate>();
						if (<sosigObjects>5__1 != null && <sosigObjects>5__1.Length != 0)
						{
							<>4__this.cachedSosigTemplates = <sosigObjects>5__1;
							<>s__2 = <>4__this.cachedSosigTemplates;
							for (<>s__3 = 0; <>s__3 < <>s__2.Length; <>s__3++)
							{
								<template>5__4 = <>s__2[<>s__3];
								if ((Object)(object)<template>5__4 != (Object)null)
								{
									<>4__this.allyTemplates.Add(<template>5__4);
									<>4__this.enemyTemplates.Add(<template>5__4);
								}
								<template>5__4 = null;
							}
							<>s__2 = null;
							ManualLogSource logger = <>4__this.logger;
							if (logger != null)
							{
								logger.LogInfo((object)$"Loaded {<>4__this.allyTemplates.Count} legacy sosig templates (fallback)");
							}
						}
						else
						{
							ManualLogSource logger2 = <>4__this.logger;
							if (logger2 != null)
							{
								logger2.LogWarning((object)"No legacy sosig templates found - using modern spawn system only");
							}
						}
						<sosigObjects>5__1 = null;
					}
					catch (Exception ex)
					{
						<ex>5__5 = ex;
						ManualLogSource logger3 = <>4__this.logger;
						if (logger3 != null)
						{
							logger3.LogError((object)("Template loading failed: " + <ex>5__5.Message));
						}
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <UpdateSosigsCoroutine>d__70 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public AdvancedChatSosigSpawner <>4__this;

			private WaitForSeconds <wait>5__1;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <UpdateSosigsCoroutine>d__70(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<wait>5__1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<wait>5__1 = new WaitForSeconds(1f);
					break;
				case 1:
					<>1__state = -1;
					<>4__this.UpdateAllySosigs();
					<>4__this.UpdateEnemySosigs();
					break;
				}
				<>2__current = <wait>5__1;
				<>1__state = 1;
				return true;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static List<Sosig> spawnedChatters = new List<Sosig>();

		public static List<Sosig> spawnedEnemyChatters = new List<Sosig>();

		private H3TVRImproved plugin;

		private ManualLogSource logger;

		private SteamFriendsIntegration steamFriends;

		private ChatWatcher chatWatcher;

		private bool chatWatcherEnabled = false;

		[Header("Sosig Templates")]
		public SosigEnemyID defaultAllyID = (SosigEnemyID)100;

		public SosigEnemyID defaultEnemyID = (SosigEnemyID)108;

		public List<SosigEnemyTemplate> allyTemplates = new List<SosigEnemyTemplate>();

		public List<SosigEnemyTemplate> enemyTemplates = new List<SosigEnemyTemplate>();

		private SosigEnemyTemplate[] cachedSosigTemplates;

		private List<SosigEnemyID> allyPoolIDs = new List<SosigEnemyID>();

		private List<SosigEnemyID> enemyPoolIDs = new List<SosigEnemyID>();

		public GameObject nameplateAlly;

		public GameObject nameplateEnemy;

		public string SpawnerName = "ChatUser";

		private List<string> allyNames = new List<string>();

		private List<string> enemyNames = new List<string>();

		private ConfigEntry<int> maxAllySosigs;

		private ConfigEntry<int> maxEnemySosigs;

		private ConfigEntry<float> spawnCooldown;

		private ConfigEntry<bool> enableNameplates;

		private ConfigEntry<float> sosigLifetime;

		private ConfigEntry<bool> enableAutoCleanup;

		private ConfigEntry<float> enemyIFF;

		private ConfigEntry<float> followDistance;

		private ConfigEntry<float> enemyAggressionDistance;

		private ConfigEntry<bool> useModernSpawnSystem;

		private ConfigEntry<string> allySosigPool;

		private ConfigEntry<string> enemySosigPool;

		private ConfigEntry<bool> enableArmorCustomization;

		private ConfigEntry<string> allyNamesFilePath;

		private ConfigEntry<string> enemyNamesFilePath;

		private ConfigEntry<bool> useRandomNames;

		private ConfigEntry<int> maxSosigsPerUser;

		private ConfigEntry<bool> enableCoverAI;

		private ConfigEntry<float> sosigUpdateInterval;

		private ConfigEntry<bool> enableChatWatcherIntegration;

		private float lastSpawnTime;

		private static readonly LayerMask EnvironmentMask = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { "Environment" }));

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

		private Dictionary<string, float> userLastSpawnTime = new Dictionary<string, float>();

		private Dictionary<SosigEnemyID, SosigEnemyTemplate> templateCache = new Dictionary<SosigEnemyID, SosigEnemyTemplate>();

		public static AdvancedChatSosigSpawner Instance { get; private set; }

		public void Initialize(H3TVRImproved pluginInstance, ManualLogSource logSource)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			Instance = this;
			plugin = pluginInstance;
			logger = logSource;
			InitializeConfiguration();
			InitializeSosigTemplates();
			ManualLogSource obj = logger;
			if (obj != null)
			{
				obj.LogInfo((object)"Advanced Chat Sosig Spawner initialized (Update 120 TNH System, ChatWatcher compatible)");
			}
			((MonoBehaviour)this).StartCoroutine(DelayedInitialization());
			((MonoBehaviour)this).StartCoroutine(UpdateSosigsCoroutine());
			((MonoBehaviour)this).StartCoroutine(CleanupCoroutine());
			((MonoBehaviour)this).StartCoroutine(LinkSteamFriendsIntegration());
			if (enableChatWatcherIntegration.Value)
			{
				((MonoBehaviour)this).StartCoroutine(InitializeChatWatcher());
			}
		}

		private IEnumerator InitializeChatWatcher()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <InitializeChatWatcher>d__48(0)
			{
				<>4__this = this
			};
		}

		private IEnumerator LinkSteamFriendsIntegration()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LinkSteamFriendsIntegration>d__49(0)
			{
				<>4__this = this
			};
		}

		private IEnumerator DelayedInitialization()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedInitialization>d__50(0)
			{
				<>4__this = this
			};
		}

		private void InitializeConfiguration()
		{
			H3TVRImproved h3TVRImproved = plugin;
			if (((h3TVRImproved != null) ? ((BaseUnityPlugin)h3TVRImproved).Config : null) == null)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)"Plugin config is null");
				}
				return;
			}
			try
			{
				maxAllySosigs = ((BaseUnityPlugin)plugin).Config.Bind<int>("Chat Spawner", "MaxAllySosigs", 8, "Maximum ally sosigs");
				maxEnemySosigs = ((BaseUnityPlugin)plugin).Config.Bind<int>("Chat Spawner", "MaxEnemySosigs", 8, "Maximum enemy sosigs");
				spawnCooldown = ((BaseUnityPlugin)plugin).Config.Bind<float>("Chat Spawner", "SpawnCooldown", 2f, "Cooldown between spawns");
				enableNameplates = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Chat Spawner", "EnableNameplates", true, "Show nameplates above sosigs");
				sosigLifetime = ((BaseUnityPlugin)plugin).Config.Bind<float>("Chat Spawner", "SosigLifetime", 300f, "Sosig lifetime in seconds (0 = infinite)");
				enableAutoCleanup = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Chat Spawner", "EnableAutoCleanup", true, "Auto cleanup dead sosigs");
				enemyIFF = ((BaseUnityPlugin)plugin).Config.Bind<float>("Chat Spawner", "EnemyIFF", 1f, "Enemy IFF code");
				followDistance = ((BaseUnityPlugin)plugin).Config.Bind<float>("Chat Spawner", "FollowDistance", 6f, "Distance for allies to follow player");
				enemyAggressionDistance = ((BaseUnityPlugin)plugin).Config.Bind<float>("Chat Spawner", "EnemyAggressionDistance", 20f, "Distance at which enemies become aggressive");
				useModernSpawnSystem = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Chat Spawner", "UseModernSpawnSystem", true, "Use Update 120's modern TNH sosig spawn system (recommended)");
				allySosigPool = ((BaseUnityPlugin)plugin).Config.Bind<string>("Chat Spawner", "AllySosigPool", "M_Swat_Scout,M_Swat_Sniper,M_Swat_Breacher", "Comma-separated list of SosigEnemyID names for allies\nValid IDs include: M_Swat_Scout, M_Swat_Sniper, M_Swat_Breacher, M_Swat_Heavy, M_Swat_Riot, M_Merc_Scout, M_Merc_Sniper, M_Merc_Heavy, M_Zombies_Melee, M_Zombies_Ranged, M_Soldier_Scout, M_Soldier_Sniper, M_Soldier_Heavy, and many more. Check H3VR's SosigEnemyID enum for complete list.");
				enemySosigPool = ((BaseUnityPlugin)plugin).Config.Bind<string>("Chat Spawner", "EnemySosigPool", "M_Swat_Heavy,M_Swat_Breacher,M_Swat_Sniper", "Comma-separated list of SosigEnemyID names for enemies\nValid IDs include: M_Swat_Heavy, M_Swat_Riot, M_Swat_Breacher, M_Merc_Heavy, M_Zombies_Ranged, M_Soldier_Heavy, M_PMC_Heavy, and many more. Check H3VR's SosigEnemyID enum for complete list.");
				enableArmorCustomization = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Chat Spawner Advanced", "EnableArmorCustomization", true, "Enable armor customization system");
				allyNamesFilePath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Chat Spawner Advanced", "AllyNamesFilePath", "Plugins/H3TwitchTools/AllyNames.ini", "File path for ally names list (INI file)");
				enemyNamesFilePath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Chat Spawner Advanced", "EnemyNamesFilePath", "Plugins/H3TwitchTools/EnemyNames.ini", "File path for enemy names list (INI file)");
				useRandomNames = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Chat Spawner Advanced", "UseRandomNames", true, "Use random names from name lists");
				maxSosigsPerUser = ((BaseUnityPlugin)plugin).Config.Bind<int>("Chat Spawner Advanced", "MaxSosigsPerUser", 2, "Maximum sosigs per Twitch user");
				enableCoverAI = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Chat Spawner Advanced", "EnableCoverAI", true, "Enable advanced cover-taking AI behavior");
				sosigUpdateInterval = ((BaseUnityPlugin)plugin).Config.Bind<float>("Chat Spawner Advanced", "UpdateInterval", 1f, "Interval between sosig AI updates (seconds)");
				enableChatWatcherIntegration = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Chat Spawner Integration", "EnableChatWatcher", true, "Enable ChatWatcher integration for file-based Twitch chat spawning\nWhen enabled, sosigs will spawn automatically from chat files (H3TwitchTools compatible)");
				ManualLogSource obj2 = logger;
				if (obj2 != null)
				{
					obj2.LogInfo((object)"Configuration initialized successfully (ChatWatcher integration ready)");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj3 = logger;
				if (obj3 != null)
				{
					obj3.LogError((object)("Config init failed: " + ex.Message));
				}
			}
		}

		private void InitializeSosigTemplates()
		{
			try
			{
				InitializeSosigPools();
				((MonoBehaviour)this).StartCoroutine(LoadTemplatesDelayed());
				BuildTemplateCache();
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("Template initialization failed: " + ex.Message));
				}
			}
		}

		private void InitializeSosigPools()
		{
			//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_004f: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string[] array = allySosigPool.Value.Split(new char[1] { ',' });
				string[] array2 = array;
				foreach (string text in array2)
				{
					try
					{
						SosigEnemyID item = (SosigEnemyID)Enum.Parse(typeof(SosigEnemyID), text.Trim());
						allyPoolIDs.Add(item);
					}
					catch
					{
						ManualLogSource obj = logger;
						if (obj != null)
						{
							obj.LogWarning((object)("Invalid ally sosig ID: " + text));
						}
					}
				}
				string[] array3 = enemySosigPool.Value.Split(new char[1] { ',' });
				string[] array4 = array3;
				foreach (string text2 in array4)
				{
					try
					{
						SosigEnemyID item2 = (SosigEnemyID)Enum.Parse(typeof(SosigEnemyID), text2.Trim());
						enemyPoolIDs.Add(item2);
					}
					catch
					{
						ManualLogSource obj3 = logger;
						if (obj3 != null)
						{
							obj3.LogWarning((object)("Invalid enemy sosig ID: " + text2));
						}
					}
				}
				if (allyPoolIDs.Count == 0)
				{
					allyPoolIDs.Add((SosigEnemyID)100);
					allyPoolIDs.Add((SosigEnemyID)102);
				}
				if (enemyPoolIDs.Count == 0)
				{
					enemyPoolIDs.Add((SosigEnemyID)108);
					enemyPoolIDs.Add((SosigEnemyID)109);
				}
				ManualLogSource obj5 = logger;
				if (obj5 != null)
				{
					obj5.LogInfo((object)$"Loaded {allyPoolIDs.Count} ally sosig types, {enemyPoolIDs.Count} enemy sosig types");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj6 = logger;
				if (obj6 != null)
				{
					obj6.LogError((object)("Failed to initialize sosig pools: " + ex.Message));
				}
				allyPoolIDs.Add((SosigEnemyID)100);
				enemyPoolIDs.Add((SosigEnemyID)108);
			}
		}

		private IEnumerator LoadTemplatesDelayed()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadTemplatesDelayed>d__54(0)
			{
				<>4__this = this
			};
		}

		private void LoadNameLists()
		{
			try
			{
				if (File.Exists(allyNamesFilePath.Value))
				{
					string[] array = File.ReadAllLines(allyNamesFilePath.Value);
					string[] array2 = array;
					foreach (string text in array2)
					{
						string text2 = text.Trim();
						if (!string.IsNullOrEmpty(text2) && !text2.StartsWith("#") && !text2.StartsWith(";"))
						{
							allyNames.Add(text2);
						}
					}
					ManualLogSource obj = logger;
					if (obj != null)
					{
						obj.LogInfo((object)$"Loaded {allyNames.Count} ally names");
					}
				}
				else
				{
					ManualLogSource obj2 = logger;
					if (obj2 != null)
					{
						obj2.LogWarning((object)("Ally names file not found: " + allyNamesFilePath.Value));
					}
					CreateDefaultNameFile(allyNamesFilePath.Value, isAlly: true);
				}
				if (File.Exists(enemyNamesFilePath.Value))
				{
					string[] array3 = File.ReadAllLines(enemyNamesFilePath.Value);
					string[] array4 = array3;
					foreach (string text3 in array4)
					{
						string text4 = text3.Trim();
						if (!string.IsNullOrEmpty(text4) && !text4.StartsWith("#") && !text4.StartsWith(";"))
						{
							enemyNames.Add(text4);
						}
					}
					ManualLogSource obj3 = logger;
					if (obj3 != null)
					{
						obj3.LogInfo((object)$"Loaded {enemyNames.Count} enemy names");
					}
				}
				else
				{
					ManualLogSource obj4 = logger;
					if (obj4 != null)
					{
						obj4.LogWarning((object)("Enemy names file not found: " + enemyNamesFilePath.Value));
					}
					CreateDefaultNameFile(enemyNamesFilePath.Value, isAlly: false);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj5 = logger;
				if (obj5 != null)
				{
					obj5.LogError((object)("Failed to load name lists: " + ex.Message));
				}
			}
		}

		private void CreateDefaultNameFile(string path, bool isAlly)
		{
			try
			{
				string directoryName = Path.GetDirectoryName(path);
				if (!Directory.Exists(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				string[] array = ((!isAlly) ? new string[6] { "# Enemy Sosig Names", "Hostile Bot", "Attacker", "Enemy", "Threat", "Opponent" } : new string[6] { "# Ally Sosig Names", "Friendly Bot", "Guardian", "Protector", "Ally", "Helper" });
				File.WriteAllLines(path, array);
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogInfo((object)("Created default name file: " + path));
				}
				if (isAlly)
				{
					allyNames.AddRange(array.Skip(1));
				}
				else
				{
					enemyNames.AddRange(array.Skip(1));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj2 = logger;
				if (obj2 != null)
				{
					obj2.LogError((object)("Failed to create default name file: " + ex.Message));
				}
			}
		}

		public void SpawningSequence(string username)
		{
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: 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_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (spawnedChatters.Count >= maxAllySosigs.Value)
				{
					ManualLogSource obj = logger;
					if (obj != null)
					{
						obj.LogWarning((object)$"Max ally sosigs reached ({maxAllySosigs.Value}) - cannot spawn for {username}");
					}
					return;
				}
				if (Time.time - lastSpawnTime < spawnCooldown.Value)
				{
					ManualLogSource obj2 = logger;
					if (obj2 != null)
					{
						obj2.LogWarning((object)$"Spawn cooldown active ({spawnCooldown.Value}s) - skipping {username}");
					}
					return;
				}
				if (userSosigCounts.ContainsKey(username) && userSosigCounts[username] >= maxSosigsPerUser.Value)
				{
					ManualLogSource obj3 = logger;
					if (obj3 != null)
					{
						obj3.LogWarning((object)$"User {username} has reached max sosigs limit ({maxSosigsPerUser.Value})");
					}
					return;
				}
				Vector3 pos = CalculateAllySpawnPoint();
				Quaternion identity = Quaternion.identity;
				Sosig val = null;
				if (useModernSpawnSystem.Value)
				{
					SosigEnemyID randomAllyID = GetRandomAllyID();
					val = SpawnSosigModern(randomAllyID, pos, identity, 0);
				}
				if ((Object)(object)val == (Object)null)
				{
					SosigEnemyTemplate randomTemplate = GetRandomTemplate(isAlly: true);
					if ((Object)(object)randomTemplate != (Object)null)
					{
						val = SpawnSosigLegacy(randomTemplate, pos, identity, 0);
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					SetupAllyBehavior(val);
					string text = username;
					if (useRandomNames.Value)
					{
						text = GetRandomName(isAlly: true);
						ManualLogSource obj4 = logger;
						if (obj4 != null)
						{
							obj4.LogInfo((object)("Using random ally name from INI: " + text + " (spawned by " + username + ")"));
						}
					}
					if (enableNameplates.Value && (Object)(object)nameplateAlly != (Object)null)
					{
						AttachNameplate(val, text, nameplateAlly, isEnemy: false);
					}
					spawnedChatters.Add(val);
					lastSpawnTime = Time.time;
					if (userSosigCounts.ContainsKey(username))
					{
						userSosigCounts[username]++;
					}
					else
					{
						userSosigCounts.Add(username, 1);
					}
					ManualLogSource obj5 = logger;
					if (obj5 != null)
					{
						obj5.LogInfo((object)$"✓ Spawned ally sosig '{text}' for {username} ({spawnedChatters.Count}/{maxAllySosigs.Value})");
					}
				}
				else
				{
					ManualLogSource obj6 = logger;
					if (obj6 != null)
					{
						obj6.LogError((object)("Failed to spawn ally sosig for " + username));
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj7 = logger;
				if (obj7 != null)
				{
					obj7.LogError((object)("Ally spawn failed for " + username + ": " + ex.Message));
				}
			}
		}

		public void SpawningSequenceEnemy(int IFF, string username)
		{
			//IL_00a8: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_00eb: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (spawnedEnemyChatters.Count >= maxEnemySosigs.Value)
				{
					ManualLogSource obj = logger;
					if (obj != null)
					{
						obj.LogWarning((object)$"Max enemy sosigs reached ({maxEnemySosigs.Value}) - cannot spawn for {username}");
					}
					return;
				}
				if (Time.time - lastSpawnTime < spawnCooldown.Value)
				{
					ManualLogSource obj2 = logger;
					if (obj2 != null)
					{
						obj2.LogWarning((object)$"Spawn cooldown active ({spawnCooldown.Value}s) - skipping {username}");
					}
					return;
				}
				Vector3 pos = CalculateEnemySpawnPoint();
				Quaternion identity = Quaternion.identity;
				int iFF = ((IFF > 0) ? IFF : Mathf.Max(1, (int)enemyIFF.Value));
				Sosig val = null;
				if (useModernSpawnSystem.Value)
				{
					SosigEnemyID randomEnemyID = GetRandomEnemyID();
					val = SpawnSosigModern(randomEnemyID, pos, identity, iFF);
				}
				if ((Object)(object)val == (Object)null)
				{
					SosigEnemyTemplate randomTemplate = GetRandomTemplate(isAlly: false);
					if ((Object)(object)randomTemplate != (Object)null)
					{
						val = SpawnSosigLegacy(randomTemplate, pos, identity, iFF);
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					SetupEnemyBehavior(val);
					string text = username;
					if (useRandomNames.Value)
					{
						text = GetRandomName(isAlly: false);
						ManualLogSource obj3 = logger;
						if (obj3 != null)
						{
							obj3.LogInfo((object)("Using random enemy name from INI: " + text + " (spawned by " + username + ")"));
						}
					}
					if (enableNameplates.Value && (Object)(object)nameplateEnemy != (Object)null)
					{
						AttachNameplate(val, text, nameplateEnemy, isEnemy: true);
					}
					spawnedEnemyChatters.Add(val);
					lastSpawnTime = Time.time;
					ManualLogSource obj4 = logger;
					if (obj4 != null)
					{
						obj4.LogInfo((object)$"✓ Spawned enemy sosig '{text}' for {username} ({spawnedEnemyChatters.Count}/{maxEnemySosigs.Value})");
					}
				}
				else
				{
					ManualLogSource obj5 = logger;
					if (obj5 != null)
					{
						obj5.LogError((object)("Failed to spawn enemy sosig for " + username));
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj6 = logger;
				if (obj6 != null)
				{
					obj6.LogError((object)("Enemy spawn failed for " + username + ": " + ex.Message));
				}
			}
		}

		private Sosig SpawnSosigModern(SosigEnemyID enemyID, Vector3 pos, Quaternion rot, int IFF)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (templateCache == null || templateCache.Count == 0)
				{
					ManualLogSource obj = logger;
					if (obj != null)
					{
						obj.LogWarning((object)"Template cache not ready, attempting to rebuild...");
					}
					BuildTemplateCache();
					if (templateCache.Count == 0)
					{
						ManualLogSource obj2 = logger;
						if (obj2 != null)
						{
							obj2.LogError((object)"Template cache rebuild failed - falling back to legacy spawn");
						}
						return null;
					}
				}
				SosigEnemyTemplate val = null;
				if (templateCache.ContainsKey(enemyID))
				{
					val = templateCache[enemyID];
				}
				if ((Object)(object)val == (Object)null && (Object)(object)ManagerSingleton<IM>.Instance != (Object)null && ManagerSingleton<IM>.Instance.odicSosigObjsByID != null && ManagerSingleton<IM>.Instance.odicSosigObjsByID.ContainsKey(enemyID))
				{
					val = ManagerSingleton<IM>.Instance.odicSosigObjsByID[enemyID];
					templateCache[enemyID] = val;
					ManualLogSource obj3 = logger;
					if (obj3 != null)
					{
						obj3.LogInfo((object)$"Cached template for {enemyID} from IM.Instance");
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource obj4 = logger;
					if (obj4 != null)
					{
						obj4.LogWarning((object)$"Template not in cache for {enemyID}, searching Resources...");
					}
					SosigEnemyTemplate[] array = Resources.FindObjectsOfTypeAll<SosigEnemyTemplate>();
					SosigEnemyTemplate[] array2 = array;
					foreach (SosigEnemyTemplate val2 in array2)
					{
						if ((Object)(object)val2 != (Object)null && val2.SosigEnemyID == enemyID)
						{
							val = val2;
							templateCache[enemyID] = val;
							ManualLogSource obj5 = logger;
							if (obj5 != null)
							{
								obj5.LogInfo((object)$"Found and cached template for {enemyID}");
							}
							break;
						}
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource obj6 = logger;
					if (obj6 != null)
					{
						obj6.LogError((object)$"Could not find template for SosigEnemyID: {enemyID}");
					}
					return null;
				}
				Sosig val3 = SpawnSosigLegacy(val, pos, rot, IFF);
				if ((Object)(object)val3 == (Object)null)
				{
					ManualLogSource obj7 = logger;
					if (obj7 != null)
					{
						obj7.LogError((object)"Modern sosig spawn returned null");
					}
					return null;
				}
				try
				{
					if (val.ConfigTemplates != null && val.ConfigTemplates.Count > 0)
					{
						SosigConfigTemplate val4 = val.ConfigTemplates[Random.Range(0, val.ConfigTemplates.Count)];
						val3.Configure(val4);
					}
				}
				catch (Exception ex)
				{
					ManualLogSource obj8 = logger;
					if (obj8 != null)
					{
						obj8.LogWarning((object)("Failed to apply config template: " + ex.Message));
					}
				}
				val3.E.IFFCode = IFF;
				val3.SetIFF(IFF);
				try
				{
					val3.Inventory.FillAllAmmo();
				}
				catch (Exception ex2)
				{
					ManualLogSource obj9 = logger;
					if (obj9 != null)
					{
						obj9.LogWarning((object)("Failed to fill ammo: " + ex2.Message));
					}
				}
				try
				{
					if (val.OutfitConfig != null && val.OutfitConfig.Count > 0)
					{
						ApplyOutfit(val3, val.OutfitConfig[Random.Range(0, val.OutfitConfig.Count)]);
					}
				}
				catch (Exception ex3)
				{
					ManualLogSource obj10 = logger;
					if (obj10 != null)
					{
						obj10.LogWarning((object)("Failed to apply outfit: " + ex3.Message));
					}
				}
				return val3;
			}
			catch (Exception ex4)
			{
				ManualLogSource obj11 = logger;
				if (obj11 != null)
				{
					obj11.LogError((object)("Modern sosig spawn failed: " + ex4.Message + "\n" + ex4.StackTrace));
				}
				return null;
			}
		}

		private Sosig SpawnSosigLegacy(SosigEnemyTemplate template, Vector3 pos, Quaternion rot, int IFF)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)template == (Object)null || template.SosigPrefabs == null || template.SosigPrefabs.Count == 0)
				{
					ManualLogSource obj = logger;
					if (obj != null)
					{
						obj.LogError((object)"Invalid template");
					}
					return null;
				}
				FVRObject val = template.SosigPrefabs[Random.Range(0, template.SosigPrefabs.Count)];
				if ((Object)(object)((val != null) ? ((AnvilAsset)val).GetGameObject() : null) == (Object)null)
				{
					ManualLogSource obj2 = logger;
					if (obj2 != null)
					{
						obj2.LogError((object)"Invalid prefab");
					}
					return null;
				}
				GameObject val2 = Object.Instantiate<GameObject>(((AnvilAsset)val).GetGameObject(), pos, rot);
				Sosig componentInChildren = val2.GetComponentInChildren<Sosig>();
				if ((Object)(object)componentInChildren == (Object)null)
				{
					Object.Destroy((Object)(object)val2);
					return null;
				}
				if (template.ConfigTemplates != null && template.ConfigTemplates.Count > 0)
				{
					SosigConfigTemplate val3 = template.ConfigTemplates[Random.Range(0, template.ConfigTemplates.Count)];
					if ((Object)(object)val3 != (Object)null)
					{
						componentInChildren.Configure(val3);
					}
				}
				componentInChildren.E.IFFCode = IFF;
				if (IFF < componentInChildren.Priority.IFFChart.Length)
				{
					componentInChildren.Priority.IFFChart[IFF] = true;
				}
				EquipWeapons(componentInChildren, template, pos, rot);
				if (template.OutfitConfig != null && template.OutfitConfig.Count > 0)
				{
					ApplyOutfit(componentInChildren, template.OutfitConfig[Random.Range(0, template.OutfitConfig.Count)]);
				}
				return componentInChildren;
			}
			catch (Exception ex)
			{
				ManualLogSource obj3 = logger;
				if (obj3 != null)
				{
					obj3.LogError((object)("Legacy sosig spawn failed: " + ex.Message));
				}
				return null;
			}
		}

		private void EquipWeapons(Sosig sosig, SosigEnemyTemplate template, Vector3 pos, Quaternion rot)
		{
			//IL_003e: 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_0084: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (template.WeaponOptions != null && template.WeaponOptions.Count > 0)
				{
					EquipWeapon(sosig, template.WeaponOptions[Random.Range(0, template.WeaponOptions.Count)], pos, rot);
				}
				if (template.WeaponOptions_Secondary != null && template.WeaponOptions_Secondary.Count > 0)
				{
					EquipWeapon(sosig, template.WeaponOptions_Secondary[Random.Range(0, template.WeaponOptions_Secondary.Count)], pos, rot);
				}
				if (template.WeaponOptions_Tertiary != null && template.WeaponOptions_Tertiary.Count > 0)
				{
					EquipWeapon(sosig, template.WeaponOptions_Tertiary[Random.Range(0, template.WeaponOptions_Tertiary.Count)], pos, rot);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("Weapon equip failed: " + ex.Message));
				}
			}
		}

		private void EquipWeapon(Sosig sosig, FVRObject weaponObj, Vector3 pos, Quaternion rot)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Invalid comparison between Unknown and I4
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)((weaponObj != null) ? ((AnvilAsset)weaponObj).GetGameObject() : null) == (Object)null)
				{
					return;
				}
				GameObject val = Object.Instantiate<GameObject>(((AnvilAsset)weaponObj).GetGameObject(), pos + Vector3.up * 0.1f, rot);
				SosigWeapon component = val.GetComponent<SosigWeapon>();
				if ((Object)(object)component != (Object)null)
				{
					component.SetAutoDestroy(true);
					component.O.SpawnLockable = false;
					component.SetAmmoClamping(true);
					component.IsShakeReloadable = false;
					if ((int)component.Type == 0)
					{
						sosig.Inventory.FillAmmoWithType(component.AmmoType);
					}
					sosig.Inventory.Init();
					sosig.Inventory.FillAllAmmo();
					sosig.InitHands();
					sosig.ForceEquip(component);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("Weapon equip error: " + ex.Message));
				}
			}
		}

		private void ApplyOutfit(Sosig sosig, SosigOutfitConfig outfit)
		{
			try
			{
				if (!((Object)(object)outfit == (Object)null) && sosig.Links.Count >= 4)
				{
					if (Random.value < outfit.Chance_Headwear)
					{
						SpawnAccessory(outfit.Headwear, sosig.Links[0]);
					}
					if (Random.value < outfit.Chance_Facewear)
					{
						SpawnAccessory(outfit.Facewear, sosig.Links[0]);
					}
					if (Random.value < outfit.Chance_Eyewear)
					{
						SpawnAccessory(outfit.Eyewear, sosig.Links[0]);
					}
					if (Random.value < outfit.Chance_Torsowear)
					{
						SpawnAccessory(outfit.Torsowear, sosig.Links[1]);
					}
					if (Random.value < outfit.Chance_Pantswear)
					{
						SpawnAccessory(outfit.Pantswear, sosig.Links[2]);
					}
					if (sosig.Links.Count > 3 && Random.value < outfit.Chance_Pantswear_Lower)
					{
						SpawnAccessory(outfit.Pantswear_Lower, sosig.Links[3]);
					}
					if (Random.value < outfit.Chance_Backpacks)
					{
						SpawnAccessory(outfit.Backpacks, sosig.Links[1]);
					}
					if (Random.value < outfit.Chance_TorosDecoration)
					{
						SpawnAccessory(outfit.TorosDecoration, sosig.Links[1]);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("Outfit apply failed: " + ex.Message));
				}
			}
		}

		private void SpawnAccessory(List<FVRObject> accessories, SosigLink link)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if (accessories == null || accessories.Count == 0 || (Object)(object)link == (Object)null)
			{
				return;
			}
			try
			{
				FVRObject val = accessories[Random.Range(0, accessories.Count)];
				if (!((Object)(object)((val != null) ? ((AnvilAsset)val).GetGameObject() : null) == (Object)null))
				{
					GameObject val2 = Object.Instantiate<GameObject>(((AnvilAsset)val).GetGameObject(), ((Component)link).transform.position, ((Component)link).transform.rotation);
					val2.transform.SetParent(((Component)link).transform);
					SosigWearable component = val2.GetComponent<SosigWearable>();
					if ((Object)(object)component != (Object)null)
					{
						component.RegisterWearable(link);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("Accessory spawn failed: " + ex.Message));
				}
			}
		}

		private void SetupAllyBehavior(Sosig sosig)
		{
			//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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				FVRPlayerBody currentPlayerBody = GM.CurrentPlayerBody;
				object obj;
				if (currentPlayerBody == null)
				{
					obj = null;
				}
				else
				{
					Transform head = currentPlayerBody.Head;
					obj = ((head != null) ? ((Component)head).transform : null);
				}
				if (!((Object)obj == (Object)null))
				{
					Vector3 position = ((Component)GM.CurrentPlayerBody.Head).transform.position;
					float num = (float)(Random.Range(0, 2) * 2 - 1) * Random.Range(0.75f, 2.5f);
					float num2 = (float)(Random.Range(0, 2) * 2 - 1) * Random.Range(0.75f, 2.5f);
					Vector3 val = default(Vector3);
					((Vector3)(ref val))..ctor(position.x + num, position.y, position.z + num2);
					sosig.CommandAssaultPoint(val);
					sosig.FallbackOrder = (SosigOrder)4;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj2 = logger;
				if (obj2 != null)
				{
					obj2.LogError((object)("Ally behavior setup failed: " + ex.Message));
				}
			}
		}

		private void SetupEnemyBehavior(Sosig sosig)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				FVRPlayerBody currentPlayerBody = GM.CurrentPlayerBody;
				if (!((Object)(object)((currentPlayerBody != null) ? ((Component)currentPlayerBody).transform : null) == (Object)null))
				{
					sosig.CommandAssaultPoint(((Component)GM.CurrentPlayerBody).transform.position);
					sosig.FallbackOrder = (SosigOrder)4;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("Enemy behavior setup failed: " + ex.Message));
				}
			}
		}

		private void AttachNameplate(Sosig sosig, string name, GameObject nameplatePrefab, bool isEnemy)
		{
			//IL_0057: 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)
			try
			{
				if (sosig.Links.Count != 0 && !((Object)(object)nameplatePrefab == (Object)null))
				{
					SpawnerName = name;
					GameObject val = Object.Instantiate<GameObject>(nameplatePrefab, ((Component)sosig.Links[0]).transform, false);
					val.transform.localPosition = new Vector3(0f, 0.3f, 0f);
					val.transform.localRotation = Quaternion.identity;
					Text[] componentsInChildren = val.GetComponentsInChildren<Text>();
					Text[] array = componentsInChildren;
					foreach (Text val2 in array)
					{
						val2.text = name;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("Nameplate attach failed: " + ex.Message));
				}
			}
		}

		private Vector3 CalculateAllySpawnPoint()
		{
			//IL_0040: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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)
			FVRPlayerBody currentPlayerBody = GM.CurrentPlayerBody;
			object obj;
			if (currentPlayerBody == null)
			{
				obj = null;
			}
			else
			{
				Transform head = currentPlayerBody.Head;
				obj = ((head != null) ? ((Component)head).transform : null);
			}
			if ((Object)obj == (Object)null)
			{
				return Vector3.zero;
			}
			Vector3 position = ((Component)GM.CurrentPlayerBody.Head).transform.position;
			float num = Random.Range(0f, 360f) * ((float)Math.PI / 180f);
			float num2 = Random.Range(2f, 4f);
			return new Vector3(position.x + Mathf.Cos(num) * num2, position.y, position.z + Mathf.Sin(num) * num2);
		}

		private Vector3 CalculateEnemySpawnPoint()
		{
			//IL_0040: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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)
			FVRPlayerBody currentPlayerBody = GM.CurrentPlayerBody;
			object obj;
			if (currentPlayerBody == null)
			{
				obj = null;
			}
			else
			{
				Transform head = currentPlayerBody.Head;
				obj = ((head != null) ? ((Component)head).transform : null);
			}
			if ((Object)obj == (Object)null)
			{
				return Vector3.zero;
			}
			Vector3 position = ((Component)GM.CurrentPlayerBody.Head).transform.position;
			float num = Random.Range(0f, 360f) * ((float)Math.PI / 180f);
			float num2 = Random.Range(8f, 15f);
			return new Vector3(position.x + Mathf.Cos(num) * num2, position.y, position.z + Mathf.Sin(num) * num2);
		}

		private IEnumerator UpdateSosigsCoroutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <UpdateSosigsCoroutine>d__70(0)
			{
				<>4__this = this
			};
		}

		private void UpdateAllySosigs()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Invalid comparison between Unknown and I4
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)GM.CurrentPlayerBody?.Head == (Object)null)
			{
				return;
			}
			Vector3 val2 = default(Vector3);
			for (int num = spawnedChatters.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)spawnedChatters[num] == (Object)null || (int)spawnedChatters[num].BodyState == 3)
				{
					if (enableAutoCleanup.Value && (Object)(object)spawnedChatters[num] != (Object)null)
					{
						spawnedChatters[num].TickDownToClear(3f);
					}
					spawnedChatters.RemoveAt(num);
				}
				else
				{
					Sosig val = spawnedChatters[num];
					if (!val.m_isStunned)
					{
						Vector3 position = GM.CurrentPlayerBody.Head.position;
						float num2 = Vector3.Distance(position, val.m_assaultPoint);
						if (num2 > followDistance.Value)
						{
							float num3 = (float)(Random.Range(0, 2) * 2 - 1) * Random.Range(0.75f, 2.5f);
							float num4 = (float)(Random.Range(0, 2) * 2 - 1) * Random.Range(0.75f, 2.5f);
							((Vector3)(ref val2))..ctor(position.x + num3, position.y, position.z + num4);
							if (!Physics.Linecast(position, val2, LayerMask.op_Implicit(EnvironmentMask)))
							{
								val.CommandAssaultPoint(val2);
							}
						}
					}
					if (val.Priority.HasFreshTarget() && (int)val.CurrentOrder == 3 && val.m_entityRecognition >= 0.65f)
					{
						val.SetCurrentOrder((SosigOrder)2);
					}
				}
			}
		}

		private void UpdateEnemySosigs()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			//IL_00d8: 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_00df: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Invalid comparison between Unknown and I4
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Invalid comparison between Unknown and I4
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Invalid comparison between Unknown and I4
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)GM.CurrentPlayerBody?.Head == (Object)null)
			{
				return;
			}
			for (int i = spawnedEnemyChatters.Count - 1; i >= 0; i++)
			{
				if ((Object)(object)spawnedEnemyChatters[i] == (Object)null || (int)spawnedEnemyChatters[i].BodyState == 3)
				{
					if (enableAutoCleanup.Value && (Object)(object)spawnedEnemyChatters[i] != (Object)null)
					{
						spawnedEnemyChatters[i].TickDownToClear(3f);
					}
					spawnedEnemyChatters.RemoveAt(i);
					continue;
				}
				Sosig val = spawnedEnemyChatters[i];
				if (!val.m_isStunned)
				{
					Vector3 position = GM.CurrentPlayerBody.Head.position;
					float num = Vector3.Distance(position, ((Component)val.Links[1]).transform.position);
					if (num > enemyAggressionDistance.Value)
					{
						val.CommandAssaultPoint(((Component)GM.CurrentPlayerBody).transform.position);
					}
				}
				if (val.Priority.HasFreshTarget() && (int)val.CurrentOrder == 3 && val.m_entityRecognition >= 0.55f)
				{
					val.SetCurrentOrder((SosigOrder)2);
				}
				if ((int)val.CurrentOrder == 0 || (int)val.CurrentOrder == 9 || (int)val.CurrentOrder == 1)
				{
					val.CommandAssaultPoint(((Component)GM.CurrentPlayerBody).transform.position);
				}
			}
		}

		private IEnumerator CleanupCoroutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CleanupCoroutine>d__73(0)
			{
				<>4__this = this
			};
		}

		private void CleanupDeadSosigs()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			if (!enableAutoCleanup.Value)
			{
				return;
			}
			foreach (Sosig item in spawnedChatters.Concat(spawnedEnemyChatters))
			{
				if ((Object)(object)item != (Object)null && (int)item.BodyState == 3)
				{
					item.TickDownToClear(3f);
				}
			}
		}

		public void ClearSosigs(bool clearAllies = true, bool clearEnemies = true)
		{
			try
			{
				int num = 0;
				if (clearAllies)
				{
					for (int num2 = spawnedChatters.Count - 1; num2 >= 0; num2--)
					{
						if ((Object)(object)spawnedChatters[num2] != (Object)null)
						{
							Object.Destroy((Object)(object)((Component)spawnedChatters[num2]).gameObject);
							num++;
						}
					}
					spawnedChatters.Clear();
				}
				if (clearEnemies)
				{
					for (int num3 = spawnedEnemyChatters.Count - 1; num3 >= 0; num3--)
					{
						if ((Object)(object)spawnedEnemyChatters[num3] != (Object)null)
						{
							Object.Destroy((Object)(object)((Component)spawnedEnemyChatters[num3]).gameObject);
							num++;
						}
					}
					spawnedEnemyChatters.Clear();
				}
				userSosigCounts.Clear();
				userLastSpawnTime.Clear();
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogInfo((object)$"Cleared {num} sosigs (ChatWatcher compatible)");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj2 = logger;
				if (obj2 != null)
				{
					obj2.LogError((object)("Clear sosigs failed: " + ex.Message));
				}
			}
		}

		public void ClearAllSosigs()
		{
			ClearSosigs();
			BossSosigSystem.ClearAllBosses();
			if (!chatWatcherEnabled || !((Object)(object)chatWatcher != (Object)null))
			{
				return;
			}
			try
			{
				chatWatcher.ClearCache();
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogWarning((object)("Failed to clear ChatWatcher cache: " + ex.Message));
				}
			}
		}

		public ChatWatcher GetChatWatcher()
		{
			return chatWatcher;
		}

		public bool IsChatWatcherEnabled()
		{
			return chatWatcherEnabled && (Object)(object)chatWatcher != (Object)null;
		}

		public Sosig SpawningSequenceBoss(BossSosigSystem.BossType bossType, string username = null)
		{
			//IL_0082: 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_0088: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (spawnedEnemyChatters.Count >= maxEnemySosigs.Value)
				{
					ManualLogSource obj = logger;
					if (obj != null)
					{
						obj.LogWarning((object)"Max enemy sosigs reached - cannot spawn boss");
					}
					return null;
				}
				if (Time.time - lastSpawnTime < spawnCooldown.Value)
				{
					ManualLogSource obj2 = logger;
					if (obj2 != null)
					{
						obj2.LogWarning((object)"Spawn cooldown active");
					}
					return null;
				}
				Vector3 pos = CalculateBossSpawnPoint();
				Quaternion identity = Quaternion.identity;
				int num = Mathf.Max(1, (int)enemyIFF.Value);
				Sosig val = null;
				if (useModernSpawnSystem.Value)
				{
					SosigEnemyID bossTemplate = GetBossTemplate(bossType);
					val = SpawnSosigModern(bossTemplate, pos, identity, num);
				}
				if ((Object)(object)val == (Object)null)
				{
					SosigEnemyTemplate randomTemplate = GetRandomTemplate(isAlly: false);
					if ((Object)(object)randomTemplate != (Object)null)
					{
						val = SpawnSosigLegacy(randomTemplate, pos, identity, num);
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					SetupEnemyBehavior(val);
					BossSosig bossSosig = ((Component)val).gameObject.AddComponent<BossSosig>();
					bossSosig.Initialize(bossType, logger);
					string text = username ?? $"BOSS_{bossType}";
					if (enableNameplates.Value && (Object)(object)nameplateEnemy != (Object)null)
					{
						AttachNameplate(val, "★ " + text + " ★", nameplateEnemy, isEnemy: true);
					}
					spawnedEnemyChatters.Add(val);
					lastSpawnTime = Time.time;
					ManualLogSource obj3 = logger;
					if (obj3 != null)
					{
						obj3.LogInfo((object)$"Spawned {bossType} BOSS '{text}' (IFF: {num})");
					}
					return val;
				}
				ManualLogSource obj4 = logger;
				if (obj4 != null)
				{
					obj4.LogError((object)"Failed to spawn boss sosig");
				}
				return null;
			}
			catch (Exception ex)
			{
				ManualLogSource obj5 = logger;
				if (obj5 != null)
				{
					obj5.LogError((object)("Boss spawn failed: " + ex.Message));
				}
				return null;
			}
		}

		private Vector3 CalculateBossSpawnPoint()
		{
			//IL_0040: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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)
			FVRPlayerBody currentPlayerBody = GM.CurrentPlayerBody;
			object obj;
			if (currentPlayerBody == null)
			{
				obj = null;
			}
			else
			{
				Transform head = currentPlayerBody.Head;
				obj = ((head != null) ? ((Component)head).transform : null);
			}
			if ((Object)obj == (Object)null)
			{
				return Vector3.zero;
			}
			Vector3 position = ((Component)GM.CurrentPlayerBody.Head).transform.position;
			float num = Random.Range(0f, 360f) * ((float)Math.PI / 180f);
			float num2 = Random.Range(20f, 30f);
			return new Vector3(position.x + Mathf.Cos(num) * num2, position.y, position.z + Mathf.Sin(num) * num2);
		}

		private SosigEnemyID GetBossTemplate(BossSosigSystem.BossType bossType)
		{
			//IL_002b: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			switch (bossType)
			{
			case BossSosigSystem.BossType.Tank:
			case BossSosigSystem.BossType.Juggernaut:
				return (SosigEnemyID)108;
			case BossSosigSystem.BossType.Sniper:
				return (SosigEnemyID)102;
			case BossSosigSystem.BossType.Berserker:
			case BossSosigSystem.BossType.Assassin:
				return (SosigEnemyID)109;
			default:
				return GetRandomEnemyID();
			}
		}

		public void QueueSpawn(string username, string displayName, bool isFriendly, string armorPreset = null, SpawnPriority priority = SpawnPriority.Normal, string behavior = null)
		{
			try
			{
				if (isFriendly)
				{
					SpawningSequence(displayName ?? username);
				}
				else
				{
					SpawningSequenceEnemy((int)enemyIFF.Value, displayName ?? username);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("QueueSpawn failed for " + username + ": " + ex.Message));
				}
			}
		}

		public SosigStats GetStats()
		{
			SosigStats result = default(SosigStats);
			result.Allies = spawnedChatters.Count;
			result.Enemies = spawnedEnemyChatters.Count;
			result.Queued = 0;
			result.TotalActive = spawnedChatters.Count + spawnedEnemyChatters.Count;
			result.ChatWatcherActive = chatWatcherEnabled && (Object)(object)chatWatcher != (Object)null;
			return result;
		}

		public bool QueueTwitchSpawnRequest(string username, string displayName, bool isFriendly, string armorPreset = null, SpawnPriority priority = SpawnPriority.Normal, string requestedBehavior = null)
		{
			try
			{
				string arg = (chatWatcherEnabled ? "ChatWatcher" : "Direct");
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogDebug((object)$"Twitch spawn request from {arg}: {username} (friendly: {isFriendly})");
				}
				if (isFriendly)
				{
					SpawningSequence(displayName ?? username);
				}
				else
				{
					SpawningSequenceEnemy((int)enemyIFF.Value, displayName ?? username);
				}
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource obj2 = logger;
				if (obj2 != null)
				{
					obj2.LogError((object)("Twitch spawn request failed for " + username + ": " + ex.Message));
				}
				return false;
			}
		}

		private void ApplyOutfitModern(Sosig sosig, SosigOutfitConfig outfit)
		{
			try
			{
				if (!((Object)(object)outfit == (Object)null) && sosig.Links.Count >= 4)
				{
					ApplyOutfit(sosig, outfit);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("Modern outfit apply failed: " + ex.Message));
				}
				ApplyOutfit(sosig, outfit);
			}
		}

		private string GetRandomName(bool isAlly)
		{
			if ((Object)(object)steamFriends != (Object)null && steamFriends.IsAvailable() && plugin.UseSteamFriendsRandomNames())
			{
				try
				{
					string randomFriendName = steamFriends.GetRandomFriendName();
					if (!string.IsNullOrEmpty(randomFriendName) && randomFriendName != "Steam Friend")
					{
						ManualLogSource obj = logger;
						if (obj != null)
						{
							obj.LogDebug((object)("Using Steam friend name: " + randomFriendName));
						}
						return randomFriendName;
					}
				}
				catch (Exception ex)
				{
					ManualLogSource obj2 = logger;
					if (obj2 != null)
					{
						obj2.LogWarning((object)("Failed to get Steam friend name: " + ex.Message));
					}
				}
			}
			List<string> list = (isAlly ? allyNames : enemyNames);
			if (list.Count == 0)
			{
				LoadNameLists();
			}
			if (list.Count == 0)
			{
				return isAlly ? "Ally" : "Enemy";
			}
			return list[Random.Range(0, list.Count)];
		}

		private SosigEnemyID GetRandomAllyID()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003b: Unknown result type (might be due to invalid IL or missing references)
			if (allyPoolIDs.Count == 0)
			{
				return defaultAllyID;
			}
			return allyPoolIDs[Random.Range(0, allyPoolIDs.Count)];
		}

		private SosigEnemyID GetRandomEnemyID()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003b: Unknown result type (might be due to invalid IL or missing references)
			if (enemyPoolIDs.Count == 0)
			{
				return defaultEnemyID;
			}
			return enemyPoolIDs[Random.Range(0, enemyPoolIDs.Count)];
		}

		private SosigEnemyTemplate GetRandomTemplate(bool isAlly)
		{
			List<SosigEnemyTemplate> list = (isAlly ? allyTemplates : enemyTemplates);
			if (list == null || list.Count == 0)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogWarning((object)("No " + (isAlly ? "ally" : "enemy") + " templates available"));
				}
				return null;
			}
			return list[Random.Range(0, list.Count)];
		}

		private void BuildTemplateCache()
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)ManagerSingleton<IM>.Instance == (Object)null)
				{
					ManualLogSource obj = logger;
					if (obj != null)
					{
						obj.LogWarning((object)"Cannot build template cache - IM.Instance is null (H3VR not ready)");
					}
					return;
				}
				if (ManagerSingleton<IM>.Instance.odicSosigObjsByID == null)
				{
					ManualLogSource obj2 = logger;
					if (obj2 != null)
					{
						obj2.LogWarning((object)"Cannot build template cache - odicSosigObjsByID is null (H3VR not ready)");
					}
					return;
				}
				int num = 0;
				ManualLogSource obj3 = logger;
				if (obj3 != null)
				{
					obj3.LogInfo((object)"Building template cache from IM.Instance...");
				}
				foreach (SosigEnemyID item in allyPoolIDs.Concat(enemyPoolIDs).Distinct())
				{
					if (ManagerSingleton<IM>.Instance.odicSosigObjsByID.ContainsKey(item))
					{
						SosigEnemyTemplate val = ManagerSingleton<IM>.Instance.odicSosigObjsByID[item];
						if ((Object)(object)val != (Object)null)
						{
							templateCache[item] = val;
							num++;
							ManualLogSource obj4 = logger;
							if (obj4 != null)
							{
								obj4.LogDebug((object)$"  Cached: {item}");
							}
						}
						else
						{
							ManualLogSource obj5 = logger;
							if (obj5 != null)
							{
								obj5.LogWarning((object)$"  Template null for {item}");
							}
						}
					}
					else
					{
						ManualLogSource obj6 = logger;
						if (obj6 != null)
						{
							obj6.LogWarning((object)$"  ID not found in IM: {item}");
						}
					}
				}
				ManualLogSource obj7 = logger;
				if (obj7 != null)
				{
					obj7.LogInfo((object)$"Template cache built: {num}/{allyPoolIDs.Count + enemyPoolIDs.Count} templates loaded");
				}
				ManualLogSource obj8 = logger;
				if (obj8 != null)
				{
					obj8.LogInfo((object)$"Template cache status: {templateCache.Count} total templates");
				}
				ManualLogSource obj9 = logger;
				if (obj9 != null)
				{
					obj9.LogInfo((object)$"  Ally pool: {allyPoolIDs.Count} IDs configured");
				}
				ManualLogSource obj10 = logger;
				if (obj10 != null)
				{
					obj10.LogInfo((object)$"  Enemy pool: {enemyPoolIDs.Count} IDs configured");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj11 = logger;
				if (obj11 != null)
				{
					obj11.LogWarning((object)("Failed to build template cache: " + ex.Message));
				}
				ManualLogSource obj12 = logger;
				if (obj12 != null)
				{
					obj12.LogDebug((object)("Stack trace: " + ex.StackTrace));
				}
			}
		}

		public void OnReceiveNameLists(List<string> allyList, List<string> enemyList)
		{
			try
			{
				allyNames = allyList;
				enemyNames = enemyList;
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogInfo((object)$"Received {allyNames.Count} ally names and {enemyNames.Count} enemy names from ChatWatcher");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj2 = logger;
				if (obj2 != null)
				{
					obj2.LogError((object)("Failed to process received name lists: " + ex.Message));
				}
			}
		}

		public string GetSystemStatus()
		{
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("=== Advanced Chat Sosig Spawner Status ===");
				stringBuilder.AppendLine($"Active Allies: {spawnedChatters.Count}/{maxAllySosigs.Value}");
				stringBuilder.AppendLine($"Active Enemies: {spawnedEnemyChatters.Count}/{maxEnemySosigs.Value}");
				stringBuilder.AppendLine("ChatWatcher: " + (chatWatcherEnabled ? "ACTIVE" : "INACTIVE"));
				stringBuilder.AppendLine("Steam Friends: " + (((Object)(object)steamFriends != (Object)null && steamFriends.IsAvailable()) ? "AVAILABLE" : "N/A"));
				stringBuilder.AppendLine($"Template Cache: {templateCache.Count} templates");
				stringBuilder.AppendLine($"Ally Pool: {allyPoolIDs.Count} types");
				stringBuilder.AppendLine($"Enemy Pool: {enemyPoolIDs.Count} types");
				stringBuilder.AppendLine($"Ally Names: {allyNames.Count} loaded");
				stringBuilder.AppendLine($"Enemy Names: {enemyNames.Count} loaded");
				stringBuilder.AppendLine("Modern Spawn System: " + (useModernSpawnSystem.Value ? "ENABLED" : "DISABLED"));
				stringBuilder.AppendLine("Nameplates: " + (enableNameplates.Value ? "ENABLED" : "DISABLED"));
				stringBuilder.AppendLine($"User Tracking: {userSosigCounts.Count} users");
				stringBuilder.AppendLine("==========================================");
				return stringBuilder.ToString();
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("Failed to get system status: " + ex.Message));
				}
				return "ERROR: Could not get status";
			}
		}

		public void ReloadNameLists()
		{
			try
			{
				allyNames.Clear();
				enemyNames.Clear();
				LoadNameLists();
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogInfo((object)$"Reloaded name lists: {allyNames.Count} allies, {enemyNames.Count} enemies");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj2 = logger;
				if (obj2 != null)
				{
					obj2.LogError((object)("Failed to reload name lists: " + ex.Message));
				}
			}
		}

		public void RebuildTemplateCache()
		{
			try
			{
				templateCache.Clear();
				BuildTemplateCache();
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogInfo((object)$"Rebuilt template cache: {templateCache.Count} templates");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj2 = logger;
				if (obj2 != null)
				{
					obj2.LogError((object)("Failed to rebuild template cache: " + ex.Message));
				}
			}
		}
	}
	public class AdvancedSosigAI : MonoBehaviour
	{
		public enum AIState
		{
			Following,
			Assault,
			TakingCover,
			Suppressing,
			Flanking,
			Retreating,
			HoldingPosition
		}

		[CompilerGenerated]
		private sealed class <AIUpdateLoop>d__41 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public AdvancedSosigAI <>4__this;

			private WaitForSeconds <wait>5__1;

			private Exception <ex>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <AIUpdateLoop>d__41(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<wait>5__1 = null;
				<ex>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fe: Invalid comparison between Unknown and I4
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<wait>5__1 = new WaitForSeconds(2f);
					break;
				case 1:
					<>1__state = -1;
					try
					{
						if (EnableAdvancedAI)
						{
							if (<>4__this.isAlly && PreventFriendlyFire)
							{
								<>4__this.EnforceFriendlyFirePrevention();
							}
							<>4__this.UpdateAIBehavior();
						}
					}
					catch (Exception ex)
					{
						<ex>5__2 = ex;
						ManualLogSource logger = <>4__this.logger;
						if (logger != null)
						{
							logger.LogError((object)("Advanced AI update error: " + <ex>5__2.Message));
						}
					}
					break;
				}
				if (<>4__this.isInitialized && (Object)(object)<>4__this.sosig != (Object)null && (int)<>4__this.sosig.BodyState != 3)
				{
					<>2__current = <wait>5__1;
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private AIState currentState = AIState.Following;

		private Transform coverPoint;

		private float lastStateChangeTime;

		private Vector3 lastKnownEnemyPosition;

		private bool hasLineOfSight;

		private int sosigIFF = -1;

		private bool isAlly = false;

		private Sosig sosig;

		private ManualLogSource logger;

		private bool isInitialized;

		public static bool EnableAdvancedAI { get; set; } = true;


		public static bool EnableCoverSystem { get; set; } = true;


		public static bool EnableSquadCoordination { get; set; } = false;


		public static bool EnableTacticalMovement { get; set; } = true;


		public static float CoverSearchRadius { get; set; } = 15f;


		public static float SuppressionRadius { get; set; } = 10f;


		public static bool PreventFriendlyFire { get; set; } = true;


		public void Initialize(Sosig sosigInstance, ManualLogSource logSource)
		{
			sosig = sosigInstance;
			logger = logSource;
			isInitialized = true;
			if ((Object)(object)sosig != (Object)null)
			{
				sosigIFF = sosig.E.IFFCode;
				isAlly = sosigIFF == 0;
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogDebug((object)$"[AdvancedAI] Initialized for sosig with IFF {sosigIFF} (Ally: {isAlly})");
				}
				if (isAlly && PreventFriendlyFire)
				{
					ConfigureFriendlyFirePrevention();
				}
			}
			if (EnableAdvancedAI)
			{
				((MonoBehaviour)this).StartCoroutine(AIUpdateLoop());
			}
		}

		private void ConfigureFriendlyFirePrevention()
		{
			try
			{
				if (!((Object)(object)sosig == (Object)null) && isAlly)
				{
					sosig.E.IFFCode = 0;
					sosig.SetIFF(0);
					ManualLogSource obj = logger;
					if (obj != null)
					{
						obj.LogDebug((object)"[AdvancedAI] Friendly fire prevention configured for ally sosig");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj2 = logger;
				if (obj2 != null)
				{
					obj2.LogError((object)("[AdvancedAI] Error configuring friendly fire prevention: " + ex.Message));
				}
			}
		}

		private IEnumerator AIUpdateLoop()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <AIUpdateLoop>d__41(0)
			{
				<>4__this = this
			};
		}

		private void EnforceFriendlyFirePrevention()
		{
			try
			{
				if (sosig.E.IFFCode != 0)
				{
					sosig.E.IFFCode = 0;
					sosig.SetIFF(0);
					ManualLogSource obj = logger;
					if (obj != null)
					{
						obj.LogDebug((object)"[AdvancedAI] Reset ally IFF to 0");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj2 = logger;
				if (obj2 != null)
				{
					obj2.LogDebug((object)("[AdvancedAI] Error enforcing friendly fire prevention: " + ex.Message));
				}
			}
		}

		private void UpdateAIBehavior()
		{
			if (!((Object)(object)sosig == (Object)null) && !sosig.m_isStunned)
			{
				UpdateTargetTracking();
				EvaluateState();
				ExecuteCurrentState();
			}
		}

		private void UpdateTargetTracking()
		{
			//IL_001c: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (sosig.Priority.HasFreshTarget())
			{
				Vector3 assaultPoint = sosig.m_assaultPoint;
				if (!IsTargetingPlayer())
				{
					lastKnownEnemyPosition = assaultPoint;
					hasLineOfSight = HasLineOfSight(assaultPoint);
					return;
				}
				hasLineOfSight = false;
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogDebug((object)"[AdvancedAI] Prevented ally from targeting player");
				}
			}
			else
			{
				hasLineOfSight = false;
			}
		}

		private bool IsTargetingPlayer()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!isAlly || (Object)(object)GM.CurrentPlayerBody == (Object)null)
			{
				return false;
			}
			float num = Vector3.Distance(sosig.m_assaultPoint, ((Component)GM.CurrentPlayerBody).transform.position);
			return num < 2f;
		}

		private void EvaluateState()
		{
			if (!(Time.time - lastStateChangeTime < 3f))
			{
				if (isAlly)
				{
					EvaluateAllyState();
				}
				else
				{
					EvaluateEnemyState();
				}
			}
		}

		private void EvaluateAllyState()
		{
			//IL_0039: 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)
			if (!sosig.Priority.HasFreshTarget() || IsTargetingPlayer())
			{
				SetState(AIState.Following);
				return;
			}
			float num = Vector3.Distance(((Component)sosig).transform.position, lastKnownEnemyPosition);
			float healthPercent = GetHealthPercent();
			if (healthPercent < 0.3f && EnableCoverSystem)
			{
				if (FindNearestCover())
				{
					SetState(AIState.TakingCover);
				}
				else
				{
					SetState(AIState.Retreating);
				}
			}
			else if (EnableCoverSystem && num > 8f && healthPercent < 0.6f && FindNearestCover())
			{
				SetState(AIState.TakingCover);
			}
			else
			{
				SetState(AIState.Assault);
			}
		}

		private void EvaluateEnemyState()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!sosig.Priority.HasFreshTarget())
			{
				SetState(AIState.Assault);
				return;
			}
			float num = Vector3.Distance(((Component)sosig).transform.position, lastKnownEnemyPosition);
			float healthPercent = GetHealthPercent();
			if (healthPercent < 0.3f && EnableCoverSystem)
			{
				if (FindNearestCover())
				{
					SetState(AIState.TakingCover);
				}
				else
				{
					SetState(AIState.Retreating);
				}
			}
			else if (num < 8f && healthPercent > 0.5f)
			{
				SetState(AIState.Assault);
			}
			else if (EnableCoverSystem && num > 8f && num < 25f && (!hasLineOfSight || healthPercent < 0.6f) && FindNearestCover())
			{
				SetState(AIState.TakingCover);
			}
			else
			{
				SetState(AIState.Assault);
			}
		}

		private void SetState(AIState newState)
		{
			if (currentState != newState)
			{
				currentState = newState;
				lastStateChangeTime = Time.time;
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogDebug((object)$"Sosig AI state changed to: {newState}");
				}
			}
		}

		private void ExecuteCurrentState()
		{
			if (isAlly && currentState == AIState.Assault && IsTargetingPlayer())
			{
				SetState(AIState.Following);
				return;
			}
			switch (currentState)
			{
			case AIState.Following:
				break;
			case AIState.Assault:
				ExecuteAssault();
				break;
			case AIState.TakingCover:
				ExecuteTakeCover();
				break;
			case AIState.Suppressing:
				ExecuteSuppression();
				break;
			case AIState.Flanking:
				ExecuteFlank();
				break;
			case AIState.Retreating:
				ExecuteRetreat();
				break;
			case AIState.HoldingPosition:
				ExecuteHold();
				break;
			}
		}

		private void ExecuteAssault()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (isAlly && IsTargetingPlayer())
			{
				SetState(AIState.Following);
			}
			else if (!hasLineOfSight && EnableTacticalMovement)
			{
				sosig.CommandAssaultPoint(lastKnownEnemyPosition);
			}
			else
			{
				sosig.SetCurrentOrder((SosigOrder)7);
			}
		}

		private void ExecuteTakeCover()
		{
			//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_004f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)coverPoint != (Object)null)
			{
				float num = Vector3.Distance(((Component)sosig).transform.position, coverPoint.position);
				if (num > 1.5f)
				{
					sosig.CommandAssaultPoint(coverPoint.position);
				}
				else if (hasLineOfSight && (!isAlly || !IsTargetingPlayer()))
				{
					sosig.SetCurrentOrder((SosigOrder)2);
				}
				else
				{
					sosig.SetCurrentOrder((SosigOrder)1);
				}
			}
			else
			{
				SetState(AIState.Assault);
			}
		}

		private void ExecuteSuppression()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (isAlly && IsTargetingPlayer())
			{
				SetState(AIState.Following);
			}
			else if (hasLineOfSight)
			{
				sosig.SetCurrentOrder((SosigOrder)2);
			}
			else
			{
				sosig.CommandAssaultPoint(lastKnownEnemyPosition);
			}
		}

		private void ExecuteFlank()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = CalculateFlankPosition();
			if (val != Vector3.zero)
			{
				sosig.CommandAssaultPoint(val);
			}
			else
			{
				SetState(AIState.Assault);
			}
		}

		private void ExecuteRetreat()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = CalculateRetreatPosition();
			if (val != Vector3.zero)
			{
				sosig.CommandAssaultPoint(val);
			}
			if (GetHealthPercent() > 0.5f)
			{
				SetState(AIState.Assault);
			}
		}

		private void ExecuteHold()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			sosig.SetCurrentOrder((SosigOrder)1);
			if ((!isAlly || !IsTargetingPlayer()) && Vector3.Distance(((Component)sosig).transform.position, lastKnownEnemyPosition) < 10f)
			{
				SetState(AIState.Assault);
			}
		}

		private bool HasLineOfSight(Vector3 targetPosition)
		{
			//IL_0043: 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_0049: 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)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sosig == (Object)null || sosig.Links.Count == 0)
			{
				return false;
			}
			Vector3 position = ((Component)sosig.Links[0]).transform.position;
			Vector3 val = targetPosition - position;
			return !Physics.Raycast(position, ((Vector3)(ref val)).normalized, ((Vector3)(ref val)).magnitude, LayerMask.GetMask(new string[1] { "Environment" }));
		}

		private bool FindNearestCover()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			if (!EnableCoverSystem)
			{
				return false;
			}
			Collider[] array = Physics.OverlapSphere(((Component)sosig).transform.position, CoverSearchRadius);
			float num = float.MaxValue;
			Transform val = null;
			Collider[] array2 = array;
			foreach (Collider val2 in array2)
			{
				if (((Component)val2).gameObject.layer == LayerMask.NameToLayer("Environment"))
				{
					float num2 = Vector3.Distance(((Component)sosig).transform.position, ((Component)val2).transform.position);
					if (IsCoverEffective(((Component)val2).transform.position) && num2 < num)
					{
						num = num2;
						val = ((Component)val2).transform;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				coverPoint = val;
				return true;
			}
			return false;
		}

		private bool IsCoverEffective(Vector3 coverPosition)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_0029: 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_0033: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = lastKnownEnemyPosition - ((Component)sosig).transform.position;
			Vector3 val2 = coverPosition - ((Component)sosig).transform.position;
			float num = Vector3.Dot(((Vector3)(ref val)).normalized, ((Vector3)(ref val2)).normalized);
			return num > 0.5f;
		}

		private Vector3 CalculateFlankPosition()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_0074: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: 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_0101: 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)
			if (lastKnownEnemyPosition == Vector3.zero)
			{
				return Vector3.zero;
			}
			Vector3 val = lastKnownEnemyPosition - ((Component)sosig).transform.position;
			Vector3 val2 = Vector3.Cross(val, Vector3.up);
			Vector3 normalized = ((Vector3)(ref val2)).normalized;
			Vector3 val3 = ((Component)sosig).transform.position + normalized * 10f;
			Vector3 val4 = ((Component)sosig).transform.position - normalized * 10f;
			if (!Physics.Linecast(((Component)sosig).transform.position, val3, LayerMask.GetMask(new string[1] { "Environment" })))
			{
				return val3;
			}
			if (!Physics.Linecast(((Component)sosig).transform.position, val4, LayerMask.GetMask(new string[1] { "Environment" })))
			{
				return val4;
			}
			return Vector3.zero;
		}

		private Vector3 CalculateRetreatPosition()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown resul