Decompiled source of VikingFactions v0.1.0

VikingFactions.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
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.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;
using VikingAI.Core;
using VikingAI.NPC.Affordances;
using VikingAI.NPC.Prefabs;
using VikingAI.Profiles;
using VikingAI.Simulation;
using VikingAI.Tactics;
using VikingFactions.Configuration;
using VikingFactions.Core;
using VikingFactions.Marauders;
using VikingFactions.Telemetry;
using VikingFactions.Wayfarers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("DigitalVikings")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+b6666f0c545d294537dbbdd0de1bace62fa14cf3")]
[assembly: AssemblyProduct("VikingFactions")]
[assembly: AssemblyTitle("VikingFactions")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 VikingFactions
{
	public static class FactionPrefabs
	{
		public static void RegisterAll()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00be: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: 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_015c: Expected O, but got Unknown
			HumanoidPrefabConfig val = new HumanoidPrefabConfig();
			val.PrefabName = "VF_Wayfarer";
			val.DisplayName = "Wayfarer";
			val.Faction = (Faction)0;
			val.Group = "VF_Wayfarers";
			val.MaxHealth = 90f;
			val.IsAggravatable = false;
			val.DefaultItemNames = new string[3] { "ArmorRagsChest", "ArmorRagsLegs", "CapeDeerHide" };
			val.BehaviorProfile = AgentBehaviorProfile.CreateVillagerDefault("VF_Wayfarer", (NpcRoleFlags)65536);
			HumanoidPrefabBuilder.CreateHumanoidNpcPrefab(val);
			if (RaiderFactionRegistry.TryGetFaction("marauders", out IRaiderFactionDefinition definition))
			{
				HumanoidPrefabBuilder.CreateHumanoidNpcPrefab(new HumanoidPrefabConfig
				{
					PrefabName = "VF_Marauder",
					DisplayName = "Exile Marauder",
					Faction = (Faction)7,
					Group = "VF_Marauders",
					MaxHealth = 160f,
					IsAggravatable = true,
					DefaultItemNames = definition.RaiderDefaultEquipment,
					BehaviorProfile = AgentBehaviorProfile.CreateVillagerDefault("VF_Marauder", (NpcRoleFlags)131072)
				});
				HumanoidPrefabBuilder.CreateHumanoidNpcPrefab(new HumanoidPrefabConfig
				{
					PrefabName = "VF_Warlord",
					DisplayName = "Marauder Warlord",
					Faction = (Faction)7,
					Group = "VF_Marauders",
					MaxHealth = 700f,
					IsAggravatable = true,
					DefaultItemNames = definition.WarlordDefaultEquipment,
					BehaviorProfile = AgentBehaviorProfile.CreateVillagerDefault("VF_Warlord", (NpcRoleFlags)131072)
				});
			}
		}
	}
	[BepInPlugin("com.digitalvikings.vikingfactions", "VikingFactions", "0.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class VikingFactionsPlugin : BaseUnityPlugin
	{
		public const string ModGuid = "com.digitalvikings.vikingfactions";

		public const string ModName = "VikingFactions";

		public const string ModVersion = "0.1.0";

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"VikingFactions v0.1.0 initializing...");
			ModConfig.Init(((BaseUnityPlugin)this).Config);
			RaiderFactionRegistry.RegisterBuiltInFactions();
			BrainPipeline.RegisterModule((IAIBrainModule)(object)new WayfarerBrainModule());
			BrainPipeline.RegisterModule((IAIBrainModule)(object)new MarauderHeistBrainModule());
			VirtualAgentDirector.RegisterTask((IVirtualAgentTask)(object)new WayfarerVirtualTask());
			VirtualAgentDirector.RegisterTask((IVirtualAgentTask)(object)new MarauderVirtualTask());
			VirtualAgentDirector.OnAgentRestored += OnAgentRestoredAfterWorldLoad;
			PrefabManager.OnVanillaPrefabsAvailable += FactionPrefabs.RegisterAll;
			VikingFactionsConsoleCommand.Register();
			_harmony = new Harmony("com.digitalvikings.vikingfactions");
			_harmony.PatchAll();
			Log.LogInfo((object)"VikingFactions v0.1.0 loaded successfully.");
		}

		private void Update()
		{
			if (ModConfig.ModEnabled.Value)
			{
				HospitalityScanner.Tick();
			}
		}

		private void OnDestroy()
		{
			VirtualAgentDirector.OnAgentRestored -= OnAgentRestoredAfterWorldLoad;
			PrefabManager.OnVanillaPrefabsAvailable -= FactionPrefabs.RegisterAll;
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private static void OnAgentRestoredAfterWorldLoad(ZDO zdo)
		{
			if (zdo != null && zdo.IsValid())
			{
				if (zdo.GetPrefab() == StringExtensionMethods.GetStableHashCode("VF_Wayfarer"))
				{
					HospitalityScanner.RegisterWayfarer(zdo);
				}
				else if (zdo.GetInt("VF_Raider_State", -1) >= 0)
				{
					RaiderCampDirector.RegisterCampPiece(zdo);
				}
			}
		}
	}
}
namespace VikingFactions.Wayfarers
{
	public static class HospitalityScanner
	{
		public const string WayfarerPrefabName = "VF_Wayfarer";

		private static float _nextScanTime;

		private static float _lastSpawnTime = -9999f;

		private static readonly HashSet<ZDO> _wayfarerZdos = new HashSet<ZDO>();

		public static int LastEvaluatedComfort { get; private set; }

		public static Vector3 LastQualifyingHearthPos { get; private set; }

		public static int ActiveWayfarerCount { get; private set; }

		public static void RegisterWayfarer(ZDO zdo)
		{
			if (zdo != null)
			{
				_wayfarerZdos.Add(zdo);
			}
		}

		public static void Tick()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.ModEnabled.Value && ModConfig.EnableWayfarers.Value && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				float time = Time.time;
				if (!(time < _nextScanTime))
				{
					_nextScanTime = time + 15f;
					EvaluateAndSchedule(((Component)Player.m_localPlayer).transform.position, time);
				}
			}
		}

		public static bool TryFindQualifyingHearth(Vector3 origin, out Vector3 hearthPos, out int comfort)
		{
			//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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_009d: 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)
			hearthPos = Vector3.zero;
			comfort = 0;
			int num = 0;
			float num2 = 3600f;
			float num3 = default(float);
			bool flag = default(bool);
			foreach (Fireplace fireplace in PieceRegistry.Fireplaces)
			{
				if ((Object)(object)fireplace == (Object)null)
				{
					continue;
				}
				Vector3 val = ((Component)fireplace).transform.position - origin;
				if (((Vector3)(ref val)).sqrMagnitude > num2 || !fireplace.IsBurning())
				{
					continue;
				}
				Vector3 val2 = ((Component)fireplace).transform.position + Vector3.up * 0.8f;
				Cover.GetCoverForPoint(val2, ref num3, ref flag, 0.5f);
				if (flag || !(num3 < 0.7f))
				{
					int num4 = SE_Rested.CalculateComfortLevel(true, val2);
					if (num4 > num)
					{
						num = num4;
						hearthPos = ((Component)fireplace).transform.position;
					}
				}
			}
			if (num < ModConfig.MinHospitalityComfort.Value)
			{
				return false;
			}
			comfort = num;
			return true;
		}

		private static void EvaluateAndSchedule(Vector3 playerPos, float now)
		{
			//IL_0000: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			if (!TryFindQualifyingHearth(playerPos, out var hearthPos, out var comfort))
			{
				LastEvaluatedComfort = 0;
				return;
			}
			LastEvaluatedComfort = comfort;
			LastQualifyingHearthPos = hearthPos;
			int num = Mathf.Max(1, comfort / Mathf.Max(1, ModConfig.ComfortPerWayfarerCap.Value));
			int num2 = (ActiveWayfarerCount = CountActiveWayfarers());
			if (num2 < num && !(now - _lastSpawnTime < ModConfig.WayfarerSpawnIntervalSeconds.Value) && SpawnWayfarerTowards(hearthPos))
			{
				_lastSpawnTime = now;
				ActiveWayfarerCount = num2 + 1;
			}
		}

		public static int CountActiveWayfarers()
		{
			int num = 0;
			_wayfarerZdos.RemoveWhere((ZDO z) => z == null || !z.IsValid());
			foreach (ZDO wayfarerZdo in _wayfarerZdos)
			{
				if (wayfarerZdo.GetInt("VF_WF_State", 0) != 2)
				{
					num++;
				}
			}
			return num;
		}

		public static bool SpawnWayfarerTowards(Vector3 hearthPos, float minDist = 150f, float maxDist = 280f)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0023: 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_0062: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			if (!FindValidLandPoint(hearthPos, minDist, maxDist, out var pos))
			{
				return false;
			}
			Vector3 val = pos;
			Vector3 val2 = hearthPos - pos;
			ZDO val3 = VirtualAgentDirector.SpawnVirtualAgentZdo("VF_Wayfarer", val, Quaternion.LookRotation(((Vector3)(ref val2)).normalized), (NpcRoleFlags)65536, true);
			if (val3 == null)
			{
				return false;
			}
			double timeSeconds = ZNet.instance.GetTimeSeconds();
			val3.Set("VF_WF_State", 0);
			val3.Set("VF_WF_TargetPos", hearthPos);
			val3.Set("VF_WF_OriginPos", pos);
			val3.Set("VF_WF_LastMeal", (float)timeSeconds);
			val3.Set("VF_WF_Mood", 0);
			val3.Set("VF_WF_Since", (float)timeSeconds);
			RegisterWayfarer(val3);
			VikingFactionsPlugin.Log.LogInfo((object)$"[Hospitality] Wayfarer dispatched from {pos:F0} toward hearth {hearthPos:F0} (comfort {LastEvaluatedComfort}).");
			return true;
		}

		public static bool FindValidLandPoint(Vector3 center, float minDist, float maxDist, out Vector3 pos)
		{
			//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_0052: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Invalid comparison between Unknown and I4
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			pos = Vector3.zero;
			if (WorldGenerator.instance == null)
			{
				return false;
			}
			float num = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : 30f);
			for (int i = 0; i < 24; i++)
			{
				float num2 = Random.Range(0f, MathF.PI * 2f);
				float num3 = Random.Range(minDist, maxDist);
				Vector3 val = center + new Vector3(Mathf.Cos(num2) * num3, 0f, Mathf.Sin(num2) * num3);
				Biome biome = WorldGenerator.instance.GetBiome(val.x, val.z, 0.02f, false);
				if ((int)biome != 256 && (int)biome != 0)
				{
					float height = WorldGenerator.instance.GetHeight(val.x, val.z);
					if (!(height <= num + 1.2f))
					{
						val.y = height;
						pos = val;
						return true;
					}
				}
			}
			return false;
		}
	}
	public sealed class WayfarerBrainModule : IAIBrainModule
	{
		private sealed class LocalState
		{
			public float NextChat = Time.time + Random.Range(15f, 35f);

			public float NextBedCheck;

			public float Neglect;

			public Component? Bed;
		}

		private const float MovingScore = 60f;

		private const float ServiceScore = 50f;

		private static readonly string[] _happy = new string[4] { "A warm fire and good company!", "May Odin bless this hall.", "Fine shelter from the wilds.", "Nothing beats a hot hearth after a long march." };

		private static readonly string[] _hungry = new string[3] { "The larders in this hall are bare...", "My stomach rumbles. Is there no food to spare?", "A warm fire, yet an empty table." };

		private static readonly string[] _noBed = new string[2] { "Not a spare bunk in the hall tonight...", "Sleeping on the floorboards again, it seems." };

		private static readonly string[] _depart = new string[2] { "The hearth grows cold. Time to move on.", "Safe travels, friend. I must return to the road." };

		private static readonly ConditionalWeakTable<Character, LocalState> _states = new ConditionalWeakTable<Character, LocalState>();

		public string Id => "VikingFactions.WayfarerHospitality";

		private static LocalState GetState(Character c)
		{
			return _states.GetValue(c, (Character _) => new LocalState());
		}

		private static bool IsWayfarer(Character c, out ZDO zdo)
		{
			zdo = null;
			ZNetView nView = AgentProfileRegistry.GetNView(c);
			if ((Object)(object)nView == (Object)null || !nView.IsValid() || !nView.IsOwner())
			{
				return false;
			}
			zdo = nView.GetZDO();
			if (zdo != null)
			{
				return zdo.GetPrefab() == StringExtensionMethods.GetStableHashCode("VF_Wayfarer");
			}
			return false;
		}

		public float EvaluateUtility(BaseAI ai, Character character, AgentBehaviorProfile profile)
		{
			if (!ModConfig.ModEnabled.Value || !ModConfig.EnableWayfarers.Value)
			{
				return 0f;
			}
			if (!IsWayfarer(character, out ZDO zdo))
			{
				return 0f;
			}
			MonsterAI val = (MonsterAI)(object)((ai is MonsterAI) ? ai : null);
			if (val != null && (Object)(object)((BaseAI)val).GetTargetCreature() != (Object)null)
			{
				return 0f;
			}
			if (zdo.GetInt("VF_WF_State", 0) != 1)
			{
				return 60f;
			}
			LocalState state = GetState(character);
			double timeSeconds = ZNet.instance.GetTimeSeconds();
			if (timeSeconds - (double)zdo.GetFloat("VF_WF_LastMeal", (float)timeSeconds) >= (double)ModConfig.WayfarerMealIntervalSeconds.Value || EnvMan.IsNight() || state.Neglect >= 120f)
			{
				return 50f;
			}
			CheckHearthUpkeep(character, state, Time.deltaTime);
			AmbientChatter(character, zdo, state);
			return 0f;
		}

		public bool Tick(BaseAI ai, Character character, AgentBehaviorProfile profile, float dt)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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 (!IsWayfarer(character, out ZDO zdo))
			{
				return false;
			}
			LocalState state = GetState(character);
			int num = zdo.GetInt("VF_WF_State", 0);
			Vector3 position = ((Component)character).transform.position;
			switch (num)
			{
			case 0:
			{
				Vector3 vec2 = zdo.GetVec3("VF_WF_TargetPos", position);
				if (Utils.DistanceXZ(position, vec2) <= 8f)
				{
					zdo.Set("VF_WF_State", 1);
					zdo.Set("VF_WF_Since", (float)ZNet.instance.GetTimeSeconds());
					ai.StopMoving();
					AiHelpers.Say(character, "Hail! May a weary traveler share your hearth?");
					return true;
				}
				AiHelpers.MoveTo(ai, dt, vec2, 3f, run: false);
				return true;
			}
			case 2:
			{
				ReleaseBed(character, state);
				Vector3 vec = zdo.GetVec3("VF_WF_OriginPos", position);
				if (Utils.DistanceXZ(position, vec) <= 10f)
				{
					if (ZDOMan.instance != null)
					{
						ZDOMan.instance.DestroyZDO(zdo);
					}
					return true;
				}
				AiHelpers.MoveTo(ai, dt, vec, 3f, run: false);
				return true;
			}
			default:
			{
				CheckHearthUpkeep(character, state, dt);
				if (state.Neglect >= 120f)
				{
					AiHelpers.Say(character, _depart[Random.Range(0, _depart.Length)]);
					zdo.Set("VF_WF_State", 2);
					return true;
				}
				double timeSeconds = ZNet.instance.GetTimeSeconds();
				if (timeSeconds - (double)zdo.GetFloat("VF_WF_LastMeal", (float)timeSeconds) >= (double)ModConfig.WayfarerMealIntervalSeconds.Value && TryMeal(ai, character, zdo, state, timeSeconds, dt))
				{
					return true;
				}
				if (EnvMan.IsNight())
				{
					if (TrySleep(ai, character, state, dt))
					{
						return true;
					}
				}
				else
				{
					ReleaseBed(character, state);
				}
				AmbientChatter(character, zdo, state);
				return false;
			}
			}
		}

		private static bool TryMeal(BaseAI ai, Character character, ZDO zdo, LocalState local, double now, float dt)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			Container val = null;
			ItemData val2 = null;
			float num = float.MaxValue;
			Vector3 position = ((Component)character).transform.position;
			foreach (Container container in PieceRegistry.Containers)
			{
				if ((Object)(object)container == (Object)null)
				{
					continue;
				}
				Vector3 val3 = ((Component)container).transform.position - position;
				float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
				if (sqrMagnitude > 484f || sqrMagnitude >= num || container.IsInUse())
				{
					continue;
				}
				Inventory inventory = container.GetInventory();
				if (inventory == null)
				{
					continue;
				}
				List<ItemData> allItems = inventory.GetAllItems();
				for (int i = 0; i < allItems.Count; i++)
				{
					ItemData val4 = allItems[i];
					if (val4?.m_shared != null && val4.m_shared.m_food > 0f)
					{
						num = sqrMagnitude;
						val = container;
						val2 = val4;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null || val2 == null)
			{
				zdo.Set("VF_WF_Mood", -1);
				local.Neglect += dt * 1.5f;
				if (Time.time >= local.NextChat)
				{
					local.NextChat = Time.time + Random.Range(35f, 60f);
					AiHelpers.Say(character, _hungry[Random.Range(0, _hungry.Length)]);
				}
				return false;
			}
			if (Vector3.Distance(position, ((Component)val).transform.position) > 2.2f)
			{
				AiHelpers.MoveTo(ai, dt, ((Component)val).transform.position, 1.8f, run: false);
				return true;
			}
			ai.StopMoving();
			AiHelpers.LookAt(ai, ((Component)val).transform.position);
			ZNetView component = ((Component)val).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				component.ClaimOwnership();
			}
			string name = val2.m_shared.m_name;
			val.GetInventory().RemoveOneItem(val2);
			zdo.Set("VF_WF_LastMeal", (float)now);
			zdo.Set("VF_WF_Mood", 1);
			local.Neglect = Mathf.Max(0f, local.Neglect - 45f);
			character.Heal(25f, true);
			AiHelpers.Say(character, "Grateful for the " + Localization.instance.Localize(name) + "!");
			local.NextChat = Time.time + Random.Range(45f, 90f);
			return true;
		}

		private static bool TrySleep(BaseAI ai, Character character, LocalState local, float dt)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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)
			Vector3 position = ((Component)character).transform.position;
			if ((Object)(object)local.Bed == (Object)null)
			{
				if (Time.time < local.NextBedCheck)
				{
					return false;
				}
				local.NextBedCheck = Time.time + 8f;
				Bed val = null;
				float num = 576f;
				foreach (Bed bed in PieceRegistry.Beds)
				{
					if (!((Object)(object)bed == (Object)null) && !AffordanceRegistry.IsReservedByOther((Component)(object)bed, character) && !PlayerInBed(bed))
					{
						Vector3 val2 = ((Component)bed).transform.position - position;
						float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
						if (sqrMagnitude < num)
						{
							num = sqrMagnitude;
							val = bed;
						}
					}
				}
				if (!((Object)(object)val != (Object)null) || !AffordanceRegistry.TryReserve((Component)(object)val, character, 60f))
				{
					if (Time.time >= local.NextChat)
					{
						local.NextChat = Time.time + Random.Range(45f, 80f);
						AiHelpers.Say(character, _noBed[Random.Range(0, _noBed.Length)]);
					}
					return false;
				}
				local.Bed = (Component?)(object)val;
			}
			AffordanceRegistry.TryReserve(local.Bed, character, 30f);
			Vector3 position2 = local.Bed.transform.position;
			if (Vector3.Distance(position, position2) > 2f)
			{
				AiHelpers.MoveTo(ai, dt, position2, 1.6f, run: false);
				return true;
			}
			ai.StopMoving();
			ZSyncAnimation component = ((Component)character).GetComponent<ZSyncAnimation>();
			if (component != null)
			{
				component.SetBool("attach_bed", true);
			}
			return true;
		}

		private static void ReleaseBed(Character character, LocalState local)
		{
			if (!((Object)(object)local.Bed == (Object)null))
			{
				AffordanceRegistry.ReleaseReservation(local.Bed, character);
				local.Bed = null;
				ZSyncAnimation component = ((Component)character).GetComponent<ZSyncAnimation>();
				if (component != null)
				{
					component.SetBool("attach_bed", false);
				}
			}
		}

		private static bool PlayerInBed(Bed bed)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			List<Player> allPlayers = Player.GetAllPlayers();
			for (int i = 0; i < allPlayers.Count; i++)
			{
				Player val = allPlayers[i];
				if ((Object)(object)val != (Object)null && ((Character)val).InBed() && Vector3.Distance(((Component)val).transform.position, ((Component)bed).transform.position) < 2.5f)
				{
					return true;
				}
			}
			return false;
		}

		private static void CheckHearthUpkeep(Character character, LocalState local, float dt)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			float num = 484f;
			Vector3 position = ((Component)character).transform.position;
			foreach (Fireplace fireplace in PieceRegistry.Fireplaces)
			{
				if ((Object)(object)fireplace != (Object)null && fireplace.IsBurning())
				{
					Vector3 val = ((Component)fireplace).transform.position - position;
					if (((Vector3)(ref val)).sqrMagnitude <= num)
					{
						flag = true;
						break;
					}
				}
			}
			local.Neglect = (flag ? Mathf.Max(0f, local.Neglect - dt * 0.5f) : (local.Neglect + dt));
		}

		private static void AmbientChatter(Character character, ZDO zdo, LocalState local)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (!(Time.time < local.NextChat))
			{
				local.NextChat = Time.time + Random.Range(45f, 95f);
				if (AiHelpers.PlayerNear(((Component)character).transform.position, 12f))
				{
					string[] array = ((zdo.GetInt("VF_WF_Mood", 0) >= 0) ? _happy : _hungry);
					AiHelpers.Say(character, array[Random.Range(0, array.Length)]);
				}
			}
		}
	}
	public sealed class WayfarerVirtualTask : IVirtualAgentTask
	{
		private const float UnattendedStaySeconds = 1200f;

		public string Id => "VikingFactions.WayfarerVirtual";

		public NpcRoleFlags RequiredRole => (NpcRoleFlags)65536;

		public void TickUnloadedZdo(ZDO zdo, NpcRoleFlags roles, float dt)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.ModEnabled.Value || !ModConfig.EnableWayfarers.Value || !zdo.IsValid() || !zdo.IsOwner())
			{
				return;
			}
			int num = zdo.GetInt("VF_WF_State", 0);
			double num2 = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : 0.0);
			switch (num)
			{
			case 0:
			{
				Vector3 vec2 = zdo.GetVec3("VF_WF_TargetPos", zdo.GetPosition());
				if (VirtualAgentDirector.MoveZdoAlongTerrain(zdo, vec2, 3.4f, dt, 8f))
				{
					zdo.Set("VF_WF_State", 1);
					zdo.Set("VF_WF_Since", (float)num2);
				}
				break;
			}
			case 1:
				if (num2 - (double)zdo.GetFloat("VF_WF_Since", (float)num2) > 1200.0)
				{
					zdo.Set("VF_WF_State", 2);
				}
				break;
			default:
			{
				Vector3 vec = zdo.GetVec3("VF_WF_OriginPos", zdo.GetPosition());
				if (VirtualAgentDirector.MoveZdoAlongTerrain(zdo, vec, 3.6f, dt, 8f) && ZDOMan.instance != null)
				{
					ZDOMan.instance.DestroyZDO(zdo);
				}
				break;
			}
			}
		}

		public void ApplyCatchUpOnLoad(Character agent, AgentBehaviorProfile profile, double elapsedOfflineSeconds)
		{
		}
	}
}
namespace VikingFactions.Telemetry
{
	public sealed class VikingFactionsConsoleCommand : ConsoleCommand
	{
		public override string Name => "vf";

		public override string Help => "VikingFactions tools (spawn_wayfarer, trigger_raid [marauders|draugr|fulings], status, clear_camps)";

		public override bool IsCheat => true;

		public static void Register()
		{
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new VikingFactionsConsoleCommand());
		}

		public override void Run(string[] args)
		{
			//IL_003e: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				Console.instance.Print("[VikingFactions] No local player.");
				return;
			}
			string text = ((args != null && args.Length != 0) ? args[0].ToLowerInvariant() : "status");
			Vector3 position = ((Component)Player.m_localPlayer).transform.position;
			switch (text)
			{
			case "spawn_wayfarer":
			{
				bool flag = HospitalityScanner.SpawnWayfarerTowards(position, 60f, 100f);
				Console.instance.Print(flag ? "[VikingFactions] Wayfarer dispatched toward your position." : "[VikingFactions] No valid spawn point found.");
				break;
			}
			case "trigger_raid":
			{
				RaiderCampDirector.ActiveCampRecord record;
				bool flag = RaiderCampDirector.TriggerFactionRaid((args.Length > 1) ? args[1] : "marauders", position, out record);
				Console.instance.Print((flag && record != null) ? $"[VikingFactions] {record.FactionDisplayName} camp placed at {record.CampCenter:F0}." : "[VikingFactions] Raid failed (unknown faction, disabled, not server, or no valid land).");
				break;
			}
			case "clear_camps":
				Console.instance.Print($"[VikingFactions] Destroyed {RaiderCampDirector.ClearAllCamps()} camp/raider ZDOs.");
				break;
			case "status":
				Console.instance.Print($"[VikingFactions] Hearth comfort: {HospitalityScanner.LastEvaluatedComfort}, " + $"active wayfarers: {HospitalityScanner.CountActiveWayfarers()}, " + $"active camps: {RaiderCampDirector.ActiveCamps.Count}");
				break;
			default:
				Console.instance.Print("Usage: vf spawn_wayfarer | trigger_raid [factionId] | status | clear_camps");
				break;
			}
		}

		public override List<string> CommandOptionList()
		{
			return new List<string> { "spawn_wayfarer", "trigger_raid", "status", "clear_camps" };
		}
	}
}
namespace VikingFactions.Patches
{
	[HarmonyPatch]
	public static class FactionPatches
	{
		[HarmonyPatch(typeof(Character), "Start")]
		[HarmonyPostfix]
		private static void Character_Start_Postfix(Character __instance)
		{
			if (!ModConfig.ModEnabled.Value || (Object)(object)__instance == (Object)null || __instance.IsPlayer())
			{
				return;
			}
			ZNetView nView = AgentProfileRegistry.GetNView(__instance);
			if ((Object)(object)nView == (Object)null || !nView.IsValid())
			{
				return;
			}
			ZDO zDO = nView.GetZDO();
			if (zDO != null)
			{
				if (zDO.GetPrefab() == StringExtensionMethods.GetStableHashCode("VF_Wayfarer"))
				{
					HospitalityScanner.RegisterWayfarer(zDO);
					VirtualAgentDirector.TrackZdoDirectly(zDO);
				}
				else if (zDO.GetInt("VF_Raider_State", -1) >= 0)
				{
					VirtualAgentDirector.TrackZdoDirectly(zDO);
				}
			}
		}

		[HarmonyPatch(typeof(RandEventSystem), "SetRandomEvent")]
		[HarmonyPrefix]
		private static bool RandEventSystem_SetRandomEvent_Prefix(RandomEvent ev, Vector3 pos, bool __runOriginal)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (!__runOriginal)
			{
				return true;
			}
			if (ev == null)
			{
				return true;
			}
			if (!ModConfig.ModEnabled.Value || !ModConfig.EnableMarauderHeists.Value || !ModConfig.InterceptVanillaRaids.Value)
			{
				return true;
			}
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return true;
			}
			if (!RaiderFactionRegistry.TryGetFactionForVanillaEvent(ev.m_name, out IRaiderFactionDefinition definition))
			{
				if (!RaiderFactionRegistry.TrySelectProgressiveFaction(out definition))
				{
					return true;
				}
			}
			else if (!RaiderFactionRegistry.IsFactionAvailable(definition) && !RaiderFactionRegistry.TrySelectProgressiveFaction(out definition))
			{
				return true;
			}
			if (RaiderCampDirector.TriggerFactionRaid(definition.FactionId, pos, out RaiderCampDirector.ActiveCampRecord _))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Character), "GetJogSpeedFactor")]
		[HarmonyPostfix]
		private static void Character_GetJogSpeedFactor_Postfix(Character __instance, ref float __result)
		{
			if (IsCarrying(__instance))
			{
				__result *= ModConfig.RaiderCarrySpeedMultiplier.Value;
			}
		}

		[HarmonyPatch(typeof(Character), "GetRunSpeedFactor")]
		[HarmonyPostfix]
		private static void Character_GetRunSpeedFactor_Postfix(Character __instance, ref float __result)
		{
			if (IsCarrying(__instance))
			{
				__result *= ModConfig.RaiderCarrySpeedMultiplier.Value;
			}
		}

		private static bool IsCarrying(Character c)
		{
			if ((Object)(object)c != (Object)null && MarauderHeistBrainModule.CarryStates.TryGetValue(c, out CarryBox value))
			{
				return value.Carrying;
			}
			return false;
		}

		[HarmonyPatch(typeof(Character), "OnDeath")]
		[HarmonyPostfix]
		private static void Character_OnDeath_Postfix(Character __instance)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || __instance.IsPlayer())
			{
				return;
			}
			ZNetView nView = AgentProfileRegistry.GetNView(__instance);
			if ((Object)(object)nView == (Object)null || !nView.IsValid() || !nView.IsOwner())
			{
				return;
			}
			ZDO zDO = nView.GetZDO();
			if (zDO != null && zDO.GetInt("VF_Raider_State", -1) >= 0)
			{
				List<ItemData> allItems = LootStore.LoadBase64(zDO, "VF_Raider_Loot").GetAllItems();
				for (int i = 0; i < allItems.Count; i++)
				{
					Vector3 val = ((Component)__instance).transform.position + Vector3.up * 0.6f + Random.insideUnitSphere * 0.4f;
					ItemDrop.DropItem(allItems[i], 0, val, Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f));
				}
				LootStore.SaveBase64(zDO, "VF_Raider_Loot", LootStore.NewInventory());
				zDO.Set("VF_Raider_Stolen", 0);
				MarauderHeistBrainModule.CarryStates.Remove(__instance);
			}
		}
	}
}
namespace VikingFactions.Marauders
{
	public sealed class CarryBox
	{
		public bool Carrying;
	}
	public sealed class MarauderHeistBrainModule : IAIBrainModule
	{
		private sealed class RaiderState
		{
			public Inventory Loot;

			public bool Initialized;

			public Container? Target;

			public float SiphonProgress;

			public float NextScan;

			public float RaidingSince;
		}

		private const float HeistScore = 60f;

		public static readonly ConditionalWeakTable<Character, CarryBox> CarryStates = new ConditionalWeakTable<Character, CarryBox>();

		private static readonly ConditionalWeakTable<Character, RaiderState> _states = new ConditionalWeakTable<Character, RaiderState>();

		public string Id => "VikingFactions.MarauderHeist";

		private static bool TryGet(Character c, out ZDO zdo)
		{
			zdo = null;
			ZNetView nView = AgentProfileRegistry.GetNView(c);
			if ((Object)(object)nView == (Object)null || !nView.IsValid() || !nView.IsOwner())
			{
				return false;
			}
			zdo = nView.GetZDO();
			if (zdo != null)
			{
				return zdo.GetInt("VF_Raider_State", -1) >= 0;
			}
			return false;
		}

		private static RaiderState Init(Character c, ZDO zdo, AgentBehaviorProfile profile)
		{
			RaiderState value = _states.GetValue(c, (Character _) => new RaiderState());
			if (!value.Initialized)
			{
				value.Initialized = true;
				value.Loot = LootStore.LoadBase64(zdo, "VF_Raider_Loot");
				CarryStates.GetValue(c, (Character _) => new CarryBox()).Carrying = value.Loot.NrOfItems() > 0;
				AgentBehaviorProfile val = profile.Clone();
				val.YieldToPlayers = false;
				val.UseFormationFollowing = false;
				val.CanTraversePortals = false;
				AgentProfileRegistry.SetInstanceProfile(c, val, false);
			}
			return value;
		}

		public float EvaluateUtility(BaseAI ai, Character character, AgentBehaviorProfile profile)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.ModEnabled.Value || !ModConfig.EnableMarauderHeists.Value)
			{
				return 0f;
			}
			if (!TryGet(character, out ZDO zdo))
			{
				return 0f;
			}
			RaiderState raiderState = Init(character, zdo, profile);
			int num = zdo.GetInt("VF_Raider_State", 3);
			switch (num)
			{
			case 3:
				return 0f;
			case 2:
				return 60f;
			default:
			{
				bool flag = character.GetHealthPercentage() < 0.99f;
				if (num == 1 && flag && raiderState.Loot.NrOfItems() > 0 && character.GetHealthPercentage() < 0.5f)
				{
					RaiderCampDirector.SetState(zdo, 2);
					return 60f;
				}
				if (flag || AiHelpers.PlayerNear(((Component)character).transform.position, 7f))
				{
					return 0f;
				}
				return 60f;
			}
			}
		}

		public bool Tick(BaseAI ai, Character character, AgentBehaviorProfile profile, float dt)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGet(character, out ZDO zdo))
			{
				return false;
			}
			RaiderState raiderState = Init(character, zdo, profile);
			int num = zdo.GetInt("VF_Raider_State", 3);
			Vector3 position = ((Component)character).transform.position;
			switch (num)
			{
			case 0:
			{
				Vector3 vec = zdo.GetVec3("VF_Raider_TargetPos", position);
				if (Utils.DistanceXZ(position, vec) <= 14f)
				{
					RaiderCampDirector.SetState(zdo, 1);
					raiderState.RaidingSince = Time.time;
					return true;
				}
				AiHelpers.MoveTo(ai, dt, vec, 6f, run: true);
				return true;
			}
			case 1:
				return TickRaiding(ai, character, zdo, raiderState, dt);
			case 2:
				return TickFleeing(ai, character, zdo, raiderState, dt);
			default:
				return false;
			}
		}

		private static bool TickRaiding(BaseAI ai, Character character, ZDO zdo, RaiderState st, float dt)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: 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)
			Vector3 position = ((Component)character).transform.position;
			if (st.RaidingSince <= 0f)
			{
				st.RaidingSince = Time.time;
			}
			if ((Object)(object)st.Target == (Object)null || !HasLoot(st.Target) || st.Target.IsInUse())
			{
				st.Target = null;
				st.SiphonProgress = 0f;
				if (Time.time >= st.NextScan)
				{
					st.NextScan = Time.time + 1.5f;
					st.Target = FindTarget(position, zdo);
				}
				if ((Object)(object)st.Target == (Object)null)
				{
					if (Time.time - st.RaidingSince > 10f)
					{
						RaiderCampDirector.SetState(zdo, 2);
					}
					return true;
				}
			}
			Vector3 position2 = ((Component)st.Target).transform.position;
			if (Utils.DistanceXZ(position, position2) > 2.2f)
			{
				AiHelpers.MoveTo(ai, dt, position2, 1.8f, run: true);
				return true;
			}
			ai.StopMoving();
			AiHelpers.LookAt(ai, position2);
			st.SiphonProgress += dt;
			if (st.SiphonProgress < ModConfig.RaiderSiphonSecondsPerStack.Value)
			{
				return true;
			}
			st.SiphonProgress = 0f;
			StealOneStack(character, zdo, st);
			return true;
		}

		private static bool TickFleeing(BaseAI ai, Character character, ZDO zdo, RaiderState st, float dt)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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)
			Vector3 position = ((Component)character).transform.position;
			Vector3 vec = zdo.GetVec3("VF_Raider_CampPos", position);
			if (Utils.DistanceXZ(position, vec) <= 6f)
			{
				RaiderCampDirector.DepositLoot(zdo);
				st.Loot = LootStore.NewInventory();
				CarryStates.GetValue(character, (Character _) => new CarryBox()).Carrying = false;
				RaiderCampDirector.SetState(zdo, 3);
				ai.StopMoving();
				return true;
			}
			AiHelpers.MoveTo(ai, dt, vec, 4f, run: true);
			return true;
		}

		private static Container? FindTarget(Vector3 pos, ZDO raiderZdo)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			Container result = null;
			float num = 2025f;
			foreach (Container container in PieceRegistry.Containers)
			{
				if ((Object)(object)container == (Object)null)
				{
					continue;
				}
				Vector3 val = ((Component)container).transform.position - pos;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (!(sqrMagnitude >= num) && HasLoot(container) && !container.IsInUse())
				{
					ZNetView component = ((Component)container).GetComponent<ZNetView>();
					if (!((Object)(object)component == (Object)null) && component.IsValid() && !component.GetZDO().GetBool("VF_IsSpoilsChest", false) && (!ModConfig.RaidersRespectWards.Value || !PrivateArea.InsideFactionArea(((Component)container).transform.position, (Faction)0)))
					{
						num = sqrMagnitude;
						result = container;
					}
				}
			}
			return result;
		}

		private static bool HasLoot(Container c)
		{
			Inventory inventory = c.GetInventory();
			if (inventory != null)
			{
				return inventory.NrOfItems() > 0;
			}
			return false;
		}

		private static void StealOneStack(Character character, ZDO zdo, RaiderState st)
		{
			Container target = st.Target;
			Inventory inventory = target.GetInventory();
			ItemData val = null;
			float num = -1f;
			List<ItemData> allItems = inventory.GetAllItems();
			for (int i = 0; i < allItems.Count; i++)
			{
				ItemData val2 = allItems[i];
				if (val2?.m_shared != null)
				{
					float num2 = ((val2.m_shared.m_value <= 0) ? 1 : val2.m_shared.m_value) * val2.m_stack;
					if (num2 > num)
					{
						num = num2;
						val = val2;
					}
				}
			}
			if (val == null)
			{
				return;
			}
			ZNetView component = ((Component)target).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				component.ClaimOwnership();
			}
			ItemData val3 = val.Clone();
			if (!st.Loot.AddItem(val3))
			{
				RaiderCampDirector.SetState(zdo, 2);
				return;
			}
			inventory.RemoveItem(val);
			LootStore.SaveBase64(zdo, "VF_Raider_Loot", st.Loot);
			int num3 = zdo.GetInt("VF_Raider_Stolen", 0) + 1;
			zdo.Set("VF_Raider_Stolen", num3);
			CarryStates.GetValue(character, (Character _) => new CarryBox()).Carrying = true;
			if (num3 >= ModConfig.MaxStacksPerRaider.Value)
			{
				RaiderCampDirector.SetState(zdo, 2);
			}
		}
	}
	public sealed class MarauderVirtualTask : IVirtualAgentTask
	{
		private const float GiveUpSeconds = 180f;

		public string Id => "VikingFactions.MarauderVirtual";

		public NpcRoleFlags RequiredRole => (NpcRoleFlags)131072;

		public void TickUnloadedZdo(ZDO zdo, NpcRoleFlags roles, float dt)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.ModEnabled.Value || !ModConfig.EnableMarauderHeists.Value || !zdo.IsValid() || !zdo.IsOwner())
			{
				return;
			}
			int num = zdo.GetInt("VF_Raider_State", 3);
			if (num == 3)
			{
				return;
			}
			double num2 = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : 0.0);
			switch (num)
			{
			case 0:
			{
				Vector3 vec2 = zdo.GetVec3("VF_Raider_TargetPos", zdo.GetPosition());
				if (VirtualAgentDirector.MoveZdoAlongTerrain(zdo, vec2, 4.5f, dt, 14f))
				{
					RaiderCampDirector.SetState(zdo, 1);
				}
				break;
			}
			case 1:
				if (num2 - (double)zdo.GetFloat("VF_Raider_Since", (float)num2) > 180.0)
				{
					RaiderCampDirector.SetState(zdo, 2);
				}
				break;
			case 2:
			{
				bool flag = zdo.GetInt("VF_Raider_Stolen", 0) > 0;
				float num3 = 4.6f * (flag ? ModConfig.RaiderCarrySpeedMultiplier.Value : 1f);
				Vector3 vec = zdo.GetVec3("VF_Raider_CampPos", zdo.GetPosition());
				if (VirtualAgentDirector.MoveZdoAlongTerrain(zdo, vec, num3, dt, 6f))
				{
					if (flag)
					{
						RaiderCampDirector.DepositLoot(zdo);
					}
					RaiderCampDirector.SetState(zdo, 3);
				}
				break;
			}
			}
		}

		public void ApplyCatchUpOnLoad(Character agent, AgentBehaviorProfile profile, double elapsedOfflineSeconds)
		{
		}
	}
	public static class RaiderCampDirector
	{
		public sealed class ActiveCampRecord
		{
			public int CampGuid;

			public string FactionId = "";

			public string FactionDisplayName = "";

			public Vector3 CampCenter;

			public Vector3 RaidTargetPos;

			public bool MinimapPinned;

			public readonly List<ZDO> Zdos = new List<ZDO>();
		}

		public const int SpoilsChestWidth = 6;

		public const int SpoilsChestHeight = 3;

		private static readonly Dictionary<int, ActiveCampRecord> _camps = new Dictionary<int, ActiveCampRecord>();

		public static IReadOnlyDictionary<int, ActiveCampRecord> ActiveCamps => _camps;

		public static void RegisterCampPiece(ZDO zdo)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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)
			if (zdo == null || !zdo.IsValid())
			{
				return;
			}
			int num = zdo.GetInt("VF_CampGuid", 0);
			if (num == 0)
			{
				return;
			}
			if (!_camps.TryGetValue(num, out ActiveCampRecord value))
			{
				string factionId = zdo.GetString("VF_Raider_Faction", "marauders");
				string factionDisplayName = "Raider";
				if (RaiderFactionRegistry.TryGetFaction(factionId, out IRaiderFactionDefinition definition))
				{
					factionDisplayName = definition.DisplayName;
				}
				value = new ActiveCampRecord
				{
					CampGuid = num,
					FactionId = factionId,
					FactionDisplayName = factionDisplayName,
					CampCenter = zdo.GetVec3("VF_Raider_CampPos", zdo.GetPosition()),
					RaidTargetPos = zdo.GetVec3("VF_Raider_TargetPos", zdo.GetPosition())
				};
				_camps[num] = value;
			}
			if (!value.Zdos.Contains(zdo))
			{
				value.Zdos.Add(zdo);
			}
		}

		public static void SetState(ZDO zdo, int state)
		{
			zdo.Set("VF_Raider_State", state);
			zdo.Set("VF_Raider_Since", ((Object)(object)ZNet.instance != (Object)null) ? ((float)ZNet.instance.GetTimeSeconds()) : 0f);
		}

		public static bool TriggerFactionRaid(string factionId, Vector3 settlementPos, out ActiveCampRecord? record)
		{
			//IL_007c: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			record = null;
			if (!ModConfig.ModEnabled.Value || !ModConfig.EnableMarauderHeists.Value)
			{
				return false;
			}
			if (ZDOMan.instance == null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return false;
			}
			if (!RaiderFactionRegistry.TryGetAvailableFaction(factionId, out IRaiderFactionDefinition definition) && !RaiderFactionRegistry.TrySelectProgressiveFaction(out definition))
			{
				return false;
			}
			float value = ModConfig.CampSpawnMinDistance.Value;
			float num = Mathf.Max(value + 50f, ModConfig.CampSpawnMaxDistance.Value);
			if (TryFindReusableCampNearby(definition.FactionId, settlementPos, value * 0.8f, num * 1.2f, out ActiveCampRecord reusable) && ReoccupyCamp(reusable, definition, settlementPos))
			{
				record = reusable;
				return true;
			}
			if (!HospitalityScanner.FindValidLandPoint(settlementPos, value, num, out var pos))
			{
				return false;
			}
			int num2 = Random.Range(100000, int.MaxValue);
			Vector3 val = settlementPos - pos;
			val.y = 0f;
			Quaternion val2 = Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up);
			ActiveCampRecord activeCampRecord = new ActiveCampRecord
			{
				CampGuid = num2,
				FactionId = definition.FactionId,
				FactionDisplayName = definition.DisplayName,
				CampCenter = pos,
				RaidTargetPos = settlementPos
			};
			for (int i = 0; i < definition.CampPieces.Count; i++)
			{
				CampPieceEntry campPieceEntry = definition.CampPieces[i];
				int stableHashCode = StringExtensionMethods.GetStableHashCode(campPieceEntry.PrefabName);
				Vector3 val3 = GroundAt(pos + val2 * campPieceEntry.LocalOffset);
				ZDO val4 = ZDOMan.instance.CreateNewZDO(val3, stableHashCode);
				val4.Persistent = true;
				val4.SetPrefab(stableHashCode);
				val4.SetRotation(val2 * Quaternion.Euler(0f, campPieceEntry.LocalYawDegrees, 0f));
				val4.Set("VF_CampGuid", num2);
				val4.Set("VF_CampState", 0);
				val4.Set("VF_CampLastRaid", (float)ZNet.instance.GetTimeSeconds());
				if (campPieceEntry.IsSpoilsChest)
				{
					val4.Set("VF_IsSpoilsChest", true);
					val4.Set(ZDOVars.s_addedDefaultItems, true);
					SeedBounty(val4, definition.WarlordBountyTable);
				}
				activeCampRecord.Zdos.Add(val4);
			}
			SpawnRaider(definition, definition.WarlordPrefabName, GroundAt(pos + val2 * new Vector3(0f, 0f, 1.5f)), val2, num2, pos, settlementPos, 3, activeCampRecord);
			for (int j = 0; j < definition.CampGuardCount; j++)
			{
				float num3 = (float)j / (float)Mathf.Max(1, definition.CampGuardCount) * MathF.PI * 2f;
				Vector3 pos2 = GroundAt(pos + new Vector3(Mathf.Cos(num3) * 3.5f, 0f, Mathf.Sin(num3) * 3.5f));
				SpawnRaider(definition, definition.RaiderPrefabName, pos2, val2, num2, pos, settlementPos, 3, activeCampRecord);
			}
			int num4 = Random.Range(definition.MinRaidSize, definition.MaxRaidSize + 1);
			for (int k = 0; k < num4; k++)
			{
				Vector3 pos3 = GroundAt(pos + val2 * new Vector3(((float)k - (float)num4 * 0.5f) * 2f, 0f, -2.5f));
				SpawnRaider(definition, definition.RaiderPrefabName, pos3, val2, num2, pos, settlementPos, 0, activeCampRecord);
			}
			_camps[num2] = activeCampRecord;
			record = activeCampRecord;
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)2, definition.DisplayName + " are marching on your stores!", 0, (Sprite)null, false, true);
			}
			VikingFactionsPlugin.Log.LogInfo((object)$"[Camps] '{definition.DisplayName}' camp {num2} at {pos:F0}; {num4} raiders -> {settlementPos:F0}.");
			return true;
		}

		private static bool TryFindReusableCampNearby(string factionId, Vector3 center, float minDist, float maxDist, out ActiveCampRecord reusable)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			reusable = null;
			float num = minDist * minDist;
			float num2 = maxDist * maxDist;
			foreach (KeyValuePair<int, ActiveCampRecord> camp in _camps)
			{
				ActiveCampRecord value = camp.Value;
				if (string.Equals(value.FactionId, factionId, StringComparison.OrdinalIgnoreCase))
				{
					float num3 = Utils.DistanceXZ(center, value.CampCenter);
					num3 *= num3;
					if (!(num3 < num) && !(num3 > num2) && FindSpoilsChest(value.CampGuid) != null)
					{
						reusable = value;
						return true;
					}
				}
			}
			return false;
		}

		private static bool ReoccupyCamp(ActiveCampRecord camp, IRaiderFactionDefinition faction, Vector3 targetPos)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			camp.RaidTargetPos = targetPos;
			Vector3 campCenter = camp.CampCenter;
			Vector3 val = targetPos - campCenter;
			val.y = 0f;
			Quaternion val2 = Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up);
			camp.Zdos.RemoveAll((ZDO z) => z == null || !z.IsValid());
			ZDO val3 = FindSpoilsChest(camp.CampGuid);
			if (val3 != null)
			{
				if (LootStore.LoadChest(val3).NrOfItems() == 0)
				{
					SeedBounty(val3, faction.WarlordBountyTable);
				}
				val3.Set("VF_CampState", 0);
				val3.Set("VF_CampLastRaid", (float)ZNet.instance.GetTimeSeconds());
			}
			int num = 0;
			for (int num2 = 0; num2 < camp.Zdos.Count; num2++)
			{
				if (camp.Zdos[num2].GetInt("VF_Raider_State", -1) == 3)
				{
					num++;
				}
			}
			if (num < faction.CampGuardCount + 1)
			{
				SpawnRaider(faction, faction.WarlordPrefabName, GroundAt(campCenter + val2 * new Vector3(0f, 0f, 1.5f)), val2, camp.CampGuid, campCenter, targetPos, 3, camp);
				int num3 = Mathf.Max(0, faction.CampGuardCount - num);
				for (int num4 = 0; num4 < num3; num4++)
				{
					float num5 = (float)num4 / (float)Mathf.Max(1, num3) * MathF.PI * 2f;
					Vector3 pos = GroundAt(campCenter + new Vector3(Mathf.Cos(num5) * 3.5f, 0f, Mathf.Sin(num5) * 3.5f));
					SpawnRaider(faction, faction.RaiderPrefabName, pos, val2, camp.CampGuid, campCenter, targetPos, 3, camp);
				}
			}
			int num6 = Random.Range(faction.MinRaidSize, faction.MaxRaidSize + 1);
			for (int num7 = 0; num7 < num6; num7++)
			{
				Vector3 pos2 = GroundAt(campCenter + val2 * new Vector3(((float)num7 - (float)num6 * 0.5f) * 2f, 0f, -2.5f));
				SpawnRaider(faction, faction.RaiderPrefabName, pos2, val2, camp.CampGuid, campCenter, targetPos, 0, camp);
			}
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)2, faction.DisplayName + " are rearming at their camp and march again!", 0, (Sprite)null, false, true);
			}
			VikingFactionsPlugin.Log.LogInfo((object)$"[Camps] Reoccupied '{faction.DisplayName}' camp {camp.CampGuid} at {campCenter:F0}; {num6} raiders -> {targetPos:F0}.");
			return true;
		}

		private static void SpawnRaider(IRaiderFactionDefinition faction, string prefab, Vector3 pos, Quaternion rot, int campGuid, Vector3 campPos, Vector3 target, int state, ActiveCampRecord rec)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			ZDO val = VirtualAgentDirector.SpawnVirtualAgentZdo(prefab, pos, rot, (NpcRoleFlags)131072, faction.UsesCustomHumanoidRig);
			if (val != null)
			{
				val.Set("VF_CampGuid", campGuid);
				val.Set("VF_Raider_Faction", faction.FactionId);
				val.Set("VF_Raider_TargetPos", target);
				val.Set("VF_Raider_CampPos", campPos);
				val.Set("VF_Raider_Stolen", 0);
				val.Set(ZDOVars.s_spawnPoint, campPos);
				SetState(val, state);
				rec.Zdos.Add(val);
			}
		}

		private static Vector3 GroundAt(Vector3 p)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (WorldGenerator.instance != null)
			{
				p.y = WorldGenerator.instance.GetHeight(p.x, p.z);
			}
			return p;
		}

		private static void SeedBounty(ZDO chestZdo, IReadOnlyList<BountyLootEntry> table)
		{
			if (table == null || table.Count == 0 || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			Inventory inv = LootStore.NewInventory("SpoilsChest");
			for (int i = 0; i < table.Count; i++)
			{
				BountyLootEntry bountyLootEntry = table[i];
				if (!(Random.value > bountyLootEntry.DropChance))
				{
					LootStore.AddPrefab(inv, bountyLootEntry.ItemPrefabName, Random.Range(bountyLootEntry.MinStack, bountyLootEntry.MaxStack + 1));
				}
			}
			LootStore.SaveChest(chestZdo, inv);
		}

		public static void DepositLoot(ZDO raiderZdo)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			int campGuid = raiderZdo.GetInt("VF_CampGuid", 0);
			Vector3 vec = raiderZdo.GetVec3("VF_Raider_CampPos", raiderZdo.GetPosition());
			Inventory val = LootStore.LoadBase64(raiderZdo, "VF_Raider_Loot");
			if (val.NrOfItems() <= 0)
			{
				return;
			}
			ZDO val2 = FindSpoilsChest(campGuid);
			if (val2 != null)
			{
				val2.SetOwner(ZDOMan.GetSessionID());
				Inventory val3 = LootStore.LoadChest(val2);
				int num = LootStore.MoveAll(val, val3);
				LootStore.SaveChest(val2, val3);
				if (num > 0)
				{
					VikingFactionsPlugin.Log.LogWarning((object)$"[Camps] Spoils chest full; {num} stolen stack(s) lost.");
				}
			}
			LootStore.SaveBase64(raiderZdo, "VF_Raider_Loot", LootStore.NewInventory());
			raiderZdo.Set("VF_Raider_Stolen", 0);
			RevealCamp(campGuid, vec);
		}

		public static ZDO? FindSpoilsChest(int campGuid)
		{
			if (ZDOMan.instance == null || campGuid == 0)
			{
				return null;
			}
			int num = 0;
			List<ZDO> list = new List<ZDO>(64);
			bool allZDOsWithPrefabIterative;
			do
			{
				list.Clear();
				allZDOsWithPrefabIterative = ZDOMan.instance.GetAllZDOsWithPrefabIterative("piece_chest", list, ref num);
				for (int i = 0; i < list.Count; i++)
				{
					ZDO val = list[i];
					if (val.GetBool("VF_IsSpoilsChest", false) && val.GetInt("VF_CampGuid", 0) == campGuid)
					{
						return val;
					}
				}
			}
			while (!allZDOsWithPrefabIterative);
			return null;
		}

		public static void RevealCamp(int campGuid, Vector3 campPos)
		{
			//IL_004c: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			if (_camps.TryGetValue(campGuid, out ActiveCampRecord value))
			{
				if (value.MinimapPinned)
				{
					return;
				}
				value.MinimapPinned = true;
			}
			if ((Object)(object)Minimap.instance != (Object)null)
			{
				string text = ((value != null) ? (value.FactionDisplayName + " Camp") : "Raider Camp");
				Minimap.instance.AddPin(campPos, (PinType)9, text, true, false, 0L, default(PlatformUserID));
			}
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)2, "Raiders escaped with your spoils! Their camp is marked on your map.", 0, (Sprite)null, false, true);
			}
		}

		public static int ClearAllCamps()
		{
			int num = 0;
			foreach (ActiveCampRecord value in _camps.Values)
			{
				for (int i = 0; i < value.Zdos.Count; i++)
				{
					ZDO val = value.Zdos[i];
					if (val != null && val.IsValid() && ZDOMan.instance != null)
					{
						ZDOMan.instance.DestroyZDO(val);
						num++;
					}
				}
			}
			_camps.Clear();
			return num;
		}
	}
	public readonly struct CampPieceEntry
	{
		public readonly string PrefabName;

		public readonly Vector3 LocalOffset;

		public readonly float LocalYawDegrees;

		public readonly bool IsSpoilsChest;

		public CampPieceEntry(string prefabName, Vector3 localOffset, float localYawDegrees = 0f, bool isSpoilsChest = false)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			PrefabName = prefabName;
			LocalOffset = localOffset;
			LocalYawDegrees = localYawDegrees;
			IsSpoilsChest = isSpoilsChest;
		}
	}
	public readonly struct BountyLootEntry
	{
		public readonly string ItemPrefabName;

		public readonly int MinStack;

		public readonly int MaxStack;

		public readonly float DropChance;

		public BountyLootEntry(string itemPrefabName, int minStack, int maxStack, float dropChance = 1f)
		{
			ItemPrefabName = itemPrefabName;
			MinStack = minStack;
			MaxStack = maxStack;
			DropChance = dropChance;
		}
	}
	public interface IRaiderFactionDefinition
	{
		string FactionId { get; }

		string DisplayName { get; }

		string RaiderPrefabName { get; }

		string WarlordPrefabName { get; }

		bool UsesCustomHumanoidRig { get; }

		IReadOnlyList<string> RequiredGlobalKeys { get; }

		IReadOnlyList<string> ForbiddenGlobalKeys { get; }

		int MinRaidSize { get; }

		int MaxRaidSize { get; }

		int CampGuardCount { get; }

		string[] RaiderDefaultEquipment { get; }

		string[] WarlordDefaultEquipment { get; }

		IReadOnlyList<CampPieceEntry> CampPieces { get; }

		IReadOnlyList<BountyLootEntry> WarlordBountyTable { get; }

		IReadOnlyList<string> InterceptedVanillaEvents { get; }
	}
	public sealed class RaiderFactionDefinition : IRaiderFactionDefinition
	{
		public string FactionId { get; set; } = "";

		public string DisplayName { get; set; } = "";

		public string RaiderPrefabName { get; set; } = "";

		public string WarlordPrefabName { get; set; } = "";

		public bool UsesCustomHumanoidRig { get; set; }

		public IReadOnlyList<string> RequiredGlobalKeys { get; set; } = Array.Empty<string>();

		public IReadOnlyList<string> ForbiddenGlobalKeys { get; set; } = Array.Empty<string>();

		public int MinRaidSize { get; set; } = 3;

		public int MaxRaidSize { get; set; } = 4;

		public int CampGuardCount { get; set; } = 2;

		public string[] RaiderDefaultEquipment { get; set; } = Array.Empty<string>();

		public string[] WarlordDefaultEquipment { get; set; } = Array.Empty<string>();

		public IReadOnlyList<CampPieceEntry> CampPieces { get; set; } = Array.Empty<CampPieceEntry>();

		public IReadOnlyList<BountyLootEntry> WarlordBountyTable { get; set; } = Array.Empty<BountyLootEntry>();

		public IReadOnlyList<string> InterceptedVanillaEvents { get; set; } = Array.Empty<string>();
	}
	public static class RaiderFactionRegistry
	{
		public const string MarauderPrefabName = "VF_Marauder";

		public const string WarlordPrefabName = "VF_Warlord";

		private static readonly Dictionary<string, IRaiderFactionDefinition> _factions = new Dictionary<string, IRaiderFactionDefinition>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, IRaiderFactionDefinition> _vanillaEventMap = new Dictionary<string, IRaiderFactionDefinition>(StringComparer.OrdinalIgnoreCase);

		public static void RegisterFaction(IRaiderFactionDefinition definition)
		{
			if (definition == null || string.IsNullOrWhiteSpace(definition.FactionId))
			{
				return;
			}
			_factions[definition.FactionId] = definition;
			if (definition.InterceptedVanillaEvents == null)
			{
				return;
			}
			for (int i = 0; i < definition.InterceptedVanillaEvents.Count; i++)
			{
				string text = definition.InterceptedVanillaEvents[i];
				if (!string.IsNullOrWhiteSpace(text))
				{
					_vanillaEventMap[text] = definition;
				}
			}
		}

		public static bool TryGetFaction(string factionId, out IRaiderFactionDefinition definition)
		{
			return _factions.TryGetValue(factionId, out definition);
		}

		public static bool TryGetFactionForVanillaEvent(string eventName, out IRaiderFactionDefinition definition)
		{
			return _vanillaEventMap.TryGetValue(eventName, out definition);
		}

		public static bool IsFactionAvailable(IRaiderFactionDefinition definition)
		{
			if (definition == null)
			{
				return false;
			}
			if ((Object)(object)ZoneSystem.instance == (Object)null)
			{
				return true;
			}
			if (definition.RequiredGlobalKeys != null)
			{
				for (int i = 0; i < definition.RequiredGlobalKeys.Count; i++)
				{
					string text = definition.RequiredGlobalKeys[i];
					if (!string.IsNullOrWhiteSpace(text) && !ZoneSystem.instance.GetGlobalKey(text))
					{
						return false;
					}
				}
			}
			if (definition.ForbiddenGlobalKeys != null)
			{
				for (int j = 0; j < definition.ForbiddenGlobalKeys.Count; j++)
				{
					string text2 = definition.ForbiddenGlobalKeys[j];
					if (!string.IsNullOrWhiteSpace(text2) && ZoneSystem.instance.GetGlobalKey(text2))
					{
						return false;
					}
				}
			}
			return true;
		}

		public static bool TryGetAvailableFaction(string factionId, out IRaiderFactionDefinition definition)
		{
			definition = null;
			if (!TryGetFaction(factionId, out IRaiderFactionDefinition definition2))
			{
				return false;
			}
			if (!IsFactionAvailable(definition2))
			{
				return false;
			}
			definition = definition2;
			return true;
		}

		public static bool TrySelectProgressiveFaction(out IRaiderFactionDefinition chosen)
		{
			chosen = null;
			List<IRaiderFactionDefinition> list = new List<IRaiderFactionDefinition>();
			foreach (IRaiderFactionDefinition value in _factions.Values)
			{
				if (IsFactionAvailable(value))
				{
					list.Add(value);
				}
			}
			if (list.Count == 0)
			{
				return false;
			}
			list.Sort((IRaiderFactionDefinition a, IRaiderFactionDefinition b) => (b.RequiredGlobalKeys?.Count ?? 0).CompareTo(a.RequiredGlobalKeys?.Count ?? 0));
			if (list.Count > 1 && Random.value < 0.3f)
			{
				chosen = list[Random.Range(1, list.Count)];
			}
			else
			{
				chosen = list[0];
			}
			return true;
		}

		public static IEnumerable<IRaiderFactionDefinition> GetAllFactions()
		{
			return _factions.Values;
		}

		internal static void RegisterBuiltInFactions()
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_045c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0487: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0508: Unknown result type (might be due to invalid IL or missing references)
			//IL_0533: Unknown result type (might be due to invalid IL or missing references)
			//IL_0652: Unknown result type (might be due to invalid IL or missing references)
			//IL_067d: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0729: Unknown result type (might be due to invalid IL or missing references)
			//IL_0754: Unknown result type (might be due to invalid IL or missing references)
			//IL_077f: Unknown result type (might be due to invalid IL or missing references)
			RaiderFactionDefinition raiderFactionDefinition = new RaiderFactionDefinition();
			raiderFactionDefinition.FactionId = "marauders";
			raiderFactionDefinition.DisplayName = "Exile Marauders";
			raiderFactionDefinition.RaiderPrefabName = "VF_Marauder";
			raiderFactionDefinition.WarlordPrefabName = "VF_Warlord";
			raiderFactionDefinition.UsesCustomHumanoidRig = true;
			raiderFactionDefinition.RequiredGlobalKeys = Array.Empty<string>();
			raiderFactionDefinition.ForbiddenGlobalKeys = Array.Empty<string>();
			raiderFactionDefinition.MinRaidSize = 3;
			raiderFactionDefinition.MaxRaidSize = 4;
			raiderFactionDefinition.CampGuardCount = 2;
			raiderFactionDefinition.RaiderDefaultEquipment = new string[5] { "ArmorLeatherChest", "ArmorLeatherLegs", "HelmetLeather", "AxeBronze", "ShieldWood" };
			raiderFactionDefinition.WarlordDefaultEquipment = new string[6] { "ArmorIronChest", "ArmorIronLegs", "HelmetIron", "CapeWolf", "SwordIron", "ShieldBanded" };
			raiderFactionDefinition.CampPieces = new CampPieceEntry[13]
			{
				new CampPieceEntry("bonfire", Vector3.zero),
				new CampPieceEntry("piece_chest", new Vector3(0f, 0f, 2.8f), 180f, isSpoilsChest: true),
				new CampPieceEntry("piece_chair02", new Vector3(-2.4f, 0f, 0.5f), 90f),
				new CampPieceEntry("piece_chair02", new Vector3(2.4f, 0f, 0.5f), -90f),
				new CampPieceEntry("piece_banner01", new Vector3(-2.2f, 0f, 3f), 160f),
				new CampPieceEntry("piece_banner01", new Vector3(2.2f, 0f, 3f), -160f),
				new CampPieceEntry("wood_wall_roof_45", new Vector3(0f, 0f, 3.4f)),
				new CampPieceEntry("stake_wall", new Vector3(-4.5f, 0f, 4.5f), 45f),
				new CampPieceEntry("stake_wall", new Vector3(4.5f, 0f, 4.5f), -45f),
				new CampPieceEntry("stake_wall", new Vector3(-5.5f, 0f, 0f), 90f),
				new CampPieceEntry("stake_wall", new Vector3(5.5f, 0f, 0f), -90f),
				new CampPieceEntry("piece_groundtorch_wood", new Vector3(-3f, 0f, -3.5f)),
				new CampPieceEntry("piece_groundtorch_wood", new Vector3(3f, 0f, -3.5f))
			};
			raiderFactionDefinition.WarlordBountyTable = new BountyLootEntry[5]
			{
				new BountyLootEntry("Coins", 35, 85),
				new BountyLootEntry("Ruby", 2, 5, 0.85f),
				new BountyLootEntry("AmberPearl", 2, 6, 0.85f),
				new BountyLootEntry("SilverNecklace", 1, 2, 0.65f),
				new BountyLootEntry("Iron", 4, 10, 0.75f)
			};
			raiderFactionDefinition.InterceptedVanillaEvents = new string[3] { "army_eikthyr", "army_theelder", "skeletons" };
			RegisterFaction(raiderFactionDefinition);
			raiderFactionDefinition = new RaiderFactionDefinition();
			raiderFactionDefinition.FactionId = "draugr";
			raiderFactionDefinition.DisplayName = "Draugr Reavers";
			raiderFactionDefinition.RaiderPrefabName = "Draugr";
			raiderFactionDefinition.WarlordPrefabName = "Draugr_Elite";
			raiderFactionDefinition.UsesCustomHumanoidRig = false;
			raiderFactionDefinition.RequiredGlobalKeys = new string[1] { "defeated_gdking" };
			raiderFactionDefinition.ForbiddenGlobalKeys = Array.Empty<string>();
			raiderFactionDefinition.MinRaidSize = 3;
			raiderFactionDefinition.MaxRaidSize = 4;
			raiderFactionDefinition.CampGuardCount = 2;
			raiderFactionDefinition.CampPieces = new CampPieceEntry[7]
			{
				new CampPieceEntry("fire_pit", Vector3.zero),
				new CampPieceEntry("piece_chest", new Vector3(0f, 0f, 2.6f), 180f, isSpoilsChest: true),
				new CampPieceEntry("stone_wall_2x1", new Vector3(0f, 0f, 4f)),
				new CampPieceEntry("stone_wall_2x1", new Vector3(-3.2f, 0f, 2.5f), 60f),
				new CampPieceEntry("stone_wall_2x1", new Vector3(3.2f, 0f, 2.5f), -60f),
				new CampPieceEntry("piece_groundtorch_green", new Vector3(-2.6f, 0f, -2.6f)),
				new CampPieceEntry("piece_groundtorch_green", new Vector3(2.6f, 0f, -2.6f))
			};
			raiderFactionDefinition.WarlordBountyTable = new BountyLootEntry[4]
			{
				new BountyLootEntry("Entrails", 6, 12),
				new BountyLootEntry("IronScrap", 6, 14, 0.9f),
				new BountyLootEntry("Chain", 1, 3, 0.65f),
				new BountyLootEntry("Coins", 25, 60, 0.85f)
			};
			raiderFactionDefinition.InterceptedVanillaEvents = new string[1] { "army_bonemass" };
			RegisterFaction(raiderFactionDefinition);
			raiderFactionDefinition = new RaiderFactionDefinition();
			raiderFactionDefinition.FactionId = "fulings";
			raiderFactionDefinition.DisplayName = "Fuling Plunderers";
			raiderFactionDefinition.RaiderPrefabName = "Goblin";
			raiderFactionDefinition.WarlordPrefabName = "GoblinBrute";
			raiderFactionDefinition.UsesCustomHumanoidRig = false;
			raiderFactionDefinition.RequiredGlobalKeys = new string[1] { "defeated_dragon" };
			raiderFactionDefinition.ForbiddenGlobalKeys = Array.Empty<string>();
			raiderFactionDefinition.MinRaidSize = 4;
			raiderFactionDefinition.MaxRaidSize = 5;
			raiderFactionDefinition.CampGuardCount = 3;
			raiderFactionDefinition.CampPieces = new CampPieceEntry[8]
			{
				new CampPieceEntry("bonfire", Vector3.zero),
				new CampPieceEntry("piece_chest", new Vector3(0f, 0f, 3f), 180f, isSpoilsChest: true),
				new CampPieceEntry("stake_wall", new Vector3(-4.2f, 0f, 4.2f), 45f),
				new CampPieceEntry("stake_wall", new Vector3(4.2f, 0f, 4.2f), -45f),
				new CampPieceEntry("stake_wall", new Vector3(-5.2f, 0f, 0f), 90f),
				new CampPieceEntry("stake_wall", new Vector3(5.2f, 0f, 0f), -90f),
				new CampPieceEntry("piece_groundtorch_wood", new Vector3(-3f, 0f, -3.2f)),
				new CampPieceEntry("piece_groundtorch_wood", new Vector3(3f, 0f, -3.2f))
			};
			raiderFactionDefinition.WarlordBountyTable = new BountyLootEntry[4]
			{
				new BountyLootEntry("BlackMetalScrap", 8, 18),
				new BountyLootEntry("Coins", 60, 140),
				new BountyLootEntry("Needle", 5, 12, 0.75f),
				new BountyLootEntry("LinenThread", 4, 10, 0.7f)
			};
			raiderFactionDefinition.InterceptedVanillaEvents = new string[1] { "army_goblin" };
			RegisterFaction(raiderFactionDefinition);
		}
	}
}
namespace VikingFactions.Core
{
	public static class AiHelpers
	{
		private static readonly MethodInfo _moveTo = AccessTools.Method(typeof(BaseAI), "MoveTo", (Type[])null, (Type[])null);

		private static readonly MethodInfo _lookAt = AccessTools.Method(typeof(BaseAI), "LookAt", (Type[])null, (Type[])null);

		private static readonly object[] _moveArgs = new object[4];

		private static readonly object[] _lookArgs = new object[1];

		public static bool MoveTo(BaseAI ai, float dt, Vector3 point, float dist, bool run)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			_moveArgs[0] = dt;
			_moveArgs[1] = point;
			_moveArgs[2] = dist;
			_moveArgs[3] = run;
			if (_moveTo != null)
			{
				return (bool)_moveTo.Invoke(ai, _moveArgs);
			}
			return false;
		}

		public static void LookAt(BaseAI ai, Vector3 point)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			_lookArgs[0] = point;
			_lookAt?.Invoke(ai, _lookArgs);
		}

		public static void Say(Character speaker, string text)
		{
			//IL_0022: 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)
			if (!((Object)(object)Chat.instance == (Object)null) && !((Object)(object)speaker == (Object)null))
			{
				Chat.instance.SetNpcText(((Component)speaker).gameObject, Vector3.up * 1.8f, 20f, 6f, speaker.m_name, text, false);
			}
		}

		public static bool PlayerNear(Vector3 pos, float radius)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			List<Player> allPlayers = Player.GetAllPlayers();
			float num = radius * radius;
			for (int i = 0; i < allPlayers.Count; i++)
			{
				if ((Object)(object)allPlayers[i] != (Object)null)
				{
					Vector3 val = ((Component)allPlayers[i]).transform.position - pos;
					if (((Vector3)(ref val)).sqrMagnitude <= num)
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	public static class FactionRoles
	{
		public const NpcRoleFlags Wayfarer = (NpcRoleFlags)65536u;

		public const NpcRoleFlags Marauder = (NpcRoleFlags)131072u;
	}
	public static class FactionKeys
	{
		public const string WfState = "VF_WF_State";

		public const string WfTargetPos = "VF_WF_TargetPos";

		public const string WfOriginPos = "VF_WF_OriginPos";

		public const string WfLastMeal = "VF_WF_LastMeal";

		public const string WfMood = "VF_WF_Mood";

		public const string WfSince = "VF_WF_Since";

		public const string CampGuid = "VF_CampGuid";

		public const string CampState = "VF_CampState";

		public const string CampLastRaidTime = "VF_CampLastRaid";

		public const string IsSpoilsChest = "VF_IsSpoilsChest";

		public const string RaiderState = "VF_Raider_State";

		public const string RaiderTargetPos = "VF_Raider_TargetPos";

		public const string RaiderCampPos = "VF_Raider_CampPos";

		public const string RaiderFaction = "VF_Raider_Faction";

		public const string RaiderStolen = "VF_Raider_Stolen";

		public const string RaiderLoot = "VF_Raider_Loot";

		public const string RaiderSince = "VF_Raider_Since";
	}
	public static class LootStore
	{
		public const int Width = 6;

		public const int Height = 3;

		public static Inventory NewInventory(string name = "VF_Loot")
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			return new Inventory(name, (Sprite)null, 6, 3);
		}

		public static Inventory LoadBase64(ZDO zdo, string key)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Inventory val = NewInventory();
			string text = zdo.GetString(key, "");
			if (!string.IsNullOrEmpty(text))
			{
				try
				{
					val.Load(new ZPackage(text));
				}
				catch (Exception ex)
				{
					VikingFactionsPlugin.Log.LogWarning((object)("[LootStore] Failed to load '" + key + "': " + ex.Message));
				}
			}
			return val;
		}

		public static void SaveBase64(ZDO zdo, string key, Inventory inv)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			if (inv.NrOfItems() == 0)
			{
				zdo.Set(key, "");
				return;
			}
			ZPackage val = new ZPackage();
			inv.Save(val);
			zdo.Set(key, val.GetBase64());
		}

		public static Inventory LoadChest(ZDO chestZdo)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			Inventory val = NewInventory("SpoilsChest");
			byte[] byteArray = chestZdo.GetByteArray(ZDOVars.s_items, (byte[])null);
			if (byteArray != null && byteArray.Length != 0)
			{
				try
				{
					val.Load(new ZPackage(byteArray));
				}
				catch (Exception ex)
				{
					VikingFactionsPlugin.Log.LogWarning((object)("[LootStore] Failed to load chest: " + ex.Message));
				}
			}
			return val;
		}

		public static void SaveChest(ZDO chestZdo, Inventory inv)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			inv.Save(val);
			chestZdo.Set(ZDOVars.s_items, val.GetArray());
		}

		public static bool AddPrefab(Inventory inv, string prefabName, int stack)
		{
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				return false;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
			if ((Object)(object)itemPrefab == (Object)null || (Object)(object)itemPrefab.GetComponent<ItemDrop>() == (Object)null)
			{
				return false;
			}
			return inv.AddItem(itemPrefab, stack);
		}

		public static int MoveAll(Inventory source, Inventory dest)
		{
			int num = 0;
			List<ItemData> list = new List<ItemData>(source.GetAllItems());
			for (int i = 0; i < list.Count; i++)
			{
				ItemData val = list[i].Clone();
				if (!dest.AddItem(val))
				{
					num++;
				}
			}
			return num;
		}
	}
}
namespace VikingFactions.Configuration
{
	public class ConfigurationManagerAttributes
	{
		public bool? Browsable;

		public string? Category;

		public bool? DefaultValue;

		public bool? HideDefaultButton;

		public bool? HideSettingName;

		public string? Description;

		public int? Order;

		public bool? ReadOnly;

		public bool? IsAdvanced;

		public bool? IsAdminOnly;
	}
	public static class ModConfig
	{
		public static ConfigEntry<bool> ModEnabled { get; private set; }

		public static ConfigEntry<bool> EnableWayfarers { get; private set; }

		public static ConfigEntry<int> MinHospitalityComfort { get; private set; }

		public static ConfigEntry<int> ComfortPerWayfarerCap { get; private set; }

		public static ConfigEntry<float> WayfarerSpawnIntervalSeconds { get; private set; }

		public static ConfigEntry<float> WayfarerMealIntervalSeconds { get; private set; }

		public static ConfigEntry<bool> EnableMarauderHeists { get; private set; }

		public static ConfigEntry<bool> InterceptVanillaRaids { get; private set; }

		public static ConfigEntry<int> MaxStacksPerRaider { get; private set; }

		public static ConfigEntry<float> RaiderSiphonSecondsPerStack { get; private set; }

		public static ConfigEntry<float> RaiderCarrySpeedMultiplier { get; private set; }

		public static ConfigEntry<bool> RaidersRespectWards { get; private set; }

		public static ConfigEntry<float> CampSpawnMinDistance { get; private set; }

		public static ConfigEntry<float> CampSpawnMaxDistance { get; private set; }

		public static void Init(ConfigFile config)
		{
			ModEnabled = Bind(config, "1 - General", "Enabled", defaultValue: true, "Master switch to enable or disable all features of VikingFactions.", 100, null, isAdminOnly: true);
			EnableWayfarers = Bind(config, "2 - Wayfarers & Mead Hall", "EnableWayfarers", defaultValue: true, "Enable friendly Wayfarer travelers to visit qualifying Mead Halls and settlements.", 90, null, isAdminOnly: true);
			MinHospitalityComfort = Bind(config, "2 - Wayfarers & Mead Hall", "MinHospitalityComfort", 4, "Minimum comfort level near a lit hearth with roof cover required to attract Wayfarers.", 80, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(1, 20), isAdminOnly: true);
			ComfortPerWayfarerCap = Bind(config, "2 - Wayfarers & Mead Hall", "ComfortPerWayfarerCap", 3, "Comfort points required per simultaneous Wayfarer guest (e.g. Comfort 12 allows up to 4 Wayfarers).", 70, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(1, 10), isAdminOnly: true);
			WayfarerSpawnIntervalSeconds = Bind(config, "2 - Wayfarers & Mead Hall", "WayfarerSpawnIntervalSeconds", 300f, "Minimum interval in seconds between new Wayfarer arrivals at a qualifying Mead Hall.", 60, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(30f, 3600f), isAdminOnly: true);
			WayfarerMealIntervalSeconds = Bind(config, "2 - Wayfarers & Mead Hall", "WayfarerMealIntervalSeconds", 1200f, "Interval in seconds between Wayfarer meals consumed from nearby communal chests.", 50, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(120f, 7200f), isAdminOnly: true);
			EnableMarauderHeists = Bind(config, "3 - Marauders & Retaliation Camps", "EnableMarauderHeists", defaultValue: true, "Enable Marauder warbands, heist chest siphoning, and procedural retaliation camps.", 90, null, isAdminOnly: true);
			InterceptVanillaRaids = Bind(config, "3 - Marauders & Retaliation Camps", "InterceptVanillaRaids", defaultValue: true, "Convert eligible vanilla base raid events into physicalized VikingFactions camps and marching warbands.", 80, null, isAdminOnly: true);
			MaxStacksPerRaider = Bind(config, "3 - Marauders & Retaliation Camps", "MaxStacksPerRaider", 3, "Maximum number of item stacks a single raider can siphon before retreating to camp.", 70, (AcceptableValueBase?)(object)new AcceptableValueRange<int>(1, 10), isAdminOnly: true);
			RaiderSiphonSecondsPerStack = Bind(config, "3 - Marauders & Retaliation Camps", "RaiderSiphonSecondsPerStack", 4.5f, "Seconds a raider must channel at an unlocked chest to siphon one stack of items.", 60, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(1f, 20f), isAdminOnly: true);
			RaiderCarrySpeedMultiplier = Bind(config, "3 - Marauders & Retaliation Camps", "RaiderCarrySpeedMultiplier", 0.85f, "Movement speed multiplier applied to raiders carrying stolen loot.", 50, (AcceptableValueBase?)(object)new AcceptableValueRange<float>(0.3f, 1f), isAdminOnly: true);
			RaidersRespectWards = Bind(config, "3 - Marauders & Retaliation Camps", "RaidersRespectWards", defaultValue: true, "If true, raiders will not siphon chests that lie inside an active player ward area.", 45, null, isAdminOnly: true);
			CampSpawnMinDistance = Bind(config, "3 - Marauders & Retaliation Camps", "CampSpawnMinDistance", 250f, "Minimum distance in meters from the target settlement to spawn a procedural raider camp.", 40, (AcceptableValueBase?)(object)new AcceptableValueRan