Decompiled source of RaiderClans v1.0.0

RaiderClans.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RaiderClans")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Hostile Player-Model Raiders & Infused Loot Mod for Valheim")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RaiderClans")]
[assembly: AssemblyTitle("RaiderClans")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RaiderClans
{
	public interface IRaiderBehaviorFactory
	{
		void Attach(GameObject raiderObject);
	}
	public interface IStructureAttackAugment
	{
		bool CanApply(HitData hitData, Piece targetPiece);

		void Apply(HitData hitData, Piece targetPiece);
	}
	public sealed class TorchFireAugment : IStructureAttackAugment
	{
		public bool CanApply(HitData hitData, Piece targetPiece)
		{
			return false;
		}

		public void Apply(HitData hitData, Piece targetPiece)
		{
			RaiderClansPlugin.LogDebug("[TorchFireAugment] Would ignite " + (((targetPiece != null) ? ((Object)targetPiece).name : null) ?? "<null>") + " once fire system is ready.");
		}
	}
	public sealed class PillagerBehaviorFactory : IRaiderBehaviorFactory
	{
		private static readonly StructurePriority[] DefaultPriorities = new StructurePriority[17]
		{
			new StructurePriority("guard_stone", null, 0),
			new StructurePriority("portal_wood", null, 1),
			new StructurePriority("piece_workbench", null, 2),
			new StructurePriority("piece_stonecutter", null, 3),
			new StructurePriority("forge", null, 4),
			new StructurePriority("blackforge", null, 5),
			new StructurePriority("mage_table", null, 6),
			new StructurePriority("artisan_table", null, 7),
			new StructurePriority(null, (PieceCategory)1, 8),
			new StructurePriority("piece_chest_blackmetal", null, 9),
			new StructurePriority("piece_chest_private", null, 10),
			new StructurePriority("piece_chest_wood", null, 11),
			new StructurePriority("piece_door_iron", null, 12),
			new StructurePriority("piece_door_secret", null, 13),
			new StructurePriority("piece_door", null, 14),
			new StructurePriority(null, (PieceCategory)3, 15),
			new StructurePriority(null, (PieceCategory)2, 16)
		};

		private readonly IReadOnlyList<StructurePriority> _priorities;

		private readonly float _searchRadius;

		private readonly float _scanInterval;

		private readonly List<IStructureAttackAugment> _augments;

		private PillagerBehaviorFactory(IReadOnlyList<StructurePriority> priorities, float searchRadius, float scanInterval, IEnumerable<IStructureAttackAugment> augments)
		{
			_priorities = priorities;
			_searchRadius = searchRadius;
			_scanInterval = scanInterval;
			_augments = new List<IStructureAttackAugment>(augments ?? Array.Empty<IStructureAttackAugment>());
		}

		public static PillagerBehaviorFactory CreateDefault()
		{
			return new PillagerBehaviorFactory(DefaultPriorities, 45f, 5f, new TorchFireAugment[1]
			{
				new TorchFireAugment()
			});
		}

		public void Attach(GameObject raiderObject)
		{
			if (!((Object)(object)raiderObject == (Object)null))
			{
				PillagerBehavior pillagerBehavior = raiderObject.GetComponent<PillagerBehavior>();
				if ((Object)(object)pillagerBehavior == (Object)null)
				{
					pillagerBehavior = raiderObject.AddComponent<PillagerBehavior>();
				}
				pillagerBehavior.Configure(_priorities, _searchRadius, _scanInterval, _augments);
				MonsterAI component = raiderObject.GetComponent<MonsterAI>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_enableHuntPlayer = false;
					((BaseAI)component).SetHuntPlayer(false);
				}
			}
		}
	}
	public class PillagerBehavior : MonoBehaviour
	{
		private enum PillagerState
		{
			Searching,
			StructureCommitted,
			AggroPlayer,
			NoStructures
		}

		private const float AggroMemorySeconds = 10f;

		private const float BlockCheckInterval = 0.5f;

		private const float BlockingDetectionRadius = 2.5f;

		private const float StructureProgressSampleInterval = 2f;

		private const float StructureProgressThreshold = 1.5f;

		private const float StructureStuckTimeout = 6f;

		private static readonly FieldRef<MonsterAI, StaticTarget> TargetStaticField = AccessTools.FieldRefAccess<MonsterAI, StaticTarget>("m_targetStatic");

		private static readonly FieldRef<MonsterAI, Character> TargetCreatureField = AccessTools.FieldRefAccess<MonsterAI, Character>("m_targetCreature");

		private MonsterAI _monsterAI;

		private BaseAI _baseAI;

		private Character _character;

		private ZNetView _nview;

		private readonly List<Piece> _structureBuffer = new List<Piece>(64);

		private readonly List<IStructureAttackAugment> _augments = new List<IStructureAttackAugment>();

		private IReadOnlyList<StructurePriority> _priorities = Array.Empty<StructurePriority>();

		private float _searchRadius = 40f;

		private float _scanInterval = 5f;

		private float _nextScanTime;

		private float _nextBlockCheck;

		private Piece _currentStructureTarget;

		private Character _currentAggressor;

		private float _aggroExpiry;

		private float _structureProgressSampleTime;

		private float _previousStructureDistance;

		private float _structureStuckTimer;

		private PillagerState _state = PillagerState.Searching;

		public void Configure(IReadOnlyList<StructurePriority> priorities, float searchRadius, float scanInterval, IEnumerable<IStructureAttackAugment> augments)
		{
			_priorities = priorities ?? Array.Empty<StructurePriority>();
			_searchRadius = Mathf.Max(5f, searchRadius);
			_scanInterval = Mathf.Max(1f, scanInterval);
			_augments.Clear();
			if (augments != null)
			{
				_augments.AddRange(augments);
			}
		}

		private void Awake()
		{
			_monsterAI = ((Component)this).GetComponent<MonsterAI>();
			_baseAI = (BaseAI)(object)_monsterAI;
			_character = ((Component)this).GetComponent<Character>();
			_nview = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)_character != (Object)null)
			{
				Character character = _character;
				character.m_onDamaged = (Action<float, Character>)Delegate.Combine(character.m_onDamaged, new Action<float, Character>(OnDamaged));
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_character != (Object)null)
			{
				Character character = _character;
				character.m_onDamaged = (Action<float, Character>)Delegate.Remove(character.m_onDamaged, new Action<float, Character>(OnDamaged));
			}
		}

		private void Update()
		{
			if (!ShouldRun())
			{
				return;
			}
			float deltaTime = Time.deltaTime;
			if (UpdateAggroState())
			{
				MaintainAggressorTarget();
				return;
			}
			MaintainStructureTarget(deltaTime);
			ScanForStructureTargets();
			if ((Object)(object)_currentStructureTarget != (Object)null)
			{
				CheckBlockingPlayer();
			}
		}

		internal static void TryHandleStructureHit(Character attacker, Piece targetPiece, HitData hitData)
		{
			if (!((Object)(object)attacker == (Object)null) && !((Object)(object)targetPiece == (Object)null) && hitData != null)
			{
				((Component)attacker).GetComponent<PillagerBehavior>()?.ApplyAugments(targetPiece, hitData);
			}
		}

		private bool ShouldRun()
		{
			if ((Object)(object)_monsterAI == (Object)null || (Object)(object)_baseAI == (Object)null || (Object)(object)_character == (Object)null || (Object)(object)_nview == (Object)null)
			{
				return false;
			}
			if (!_nview.IsValid() || !_nview.IsOwner())
			{
				return false;
			}
			return true;
		}

		private void OnDamaged(float damage, Character attacker)
		{
			if (!((Object)(object)attacker == (Object)null) && !attacker.IsDead() && attacker.IsPlayer())
			{
				AdoptAggressor(attacker);
			}
		}

		private bool UpdateAggroState()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_currentAggressor == (Object)null)
			{
				return false;
			}
			_state = PillagerState.AggroPlayer;
			if (_currentAggressor.IsDead() || Time.time > _aggroExpiry || Vector3.Distance(((Component)_currentAggressor).transform.position, ((Component)this).transform.position) > _searchRadius * 1.5f)
			{
				ClearAggressor();
			}
			return (Object)(object)_currentAggressor != (Object)null;
		}

		private void MaintainAggressorTarget()
		{
			if (!((Object)(object)_monsterAI == (Object)null) && !((Object)(object)_currentAggressor == (Object)null))
			{
				TargetStaticField.Invoke(_monsterAI) = null;
				Character val = TargetCreatureField.Invoke(_monsterAI);
				if ((Object)(object)val != (Object)(object)_currentAggressor)
				{
					TargetCreatureField.Invoke(_monsterAI) = _currentAggressor;
				}
				((BaseAI)_monsterAI).Alert();
			}
		}

		private void ClearAggressor()
		{
			_currentAggressor = null;
			_aggroExpiry = 0f;
			if ((Object)(object)_monsterAI != (Object)null)
			{
				TargetCreatureField.Invoke(_monsterAI) = null;
				if (((BaseAI)_monsterAI).HuntPlayer())
				{
					((BaseAI)_monsterAI).SetHuntPlayer(false);
				}
			}
			_state = (((Object)(object)_currentStructureTarget != (Object)null) ? PillagerState.StructureCommitted : PillagerState.Searching);
		}

		private void AdoptAggressor(Character aggressor)
		{
			if (!((Object)(object)aggressor == (Object)null))
			{
				_currentAggressor = aggressor;
				_aggroExpiry = Time.time + 10f;
				BaseAI baseAI = _baseAI;
				if (baseAI != null)
				{
					baseAI.SetAggravated(true, (AggravatedReason)0);
				}
				if ((Object)(object)_monsterAI != (Object)null && !((BaseAI)_monsterAI).HuntPlayer())
				{
					((BaseAI)_monsterAI).SetHuntPlayer(true);
				}
			}
		}

		private void ScanForStructureTargets()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time < _nextScanTime)
			{
				return;
			}
			_nextScanTime = Time.time + _scanInterval;
			if (!HasValidStructureTarget())
			{
				RaiderTargetingService.FindPlayerStructures(((Component)this).transform.position, _searchRadius, _structureBuffer);
				Piece val = RaiderTargetingService.SelectHighestPriorityStructure(_structureBuffer, _priorities, ((Component)this).transform.position);
				if ((Object)(object)val == (Object)null)
				{
					HandleNoStructuresFound();
				}
				else
				{
					AssignStructureTarget(val);
				}
			}
		}

		private void MaintainStructureTarget(float dt)
		{
			if (HasValidStructureTarget())
			{
				StaticTarget val = TargetStaticField.Invoke(_monsterAI);
				if ((Object)(object)val != (Object)(object)_currentStructureTarget)
				{
					TargetStaticField.Invoke(_monsterAI) = (StaticTarget)(object)_currentStructureTarget;
					TargetCreatureField.Invoke(_monsterAI) = null;
				}
				UpdateStructureProgress(dt);
			}
		}

		internal bool ShouldPreferStructureTarget()
		{
			return (Object)(object)_currentStructureTarget != (Object)null && (Object)(object)_currentAggressor == (Object)null;
		}

		private void AssignStructureTarget(Piece piece)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			_currentStructureTarget = piece;
			if (!((Object)(object)_monsterAI == (Object)null))
			{
				TargetCreatureField.Invoke(_monsterAI) = null;
				TargetStaticField.Invoke(_monsterAI) = (StaticTarget)(object)piece;
				BaseAI baseAI = _baseAI;
				if (baseAI != null)
				{
					baseAI.SetAggravated(true, (AggravatedReason)0);
				}
				((BaseAI)_monsterAI).Alert();
				_state = PillagerState.StructureCommitted;
				_structureStuckTimer = 0f;
				_previousStructureDistance = Vector3.Distance(((Component)this).transform.position, ((Component)piece).transform.position);
				_structureProgressSampleTime = Time.time + 2f;
			}
		}

		private void ClearStructureTarget()
		{
			_currentStructureTarget = null;
			if ((Object)(object)_monsterAI != (Object)null)
			{
				TargetStaticField.Invoke(_monsterAI) = null;
			}
			_state = PillagerState.Searching;
			_structureStuckTimer = 0f;
		}

		private void CheckBlockingPlayer()
		{
			//IL_003f: 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)_currentStructureTarget == (Object)null || Time.time < _nextBlockCheck)
			{
				return;
			}
			_nextBlockCheck = Time.time + 0.5f;
			Character val = RaiderTargetingService.FindBlockingPlayer(((Component)this).transform.position, ((Component)_currentStructureTarget).transform.position, 2.5f);
			if ((Object)(object)val != (Object)null && val.IsPlayer())
			{
				MonsterAI monsterAI = _monsterAI;
				if (monsterAI != null)
				{
					((BaseAI)monsterAI).Alert();
				}
			}
		}

		private void ApplyAugments(Piece targetPiece, HitData hitData)
		{
			if ((Object)(object)targetPiece == (Object)null || hitData == null || _augments.Count == 0)
			{
				return;
			}
			foreach (IStructureAttackAugment augment in _augments)
			{
				if (augment != null && augment.CanApply(hitData, targetPiece))
				{
					augment.Apply(hitData, targetPiece);
				}
			}
		}

		private bool HasValidStructureTarget()
		{
			if ((Object)(object)_currentStructureTarget == (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)_currentStructureTarget).gameObject == (Object)null || !((Component)_currentStructureTarget).gameObject.activeInHierarchy || !_currentStructureTarget.IsPlacedByPlayer())
			{
				ClearStructureTarget();
				return false;
			}
			return true;
		}

		private void UpdateStructureProgress(float dt)
		{
			//IL_001d: 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)
			if ((Object)(object)_currentStructureTarget == (Object)null)
			{
				return;
			}
			float num = Vector3.Distance(((Component)this).transform.position, ((Component)_currentStructureTarget).transform.position);
			if (num <= 2.5f)
			{
				_structureStuckTimer = 0f;
			}
			else
			{
				if (Time.time < _structureProgressSampleTime)
				{
					return;
				}
				float num2 = _previousStructureDistance - num;
				if (num2 < 1.5f)
				{
					_structureStuckTimer += 2f;
					if (_structureStuckTimer >= 6f)
					{
						RaiderClansPlugin.LogDebug("[PillagerBehavior] Structure target unreachable, searching for a new one.");
						ClearStructureTarget();
						return;
					}
				}
				else
				{
					_structureStuckTimer = 0f;
				}
				_previousStructureDistance = num;
				_structureProgressSampleTime = Time.time + 2f;
			}
		}

		private void HandleNoStructuresFound()
		{
			_state = PillagerState.NoStructures;
			TargetStaticField.Invoke(_monsterAI) = null;
		}
	}
	[HarmonyPatch(typeof(WearNTear), "RPC_Damage")]
	internal static class PillagerStructureHitPatch
	{
		private static void Prefix(WearNTear __instance, HitData hit)
		{
			if ((Object)(object)__instance == (Object)null || hit == null)
			{
				return;
			}
			Character attacker = hit.GetAttacker();
			if (!((Object)(object)attacker == (Object)null))
			{
				Piece component = ((Component)__instance).GetComponent<Piece>();
				if (!((Object)(object)component == (Object)null))
				{
					PillagerBehavior.TryHandleStructureHit(attacker, component, hit);
				}
			}
		}
	}
	public class RaiderAI
	{
		public readonly struct RaiderSpawnRequest
		{
			public Vector3 Position { get; }

			public Biome Biome { get; }

			public RaiderRole Role { get; }

			public RaiderSpawnRequest(Vector3 position, Biome biome, RaiderRole role)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0003: 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_000a: Unknown result type (might be due to invalid IL or missing references)
				Position = position;
				Biome = biome;
				Role = role;
			}
		}

		public const string RaiderCustomDataKey = "RaiderClans_IsRaider";

		private const string ChieftainCustomDataKey = "RaiderClans_IsChieftain";

		private const string BiomeCustomDataKey = "RaiderClans_Biome";

		private const string RoleCustomDataKey = "RaiderClans_Role";

		private const string MinimalPrefabName = "RaiderClan_Minimal";

		private static bool s_minimalPrefabRegistered;

		private static readonly Dictionary<RaiderRole, StatusEffect> s_damageEffects = new Dictionary<RaiderRole, StatusEffect>();

		public static void Initialize()
		{
			RaiderRoleRegistry.Initialize();
			PrefabManager.OnVanillaPrefabsAvailable += RegisterMinimalRaiderPrefab;
		}

		private static void RegisterMinimalRaiderPrefab()
		{
			if (!s_minimalPrefabRegistered)
			{
				RaiderClansPlugin.LogDebug("Registering minimal raider NPC prefab via Jotunn");
				GameObject val = CreateMinimalRaiderPrefab("RaiderClan_Minimal");
				if ((Object)(object)val != (Object)null)
				{
					PrefabManager.Instance.AddPrefab(val);
					s_minimalPrefabRegistered = true;
					RaiderClansPlugin.Logger.LogInfo((object)"Minimal raider prefab registered successfully via Jotunn");
				}
				else
				{
					RaiderClansPlugin.Logger.LogError((object)"Failed to register minimal raider prefab");
				}
			}
		}

		private static GameObject CreateMinimalRaiderPrefab(string prefabName)
		{
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Expected O, but got Unknown
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			RaiderClansPlugin.LogDebug("Creating " + prefabName + " prefab (minimal Player clone)");
			GameObject val = PrefabManager.Instance.CreateClonedPrefab(prefabName, "Player");
			if ((Object)(object)val == (Object)null)
			{
				RaiderClansPlugin.Logger.LogError((object)"Failed to clone Player prefab");
				return null;
			}
			PlayerController component = val.GetComponent<PlayerController>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			AudioListener[] componentsInChildren = val.GetComponentsInChildren<AudioListener>(true);
			foreach (AudioListener val2 in componentsInChildren)
			{
				Object.DestroyImmediate((Object)(object)val2);
			}
			GuidePoint[] componentsInChildren2 = val.GetComponentsInChildren<GuidePoint>(true);
			foreach (GuidePoint val3 in componentsInChildren2)
			{
				Object.DestroyImmediate((Object)(object)val3);
			}
			Player component2 = val.GetComponent<Player>();
			if ((Object)(object)component2 == (Object)null)
			{
				RaiderClansPlugin.Logger.LogError((object)"Player clone missing Player component!");
				return null;
			}
			ItemDrop unarmedWeapon = ((Humanoid)component2).m_unarmedWeapon;
			EffectList consumeItemEffects = ((Humanoid)component2).m_consumeItemEffects;
			EffectList equipEffects = ((Humanoid)component2).m_equipEffects;
			Object.DestroyImmediate((Object)(object)component2);
			Humanoid val4 = val.AddComponent<Humanoid>();
			val4.m_unarmedWeapon = unarmedWeapon;
			val4.m_consumeItemEffects = consumeItemEffects;
			val4.m_equipEffects = equipEffects;
			Character val5 = (Character)(object)val4;
			if ((Object)(object)val5 != (Object)null)
			{
				val5.m_name = "Clan Raider";
				val5.m_group = "Raiders";
				val5.m_faction = (Faction)3;
				val5.m_walkSpeed = 2f;
				val5.m_runSpeed = 4f;
				val5.m_health = 100f;
				val5.m_staggerWhenBlocked = true;
				val5.m_staggerDamageFactor = 0.2f;
				Transform val6 = Utils.FindChild(val.transform, "EyePos", (IterativeSearchType)0);
				if ((Object)(object)val6 == (Object)null)
				{
					GameObject val7 = new GameObject("EyePos");
					val7.transform.SetParent(val.transform);
					val7.transform.localPosition = new Vector3(0f, 1.6f, 0f);
					val6 = val7.transform;
				}
				val5.m_eye = val6;
				CharacterDrop val8 = val.GetComponent<CharacterDrop>();
				if ((Object)(object)val8 == (Object)null)
				{
					val8 = val.AddComponent<CharacterDrop>();
				}
				val8.m_dropsEnabled = true;
			}
			MonsterAI val9 = val.AddComponent<MonsterAI>();
			((BaseAI)val9).m_viewRange = 60f;
			((BaseAI)val9).m_viewAngle = 90f;
			((BaseAI)val9).m_hearRange = 30f;
			((BaseAI)val9).m_aggravatable = true;
			val9.m_attackPlayerObjects = true;
			val9.m_enableHuntPlayer = true;
			val9.m_minAttackInterval = 2f;
			val9.m_circleTargetInterval = 0f;
			((BaseAI)val9).m_randomMoveInterval = 1f;
			((BaseAI)val9).m_randomMoveRange = 5f;
			RaiderClansPlugin.LogDebug(prefabName + " prefab created successfully");
			return val;
		}

		public static Humanoid SpawnRaider(Vector3 position, Biome biome, bool isChieftain = false, bool isRanged = false)
		{
			//IL_001b: 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)
			RaiderRole role = (isChieftain ? RaiderRole.Chieftain : RaiderRole.Warrior);
			if (isRanged)
			{
				RaiderClansPlugin.LogDebug("Ranged raiders not yet implemented; defaulting to melee role behavior.");
			}
			return SpawnRaider(new RaiderSpawnRequest(position, biome, role));
		}

		public static Humanoid SpawnRaider(RaiderSpawnRequest request)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Expected I4, but got Unknown
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			RaiderClansPlugin.LogDebug($"Attempting to spawn raider role {request.Role} at {request.Position}");
			GameObject prefab = ZNetScene.instance.GetPrefab("RaiderClan_Minimal");
			if ((Object)(object)prefab == (Object)null)
			{
				RaiderClansPlugin.Logger.LogError((object)"Could not find RaiderClan_Minimal template in ZNetScene");
				return null;
			}
			RaiderRoleConfig config = RaiderRoleRegistry.GetConfig(request.Role);
			Vector3 position = request.Position;
			Biome biome = request.Biome;
			GameObject val = Object.Instantiate<GameObject>(prefab, position, Quaternion.identity);
			if ((Object)(object)val == (Object)null)
			{
				RaiderClansPlugin.Logger.LogError((object)"Failed to instantiate raider");
				return null;
			}
			RaiderClansPlugin.LogDebug("Spawned minimal raider instance: " + ((Object)val).name);
			Humanoid component = val.GetComponent<Humanoid>();
			if ((Object)(object)component == (Object)null)
			{
				RaiderClansPlugin.Logger.LogError((object)"Failed to get Humanoid component from spawned raider");
				ZNetScene.instance.Destroy(val);
				return null;
			}
			Character component2 = ((Component)component).GetComponent<Character>();
			if ((Object)(object)component2 == (Object)null)
			{
				RaiderClansPlugin.Logger.LogError((object)"Spawned raider missing Character component");
				ZNetScene.instance.Destroy(val);
				return null;
			}
			component2.m_faction = (Faction)3;
			component2.m_name = "Clan Raider";
			ZNetView val2 = ((Character)component).m_nview ?? val.GetComponent<ZNetView>();
			ZDO val3 = ((val2 != null) ? val2.GetZDO() : null);
			if (val3 != null)
			{
				val3.Set("RaiderClans_IsRaider", true);
				val3.Set("RaiderClans_IsChieftain", request.Role == RaiderRole.Chieftain);
				val3.Set("RaiderClans_Biome", (int)biome);
				val3.Set("RaiderClans_Role", (int)request.Role);
			}
			else
			{
				RaiderClansPlugin.Logger.LogWarning((object)"Spawned raider without valid ZDO; custom metadata unavailable");
			}
			float baseHealthForBiome = RaiderRoleRegistry.GetBaseHealthForBiome(biome);
			float num = Mathf.Max(50f, baseHealthForBiome * config.HealthMultiplier);
			component2.SetMaxHealth(num);
			component2.SetHealth(num);
			CharacterDrop component3 = val.GetComponent<CharacterDrop>();
			RaiderLoot.ConfigureCharacterDrop(component3, biome);
			ApplyRoleConfiguration(component, val, config, biome);
			RaiderClansPlugin.LogDebug("Successfully spawned minimal raider");
			return component;
		}

		private static void ApplyRoleConfiguration(Humanoid raider, GameObject raiderObj, RaiderRoleConfig config, Biome biome)
		{
			//IL_0101: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)raider == (Object)null || config == null)
			{
				return;
			}
			Character component = ((Component)raider).GetComponent<Character>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_name = "Clan " + config.DisplayName;
				component.m_walkSpeed *= config.MoveSpeedMultiplier;
				component.m_runSpeed *= config.MoveSpeedMultiplier;
				if (Mathf.Abs(config.ModelScale - 1f) > 0.01f)
				{
					raiderObj.transform.localScale = Vector3.Scale(raiderObj.transform.localScale, new Vector3(config.ModelScale, config.ModelScale, config.ModelScale));
				}
			}
			MonsterAI component2 = ((Component)raider).GetComponent<MonsterAI>();
			if ((Object)(object)component2 != (Object)null)
			{
				((BaseAI)component2).m_pathAgentType = (AgentType)10;
				if (config.Role == RaiderRole.Pillager)
				{
					component2.m_enableHuntPlayer = false;
					((BaseAI)component2).SetHuntPlayer(false);
				}
			}
			ApplyDefaultItems(raider, config.ResolveDefaultItems(biome));
			config.BehaviorFactory?.Attach(raiderObj);
			ApplyDamageMultiplier(component, config);
		}

		private static void ApplyDefaultItems(Humanoid humanoid, IReadOnlyList<string> prefabNames)
		{
			if ((Object)(object)humanoid == (Object)null || prefabNames == null || prefabNames.Count == 0)
			{
				return;
			}
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance == (Object)null)
			{
				RaiderClansPlugin.Logger.LogWarning((object)"ObjectDB not ready; cannot equip raider role items.");
				return;
			}
			List<GameObject> list = new List<GameObject>();
			foreach (string prefabName in prefabNames)
			{
				if (!string.IsNullOrWhiteSpace(prefabName))
				{
					GameObject itemPrefab = instance.GetItemPrefab(prefabName);
					if ((Object)(object)itemPrefab != (Object)null)
					{
						list.Add(itemPrefab);
					}
					else
					{
						RaiderClansPlugin.Logger.LogWarning((object)("Missing item prefab '" + prefabName + "' for raider role " + ((Object)humanoid).name));
					}
				}
			}
			if (list.Count != 0)
			{
				humanoid.m_defaultItems = list.ToArray();
				GameObject[] defaultItems = humanoid.m_defaultItems;
				foreach (GameObject val in defaultItems)
				{
					humanoid.GiveDefaultItem(val);
				}
			}
		}

		private static void ApplyDamageMultiplier(Character character, RaiderRoleConfig config)
		{
			if ((Object)(object)character == (Object)null || config == null || Mathf.Approximately(config.DamageMultiplier, 1f))
			{
				return;
			}
			SEMan sEMan = character.GetSEMan();
			if (sEMan != null)
			{
				StatusEffect damageEffectTemplate = GetDamageEffectTemplate(config);
				if ((Object)(object)damageEffectTemplate != (Object)null)
				{
					sEMan.AddStatusEffect(damageEffectTemplate, true, 0, 0f);
				}
			}
		}

		private static StatusEffect GetDamageEffectTemplate(RaiderRoleConfig config)
		{
			//IL_005f: 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_0081: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			if (s_damageEffects.TryGetValue(config.Role, out var value))
			{
				return value;
			}
			SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>();
			((Object)val).name = $"SE_Raider_{config.Role}_Damage";
			((StatusEffect)val).m_name = ((Object)val).name;
			val.m_damageModifier = config.DamageMultiplier;
			val.m_modifyAttackSkill = (SkillType)999;
			((StatusEffect)val).m_icon = null;
			((StatusEffect)val).m_tooltip = string.Empty;
			((StatusEffect)val).m_startEffects = new EffectList();
			((StatusEffect)val).m_stopEffects = new EffectList();
			((StatusEffect)val).m_ttl = 0f;
			((StatusEffect)val).m_cooldown = 0f;
			s_damageEffects[config.Role] = (StatusEffect)(object)val;
			return (StatusEffect)(object)val;
		}

		public static bool IsRaider(Character character)
		{
			if (character?.m_nview?.m_zdo == null)
			{
				return false;
			}
			return character.m_nview.m_zdo.GetBool("RaiderClans_IsRaider", false);
		}

		public static RaiderRole? GetRole(Character character)
		{
			if (character?.m_nview?.m_zdo == null)
			{
				return null;
			}
			int num = character.m_nview.m_zdo.GetInt("RaiderClans_Role", -1);
			if (num == -1)
			{
				return null;
			}
			return (RaiderRole)num;
		}

		public static bool IsChieftain(Character character)
		{
			if (character?.m_nview?.m_zdo == null)
			{
				return false;
			}
			return character.m_nview.m_zdo.GetBool("RaiderClans_IsChieftain", false);
		}
	}
	[HarmonyPatch]
	internal class RaiderClansDevCommands
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__0_0;

			public static ConsoleOptionsFetcher <>9__0_1;

			public static ConsoleEvent <>9__0_2;

			public static ConsoleOptionsFetcher <>9__0_3;

			public static ConsoleOptionsFetcher <>9__0_4;

			public static ConsoleEvent <>9__0_5;

			public static ConsoleEvent <>9__0_6;

			public static ConsoleEvent <>9__0_7;

			public static ConsoleEvent <>9__0_8;

			public static ConsoleOptionsFetcher <>9__0_9;

			public static ConsoleEvent <>9__0_10;

			public static ConsoleOptionsFetcher <>9__0_11;

			public static ConsoleEvent <>9__0_12;

			public static ConsoleEvent <>9__0_13;

			internal void <AddCustomCommands>b__0_0(ConsoleEventArgs args)
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bf: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_0106: Unknown result type (might be due to invalid IL or missing references)
				//IL_010c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0127: Unknown result type (might be due to invalid IL or missing references)
				//IL_0133: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					args.Context.AddString("No local player found");
					return;
				}
				Biome val = (Biome)1;
				if (args.Length >= 2)
				{
					if (Enum.TryParse<Biome>(args[1], ignoreCase: true, out Biome result))
					{
						val = result;
					}
					else
					{
						args.Context.AddString("Invalid biome: " + args[1] + ". Using Meadows.");
					}
				}
				bool result2 = false;
				if (args.Length >= 3)
				{
					bool.TryParse(args[2], out result2);
				}
				Vector3 val2 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 3f;
				Humanoid val3 = RaiderAI.SpawnRaider(val2, val, result2);
				if ((Object)(object)val3 != (Object)null)
				{
					args.Context.AddString(string.Format("Spawned {0} for biome {1} at {2}", result2 ? "Chieftain" : "Raider", val, val2));
					RaiderClansPlugin.Logger.LogInfo((object)$"Dev command spawned raider: Biome={val}, Chieftain={result2}, Pos={val2}");
				}
				else
				{
					args.Context.AddString("Failed to spawn raider - check logs");
				}
			}

			internal List<string> <AddCustomCommands>b__0_1()
			{
				return new List<string> { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands" };
			}

			internal void <AddCustomCommands>b__0_2(ConsoleEventArgs args)
			{
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					args.Context.AddString("No local player found");
				}
				else if (args.Length >= 2)
				{
					if (Enum.TryParse<Biome>(args[1], ignoreCase: true, out Biome result))
					{
						RaiderEvents.StartRaidManually(result);
						args.Context.AddString($"Raider clan raid event started for {result}!");
						RaiderClansPlugin.Logger.LogInfo((object)$"Dev command started raid event for biome {result}");
					}
					else
					{
						args.Context.AddString("Invalid biome '" + args[1] + "'.");
					}
				}
				else
				{
					RaiderEvents.StartRaidManually();
					args.Context.AddString("Raider clan raid event started!");
					RaiderClansPlugin.Logger.LogInfo((object)"Dev command started raid event");
				}
			}

			internal List<string> <AddCustomCommands>b__0_3()
			{
				return new List<string> { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands" };
			}

			internal List<string> <AddCustomCommands>b__0_4()
			{
				return new List<string> { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands" };
			}

			internal void <AddCustomCommands>b__0_5(ConsoleEventArgs args)
			{
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					args.Context.AddString("No local player found");
					return;
				}
				Vector2i zone = ZoneSystem.GetZone(((Component)Player.m_localPlayer).transform.position);
				args.Context.AddString($"Processing zone {zone}...");
				RaiderClansPlugin.Logger.LogInfo((object)$"Dev command processing zone: {zone}");
				int num = RaiderTowerOverwrites.ProcessZoneLocations(zone);
				args.Context.AddString($"Processed {num} locations in zone {zone}");
			}

			internal void <AddCustomCommands>b__0_6(ConsoleEventArgs args)
			{
				if (args.Length >= 2)
				{
					if (args[1].ToLower() == "on")
					{
						RaiderClansPlugin.EnableDebugLogging.Value = true;
						args.Context.AddString("Debug logging enabled");
					}
					else if (args[1].ToLower() == "off")
					{
						RaiderClansPlugin.EnableDebugLogging.Value = false;
						args.Context.AddString("Debug logging disabled");
					}
				}
				else
				{
					args.Context.AddString("Debug logging is currently " + (RaiderClansPlugin.EnableDebugLogging.Value ? "enabled" : "disabled"));
				}
			}

			internal void <AddCustomCommands>b__0_7(ConsoleEventArgs args)
			{
				HashSet<string> processedLocations = RaiderTowerOverwrites.GetProcessedLocations();
				args.Context.AddString($"Processed {processedLocations.Count} locations:");
				foreach (string item in processedLocations)
				{
					args.Context.AddString("  - " + item);
				}
			}

			internal void <AddCustomCommands>b__0_8(ConsoleEventArgs args)
			{
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_0097: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bb: 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_008a: 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_00ec: 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)
				if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					args.Context.AddString("No local player found");
					return;
				}
				if (args.Length < 2 || !Enum.TryParse<RaiderRole>(args[1], ignoreCase: true, out var result))
				{
					args.Context.AddString("Usage: raiderclan_spawnrole <Warrior|Pillager|Chieftain> [Biome]");
					return;
				}
				Biome val = (Biome)1;
				if (args.Length >= 3 && Enum.TryParse<Biome>(args[2], ignoreCase: true, out Biome result2))
				{
					val = result2;
				}
				Vector3 val2 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 3f;
				Humanoid val3 = RaiderAI.SpawnRaider(new RaiderAI.RaiderSpawnRequest(val2, val, result));
				args.Context.AddString(((Object)(object)val3 != (Object)null) ? $"Spawned {result} with {val} loadout at {val2}" : "Failed to spawn raider");
			}

			internal List<string> <AddCustomCommands>b__0_9()
			{
				return new List<string> { "Warrior", "Pillager", "Chieftain" };
			}

			internal void <AddCustomCommands>b__0_10(ConsoleEventArgs args)
			{
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a2: Expected O, but got Unknown
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
				//IL_012f: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					args.Context.AddString("No local player found");
					return;
				}
				if (args.Length < 2)
				{
					args.Context.AddString("Usage: raiderclan_spawngarrison <tower|village> [radius]");
					return;
				}
				string text = args[1].ToLowerInvariant();
				float num = 20f;
				if (args.Length >= 3 && float.TryParse(args[2], out var result))
				{
					num = Mathf.Clamp(result, 5f, 50f);
				}
				GameObject val = new GameObject("RaiderClans_GarrisonRoot");
				val.transform.position = ((Component)Player.m_localPlayer).transform.position;
				if (text == "tower")
				{
					RaiderTowerOverwrites.SpawnTowerRaiders(val);
					args.Context.AddString($"Spawned tower garrison at {val.transform.position} (radius {num})");
				}
				else if (text == "village")
				{
					RaiderTowerOverwrites.SpawnVillageRaiders(val);
					args.Context.AddString($"Spawned village garrison at {val.transform.position} (radius {num})");
				}
				else
				{
					args.Context.AddString("Invalid garrison type. Use 'tower' or 'village'.");
				}
				Object.Destroy((Object)(object)val);
			}

			internal List<string> <AddCustomCommands>b__0_11()
			{
				return new List<string> { "tower", "village" };
			}

			internal void <AddCustomCommands>b__0_12(ConsoleEventArgs args)
			{
				if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					args.Context.AddString("No local player found");
					return;
				}
				if (args.Length < 2 || !int.TryParse(args[1], out var result))
				{
					args.Context.AddString("Usage: raiderclan_wave <waveNumber>");
					return;
				}
				if (!RaiderEvents.IsRaidActive())
				{
					RaiderEvents.StartRaidManually();
				}
				MethodInfo methodInfo = AccessTools.Method(typeof(RaiderEvents), "SpawnWave", (Type[])null, (Type[])null);
				for (int i = 0; i < result; i++)
				{
					methodInfo.Invoke(null, null);
				}
				args.Context.AddString($"Spawned raid wave {result}");
			}

			internal void <AddCustomCommands>b__0_13(ConsoleEventArgs args)
			{
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_009e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: 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.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					args.Context.AddString("No local player found");
					return;
				}
				Biome val = (Biome)1;
				if (args.Length >= 2 && Enum.TryParse<Biome>(args[1], ignoreCase: true, out Biome result))
				{
					val = result;
				}
				Vector3 val2 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 2f;
				RaiderLoot.DropRegularLoot(val2, val);
				args.Context.AddString($"Spawned regular loot for {val} biome at {val2}");
			}
		}

		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		[HarmonyPostfix]
		private static void AddCustomCommands()
		{
			//IL_001f: 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_002a: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//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_004e: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_0151: 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_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Expected O, but got Unknown
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Expected O, but got Unknown
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Expected O, but got Unknown
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Expected O, but got Unknown
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Expected O, but got Unknown
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Expected O, but got Unknown
			object obj = <>c.<>9__0_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					//IL_002c: Unknown result type (might be due to invalid IL or missing references)
					//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
					//IL_00bf: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
					//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
					//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
					//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
					//IL_0056: Unknown result type (might be due to invalid IL or missing references)
					//IL_0058: Unknown result type (might be due to invalid IL or missing references)
					//IL_0106: Unknown result type (might be due to invalid IL or missing references)
					//IL_010c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0127: Unknown result type (might be due to invalid IL or missing references)
					//IL_0133: Unknown result type (might be due to invalid IL or missing references)
					if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
					{
						args.Context.AddString("No local player found");
					}
					else
					{
						Biome val16 = (Biome)1;
						if (args.Length >= 2)
						{
							if (Enum.TryParse<Biome>(args[1], ignoreCase: true, out Biome result))
							{
								val16 = result;
							}
							else
							{
								args.Context.AddString("Invalid biome: " + args[1] + ". Using Meadows.");
							}
						}
						bool result2 = false;
						if (args.Length >= 3)
						{
							bool.TryParse(args[2], out result2);
						}
						Vector3 val17 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 3f;
						Humanoid val18 = RaiderAI.SpawnRaider(val17, val16, result2);
						if ((Object)(object)val18 != (Object)null)
						{
							args.Context.AddString(string.Format("Spawned {0} for biome {1} at {2}", result2 ? "Chieftain" : "Raider", val16, val17));
							RaiderClansPlugin.Logger.LogInfo((object)$"Dev command spawned raider: Biome={val16}, Chieftain={result2}, Pos={val17}");
						}
						else
						{
							args.Context.AddString("Failed to spawn raider - check logs");
						}
					}
				};
				<>c.<>9__0_0 = val;
				obj = (object)val;
			}
			object obj2 = <>c.<>9__0_1;
			if (obj2 == null)
			{
				ConsoleOptionsFetcher val2 = () => new List<string> { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands" };
				<>c.<>9__0_1 = val2;
				obj2 = (object)val2;
			}
			new ConsoleCommand("raiderclan_spawn", "[biome] [isChieftain] - Spawn a test raider", (ConsoleEvent)obj, true, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, false);
			object obj3 = <>c.<>9__0_2;
			if (obj3 == null)
			{
				ConsoleEvent val3 = delegate(ConsoleEventArgs args)
				{
					//IL_004e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0060: Unknown result type (might be due to invalid IL or missing references)
					//IL_007b: Unknown result type (might be due to invalid IL or missing references)
					if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
					{
						args.Context.AddString("No local player found");
					}
					else if (args.Length >= 2)
					{
						if (Enum.TryParse<Biome>(args[1], ignoreCase: true, out Biome result))
						{
							RaiderEvents.StartRaidManually(result);
							args.Context.AddString($"Raider clan raid event started for {result}!");
							RaiderClansPlugin.Logger.LogInfo((object)$"Dev command started raid event for biome {result}");
						}
						else
						{
							args.Context.AddString("Invalid biome '" + args[1] + "'.");
						}
					}
					else
					{
						RaiderEvents.StartRaidManually();
						args.Context.AddString("Raider clan raid event started!");
						RaiderClansPlugin.Logger.LogInfo((object)"Dev command started raid event");
					}
				};
				<>c.<>9__0_2 = val3;
				obj3 = (object)val3;
			}
			ConsoleEvent val4 = (ConsoleEvent)obj3;
			object obj4 = <>c.<>9__0_3;
			if (obj4 == null)
			{
				ConsoleOptionsFetcher val5 = () => new List<string> { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands" };
				<>c.<>9__0_3 = val5;
				obj4 = (object)val5;
			}
			new ConsoleCommand("raiderclan_startraid", "[biome] - Start a raider clan raid event (optional biome override)", val4, true, false, false, false, false, (ConsoleOptionsFetcher)obj4, false, false, false);
			object obj5 = <>c.<>9__0_4;
			if (obj5 == null)
			{
				ConsoleOptionsFetcher val6 = () => new List<string> { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "AshLands" };
				<>c.<>9__0_4 = val6;
				obj5 = (object)val6;
			}
			new ConsoleCommand("raidclan_startraid", "[biome] - Alias for raiderclan_startraid", val4, true, false, false, false, false, (ConsoleOptionsFetcher)obj5, false, false, false);
			object obj6 = <>c.<>9__0_5;
			if (obj6 == null)
			{
				ConsoleEvent val7 = delegate(ConsoleEventArgs args)
				{
					//IL_0030: Unknown result type (might be due to invalid IL or missing references)
					//IL_0035: Unknown result type (might be due to invalid IL or missing references)
					//IL_003a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0046: Unknown result type (might be due to invalid IL or missing references)
					//IL_0061: Unknown result type (might be due to invalid IL or missing references)
					//IL_0072: Unknown result type (might be due to invalid IL or missing references)
					//IL_008a: Unknown result type (might be due to invalid IL or missing references)
					if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
					{
						args.Context.AddString("No local player found");
					}
					else
					{
						Vector2i zone = ZoneSystem.GetZone(((Component)Player.m_localPlayer).transform.position);
						args.Context.AddString($"Processing zone {zone}...");
						RaiderClansPlugin.Logger.LogInfo((object)$"Dev command processing zone: {zone}");
						int num = RaiderTowerOverwrites.ProcessZoneLocations(zone);
						args.Context.AddString($"Processed {num} locations in zone {zone}");
					}
				};
				<>c.<>9__0_5 = val7;
				obj6 = (object)val7;
			}
			new ConsoleCommand("raiderclan_processzone", "- Force process locations in current zone", (ConsoleEvent)obj6, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj7 = <>c.<>9__0_6;
			if (obj7 == null)
			{
				ConsoleEvent val8 = delegate(ConsoleEventArgs args)
				{
					if (args.Length >= 2)
					{
						if (args[1].ToLower() == "on")
						{
							RaiderClansPlugin.EnableDebugLogging.Value = true;
							args.Context.AddString("Debug logging enabled");
						}
						else if (args[1].ToLower() == "off")
						{
							RaiderClansPlugin.EnableDebugLogging.Value = false;
							args.Context.AddString("Debug logging disabled");
						}
					}
					else
					{
						args.Context.AddString("Debug logging is currently " + (RaiderClansPlugin.EnableDebugLogging.Value ? "enabled" : "disabled"));
					}
				};
				<>c.<>9__0_6 = val8;
				obj7 = (object)val8;
			}
			new ConsoleCommand("raiderclan_debug", "[on/off] - Toggle debug logging", (ConsoleEvent)obj7, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj8 = <>c.<>9__0_7;
			if (obj8 == null)
			{
				ConsoleEvent val9 = delegate(ConsoleEventArgs args)
				{
					HashSet<string> processedLocations = RaiderTowerOverwrites.GetProcessedLocations();
					args.Context.AddString($"Processed {processedLocations.Count} locations:");
					foreach (string item in processedLocations)
					{
						args.Context.AddString("  - " + item);
					}
				};
				<>c.<>9__0_7 = val9;
				obj8 = (object)val9;
			}
			new ConsoleCommand("raiderclan_listlocations", "- List all processed locations", (ConsoleEvent)obj8, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj9 = <>c.<>9__0_8;
			if (obj9 == null)
			{
				ConsoleEvent val10 = delegate(ConsoleEventArgs args)
				{
					//IL_0067: Unknown result type (might be due to invalid IL or missing references)
					//IL_0097: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
					//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
					//IL_00bb: 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_008a: 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_00ec: 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)
					RaiderRole result;
					if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
					{
						args.Context.AddString("No local player found");
					}
					else if (args.Length < 2 || !Enum.TryParse<RaiderRole>(args[1], ignoreCase: true, out result))
					{
						args.Context.AddString("Usage: raiderclan_spawnrole <Warrior|Pillager|Chieftain> [Biome]");
					}
					else
					{
						Biome val16 = (Biome)1;
						if (args.Length >= 3 && Enum.TryParse<Biome>(args[2], ignoreCase: true, out Biome result2))
						{
							val16 = result2;
						}
						Vector3 val17 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 3f;
						Humanoid val18 = RaiderAI.SpawnRaider(new RaiderAI.RaiderSpawnRequest(val17, val16, result));
						args.Context.AddString(((Object)(object)val18 != (Object)null) ? $"Spawned {result} with {val16} loadout at {val17}" : "Failed to spawn raider");
					}
				};
				<>c.<>9__0_8 = val10;
				obj9 = (object)val10;
			}
			object obj10 = <>c.<>9__0_9;
			if (obj10 == null)
			{
				ConsoleOptionsFetcher val11 = () => new List<string> { "Warrior", "Pillager", "Chieftain" };
				<>c.<>9__0_9 = val11;
				obj10 = (object)val11;
			}
			new ConsoleCommand("raiderclan_spawnrole", "<role> [biome] - Spawn a specific raider role with biome gear", (ConsoleEvent)obj9, true, false, false, false, false, (ConsoleOptionsFetcher)obj10, false, false, false);
			object obj11 = <>c.<>9__0_10;
			if (obj11 == null)
			{
				ConsoleEvent val12 = delegate(ConsoleEventArgs args)
				{
					//IL_009c: Unknown result type (might be due to invalid IL or missing references)
					//IL_00a2: Expected O, but got Unknown
					//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
					//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
					//IL_012f: Unknown result type (might be due to invalid IL or missing references)
					if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
					{
						args.Context.AddString("No local player found");
					}
					else if (args.Length < 2)
					{
						args.Context.AddString("Usage: raiderclan_spawngarrison <tower|village> [radius]");
					}
					else
					{
						string text = args[1].ToLowerInvariant();
						float num = 20f;
						if (args.Length >= 3 && float.TryParse(args[2], out var result))
						{
							num = Mathf.Clamp(result, 5f, 50f);
						}
						GameObject val16 = new GameObject("RaiderClans_GarrisonRoot");
						val16.transform.position = ((Component)Player.m_localPlayer).transform.position;
						if (text == "tower")
						{
							RaiderTowerOverwrites.SpawnTowerRaiders(val16);
							args.Context.AddString($"Spawned tower garrison at {val16.transform.position} (radius {num})");
						}
						else if (text == "village")
						{
							RaiderTowerOverwrites.SpawnVillageRaiders(val16);
							args.Context.AddString($"Spawned village garrison at {val16.transform.position} (radius {num})");
						}
						else
						{
							args.Context.AddString("Invalid garrison type. Use 'tower' or 'village'.");
						}
						Object.Destroy((Object)(object)val16);
					}
				};
				<>c.<>9__0_10 = val12;
				obj11 = (object)val12;
			}
			object obj12 = <>c.<>9__0_11;
			if (obj12 == null)
			{
				ConsoleOptionsFetcher val13 = () => new List<string> { "tower", "village" };
				<>c.<>9__0_11 = val13;
				obj12 = (object)val13;
			}
			new ConsoleCommand("raiderclan_spawngarrison", "<tower|village> [radius] - Spawn a raider garrison using tower/village rules", (ConsoleEvent)obj11, true, false, false, false, false, (ConsoleOptionsFetcher)obj12, false, false, false);
			object obj13 = <>c.<>9__0_12;
			if (obj13 == null)
			{
				ConsoleEvent val14 = delegate(ConsoleEventArgs args)
				{
					int result;
					if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
					{
						args.Context.AddString("No local player found");
					}
					else if (args.Length < 2 || !int.TryParse(args[1], out result))
					{
						args.Context.AddString("Usage: raiderclan_wave <waveNumber>");
					}
					else
					{
						if (!RaiderEvents.IsRaidActive())
						{
							RaiderEvents.StartRaidManually();
						}
						MethodInfo methodInfo = AccessTools.Method(typeof(RaiderEvents), "SpawnWave", (Type[])null, (Type[])null);
						for (int i = 0; i < result; i++)
						{
							methodInfo.Invoke(null, null);
						}
						args.Context.AddString($"Spawned raid wave {result}");
					}
				};
				<>c.<>9__0_12 = val14;
				obj13 = (object)val14;
			}
			new ConsoleCommand("raiderclan_wave", "<waveNumber> - Force-spawn a raid wave", (ConsoleEvent)obj13, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			object obj14 = <>c.<>9__0_13;
			if (obj14 == null)
			{
				ConsoleEvent val15 = delegate(ConsoleEventArgs args)
				{
					//IL_002a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0061: Unknown result type (might be due to invalid IL or missing references)
					//IL_0070: Unknown result type (might be due to invalid IL or missing references)
					//IL_007a: Unknown result type (might be due to invalid IL or missing references)
					//IL_007f: Unknown result type (might be due to invalid IL or missing references)
					//IL_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_0086: Unknown result type (might be due to invalid IL or missing references)
					//IL_0098: Unknown result type (might be due to invalid IL or missing references)
					//IL_009e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0052: 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.op_Implicit((Object)(object)Player.m_localPlayer))
					{
						args.Context.AddString("No local player found");
					}
					else
					{
						Biome val16 = (Biome)1;
						if (args.Length >= 2 && Enum.TryParse<Biome>(args[1], ignoreCase: true, out Biome result))
						{
							val16 = result;
						}
						Vector3 val17 = ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 2f;
						RaiderLoot.DropRegularLoot(val17, val16);
						args.Context.AddString($"Spawned regular loot for {val16} biome at {val17}");
					}
				};
				<>c.<>9__0_13 = val15;
				obj14 = (object)val15;
			}
			new ConsoleCommand("raiderclan_spawnloot", "[biome] - Spawn infused loot item", (ConsoleEvent)obj14, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			RaiderClansPlugin.Logger.LogInfo((object)"RaiderClans dev commands registered");
		}
	}
	[HarmonyPatch(typeof(Game), "FixedUpdate")]
	internal class GameFixedUpdatePatch
	{
		private static void Postfix(Game __instance)
		{
			RaiderEvents.Update(Time.fixedDeltaTime);
		}
	}
	[HarmonyPatch(typeof(Character), "OnDeath")]
	internal class CharacterOnDeathPatch
	{
		private static void Postfix(Character __instance)
		{
			bool flag = RaiderAI.IsRaider(__instance);
			if (!flag)
			{
				string text = __instance.m_name ?? string.Empty;
				flag = text.StartsWith("Clan ", StringComparison.OrdinalIgnoreCase) || ((Object)__instance).name.Contains("RaiderClan_Melee") || ((Object)__instance).name.Contains("RaiderClan_Ranged");
			}
			bool flag2 = RaiderAI.IsChieftain(__instance) || __instance.m_name == "Clan Chieftain";
			RaiderClansPlugin.LogDebug($"Character died: {((Object)__instance).name}, isRaider={flag}, isChieftain={flag2}");
			if (flag)
			{
				RaiderEvents.OnRaiderKilled(__instance, identityConfirmed: true, flag2);
			}
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetDamage", new Type[]
	{
		typeof(int),
		typeof(float)
	})]
	internal class ItemDataGetDamagePatch
	{
		private static void Postfix(ItemData __instance, ref DamageTypes __result)
		{
			float infusedDamageBonus = RaiderLoot.GetInfusedDamageBonus(__instance);
			if (infusedDamageBonus > 1f)
			{
				((DamageTypes)(ref __result)).Modify(infusedDamageBonus);
			}
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetArmor", new Type[]
	{
		typeof(int),
		typeof(float)
	})]
	internal class ItemDataGetArmorPatch
	{
		private static void Postfix(ItemData __instance, ref float __result)
		{
			float infusedArmorBonus = RaiderLoot.GetInfusedArmorBonus(__instance);
			if (infusedArmorBonus > 1f)
			{
				__result *= infusedArmorBonus;
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "EquipItem", new Type[]
	{
		typeof(ItemData),
		typeof(bool)
	})]
	internal class HumanoidEquipItemPatch
	{
		private static void Postfix(Humanoid __instance, ItemData item, bool triggerEquipEffects)
		{
			if (!triggerEquipEffects || item == null)
			{
				return;
			}
			float infusedDamageBonus = RaiderLoot.GetInfusedDamageBonus(item);
			float infusedArmorBonus = RaiderLoot.GetInfusedArmorBonus(item);
			if (!(infusedDamageBonus > 1f) && !(infusedArmorBonus > 1f))
			{
				return;
			}
			SEMan sEMan = ((Character)__instance).GetSEMan();
			if (sEMan != null)
			{
				StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Potion_hasty"));
				if ((Object)(object)statusEffect != (Object)null)
				{
					sEMan.AddStatusEffect(statusEffect, false, 0, 0f);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UnequipItem", new Type[]
	{
		typeof(ItemData),
		typeof(bool)
	})]
	internal class HumanoidUnequipItemPatch
	{
		private static void Postfix(Humanoid __instance, ItemData item, bool triggerEquipEffects)
		{
			if (!triggerEquipEffects || item == null)
			{
				return;
			}
			float infusedDamageBonus = RaiderLoot.GetInfusedDamageBonus(item);
			float infusedArmorBonus = RaiderLoot.GetInfusedArmorBonus(item);
			if (!(infusedDamageBonus > 1f) && !(infusedArmorBonus > 1f))
			{
				return;
			}
			SEMan sEMan = ((Character)__instance).GetSEMan();
			if (sEMan != null)
			{
				StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Potion_hasty"));
				if ((Object)(object)statusEffect != (Object)null)
				{
					sEMan.RemoveStatusEffect(statusEffect, false);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(bool),
		typeof(float),
		typeof(int)
	})]
	internal class ItemDataGetTooltipPatch
	{
		private static void Postfix(ItemData item, int qualityLevel, bool crafting, float worldLevel, int stackOverride, ref string __result)
		{
			if (item != null && (RaiderLoot.GetInfusedDamageBonus(item) > 1f || RaiderLoot.GetInfusedArmorBonus(item) > 1f))
			{
				float infusedDamageBonus = RaiderLoot.GetInfusedDamageBonus(item);
				float infusedArmorBonus = RaiderLoot.GetInfusedArmorBonus(item);
				__result += "\n<color=orange>Infused</color>";
				if (infusedDamageBonus > 1f)
				{
					int num = Mathf.RoundToInt((infusedDamageBonus - 1f) * 100f);
					__result += $"\n<color=yellow>+{num}% Damage</color>";
				}
				if (infusedArmorBonus > 1f)
				{
					int num2 = Mathf.RoundToInt((infusedArmorBonus - 1f) * 100f);
					__result += $"\n<color=yellow>+{num2}% Armor</color>";
				}
				__result += "\n<color=yellow>+25% Movement Speed</color>";
			}
		}
	}
	[HarmonyPatch(typeof(Character), "HaveEitr")]
	internal class CharacterHaveEitrPatch
	{
		private static bool Prefix(Character __instance, ref bool __result)
		{
			if (RaiderAI.IsRaider(__instance))
			{
				__result = true;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Character), "UseEitr")]
	internal class CharacterUseEitrPatch
	{
		private static bool Prefix(Character __instance)
		{
			if (RaiderAI.IsRaider(__instance))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Projectile), "FixedUpdate")]
	internal static class ProjectileFixedUpdatePatch
	{
		private static readonly FieldRef<Projectile, ZNetView> NviewRef = AccessTools.FieldRefAccess<Projectile, ZNetView>("m_nview");

		private static readonly FieldRef<Projectile, Character> OwnerRef = AccessTools.FieldRefAccess<Projectile, Character>("m_owner");

		private static readonly HashSet<int> LoggedProjectiles = new HashSet<int>();

		private static void Prefix(Projectile __instance)
		{
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			ZNetView val = NviewRef.Invoke(__instance);
			if ((Object)(object)val == (Object)null || !val.IsValid())
			{
				return;
			}
			Character val2 = OwnerRef.Invoke(__instance);
			if (!((Object)(object)val2 == (Object)null) && RaiderAI.IsRaider(val2) && !val.IsOwner())
			{
				int instanceID = ((Object)__instance).GetInstanceID();
				if (LoggedProjectiles.Add(instanceID))
				{
					ZDO zDO = val.GetZDO();
					long num = ((zDO != null) ? zDO.GetOwner() : 0);
					long num2 = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.GetUID() : 0);
					RaiderClansPlugin.LogDebug($"[ProjectileDebug] Raider projectile not owned locally. owner={val2.m_name} projOwnerPeer={num} localPeer={num2} pos={((Component)__instance).transform.position}");
				}
			}
		}
	}
	[HarmonyPatch(typeof(Projectile), "OnHit")]
	internal static class ProjectileOnHitPatch
	{
		private static readonly FieldRef<Projectile, Character> OwnerRef = AccessTools.FieldRefAccess<Projectile, Character>("m_owner");

		private static readonly FieldRef<Projectile, HitData> OriginalHitDataRef = AccessTools.FieldRefAccess<Projectile, HitData>("m_originalHitData");

		private static readonly FieldRef<Projectile, DamageTypes> DamageRef = AccessTools.FieldRefAccess<Projectile, DamageTypes>("m_damage");

		private static void Prefix(Projectile __instance, Collider collider, Vector3 hitPoint, bool water, Vector3 normal)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			Character val = OwnerRef.Invoke(__instance);
			if (!((Object)(object)val == (Object)null) && RaiderAI.IsRaider(val))
			{
				string text = (Object.op_Implicit((Object)(object)collider) ? ((Object)collider).name : "<null>");
				DamageTypes val2 = DamageRef.Invoke(__instance);
				float totalDamage = ((DamageTypes)(ref val2)).GetTotalDamage();
				HitData obj = OriginalHitDataRef.Invoke(__instance);
				float num = ((obj != null) ? ((DamageTypes)(ref obj.m_damage)).GetTotalDamage() : 0f);
				RaiderClansPlugin.LogDebug($"[ProjectileDebug] OnHit owner={val.m_name} targetCollider={text} water={water} pos={hitPoint} projDamage={totalDamage:F2} originalDamage={num:F2}");
			}
		}
	}
	[BepInPlugin("com.ruijven.raiderclans", "RaiderClans", "1.0.0")]
	internal class RaiderClansPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.ruijven.raiderclans";

		public const string PluginName = "RaiderClans";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Logger;

		public static ConfigEntry<float> DailyRaidChance;

		public static ConfigEntry<float> RaidCheckTimeOfDay;

		public static ConfigEntry<bool> EnableTowerOverwrites;

		public static ConfigEntry<bool> EnableRaidEvents;

		public static ConfigEntry<bool> EnableDebugLogging;

		public static ConfigEntry<string> Wave1Composition;

		public static ConfigEntry<string> Wave2Composition;

		public static ConfigEntry<string> Wave3Composition;

		public static ConfigEntry<string> Wave4Composition;

		public static ConfigEntry<bool> EnableRegularLoot;

		public static ConfigEntry<bool> ChieftainDropInfusedItem;

		public static ConfigEntry<float> InfusedDamageBonus;

		public static ConfigEntry<float> InfusedArmorBonus;

		internal static RaiderClansPlugin Instance { get; private set; }

		private void Awake()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			InitializeConfig();
			Harmony val = new Harmony("com.ruijven.raiderclans");
			val.PatchAll(Assembly.GetExecutingAssembly());
			RaiderAI.Initialize();
			RaiderTowerOverwrites.Initialize();
			((MonoBehaviour)this).StartCoroutine(DelayedInitialization());
			Logger.LogInfo((object)"RaiderClans v1.0.0 loaded successfully!");
		}

		private void OnDestroy()
		{
			RaiderTowerOverwrites.SaveProcessedLocations();
		}

		private void InitializeConfig()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Expected O, but got Unknown
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Expected O, but got Unknown
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Expected O, but got Unknown
			DailyRaidChance = ((BaseUnityPlugin)this).Config.Bind<float>("Raid Events", "DailyRaidChance", 0.15f, new ConfigDescription("Chance for a raid to trigger each day at the specified time (0.0 - 1.0, e.g., 0.15 = 15%)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			RaidCheckTimeOfDay = ((BaseUnityPlugin)this).Config.Bind<float>("Raid Events", "RaidCheckTimeOfDay", 0.6f, new ConfigDescription("Time of day to check for raid trigger (0.0 - 1.0, e.g., 0.6 = just after noon)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			EnableTowerOverwrites = ((BaseUnityPlugin)this).Config.Bind<bool>("Tower Overwrites", "EnableTowerOverwrites", true, new ConfigDescription("Enable Mistlands Dvergr tower overwrites with raiders", (AcceptableValueBase)null, Array.Empty<object>()));
			EnableRaidEvents = ((BaseUnityPlugin)this).Config.Bind<bool>("Raid Events", "EnableRaidEvents", true, new ConfigDescription("Enable custom raid event system", (AcceptableValueBase)null, Array.Empty<object>()));
			EnableDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableDebugLogging", false, new ConfigDescription("Enable verbose debug logging for troubleshooting", (AcceptableValueBase)null, Array.Empty<object>()));
			Wave1Composition = ((BaseUnityPlugin)this).Config.Bind<string>("Raid Waves", "Wave1", "Warrior:2", "Comma-separated Role:Count entries (e.g., Warrior:3,Pillager:1) for wave 1");
			Wave2Composition = ((BaseUnityPlugin)this).Config.Bind<string>("Raid Waves", "Wave2", "Warrior:3,Pillager:1", "Comma-separated Role:Count entries (e.g., Warrior:3,Pillager:1) for wave 2");
			Wave3Composition = ((BaseUnityPlugin)this).Config.Bind<string>("Raid Waves", "Wave3", "Warrior:4,Pillager:2", "Comma-separated Role:Count entries (e.g., Warrior:4,Pillager:2) for wave 3");
			Wave4Composition = ((BaseUnityPlugin)this).Config.Bind<string>("Raid Waves", "Wave4", "Warrior:5,Pillager:3,Chieftain:1", "Comma-separated Role:Count entries (e.g., Warrior:5,Pillager:3,Chieftain:1) for wave 4");
			Wave1Composition.SettingChanged += OnWaveConfigChanged;
			Wave2Composition.SettingChanged += OnWaveConfigChanged;
			Wave3Composition.SettingChanged += OnWaveConfigChanged;
			Wave4Composition.SettingChanged += OnWaveConfigChanged;
			ReloadWaveConfigFromSettings();
			EnableRegularLoot = ((BaseUnityPlugin)this).Config.Bind<bool>("Loot - Regular Raiders", "EnableLoot", true, new ConfigDescription("Enable loot drops for regular raiders", (AcceptableValueBase)null, Array.Empty<object>()));
			ChieftainDropInfusedItem = ((BaseUnityPlugin)this).Config.Bind<bool>("Loot - Chieftains", "DropInfusedItem", true, new ConfigDescription("Whether chieftains drop infused items", (AcceptableValueBase)null, Array.Empty<object>()));
			InfusedDamageBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Loot - Chieftains", "InfusedDamageBonus", 1.2f, new ConfigDescription("Damage bonus multiplier for infused items (e.g., 1.2 = +20% damage)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), Array.Empty<object>()));
			InfusedArmorBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Loot - Chieftains", "InfusedArmorBonus", 1.2f, new ConfigDescription("Armor bonus multiplier for infused items (e.g., 1.2 = +20% armor)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), Array.Empty<object>()));
			void OnWaveConfigChanged(object _, EventArgs __)
			{
				ReloadWaveConfigFromSettings();
			}
		}

		private IEnumerator DelayedInitialization()
		{
			while ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_items.Count == 0)
			{
				yield return null;
			}
			RaiderLoot.Initialize();
			Logger.LogInfo((object)"RaiderClans systems initialized successfully.");
			Logger.LogInfo((object)"Raider prefab will be created when ZNetScene loads.");
		}

		public static void LogDebug(string message)
		{
			if (EnableDebugLogging.Value)
			{
				Logger.LogInfo((object)("[DEBUG] " + message));
			}
		}

		private void ReloadWaveConfigFromSettings()
		{
			RaiderEvents.ConfigureWaves(Wave1Composition?.Value, Wave2Composition?.Value, Wave3Composition?.Value, Wave4Composition?.Value);
		}
	}
	public class RaiderEvents
	{
		private sealed class RaidWaveDefinition
		{
			public int WaveNumber { get; }

			public Dictionary<RaiderRole, int> RoleCounts { get; }

			public RaidWaveDefinition(int waveNumber, Dictionary<RaiderRole, int> roleCounts)
			{
				WaveNumber = waveNumber;
				RoleCounts = roleCounts ?? new Dictionary<RaiderRole, int>();
			}
		}

		private static bool raidActive = false;

		private static Vector3 raidPosition;

		private static Biome raidBiome;

		private static int currentWave = 0;

		private static int raidersKilled = 0;

		private static bool chieftainSpawned = false;

		private static List<Character> activeRaiders = new List<Character>();

		private static float lastRaidCheckTime = -1f;

		private static float nextWaveTime = 0f;

		private const float WAVE_INTERVAL = 30f;

		private static RaidWaveDefinition[] s_waveDefinitions = DefaultWaves;

		private static readonly RaidWaveDefinition[] DefaultWaves = new RaidWaveDefinition[4]
		{
			new RaidWaveDefinition(1, new Dictionary<RaiderRole, int> { 
			{
				RaiderRole.Warrior,
				2
			} }),
			new RaidWaveDefinition(2, new Dictionary<RaiderRole, int>
			{
				{
					RaiderRole.Warrior,
					3
				},
				{
					RaiderRole.Pillager,
					1
				}
			}),
			new RaidWaveDefinition(3, new Dictionary<RaiderRole, int>
			{
				{
					RaiderRole.Warrior,
					4
				},
				{
					RaiderRole.Pillager,
					2
				}
			}),
			new RaidWaveDefinition(4, new Dictionary<RaiderRole, int>
			{
				{
					RaiderRole.Warrior,
					5
				},
				{
					RaiderRole.Pillager,
					3
				},
				{
					RaiderRole.Chieftain,
					1
				}
			})
		};

		public static void StartRaidManually()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Biome highestUnlockedBiome = GetHighestUnlockedBiome();
			StartRaidManually(highestUnlockedBiome);
		}

		public static void StartRaidManually(Biome biome)
		{
			//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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				RaiderClansPlugin.Logger.LogWarning((object)"No local player found for manual raid start");
				return;
			}
			if (raidActive)
			{
				RaiderClansPlugin.Logger.LogWarning((object)"Raid already active");
				return;
			}
			Vector3 position = ((Component)Player.m_localPlayer).transform.position;
			RaiderClansPlugin.Logger.LogInfo((object)$"Manually starting raid at {position}, biome: {biome}");
			StartRaid(position, biome);
		}

		public static void Update(float dt)
		{
			if (RaiderClansPlugin.EnableRaidEvents.Value && ZNet.instance.IsServer())
			{
				CheckDailyRaidTrigger();
				UpdateRaidState(dt);
			}
		}

		private static void CheckDailyRaidTrigger()
		{
			float dayFraction = EnvMan.instance.GetDayFraction();
			float value = RaiderClansPlugin.RaidCheckTimeOfDay.Value;
			if (lastRaidCheckTime < 0f || dayFraction < lastRaidCheckTime)
			{
				lastRaidCheckTime = dayFraction;
			}
			else if (dayFraction >= value && lastRaidCheckTime < value)
			{
				lastRaidCheckTime = dayFraction;
				if (Random.value <= RaiderClansPlugin.DailyRaidChance.Value)
				{
					StartRaid();
				}
			}
		}

		private static void StartRaid()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			if (raidActive)
			{
				RaiderClansPlugin.LogDebug("Raid already active, skipping StartRaid");
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				RaiderClansPlugin.Logger.LogWarning((object)"No local player found for raid start");
				return;
			}
			Biome biome = WorldGenerator.instance.GetBiome(((Component)localPlayer).transform.position);
			raidBiome = GetHighestUnlockedBiome();
			raidPosition = ((Component)localPlayer).transform.position;
			raidActive = true;
			currentWave = 0;
			raidersKilled = 0;
			chieftainSpawned = false;
			activeRaiders.Clear();
			nextWaveTime = Time.time;
			RaiderClansPlugin.Logger.LogInfo((object)$"Starting raid in biome: {raidBiome} at position {raidPosition}");
			RaiderClansPlugin.LogDebug($"Player biome: {biome}, Raid biome: {raidBiome}");
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Raiders are attacking!", 0, (Sprite)null);
			}
		}

		private static void StartRaid(Vector3 position, Biome biome)
		{
			//IL_0018: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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 (raidActive)
			{
				RaiderClansPlugin.LogDebug("Raid already active, skipping StartRaid");
				return;
			}
			raidBiome = biome;
			raidPosition = position;
			raidActive = true;
			currentWave = 0;
			raidersKilled = 0;
			chieftainSpawned = false;
			activeRaiders.Clear();
			nextWaveTime = Time.time;
			RaiderClansPlugin.Logger.LogInfo((object)$"Starting raid in biome: {raidBiome} at position {raidPosition}");
		}

		private static Biome GetHighestUnlockedBiome()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_0073: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			ZoneSystem instance = ZoneSystem.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return (Biome)1;
			}
			if (instance.GetGlobalKey("defeated_queen"))
			{
				return (Biome)32;
			}
			if (instance.GetGlobalKey("defeated_bonemass"))
			{
				return (Biome)512;
			}
			if (instance.GetGlobalKey("defeated_goblinking"))
			{
				return (Biome)16;
			}
			if (instance.GetGlobalKey("defeated_dragon"))
			{
				return (Biome)4;
			}
			if (instance.GetGlobalKey("defeated_greydwarf"))
			{
				return (Biome)2;
			}
			if (instance.GetGlobalKey("defeated_eikthyr"))
			{
				return (Biome)8;
			}
			return (Biome)1;
		}

		private static void SpawnWave()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			RaidWaveDefinition[] waveDefinitions = GetWaveDefinitions();
			int num = currentWave;
			if (num >= waveDefinitions.Length)
			{
				RaiderClansPlugin.LogDebug("No additional wave definitions available.");
				return;
			}
			RaidWaveDefinition raidWaveDefinition = waveDefinitions[num];
			currentWave++;
			int num2 = 0;
			foreach (KeyValuePair<RaiderRole, int> roleCount in raidWaveDefinition.RoleCounts)
			{
				RaiderRole key = roleCount.Key;
				int num3 = Mathf.Max(0, roleCount.Value);
				for (int i = 0; i < num3; i++)
				{
					Vector3 distributedSpawnPosition = GetDistributedSpawnPosition();
					Humanoid val = RaiderAI.SpawnRaider(new RaiderAI.RaiderSpawnRequest(distributedSpawnPosition, raidBiome, key));
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					Character component = ((Component)val).GetComponent<Character>();
					if ((Object)(object)component != (Object)null)
					{
						activeRaiders.Add(component);
					}
					if (key == RaiderRole.Chieftain && !chieftainSpawned)
					{
						chieftainSpawned = true;
						if ((Object)(object)Player.m_localPlayer != (Object)null)
						{
							((Character)Player.m_localPlayer).Message((MessageType)2, "The Clan Chieftain has entered the fray!", 0, (Sprite)null);
						}
						RaiderClansPlugin.Logger.LogInfo((object)"Chieftain spawned with wave");
					}
					num2++;
				}
			}
			RaiderClansPlugin.Logger.LogInfo((object)$"Wave {raidWaveDefinition.WaveNumber}: Spawned {num2} raiders");
		}

		private static Vector3 GetDistributedSpawnPosition()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//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_004b: Unknown result type (might be due to invalid IL or missing references)
			float num = Random.Range(18f, 32f);
			float num2 = Random.Range(0f, MathF.PI * 2f);
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(Mathf.Cos(num2) * num, 0f, Mathf.Sin(num2) * num);
			return raidPosition + val;
		}

		private static void UpdateRaidState(float dt)
		{
			if (!raidActive)
			{
				return;
			}
			activeRaiders.RemoveAll((Character r) => (Object)(object)r == (Object)null || r.IsDead());
			RaidWaveDefinition[] waveDefinitions = GetWaveDefinitions();
			if (currentWave < waveDefinitions.Length && Time.time >= nextWaveTime)
			{
				SpawnWave();
				if (currentWave < waveDefinitions.Length)
				{
					nextWaveTime = Time.time + 30f;
				}
			}
			if (chieftainSpawned)
			{
				Character val = activeRaiders.Find((Character r) => RaiderAI.IsChieftain(r));
				if ((Object)(object)val == (Object)null || val.IsDead())
				{
					MakeRaidersFlee();
					EndRaid();
				}
			}
			else if (currentWave >= waveDefinitions.Length && activeRaiders.Count == 0)
			{
				EndRaid();
			}
		}

		public static void ConfigureWaves(params string[] waveDefinitions)
		{
			if (waveDefinitions == null || waveDefinitions.Length == 0)
			{
				s_waveDefinitions = DefaultWaves;
				RaiderClansPlugin.Logger.LogInfo((object)"Using default raid wave definitions.");
				return;
			}
			List<RaidWaveDefinition> list = new List<RaidWaveDefinition>();
			for (int i = 0; i < waveDefinitions.Length; i++)
			{
				Dictionary<RaiderRole, int> roleCounts = ParseWaveDefinition(waveDefinitions[i], i);
				list.Add(new RaidWaveDefinition(i + 1, roleCounts));
			}
			s_waveDefinitions = list.ToArray();
			RaiderClansPlugin.Logger.LogInfo((object)"Raid wave definitions reloaded from configuration.");
		}

		private static RaidWaveDefinition[] GetWaveDefinitions()
		{
			return s_waveDefinitions ?? DefaultWaves;
		}

		private static Dictionary<RaiderRole, int> ParseWaveDefinition(string config, int fallbackIndex)
		{
			Dictionary<RaiderRole, int> dictionary = new Dictionary<RaiderRole, int>();
			if (!string.IsNullOrWhiteSpace(config))
			{
				string[] array = config.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				string[] array2 = array;
				foreach (string text in array2)
				{
					string text2 = text.Trim();
					if (text2.Length == 0)
					{
						continue;
					}
					string[] array3 = text2.Split(new char[2] { ':', '=' }, StringSplitOptions.RemoveEmptyEntries);
					if (array3.Length == 2)
					{
						int result2;
						if (!Enum.TryParse<RaiderRole>(array3[0].Trim(), ignoreCase: true, out var result))
						{
							RaiderClansPlugin.Logger.LogWarning((object)("Unknown raider role '" + array3[0] + "' in wave config '" + config + "'"));
						}
						else if (!int.TryParse(array3[1].Trim(), out result2) || result2 <= 0)
						{
							RaiderClansPlugin.Logger.LogWarning((object)$"Invalid count '{array3[1]}' for role '{result}' in wave config '{config}'");
						}
						else if (dictionary.ContainsKey(result))
						{
							dictionary[result] += result2;
						}
						else
						{
							dictionary[result] = result2;
						}
					}
				}
			}
			if (dictionary.Count == 0)
			{
				return CloneRoleCounts(DefaultWaves[Mathf.Clamp(fallbackIndex, 0, DefaultWaves.Length - 1)]);
			}
			return dictionary;
		}

		private static Dictionary<RaiderRole, int> CloneRoleCounts(RaidWaveDefinition definition)
		{
			Dictionary<RaiderRole, int> dictionary = new Dictionary<RaiderRole, int>();
			foreach (KeyValuePair<RaiderRole, int> roleCount in definition.RoleCounts)
			{
				dictionary[roleCount.Key] = roleCount.Value;
			}
			return dictionary;
		}

		private static void MakeRaidersFlee()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			foreach (Character activeRaider in activeRaiders)
			{
				if ((Object)(object)activeRaider != (Object)null && !activeRaider.IsDead() && !RaiderAI.IsChieftain(activeRaider))
				{
					BaseAI component = ((Component)activeRaider).GetComponent<BaseAI>();
					if ((Object)(object)component != (Object)null)
					{
						component.Flee(0f, Vector3.zero);
					}
				}
			}
		}

		private static void EndRaid()
		{
			raidActive = false;
			currentWave = 0;
			raidersKilled = 0;
			chieftainSpawned = false;
			activeRaiders.Clear();
			RaiderClansPlugin.Logger.LogInfo((object)"Raid ended");
		}

		public static void OnRaiderKilled(Character raider, bool identityConfirmed = false, bool chieftainConfirmed = false)
		{
			//IL_00c4: 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)
			if ((Object)(object)raider == (Object)null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			bool flag = identityConfirmed || RaiderAI.IsRaider(raider);
			if (!flag)
			{
				string text = raider.m_name ?? string.Empty;
				flag = text.StartsWith("Clan ", StringComparison.OrdinalIgnoreCase);
			}
			if (flag)
			{
				raidersKilled++;
				RaiderClansPlugin.Logger.LogInfo((object)$"Raider killed. Total: {raidersKilled}");
				if (chieftainConfirmed || RaiderAI.IsChieftain(raider))
				{
					RaiderLoot.DropInfusedItem(((Component)raider).transform.position, raidBiome);
					MakeRaidersFlee();
					EndRaid();
				}
			}
		}

		public static bool IsRaidActive()
		{
			return raidActive;
		}
	}
	[HarmonyPatch]
	internal class RaiderHarmonyPatches
	{
		private static bool IsRaider(Character character)
		{
			if ((Object)(object)character == (Object)null)
			{
				return false;
			}
			string name = ((Object)character).name;
			return name.Contains("RaiderClan_Melee") || name.Contains("RaiderClan_Ranged");
		}

		[HarmonyPatch(typeof(Attack), "UseAmmo")]
		[HarmonyPrefix]
		private static bool UseAmmo_Prefix(Attack __instance, ref bool __result)
		{
			if ((Object)(object)__instance?.m_character != (Object)null && IsRaider((Character)(object)__instance.m_character))
			{
				__result = true;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Character), "Awake")]
		[HarmonyPostfix]
		private static void IdentityInjection_Postfix(Character __instance)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if (!IsRaider(__instance))
			{
				return;
			}
			ZNetView nview = __instance.m_nview;
			if (nview != null)
			{
				ZDO zDO = nview.GetZDO();
				if (zDO != null)
				{
					zDO.Set("RaiderClans_IsRaider", true);
				}
			}
			ZNetView nview2 = __instance.m_nview;
			ZDO val = ((nview2 != null) ? nview2.GetZDO() : null);
			if (val != null)
			{
				int num = val.GetInt("RaiderClans_Biome", 1);
				Biome val2 = (Biome)num;
				RaiderClansPlugin.LogDebug($"[AWAKE] Retrieved biome from ZDO: {val2} (int: {num})");
				CharacterDrop component = ((Component)__instance).GetComponent<CharacterDrop>();
				RaiderLoot.ConfigureCharacterDrop(component, val2);
			}
		}

		[HarmonyPatch(typeof(MonsterAI), "UpdateAI")]
		[HarmonyPostfix]
		private static void PathfindingFallback_Postfix(MonsterAI __instance, float dt)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			Character component = ((Component)__instance).GetComponent<Character>();
			if (IsRaider(component) && (Object)(object)__instance.m_targetCreature != (Object)null && !((BaseAI)__instance).HavePath(((Component)__instance.m_targetCreature).transform.position))
			{
				Vector3 position = ((Component)__instance.m_targetCreature).transform.position;
				Vector3 position2 = ((Component)__instance).transform.position;
				Vector3 val = position - position2;
				val.y = 0f;
				((Vector3)(ref val)).Normalize();
				((BaseAI)__instance).MoveTo(dt, position2 + val, 5f, ((BaseAI)__instance).IsAlerted());
			}
		}

		[HarmonyPatch(typeof(Character), "OnRagdollCreated")]
		[HarmonyPrefix]
		private static bool SkipRagdoll_Prefix(Character __instance, Ragdoll ragdoll)
		{
			if (IsRaider(__instance))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Humanoid), "EquipBestWeapon")]
		[HarmonyPrefix]
		private static bool PreventWeaponSwitching_Prefix(Humanoid __instance)
		{
			if ((Object)(object)__instance != (Object)null && IsRaider((Character)(object)__instance))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Character), "SetVisible")]
		[HarmonyPrefix]
		private static void SetVisibleLogging_Prefix(Character __instance, bool visible)
		{
			if ((Object)(object)__instance != (Object)null && IsRaider(__instance))
			{
				ZNetView nview = __instance.m_nview;
				ZDO val = ((nview != null) ? nview.GetZDO() : null);
				RaiderClansPlugin.LogDebug($"[VISIBILITY] {((Object)__instance).name} SetVisible({visible}) HasOwner={((val != null) ? new bool?(val.HasOwner()) : ((bool?)null))} Owner={((val != null) ? new long?(val.GetOwner()) : ((long?)null))} IsOwner={((val != null) ? new bool?(val.IsOwner()) : ((bool?)null))} IsValid={((val != null) ? new bool?(val.IsValid()) : ((bool?)null))}");
			}
		}

		[HarmonyPatch(typeof(BaseAI), "FindEnemy")]
		[HarmonyPrefix]
		private static bool EnforceStructurePriority_Prefix(BaseAI __instance, ref Character __result)
		{
			MonsterAI val = (MonsterAI)(object)((__instance is MonsterAI) ? __instance : null);
			if (val != null)
			{
				PillagerBehavior component = ((Component)val).GetComponent<PillagerBehavior>();
				if ((Object)(object)component != (Object)null && component.ShouldPreferStructureTarget())
				{
					__result = null;
					return false;
				}
			}
			return true;
		}
	}
	public class RaiderLoot
	{
		private const string InfusedDamageKey = "RaiderClans_InfusedDamage";

		private const string InfusedArmorKey = "RaiderClans_InfusedArmor";

		private static Dictionary<Biome, List<string>> biomeMaterialDrops;

		private static Dictionary<Biome, string> biomeRareCores;

		public static void ConfigureCharacterDrop(CharacterDrop charDrop, Biome biome)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0093: Unknown result type (might be due to invalid IL