Decompiled source of Bifrost Breakout v0.3.21

BepInEx/plugins/Bifrost-Breakout/BifrostBreakout.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using SoftReferenceableAssets;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Bifrost Breakout")]
[assembly: AssemblyDescription("Roaming monsters, migrating wildlife, warbands, unexpected encounters, and a world whose ecology changes as you progress.")]
[assembly: AssemblyCompany("ChorusReef")]
[assembly: AssemblyProduct("Bifrost Breakout")]
[assembly: AssemblyFileVersion("0.3.21.0")]
[assembly: AssemblyVersion("0.3.21.0")]
namespace ChorusReef.BifrostBreakout;

internal static class AmbientEncounterSystem
{
	internal const string GhostCooldownKey = "bifrost_ghost_ship_next_spawn";

	internal const string MeteorCooldownKey = "bifrost_meteor_next_spawn";

	internal const double GhostCooldownSeconds = 3600.0;

	internal const double MeteorCooldownSeconds = 1800.0;

	private const double AttemptIntervalSeconds = 300.0;

	private const float GhostChance = 20f;

	private const float MeteorChance = 25f;

	private static MonoBehaviour _host;

	private static Coroutine _loop;

	private static ConfigEntry<bool> _ghostEnabled;

	private static ConfigEntry<bool> _meteorEnabled;

	internal static ManualLogSource Log;

	internal static bool ServerReady
	{
		get
		{
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && (Object)(object)ZoneSystem.instance != (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				return (Object)(object)ObjectDB.instance != (Object)null;
			}
			return false;
		}
	}

	internal static void Initialize(MonoBehaviour host, ManualLogSource log, ConfigFile config)
	{
		_host = host;
		Log = log;
		_ghostEnabled = config.Bind<bool>("Ghost Ships", "Enabled", true, "Rare deep-Ocean Karves with three Wraiths and randomized cargo.");
		_meteorEnabled = config.Bind<bool>("Meteor Trolls", "Enabled", true, "Rare wilderness Trollstav impacts after Moder, outside PlayerBase coverage.");
		_loop = host.StartCoroutine(Run());
	}

	internal static void Shutdown()
	{
		if ((Object)(object)_host != (Object)null && _loop != null)
		{
			_host.StopCoroutine(_loop);
		}
		_loop = null;
		_host = null;
	}

	private static IEnumerator Run()
	{
		ZoneSystem world = null;
		double nextAttempt = 0.0;
		while (true)
		{
			yield return (object)new WaitForSeconds(10f);
			if (!ServerReady)
			{
				continue;
			}
			double timeSeconds = ZNet.instance.GetTimeSeconds();
			if ((Object)(object)world != (Object)(object)ZoneSystem.instance)
			{
				world = ZoneSystem.instance;
				nextAttempt = timeSeconds + 300.0;
			}
			if (timeSeconds < nextAttempt)
			{
				continue;
			}
			nextAttempt = timeSeconds + 300.0;
			try
			{
				List<Player> list = new List<Player>();
				List<Player> list2 = new List<Player>();
				foreach (Player allPlayer in Player.GetAllPlayers())
				{
					if (!((Object)(object)allPlayer == (Object)null) && !((Character)allPlayer).IsDead() && !((Character)allPlayer).InInterior() && !((Character)allPlayer).IsTeleporting())
					{
						if (DeepOcean(((Component)allPlayer).transform.position, out var _))
						{
							list.Add(allPlayer);
						}
						if (!DeepNorth(((Component)allPlayer).transform.position) && !MeteorEncounter.Protected(((Component)allPlayer).transform.position, 0.25f))
						{
							list2.Add(allPlayer);
						}
					}
				}
				if (_ghostEnabled.Value && list.Count > 0 && CooldownReady("bifrost_ghost_ship_next_spawn", timeSeconds) && Random.Range(0f, 100f) < 20f)
				{
					GhostShipEncounter.TrySpawn(list[Random.Range(0, list.Count)]);
				}
				if (_meteorEnabled.Value && list2.Count > 0 && world.GetGlobalKey("defeated_dragon") && CooldownReady("bifrost_meteor_next_spawn", timeSeconds) && Random.Range(0f, 100f) < 25f)
				{
					MeteorEncounter.TryStart(_host, list2[Random.Range(0, list2.Count)]);
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Ambient encounter attempt failed safely: " + ex));
			}
		}
	}

	internal static bool CooldownReady(string key, double now)
	{
		string s = default(string);
		if (!ZoneSystem.instance.GetGlobalKey(key, ref s))
		{
			return true;
		}
		if (double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
		{
			return now >= result;
		}
		return false;
	}

	internal static void BeginCooldown(string key, double seconds)
	{
		long num = (long)Math.Ceiling(ZNet.instance.GetTimeSeconds() + seconds);
		ZoneSystem.instance.SetGlobalKey(key + " " + num.ToString(CultureInfo.InvariantCulture));
	}

	internal static bool DeepOcean(Vector3 point, out float surface)
	{
		//IL_000e: 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_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Invalid comparison between Unknown and I4
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		surface = 0f;
		ZoneSystem instance = ZoneSystem.instance;
		if (!instance.IsZoneLoaded(point) || (int)WorldGenerator.instance.GetBiome(point) != 256)
		{
			return false;
		}
		float num = default(float);
		if (!instance.GetGroundHeight(point, ref num) || instance.m_waterLevel - num < 5f)
		{
			return false;
		}
		point.y = instance.m_waterLevel;
		surface = Floating.GetLiquidLevel(point, 1f, (LiquidType)0);
		if (surface > -1000f)
		{
			return surface - num >= 5f;
		}
		return false;
	}

	internal static bool DeepNorth(Vector3 point)
	{
		//IL_000c: 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_0014: Invalid comparison between Unknown and I4
		if (WorldGenerator.instance != null)
		{
			return (int)WorldGenerator.instance.GetBiome(point) == 64;
		}
		return false;
	}

	internal static bool AwayFromPlayers(Vector3 point, float minimumDistance)
	{
		//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)
		foreach (Player allPlayer in Player.GetAllPlayers())
		{
			if ((Object)(object)allPlayer != (Object)null && Vector3.Distance(((Component)allPlayer).transform.position, point) < minimumDistance)
			{
				return false;
			}
		}
		return true;
	}
}
internal sealed class AquaticZdoTracker
{
	private readonly string[] _prefabNames;

	private readonly int _ownershipMarkerKey;

	private readonly HashSet<ZDOID> _trackedIds = new HashSet<ZDOID>();

	private readonly List<ZDO> _recoveryBuffer = new List<ZDO>();

	private readonly List<ZDOID> _staleIds = new List<ZDOID>();

	private int _recoveryPrefabIndex;

	private int _recoverySectorIndex;

	private bool _recoveryComplete;

	internal bool RecoveryComplete => _recoveryComplete;

	internal AquaticZdoTracker(int ownershipMarkerKey, params string[] prefabNames)
	{
		if (prefabNames == null || prefabNames.Length == 0)
		{
			throw new ArgumentException("At least one aquatic prefab name is required.", "prefabNames");
		}
		_ownershipMarkerKey = ownershipMarkerKey;
		_prefabNames = prefabNames;
	}

	internal void Reset()
	{
		_trackedIds.Clear();
		_recoveryBuffer.Clear();
		_recoveryPrefabIndex = 0;
		_recoverySectorIndex = 0;
		_recoveryComplete = false;
	}

	internal bool RecoverStep(out int recovered)
	{
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		recovered = 0;
		if (_recoveryComplete)
		{
			return true;
		}
		if (ZDOMan.instance == null)
		{
			return false;
		}
		if (!ZDOMan.instance.GetAllZDOsWithPrefabIterative(_prefabNames[_recoveryPrefabIndex], _recoveryBuffer, ref _recoverySectorIndex))
		{
			return false;
		}
		for (int i = 0; i < _recoveryBuffer.Count; i++)
		{
			ZDO val = _recoveryBuffer[i];
			if (val != null && val.GetBool(_ownershipMarkerKey, false) && _trackedIds.Add(val.m_uid))
			{
				recovered++;
			}
		}
		_recoveryBuffer.Clear();
		_recoverySectorIndex = 0;
		_recoveryPrefabIndex++;
		_recoveryComplete = _recoveryPrefabIndex >= _prefabNames.Length;
		return _recoveryComplete;
	}

	internal void Track(ZDO zdo)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		if (zdo != null && zdo.GetBool(_ownershipMarkerKey, false))
		{
			_trackedIds.Add(zdo.m_uid);
		}
	}

	internal void Untrack(ZDO zdo)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		if (zdo != null)
		{
			_trackedIds.Remove(zdo.m_uid);
		}
	}

	internal void ResolveTracked(List<ZDO> result)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		result.Clear();
		_staleIds.Clear();
		ZDOMan instance = ZDOMan.instance;
		if (instance == null)
		{
			return;
		}
		foreach (ZDOID trackedId in _trackedIds)
		{
			ZDO zDO = instance.GetZDO(trackedId);
			if (zDO == null || !zDO.GetBool(_ownershipMarkerKey, false))
			{
				_staleIds.Add(trackedId);
			}
			else
			{
				result.Add(zDO);
			}
		}
		for (int i = 0; i < _staleIds.Count; i++)
		{
			_trackedIds.Remove(_staleIds[i]);
		}
	}

	internal bool Destroy(ZDO zdo)
	{
		if (zdo == null)
		{
			return false;
		}
		Untrack(zdo);
		ZNetView val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.FindInstance(zdo) : null);
		if ((Object)(object)val != (Object)null && val.IsValid())
		{
			if (!val.IsOwner())
			{
				val.ClaimOwnership();
			}
			ZNetScene.instance.Destroy(((Component)val).gameObject);
			return true;
		}
		if (ZDOMan.instance != null)
		{
			ZDOMan.instance.DestroyZDO(zdo);
		}
		return false;
	}
}
internal static class DraugrVillageRitualSystem
{
	internal const string WardPrefabName = "dverger_guardstone";

	internal const string DemisterPrefabName = "dverger_demister_large";

	internal const string AbominationPrefabName = "Abomination";

	internal const string GreenTorchPrefabName = "CastleKit_groundtorch_green";

	internal const string WardMarkerKey = "Bifrost.DraugrVillageWard";

	internal const string DemisterMarkerKey = "Bifrost.DraugrVillageDemister";

	internal const string AbominationMarkerKey = "Bifrost.DraugrVillageAbomination";

	internal const string SpawnerMarkerKey = "Bifrost.DraugrVillageProtectedSpawner";

	internal const string DecorationMarkerKey = "Bifrost.DraugrVillageDecoration";

	internal const string RitualAltarPrefabName = "altar";

	internal const string MistAnchorMarkerKey = "Bifrost.DraugrVillageMistAnchor";

	internal const float RitualRadius = 35f;

	internal const float RitualWardHealth = 100f;

	internal const float ActivationRange = 150f;

	private const float UpdateSeconds = 5f;

	private const float VillageScanRadius = 80f;

	internal const float MistRadius = 68f;

	internal const float MistHeight = 32f;

	private const double MistAfterWardSeconds = 600.0;

	private const double MistAfterCompletionSeconds = 90.0;

	private static readonly string[] MistPrefabCandidates = new string[3] { "MistArea", "MistArea_small", "MistArea_edge" };

	private static readonly string[] VillagePrefabs = new string[2] { "WoodVillage1", "WoodVillage2" };

	private static readonly HashSet<string> WaitingLogged = new HashSet<string>(StringComparer.Ordinal);

	private static readonly HashSet<string> FallbackLogged = new HashSet<string>(StringComparer.Ordinal);

	private static MonoBehaviour _host;

	private static ManualLogSource _log;

	private static Coroutine _loop;

	private static ZoneSystem _world;

	internal static void Initialize(MonoBehaviour host, ManualLogSource log)
	{
		_host = host;
		_log = log;
		_loop = host.StartCoroutine(Run());
	}

	internal static void Shutdown()
	{
		if ((Object)(object)_host != (Object)null && _loop != null)
		{
			_host.StopCoroutine(_loop);
		}
		_loop = null;
		_host = null;
		_log = null;
		_world = null;
		WaitingLogged.Clear();
		FallbackLogged.Clear();
	}

	private static IEnumerator Run()
	{
		while (true)
		{
			yield return (object)new WaitForSeconds(5f);
			if (!ServerReady())
			{
				continue;
			}
			try
			{
				if ((Object)(object)_world != (Object)(object)ZoneSystem.instance)
				{
					_world = ZoneSystem.instance;
					WaitingLogged.Clear();
					FallbackLogged.Clear();
				}
				List<Vector3> list = new List<Vector3>();
				foreach (LocationInstance location in _world.GetLocationList())
				{
					if (IsVillage(location) && HasPlayerNear(location.m_position))
					{
						list.Add(location.m_position);
						MaintainOrAugment(location.m_position);
					}
				}
				MaintainLoadedVillageFallback(list);
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogError((object)("Draugr-village ritual update failed safely: " + ex));
				}
			}
		}
	}

	private static void MaintainOrAugment(Vector3 villageCenter)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: 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_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		string token = Token(villageCenter);
		if (_world.GetGlobalKey(CompletedKey(token)))
		{
			CleanupLoadedEncounter(token, keepMist: false);
			return;
		}
		if (!_world.GetGlobalKey(AugmentedKey(token)))
		{
			TryAugment(villageCenter);
			return;
		}
		if (TryFindHeart(villageCenter, out var heart, out var bounds) && TryFindRitualCenter(heart, bounds, out var center, out var rotation))
		{
			MigrateRitualObjects(token, villageCenter, center, rotation);
			EnsureMistAnchor(center, token);
			OpenVillageDoorsOnce(token, villageCenter, center);
		}
		if (HasPlayerNear(villageCenter, 55f))
		{
			RecoverLegacyAbominationDeath(token);
		}
		TryComplete(token);
	}

	private static void MaintainLoadedVillageFallback(List<Vector3> naturalCenters)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: 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_0087: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
		Room[] array = Object.FindObjectsByType<Room>((FindObjectsInactive)1, (FindObjectsSortMode)0);
		List<Vector3> list = new List<Vector3>();
		foreach (Room val in array)
		{
			if ((Object)(object)val == (Object)null || !IsVillageHeartName(((Object)val).name) || !HasPlayerNear(((Component)val).transform.position))
			{
				continue;
			}
			Vector3 position = ((Component)val).transform.position;
			if (NearAny(position, naturalCenters, 80f) || NearAny(position, list, 80f) || FindDraugrSpawners(position).Count == 0)
			{
				continue;
			}
			list.Add(position);
			string text = Token(position);
			if (FallbackLogged.Add(text))
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogInfo((object)("The Village discovered loaded Draugr-village fallback " + text + " from room '" + ((Object)val).name + "' because no ZoneSystem LocationInstance was available."));
				}
			}
			MaintainOrAugment(position);
		}
	}

	private static bool IsVillageHeartName(string value)
	{
		if (string.IsNullOrEmpty(value))
		{
			return false;
		}
		string text = value.ToLowerInvariant();
		if (!text.Contains("meadowsvillage_greathall"))
		{
			return text.Contains("meadowsvillage_longhouse");
		}
		return true;
	}

	private static bool NearAny(Vector3 point, List<Vector3> centers, float range)
	{
		//IL_000a: 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)
		float num = range * range;
		for (int i = 0; i < centers.Count; i++)
		{
			Vector3 val = centers[i] - point;
			if (((Vector3)(ref val)).sqrMagnitude <= num)
			{
				return true;
			}
		}
		return false;
	}

	private static bool ServerReady()
	{
		if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && (Object)(object)ZoneSystem.instance != (Object)null)
		{
			return (Object)(object)ZNetScene.instance != (Object)null;
		}
		return false;
	}

	private static bool IsVillage(LocationInstance location)
	{
		//IL_0000: 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_0012: Unknown result type (might be due to invalid IL or missing references)
		if (!location.m_placed || location.m_location == null)
		{
			return false;
		}
		string prefabName = location.m_location.m_prefabName;
		for (int i = 0; i < VillagePrefabs.Length; i++)
		{
			if (string.Equals(prefabName, VillagePrefabs[i], StringComparison.Ordinal))
			{
				return true;
			}
		}
		return false;
	}

	private static bool HasPlayerNear(Vector3 center)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		return HasPlayerNear(center, 150f);
	}

	private static bool HasPlayerNear(Vector3 center, float range)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		float num = range * range;
		foreach (Player allPlayer in Player.GetAllPlayers())
		{
			if ((Object)(object)allPlayer != (Object)null && !((Character)allPlayer).IsDead())
			{
				Vector3 val = ((Component)allPlayer).transform.position - center;
				if (((Vector3)(ref val)).sqrMagnitude <= num)
				{
					return true;
				}
			}
		}
		return false;
	}

	private static void TryAugment(Vector3 villageCenter)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: 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_0074: 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_0086: 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_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		string text = Token(villageCenter);
		List<CreatureSpawner> list = FindDraugrSpawners(villageCenter);
		if (list.Count == 0)
		{
			return;
		}
		if (!TryFindHeart(villageCenter, out var heart, out var bounds))
		{
			if (WaitingLogged.Add(text))
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogInfo((object)("Draugr village " + text + " has loaded spawners but is waiting for its generated greathall/longhouse room hierarchy."));
				}
			}
		}
		else
		{
			if (!TryFindRitualCenter(heart, bounds, out var center, out var rotation))
			{
				return;
			}
			CreatureSpawner val = FindClosestSpawner(list, center);
			bool flag = MarkProtectedSpawner(val, text);
			bool num = EnsureWard(center, rotation, text);
			bool flag2 = EnsureDemister(center, text);
			bool flag3 = EnsureMistAnchor(center, text);
			bool flag4 = EnsureAbomination(center, villageCenter, ((Component)heart).transform.forward, text);
			EnsureRitualAltar(center, rotation, text);
			EnsureGreenTorches(center, rotation, text);
			OpenVillageDoorsOnce(text, villageCenter, center);
			if (num && flag4 && flag)
			{
				_world.SetGlobalKey(AugmentedKey(text));
				WaitingLogged.Remove(text);
				ManualLogSource log2 = _log;
				if (log2 != null)
				{
					log2.LogInfo((object)("Augmented The Village " + text + " using room '" + ((Object)heart).name + "' at " + Format(center) + ": ground-level protected Undead ritual ward, dormant unstarred Abomination, and Draugr spawner '" + ((Object)val).name + "'. Optional demister=" + flag2 + ", visible mist=" + flag3 + "."));
				}
			}
		}
	}

	private static List<CreatureSpawner> FindDraugrSpawners(Vector3 center)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		List<CreatureSpawner> list = new List<CreatureSpawner>();
		float num = 6400f;
		CreatureSpawner[] array = Object.FindObjectsByType<CreatureSpawner>((FindObjectsInactive)1, (FindObjectsSortMode)0);
		foreach (CreatureSpawner val in array)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.m_creaturePrefab == (Object)null))
			{
				Vector3 val2 = ((Component)val).transform.position - center;
				if (!(((Vector3)(ref val2)).sqrMagnitude > num) && ((Object)val.m_creaturePrefab).name.IndexOf("Draugr", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					list.Add(val);
				}
			}
		}
		return list;
	}

	private static bool TryFindHeart(Vector3 center, out Room heart, out Bounds bounds)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: 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_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		heart = null;
		bounds = new Bounds(center, Vector3.zero);
		float num = float.MinValue;
		float num2 = 6400f;
		Room[] array = Object.FindObjectsByType<Room>((FindObjectsInactive)1, (FindObjectsSortMode)0);
		foreach (Room val in array)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			Vector3 val2 = ((Component)val).transform.position - center;
			if (((Vector3)(ref val2)).sqrMagnitude > num2)
			{
				continue;
			}
			string text = ((Object)val).name.ToLowerInvariant();
			bool flag = text.Contains("meadowsvillage_greathall");
			bool flag2 = text.Contains("meadowsvillage_longhouse");
			if ((flag || flag2) && TryGetBounds(((Component)val).gameObject, out var bounds2))
			{
				float num3 = ((Bounds)(ref bounds2)).size.x * ((Bounds)(ref bounds2)).size.z + (flag ? 10000f : 5000f) - (text.Contains("ruin") ? 2500f : 0f);
				if (!(num3 <= num))
				{
					num = num3;
					heart = val;
					bounds = bounds2;
				}
			}
		}
		return (Object)(object)heart != (Object)null;
	}

	private static bool TryGetBounds(GameObject root, out Bounds bounds)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: 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_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		bounds = new Bounds(root.transform.position, Vector3.zero);
		bool flag = false;
		Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true);
		foreach (Collider val in componentsInChildren)
		{
			if (!((Object)(object)val == (Object)null) && val.enabled)
			{
				if (!flag)
				{
					bounds = val.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val.bounds);
				}
			}
		}
		if (flag)
		{
			return true;
		}
		Renderer[] componentsInChildren2 = root.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val2 in componentsInChildren2)
		{
			if (!((Object)(object)val2 == (Object)null) && val2.enabled)
			{
				if (!flag)
				{
					bounds = val2.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref bounds)).Encapsulate(val2.bounds);
				}
			}
		}
		return flag;
	}

	private static bool TryFindRitualCenter(Room heart, Bounds heartBounds, out Vector3 center, out Quaternion rotation)
	{
		//IL_0003: 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_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_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: 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_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: 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_00ef: 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_0110: 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_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		center = ((Bounds)(ref heartBounds)).center;
		Vector3 val = ((Component)heart).transform.forward;
		val.y = 0f;
		Door[] componentsInChildren = ((Component)heart).GetComponentsInChildren<Door>(true);
		float num = 0f;
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Vector3 val2 = ((Component)componentsInChildren[i]).transform.position - ((Bounds)(ref heartBounds)).center;
			val2.y = 0f;
			if (!(((Vector3)(ref val2)).sqrMagnitude <= num))
			{
				num = ((Vector3)(ref val2)).sqrMagnitude;
				val = val2;
			}
		}
		if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
		{
			val = Vector3.forward;
		}
		((Vector3)(ref val)).Normalize();
		float num2 = Mathf.Abs(val.x) * ((Bounds)(ref heartBounds)).extents.x + Mathf.Abs(val.z) * ((Bounds)(ref heartBounds)).extents.z;
		center = ((Bounds)(ref heartBounds)).center + val * (num2 + 3f);
		if (!TryTerrainGround(center, out center))
		{
			rotation = ((Component)heart).transform.rotation;
			return false;
		}
		rotation = Quaternion.LookRotation(val, Vector3.up);
		return true;
	}

	private static bool TryTerrainGround(Vector3 horizontal, out Vector3 grounded)
	{
		//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_000c: Unknown result type (might be due to invalid IL or missing references)
		grounded = horizontal;
		float num = default(float);
		if (!_world.GetGroundHeight(horizontal, ref num))
		{
			return false;
		}
		grounded.y = num + 0.05f;
		return true;
	}

	private static bool TryGround(Vector3 horizontal, float rayStart, out Vector3 grounded)
	{
		//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_000c: 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_002d: 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_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: 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_009b: 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_00af: 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)
		grounded = horizontal;
		float num = default(float);
		if (!_world.GetGroundHeight(horizontal, ref num))
		{
			return false;
		}
		Vector3 val = default(Vector3);
		((Vector3)(ref val))..ctor(horizontal.x, Mathf.Max(rayStart, num + 15f), horizontal.z);
		RaycastHit[] array = Physics.RaycastAll(val, Vector3.down, 60f, -5, (QueryTriggerInteraction)1);
		float num2 = float.MinValue;
		for (int i = 0; i < array.Length; i++)
		{
			RaycastHit val2 = array[i];
			if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Character>() != (Object)null) && !(((RaycastHit)(ref val2)).point.y < num - 1f) && !(((RaycastHit)(ref val2)).point.y > val.y) && !(((RaycastHit)(ref val2)).point.y <= num2))
			{
				num2 = ((RaycastHit)(ref val2)).point.y;
			}
		}
		grounded.y = ((num2 > float.MinValue) ? num2 : num);
		return true;
	}

	private static CreatureSpawner FindClosestSpawner(List<CreatureSpawner> spawners, Vector3 anchor)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		CreatureSpawner result = null;
		float num = float.MaxValue;
		for (int i = 0; i < spawners.Count; i++)
		{
			Vector3 val = ((Component)spawners[i]).transform.position - anchor;
			float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
			if (!(sqrMagnitude >= num))
			{
				num = sqrMagnitude;
				result = spawners[i];
			}
		}
		return result;
	}

	private static bool MarkProtectedSpawner(CreatureSpawner spawner, string token)
	{
		if ((Object)(object)spawner == (Object)null)
		{
			return false;
		}
		Destructible component = ((Component)spawner).GetComponent<Destructible>();
		if ((Object)(object)component == (Object)null)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)("Draugr village " + token + " spawner '" + ((Object)spawner).name + "' is not destructible and needs no friendly-fire protection."));
			}
			return true;
		}
		ZNetView val = (((Object)(object)component != (Object)null) ? ((Component)component).GetComponent<ZNetView>() : null);
		ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
		if (val2 == null)
		{
			ManualLogSource log2 = _log;
			if (log2 != null)
			{
				log2.LogWarning((object)("Draugr village " + token + " destructible spawner '" + ((Object)spawner).name + "' lacks a persistent ZNetView; the encounter will continue without marking it."));
			}
			return true;
		}
		val2.Set("Bifrost.DraugrVillageProtectedSpawner", token);
		return true;
	}

	private static bool EnsureWard(Vector3 position, Quaternion rotation, string token)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		if (_world.GetGlobalKey(WardCreatedKey(token)))
		{
			return true;
		}
		GameObject prefab = ZNetScene.instance.GetPrefab("dverger_guardstone");
		if ((Object)(object)prefab == (Object)null)
		{
			return false;
		}
		GameObject val = Object.Instantiate<GameObject>(prefab, position, rotation);
		ZNetView component = val.GetComponent<ZNetView>();
		ZDO val2 = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		if (val2 == null)
		{
			Object.Destroy((Object)(object)val);
			return false;
		}
		val2.Set("Bifrost.DraugrVillageWard", token);
		ConfigureWard(val.GetComponent<PrivateArea>());
		_world.SetGlobalKey(WardCreatedKey(token));
		return true;
	}

	private static void ConfigureWard(PrivateArea area)
	{
		//IL_0065: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)area == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)area).GetComponent<ZNetView>();
		ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		if (val == null || string.IsNullOrEmpty(val.GetString("Bifrost.DraugrVillageWard", string.Empty)))
		{
			return;
		}
		string token = val.GetString("Bifrost.DraugrVillageWard", string.Empty);
		area.m_radius = 35f;
		area.m_ownerFaction = (Faction)3;
		if ((Object)(object)area.m_areaMarker != (Object)null)
		{
			area.m_areaMarker.m_radius = 35f;
		}
		EffectArea[] componentsInChildren = ((Component)area).GetComponentsInChildren<EffectArea>(true);
		foreach (EffectArea val2 in componentsInChildren)
		{
			if ((val2.m_type & 4) != 0)
			{
				((Component)val2).gameObject.SetActive(true);
			}
		}
		ApplyCursedWardAppearance(((Component)area).gameObject);
		WearNTear component2 = ((Component)area).GetComponent<WearNTear>();
		if ((Object)(object)component2 != (Object)null)
		{
			component2.m_health = 100f;
			if (component.IsOwner())
			{
				if (val.GetFloat(ZDOVars.s_health, 100f) > 100f)
				{
					val.Set(ZDOVars.s_health, 100f);
				}
				val.Set(ZDOVars.s_maxHealth, 100f);
			}
		}
		DraugrVillageContainment draugrVillageContainment = ((Component)area).GetComponent<DraugrVillageContainment>();
		if ((Object)(object)draugrVillageContainment == (Object)null)
		{
			draugrVillageContainment = ((Component)area).gameObject.AddComponent<DraugrVillageContainment>();
		}
		draugrVillageContainment.Configure(token, 35f);
	}

	private static void MigrateRitualObjects(string token, Vector3 villageCenter, Vector3 anchor, Quaternion rotation)
	{
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: 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_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: 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_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		if (_world.GetGlobalKey(WardDestroyedKey(token)))
		{
			return;
		}
		ZNetView[] array = Object.FindObjectsByType<ZNetView>((FindObjectsInactive)1, (FindObjectsSortMode)0);
		List<ZNetView> list = new List<ZNetView>();
		foreach (ZNetView val in array)
		{
			ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
			if (val2 == null)
			{
				continue;
			}
			if (string.Equals(val2.GetString("Bifrost.DraugrVillageWard", string.Empty), token, StringComparison.Ordinal))
			{
				MovePersistentObject(val, anchor, rotation);
			}
			else if (string.Equals(val2.GetString("Bifrost.DraugrVillageDemister", string.Empty), token, StringComparison.Ordinal))
			{
				MovePersistentObject(val, anchor + Vector3.down * 0.15f, Quaternion.identity);
			}
			else if (string.Equals(val2.GetString("Bifrost.DraugrVillageDecoration", string.Empty), token, StringComparison.Ordinal) && ((Object)((Component)val).gameObject).name.IndexOf("groundtorch_green", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				list.Add(val);
			}
			else
			{
				if (_world.GetGlobalKey(AbominationCenteredKey(token)) || !string.Equals(val2.GetString("Bifrost.DraugrVillageAbomination", string.Empty), token, StringComparison.Ordinal))
				{
					continue;
				}
				Vector3 grounded = villageCenter;
				if (TryTerrainGround(grounded, out grounded))
				{
					Vector3 val3 = anchor - grounded;
					val3.y = 0f;
					if (((Vector3)(ref val3)).sqrMagnitude < 0.01f)
					{
						val3 = rotation * Vector3.forward;
					}
					((Vector3)(ref val3)).Normalize();
					MovePersistentObject(val, grounded, Quaternion.LookRotation(val3, Vector3.up));
					_world.SetGlobalKey(AbominationCenteredKey(token));
				}
			}
		}
		list.Sort(delegate(ZNetView left, ZNetView right)
		{
			ZDO val4 = (((Object)(object)left != (Object)null && left.IsValid()) ? left.GetZDO() : null);
			ZDO val5 = (((Object)(object)right != (Object)null && right.IsValid()) ? right.GetZDO() : null);
			string strA = ((val4 != null) ? ((object)Unsafe.As<ZDOID, ZDOID>(ref val4.m_uid)/*cast due to .constrained prefix*/).ToString() : string.Empty);
			string strB = ((val5 != null) ? ((object)Unsafe.As<ZDOID, ZDOID>(ref val5.m_uid)/*cast due to .constrained prefix*/).ToString() : string.Empty);
			return string.CompareOrdinal(strA, strB);
		});
		Vector3[] array2 = RitualTorchOffsets();
		int num = Mathf.Min(list.Count, array2.Length);
		for (int num2 = 0; num2 < num; num2++)
		{
			Vector3 grounded2 = anchor + rotation * array2[num2];
			if (TryTerrainGround(grounded2, out grounded2))
			{
				MovePersistentObject(list[num2], grounded2, rotation);
			}
		}
	}

	private static void MovePersistentObject(ZNetView view, Vector3 position, Quaternion rotation)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)view == (Object)null || !view.IsValid())
		{
			return;
		}
		Vector3 val = ((Component)view).transform.position - position;
		if (!(((Vector3)(ref val)).sqrMagnitude < 0.04f) || !(Quaternion.Angle(((Component)view).transform.rotation, rotation) < 2f))
		{
			if (!view.IsOwner())
			{
				view.ClaimOwnership();
			}
			((Component)view).transform.SetPositionAndRotation(position, rotation);
			ZDO zDO = view.GetZDO();
			if (zDO != null)
			{
				zDO.SetPosition(position);
				zDO.SetRotation(rotation);
			}
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)("The Village moved persistent ritual object '" + ((Object)((Component)view).gameObject).name + "' to ground-level objective at " + Format(position) + "."));
			}
		}
	}

	internal static void ApplyCursedWardAppearance(GameObject ward)
	{
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: 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_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: 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_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)ward == (Object)null)
		{
			return;
		}
		ZNetView component = ward.GetComponent<ZNetView>();
		ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		bool num = val != null && !string.IsNullOrEmpty(val.GetString("Bifrost.DraugrVillageWard", string.Empty));
		bool flag = val != null && !string.IsNullOrEmpty(val.GetString(1888340365, string.Empty));
		if (!num && !flag)
		{
			return;
		}
		Color val2 = default(Color);
		((Color)(ref val2))..ctor(0.085f, 0.035f, 0.025f, 1f);
		Color val3 = default(Color);
		((Color)(ref val3))..ctor(0.03f, 0.18f, 0.045f, 1f);
		Renderer[] componentsInChildren = ward.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val4 in componentsInChildren)
		{
			if ((Object)(object)val4 == (Object)null)
			{
				continue;
			}
			Material[] materials = val4.materials;
			foreach (Material val5 in materials)
			{
				if (!((Object)(object)val5 == (Object)null))
				{
					if (val5.HasProperty("_Color"))
					{
						Color color = val5.color;
						Color color2 = Color.Lerp(color, val2, 0.78f);
						color2.a = color.a;
						val5.color = color2;
					}
					if (val5.HasProperty("_BaseColor"))
					{
						Color color3 = val5.GetColor("_BaseColor");
						Color val6 = Color.Lerp(color3, val2, 0.78f);
						val6.a = color3.a;
						val5.SetColor("_BaseColor", val6);
					}
					string text = (((Object)val4).name + " " + ((Object)val5).name).ToLowerInvariant();
					bool flag2 = text.Contains("rune") || text.Contains("glow") || text.Contains("active");
					if (val5.HasProperty("_EmissionColor"))
					{
						val5.SetColor("_EmissionColor", flag2 ? val3 : Color.black);
					}
				}
			}
		}
	}

	private static bool EnsureDemister(Vector3 position, string token)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		if (_world.GetGlobalKey(DemisterCreatedKey(token)))
		{
			return true;
		}
		GameObject prefab = ZNetScene.instance.GetPrefab("dverger_demister_large");
		if ((Object)(object)prefab == (Object)null)
		{
			return false;
		}
		GameObject val = Object.Instantiate<GameObject>(prefab, position + Vector3.down * 0.15f, Quaternion.identity);
		ZNetView component = val.GetComponent<ZNetView>();
		ZDO val2 = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		if (val2 == null)
		{
			Object.Destroy((Object)(object)val);
			return false;
		}
		val2.Set("Bifrost.DraugrVillageDemister", token);
		ConfigureDemister(val);
		_world.SetGlobalKey(DemisterCreatedKey(token));
		return true;
	}

	private static void ConfigureDemister(GameObject demister)
	{
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: 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_0170: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)demister == (Object)null)
		{
			return;
		}
		ZNetView component = demister.GetComponent<ZNetView>();
		ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		string text = ((val != null) ? val.GetString("Bifrost.DraugrVillageDemister", string.Empty) : string.Empty);
		if (string.IsNullOrEmpty(text))
		{
			return;
		}
		if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey(WardDestroyedKey(text)))
		{
			if (component.IsOwner())
			{
				ZNetScene.instance.Destroy(demister);
			}
			return;
		}
		WearNTear component2 = demister.GetComponent<WearNTear>();
		if ((Object)(object)component2 != (Object)null)
		{
			component2.m_triggerPrivateArea = false;
		}
		MeshRenderer[] componentsInChildren = demister.GetComponentsInChildren<MeshRenderer>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			((Renderer)componentsInChildren[i]).enabled = false;
		}
		Collider[] componentsInChildren2 = demister.GetComponentsInChildren<Collider>(true);
		for (int i = 0; i < componentsInChildren2.Length; i++)
		{
			componentsInChildren2[i].enabled = false;
		}
		ParticleSystemForceField[] componentsInChildren3 = demister.GetComponentsInChildren<ParticleSystemForceField>(true);
		foreach (ParticleSystemForceField obj in componentsInChildren3)
		{
			Transform parent = ((Component)obj).transform.parent;
			Vector3 val2 = (((Object)(object)parent != (Object)null) ? parent.lossyScale : Vector3.one);
			((Component)obj).transform.localScale = new Vector3(1f / Mathf.Max(0.01f, val2.x), 1f / Mathf.Max(0.01f, val2.y), 1f / Mathf.Max(0.01f, val2.z));
			obj.endRange = 35f;
		}
	}

	private static bool EnsureMistAnchor(Vector3 position, string token)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		if (_world.GetGlobalKey(MistCreatedKey(token)))
		{
			return true;
		}
		if (!DraugrVillageMistVisual.HasVerifiedSource())
		{
			return false;
		}
		GameObject prefab = ZNetScene.instance.GetPrefab("dverger_demister_large");
		if ((Object)(object)prefab == (Object)null)
		{
			return false;
		}
		GameObject val = Object.Instantiate<GameObject>(prefab, position, Quaternion.identity);
		ZNetView component = val.GetComponent<ZNetView>();
		ZDO val2 = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		if (val2 == null)
		{
			Object.Destroy((Object)(object)val);
			return false;
		}
		val2.Set("Bifrost.DraugrVillageMistAnchor", token);
		ConfigureMistAnchor(val);
		_world.SetGlobalKey(MistCreatedKey(token));
		ManualLogSource log = _log;
		if (log != null)
		{
			log.LogInfo((object)("Draugr village " + token + " created a Bifrost-owned 68m temporary mist volume from " + DraugrVillageMistVisual.VerifiedSourceName + "."));
		}
		return true;
	}

	private static void ConfigureMistAnchor(GameObject anchor)
	{
		if ((Object)(object)anchor == (Object)null)
		{
			return;
		}
		ZNetView component = anchor.GetComponent<ZNetView>();
		ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		string text = ((val != null) ? val.GetString("Bifrost.DraugrVillageMistAnchor", string.Empty) : string.Empty);
		if (!string.IsNullOrEmpty(text))
		{
			Demister[] componentsInChildren = anchor.GetComponentsInChildren<Demister>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Behaviour)componentsInChildren[i]).enabled = false;
			}
			ParticleSystemForceField[] componentsInChildren2 = anchor.GetComponentsInChildren<ParticleSystemForceField>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				((Component)componentsInChildren2[i]).gameObject.SetActive(false);
			}
			MeshRenderer[] componentsInChildren3 = anchor.GetComponentsInChildren<MeshRenderer>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				((Renderer)componentsInChildren3[i]).enabled = false;
			}
			Collider[] componentsInChildren4 = anchor.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				componentsInChildren4[i].enabled = false;
			}
			WearNTear component2 = anchor.GetComponent<WearNTear>();
			if ((Object)(object)component2 != (Object)null)
			{
				((Behaviour)component2).enabled = false;
			}
			DraugrVillageMistVisual draugrVillageMistVisual = anchor.GetComponent<DraugrVillageMistVisual>();
			if ((Object)(object)draugrVillageMistVisual == (Object)null)
			{
				draugrVillageMistVisual = anchor.AddComponent<DraugrVillageMistVisual>();
			}
			draugrVillageMistVisual.Configure(text);
		}
	}

	private static bool EnsureAbomination(Vector3 anchor, Vector3 villageCenter, Vector3 fallbackDirection, string token)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		if (_world.GetGlobalKey(AbominationCreatedKey(token)))
		{
			return true;
		}
		GameObject prefab = ZNetScene.instance.GetPrefab("Abomination");
		if ((Object)(object)prefab == (Object)null)
		{
			return false;
		}
		Vector3 val = villageCenter;
		float num = default(float);
		if (!_world.GetGroundHeight(val, ref num))
		{
			return false;
		}
		val.y = num + 0.2f;
		Vector3 val2 = anchor - val;
		val2.y = 0f;
		if (((Vector3)(ref val2)).sqrMagnitude < 0.1f)
		{
			val2 = fallbackDirection;
			val2.y = 0f;
		}
		((Vector3)(ref val2)).Normalize();
		GameObject val3 = Object.Instantiate<GameObject>(prefab, val, Quaternion.LookRotation(val2, Vector3.up));
		ZNetView component = val3.GetComponent<ZNetView>();
		ZDO val4 = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		Character component2 = val3.GetComponent<Character>();
		if (val4 == null || (Object)(object)component2 == (Object)null)
		{
			Object.Destroy((Object)(object)val3);
			return false;
		}
		val4.Set("Bifrost.DraugrVillageAbomination", token);
		val4.Set(-841210880, true);
		component2.SetLevel(1);
		_world.SetGlobalKey(AbominationCreatedKey(token));
		_world.SetGlobalKey(AbominationCenteredKey(token));
		return true;
	}

	private static void OpenVillageDoorsOnce(string token, Vector3 villageCenter, Vector3 ritualCenter)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		if (_world.GetGlobalKey(DoorsOpenedKey(token)) || !HasPlayerNear(ritualCenter, 34f))
		{
			return;
		}
		MethodInfo methodInfo = AccessTools.Method(typeof(Door), "SetState", new Type[1] { typeof(int) }, (Type[])null);
		if (methodInfo == null)
		{
			return;
		}
		Door[] array = Object.FindObjectsByType<Door>((FindObjectsInactive)1, (FindObjectsSortMode)0);
		int num = 0;
		int num2 = 0;
		float num3 = 6400f;
		foreach (Door val in array)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			Vector3 val2 = ((Component)val).transform.position - villageCenter;
			if (((Vector3)(ref val2)).sqrMagnitude > num3)
			{
				continue;
			}
			ZNetView component = ((Component)val).GetComponent<ZNetView>();
			ZDO val3 = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
			if (val3 == null)
			{
				continue;
			}
			num++;
			if (val3.GetInt(ZDOVars.s_state, 0) == 0)
			{
				if (!component.IsOwner())
				{
					component.ClaimOwnership();
				}
				methodInfo.Invoke(val, new object[1] { 1 });
				num2++;
			}
		}
		if (num != 0)
		{
			_world.SetGlobalKey(DoorsOpenedKey(token));
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)("The Village trap " + token + " opened " + num2 + " of " + num + " loaded door(s) in one networked activation."));
			}
		}
	}

	private static void EnsureRitualAltar(Vector3 anchor, Quaternion rotation, string token)
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: 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_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		if (_world.GetGlobalKey(AltarCreatedKey(token)))
		{
			return;
		}
		GameObject prefab = ZNetScene.instance.GetPrefab("altar");
		if ((Object)(object)prefab == (Object)null)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)"Optional ritual prefab altar is not a runtime network prefab; The Village altar was deferred.");
			}
			_world.SetGlobalKey(AltarCreatedKey(token));
			return;
		}
		Vector3 grounded = anchor + rotation * new Vector3(0f, 0f, -2.2f);
		if (!TryGround(grounded, anchor.y + 8f, out grounded))
		{
			ManualLogSource log2 = _log;
			if (log2 != null)
			{
				log2.LogWarning((object)("The Village " + token + " could not ground its optional ritual altar."));
			}
			_world.SetGlobalKey(AltarCreatedKey(token));
			return;
		}
		GameObject val = Object.Instantiate<GameObject>(prefab, grounded, rotation);
		ZNetView component = val.GetComponent<ZNetView>();
		ZDO val2 = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		if (val2 == null)
		{
			Object.Destroy((Object)(object)val);
			ManualLogSource log3 = _log;
			if (log3 != null)
			{
				log3.LogInfo((object)"Optional ritual prefab altar lacks a persistent ZNetView; The Village altar was deferred.");
			}
			_world.SetGlobalKey(AltarCreatedKey(token));
			return;
		}
		val2.Set("Bifrost.DraugrVillageDecoration", token);
		_world.SetGlobalKey(AltarCreatedKey(token));
		ManualLogSource log4 = _log;
		if (log4 != null)
		{
			log4.LogInfo((object)("The Village " + token + " placed optional ritual altar 'altar' at " + Format(grounded) + "."));
		}
	}

	private static void EnsureGreenTorches(Vector3 anchor, Quaternion rotation, string token)
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: 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)
		if (_world.GetGlobalKey(DecorationsCreatedKey(token)))
		{
			return;
		}
		GameObject prefab = ZNetScene.instance.GetPrefab("CastleKit_groundtorch_green");
		if ((Object)(object)prefab == (Object)null)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)"Optional ritual prefab CastleKit_groundtorch_green is not a runtime network prefab; green torches were deferred.");
			}
			_world.SetGlobalKey(DecorationsCreatedKey(token));
			return;
		}
		Vector3[] array = RitualTorchOffsets();
		int num = 0;
		for (int i = 0; i < array.Length; i++)
		{
			Vector3 grounded = anchor + rotation * array[i];
			if (TryTerrainGround(grounded, out grounded))
			{
				GameObject val = Object.Instantiate<GameObject>(prefab, grounded, rotation);
				ZNetView component = val.GetComponent<ZNetView>();
				ZDO val2 = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
				if (val2 != null)
				{
					val2.Set("Bifrost.DraugrVillageDecoration", token);
					num++;
				}
				else
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}
		_world.SetGlobalKey(DecorationsCreatedKey(token));
		ManualLogSource log2 = _log;
		if (log2 != null)
		{
			log2.LogInfo((object)("Draugr village " + token + " placed " + num + " optional green ritual torch(es)."));
		}
	}

	private static Vector3[] RitualTorchOffsets()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: 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_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		return (Vector3[])(object)new Vector3[4]
		{
			new Vector3(3f, 0f, 3f),
			new Vector3(-3f, 0f, 3f),
			new Vector3(3f, 0f, -3f),
			new Vector3(-3f, 0f, -3f)
		};
	}

	internal static bool IgnoreUndeadSpawnerDamage(Destructible destructible, HitData hit)
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Invalid comparison between Unknown and I4
		if ((Object)(object)destructible == (Object)null || hit == null)
		{
			return false;
		}
		ZNetView component = ((Component)destructible).GetComponent<ZNetView>();
		ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		if (val == null || string.IsNullOrEmpty(val.GetString("Bifrost.DraugrVillageProtectedSpawner", string.Empty)))
		{
			return false;
		}
		Character attacker = hit.GetAttacker();
		if ((Object)(object)attacker != (Object)null)
		{
			return (int)attacker.GetFaction() == 3;
		}
		return false;
	}

	internal static bool IgnoreUndeadWardDamage(WearNTear wear, HitData hit)
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Invalid comparison between Unknown and I4
		if ((Object)(object)wear == (Object)null || hit == null)
		{
			return false;
		}
		ZNetView component = ((Component)wear).GetComponent<ZNetView>();
		ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		if (val == null || string.IsNullOrEmpty(val.GetString("Bifrost.DraugrVillageWard", string.Empty)))
		{
			return false;
		}
		Character attacker = hit.GetAttacker();
		if ((Object)(object)attacker != (Object)null)
		{
			return (int)attacker.GetFaction() == 3;
		}
		return false;
	}

	internal static void ConfigureLoadedObject(GameObject gameObject)
	{
		if ((Object)(object)gameObject == (Object)null)
		{
			return;
		}
		ZNetView component = gameObject.GetComponent<ZNetView>();
		ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		if (val != null)
		{
			if (!string.IsNullOrEmpty(val.GetString("Bifrost.DraugrVillageWard", string.Empty)))
			{
				ConfigureWard(gameObject.GetComponent<PrivateArea>());
			}
			if (!string.IsNullOrEmpty(val.GetString("Bifrost.DraugrVillageDemister", string.Empty)))
			{
				ConfigureDemister(gameObject);
			}
			if (!string.IsNullOrEmpty(val.GetString("Bifrost.DraugrVillageMistAnchor", string.Empty)))
			{
				ConfigureMistAnchor(gameObject);
			}
			string text = FirstMarker(val, "Bifrost.DraugrVillageWard", "Bifrost.DraugrVillageDemister", "Bifrost.DraugrVillageAbomination", "Bifrost.DraugrVillageDecoration", "Bifrost.DraugrVillageProtectedSpawner");
			if (!string.IsNullOrEmpty(text) && (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey(CompletedKey(text)))
			{
				CleanupLoadedObject(gameObject, val, text, keepMist: false);
			}
		}
	}

	internal static void OnCharacterDeath(Character character)
	{
		if (!ServerReady() || (Object)(object)character == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)character).GetComponent<ZNetView>();
		ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		string text = ((val != null) ? val.GetString("Bifrost.DraugrVillageAbomination", string.Empty) : string.Empty);
		if (!string.IsNullOrEmpty(text))
		{
			_world.SetGlobalKey(AbominationDeadKey(text));
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)("Draugr village ritual Abomination " + text + " was killed."));
			}
			TryComplete(text);
		}
	}

	internal static void OnWearNTearDestroyed(WearNTear wear)
	{
		if (!ServerReady() || (Object)(object)wear == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)wear).GetComponent<ZNetView>();
		ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		string text = ((val != null) ? val.GetString("Bifrost.DraugrVillageWard", string.Empty) : string.Empty);
		if (string.IsNullOrEmpty(text))
		{
			return;
		}
		ZoneSystem.instance.SetGlobalKey(WardDestroyedKey(text));
		SetMistCleanupDeadline(text, 600.0, onlyShorten: false);
		Demister[] array = Object.FindObjectsByType<Demister>((FindObjectsInactive)1, (FindObjectsSortMode)0);
		for (int i = 0; i < array.Length; i++)
		{
			ZNetView componentInParent = ((Component)array[i]).GetComponentInParent<ZNetView>();
			ZDO val2 = (((Object)(object)componentInParent != (Object)null && componentInParent.IsValid()) ? componentInParent.GetZDO() : null);
			if (val2 != null && string.Equals(val2.GetString("Bifrost.DraugrVillageDemister", string.Empty), text, StringComparison.Ordinal))
			{
				if (!componentInParent.IsOwner())
				{
					componentInParent.ClaimOwnership();
				}
				ZNetScene.instance.Destroy(((Component)componentInParent).gameObject);
			}
		}
		ManualLogSource log = _log;
		if (log != null)
		{
			log.LogInfo((object)("Draugr village ritual Ward " + text + " was destroyed; its 35m demister was removed and the mist will close in for at most 10 minutes."));
		}
		TryComplete(text);
	}

	private static void RecoverLegacyAbominationDeath(string token)
	{
		if (!_world.GetGlobalKey(AbominationCreatedKey(token)) || _world.GetGlobalKey(AbominationDeadKey(token)))
		{
			return;
		}
		Character[] array = Object.FindObjectsByType<Character>((FindObjectsInactive)1, (FindObjectsSortMode)0);
		for (int i = 0; i < array.Length; i++)
		{
			ZNetView component = ((Component)array[i]).GetComponent<ZNetView>();
			ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
			if (val != null && string.Equals(val.GetString("Bifrost.DraugrVillageAbomination", string.Empty), token, StringComparison.Ordinal))
			{
				return;
			}
		}
		_world.SetGlobalKey(AbominationDeadKey(token));
		ManualLogSource log = _log;
		if (log != null)
		{
			log.LogInfo((object)("Recovered completed ritual Abomination state for existing Draugr village " + token + "."));
		}
	}

	private static void TryComplete(string token)
	{
		if (!((Object)(object)_world == (Object)null) && !_world.GetGlobalKey(CompletedKey(token)) && _world.GetGlobalKey(WardDestroyedKey(token)) && _world.GetGlobalKey(AbominationDeadKey(token)))
		{
			_world.SetGlobalKey(CompletedKey(token));
			SetMistCleanupDeadline(token, 90.0, onlyShorten: true);
			CleanupLoadedEncounter(token, keepMist: true);
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)("Draugr village ritual " + token + " completed permanently: Ward and ritual Abomination are dead. Decorations were retired and the closing mist will clear in 90 seconds."));
			}
		}
	}

	private static void SetMistCleanupDeadline(string token, double seconds, bool onlyShorten)
	{
		if (!((Object)(object)ZNet.instance == (Object)null) && !((Object)(object)ZoneSystem.instance == (Object)null))
		{
			double num = ZNet.instance.GetTimeSeconds() + seconds;
			string s = default(string);
			if (!onlyShorten || !ZoneSystem.instance.GetGlobalKey(MistCleanupKey(token), ref s) || !double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !(result <= num))
			{
				ZoneSystem.instance.SetGlobalKey(MistCleanupKey(token) + " " + Math.Ceiling(num).ToString(CultureInfo.InvariantCulture));
			}
		}
	}

	internal static bool MistExpired(string token)
	{
		if ((Object)(object)ZoneSystem.instance == (Object)null || (Object)(object)ZNet.instance == (Object)null)
		{
			return false;
		}
		string s = default(string);
		if (ZoneSystem.instance.GetGlobalKey(MistCleanupKey(token), ref s) && double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
		{
			return ZNet.instance.GetTimeSeconds() >= result;
		}
		return false;
	}

	private static void CleanupLoadedEncounter(string token, bool keepMist)
	{
		ZNetView[] array = Object.FindObjectsByType<ZNetView>((FindObjectsInactive)1, (FindObjectsSortMode)0);
		foreach (ZNetView val in array)
		{
			ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null);
			if (val2 != null)
			{
				CleanupLoadedObject(((Component)val).gameObject, val2, token, keepMist);
			}
		}
	}

	private static void CleanupLoadedObject(GameObject gameObject, ZDO zdo, string token, bool keepMist)
	{
		if (string.Equals(zdo.GetString("Bifrost.DraugrVillageProtectedSpawner", string.Empty), token, StringComparison.Ordinal))
		{
			zdo.Set("Bifrost.DraugrVillageProtectedSpawner", string.Empty);
		}
		bool flag = string.Equals(zdo.GetString("Bifrost.DraugrVillageMistAnchor", string.Empty), token, StringComparison.Ordinal);
		if ((!string.Equals(zdo.GetString("Bifrost.DraugrVillageDemister", string.Empty), token, StringComparison.Ordinal) && !string.Equals(zdo.GetString("Bifrost.DraugrVillageDecoration", string.Empty), token, StringComparison.Ordinal) && (!flag || keepMist || !MistExpired(token))) || (Object)(object)ZNetScene.instance == (Object)null)
		{
			return;
		}
		ZNetView component = gameObject.GetComponent<ZNetView>();
		if (!((Object)(object)component == (Object)null) && component.IsValid())
		{
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			ZNetScene.instance.Destroy(gameObject);
		}
	}

	private static string FirstMarker(ZDO zdo, params string[] keys)
	{
		for (int i = 0; i < keys.Length; i++)
		{
			string text = zdo.GetString(keys[i], string.Empty);
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
		}
		return string.Empty;
	}

	private static string Token(Vector3 position)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//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)
		Vector2s zone = ZoneSystem.GetZone(position);
		return zone.x + ":" + zone.y;
	}

	private static string StateKey(string prefix, string token)
	{
		return prefix + token.Replace(':', '_');
	}

	private static string AugmentedKey(string token)
	{
		return StateKey("bifrost_draugr_village_augmented_", token);
	}

	private static string WardCreatedKey(string token)
	{
		return StateKey("bifrost_draugr_village_ward_created_", token);
	}

	private static string WardDestroyedKey(string token)
	{
		return StateKey("bifrost_draugr_village_ward_destroyed_", token);
	}

	private static string DemisterCreatedKey(string token)
	{
		return StateKey("bifrost_draugr_village_demister_created_", token);
	}

	private static string AbominationCreatedKey(string token)
	{
		return StateKey("bifrost_draugr_village_abomination_created_", token);
	}

	private static string AbominationCenteredKey(string token)
	{
		return StateKey("bifrost_draugr_village_abomination_centered_", token);
	}

	private static string AltarCreatedKey(string token)
	{
		return StateKey("bifrost_draugr_village_altar_created_", token);
	}

	private static string DecorationsCreatedKey(string token)
	{
		return StateKey("bifrost_draugr_village_decorations_created_", token);
	}

	private static string DoorsOpenedKey(string token)
	{
		return StateKey("bifrost_draugr_village_doors_opened_", token);
	}

	private static string MistCreatedKey(string token)
	{
		return StateKey("bifrost_draugr_village_mist_created_", token);
	}

	private static string MistCleanupKey(string token)
	{
		return StateKey("bifrost_draugr_village_mist_cleanup_", token);
	}

	private static string AbominationDeadKey(string token)
	{
		return StateKey("bifrost_draugr_village_abomination_dead_", token);
	}

	private static string CompletedKey(string token)
	{
		return StateKey("bifrost_draugr_village_completed_", token);
	}

	private static string Format(Vector3 value)
	{
		return value.x.ToString("0.0") + "," + value.y.ToString("0.0") + "," + value.z.ToString("0.0");
	}

	internal static GameObject FindVerifiedMistSource()
	{
		if ((Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null)
		{
			return null;
		}
		for (int i = 0; i < MistPrefabCandidates.Length; i++)
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(MistPrefabCandidates[i]);
			if (IsVerifiedMistSource(prefab))
			{
				return prefab;
			}
		}
		for (int j = 0; j < MistPrefabCandidates.Length; j++)
		{
			for (int k = 0; k < ZoneSystem.instance.m_vegetation.Count; k++)
			{
				GameObject prefab2 = ZoneSystem.instance.m_vegetation[k].m_prefab;
				if ((Object)(object)prefab2 != (Object)null && string.Equals(((Object)prefab2).name, MistPrefabCandidates[j], StringComparison.Ordinal) && IsVerifiedMistSource(prefab2))
				{
					return prefab2;
				}
			}
		}
		return null;
	}

	private static bool IsVerifiedMistSource(GameObject source)
	{
		if ((Object)(object)source == (Object)null || (Object)(object)source.GetComponentInChildren<Mister>(true) == (Object)null || (Object)(object)source.GetComponentInChildren<MistEmitter>(true) == (Object)null || (Object)(object)source.GetComponentInChildren<ZNetView>(true) != (Object)null)
		{
			return false;
		}
		MistEmitter[] componentsInChildren = source.GetComponentsInChildren<MistEmitter>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i].m_psystem != (Object)null)
			{
				return true;
			}
		}
		return false;
	}
}
internal sealed class DraugrVillageMistVisual : MonoBehaviour
{
	private static GameObject _verifiedSource;

	private static bool _sourceChecked;

	private static bool _missingLogged;

	private string _token;

	private GameObject _visual;

	private float _nextCheck;

	internal static string VerifiedSourceName
	{
		get
		{
			if (!((Object)(object)_verifiedSource != (Object)null))
			{
				return "none";
			}
			return ((Object)_verifiedSource).name;
		}
	}

	internal static bool HasVerifiedSource()
	{
		if (!_sourceChecked || (Object)(object)_verifiedSource == (Object)null)
		{
			_sourceChecked = true;
			_verifiedSource = DraugrVillageRitualSystem.FindVerifiedMistSource();
		}
		if ((Object)(object)_verifiedSource == (Object)null && !_missingLogged)
		{
			_missingLogged = true;
			Debug.LogWarning((object)"Bifrost Breakout: none of MistArea, MistArea_small, or MistArea_edge was a safe runtime prefab with Mister, configured MistEmitter particles, and no ZNetView. The Village will continue without optional mist dressing.");
		}
		return (Object)(object)_verifiedSource != (Object)null;
	}

	internal void Configure(string token)
	{
		_token = token;
		EnsureVisual();
	}

	private void Update()
	{
		if (Time.time < _nextCheck)
		{
			return;
		}
		_nextCheck = Time.time + 2f;
		if (string.IsNullOrEmpty(_token))
		{
			return;
		}
		if (DraugrVillageRitualSystem.MistExpired(_token))
		{
			if ((Object)(object)_visual != (Object)null)
			{
				Object.Destroy((Object)(object)_visual);
			}
			_visual = null;
			ZNetView component = ((Component)this).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid() && component.IsOwner() && (Object)(object)ZNetScene.instance != (Object)null)
			{
				ZNetScene.instance.Destroy(((Component)this).gameObject);
			}
		}
		else
		{
			EnsureVisual();
		}
	}

	private void EnsureVisual()
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)_visual != (Object)null) && HasVerifiedSource())
		{
			_visual = Object.Instantiate<GameObject>(_verifiedSource, ((Component)this).transform.position, Quaternion.identity, ((Component)this).transform);
			((Object)_visual).name = "Bifrost_DraugrVillageTemporaryMist";
			Mister[] componentsInChildren = _visual.GetComponentsInChildren<Mister>(true);
			foreach (Mister obj in componentsInChildren)
			{
				obj.m_radius = 68f;
				obj.m_height = 32f;
			}
			MistEmitter[] componentsInChildren2 = _visual.GetComponentsInChildren<MistEmitter>(true);
			foreach (MistEmitter obj2 in componentsInChildren2)
			{
				obj2.m_totalRadius = 68f;
				obj2.SetEmit(true);
			}
			Debug.Log((object)("Bifrost Breakout: Draugr village " + _token + " activated local temporary mist from verified vanilla prefab " + VerifiedSourceName + " (68m radius, 32m height)."));
		}
	}
}
internal sealed class DraugrVillageContainment : MonoBehaviour
{
	private const float ArmMargin = 1f;

	private const float BoundaryInset = 0.75f;

	private const float TeleportEscapeMargin = 5f;

	private string _token;

	private float _radius;

	private bool _armed;

	internal void Configure(string token, float radius)
	{
		_token = token;
		_radius = radius;
	}

	private void FixedUpdate()
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: 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_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: 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_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(_token) || _radius <= 0f)
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
		{
			_armed = false;
			return;
		}
		Vector3 position = ((Component)localPlayer).transform.position;
		Vector3 val = position - ((Component)this).transform.position;
		val.y = 0f;
		float magnitude = ((Vector3)(ref val)).magnitude;
		if (!_armed)
		{
			if (magnitude <= _radius - 1f)
			{
				_armed = true;
			}
		}
		else
		{
			if (magnitude <= _radius)
			{
				return;
			}
			if (magnitude > _radius + 5f)
			{
				_armed = false;
				return;
			}
			Vector3 val2 = ((((Vector3)(ref val)).sqrMagnitude > 0.001f) ? ((Vector3)(ref val)).normalized : Vector3.forward);
			Vector3 position2 = ((Component)this).transform.position + val2 * (_radius - 0.75f);
			position2.y = position.y;
			((Component)localPlayer).transform.position = position2;
			Vector3 velocity = ((Character)localPlayer).GetVelocity();
			float num = Vector3.Dot(velocity, val2);
			if (num > 0f)
			{
				((Character)localPlayer).SetVelocity(velocity - val2 * num);
			}
		}
	}
}
[HarmonyPatch(typeof(ZNetScene), "CreateObject")]
internal static class DraugrVillageRitualCreateObjectPatch
{
	[HarmonyPostfix]
	private static void Postfix(GameObject __result)
	{
		DraugrVillageRitualSystem.ConfigureLoadedObject(__result);
	}
}
[HarmonyPatch(typeof(Destructible), "RPC_Damage")]
internal static class DraugrVillageSpawnerFriendlyFirePatch
{
	[HarmonyPrefix]
	private static bool Prefix(Destructible __instance, HitData hit)
	{
		return !DraugrVillageRitualSystem.IgnoreUndeadSpawnerDamage(__instance, hit);
	}
}
[HarmonyPatch(typeof(WearNTear), "Destroy")]
internal static class DraugrVillageWardDestroyedPatch
{
	[HarmonyPrefix]
	private static void Prefix(WearNTear __instance)
	{
		DraugrVillageRitualSystem.OnWearNTearDestroyed(__instance);
	}
}
[HarmonyPatch(typeof(WearNTear), "RPC_Damage")]
internal static class DraugrVillageWardFriendlyFirePatch
{
	[HarmonyPrefix]
	private static bool Prefix(WearNTear __instance, HitData hit)
	{
		return !DraugrVillageRitualSystem.IgnoreUndeadWardDamage(__instance, hit);
	}
}
internal static class FortressSortieSystem
{
	private sealed class FortressState
	{
		internal readonly string Token;

		internal Vector3 Center;

		internal FortressState(string token, Vector3 center)
		{
			//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)
			Token = token;
			Center = center;
		}
	}

	internal const string FortressPrefabName = "CharredFortress";

	internal const string CommanderPrefabName = "Charred_Mage";

	internal const string ExteriorGatePrefabName = "Ashlands_Fortress_Gate_Door";

	internal const string WardPrefabName = "dverger_guardstone";

	internal const int CommanderMarkerKey = 694315693;

	internal const int WardMarkerKey = 1888340365;

	internal const int GateFortressMarkerKey = 470325472;

	internal const int GateOpenMarkerKey = 2050492924;

	internal const int GateCloseTimeKey = -55907439;

	internal const int GatePhaseKey = 778750144;

	internal const int WardLayoutVersionKey = -1203120781;

	internal const int SortieThreshold = 8;

	internal const float PlayerActivationRange = 100f;

	internal const float GateOpenSeconds = 30f;

	internal const float FortressWardRadius = 65f;

	private const float UpdateIntervalSeconds = 5f;

	private const float CentralCommanderRadius = 6f;

	private const float CentralCommanderMinimumHeight = 8f;

	private const float ExteriorGateRadiusMin = 14f;

	private const float ExteriorGateRadiusMax = 24f;

	private const float CourtyardWardOffset = 8f;

	private const float WardGroundRayStart = 20f;

	private const float WardGroundRayDistance = 50f;

	private const int CurrentWardLayoutVersion = 1;

	private const float InteriorHalfExtent = 18.5f;

	private const int InitialSortiePhase = 0;

	private const int WaitingForPopulationDropPhase = 1;

	private const int WaitingForRefillPhase = 2;

	private static readonly HashSet<string> DefenderPrefabs = new HashSet<string>(StringComparer.Ordinal) { "Charred_Archer", "Charred_Mage", "Charred_Melee", "Charred_Melee_Dyrnwyn", "Charred_Twitcher" };

	private static readonly MethodInfo WakeupMethod = AccessTools.Method(typeof(MonsterAI), "Wakeup", (Type[])null, (Type[])null);

	private static readonly MethodInfo SetTargetMethod = AccessTools.Method(typeof(MonsterAI), "SetTarget", new Type[1] { typeof(Character) }, (Type[])null);

	private static readonly MethodInfo SetAlertedMethod = AccessTools.Method(typeof(MonsterAI), "SetAlerted", new Type[1] { typeof(bool) }, (Type[])null);

	private static readonly FieldInfo TargetCreatureField = AccessTools.Field(typeof(MonsterAI), "m_targetCreature");

	private static readonly Dictionary<string, FortressState> Fortresses = new Dictionary<string, FortressState>(StringComparer.Ordinal);

	private static readonly List<FortressGateRuntime> Gates = new List<FortressGateRuntime>();

	private static readonly List<FortressWardRuntime> Wards = new List<FortressWardRuntime>();

	private static readonly List<Character> Defenders = new List<Character>();

	private static readonly List<FortressGateRuntime> ExteriorGates = new List<FortressGateRuntime>();

	private static readonly RaycastHit[] WardGroundHits = (RaycastHit[])(object)new RaycastHit[32];

	private static MonoBehaviour _host;

	private static ManualLogSource _log;

	private static Coroutine _loop;

	private static ZoneSystem _world;

	internal static void Initialize(MonoBehaviour host, ManualLogSource log)
	{
		_host = host;
		_log = log;
		_loop = host.StartCoroutine(Run());
	}

	internal static void Shutdown()
	{
		if ((Object)(object)_host != (Object)null && _loop != null)
		{
			_host.StopCoroutine(_loop);
		}
		_loop = null;
		_host = null;
		_world = null;
		_log = null;
		Fortresses.Clear();
		Gates.Clear();
		Wards.Clear();
		Defenders.Clear();
		ExteriorGates.Clear();
	}

	private static IEnumerator Run()
	{
		while (true)
		{
			yield return (object)new WaitForSeconds(5f);
			if (!ServerReady())
			{
				continue;
			}
			try
			{
				if ((Object)(object)_world != (Object)(object)ZoneSystem.instance)
				{
					_world = ZoneSystem.instance;
					Fortresses.Clear();
				}
				RefreshFortresses();
				foreach (FortressState value in Fortresses.Values)
				{
					Player val = FindNearbyPlayer(value.Center);
					if ((Object)(object)val != (Object)null)
					{
						UpdateFortress(value, val);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogError((object)("Fortress sortie update failed safely: " + ex));
				}
			}
		}
	}

	private static bool ServerReady()
	{
		if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && (Object)(object)ZoneSystem.instance != (Object)null)
		{
			return (Object)(object)ZNetScene.instance != (Object)null;
		}
		return false;
	}

	private static void RefreshFortresses()
	{
		//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_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		foreach (LocationInstance location in _world.GetLocationList())
		{
			if (location.m_placed && location.m_location != null && string.Equals(location.m_location.m_prefabName, "CharredFortress", StringComparison.Ordinal))
			{
				string text = FortressToken(location.m_position);
				if (Fortresses.TryGetValue(text, out var value))
				{
					value.Center = location.m_position;
				}
				else
				{
					Fortresses.Add(text, new FortressState(text, location.m_position));
				}
			}
		}
	}

	private static Player FindNearbyPlayer(Vector3 center)
	{
		//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)
		Player result = null;
		float num = 100f;
		foreach (Player allPlayer in Player.GetAllPlayers())
		{
			if (!((Object)(object)allPlayer == (Object)null) && !((Character)allPlayer).IsDead() && !((Character)allPlayer).InInterior() && !((Character)allPlayer).IsTeleporting())
			{
				float num2 = DistanceXZ(((Component)allPlayer).transform.position, center);
				if (num2 <= num)
				{
					result = allPlayer;
					num = num2;
				}
			}
		}
		return result;
	}

	private static void UpdateFortress(FortressState fortress, Player player)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		FindExteriorGates(fortress.Center, ExteriorGates);
		EnsureWard(fortress, ExteriorGates);
		EnsureCommander(fortress);
		if (ExteriorGates.Count != 2)
		{
			return;
		}
		double timeSeconds = ZNet.instance.GetTimeSeconds();
		CloseExpiredGates(ExteriorGates, timeSeconds);
		string text = CommanderDeadKey(fortress.Token);
		if (!_world.GetGlobalKey(text) && !((Object)(object)FindCommander(fortress.Token) == (Object)null))
		{
			FindInsideDefenders(fortress, ExteriorGates, Defenders);
			int num = ReadSortiePhase(ExteriorGates);
			if (num == 1 && Defenders.Count < 8)
			{
				WriteSortiePhase(ExteriorGates, 2);
				num = 2;
			}
			if (!AnyGateOpen(ExteriorGates) && Defenders.Count >= 8 && num != 1)
			{
				BeginSortie(fortress, ExteriorGates, Defenders, player, timeSeconds);
			}
		}
	}

	private static void EnsureCommander(FortressState fortress)
	{
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		if (_world.GetGlobalKey(CommanderDeadKey(fortress.Token)))
		{
			return;
		}
		Character val = FindCommander(fortress.Token);
		if ((Object)(object)val != (Object)null)
		{
			SetCommanderLevel(val);
		}
		else if (!_world.GetGlobalKey(CommanderAssignedKey(fortress.Token)))
		{
			Character val2 = FindCentralCommanderCandidate(fortress.Center);
			if ((Object)(object)val2 != (Object)null)
			{
				AssignCommander(val2, fortress.Token);
			}
		}
	}

	private static Character FindCentralCommanderCandidate(Vector3 center)
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		Character result = null;
		float num = 6f;
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsDead() && IsPrefab(((Component)allCharacter).gameObject, "Charred_Mage") && !(((Component)allCharacter).transform.position.y < center.y + 8f))
			{
				float num2 = DistanceXZ(((Component)allCharacter).transform.position, center);
				if (num2 <= num)
				{
					result = allCharacter;
					num = num2;
				}
			}
		}
		return result;
	}

	private static Character FindCommander(string token)
	{
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsDead())
			{
				ZNetView component = ((Component)allCharacter).GetComponent<ZNetView>();
				ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
				if (val != null && string.Equals(val.GetString(694315693, string.Empty), token, StringComparison.Ordinal))
				{
					return allCharacter;
				}
			}
		}
		return null;
	}

	private static void AssignCommander(Character character, string token)
	{
		ZNetView component = ((Component)character).GetComponent<ZNetView>();
		if (!((Object)(object)component == (Object)null) && component.IsValid())
		{
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			component.GetZDO().Set(694315693, token);
			SetCommanderLevel(character);
			_world.SetGlobalKey(CommanderAssignedKey(token));
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)("Assigned the central Charred_Mage as the two-star commander of fortress " + token + "."));
			}
		}
	}

	private static void SetCommanderLevel(Character commander)
	{
		if (commander.GetLevel() == 3)
		{
			return;
		}
		ZNetView component = ((Component)commander).GetComponent<ZNetView>();
		if (!((Object)(object)component == (Object)null) && component.IsValid())
		{
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			commander.SetLevel(3);
		}
	}

	internal static void TryInitializeCharacter(Character character)
	{
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: 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)
		if ((Object)(object)character == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null)
		{
			return;
		}
		try
		{
			ZNetView component = ((Component)character).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner())
			{
				return;
			}
			if (!string.IsNullOrEmpty(component.GetZDO().GetString(694315693, string.Empty)))
			{
				SetCommanderLevel(character);
			}
			else
			{
				if (!IsPrefab(((Component)character).gameObject, "Charred_Mage"))
				{
					return;
				}
				{
					foreach (LocationInstance location in ZoneSystem.instance.GetLocationList())
					{
						if (location.m_placed && location.m_location != null && string.Equals(location.m_location.m_prefabName, "CharredFortress", StringComparison.Ordinal) && !(DistanceXZ(((Component)character).transform.position, location.m_position) > 6f) && !(((Component)character).transform.position.y < location.m_position.y + 8f))
						{
							string token = FortressToken(location.m_position);
							if (!ZoneSystem.instance.GetGlobalKey(CommanderDeadKey(token)) && !ZoneSystem.instance.GetGlobalKey(CommanderAssignedKey(token)))
							{
								AssignCommander(character, token);
							}
							break;
						}
					}
					return;
				}
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogError((object)("Fortress commander initialization failed safely: " + ex));
			}
		}
	}

	internal static void OnCharacterDeath(Character character)
	{
		if ((Object)(object)character == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)character).GetComponent<ZNetView>();
		ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null);
		string text = ((val != null) ? val.GetString(694315693, string.Empty) : string.Empty);
		if (!string.IsNullOrEmpty(text))
		{
			ZoneSystem.instance.SetGlobalKey(CommanderDeadKey(text));
			ManualLogSource log = _log;
			if (log != null)
			{
				log.LogInfo((object)("Fortress commander " + text + " was killed; its automatic sorties are permanently disabled."));
			}
		}
	}

	private static void FindExteriorGates(Vector3 center, List<FortressGateRuntime> result)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		result.Clear();
		for (int num = Gates.Count - 1; num >= 0; num--)
		{
			FortressGateRuntime fortressGateRuntime = Gates[num];
			if ((Object)(object)fortressGateRuntime == (Object)null)
			{
				Gates.RemoveAt(num);
			}
			else
			{
				float num2 = DistanceXZ(((Component)fortre