Decompiled source of Beyond v0.32.1

plugins/Beyond.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Beyond.Core;
using Beyond.Plugin.Integration;
using Beyond.Plugin.Runtime;
using Beyond.Plugin.World;
using HarmonyLib;
using Jotunn;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using PassiveTree;
using SoftReferenceableAssets;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Brom8")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.32.1.0")]
[assembly: AssemblyInformationalVersion("0.32.1+7631678d0972989b79d54fd3945dbfa47aa166be")]
[assembly: AssemblyProduct("Beyond")]
[assembly: AssemblyTitle("Beyond")]
[assembly: AssemblyVersion("0.32.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Beyond.Plugin
{
	[BepInPlugin("brom8.beyond", "Beyond", "0.32.1")]
	[BepInDependency("com.jotunn.jotunn", "2.30.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class BeyondPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "brom8.beyond";

		public const string PluginName = "Beyond";

		public const string PluginVersion = "0.32.1";

		public const string PathOfValheimanGuid = "treextr.pathofvalheiman";

		private BeyondSettings _settings;

		private string _assetReport = "Asset probe pending world prefab registration.";

		private string _targetVersion = "unknown";

		private bool _loaded;

		private bool _voidRegistryPending;

		private Harmony? _patches;

		internal static BeyondPlugin? Instance { get; private set; }

		internal TrialRuntime? Runtime { get; private set; }

		internal void LoggerForWorld(string message)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		}

		private void Awake()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			TestSaveDirectory.Apply(((BaseUnityPlugin)this).Logger);
			_settings = new BeyondSettings(((BaseUnityPlugin)this).Config);
			Instance = this;
			Runtime = new TrialRuntime(_settings, ((BaseUnityPlugin)this).Logger);
			_patches = new Harmony("brom8.beyond");
			try
			{
				_patches.PatchAll(typeof(BeyondPlugin).Assembly);
			}
			catch (Exception ex)
			{
				_patches.UnpatchSelf();
				Runtime.Dispose();
				Runtime = null;
				((BaseUnityPlugin)this).Logger.LogError((object)("Beyond could not install its scoped game hooks and has stopped: " + ex));
				return;
			}
			if (Chainloader.PluginInfos.TryGetValue("treextr.pathofvalheiman", out var value))
			{
				_targetVersion = value.Metadata.Version.ToString();
			}
			PrefabManager.OnPrefabsRegistered += OnPrefabsRegistered;
			ItemManager.OnItemsRegistered += OnVoidItemsRegistered;
			PrefabManager.OnVanillaPrefabsAvailable += RegisterContent;
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new StatusCommand(Describe, delegate(string text)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)text);
			}));
			_loaded = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Beyond 0.32.1 experimental Trial loaded; PathOfValheiman " + _targetVersion + ". Use the separate test profile and test saves."));
		}

		private void RegisterContent()
		{
			try
			{
				TrialEnemyDirector.RegisterPrefab();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Beyond content registration failed: " + ex));
				Runtime?.BlockStarts("Beyond content is unavailable. Check the host log and restart after fixing dependencies.");
			}
			try
			{
				VoidCreatures.Register();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Void creatures registered: Beyond_VoidEidolon, Beyond_Riftstalker, Beyond_HollowCantor, Beyond_VoidBlob (no rewards).");
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Void creature registration failed; do not use their spawn commands: " + ex2));
			}
		}

		private void Update()
		{
			Runtime?.Tick();
		}

		private void LateUpdate()
		{
			Runtime?.LateUpdate();
		}

		private void OnPrefabsRegistered()
		{
			_assetReport = VisualAssets.Probe();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Beyond asset probe:\n" + _assetReport));
			if (EnemyPrefabRegistry.CheckScene(out string message))
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)message);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)message);
			}
			_voidRegistryPending = true;
			if (!VoidBlob.CheckWeapon())
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Void spawn registry: waiting for ObjectDB animation-weapon registration.");
			}
			else
			{
				OnVoidItemsRegistered();
			}
		}

		private void OnVoidItemsRegistered()
		{
			if (_voidRegistryPending && !((Object)(object)ZNetScene.instance == (Object)null))
			{
				_voidRegistryPending = false;
				if (VoidCreatures.CheckScene(out string message))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)message);
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogError((object)message);
				}
			}
		}

		private string Describe()
		{
			if (!_loaded)
			{
				return "Beyond foundation is not active.";
			}
			FloorRules val = _settings.SnapshotTrial();
			return "Beyond 0.32.1 | PathOfValheiman " + _targetVersion + "\n" + $"Floor 0 Trial: gate {val.EntryWindowSeconds}s, survival {val.SurvivalSeconds}s, shared coin pool {val.CoinPool}, participant cap {val.ParticipantLimit}.\n" + "Experimental Beyond: " + Runtime?.Status + "\n" + Runtime?.Client?.GroundStatus + "\n" + _assetReport;
		}

		private void OnDestroy()
		{
			_loaded = false;
			PrefabManager.OnPrefabsRegistered -= OnPrefabsRegistered;
			ItemManager.OnItemsRegistered -= OnVoidItemsRegistered;
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterContent;
			Runtime?.Dispose();
			VoidModels.Dispose();
			Harmony? patches = _patches;
			if (patches != null)
			{
				patches.UnpatchSelf();
			}
			Instance = null;
		}
	}
	internal sealed class BeyondSettings
	{
		private readonly ConfigEntry<float>[] _floorHealth = new ConfigEntry<float>[21];

		private readonly ConfigEntry<float>[] _floorDamage = new ConfigEntry<float>[21];

		private readonly ConfigEntry<int>[] _offerPrices = new ConfigEntry<int>[ShopCatalogue.ExtendedOffers.Count];

		public ConfigEntry<int> EntryCoinsPerFloor { get; }

		public ConfigEntry<int> ClearCoinsPerFloor { get; }

		public ConfigEntry<bool> AllowNewRuns { get; }

		public ConfigEntry<int> ScalingStartFloor { get; }

		public ConfigEntry<float> HealthGrowth { get; }

		public ConfigEntry<KeyboardShortcut> MenuShortcut { get; }

		public ConfigEntry<float> DamageGrowth { get; }

		public ConfigEntry<float> NamedHealthBonusEffect { get; }

		public ConfigEntry<int> EntryWindowSeconds { get; }

		public ConfigEntry<int> SurvivalSeconds { get; }

		public ConfigEntry<int> CoinPool { get; }

		public ConfigEntry<int> ParticipantLimit { get; }

		public ConfigEntry<int> MaxInstances { get; }

		public ConfigEntry<int> EnemyLimit { get; }

		public ConfigEntry<int> IronPrice { get; }

		public ConfigEntry<int> TinPrice { get; }

		public ConfigEntry<int> CopperPrice { get; }

		public ConfigEntry<int> BronzePrice { get; }

		public ConfigEntry<int> SimpleRunePacketPrice { get; }

		public ConfigEntry<int> SurtlingCorePrice { get; }

		public ConfigEntry<int> CoreWoodPrice { get; }

		public ConfigEntry<int> FineWoodPrice { get; }

		public ConfigEntry<int> AncientBarkPrice { get; }

		public ConfigEntry<int> GuckPrice { get; }

		public ConfigEntry<int> SilverPrice { get; }

		public ConfigEntry<int> ObsidianPrice { get; }

		public ConfigEntry<int> CrystalPrice { get; }

		public SharedRealmSettings Realm { get; }

		public BeyondSettings(ConfigFile config)
		{
			//IL_0056: 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_0094: 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_00a1: Expected O, but got Unknown
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Expected O, but got Unknown
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Expected O, but got Unknown
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Expected O, but got Unknown
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Expected O, but got Unknown
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Expected O, but got Unknown
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Expected O, but got Unknown
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Expected O, but got Unknown
			//IL_0451: Unknown result type (might be due to invalid IL or missing references)
			//IL_045b: Expected O, but got Unknown
			//IL_048b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0495: Expected O, but got Unknown
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Expected O, but got Unknown
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Expected O, but got Unknown
			//IL_0508: Unknown result type (might be due to invalid IL or missing references)
			//IL_0512: Expected O, but got Unknown
			//IL_053a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0544: Expected O, but got Unknown
			//IL_0568: Unknown result type (might be due to invalid IL or missing references)
			//IL_0572: Expected O, but got Unknown
			//IL_059c: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a6: Expected O, but got Unknown
			//IL_0634: Unknown result type (might be due to invalid IL or missing references)
			//IL_063e: Expected O, but got Unknown
			//IL_065a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0664: Expected O, but got Unknown
			//IL_06ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b5: Expected O, but got Unknown
			//IL_070d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0717: Expected O, but got Unknown
			//IL_0744: Unknown result type (might be due to invalid IL or missing references)
			//IL_074e: Expected O, but got Unknown
			//IL_077b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0785: Expected O, but got Unknown
			//IL_07b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_07bc: Expected O, but got Unknown
			//IL_07e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f3: Expected O, but got Unknown
			//IL_0820: Unknown result type (might be due to invalid IL or missing references)
			//IL_082a: Expected O, but got Unknown
			//IL_0857: Unknown result type (might be due to invalid IL or missing references)
			//IL_0861: Expected O, but got Unknown
			//IL_088e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0898: Expected O, but got Unknown
			//IL_08c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_08cf: Expected O, but got Unknown
			//IL_08fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0906: Expected O, but got Unknown
			//IL_0933: Unknown result type (might be due to invalid IL or missing references)
			//IL_093d: Expected O, but got Unknown
			//IL_096a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0974: Expected O, but got Unknown
			//IL_0990: Unknown result type (might be due to invalid IL or missing references)
			//IL_099a: Expected O, but got Unknown
			Realm = new SharedRealmSettings(config);
			ConfigEntry<KeyboardShortcut> val = config.Bind<KeyboardShortcut>("UI", "MenuShortcut", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Retired shortcut location.");
			MenuShortcut = config.Bind<KeyboardShortcut>("00 - Interface", "MenuShortcut", val.Value, "Local Beyond menu shortcut. Default F8. Inventory can stay open; approach the stone to open a portal. Suppressed while typing, fighting in Beyond or using other blocking interfaces.");
			config.Remove(((ConfigEntryBase)val).Definition);
			ConfigurationManagerAttributes val2 = new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			};
			EntryCoinsPerFloor = config.Bind<int>("01 - Economy", "EntryCoinsPerFloor", 100, new ConfigDescription("Numbered floor entry = floor number times this amount. Bank first plus carried shortfall. Only opener pays; friends enter free.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50000), new object[1] { val2 }));
			ClearCoinsPerFloor = config.Bind<int>("01 - Economy", "ClearCoinsPerFloor", 300, new ConfigDescription("Numbered clear reward = floor number times this amount. Banked only for a surviving opener. Trial remains 200 by default.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50000), new object[1] { val2 }));
			foreach (ShopOffer extendedOffer in ShopCatalogue.ExtendedOffers)
			{
				_offerPrices[extendedOffer.PriceIndex] = config.Bind<int>("Shop.Floor" + extendedOffer.Tab, extendedOffer.Request + "Price", extendedOffer.DefaultPrice, new ConfigDescription("Coin price for " + extendedOffer.Quantity + " " + extendedOffer.DisplayName + ". Captured at run start.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			}
			ScalingStartFloor = config.Bind<int>("Scaling", "StartFloor", 1, new ConfigDescription("First floor receiving one growth step. Floor1 at10% grows to1.10x; Floor2 to1.21x. Trial stays neutral by default.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), new object[1] { val2 }));
			ConfigEntry<int> val3 = config.Bind<int>("Migration", "ScalingRevision", 0, "Internal default migration; leave unchanged.");
			if (val3.Value < 1)
			{
				if (ScalingStartFloor.Value == 10)
				{
					ScalingStartFloor.Value = 1;
				}
				val3.Value = 1;
			}
			NamedHealthBonusEffect = config.Bind<float>("Scaling", "NamedHealthBonusEffect", 2f, new ConfigDescription("Multiply only the added health-growth bonus for required named targets.2 means normal+21% becomes named+42%; authored base health/stars/rarity and per-floor overrides remain separate. Captured at run start.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), new object[1] { val2 }));
			HealthGrowth = config.Bind<float>("Scaling", "HealthGrowthPerFloor", 0.1f, new ConfigDescription("Additional compounded health growth per floor from StartFloor. 0.10 means 10%; final factors clamp to 0.01..100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { val2 }));
			DamageGrowth = config.Bind<float>("Scaling", "DamageGrowthPerFloor", 0f, new ConfigDescription("Separate compounded damage growth per floor from StartFloor. Default 0 keeps damage unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { val2 }));
			for (int i = 0; i <= 20; i++)
			{
				string text = ((i == 0) ? "Trial" : ("Floor" + i));
				_floorHealth[i] = config.Bind<float>(text, "HealthMultiplier", 1f, new ConfigDescription("Additional health multiplier for this floor; combines once with Scaling growth and PoV difficulty. Captured at run start.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), new object[1] { val2 }));
				_floorDamage[i] = config.Bind<float>(text, "DamageMultiplier", 1f, new ConfigDescription("Additional damage multiplier for this floor; default 1. Captured at run start.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), new object[1] { val2 }));
			}
			AllowNewRuns = config.Bind<bool>("General", "AllowNewRuns", true, new ConfigDescription("Enable new Beyond runs. Disable to stop new runs while retaining recovery/exits. Use test saves.", (AcceptableValueBase)null, new object[1] { val2 }));
			EntryWindowSeconds = config.Bind<int>("Trial", "EntryWindowSeconds", 10, new ConfigDescription("Entry reservation window for all floors (legacy Trial section). Accepted transfers have a bounded arrival wait before combat.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 120), new object[1] { val2 }));
			SurvivalSeconds = config.Bind<int>("Trial", "SurvivalSeconds", 100, new ConfigDescription("Host survival duration in seconds; captured when an attempt starts.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 3600), new object[1] { val2 }));
			CoinPool = config.Bind<int>("Trial", "CoinPool", 200, new ConfigDescription("Trial reward banked for the surviving portal opener. Design default: 200.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000000), new object[1] { val2 }));
			for (int j = 1; j <= 20; j++)
			{
				ConfigEntry<int> val4 = config.Bind<int>("Floor" + j, "CoinPool", 300 * j, "Retired by C11 economy.");
				config.Remove(((ConfigEntryBase)val4).Definition);
			}
			ParticipantLimit = config.Bind<int>("Dungeons", "ParticipantLimit", 8, new ConfigDescription("Bound on unique participants in one attempt. Initial test target is solo then two players.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 16), new object[1] { val2 }));
			MaxInstances = config.Bind<int>("Dungeons", "MaxConcurrentInstances", 4, new ConfigDescription("Maximum simultaneous Beyond instances, including shops and pending returns. Fixed support layouts are pooled; hard maximum 4.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 4), new object[1] { val2 }));
			ConfigEntry<int> val5 = config.Bind<int>("Trial", "MaxLivingEnemies", 50, new ConfigDescription("Retired Trial limit, migrated to the per-instance setting.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>()));
			EnemyLimit = config.Bind<int>("Dungeons", "MaxLivingEnemiesPerInstance", val5.Value, new ConfigDescription("Living-enemy limit for EACH independent Beyond instance, including boss/adds. No shared population cap. Four instances can total 200 enemies at 50 each. Spawn pacing stays bounded.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), new object[1] { val2 }));
			ConfigEntry<int> val6 = config.Bind<int>("Dungeons", "MaxLivingEnemiesTotal", 50, "Retired shared cap; no longer enforced.");
			config.Remove(((ConfigEntryBase)val5).Definition);
			config.Remove(((ConfigEntryBase)val6).Definition);
			config.Save();
			ConfigEntry<int> val7 = config.Bind<int>("Shop", "BeyondEntranceKeyPrice", 100, "Retired item.");
			config.Remove(((ConfigEntryBase)val7).Definition);
			IronPrice = config.Bind<int>("Shop", "TrialIronPrice", 100, new ConfigDescription("Standard coin price for a packet of 2 iron bars in floor tab 3. Legacy setting name retained.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			ConfigEntry<int> val8 = config.Bind<int>("Migration", "IronPriceRevision", 0, new ConfigDescription("Internal one-time iron-price migration marker.", (AcceptableValueBase)null, Array.Empty<object>()));
			if (val8.Value < 1)
			{
				if (IronPrice.Value == 10)
				{
					IronPrice.Value = 50;
				}
				val8.Value = 1;
			}
			ConfigEntry<int> val9 = config.Bind<int>("Migration", "IronPacketRevision", 0, new ConfigDescription("Internal one-time migration of the former iron default to packet pricing.", (AcceptableValueBase)null, Array.Empty<object>()));
			if (val9.Value < 1)
			{
				if (IronPrice.Value == 50)
				{
					IronPrice.Value = 100;
				}
				val9.Value = 1;
			}
			TinPrice = config.Bind<int>("Shop", "TinPrice", 10, new ConfigDescription("Standard coin price per Tin bar in the Trial tab.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			CopperPrice = config.Bind<int>("Shop", "CopperPrice", 10, new ConfigDescription("Standard coin price per Copper bar in the Trial tab.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			BronzePrice = config.Bind<int>("Shop", "BronzePrice", 30, new ConfigDescription("Standard coin price per Bronze bar in the Trial tab.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			SimpleRunePacketPrice = config.Bind<int>("Shop", "SimpleRunePacketPrice", 100, new ConfigDescription("Standard coin price per basic PoV rune packet in every Trial tab. Fixed packets use base ordinary-dust costs at 100 dust: Insight/Guise 10, Spark 7, Weaving 5, Change 4. Ignores blank runestones and passive discounts. Host-controlled; captured at run start.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			SurtlingCorePrice = config.Bind<int>("Shop", "SurtlingCorePrice", 100, new ConfigDescription("Standard coin price for a packet of 2 Surtling cores in floor tab 1.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			CoreWoodPrice = config.Bind<int>("Shop", "CoreWoodPrice", 100, new ConfigDescription("Standard coin price for a packet of 10 core wood in floor tab 2.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			FineWoodPrice = config.Bind<int>("Shop", "FineWoodPrice", 100, new ConfigDescription("Standard coin price for a packet of 10 fine wood in floor tab 2.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			AncientBarkPrice = config.Bind<int>("Shop", "AncientBarkPrice", 100, new ConfigDescription("Coin price per packet of 10 ancient bark in tab 4.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			GuckPrice = config.Bind<int>("Shop", "GuckPrice", 100, new ConfigDescription("Coin price per packet of 5 guck in tab 4.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			SilverPrice = config.Bind<int>("Shop", "SilverPrice", 100, new ConfigDescription("Coin price per packet of 2 silver bars in tab 5.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			ObsidianPrice = config.Bind<int>("Shop", "ObsidianPrice", 100, new ConfigDescription("Coin price per packet of 10 obsidian in tab 6.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			CrystalPrice = config.Bind<int>("Shop", "CrystalPrice", 100, new ConfigDescription("Coin price per packet of 5 crystal in tab 6.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000000), new object[1] { val2 }));
			ConfigEntry<int> val10 = config.Bind<int>("Migration", "ShopPacketRevision", 0, new ConfigDescription("Internal one-time migration of former default unit prices to packet prices.", (AcceptableValueBase)null, Array.Empty<object>()));
			if (val10.Value < 1)
			{
				if (SurtlingCorePrice.Value == 50)
				{
					SurtlingCorePrice.Value = 100;
				}
				if (CoreWoodPrice.Value == 10)
				{
					CoreWoodPrice.Value = 100;
				}
				if (FineWoodPrice.Value == 10)
				{
					FineWoodPrice.Value = 100;
				}
				val10.Value = 1;
			}
			config.Save();
		}

		public CreaturePower SnapshotScaling(int floor)
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			return new CreaturePower(FloorScaling.Factor(floor, ScalingStartFloor.Value, HealthGrowth.Value, _floorHealth[floor].Value), FloorScaling.Factor(floor, ScalingStartFloor.Value, DamageGrowth.Value, _floorDamage[floor].Value), (float?)FloorScaling.NamedFactor(FloorScaling.Factor(floor, ScalingStartFloor.Value, HealthGrowth.Value, 1f), NamedHealthBonusEffect.Value, _floorHealth[floor].Value));
		}

		public ShopPrices SnapshotShop()
		{
			return new ShopPrices
			{
				tin = TinPrice.Value,
				copper = CopperPrice.Value,
				bronze = BronzePrice.Value,
				iron = IronPrice.Value,
				surtlingCore = SurtlingCorePrice.Value,
				coreWood = CoreWoodPrice.Value,
				fineWood = FineWoodPrice.Value,
				ancientBark = AncientBarkPrice.Value,
				guck = GuckPrice.Value,
				silver = SilverPrice.Value,
				obsidian = ObsidianPrice.Value,
				crystal = CrystalPrice.Value,
				simpleRunePacket = SimpleRunePacketPrice.Value,
				extended = Array.ConvertAll(_offerPrices, (ConfigEntry<int> entry) => entry.Value)
			};
		}

		public FloorRules SnapshotTrial()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			return new FloorRules(0, (double)SurvivalSeconds.Value, CoinPool.Value, ParticipantLimit.Value, (double)EntryWindowSeconds.Value, 45.0, 2.0, (FloorObjective)0);
		}

		public FloorRules SnapshotFloor(int floor)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			if (floor != 0)
			{
				return new FloorRules(floor, 100.0, ClearCoinsPerFloor.Value * floor, ParticipantLimit.Value, (double)EntryWindowSeconds.Value, 45.0, 2.0, (FloorObjective)1);
			}
			return SnapshotTrial();
		}
	}
	internal sealed class SharedRealmSettings
	{
		public ConfigEntry<bool> Enabled { get; }

		public ConfigEntry<bool> LandscapePreview { get; }

		public ConfigEntry<int> MinimumFloor { get; }

		public ConfigEntry<int> RespawnSeconds { get; }

		public ConfigEntry<int> EnemyLimit { get; }

		public ConfigEntry<float> Health { get; }

		public ConfigEntry<float> Damage { get; }

		public SharedRealmSettings(ConfigFile file)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Expected O, but got Unknown
			ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			};
			Enabled = file.Bind<bool>("Shared realm", "Enabled", true, new ConfigDescription("Host: allow new free shared-realm visits; exits/recovery remain available when disabled.", (AcceptableValueBase)null, new object[1] { val }));
			LandscapePreview = file.Bind<bool>("Shared realm", "LandscapePreview", true, new ConfigDescription("Host: new shared visits use the separate768m six-setting biome showcase (no enemies). False selects the original1km realm. Destination is pinned per visit; reload world to change.", (AcceptableValueBase)null, new object[1] { val }));
			MinimumFloor = file.Bind<int>("Shared realm", "MinimumCompletedFloor", 14, new ConfigDescription("Personal highest completion required for shared-realm entry. Use0 for testing after Trial.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), new object[1] { val }));
			RespawnSeconds = file.Bind<int>("Shared realm", "RespawnSeconds", 600, new ConfigDescription("Earliest respawn after confirmed native death processing, measured in host-running seconds. Living actors are never replaced.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(60, 3600), new object[1] { val }));
			EnemyLimit = file.Bind<int>("Shared realm", "MaxLivingEnemies", 50, new ConfigDescription("Independent shared-realm ceiling including named targets/adds. Not shared with numbered instances; authored initial roster is eight named targets.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), new object[1] { val }));
			Health = file.Bind<float>("Shared realm", "HealthMultiplier", 1f, new ConfigDescription("Additional shared-realm health factor, independent of numbered-floor exponential scaling. Native stars/authored base health remain explicit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), new object[1] { val }));
			Damage = file.Bind<float>("Shared realm", "DamageMultiplier", 1f, new ConfigDescription("Additional shared-realm damage factor. Physical-world biome/corruption multipliers are excluded.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), new object[1] { val }));
		}
	}
	internal sealed class StatusCommand : ConsoleCommand
	{
		private readonly Func<string> _describe;

		private readonly Action<string> _writeLog;

		public override string Name => "beyond_status";

		public override string Help => "Show Beyond foundation/version/config status and runtime asset availability; makes no world changes.";

		public StatusCommand(Func<string> describe, Action<string> writeLog)
		{
			_describe = describe;
			_writeLog = writeLog;
		}

		public override void Run(string[] args)
		{
			_writeLog(_describe());
		}

		public override void Run(string[] args, Terminal terminal)
		{
			terminal.AddString(_describe());
		}
	}
	internal static class VisualAssets
	{
		internal static readonly (string Role, string Prefab)[] Candidates = new(string, string)[11]
		{
			("entrance totem", "StatueEvil"),
			("portal", "portal_wood"),
			("arena floor", "stone_floor_2x2"),
			("ruin boundary", "stone_wall_4x2"),
			("blue accent light", "piece_groundtorch_blue"),
			("Trial enemy", "Troll"),
			("bear option", "Bjorn"),
			("goblin", "Goblin"),
			("trader", "Haldor"),
			("currency", "Coins"),
			("first shop resource", "Iron")
		};

		internal static string Probe()
		{
			List<string> list = new List<string>();
			(string, string)[] candidates = Candidates;
			for (int i = 0; i < candidates.Length; i++)
			{
				(string, string) tuple = candidates[i];
				bool flag = (Object)(object)PrefabManager.Instance.GetPrefab(tuple.Item2) != (Object)null;
				list.Add(tuple.Item1 + ": " + tuple.Item2 + " = " + (flag ? "available" : "missing"));
			}
			return string.Join("\n", list);
		}
	}
}
namespace Beyond.Plugin.World
{
	internal static class AdvancedFloorLayout
	{
		public static Vector3 Entry(int floor)
		{
			//IL_0025: 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_003c: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			return (Vector3)(floor switch
			{
				4 => new Vector3(0f, 2f, -35f), 
				5 => new Vector3(0f, 2f, -36f), 
				6 => new Vector3(-20f, 2f, -77f), 
				_ => throw new ArgumentOutOfRangeException("floor"), 
			});
		}

		public static Vector3 Boss(int floor)
		{
			//IL_0025: 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_003c: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			return (Vector3)(floor switch
			{
				4 => new Vector3(12f, 1.5f, 20f), 
				5 => new Vector3(0f, 1.5f, 28f), 
				6 => new Vector3(18f, 1.5f, 73f), 
				_ => throw new ArgumentOutOfRangeException("floor"), 
			});
		}

		public static Vector3 ShopGate(int floor)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			return Boss(floor) + new Vector3(0f, -1.5f, -9f);
		}

		public static Vector3 Group(int floor, int group)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			return (Vector3)(floor switch
			{
				4 => Vector3.zero, 
				5 => group switch
				{
					0 => new Vector3(-22f, 0f, -12f), 
					1 => new Vector3(22f, 0f, 0f), 
					_ => new Vector3(0f, 0f, 24f), 
				}, 
				6 => group switch
				{
					0 => new Vector3(-18f, 0f, -48f), 
					1 => new Vector3(18f, 0f, -2f), 
					_ => new Vector3(-18f, 0f, 43f), 
				}, 
				_ => throw new ArgumentOutOfRangeException("floor"), 
			});
		}

		public static Vector3 Guard(int floor, int index, int groupSize)
		{
			//IL_0048: 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_0077: 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)
			int num = index / groupSize;
			int num2 = index % groupSize;
			if (floor == 4)
			{
				float num3 = ((float)num2 * 137.5f + (float)(num * 41)) * (MathF.PI / 180f);
				float num4 = 15 + num2 % 3 * 2;
				return new Vector3(Mathf.Sin(num3) * num4, 1.5f, Mathf.Cos(num3) * num4);
			}
			return Group(floor, num) + new Vector3(((float)(num2 % 4) - 1.5f) * 2.7f, 1.5f, ((float)(num2 / 4) - 1.5f) * 3f);
		}

		public static Mesh RoundBoundary()
		{
			//IL_0076: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0090: 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_009f: 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)
			CanyonLayout.Builder builder = new CanyonLayout.Builder();
			Vector3 val = default(Vector3);
			Vector3 val2 = default(Vector3);
			for (int i = 0; i < 64; i++)
			{
				float num = (float)i * MathF.PI / 32f;
				float num2 = (float)(i + 1) * MathF.PI / 32f;
				((Vector3)(ref val))..ctor(Mathf.Sin(num) * 46f, -2f, Mathf.Cos(num) * 46f);
				((Vector3)(ref val2))..ctor(Mathf.Sin(num2) * 46f, -2f, Mathf.Cos(num2) * 46f);
				builder.Quad(val, val + Vector3.up * 40f, val2 + Vector3.up * 40f, val2, doubleSided: true);
			}
			return builder.Build("Beyond compact floor invisible rim");
		}

		public static void Build(NativeScenery scenery, Transform parent, Vector3 origin, int floor)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: 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)
			int count = 0;
			bool frost = floor >= 5;
			if (floor == 4 || floor == 5)
			{
				for (int i = 0; i < 28; i++)
				{
					float num = (float)i * MathF.PI * 2f / 28f;
					Rock(Mathf.Sin(num) * 44f, Mathf.Cos(num) * 44f, 15f, (floor == 4) ? 14 : 23, 17f, i * 73);
					if (floor == 4 && i % 2 == 0)
					{
						Place((i % 4 == 0) ? "SwampTree2" : "SwampTree1", Mathf.Sin(num) * 40f, Mathf.Cos(num) * 40f, 1f, 24 + i % 4, 1f, i * 39, uniform: true);
					}
					if (floor == 5 && i % 4 == 0)
					{
						Place("FirTree_small", Mathf.Sin(num) * 38f, Mathf.Cos(num) * 38f, 1f, 10 + i % 3, 1f, i * 37, uniform: true);
					}
				}
				if (floor == 4)
				{
					Vector2[] array = (Vector2[])(object)new Vector2[6]
					{
						new Vector2(-8f, -7f),
						new Vector2(8f, -6f),
						new Vector2(-5f, 8f),
						new Vector2(7f, 9f),
						new Vector2(-12f, 0f),
						new Vector2(2f, -12f)
					};
					for (int j = 0; j < array.Length; j++)
					{
						Rock(array[j].x, array[j].y, 3.4f, 0.9f, 4f, j * 67, 0.72f);
					}
					for (int k = 0; k < 3; k++)
					{
						float num2 = (float)k * MathF.PI * 2f / 3f;
						float num3 = Mathf.Cos(num2) * 30f;
						float num4 = Mathf.Sin(num2) * 30f;
						Rock(num3, num4, 10f, 6f, 10f, k * 81);
						Place("SwampTree2", num3, num4, 1f, 26f, 1f, k * 100, uniform: true);
						Place("SwampTree2_log", num3 + 2f, num4 + 3f, 9f, 1.8f, 3f, k * 110);
					}
				}
				else
				{
					Rock(0f, -2f, 18f, 21f, 25f, 17f);
					Rock(-4f, -7f, 12f, 10f, 14f, 93f);
					Rock(5f, 5f, 11f, 15f, 12f, 42f);
				}
				for (int l = 0; l < 22; l++)
				{
					float num5 = (float)l * 137.5f * (MathF.PI / 180f);
					float x = Mathf.Sin(num5) * 33f;
					float z = Mathf.Cos(num5) * 33f;
					Rock(x, z, 3 + l % 3, 0.8f, 4f, l * 47, 0.8f);
					if (floor == 4)
					{
						Place("Bush01", x, z, 2.5f, 1.2f, 2.5f, l * 81);
					}
					else if (l % 3 == 0)
					{
						Place("FirTree_small_dead", x, z, 1f, 5f, 1f, l * 89, uniform: true);
					}
				}
				return;
			}
			if (floor == 6)
			{
				for (int m = -1; m <= 1; m += 2)
				{
					for (int n = 0; n < 17; n++)
					{
						Rock(m * 43, -95 + n * 12, 18f, 24 + n % 3 * 3, 20f, n * 53);
					}
				}
				for (int num6 = -1; num6 <= 1; num6 += 2)
				{
					for (int num7 = 0; num7 < 7; num7++)
					{
						Rock(-42 + num7 * 14, num6 * 98, 22f, 28f, 18f, num7 * 71);
					}
				}
				for (int num8 = 0; num8 < 3; num8++)
				{
					int num9 = ((num8 % 2 == 0) ? 1 : (-1));
					float num10 = -44 + num8 * 44;
					Rock(num9 * 18, num10, 23f, 18f, 19f, 20 + num8 * 57);
					Rock(num9 * 30, num10 - 4f, 17f, 24f, 16f, num8 * 83);
					Place("Pickable_MountainCaveCrystal", num9 * 12, num10 - 9f, 2f, 3f, 2f, num8 * 109);
					Place("Pickable_MountainCaveCrystal", num9 * 28, num10 + 10f, 3f, 4f, 3f, num8 * 39);
				}
				for (int num11 = -1; num11 <= 1; num11 += 2)
				{
					for (int num12 = 0; num12 < 12; num12++)
					{
						Rock(num11 * 34, -85 + num12 * 15, 4f, 0.7f, 5f, num12 * 47, 0.8f);
						if (num12 % 3 == 0)
						{
							Place("Pickable_MountainCaveCrystal", num11 * 36, -85 + num12 * 15, 2f, 2.5f, 2f, num12 * 67);
						}
					}
				}
				scenery.Run(delegate
				{
					//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_001c: 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_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_0047: 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)
					GameObject val = new GameObject("Beyond warm sanctum court");
					val.transform.SetParent(parent, false);
					val.transform.position = origin + NumberedFloorLayout.AtGround(floor, new Vector3(18f, 5f, 73f));
					Light obj = val.AddComponent<Light>();
					obj.type = (LightType)2;
					obj.color = new Color(1f, 0.36f, 0.12f);
					obj.range = 26f;
					obj.intensity = 2.3f;
					obj.shadows = (LightShadows)0;
				});
				return;
			}
			throw new ArgumentOutOfRangeException("floor");
			void Place(string prefab, float num13, float num14, float w, float h, float d, float yaw = 0f, bool uniform = false, float embed = 0f)
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: 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)
				if (++count > 190)
				{
					throw new InvalidOperationException("Beyond advanced scenery budget exceeded.");
				}
				scenery.Place(parent, prefab, origin + NumberedFloorLayout.AtGround(floor, new Vector3(num13, -0.1f - h * embed, num14)), new Vector3(w, h, d), yaw, uniform, warm: false, frost);
			}
			void Rock(float x2, float z2, float w, float h, float d, float yaw = 0f, float embed = 0.5f)
			{
				Place("Rock_7", x2, z2, w, h, d, yaw, uniform: false, embed);
			}
		}
	}
	internal sealed class AuthoredVoidSkin
	{
		private readonly List<Object> Assets = new List<Object>();

		private readonly string _prefix;

		private readonly VoidKind _kind;

		private static readonly Dictionary<VoidKind, AuthoredVoidSkin> Skins = new Dictionary<VoidKind, AuthoredVoidSkin>();

		private Mesh[]? _meshes;

		private Material[]? _materials;

		private string[] _names = Array.Empty<string>();

		private AuthoredVoidSkin(VoidKind kind)
		{
			//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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			_kind = kind;
			_prefix = (((int)kind == 0) ? "eidolon" : (((int)kind == 1) ? "riftstalker" : "hollowcantor"));
		}

		internal static void Build(VoidKind kind, Transform rig, IReadOnlyDictionary<string, Transform> bones, Material native)
		{
			//IL_0005: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			if (!Skins.TryGetValue(kind, out AuthoredVoidSkin value))
			{
				value = new AuthoredVoidSkin(kind);
				Skins.Add(kind, value);
			}
			value.Attach(rig, bones, native);
		}

		private void Attach(Transform rig, IReadOnlyDictionary<string, Transform> bones, Material native)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			if (_meshes == null)
			{
				Load(rig, bones, native);
			}
			Transform[] array = (Transform[])(object)new Transform[_names.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = bones[_names[i]];
			}
			for (int j = 0; j < 3; j++)
			{
				GameObject val = new GameObject("Stone" + j);
				val.transform.SetParent(rig, false);
				SkinnedMeshRenderer obj = val.AddComponent<SkinnedMeshRenderer>();
				obj.sharedMesh = _meshes[j];
				((Renderer)obj).sharedMaterial = _materials[j];
				obj.bones = array;
				obj.rootBone = bones["body"];
				obj.quality = (SkinQuality)4;
				obj.updateWhenOffscreen = false;
				((Renderer)obj).localBounds = (((int)_kind == 0) ? new Bounds(new Vector3(0f, 2.8f, 0f), new Vector3(11f, 10f, 10f)) : new Bounds(new Vector3(0f, 1.3f, 0f), new Vector3(7f, 7f, 8f)));
				((Renderer)obj).shadowCastingMode = (ShadowCastingMode)(j != 2);
				((Renderer)obj).receiveShadows = j != 2;
			}
		}

		private void Load(Transform rig, IReadOnlyDictionary<string, Transform> bones, Material native)
		{
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: 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_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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_05aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_05af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0401: Unknown result type (might be due to invalid IL or missing references)
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0413: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0603: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Expected O, but got Unknown
			//IL_0639: Unknown result type (might be due to invalid IL or missing references)
			//IL_063e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0660: Unknown result type (might be due to invalid IL or missing references)
			//IL_0668: Unknown result type (might be due to invalid IL or missing references)
			//IL_0669: Unknown result type (might be due to invalid IL or missing references)
			//IL_0673: Unknown result type (might be due to invalid IL or missing references)
			//IL_0674: Unknown result type (might be due to invalid IL or missing references)
			//IL_0680: Expected O, but got Unknown
			//IL_06a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0798: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ae: Unknown result type (might be due to invalid IL or missing references)
			using BinaryReader binaryReader = new BinaryReader(Resource(_prefix + ".mesh"));
			if (Encoding.ASCII.GetString(binaryReader.ReadBytes(8)) != "BEVM0001")
			{
				throw new InvalidDataException("Invalid Eidolon skin format.");
			}
			int num = binaryReader.ReadInt32();
			int num2 = binaryReader.ReadInt32();
			if (num < 3 || num > 100000 || num % 3 != 0 || num2 < 1 || num2 > 64)
			{
				throw new InvalidDataException("Invalid Eidolon skin counts.");
			}
			_names = new string[num2];
			Matrix4x4[] array = (Matrix4x4[])(object)new Matrix4x4[num2];
			HashSet<string> hashSet = new HashSet<string>();
			for (int i = 0; i < num2; i++)
			{
				int num3 = binaryReader.ReadInt32();
				if (num3 < 1 || num3 > 64)
				{
					throw new InvalidDataException("Invalid joint name.");
				}
				string text = Encoding.UTF8.GetString(binaryReader.ReadBytes(num3));
				if (!hashSet.Add(text) || !bones.TryGetValue(text, out Transform value))
				{
					throw new InvalidDataException("Missing/repeated Eidolon joint: " + text);
				}
				_names[i] = text;
				array[i] = value.worldToLocalMatrix * rig.localToWorldMatrix;
			}
			Vector3[] array2 = (Vector3[])(object)new Vector3[num];
			Vector3[] array3 = (Vector3[])(object)new Vector3[num];
			Vector2[] array4 = (Vector2[])(object)new Vector2[num];
			BoneWeight[] array5 = (BoneWeight[])(object)new BoneWeight[num];
			List<int>[] array6 = new List<int>[3]
			{
				new List<int>(),
				new List<int>(),
				new List<int>()
			};
			int num4 = -1;
			for (int j = 0; j < num; j++)
			{
				array2[j] = new Vector3(F(binaryReader), F(binaryReader), F(binaryReader));
				array3[j] = new Vector3(F(binaryReader), F(binaryReader), F(binaryReader));
				array4[j] = new Vector2(F(binaryReader), F(binaryReader));
				int[] array7 = new int[4]
				{
					binaryReader.ReadInt32(),
					binaryReader.ReadInt32(),
					binaryReader.ReadInt32(),
					binaryReader.ReadInt32()
				};
				float[] array8 = new float[4]
				{
					F(binaryReader),
					F(binaryReader),
					F(binaryReader),
					F(binaryReader)
				};
				float num5 = 0f;
				for (int k = 0; k < 4; k++)
				{
					if (array7[k] < 0 || array7[k] >= num2 || array8[k] < 0f || array8[k] > 1f)
					{
						throw new InvalidDataException("Invalid skin influence.");
					}
					num5 += array8[k];
				}
				if (Mathf.Abs(num5 - 1f) > 0.001f || ((Vector3)(ref array3[j])).sqrMagnitude < 0.1f)
				{
					throw new InvalidDataException("Invalid skin weight sum/normal.");
				}
				int num6 = j;
				BoneWeight val = default(BoneWeight);
				((BoneWeight)(ref val)).boneIndex0 = array7[0];
				((BoneWeight)(ref val)).boneIndex1 = array7[1];
				((BoneWeight)(ref val)).boneIndex2 = array7[2];
				((BoneWeight)(ref val)).boneIndex3 = array7[3];
				((BoneWeight)(ref val)).weight0 = array8[0];
				((BoneWeight)(ref val)).weight1 = array8[1];
				((BoneWeight)(ref val)).weight2 = array8[2];
				((BoneWeight)(ref val)).weight3 = array8[3];
				array5[num6] = val;
				int num7 = binaryReader.ReadInt32();
				if (num7 < 0 || num7 > 2 || (j % 3 != 0 && num7 != num4))
				{
					throw new InvalidDataException("Invalid material triangle.");
				}
				num4 = num7;
				array6[num7].Add(j);
			}
			if (binaryReader.BaseStream.Position != binaryReader.BaseStream.Length)
			{
				throw new InvalidDataException("Trailing Eidolon skin data.");
			}
			Mesh[] array9 = (Mesh[])(object)new Mesh[3];
			for (int l = 0; l < 3; l++)
			{
				if (array6[l].Count == 0)
				{
					throw new InvalidDataException("Empty Eidolon skin material.");
				}
				int count = array6[l].Count;
				Vector3[] array10 = (Vector3[])(object)new Vector3[count];
				Vector3[] array11 = (Vector3[])(object)new Vector3[count];
				Vector2[] array12 = (Vector2[])(object)new Vector2[count];
				BoneWeight[] array13 = (BoneWeight[])(object)new BoneWeight[count];
				int[] array14 = new int[count];
				for (int m = 0; m < count; m++)
				{
					int num8 = array6[l][m];
					array10[m] = array2[num8];
					array11[m] = array3[num8];
					array12[m] = array4[num8];
					array13[m] = array5[num8];
					array14[m] = m;
				}
				Mesh val2 = new Mesh
				{
					name = _prefix + " sculpted skin " + l,
					indexFormat = (IndexFormat)(count > 65535)
				};
				Assets.Add((Object)(object)val2);
				val2.vertices = array10;
				val2.normals = array11;
				val2.uv = array12;
				val2.boneWeights = array13;
				val2.bindposes = array;
				val2.SetTriangles(array14, 0);
				val2.RecalculateTangents();
				val2.RecalculateBounds();
				array9[l] = val2;
			}
			Texture2D val3 = Texture(_prefix + "_basecolor.png", linear: false);
			Texture2D val4 = Texture(_prefix + "_normal.png", linear: true);
			Texture2D val5 = Texture(_prefix + "_roughness.png", linear: true);
			Texture2D val6 = Texture(_prefix + "_occlusion.png", linear: true);
			Texture2D val7 = Texture(_prefix + "_emission.png", linear: false);
			Color32[] pixels = val4.GetPixels32();
			for (int n = 0; n < pixels.Length; n++)
			{
				pixels[n] = new Color32(byte.MaxValue, pixels[n].g, pixels[n].b, pixels[n].r);
			}
			val4.SetPixels32(pixels);
			val4.Apply(true, true);
			Color32[] pixels2 = val5.GetPixels32();
			for (int num9 = 0; num9 < pixels2.Length; num9++)
			{
				pixels2[num9] = new Color32((byte)0, (byte)0, (byte)0, (byte)(255 - pixels2[num9].r));
			}
			val5.SetPixels32(pixels2);
			val5.Apply(true, true);
			Material[] array15 = (Material[])(object)new Material[3];
			for (int num10 = 0; num10 < 3; num10++)
			{
				Material val8 = new Material(native)
				{
					name = "Beyond sculpted " + _prefix + " " + num10,
					mainTexture = (Texture)(object)val3,
					mainTextureScale = Vector2.one,
					mainTextureOffset = Vector2.zero
				};
				Assets.Add((Object)(object)val8);
				if (val8.HasProperty("_Color"))
				{
					val8.SetColor("_Color", Color.white);
				}
				if (val8.HasProperty("_Metallic"))
				{
					val8.SetFloat("_Metallic", 0f);
				}
				Map(val8, "_BumpMap", (Texture)(object)val4, "_NORMALMAP");
				Map(val8, "_MetallicGlossMap", (Texture)(object)val5, "_METALLICGLOSSMAP");
				Map(val8, "_OcclusionMap", (Texture)(object)val6);
				Map(val8, "_EmissionMap", (Texture)(object)val7, "_EMISSION");
				if (val8.HasProperty("_BumpScale"))
				{
					val8.SetFloat("_BumpScale", 0.7f);
				}
				if (val8.HasProperty("_OcclusionStrength"))
				{
					val8.SetFloat("_OcclusionStrength", 0.65f);
				}
				if (val8.HasProperty("_GlossMapScale"))
				{
					val8.SetFloat("_GlossMapScale", 1f);
				}
				if (val8.HasProperty("_EmissionColor"))
				{
					val8.SetColor("_EmissionColor", new Color(0.8f, 0.01f, 1f) * ((num10 == 2) ? 3f : 0.3f));
				}
				array15[num10] = val8;
			}
			val3.Apply(true, true);
			val6.Apply(true, true);
			val7.Apply(true, true);
			_meshes = array9;
			_materials = array15;
			Debug.Log((object)("Beyond " + _prefix + " weighted skin loaded: " + num / 3 + " triangles, " + num2 + " joints, 1024px base/normal/response/AO/emission. Native appearance/deformation still require testing."));
			Debug.Log((object)("Beyond " + _prefix + " native shader '" + ((Object)native.shader).name + "'; map properties normal=" + native.HasProperty("_BumpMap") + ", roughness=" + native.HasProperty("_MetallicGlossMap") + ", AO=" + native.HasProperty("_OcclusionMap") + ", emission=" + native.HasProperty("_EmissionMap") + "."));
		}

		private static float F(BinaryReader reader)
		{
			float num = reader.ReadSingle();
			if (float.IsNaN(num) || float.IsInfinity(num))
			{
				throw new InvalidDataException("Non-finite Eidolon skin data.");
			}
			return num;
		}

		private Stream Resource(string name)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return Assembly.GetExecutingAssembly().GetManifestResourceStream((((int)_kind == 0) ? "Beyond.Eidolon." : "Beyond.Adds.") + name) ?? throw new InvalidDataException("Missing authored Eidolon asset: " + name);
		}

		private Texture2D Texture(string name, bool linear)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_003f: Expected O, but got Unknown
			using Stream stream = Resource(name);
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, linear)
			{
				name = "Beyond " + name,
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			Assets.Add((Object)(object)val);
			if (!ImageConversion.LoadImage(val, memoryStream.ToArray(), false) || ((Texture)val).width != 1024 || ((Texture)val).height != 1024)
			{
				throw new InvalidDataException("Invalid authored Eidolon map: " + name);
			}
			return val;
		}

		private static void Map(Material material, string property, Texture texture, string keyword = "")
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (material.HasProperty(property))
			{
				material.SetTexture(property, texture);
				material.SetTextureScale(property, Vector2.one);
				material.SetTextureOffset(property, Vector2.zero);
				if (keyword.Length > 0)
				{
					material.EnableKeyword(keyword);
				}
			}
		}

		internal static void Dispose()
		{
			foreach (AuthoredVoidSkin value in Skins.Values)
			{
				foreach (Object asset in value.Assets)
				{
					if (asset != (Object)null)
					{
						Object.Destroy(asset);
					}
				}
			}
			Skins.Clear();
		}
	}
	internal sealed class BeyondAtmosphere : IDisposable
	{
		private const string ArenaName = "brom8.beyond.island";

		private const string CanyonName = "brom8.beyond.canyon";

		private const string ForestName = "brom8.beyond.forest";

		private const string SwampName = "brom8.beyond.swamp";

		private const string MountainName = "brom8.beyond.mountain";

		private const string SanctumName = "brom8.beyond.sanctum";

		private const string ShopName = "brom8.beyond.stars";

		private readonly TrialWorld _world;

		private readonly BeyondIslandMist _mist = new BeyondIslandMist();

		private readonly BeyondSnow _snow = new BeyondSnow();

		private readonly Dictionary<int, EnvSetup> _later = new Dictionary<int, EnvSetup>();

		private EnvMan? _manager;

		private EnvSetup? _arena;

		private EnvSetup? _canyon;

		private EnvSetup? _forest;

		private EnvSetup? _swamp;

		private EnvSetup? _mountain;

		private EnvSetup? _sanctum;

		private EnvSetup? _shop;

		private Camera? _camera;

		private CameraClearFlags _clear;

		private Color _background;

		private float _far;

		private bool _active;

		private bool _inShop;

		private int _floor;

		private bool _fog;

		private FogMode _fogMode;

		private float _fogDensity;

		private Color _fogColor;

		private EnvSetup? FloorEnvironment
		{
			get
			{
				if (_later.TryGetValue(_floor, out EnvSetup value))
				{
					return value;
				}
				EnvSetup result;
				switch (_floor)
				{
				case 1:
					result = _canyon;
					break;
				case 2:
					result = _forest;
					break;
				case 3:
				case 4:
					result = _swamp;
					break;
				case 5:
					result = _mountain;
					break;
				case 6:
					result = _sanctum;
					break;
				default:
					result = _arena;
					break;
				}
				return result;
			}
		}

		public string? EnvironmentOverride
		{
			get
			{
				if (!_active)
				{
					return null;
				}
				if (!_inShop)
				{
					return FloorEnvironment?.m_name;
				}
				return "brom8.beyond.stars";
			}
		}

		public BeyondAtmosphere(TrialWorld world)
		{
			_world = world;
		}

		public void LateUpdate()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_047e: Unknown result type (might be due to invalid IL or missing references)
			//IL_048b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0659: Unknown result type (might be due to invalid IL or missing references)
			//IL_059f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_060d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0553: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_0560: Unknown result type (might be due to invalid IL or missing references)
			//IL_0565: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			BeyondPlugin? instance = BeyondPlugin.Instance;
			bool flag = instance != null && instance.Runtime?.Realm?.Inside == true;
			if (!((Object)(object)localPlayer != (Object)null) || !(_world.IsBeyond(((Component)localPlayer).transform.position) || flag))
			{
				Restore();
			}
			else
			{
				if ((Object)(object)EnvMan.instance == (Object)null)
				{
					return;
				}
				if ((Object)(object)_manager != (Object)(object)EnvMan.instance)
				{
					_manager = EnvMan.instance;
					EnvSetup source = (from e in _manager.m_environments
						where e.m_name.IndexOf("mist", StringComparison.OrdinalIgnoreCase) >= 0
						orderby e.m_fogDensityDay descending
						select e).FirstOrDefault() ?? _manager.m_environments.First();
					_arena = Create(source, "brom8.beyond.island", shop: false);
					_shop = Create(source, "brom8.beyond.stars", shop: true);
					_canyon = CreateCanyon(source);
					_forest = CreateForest(source);
					_swamp = CreateSwamp(source);
					_manager.m_environments.Add(_arena);
					_manager.m_environments.Add(_shop);
					_manager.m_environments.Add(_canyon);
					_manager.m_environments.Add(_forest);
					_manager.m_environments.Add(_swamp);
					_mountain = CreateMountain(source, sanctum: false);
					_sanctum = CreateMountain(source, sanctum: true);
					_manager.m_environments.Add(_mountain);
					_manager.m_environments.Add(_sanctum);
					_later.Clear();
					for (int num = 7; num <= 20; num++)
					{
						EnvSetup val;
						if ((uint)(num - 13) <= 1u)
						{
							val = CreateMountain(source, sanctum: false);
						}
						else
						{
							EnvSetup val2;
							if (((uint)(num - 7) <= 1u || (uint)(num - 11) <= 1u) ? true : false)
							{
								val2 = CreateCanyon(source);
							}
							else
							{
								bool flag2 = ((num == 9 || num == 17) ? true : false);
								val2 = (flag2 ? CreateForest(source) : CreateMountain(source, sanctum: true));
							}
							val = val2;
						}
						EnvSetup val3 = val;
						val3.m_name = "brom8.beyond.floor" + num;
						if ((uint)(num - 13) <= 1u)
						{
							val3.m_snowBuildup = 1f;
							val3.m_fogDensityDay = (val3.m_fogDensityNight = 0.008f);
						}
						if (((uint)(num - 11) <= 1u || num == 18) ? true : false)
						{
							val3.m_ambColorDay = (val3.m_ambColorNight = new Color(0.43f, 0.22f, 0.16f));
						}
						_later.Add(num, val3);
						_manager.m_environments.Add(val3);
					}
				}
				if (!_active)
				{
					_fog = RenderSettings.fog;
					_fogMode = RenderSettings.fogMode;
					_fogDensity = RenderSettings.fogDensity;
					_fogColor = RenderSettings.fogColor;
				}
				_active = true;
				_inShop = !flag && _world.IsShop(((Component)localPlayer).transform.position);
				_floor = (flag ? BeyondPlugin.Instance.Runtime.Realm.EnvironmentFloor : _world.SelectedFloor);
				_mist.Update(!_inShop && _floor == 0, _world.Arena);
				BeyondSnow snow = _snow;
				bool flag3 = !_inShop;
				if (flag3)
				{
					int floor = _floor;
					bool flag4 = (uint)(floor - 13) <= 1u;
					flag3 = flag4;
				}
				snow.Update(flag3, ((Component)localPlayer).transform.position);
				EnvSetup val4 = (_inShop ? _shop : FloorEnvironment);
				Color val5 = val4.m_fogColorDay;
				if (flag && SharedRealmWorld.ContainsPreview(((Component)localPlayer).transform.position))
				{
					float num2 = ((Component)localPlayer).transform.position.z - SharedRealmWorld.PreviewOrigin.z;
					int num3 = LandscapePreviewLayout.Section(num2);
					if (num3 > 0)
					{
						int num4 = LandscapePreviewLayout.EnvironmentFloor((float)(num3 * 128 - 65));
						EnvSetup value;
						EnvSetup val = (EnvSetup)((!_later.TryGetValue(num4, out value)) ? (num4 switch
						{
							1 => _canyon, 
							2 => _forest, 
							3 => _swamp, 
							6 => _sanctum, 
							_ => _mountain, 
						}) : value);
						EnvSetup val6 = val;
						if (val6 != null)
						{
							val5 = Color.Lerp(val6.m_fogColorDay, val5, LandscapePreviewLayout.Transition(num2));
						}
					}
				}
				Camera main = Camera.main;
				if ((Object)(object)main != (Object)(object)_camera)
				{
					RestoreCamera();
					_camera = main;
					if ((Object)(object)_camera != (Object)null)
					{
						_clear = _camera.clearFlags;
						_background = _camera.backgroundColor;
						_far = _camera.farClipPlane;
					}
				}
				if ((Object)(object)_camera != (Object)null)
				{
					_camera.clearFlags = (CameraClearFlags)2;
					_camera.backgroundColor = (Color)((_inShop || _floor == 0) ? new Color(0.009f, 0.006f, 0.022f) : val5);
					_camera.farClipPlane = (flag ? 650 : (_inShop ? 90 : ((_floor == 0) ? 160 : 210)));
				}
				RenderSettings.fog = true;
				RenderSettings.fogMode = (FogMode)3;
				RenderSettings.fogColor = val5;
				RenderSettings.fogDensity = (flag ? 0.0025f : val4.m_fogDensityDay);
			}
		}

		private static EnvSetup CreateCanyon(EnvSetup source)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			EnvSetup obj = Create(source, "brom8.beyond.canyon", shop: false);
			obj.m_alwaysDark = false;
			obj.m_ambColorDay = (obj.m_ambColorNight = new Color(0.68f, 0.46f, 0.29f));
			obj.m_fogColorDay = (obj.m_fogColorMorning = (obj.m_fogColorEvening = (obj.m_fogColorNight = new Color(0.64f, 0.39f, 0.18f))));
			obj.m_fogColorSunDay = (obj.m_fogColorSunMorning = (obj.m_fogColorSunEvening = (obj.m_fogColorSunNight = obj.m_fogColorDay)));
			obj.m_fogDensityDay = (obj.m_fogDensityMorning = (obj.m_fogDensityEvening = (obj.m_fogDensityNight = 0.009f)));
			obj.m_sunColorDay = (obj.m_sunColorMorning = (obj.m_sunColorEvening = (obj.m_sunColorNight = new Color(1f, 0.75f, 0.42f))));
			obj.m_lightIntensityDay = (obj.m_lightIntensityNight = 0.75f);
			return obj;
		}

		private static EnvSetup CreateForest(EnvSetup source)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			EnvSetup obj = Create(source, "brom8.beyond.forest", shop: false);
			obj.m_alwaysDark = false;
			obj.m_ambColorDay = (obj.m_ambColorNight = new Color(0.34f, 0.42f, 0.32f));
			obj.m_fogColorDay = (obj.m_fogColorMorning = (obj.m_fogColorEvening = (obj.m_fogColorNight = new Color(0.08f, 0.14f, 0.12f))));
			obj.m_fogColorSunDay = (obj.m_fogColorSunMorning = (obj.m_fogColorSunEvening = (obj.m_fogColorSunNight = obj.m_fogColorDay)));
			obj.m_fogDensityDay = (obj.m_fogDensityMorning = (obj.m_fogDensityEvening = (obj.m_fogDensityNight = 0.012f)));
			obj.m_sunColorDay = (obj.m_sunColorMorning = (obj.m_sunColorEvening = (obj.m_sunColorNight = new Color(0.66f, 0.76f, 0.52f))));
			obj.m_lightIntensityDay = (obj.m_lightIntensityNight = 0.6f);
			return obj;
		}

		private static EnvSetup CreateSwamp(EnvSetup source)
		{
			//IL_001d: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			EnvSetup obj = Create(source, "brom8.beyond.swamp", shop: false);
			obj.m_ambColorDay = (obj.m_ambColorNight = new Color(0.25f, 0.31f, 0.16f));
			obj.m_fogColorDay = (obj.m_fogColorMorning = (obj.m_fogColorEvening = (obj.m_fogColorNight = new Color(0.06f, 0.1f, 0.045f))));
			obj.m_fogColorSunDay = (obj.m_fogColorSunMorning = (obj.m_fogColorSunEvening = (obj.m_fogColorSunNight = obj.m_fogColorDay)));
			obj.m_fogDensityDay = (obj.m_fogDensityMorning = (obj.m_fogDensityEvening = (obj.m_fogDensityNight = 0.018f)));
			obj.m_sunColorDay = (obj.m_sunColorMorning = (obj.m_sunColorEvening = (obj.m_sunColorNight = new Color(0.45f, 0.5f, 0.22f))));
			obj.m_lightIntensityDay = (obj.m_lightIntensityNight = 0.38f);
			return obj;
		}

		private static EnvSetup CreateMountain(EnvSetup source, bool sanctum)
		{
			//IL_0047: 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_004c: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00c9: 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_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: 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)
			EnvSetup obj = Create(source, sanctum ? "brom8.beyond.sanctum" : "brom8.beyond.mountain", shop: false);
			obj.m_alwaysDark = sanctum;
			obj.m_ambColorDay = (obj.m_ambColorNight = (sanctum ? new Color(0.27f, 0.31f, 0.43f) : new Color(0.57f, 0.65f, 0.78f)));
			obj.m_fogColorDay = (obj.m_fogColorMorning = (obj.m_fogColorEvening = (obj.m_fogColorNight = (sanctum ? new Color(0.055f, 0.075f, 0.13f) : new Color(0.31f, 0.41f, 0.55f)))));
			obj.m_fogColorSunDay = (obj.m_fogColorSunMorning = (obj.m_fogColorSunEvening = (obj.m_fogColorSunNight = obj.m_fogColorDay)));
			obj.m_fogDensityDay = (obj.m_fogDensityMorning = (obj.m_fogDensityEvening = (obj.m_fogDensityNight = (sanctum ? 0.012f : 0.008f))));
			obj.m_sunColorDay = (obj.m_sunColorMorning = (obj.m_sunColorEvening = (obj.m_sunColorNight = new Color(0.68f, 0.78f, 1f))));
			obj.m_lightIntensityDay = (obj.m_lightIntensityNight = (sanctum ? 0.45f : 0.8f));
			return obj;
		}

		private static EnvSetup Create(EnvSetup source, string name, bool shop)
		{
			//IL_00be: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_00f0: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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_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_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			EnvSetup obj = source.Clone();
			obj.m_name = name;
			obj.m_default = false;
			obj.m_isWet = (obj.m_isCold = (obj.m_isColdAtNight = (obj.m_isFreezing = (obj.m_isFreezingAtNight = false))));
			obj.m_snowBuildup = 0f;
			obj.m_alwaysDark = true;
			obj.m_envObject = null;
			obj.m_psystems = Array.Empty<GameObject>();
			obj.m_ambientLoop = null;
			obj.m_ambientList = "";
			obj.m_rainCloudAlpha = 0f;
			obj.m_windMin = (obj.m_windMax = 0f);
			obj.m_ambColorDay = (obj.m_ambColorNight = (shop ? new Color(0.45f, 0.4f, 0.55f) : new Color(0.28f, 0.24f, 0.4f)));
			obj.m_fogColorDay = (obj.m_fogColorMorning = (obj.m_fogColorEvening = (obj.m_fogColorNight = new Color(0.025f, 0.018f, 0.055f))));
			obj.m_fogColorSunDay = (obj.m_fogColorSunMorning = (obj.m_fogColorSunEvening = (obj.m_fogColorSunNight = obj.m_fogColorDay)));
			float fogDensityNight = (shop ? 0.002f : Mathf.Max(0.018f, source.m_fogDensityDay * 0.5f));
			obj.m_fogDensityDay = (obj.m_fogDensityMorning = (obj.m_fogDensityEvening = (obj.m_fogDensityNight = fogDensityNight)));
			obj.m_sunColorDay = (obj.m_sunColorMorning = (obj.m_sunColorEvening = (obj.m_sunColorNight = new Color(0.3f, 0.25f, 0.45f))));
			obj.m_lightIntensityDay = (obj.m_lightIntensityNight = (shop ? 0.3f : 0.15f));
			return obj;
		}

		private void RestoreCamera()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_camera != (Object)null)
			{
				_camera.clearFlags = _clear;
				_camera.backgroundColor = _background;
				_camera.farClipPlane = _far;
			}
			_camera = null;
		}

		private void Restore()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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)
			if (_active)
			{
				_mist.Update(active: false, Vector3.zero);
				_snow.Update(active: false, Vector3.zero);
				RestoreCamera();
				RenderSettings.fog = _fog;
				RenderSettings.fogMode = _fogMode;
				RenderSettings.fogDensity = _fogDensity;
				RenderSettings.fogColor = _fogColor;
				_active = false;
			}
		}

		public void Dispose()
		{
			Restore();
			_mist.Dispose();
			_snow.Dispose();
			if ((Object)(object)_manager != (Object)null)
			{
				foreach (EnvSetup value in _later.Values)
				{
					_manager.m_environments.Remove(value);
				}
			}
			_later.Clear();
			if ((Object)(object)_manager != (Object)null)
			{
				if (_arena != null)
				{
					_manager.m_environments.Remove(_arena);
				}
				if (_shop != null)
				{
					_manager.m_environments.Remove(_shop);
				}
				if (_canyon != null)
				{
					_manager.m_environments.Remove(_canyon);
				}
				if (_forest != null)
				{
					_manager.m_environments.Remove(_forest);
				}
				if (_swamp != null)
				{
					_manager.m_environments.Remove(_swamp);
				}
			}
			if ((Object)(object)_manager != (Object)null)
			{
				if (_mountain != null)
				{
					_manager.m_environments.Remove(_mountain);
				}
				if (_sanctum != null)
				{
					_manager.m_environments.Remove(_sanctum);
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnvMan), "GetEnvironmentOverride")]
	internal static class BeyondEnvironmentPatch
	{
		private static void Postfix(ref string __result)
		{
			string text = BeyondPlugin.Instance?.Runtime?.Client?.Atmosphere.EnvironmentOverride;
			if (text != null)
			{
				__result = text;
			}
		}
	}
	internal sealed class BeyondIslandMist : IDisposable
	{
		private const int MaximumParticles = 512;

		private GameObject? _root;

		private ParticleSystem? _particles;

		private Vector3 _center;

		private bool _active;

		private bool _warned;

		private float _nextSearch;

		private float _accumulator;

		private float _perSecond = 25f;

		private MinMaxGradient _color;

		public void Update(bool active, Vector3 center)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			if (!active)
			{
				if (_active && (Object)(object)_particles != (Object)null)
				{
					_particles.Stop(true, (ParticleSystemStopBehavior)0);
					_root.SetActive(false);
				}
				_active = false;
				_accumulator = 0f;
				return;
			}
			if ((Object)(object)_particles == (Object)null)
			{
				if (Time.unscaledTime < _nextSearch)
				{
					return;
				}
				_nextSearch = Time.unscaledTime + 10f;
				ParticleMist val = FindSource();
				if ((Object)(object)val == (Object)null || !Create(val))
				{
					if (!_warned)
					{
						Debug.LogWarning((object)"[Beyond] Native ParticleMist visual is unavailable; arena uses environment haze only. Visible mist needs a supported native particle material.");
						_warned 

plugins/Beyond.Core.dll

Decompiled 5 hours ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Brom8")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.32.1.0")]
[assembly: AssemblyInformationalVersion("0.32.1+7631678d0972989b79d54fd3945dbfa47aa166be")]
[assembly: AssemblyProduct("Beyond.Core")]
[assembly: AssemblyTitle("Beyond.Core")]
[assembly: AssemblyVersion("0.32.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Beyond.Core
{
	[Serializable]
	public sealed class BankAccount
	{
		public string character = "";

		public int balance;

		public long revision;
	}
	[Serializable]
	public sealed class BankTransfer
	{
		public string character = "";

		public string transaction = "";

		public string kind = "";

		public string state = "waiting";

		public int amount;

		public int moved;

		public bool confirmed;

		public int beforeBalance;

		public long revision;
	}
	public sealed class BankLedger
	{
		public const int MaximumBalance = 1000000000;

		private readonly List<BankAccount> _accounts;

		private readonly List<BankTransfer> _transfers;

		public BankLedger(List<BankAccount> accounts, List<BankTransfer> transfers)
		{
			_accounts = accounts ?? throw new ArgumentNullException("accounts");
			_transfers = transfers ?? throw new ArgumentNullException("transfers");
			if (accounts.Any((BankAccount a) => a == null || string.IsNullOrEmpty(a.character) || a.balance < 0 || a.balance > 1000000000 || a.revision < 0 || a.revision == long.MaxValue) || accounts.Select((BankAccount a) => a.character).Distinct<string>(StringComparer.Ordinal).Count() != accounts.Count || transfers.Any((BankTransfer t) => t == null || string.IsNullOrEmpty(t.character) || !Guid.TryParseExact(t.transaction, "N", out var _) || (t.kind != "deposit" && t.kind != "withdraw") || !SupportedAmount(t.amount) || t.revision < 0 || t.revision == long.MaxValue || t.beforeBalance < 0 || t.beforeBalance > 1000000000 || (t.state != "waiting" && t.state != "settled") || t.moved < 0 || t.moved > t.amount || (t.kind == "deposit" && t.moved != 0 && t.moved != t.amount) || (t.state == "waiting" && (t.moved != 0 || t.confirmed)) || !accounts.Any((BankAccount a) => a.character == t.character)) || transfers.Select((BankTransfer t) => t.transaction).Distinct<string>(StringComparer.Ordinal).Count() != transfers.Count || transfers.Where((BankTransfer t) => t.state == "waiting").GroupBy<BankTransfer, string>((BankTransfer t) => t.character, StringComparer.Ordinal).Any((IGrouping<string, BankTransfer> g) => g.Count() > 1))
			{
				throw new ArgumentException("Invalid bank ledger; preserve the original journal.");
			}
			foreach (BankTransfer transfer in transfers.Where((BankTransfer t) => t.state == "waiting"))
			{
				if (!_accounts.Any((BankAccount a) => a.character == transfer.character) || Balance(transfer.character) > 1000000000 - transfer.amount)
				{
					throw new ArgumentException("Invalid bank reservation headroom.");
				}
			}
		}

		public int Balance(string character)
		{
			return _accounts.Find((BankAccount a) => a.character == character)?.balance ?? 0;
		}

		public BankTransfer? Pending(string character)
		{
			return _transfers.Find((BankTransfer t) => t.character == character && t.state == "waiting");
		}

		public BankTransfer? Find(string character, string transaction)
		{
			return _transfers.Find((BankTransfer t) => t.character == character && t.transaction == transaction);
		}

		public static bool SupportedAmount(int amount)
		{
			switch (amount)
			{
			case 100:
			case 500:
			case 1000:
			case 2000:
				return true;
			default:
				return false;
			}
		}

		public bool Synchronize(string character, int balance, long revision)
		{
			if (string.IsNullOrEmpty(character) || balance < 0 || balance > 1000000000 || revision < 0 || revision == long.MaxValue || Pending(character) != null)
			{
				return false;
			}
			BankAccount bankAccount = _accounts.Find((BankAccount a) => a.character == character);
			if (bankAccount == null)
			{
				bankAccount = new BankAccount
				{
					character = character
				};
				_accounts.Add(bankAccount);
			}
			bankAccount.balance = balance;
			bankAccount.revision = revision;
			return true;
		}

		public bool TryAuthorize(string character, string transaction, string kind, int amount, out BankTransfer? transfer, out string reason)
		{
			transfer = null;
			reason = "Invalid bank request.";
			if (string.IsNullOrEmpty(character) || !Guid.TryParseExact(transaction, "N", out var _) || (kind != "deposit" && kind != "withdraw") || !SupportedAmount(amount))
			{
				return false;
			}
			BankTransfer bankTransfer = _transfers.Find((BankTransfer t) => t.transaction == transaction);
			if (bankTransfer != null)
			{
				if (bankTransfer.character != character || bankTransfer.kind != kind || bankTransfer.amount != amount)
				{
					return false;
				}
				transfer = bankTransfer;
				reason = "";
				return true;
			}
			if (Pending(character) != null)
			{
				reason = "Finish the pending bank transfer first.";
				return false;
			}
			BankAccount bankAccount = _accounts.Find((BankAccount a) => a.character == character);
			int num = bankAccount?.balance ?? 0;
			if (bankAccount != null && bankAccount.revision >= 9223372036854775806L)
			{
				reason = "Bank revision limit reached; preserve the account for recovery.";
				return false;
			}
			if (kind == "withdraw" && num < amount)
			{
				reason = "Not enough coins in your bank.";
				return false;
			}
			if (kind == "deposit" && num > 1000000000 - amount)
			{
				reason = "Bank balance limit reached.";
				return false;
			}
			if (bankAccount == null)
			{
				bankAccount = new BankAccount
				{
					character = character
				};
				_accounts.Add(bankAccount);
			}
			if (kind == "withdraw")
			{
				bankAccount.balance -= amount;
			}
			transfer = new BankTransfer
			{
				character = character,
				transaction = transaction,
				kind = kind,
				amount = amount,
				beforeBalance = num,
				revision = bankAccount.revision
			};
			_transfers.Add(transfer);
			reason = "";
			return true;
		}

		public bool Settle(BankTransfer transfer, int moved)
		{
			if (!_transfers.Contains(transfer) || moved < 0 || moved > transfer.amount || (transfer.kind == "deposit" && moved != 0 && moved != transfer.amount))
			{
				return false;
			}
			if (transfer.state == "settled")
			{
				return transfer.moved == moved;
			}
			BankAccount bankAccount = _accounts.Find((BankAccount a) => a.character == transfer.character) ?? throw new InvalidOperationException("Missing bank account.");
			int num = ((transfer.kind == "deposit") ? moved : (transfer.amount - moved));
			if (bankAccount.balance > 1000000000 - num)
			{
				return false;
			}
			bankAccount.balance += num;
			transfer.moved = moved;
			transfer.state = "settled";
			bankAccount.revision = transfer.revision + 1;
			return true;
		}

		public void Trim(string character)
		{
			BankTransfer[] array = _transfers.Where((BankTransfer t) => t.character == character && t.state == "settled" && t.confirmed).ToArray();
			foreach (BankTransfer item in array.Take(Math.Max(0, array.Length - 256)))
			{
				_transfers.Remove(item);
			}
		}
	}
	public static class BankReceipt
	{
		public static bool TryResult(string receipt, out int moved)
		{
			string text = (receipt.StartsWith("done:", StringComparison.Ordinal) ? receipt.Substring(5) : (receipt.StartsWith("settled:", StringComparison.Ordinal) ? receipt.Substring(8) : null));
			moved = 0;
			if (text != null && int.TryParse(text, NumberStyles.None, CultureInfo.InvariantCulture, out moved) && moved >= 0)
			{
				return moved <= 2000;
			}
			return false;
		}

		public static bool ResolvesIntent(string receipt, string kind, int amount)
		{
			if ((kind == "deposit" || kind == "withdraw") && BankLedger.SupportedAmount(amount) && TryResult(receipt, out var moved) && moved <= amount)
			{
				if (!(kind == "withdraw") && moved != 0)
				{
					return moved == amount;
				}
				return true;
			}
			return false;
		}
	}
	[Serializable]
	public sealed class CharacterAccount
	{
		public int schema = 1;

		public string epoch = "";

		public int highest = -1;

		public bool allowLegacyProgress = true;

		public int balance;

		public long revision;

		public long deaths;

		public long bossKills;

		public string trackingSince = "";

		public bool Valid
		{
			get
			{
				if (schema == 1 && Guid.TryParseExact(epoch, "N", out var _) && highest >= -1 && highest <= 20 && balance >= 0 && balance <= 1000000000 && revision >= 0 && revision < long.MaxValue && deaths >= 0 && bossKills >= 0 && trackingSince != null)
				{
					return trackingSince.Length <= 40;
				}
				return false;
			}
		}

		public static CharacterAccount Create(int highest = -1)
		{
			return new CharacterAccount
			{
				epoch = Guid.NewGuid().ToString("N"),
				highest = highest
			};
		}

		public bool Complete(string expectedEpoch, int floor)
		{
			if (!Valid || epoch != expectedEpoch || floor < 0 || floor > 20 || floor <= highest)
			{
				return false;
			}
			highest = floor;
			return true;
		}

		public bool Reset(string expectedEpoch)
		{
			if (!Valid || epoch != expectedEpoch)
			{
				return false;
			}
			epoch = Guid.NewGuid().ToString("N");
			highest = -1;
			allowLegacyProgress = false;
			return true;
		}

		public bool ApplyBank(int before, long expectedRevision, string kind, int amount, int moved)
		{
			if (!Valid || revision >= 9223372036854775806L || balance != before || revision != expectedRevision || (amount != 500 && amount != 2000) || (kind != "deposit" && kind != "withdraw") || moved < 0 || moved > amount || (kind == "deposit" && moved != 0 && moved != amount))
			{
				return false;
			}
			long num = (long)balance + (long)((kind == "deposit") ? moved : (-moved));
			if (num < 0 || num > 1000000000)
			{
				return false;
			}
			balance = (int)num;
			revision++;
			return true;
		}
	}
	public static class CleanupSequence
	{
		public static void Run(params Action[] actions)
		{
			List<Exception> list = null;
			foreach (Action action in actions)
			{
				try
				{
					action();
				}
				catch (Exception item)
				{
					(list ?? (list = new List<Exception>())).Add(item);
				}
			}
			if (list != null)
			{
				throw new AggregateException("One or more cleanup operations failed.", list);
			}
		}
	}
	public static class CoinSplit
	{
		public static IReadOnlyDictionary<string, int> Divide(int pool, IEnumerable<string> survivors)
		{
			if (pool < 0)
			{
				throw new ArgumentOutOfRangeException("pool");
			}
			if (survivors == null)
			{
				throw new ArgumentNullException("survivors");
			}
			string[] array = survivors.ToArray();
			if (array.Length == 0 || array.Any(string.IsNullOrWhiteSpace))
			{
				throw new ArgumentException("At least one valid survivor ID is required.", "survivors");
			}
			if (array.Distinct<string>(StringComparer.Ordinal).Count() != array.Length)
			{
				throw new ArgumentException("Survivor IDs must be unique.", "survivors");
			}
			Array.Sort(array, (IComparer<string>?)StringComparer.Ordinal);
			Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal);
			int num = pool / array.Length;
			int num2 = pool % array.Length;
			for (int i = 0; i < array.Length; i++)
			{
				dictionary.Add(array[i], num + ((i < num2) ? 1 : 0));
			}
			return new ReadOnlyDictionary<string, int>(dictionary);
		}
	}
	[Serializable]
	public sealed class CommerceOperation
	{
		public string id = "";

		public string character = "";

		public string kind = "";

		public string run = "";

		public string product = "";

		public string source = "";

		public string state = "queued";

		public long world;

		public long revision;

		public int floor;

		public int amount;

		public int bankPart;

		public int carriedPart;

		public int quantity;

		public int beforeBalance;

		public bool confirmed;

		public bool IsDebit
		{
			get
			{
				if (!(kind == "entry"))
				{
					return kind == "purchase";
				}
				return true;
			}
		}

		public bool IsCredit
		{
			get
			{
				if (!(kind == "reward"))
				{
					return kind == "refund";
				}
				return true;
			}
		}

		public bool IsStatistic
		{
			get
			{
				if (!(kind == "death"))
				{
					return kind == "bosskill";
				}
				return true;
			}
		}

		public int AfterBalance => beforeBalance + (IsDebit ? (-bankPart) : (IsCredit ? bankPart : 0));

		public bool Valid
		{
			get
			{
				if (Guid.TryParseExact(id, "N", out var result) && !string.IsNullOrEmpty(character) && character.Length <= 32 && (IsDebit || IsCredit || IsStatistic) && (state == "queued" || state == "waiting" || state == "done" || state == "declined") && floor >= 0 && floor <= 20 && amount >= 0 && amount <= 1000000 && bankPart >= 0 && carriedPart >= 0 && bankPart <= amount && carriedPart <= amount && quantity >= 0 && quantity <= 9999 && product != null && product.Length <= 128 && source != null && source.Length <= 100 && run != null && (run.Length == 0 || Guid.TryParseExact(run, "N", out result)) && beforeBalance >= 0 && beforeBalance <= 1000000000 && revision >= 0 && revision < 9223372036854775806L && (kind != "purchase" || (product.Length > 0 && quantity > 0)) && (!IsStatistic || (amount == 0 && bankPart == 0 && carriedPart == 0)) && (state == "queued" || IsStatistic || bankPart + carriedPart == amount) && (kind != "reward" || state == "queued" || carriedPart == 0))
				{
					if (!(state == "queued"))
					{
						if (AfterBalance >= 0)
						{
							return AfterBalance <= 1000000000;
						}
						return false;
					}
					return true;
				}
				return false;
			}
		}

		public bool Authorize(CharacterAccount account)
		{
			if (state != "queued" || !Valid || !account.Valid || account.revision >= 9223372036854775805L)
			{
				return false;
			}
			if (IsDebit)
			{
				bankPart = Math.Min(account.balance, amount);
				carriedPart = amount - bankPart;
			}
			else if (kind == "reward")
			{
				bankPart = amount;
				carriedPart = 0;
			}
			if (IsCredit && (long)account.balance + (long)bankPart > 1000000000)
			{
				return false;
			}
			beforeBalance = account.balance;
			revision = account.revision;
			state = "waiting";
			return Valid;
		}

		public bool Apply(CharacterAccount account)
		{
			if (!Valid || state != "waiting" || !account.Valid || account.balance != beforeBalance || account.revision != revision)
			{
				return false;
			}
			if ((kind == "death" && account.deaths == long.MaxValue) || (kind == "bosskill" && account.bossKills == long.MaxValue))
			{
				return false;
			}
			account.balance = AfterBalance;
			account.revision++;
			if (kind == "death")
			{
				account.deaths++;
			}
			if (kind == "bosskill")
			{
				account.bossKills++;
			}
			return true;
		}

		public bool Matches(CommerceOperation other)
		{
			if (id == other.id && character == other.character && world == other.world && kind == other.kind && run == other.run && floor == other.floor && amount == other.amount && bankPart == other.bankPart && carriedPart == other.carriedPart && product == other.product && quantity == other.quantity && source == other.source && beforeBalance == other.beforeBalance)
			{
				return revision == other.revision;
			}
			return false;
		}
	}
	public sealed class DungeonInstance
	{
		public FloorAttempt Attempt { get; }

		public int Slot { get; }

		public Guid RunId => Attempt.RunId;

		public int MemberCount { get; internal set; }

		internal DungeonInstance(FloorAttempt attempt, int slot)
		{
			Attempt = attempt;
			Slot = slot;
		}
	}
	public sealed class DungeonDirectory
	{
		public const int HardInstanceLimit = 4;

		private readonly Dictionary<Guid, DungeonInstance> _instances = new Dictionary<Guid, DungeonInstance>();

		private readonly Dictionary<string, Guid> _members = new Dictionary<string, Guid>(StringComparer.Ordinal);

		public IReadOnlyCollection<DungeonInstance> Instances => _instances.Values;

		public bool TryOpen(FloorRules rules, double now, int maxInstances, out DungeonInstance? instance, int? preferredSlot = null)
		{
			if (rules == null)
			{
				throw new ArgumentNullException("rules");
			}
			if (maxInstances < 1 || maxInstances > 4)
			{
				throw new ArgumentOutOfRangeException("maxInstances");
			}
			instance = null;
			if (_instances.Count >= maxInstances || _instances.Values.Any((DungeonInstance i) => i.Attempt.EntrancePortalOpen))
			{
				return false;
			}
			int slot = preferredSlot.GetValueOrDefault();
			if (slot < 0 || slot >= 4)
			{
				throw new ArgumentOutOfRangeException("preferredSlot");
			}
			if (preferredSlot.HasValue && _instances.Values.Any((DungeonInstance i) => i.Slot == slot))
			{
				return false;
			}
			for (; _instances.Values.Any((DungeonInstance i) => i.Slot == slot); slot++)
			{
			}
			instance = new DungeonInstance(new FloorAttempt(rules, now), slot);
			_instances.Add(instance.RunId, instance);
			return true;
		}

		public DungeonInstance? Find(Guid id)
		{
			if (!_instances.TryGetValue(id, out DungeonInstance value))
			{
				return null;
			}
			return value;
		}

		public DungeonInstance? FindForPlayer(string player)
		{
			ValidatePlayer(player);
			if (!_members.TryGetValue(player, out var value))
			{
				return null;
			}
			return Find(value);
		}

		public bool TryReserve(Guid run, string player, double now, double pressedAt)
		{
			ValidatePlayer(player);
			DungeonInstance dungeonInstance = Find(run);
			if (_members.ContainsKey(player) || dungeonInstance == null || !dungeonInstance.Attempt.ReserveEntry(player, now, pressedAt))
			{
				return false;
			}
			_members.Add(player, run);
			dungeonInstance.MemberCount++;
			return true;
		}

		public bool ReleasePlayer(string player)
		{
			ValidatePlayer(player);
			DungeonInstance dungeonInstance = FindForPlayer(player);
			if (dungeonInstance == null)
			{
				return false;
			}
			dungeonInstance.Attempt.TryRemove(player);
			_members.Remove(player);
			dungeonInstance.MemberCount--;
			return true;
		}

		public bool TryRelease(Guid run)
		{
			DungeonInstance dungeonInstance = Find(run);
			if (dungeonInstance == null || dungeonInstance.MemberCount != 0)
			{
				return false;
			}
			if (dungeonInstance.Attempt.Phase != FloorPhase.Closed && !dungeonInstance.Attempt.TryClose(protectedBelongingsResolved: true))
			{
				return false;
			}
			return _instances.Remove(run);
		}

		private static void ValidatePlayer(string player)
		{
			if (string.IsNullOrWhiteSpace(player))
			{
				throw new ArgumentException("Player ID is required.", "player");
			}
		}
	}
	public sealed class EncounterProgress
	{
		public int Total { get; }

		public int CompletedStages { get; private set; }

		public bool Stopped { get; private set; }

		public bool Complete => CompletedStages == Total;

		public EncounterProgress(int total)
		{
			if (total <= 0)
			{
				throw new ArgumentOutOfRangeException("total");
			}
			Total = total;
		}

		public void CompleteStage()
		{
			if (!Stopped && !Complete)
			{
				CompletedStages++;
			}
		}

		public void Stop()
		{
			Stopped = true;
		}

		public string Describe(Func<int, string> title)
		{
			if (!Complete)
			{
				if (!Stopped)
				{
					return title(CompletedStages) + "\nSTAGES CLEARED " + CompletedStages + " / " + Total;
				}
				return "FLOOR ENDED";
			}
			return "FLOOR COMPLETE";
		}
	}
	public static class EnemyLootPolicy
	{
		public static bool Suppress(bool managedPrefab, bool namedTarget, string? run)
		{
			Guid result;
			if (managedPrefab && !namedTarget)
			{
				return Guid.TryParseExact(run, "N", out result);
			}
			return false;
		}
	}
	public enum FloorPhase
	{
		Admission,
		Arriving,
		Active,
		Shop,
		Failed,
		Closed
	}
	public sealed class FloorAttempt
	{
		private readonly Dictionary<string, bool> _participants = new Dictionary<string, bool>(StringComparer.Ordinal);

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

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

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

		private IReadOnlyDictionary<string, int>? _allocations;

		private readonly double _entryClosesAt;

		private readonly double _openedAt;

		private double _combatStartsAt;

		private double _lastObservedTime;

		public Guid RunId { get; }

		public FloorRules Rules { get; }

		public FloorPhase Phase { get; private set; }

		public bool EntrancePortalOpen => Phase == FloorPhase.Admission;

		public bool ShopExitOpen => Phase == FloorPhase.Shop;

		public string ObjectiveLabel
		{
			get
			{
				if (Phase != FloorPhase.Active)
				{
					return string.Empty;
				}
				if (Rules.Objective != FloorObjective.BossKill)
				{
					return "Survive";
				}
				return "Kill the Undead King";
			}
		}

		public double EntrySecondsRemaining
		{
			get
			{
				if (Phase != FloorPhase.Admission)
				{
					return 0.0;
				}
				return Math.Max(0.0, _entryClosesAt - _lastObservedTime);
			}
		}

		public double ArrivalSecondsRemaining
		{
			get
			{
				if (Phase != FloorPhase.Arriving)
				{
					return 0.0;
				}
				return Math.Max(0.0, _entryClosesAt + Rules.ArrivalGraceSeconds - _lastObservedTime);
			}
		}

		public double SurvivalSecondsRemaining
		{
			get
			{
				if (Rules.Objective == FloorObjective.Survival)
				{
					if (Phase != FloorPhase.Admission && Phase != FloorPhase.Arriving)
					{
						if (Phase != FloorPhase.Active)
						{
							return 0.0;
						}
						return Math.Max(0.0, Rules.SurvivalSeconds - (_lastObservedTime - _combatStartsAt));
					}
					return Rules.SurvivalSeconds;
				}
				return 0.0;
			}
		}

		public int EnemyPressureStage
		{
			get
			{
				if (Phase != FloorPhase.Active)
				{
					return 0;
				}
				return Math.Min(4, 1 + (int)((_lastObservedTime - _combatStartsAt) / Rules.SurvivalSeconds * 4.0));
			}
		}

		public int LivingInside => _participants.Count<KeyValuePair<string, bool>>((KeyValuePair<string, bool> p) => p.Value);

		public int PendingArrivals => _pending.Count;

		public FloorAttempt(FloorRules rules, double openedAt = 0.0)
		{
			Rules = rules ?? throw new ArgumentNullException("rules");
			if (double.IsNaN(openedAt) || double.IsInfinity(openedAt) || openedAt < 0.0)
			{
				throw new ArgumentOutOfRangeException("openedAt");
			}
			_lastObservedTime = openedAt;
			_openedAt = openedAt;
			_entryClosesAt = openedAt + rules.EntryWindowSeconds;
			_combatStartsAt = _entryClosesAt;
			RunId = Guid.NewGuid();
		}

		public bool ReserveEntry(string playerId, double now)
		{
			return ReserveEntry(playerId, now, now);
		}

		public bool ReserveEntry(string playerId, double now, double pressedAt)
		{
			ValidateId(playerId);
			Advance(now);
			if (double.IsNaN(pressedAt) || double.IsInfinity(pressedAt) || pressedAt < _openedAt || pressedAt >= _entryClosesAt || pressedAt > now)
			{
				return false;
			}
			bool flag = Phase == FloorPhase.Arriving && now < _entryClosesAt + Rules.RequestGraceSeconds && now - pressedAt <= Rules.RequestGraceSeconds;
			if ((!EntrancePortalOpen && !flag) || _reservations.Count >= Rules.ParticipantLimit || !_reservations.Add(playerId))
			{
				return false;
			}
			_pending.Add(playerId);
			return true;
		}

		public bool ConfirmArrival(string playerId, double now)
		{
			ValidateId(playerId);
			Advance(now);
			if ((Phase != FloorPhase.Admission && Phase != FloorPhase.Arriving) || !_pending.Remove(playerId))
			{
				return false;
			}
			_participants.Add(playerId, value: true);
			if (Phase == FloorPhase.Arriving && _pending.Count == 0 && now >= _entryClosesAt + Rules.RequestGraceSeconds)
			{
				StartCombat(now);
			}
			return true;
		}

		public bool IsAlive(string playerId)
		{
			bool value;
			return _participants.TryGetValue(playerId, out value) && value;
		}

		public bool TryEnter(string playerId, double now)
		{
			if (ReserveEntry(playerId, now))
			{
				return ConfirmArrival(playerId, now);
			}
			return false;
		}

		public bool TryRemove(string playerId)
		{
			ValidateId(playerId);
			if (Phase != FloorPhase.Admission && Phase != FloorPhase.Arriving && Phase != FloorPhase.Active)
			{
				return false;
			}
			if (!_pending.Remove(playerId) && (!_participants.TryGetValue(playerId, out var value) || !value))
			{
				return false;
			}
			_participants[playerId] = false;
			if (Phase == FloorPhase.Arriving && _pending.Count == 0 && _lastObservedTime >= _entryClosesAt + Rules.RequestGraceSeconds)
			{
				StartCombat(_lastObservedTime);
			}
			if (Phase == FloorPhase.Active && LivingInside == 0)
			{
				Phase = FloorPhase.Failed;
			}
			return true;
		}

		public void Abort()
		{
			if (Phase != FloorPhase.Closed)
			{
				_pending.Clear();
				string[] array = _participants.Keys.ToArray();
				foreach (string key in array)
				{
					_participants[key] = false;
				}
				_allocations = null;
				Phase = FloorPhase.Failed;
			}
		}

		public void Advance(double now)
		{
			if (double.IsNaN(now) || double.IsInfinity(now) || now < _lastObservedTime)
			{
				throw new ArgumentOutOfRangeException("now", "Use nonnegative monotonic host time.");
			}
			_lastObservedTime = now;
			if (Phase == FloorPhase.Admission && now >= _entryClosesAt)
			{
				if (_pending.Count > 0 || now < _entryClosesAt + Rules.RequestGraceSeconds)
				{
					Phase = FloorPhase.Arriving;
				}
				else
				{
					StartCombat(_entryClosesAt + Rules.RequestGraceSeconds);
				}
			}
			if (Phase == FloorPhase.Arriving && _pending.Count == 0 && now >= _entryClosesAt + Rules.RequestGraceSeconds)
			{
				StartCombat(_entryClosesAt + Rules.RequestGraceSeconds);
			}
			if (Phase == FloorPhase.Arriving && now >= _entryClosesAt + Rules.ArrivalGraceSeconds)
			{
				_pending.Clear();
				StartCombat(_entryClosesAt + Rules.ArrivalGraceSeconds);
			}
			if (Rules.Objective == FloorObjective.Survival && Phase == FloorPhase.Active && !(now - _combatStartsAt < Rules.SurvivalSeconds))
			{
				Complete();
			}
		}

		public bool CompleteBoss()
		{
			if (Rules.Objective != FloorObjective.BossKill || Phase != FloorPhase.Active || LivingInside == 0)
			{
				return false;
			}
			Complete();
			return true;
		}

		private void Complete()
		{
			_allocations = CoinSplit.Divide(Rules.CoinPool, from p in _participants
				where p.Value
				select p.Key);
			Phase = FloorPhase.Shop;
		}

		private void StartCombat(double now)
		{
			_combatStartsAt = now;
			Phase = ((LivingInside > 0) ? FloorPhase.Active : FloorPhase.Failed);
		}

		public bool CanUseShop(string playerId)
		{
			ValidateId(playerId);
			if (Phase == FloorPhase.Shop && _allocations != null)
			{
				return _allocations.ContainsKey(playerId);
			}
			return false;
		}

		public IReadOnlyList<int> VisibleShopTabs(string playerId)
		{
			if (!CanUseShop(playerId))
			{
				return Array.Empty<int>();
			}
			return ShopAccess.TabsFor(Rules.Floor);
		}

		public bool TryClaimCoins(string playerId, out int coins)
		{
			coins = 0;
			if (!CanUseShop(playerId) || !_claimed.Add(playerId))
			{
				return false;
			}
			coins = _allocations[playerId];
			return true;
		}

		public bool TryClose(bool protectedBelongingsResolved)
		{
			if ((Phase != FloorPhase.Shop && Phase != FloorPhase.Failed) || !protectedBelongingsResolved)
			{
				return false;
			}
			Phase = FloorPhase.Closed;
			return true;
		}

		private static void ValidateId(string playerId)
		{
			if (string.IsNullOrWhiteSpace(playerId))
			{
				throw new ArgumentException("Player ID is required.", "playerId");
			}
		}
	}
	public static class FloorCatalog
	{
		public const int HighestImplemented = 20;

		public static string Name(int floor)
		{
			return floor switch
			{
				0 => "Trial", 
				1 => "The Hollow Crown", 
				2 => "The Rootbound Hollow", 
				3 => "The Drowned Court", 
				4 => "The Sunken Vigil", 
				5 => "The Shattered Cirque", 
				6 => "The Emberfang Sanctum", 
				7 => "The Thresher's Run", 
				8 => "Crown of Cinders", 
				9 => "The Skybreak Crag", 
				10 => "The Amber Vault", 
				11 => "The Cinder Delta", 
				12 => "The Last Ember", 
				13 => "The White Maw", 
				14 => "The Silent Aurora", 
				15 => "The Runebound Conclave", 
				16 => "The Shattered Oath", 
				17 => "The Blight Orchard", 
				18 => "The Crimson Harvest", 
				19 => "The Forsaken Procession", 
				20 => "The Last Convergence", 
				_ => throw new ArgumentOutOfRangeException("floor"), 
			};
		}

		public static int LootLevel(int floor)
		{
			switch (floor)
			{
			case 0:
				return 1;
			case 1:
			case 2:
				return 19;
			case 3:
			case 4:
				return 43;
			case 5:
			case 6:
				return 77;
			case 7:
			case 8:
				return 97;
			case 9:
			case 10:
				return 130;
			case 11:
			case 12:
				return 181;
			case 13:
			case 14:
				return 246;
			case 15:
			case 16:
			case 17:
			case 18:
			case 19:
			case 20:
				return 246;
			default:
				throw new ArgumentOutOfRangeException("floor");
			}
		}

		public static string Biome(int floor)
		{
			switch (floor)
			{
			case 0:
				return "Meadows";
			case 1:
			case 2:
				return "BlackForest";
			case 3:
			case 4:
				return "Swamp";
			case 5:
			case 6:
				return "Mountain";
			case 7:
			case 8:
				return "Plains";
			case 9:
			case 10:
				return "Mistlands";
			case 11:
			case 12:
				return "AshLands";
			case 13:
			case 14:
			case 15:
			case 16:
			case 17:
			case 18:
			case 19:
			case 20:
				return "DeepNorth";
			default:
				throw new ArgumentOutOfRangeException("floor");
			}
		}

		public static (int X, int Z) LayoutOffset(int floor)
		{
			switch (floor)
			{
			default:
				throw new ArgumentOutOfRangeException("floor");
			case 0:
			case 1:
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
				return (X: 0, Z: floor * 512);
			case 7:
			case 8:
			case 9:
			case 10:
			case 11:
			case 12:
			case 13:
			case 14:
			case 15:
			case 16:
			case 17:
			case 18:
			case 19:
			case 20:
			{
				int num = floor - 7;
				return (X: (num < 7) ? (-2560) : 2560, Z: num % 7 * 512);
			}
			}
		}
	}
	public static class FloorProgression
	{
		public const int KeyPrice = 100;

		public const int KeyStackSize = 999;

		public static bool CanOpen(int floor, int highestCompleted, int highestAvailable)
		{
			if (floor < 0 || floor > 1000 || highestCompleted < -1 || highestCompleted > 1000 || highestAvailable < 0 || highestAvailable > 1000)
			{
				throw new ArgumentOutOfRangeException("floor");
			}
			if (floor != 0)
			{
				if (floor <= highestAvailable)
				{
					return floor <= highestCompleted + 1;
				}
				return false;
			}
			return true;
		}

		public static int RecordCompletion(int highestCompleted, int completedFloor)
		{
			if (highestCompleted < -1 || highestCompleted > 1000 || completedFloor < 0 || completedFloor > 1000)
			{
				throw new ArgumentOutOfRangeException("completedFloor");
			}
			return Math.Max(highestCompleted, completedFloor);
		}
	}
	public readonly struct RouteRoom
	{
		public double X { get; }

		public double Z { get; }

		public double Height { get; }

		public double Radius { get; }

		public RouteRoom(double x, double z, double height, double radius = 11.0)
		{
			X = x;
			Z = z;
			Height = height;
			Radius = radius;
		}
	}
	public sealed class FloorRoute
	{
		public const double PassageHalfWidth = 8.0;

		private static readonly FloorRoute[] Routes = Build();

		public IReadOnlyList<RouteRoom> Rooms { get; }

		public IReadOnlyList<(int A, int B)> Links { get; }

		public IReadOnlyList<int> Targets { get; }

		public string Shape { get; }

		private FloorRoute(string shape, RouteRoom[] rooms, (int, int)[] links, params int[] targets)
		{
			Shape = shape;
			Rooms = Array.AsReadOnly(rooms);
			Links = Array.AsReadOnly(links);
			Targets = Array.AsReadOnly(targets);
		}

		public static FloorRoute For(int floor)
		{
			if (floor < 7 || floor > 20)
			{
				throw new ArgumentOutOfRangeException("floor");
			}
			return Routes[floor - 7];
		}

		public RouteRoom Target(int index)
		{
			return Rooms[Targets[index % Targets.Count]];
		}

		public static bool IsStaged(int floor)
		{
			if (floor != 8)
			{
				return floor == 19;
			}
			return true;
		}

		public double Clearance(double x, double z)
		{
			double num = double.MaxValue;
			foreach (RouteRoom room in Rooms)
			{
				num = Math.Min(num, Math.Sqrt(Squared(x - room.X, z - room.Z)) - room.Radius);
			}
			foreach (var link in Links)
			{
				RouteRoom routeRoom = Rooms[link.A];
				RouteRoom routeRoom2 = Rooms[link.B];
				double num2 = routeRoom2.X - routeRoom.X;
				double num3 = routeRoom2.Z - routeRoom.Z;
				double num4 = Math.Max(0.0, Math.Min(1.0, ((x - routeRoom.X) * num2 + (z - routeRoom.Z) * num3) / Squared(num2, num3)));
				num = Math.Min(num, Math.Sqrt(Squared(x - routeRoom.X - num2 * num4, z - routeRoom.Z - num3 * num4)) - 8.0);
			}
			return num;
		}

		public double Elevation(double x, double z)
		{
			double num = 0.0;
			double num2 = 0.0;
			foreach (RouteRoom room in Rooms)
			{
				double num3 = Math.Exp((0.0 - Squared(x - room.X, z - room.Z)) / 900.0);
				num += num3;
				num2 += room.Height * num3;
			}
			return num2 / Math.Max(num, 1E-30);
		}

		private static double Squared(double x, double z)
		{
			return x * x + z * z;
		}

		private static RouteRoom R(double x, double z, double h, double radius = 11.0)
		{
			return new RouteRoom(x, z, h, radius);
		}

		private static FloorRoute[] Build()
		{
			return new FloorRoute[14]
			{
				new FloorRoute("Windbreak tree", new RouteRoom[8]
				{
					R(-25.0, -80.0, 0.0),
					R(-12.0, -48.0, 2.0),
					R(-29.0, -10.0, 7.0, 14.0),
					R(18.0, -34.0, 3.0),
					R(28.0, 3.0, 9.0, 14.0),
					R(-10.0, 25.0, 4.0),
					R(-25.0, 63.0, 10.0, 14.0),
					R(21.0, 66.0, 5.0)
				}, new(int, int)[7]
				{
					(0, 1),
					(1, 2),
					(1, 3),
					(3, 4),
					(2, 5),
					(5, 6),
					(5, 7)
				}, 2, 4, 6),
				new FloorRoute("Cinder ring", new RouteRoom[8]
				{
					R(-26.0, -78.0, 5.0),
					R(-28.0, -35.0, 6.0),
					R(-29.0, 20.0, 8.0),
					R(0.0, 55.0, 9.0),
					R(29.0, 20.0, 8.0),
					R(28.0, -35.0, 6.0),
					R(0.0, -25.0, 2.0, 15.0),
					R(0.0, 6.0, 1.0, 19.0)
				}, new(int, int)[10]
				{
					(0, 1),
					(1, 2),
					(2, 3),
					(3, 4),
					(4, 5),
					(5, 0),
					(1, 6),
					(5, 6),
					(6, 7),
					(7, 3)
				}, 6, 7, 7),
				new FloorRoute("Forked crag", new RouteRoom[7]
				{
					R(23.0, -80.0, 0.0),
					R(5.0, -52.0, 3.0),
					R(-28.0, -32.0, 7.0, 14.0),
					R(28.0, -13.0, 6.0),
					R(-6.0, 12.0, 11.0),
					R(-28.0, 48.0, 15.0, 14.0),
					R(24.0, 62.0, 17.0, 17.0)
				}, new(int, int)[8]
				{
					(0, 1),
					(1, 2),
					(1, 3),
					(2, 4),
					(3, 4),
					(4, 5),
					(5, 6),
					(3, 6)
				}, 2, 5, 6),
				new FloorRoute("Amber honeycomb", new RouteRoom[8]
				{
					R(-27.0, -78.0, 1.0),
					R(-27.0, -37.0, 3.0),
					R(20.0, -50.0, 5.0),
					R(-28.0, 8.0, 8.0, 15.0),
					R(20.0, -5.0, 2.0),
					R(-18.0, 56.0, 5.0, 15.0),
					R(27.0, 58.0, 13.0, 16.0),
					R(28.0, 29.0, 9.0)
				}, new(int, int)[10]
				{
					(0, 1),
					(0, 2),
					(1, 3),
					(1, 4),
					(2, 4),
					(3, 5),
					(4, 5),
					(4, 7),
					(7, 6),
					(5, 6)
				}, 3, 5, 6),
				new FloorRoute("Braided ash delta", new RouteRoom[8]
				{
					R(0.0, -81.0, 0.0),
					R(-27.0, -54.0, 2.0),
					R(26.0, -36.0, 7.0, 14.0),
					R(-27.0, -9.0, 9.0, 14.0),
					R(0.0, 15.0, 2.0),
					R(-27.0, 58.0, 5.0),
					R(27.0, 59.0, 13.0, 16.0),
					R(28.0, 14.0, 8.0)
				}, new(int, int)[10]
				{
					(0, 1),
					(0, 2),
					(1, 3),
					(2, 4),
					(3, 4),
					(3, 5),
					(4, 6),
					(2, 7),
					(7, 6),
					(5, 6)
				}, 2, 3, 6),
				new FloorRoute("Ember horseshoe", new RouteRoom[8]
				{
					R(0.0, -82.0, 0.0),
					R(-28.0, -49.0, 3.0),
					R(-28.0, 0.0, 6.0, 14.0),
					R(-23.0, 58.0, 13.0),
					R(23.0, 58.0, 16.0, 16.0),
					R(29.0, 7.0, 7.0, 14.0),
					R(28.0, -48.0, 4.0),
					R(0.0, -6.0, 2.0)
				}, new(int, int)[9]
				{
					(0, 1),
					(1, 2),
					(2, 3),
					(3, 4),
					(4, 5),
					(5, 6),
					(6, 0),
					(2, 7),
					(7, 5)
				}, 2, 5, 4),
				new FloorRoute("Alpine branching tree", new RouteRoom[8]
				{
					R(26.0, -79.0, 0.0),
					R(4.0, -52.0, 3.0),
					R(-28.0, -34.0, 8.0, 14.0),
					R(27.0, -2.0, 10.0, 14.0),
					R(-7.0, 17.0, 7.0),
					R(-28.0, 61.0, 15.0, 16.0),
					R(26.0, 62.0, 12.0),
					R(-28.0, 4.0, 5.0)
				}, new(int, int)[7]
				{
					(0, 1),
					(1, 2),
					(1, 3),
					(2, 7),
					(3, 4),
					(4, 5),
					(4, 6)
				}, 2, 3, 5),
				new FloorRoute("Aurora crescent", new RouteRoom[8]
				{
					R(-27.0, -80.0, 0.0),
					R(3.0, -58.0, 3.0),
					R(29.0, -20.0, 9.0, 14.0),
					R(28.0, 28.0, 12.0),
					R(3.0, 65.0, 17.0, 16.0),
					R(-29.0, 30.0, 10.0, 14.0),
					R(-25.0, -12.0, 4.0),
					R(0.0, 4.0, 2.0)
				}, new(int, int)[9]
				{
					(0, 1),
					(1, 2),
					(2, 3),
					(3, 4),
					(4, 5),
					(5, 6),
					(6, 0),
					(6, 7),
					(7, 2)
				}, 2, 5, 4),
				new FloorRoute("Runic clover", new RouteRoom[7]
				{
					R(0.0, -81.0, 0.0),
					R(0.0, -39.0, 2.0),
					R(-28.0, -14.0, 9.0, 15.0),
					R(27.0, -7.0, 12.0, 15.0),
					R(0.0, 19.0, 4.0),
					R(-25.0, 61.0, 8.0),
					R(26.0, 62.0, 15.0, 16.0)
				}, new(int, int)[8]
				{
					(0, 1),
					(1, 2),
					(1, 3),
					(2, 4),
					(3, 4),
					(4, 5),
					(5, 6),
					(6, 4)
				}, 2, 3, 6),
				new FloorRoute("Oathbound quarry", new RouteRoom[7]
				{
					R(-27.0, -79.0, 1.0),
					R(-27.0, -32.0, 4.0),
					R(24.0, -28.0, 12.0, 16.0),
					R(-6.0, 7.0, 3.0),
					R(-27.0, 53.0, 8.0),
					R(25.0, 60.0, 17.0, 17.0),
					R(29.0, 11.0, 11.0)
				}, new(int, int)[7]
				{
					(0, 1),
					(1, 2),
					(1, 3),
					(3, 4),
					(4, 5),
					(3, 6),
					(6, 5)
				}, 2, 5),
				new FloorRoute("Root garden maze", new RouteRoom[8]
				{
					R(26.0, -80.0, 1.0),
					R(25.0, -38.0, 3.0),
					R(-25.0, -52.0, 8.0, 14.0),
					R(-26.0, -5.0, 4.0),
					R(25.0, 5.0, 10.0, 14.0),
					R(-23.0, 51.0, 7.0),
					R(26.0, 64.0, 14.0, 17.0),
					R(0.0, 33.0, 2.0)
				}, new(int, int)[9]
				{
					(0, 1),
					(0, 2),
					(2, 3),
					(3, 4),
					(1, 4),
					(3, 5),
					(5, 7),
					(7, 4),
					(7, 6)
				}, 2, 4, 6),
				new FloorRoute("Split crimson diamond", new RouteRoom[8]
				{
					R(0.0, -81.0, 1.0),
					R(-28.0, -45.0, 3.0),
					R(27.0, -37.0, 10.0, 14.0),
					R(-28.0, 5.0, 5.0, 14.0),
					R(27.0, 22.0, 15.0),
					R(0.0, 55.0, 7.0),
					R(-25.0, 72.0, 14.0, 16.0),
					R(0.0, -6.0, 2.0)
				}, new(int, int)[9]
				{
					(0, 1),
					(0, 2),
					(1, 3),
					(2, 4),
					(3, 5),
					(4, 5),
					(5, 6),
					(1, 7),
					(7, 4)
				}, 2, 3, 6),
				new FloorRoute("Procession spiral", new RouteRoom[8]
				{
					R(-27.0, -80.0, 0.0),
					R(-28.0, -34.0, 4.0),
					R(-28.0, 25.0, 7.0),
					R(0.0, 65.0, 11.0),
					R(29.0, 29.0, 9.0),
					R(28.0, -30.0, 5.0),
					R(0.0, -25.0, 2.0),
					R(0.0, 12.0, 1.0, 20.0)
				}, new(int, int)[8]
				{
					(0, 1),
					(1, 2),
					(2, 3),
					(3, 4),
					(4, 5),
					(5, 6),
					(6, 7),
					(7, 2)
				}, 7, 7, 7),
				new FloorRoute("Convergence labyrinth", new RouteRoom[9]
				{
					R(0.0, -81.0, 1.0),
					R(-28.0, -50.0, 3.0),
					R(27.0, -46.0, 7.0),
					R(-28.0, 0.0, 11.0, 16.0),
					R(27.0, -1.0, 16.0, 16.0),
					R(0.0, 22.0, 7.0),
					R(-27.0, 62.0, 5.0),
					R(27.0, 67.0, 18.0, 17.0),
					R(0.0, -20.0, 2.0)
				}, new(int, int)[11]
				{
					(0, 1),
					(0, 2),
					(1, 3),
					(2, 4),
					(3, 5),
					(4, 5),
					(5, 6),
					(6, 7),
					(7, 4),
					(1, 8),
					(8, 4)
				}, 3, 4, 7)
			};
		}
	}
	public enum FloorObjective
	{
		Survival,
		BossKill
	}
	public sealed class FloorRules
	{
		public int Floor { get; }

		public double SurvivalSeconds { get; }

		public int CoinPool { get; }

		public int ParticipantLimit { get; }

		public double EntryWindowSeconds { get; }

		public double ArrivalGraceSeconds { get; }

		public double RequestGraceSeconds { get; }

		public FloorObjective Objective { get; }

		public FloorRules(int floor = 0, double survivalSeconds = 100.0, int coinPool = 200, int participantLimit = 8, double entryWindowSeconds = 10.0, double arrivalGraceSeconds = 45.0, double requestGraceSeconds = 0.0, FloorObjective objective = FloorObjective.Survival)
		{
			if (floor < 0 || floor > 1000)
			{
				throw new ArgumentOutOfRangeException("floor");
			}
			if (double.IsNaN(survivalSeconds) || double.IsInfinity(survivalSeconds) || survivalSeconds <= 0.0 || survivalSeconds > 3600.0)
			{
				throw new ArgumentOutOfRangeException("survivalSeconds");
			}
			if (coinPool < 0 || coinPool > 1000000)
			{
				throw new ArgumentOutOfRangeException("coinPool");
			}
			if (participantLimit < 1 || participantLimit > 16)
			{
				throw new ArgumentOutOfRangeException("participantLimit");
			}
			if (double.IsNaN(entryWindowSeconds) || double.IsInfinity(entryWindowSeconds) || entryWindowSeconds <= 0.0 || entryWindowSeconds > 120.0)
			{
				throw new ArgumentOutOfRangeException("entryWindowSeconds");
			}
			if (double.IsNaN(arrivalGraceSeconds) || double.IsInfinity(arrivalGraceSeconds) || arrivalGraceSeconds < 1.0 || arrivalGraceSeconds > 120.0)
			{
				throw new ArgumentOutOfRangeException("arrivalGraceSeconds");
			}
			if (double.IsNaN(requestGraceSeconds) || double.IsInfinity(requestGraceSeconds) || requestGraceSeconds < 0.0 || requestGraceSeconds > 5.0 || requestGraceSeconds >= arrivalGraceSeconds)
			{
				throw new ArgumentOutOfRangeException("requestGraceSeconds");
			}
			if (objective != FloorObjective.Survival && objective != FloorObjective.BossKill)
			{
				throw new ArgumentOutOfRangeException("objective");
			}
			Floor = floor;
			SurvivalSeconds = survivalSeconds;
			CoinPool = coinPool;
			ParticipantLimit = participantLimit;
			EntryWindowSeconds = entryWindowSeconds;
			ArrivalGraceSeconds = arrivalGraceSeconds;
			RequestGraceSeconds = requestGraceSeconds;
			Objective = objective;
		}
	}
	public readonly struct CreaturePower
	{
		public float Health { get; }

		public float Damage { get; }

		public float NamedHealth { get; }

		public CreaturePower(float health, float damage, float? namedHealth = null)
		{
			Health = health;
			Damage = damage;
			NamedHealth = namedHealth ?? health;
		}

		public CreaturePower ForNamedTarget()
		{
			return new CreaturePower(NamedHealth, Damage, NamedHealth);
		}
	}
	public static class FloorScaling
	{
		public static float NamedFactor(float growthFactor, float bonusEffect = 2f, float floorOverride = 1f)
		{
			if (float.IsNaN(growthFactor) || float.IsInfinity(growthFactor) || growthFactor < 1f || growthFactor > 100f || float.IsNaN(bonusEffect) || float.IsInfinity(bonusEffect) || bonusEffect < 1f || bonusEffect > 5f || float.IsNaN(floorOverride) || float.IsInfinity(floorOverride) || floorOverride < 0.1f || floorOverride > 10f)
			{
				throw new ArgumentOutOfRangeException("growthFactor");
			}
			return Math.Min(100f, (1f + bonusEffect * (growthFactor - 1f)) * floorOverride);
		}

		public static float Factor(int floor, int start, float growth, float floorOverride = 1f)
		{
			if (floor < 0 || start < 0 || float.IsNaN(growth) || float.IsInfinity(growth) || growth < 0f || growth > 1f || float.IsNaN(floorOverride) || float.IsInfinity(floorOverride) || floorOverride < 0.1f || floorOverride > 10f)
			{
				throw new ArgumentOutOfRangeException("floor");
			}
			double val = Math.Pow(1.0 + (double)growth, Math.Max(0L, (long)floor - (long)start + 1)) * (double)floorOverride;
			return (float)Math.Max(0.01, Math.Min(100.0, val));
		}
	}
	public static class FloorTerrain
	{
		public const int Cell = 3;

		public const int HalfWidth = 48;

		public const int HalfLength = 102;

		public static double Height(int floor, double x, double z)
		{
			if (floor < 1 || floor > 20)
			{
				throw new ArgumentOutOfRangeException("floor");
			}
			x = Math.Max(-48.0, Math.Min(47.999999, x));
			z = Math.Max(-102.0, Math.Min(101.999999, z));
			double num = Math.Floor((x + 48.0) / 3.0) * 3.0 - 48.0;
			double num2 = Math.Floor((z + 102.0) / 3.0) * 3.0 - 102.0;
			double num3 = (x - num) / 3.0;
			double num4 = (z - num2) / 3.0;
			double num5 = Vertex(floor, num, num2);
			double num6 = Vertex(floor, num, num2 + 3.0);
			double num7 = Vertex(floor, num + 3.0, num2);
			double num8 = Vertex(floor, num + 3.0, num2 + 3.0);
			if (!(num3 + num4 <= 1.0))
			{
				return num8 + (1.0 - num3) * (num6 - num8) + (1.0 - num4) * (num7 - num8);
			}
			return num5 + num3 * (num7 - num5) + num4 * (num6 - num5);
		}

		public static double Vertex(int floor, double x, double z)
		{
			if (floor >= 7 && floor <= 20)
			{
				return FloorRoute.For(floor).Elevation(x, z);
			}
			switch (floor)
			{
			case 1:
				return ramp(-62.0, -30.0, 3.0) + ramp(14.0, 52.0, 5.0) + hill(-24.0, -18.0, 22.0, 2.5) - hill(18.0, 0.0, 24.0, 1.2);
			case 2:
				return hill(-18.0, -24.0, 27.0, 2.4) + hill(22.0, 39.0, 24.0, 3.2);
			case 3:
			case 4:
				return 0.0;
			case 5:
				return hill(0.0, 2.0, 26.0, 8.0) + hill(-20.0, 25.0, 24.0, 3.0);
			case 6:
				return ramp(-60.0, -26.0, 3.0) + ramp(10.0, 50.0, 4.0);
			default:
				throw new ArgumentOutOfRangeException("floor");
			}
			double hill(double cx, double cz, double width, double height)
			{
				return height * Math.Exp((0.0 - ((x - cx) * (x - cx) + (z - cz) * (z - cz))) / (width * width));
			}
			double ramp(double start, double end, double height)
			{
				return height * Smooth((z - start) / (end - start));
			}
		}

		private static double Smooth(double t)
		{
			t = Math.Max(0.0, Math.Min(1.0, t));
			return t * t * (3.0 - 2.0 * t);
		}
	}
	public sealed class HuntProgress
	{
		private readonly bool[] _spawned;

		private readonly bool[] _defeated;

		public int Total => _spawned.Length;

		public int Defeated { get; private set; }

		public bool Complete => Defeated == Total;

		public bool Stopped { get; private set; }

		public HuntProgress(int targets)
		{
			if (targets < 1 || targets > 10)
			{
				throw new ArgumentOutOfRangeException("targets");
			}
			_spawned = new bool[targets];
			_defeated = new bool[targets];
		}

		public bool IsSpawned(int index)
		{
			return _spawned[index];
		}

		public bool IsDefeated(int index)
		{
			return _defeated[index];
		}

		public string Describe(Func<int, string> name)
		{
			if (Complete)
			{
				return "FLOOR COMPLETE";
			}
			string text = "";
			for (int i = 0; i < Total; i++)
			{
				if (!_defeated[i])
				{
					text = text + ((text.Length == 0) ? "" : " · ") + name(i);
				}
			}
			return "HUNT THE CHAMPIONS\n" + Defeated + " / " + Total + "\n<size=24>" + text + "</size>";
		}

		public void Spawn(int index)
		{
			if (!Stopped)
			{
				_spawned[index] = true;
			}
		}

		public void Defeat(int index)
		{
			if (!Stopped && _spawned[index] && !_defeated[index])
			{
				_defeated[index] = true;
				Defeated++;
			}
		}

		public void Stop()
		{
			Stopped = true;
		}
	}
	public sealed class InputBlockLease : IDisposable
	{
		private readonly Action<bool> _change;

		public bool Held { get; private set; }

		public InputBlockLease(Action<bool> change)
		{
			_change = change ?? throw new ArgumentNullException("change");
		}

		public void Acquire()
		{
			if (!Held)
			{
				Held = true;
				_change(obj: true);
			}
		}

		public void Dispose()
		{
			if (Held)
			{
				Held = false;
				_change(obj: false);
			}
		}
	}
	public static class ItemOrigin
	{
		public const string Key = "brom8.beyond.origin.v1";

		public static string Create(string kind, string identity, string prefab)
		{
			string text = "1|" + kind + "|" + identity + "|" + prefab;
			if (!Valid(text, prefab))
			{
				throw new ArgumentException("Invalid Beyond item origin.");
			}
			return text;
		}

		public static bool Valid(string? value, string? actualPrefab)
		{
			if (string.IsNullOrEmpty(value) || value.Length > 200 || string.IsNullOrEmpty(actualPrefab) || actualPrefab.Length > 128)
			{
				return false;
			}
			string[] array = value.Split('|');
			if (array.Length == 4 && array[0] == "1" && (array[1] == "shop" || array[1] == "bank" || array[1] == "loot") && Guid.TryParseExact(array[2], "N", out var _))
			{
				return array[3] == actualPrefab;
			}
			return false;
		}
	}
	public static class LandscapePreviewLayout
	{
		public const int Revision = 2;

		public const float HalfSize = 64f;

		public const int MinZ = -64;

		public const int MaxZ = 704;

		public const int SectionCount = 6;

		public const float FoundationX = -23f;

		public const float FoundationZ = 19f;

		public const float FoundationHeight = 5f;

		public const float WaterHeight = -1.1f;

		public static bool Contains(float x, float y, float z)
		{
			if (Math.Abs(x) <= 70f && z >= -70f && z <= 710f && y >= -25f)
			{
				return y <= 130f;
			}
			return false;
		}

		public static bool InsideTravelBounds(float x, float y, float z)
		{
			if (Math.Abs(x) <= 62f && z >= -62f && z <= 702f && y >= -15f)
			{
				return y <= 120f;
			}
			return false;
		}

		public static int Section(float z)
		{
			return Math.Max(0, Math.Min(5, (int)Math.Floor((z + 64f) / 128f)));
		}

		public static float Transition(float z)
		{
			if (Section(z) != 0)
			{
				return Smooth((z - (float)(Section(z) * 128 - 64)) / 24f);
			}
			return 1f;
		}

		public static int SurfaceSection(float x, float z)
		{
			int num = Section(z);
			if (num == 0)
			{
				return 0;
			}
			if (!((Noise(x * 0.31f, z * 0.31f, 947) + 1f) * 0.5f < Transition(z)))
			{
				return num - 1;
			}
			return num;
		}

		public static string SectionName(int section)
		{
			return section switch
			{
				1 => "The Gloaming Fen", 
				2 => "The Ochre Expanse", 
				3 => "The Stonevein Vault", 
				4 => "The Frostbound Pass", 
				5 => "The Emberwood", 
				_ => "The Rootlit Forest", 
			};
		}

		public static int EnvironmentFloor(float z)
		{
			return Section(z) switch
			{
				1 => 3, 
				2 => 1, 
				3 => 6, 
				4 => 13, 
				5 => 12, 
				_ => 2, 
			};
		}

		public static bool SupportMatches(bool preview, int mode, string expected, string actual)
		{
			if (mode == (preview ? 1 : 0) && !string.IsNullOrEmpty(expected) && expected.Length <= 128)
			{
				return string.Equals(expected, actual, StringComparison.Ordinal);
			}
			return false;
		}

		public static float PathX(float z)
		{
			return 11f + (float)Math.Sin((double)(z + 14f) * 0.055) * 13f;
		}

		public static float PathDistance(float x, float z)
		{
			return Math.Abs(x - PathX(z));
		}

		public static float FoundationDistance(float x, float z, float halfX = 16f, float halfZ = 16f)
		{
			return Math.Max(Math.Abs(x - -23f) - halfX, Math.Abs(z - 19f) - halfZ);
		}

		public static float Height(float x, float z, float halfX = 16f, float halfZ = 16f)
		{
			if (z <= 64f)
			{
				return ForestHeight(x, z, halfX, halfZ);
			}
			int num = Section(z);
			float num2 = num * 128 - 64;
			float num3 = SectionHeight(num, x, z);
			float num4 = Smooth((z - num2) / 24f);
			if (num4 < 1f)
			{
				num3 = Lerp((num == 1) ? ForestHeight(x, z, halfX, halfZ) : SectionHeight(num - 1, x, z), num3, num4);
			}
			if (((uint)(num - 1) <= 1u || num == 4) ? true : false)
			{
				float t = 1f - Smooth((LandmarkDistance(num, x, z) + 0.5f) / 4f);
				num3 = Lerp(num3, LandmarkHeight(num), t);
			}
			return num3;
		}

		public static float LandmarkX(int section)
		{
			return (section == 4) ? (-32) : (-34);
		}

		public static float LandmarkZ(int section)
		{
			return section * 128;
		}

		public static float LandmarkHeight(int section)
		{
			return RouteHeight(LandmarkZ(section)) + 0.4f;
		}

		public static float LandmarkDistance(int section, float x, float z)
		{
			return Math.Max(Math.Abs(x - LandmarkX(section)) - 16.5f, Math.Abs(z - LandmarkZ(section)) - 16.5f);
		}

		public static float RouteHeight(float z)
		{
			if (z <= 64f)
			{
				return ForestHeight(PathX(z), z, 16f, 16f);
			}
			float num = 64f;
			float num2 = ForestHeight(PathX(64f), 64f, 16f, 16f);
			for (int i = 1; i <= 6; i++)
			{
				float num3 = ((i == 6) ? 704 : (i * 128));
				float num4 = i switch
				{
					1 => 3.6f, 
					2 => 10f, 
					3 => 14f, 
					4 => 44f, 
					_ => 22f, 
				};
				if (z <= num3)
				{
					return Lerp(num2, num4, (z - num) / (num3 - num));
				}
				num = num3;
				num2 = num4;
			}
			return num2;
		}

		public static float RouteDistance(float x, float z)
		{
			float num = PathDistance(x, z);
			if (z <= 64f)
			{
				return num;
			}
			int num2 = Section(z);
			float num3 = num2 * 128;
			float num4 = x - (PathX(num3) + (float)((num2 % 2 == 0) ? (-10) : 10));
			float num5 = z - num3;
			float val = Math.Abs((float)Math.Sqrt(num4 * num4 / 784f + num5 * num5 / 1444f) - (1f + Noise(x * 0.035f, z * 0.035f, 871) * 0.13f)) * 28f;
			float num6 = Math.Min(num, val);
			if (((uint)(num2 - 1) <= 1u || num2 == 4) ? true : false)
			{
				float num7 = LandmarkX(num2);
				float num8 = PathX(num3);
				float num9 = Math.Max(0f, Math.Min(1f, (x - num8) / (num7 - num8)));
				float num10 = num8 + (num7 - num8) * num9;
				num6 = Math.Min(num6, (float)Math.Sqrt((x - num10) * (x - num10) + (z - num3) * (z - num3)));
			}
			return num6;
		}

		private static float SectionHeight(int section, float x, float z)
		{
			float num = RouteHeight(z);
			float value = x - PathX(z);
			float num2 = Noise(x * 0.23f, z * 0.23f, 391) * 0.35f + Noise(x * 0.61f, z * 0.61f, 121) * 0.1f;
			float num3 = Noise(x * 0.055f, z * 0.055f, 713);
			float num4 = Noise(x * 0.018f, z * 0.018f, 671);
			float a = section switch
			{
				1 => 0.6f + num3 * 1.1f + num4 * 0.7f + num2, 
				2 => num + 2f + (float)Math.Sin(x * 0.13f + z * 0.035f) * 3f + num3 * 2f + num2, 
				3 => num + 3f + Math.Abs(value) * 0.13f + num3 * 3f + num2, 
				4 => num + 7f + Math.Abs(value) * 0.4f + num4 * 8f + num3 * 4f + num2, 
				_ => num + 3f + num3 * 3f + num4 * 3f + num2, 
			};
			float t = 1f - Smooth((RouteDistance(x, z) - 2.5f) / 4.5f);
			a = Lerp(a, num + num2 * 0.12f, t);
			if (section == 3)
			{
				a += Smooth((Math.Abs(value) - 13f) / 15f) * 10f;
			}
			return a;
		}

		private static float Lerp(float a, float b, float t)
		{
			return a + (b - a) * t;
		}

		private static float ForestHeight(float x, float z, float halfX, float halfZ)
		{
			float num = Noise(x * 0.018f, z * 0.018f, 671) * 11f;
			float num2 = Noise(x * 0.062f, z * 0.062f, 713) * 2.5f;
			float num3 = Noise(x * 0.25f, z * 0.25f, 391) * 0.43f + Noise(x * 0.61f, z * 0.61f, 121) * 0.12f;
			float num4 = 8f * (float)Math.Exp(0f - ((x + 45f) * (x + 45f) / 300f + (z + 25f) * (z + 25f) / 950f));
			float num5 = 4f + num + num2 + num3 + num4;
			float num6 = Smooth((x - 31f) / 26f) * Smooth((25f - z) / 25f);
			num5 = num5 * (1f - num6) + (-3.4f + num3) * num6;
			float num7 = 1f - Smooth((PathDistance(x, z) - 1.4f) / 3.5f);
			float num8 = 3.2f + 0.028f * z + (float)Math.Sin(z * 0.045f) * 1.1f;
			num5 += (num8 - num5) * num7 * 0.94f;
			float num9 = 1f - Smooth((FoundationDistance(x, z, halfX, halfZ) + 0.5f) / 4.5f);
			return num5 + (5f - num5) * num9;
		}

		public static float CollisionHeight(float x, float z, float halfX = 16f, float halfZ = 16f)
		{
			float num = (float)Math.Floor(x);
			float num2 = (float)Math.Floor(z);
			float num3 = x - num;
			float num4 = z - num2;
			float num5 = Height(num, num2, halfX, halfZ);
			float num6 = Height(num + 1f, num2, halfX, halfZ);
			float num7 = Height(num, num2 + 1f, halfX, halfZ);
			float num8 = Height(num + 1f, num2 + 1f, halfX, halfZ);
			if (!(num3 + num4 <= 1f))
			{
				return num8 + (num7 - num8) * (1f - num3) + (num6 - num8) * (1f - num4);
			}
			return num5 + (num6 - num5) * num3 + (num7 - num5) * num4;
		}

		public static float Noise(float x, float z, int seed)
		{
			int num = (int)Math.Floor(x);
			int num2 = (int)Math.Floor(z);
			float num3 = Smooth(x - (float)num);
			float num4 = Smooth(z - (float)num2);
			float num5 = Hash(num, num2, seed);
			float num6 = Hash(num + 1, num2, seed);
			float num7 = Hash(num, num2 + 1, seed);
			float num8 = Hash(num + 1, num2 + 1, seed);
			return (num5 + (num6 - num5) * num3) * (1f - num4) + (num7 + (num8 - num7) * num3) * num4;
		}

		private static float Hash(int x, int z, int seed)
		{
			int num = x * 374761393 + z * 668265263 + seed * 1442695041;
			int num2 = (num ^ (num >>> 13)) * 1274126177;
			return (float)(uint)(num2 ^ (num2 >>> 16)) / 4.2949673E+09f * 2f - 1f;
		}

		public static float Smooth(float t)
		{
			t = Math.Max(0f, Math.Min(1f, t));
			return t * t * (3f - 2f * t);
		}
	}
	public static class MenuMovementPolicy
	{
		public static bool Allow(bool menuOwnsInput, bool soleInputRequest, bool otherUi, bool playerReady)
		{
			return menuOwnsInput && soleInputRequest && !otherUi && playerReady;
		}
	}
	public readonly struct PreparationIdentity
	{
		public string Token { get; }

		public string Run { get; }

		public int Floor { get; }

		public int Slot { get; }

		public PreparationIdentity(string token, string run, int floor, int slot)
		{
			if (!Guid.TryParseExact(token, "N", out var result) || (run != "" && !Guid.TryParseExact(run, "N", out result)) || floor < 0 || floor > 20 || slot < 0 || slot >= 4)
			{
				throw new ArgumentException("Invalid layout preparation identity.");
			}
			Token = token;
			Run = run;
			Floor = floor;
			Slot = slot;
		}

		public bool Matches(string token, string run, int floor, int slot)
		{
			if (string.Equals(Token, token, StringComparison.Ordinal) && string.Equals(Run, run, StringComparison.Ordinal) && Floor == floor)
			{
				return Slot == slot;
			}
			return false;
		}
	}
	public enum PreparationPhase
	{
		Queued,
		Building,
		Ready,
		Failed,
		Cancelled
	}
	public sealed class PreparationWork : IDisposable
	{
		private IEnumerator<Action>? _steps;

		public PreparationPhase Phase { get; private set; }

		public string Error { get; private set; } = "";

		public bool Terminal
		{
			get
			{
				if (Phase != PreparationPhase.Ready && Phase != PreparationPhase.Failed)
				{
					return Phase == PreparationPhase.Cancelled;
				}
				return true;
			}
		}

		public PreparationWork(IEnumerator<Action> steps)
		{
			_steps = steps ?? throw new ArgumentNullException("steps");
		}

		public void Step()
		{
			if (Terminal)
			{
				return;
			}
			Phase = PreparationPhase.Building;
			try
			{
				if (_steps.MoveNext())
				{
					_steps.Current();
					return;
				}
				Phase = PreparationPhase.Ready;
				DisposeSteps();
			}
			catch (Exception ex)
			{
				Error = ex.Message;
				Phase = PreparationPhase.Failed;
				try
				{
					DisposeSteps();
				}
				catch (Exception ex2)
				{
					Error = Error + "; preparation disposal: " + ex2.Message;
				}
			}
		}

		private void DisposeSteps()
		{
			IEnumerator<Action>? steps = _steps;
			_steps = null;
			steps?.Dispose();
		}

		public void Dispose()
		{
			if (!Terminal)
			{
				Phase = PreparationPhase.Cancelled;
			}
			try
			{
				DisposeSteps();
			}
			catch (Exception ex)
			{
				Error = Error + "; preparation disposal: " + ex.Message;
			}
		}
	}
	public sealed class RealmSpawnSlot
	{
		public int slot;

		public int generation;

		public string phase = "empty";

		public string run = "";

		public long user;

		public long authority;

		public uint id;

		public double due;

		public bool deathProcessed;

		public string diagnostic = "";

		public bool Eligible(double clock)
		{
			if (!(phase == "empty"))
			{
				if (phase == "cooling")
				{
					return clock >= due;
				}
				return false;
			}
			return true;
		}

		public void Begin(double clock)
		{
			if (!Eligible(clock) || generation == int.MaxValue)
			{
				throw new InvalidOperationException("Realm slot is not eligible.");
			}
			if (double.IsNaN(clock) || double.IsInfinity(clock) || clock < 0.0)
			{
				throw new ArgumentOutOfRangeException("clock");
			}
			generation++;
			phase = "intent";
			run = Guid.NewGuid().ToString("N");
			user = 0L;
			authority = 0L;
			id = 0u;
			deathProcessed = false;
			diagnostic = "";
		}

		public void Attach(long owner, uint nativeId)
		{
			if (phase != "intent" || nativeId == 0)
			{
				throw new InvalidOperationException("Invalid realm spawn attachment.");
			}
			user = owner;
			id = nativeId;
			phase = "alive";
		}

		public void DeathProcessed()
		{
			if (!(phase != "alive") || !(phase != "dying"))
			{
				phase = "dying";
				deathProcessed = true;
			}
		}

		public void Removed(double clock, int delay)
		{
			if (phase != "dying" || !deathProcessed)
			{
				Quarantine("Native record disappeared without completed death evidence.");
				return;
			}
			if (delay < 1 || double.IsNaN(clock) || double.IsInfinity(clock) || clock < 0.0)
			{
				throw new ArgumentOutOfRangeException("clock");
			}
			phase = "cooling";
			due = clock + (double)delay;
		}

		public void Quarantine(string reason)
		{
			phase = "quarantined";
			diagnostic = reason;
		}

		public bool Valid()
		{
			if (slot >= 0 && slot < 8 && generation >= 0 && diagnostic != null && diagnostic.Length <= 500)
			{
				bool num;
				if (generation != 0)
				{
					num = Guid.TryParseExact(run, "N", out var _);
				}
				else
				{
					if (!(run == ""))
					{
						goto IL_01e7;
					}
					if (phase == "empty")
					{
						goto IL_009f;
					}
					num = phase == "quarantined";
				}
				if (num)
				{
					goto IL_009f;
				}
			}
			goto IL_01e7;
			IL_009f:
			if ((phase == "empty" || phase == "intent" || phase == "alive" || phase == "dying" || phase == "cooling" || phase == "quarantined") && !double.IsNaN(due) && !double.IsInfinity(due) && due >= 0.0 && ((phase != "alive" && phase != "dying" && phase != "cooling") || id != 0) && (phase != "empty" || (generation == 0 && id == 0 && user == 0L && !deathProcessed)) && (phase != "intent" || id == 0))
			{
				if (!(phase != "cooling"))
				{
					return deathProcessed;
				}
				return true;
			}
			goto IL_01e7;
			IL_01e7:
			return false;
		}
	}
	public readonly struct RealmPoint
	{
		public readonly float X;

		public readonly float Y;

		public readonly float Z;

		public RealmPoint(float x, float y, float z)
		{
			X = x;
			Y = y;
			Z = z;
		}
	}
	public sealed class RealmDistrict
	{
		public int Id { get; }

		public string Name { get; }

		public RealmPoint Center { get; }

		public RealmDistrict(int id, string name, float x, float y, float z)
		{
			Id = id;
			Name = name;
			Center = new RealmPoint(x, y, z);
		}
	}
	public static class SharedRealmLayout
	{
		public const int Revision = 1;

		public const float Radius = 500f;

		public static readonly IReadOnlyList<RealmDistrict> Districts = Array.AsReadOnly(new RealmDistrict[9]
		{
			new RealmDistrict(0, "Lantern Shelf", -215f, 35f, -325f),
			new RealmDistrict(1, "Whispercut Valley", -295f, 40f, -35f),
			new RealmDistrict(2, "Mirrorfen", 65f, -24f, -80f),
			new RealmDistrict(3, "The Hanging Wood", 245f, 80f, 120f),
			new RealmDistrict(4, "Sunderfall Gorge", 295f, 25f, -155f),
			new RealmDistrict(5, "The Undervein", -65f, -60f, 65f),
			new RealmDistrict(6, "Glasswind Saddle", -145f, 105f, 280f),
			new RealmDistrict(7, "The Broken Crown", 65f, 180f, 265f),
			new RealmDistrict(8, "Cinder Garden", 115f, 25f, -295f)
		});

		public static readonly RealmPoint[][] Paths = new RealmPoint[10][]
		{
			new RealmPoint[3]
			{
				P(0),
				new RealmPoint(-305f, 35f, -230f),
				P(1)
			},
			new RealmPoint[4]
			{
				P(1),
				new RealmPoint(-330f, 65f, 130f),
				new RealmPoint(-245f, 80f, 205f),
				P(6)
			},
			new RealmPoint[7]
			{
				P(6),
				new RealmPoint(-65f, 115f, 355f),
				new RealmPoint(25f, 125f, 325f),
				new RealmPoint(-50f, 140f, 235f),
				new RealmPoint(15f, 150f, 200f),
				new RealmPoint(120f, 165f, 230f),
				P(7)
			},
			new RealmPoint[4]
			{
				P(7),
				new RealmPoint(195f, 150f, 325f),
				new RealmPoint(290f, 125f, 265f),
				P(3)
			},
			new RealmPoint[3]
			{
				P(3),
				new RealmPoint(355f, 55f, 10f),
				P(4)
			},
			new RealmPoint[3]
			{
				P(4),
				new RealmPoint(310f, 25f, -280f),
				P(8)
			},
			new RealmPoint[3]
			{
				P(8),
				new RealmPoint(-50f, 28f, -355f),
				P(0)
			},
			new RealmPoint[6]
			{
				P(1),
				new RealmPoint(-175f, 10f, -140f),
				new RealmPoint(-90f, -23f, -195f),
				new RealmPoint(65f, -24f, -195f),
				new RealmPoint(185f, -22f, -185f),
				P(4)
			},
			new RealmPoint[3]
			{
				new RealmPoint(65f, -24f, -195f),
				new RealmPoint(20f, -5f, -245f),
				P(8)
			},
			new RealmPoint[3]
			{
				new RealmPoint(-90f, -23f, -195f),
				new RealmPoint(-75f, -24f, -100f),
				P(2)
			}
		};

		public static readonly RealmPoint[][] Caves = BuildCaves();

		private static RealmPoint[][] BuildCaves()
		{
			return new RealmPoint[3][]
			{
				Spiral(-150f, 65f, 25f, MathF.PI, 2, -45f),
				Spiral(20f, 260f, 40f, -MathF.PI / 2f, 3, -40f),
				Spiral(-135f, -100f, 30f, MathF.PI, 2, -50f)
			};
			static RealmPoint[] Spiral(float cx, float cz, float radius, float startAngle, int turns, float bottom)
			{
				int num = turns * 32;
				float x = cx + (float)Math.Cos(startAngle) * radius;
				float z = cz + (float)Math.Sin(startAngle) * radius;
				float num2 = Height(x, z);
				List<RealmPoint> list = new List<RealmPoint>();
				for (int i = 0; i <= num; i++)
				{
					float num3 = (float)i / (float)num;
					float num4 = startAngle + num3 * (float)turns * MathF.PI * 2f;
					list.Add(new RealmPoint(cx + (float)Math.Cos(num4) * radius, num2 + (bottom - num2) * num3, cz + (float)Math.Sin(num4) * radius));
				}
				list.Add(P(5));
				return list.ToArray();
			}
		}

		private static RealmPoint P(int id)
		{
			return Districts[id].Center;
		}

		private static float Smooth(float t)
		{
			t = Math.Max(0f, Math.Min(1f, t));
			return t * t * (3f - 2f * t);
		}

		public static float HeightBase(float x, float z)
		{
			float num = 165f * (float)Math.Exp(0f - (x * x / 65000f + (z - 285f) * (z - 285f) / 22000f));
			float num2 = 60f * (float)Math.Exp(0f - ((x - 255f) * (x - 255f) / 24000f + (z - 120f) * (z - 120f) / 32000f));
			float num3 = -72f * (float)Math.Exp(0f - ((x - 60f) * (x - 60f) / 23000f + (z + 65f) * (z + 65f) / 18000f));
			float num4 = (float)(Math.Sin((double)x * 0.021) * Math.Cos((double)z * 0.017) * 5.0 + Math.Sin((double)(x + z) * 0.038) * 2.0);
			float num5 = Smooth(((float)Math.Sqrt(x * x + z * z) - 425f) / 55f) * 65f;
			return 25f + num + num2 + num3 + num4 + num5;
		}

		public static float Height(float x, float z)
		{
			float num = HeightBase(x, z);
			float num2 = 45f;
			float num3 = num;
			RealmPoint[][] paths = Paths;
			foreach (RealmPoint[] array in paths)
			{
				for (int j = 1; j < array.Length; j++)
				{
					RealmPoint realmPoint = array[j - 1];
					RealmPoint realmPoint2 = array[j];
					float num4 = realmPoint2.X - realmPoint.X;
					float num5 = realmPoint2.Z - realmPoint.Z;
					float num6 = Math.Max(0f, Math.Min(1f, ((x - realmPoint.X) * num4 + (z - realmPoint.Z) * num5) / (num4 * num4 + num5 * num5)));
					float num7 = (float)Math.Sqrt(Sq(x - realmPoint.X - num6 * num4) + Sq(z - realmPoint.Z - num6 * num5));
					if (num7 < num2)
					{
						num2 = num7;
						num3 = realmPoint.Y + (realmPoint2.Y - realmPoint.Y) * num6;
					}
				}
			}
			num += (num3 - num) * (1f - Smooth((num2 - 9f) / 26f));
			for (int k = 0; k < Districts.Count; k++)
			{
				if (k != 5)
				{
					RealmPoint realmPoint3 = P(k);
					float num8 = (float)Math.Sqrt(Sq(x - realmPoint3.X) + Sq(z - realmPoint3.Z));
					float num9 = k switch
					{
						0 => 48, 
						2 => 55, 
						3 => 55, 
						4 => 60, 
						7 => 48, 
						_ => 24, 
					};
					num += (realmPoint3.Y - num) * (1f - Smooth((num8 - num9) / 20f));
				}
			}
			float num10 = 1f - Smooth((Math.Abs(x - 295f) - 5f) / 10f);
			float num11 = Smooth((z + 245f) / 25f) * (1f - Smooth((z - 5f) / 30f));
			num -= 12f * num10 * num11;
			float num12 = 1f - Smooth(((float)Math.Sqrt(Sq((x - 295f) * 1.15f) + Sq(z + 226f)) - 12f) / 16f);
			num -= 28f * num12;
			float num13 = (float)Math.Sqrt(x * x + z * z);
			if (num13 > 485f)
			{
				num -= Smooth((num13 - 485f) / 15f) * 110f;
			}
			return num;
		}

		public static float CollisionHeight(float x, float z)
		{
			float num = (float)Math.Floor(x / 4f) * 4f;
			float num2 = (float)Math.Floor(z / 4f) * 4f;
			float num3 = (x - num) / 4f;
			float num4 = (z - num2) / 4f;
			float num5 = Height(num, num2);
			float num6 = Height(num + 4f, num2);
			float num7 = Height(num, num2 + 4f);
			float num8 = Height(num + 4f, num2 + 4f);
			if (!(num3 + num4 <= 1f))
			{
				return num8 + (num7 - num8) * (1f - num3) + (num6 - num8) * (1f - num4);
			}
			return num5 + (num6 - num5) * num3 + (num7 - num5) * num4;
		}

		public static float RouteDistance(float x, float z)
		{
			float num = float.MaxValue;
			RealmPoint[][] paths = Paths;
			foreach (RealmPoint[] array in paths)
			{
				for (int j = 1; j < array.Length; j++)
				{
					RealmPoint realmPoint = array[j - 1];
					RealmPoint realmPoint2 = array[j];
					float num2 = realmPoint2.X - realmPoint.X;
					float num3 = realmPoint2.Z - realmPoint.Z;
					float num4 = Math.Max(0f, Math.Min(1f, ((x - realmPoint.X) * num2 + (z - realmPoint.Z) * num3) / (num2 * num2 + num3 * num3)));
					num = Math.Min(num, (float)Math.Sqrt(Sq(x - realmPoint.X - num4 * num2) + Sq(z - realmPoint.Z - num4 * num3)));
				}
			}
			return num;
		}

		public static bool Contains(float x, float y, float z)
		{
			if (x * x + z * z <= 260100f && y >= -150f)
			{
				return y <= 330f;
			}
			return false;
		}

		public static int DistrictAt(float x, float y, float z)
		{
			if (y < -35f && Math.Abs(x + 65f) < 150f && Math.Abs(z - 65f) < 180f)
			{
				return 5;
			}
			float num = float.MaxValue;
			int result = 0;
			for (int i = 0; i < Districts.Count; i++)
			{
				if (i != 5)
				{
					RealmPoint realmPoint = P(i);
					float num2 = Sq(x - realmPoint.X) + Sq(z - realmPoint.Z);
					if (num2 < num)
					{
						num = num2;
						result = i;
					}
				}
			}
			return result;
		}

		private static float Sq(float x)
		{
			return x * x;
		}
	}
	public static class ShopAccess
	{
		public static IReadOnlyList<int> TabsFor(int currentCompletedFloor)
		{
			if (currentCompletedFloor < 0 || currentCompletedFloor > 1000)
			{
				throw new ArgumentOutOfRangeException("currentCompletedFloor");
			}
			int[] array = new int[currentCompletedFloor + 1];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = i;
			}
			return Array.AsReadOnly(array);
		}
	}
	public static class ShopFootprint
	{
		public const float HalfExtent = 21f;

		public const float MinHeight = -8f;

		public const float MaxHeight = 24f;

		public static bool Contains(float x, float y, float z)
		{
			if (Math.Abs(x) <= 21f && Math.Abs(z) <= 21f && y >= -8f)
			{
				return y <= 24f;
			}
			return false;
		}
	}
	public sealed class StoneLease
	{
		private readonly double _leaseSeconds;

		private double _lastObservedTime;

		public long Owner { get; private set; }

		public string Token { get; private set; } = string.Empty;

		public double ExpiresAt { get; private set; }

		public StoneLease(double leaseSeconds = 15.0)
		{
			if (double.IsNaN(leaseSeconds) || double.IsInfinity(leaseSeconds) || leaseSeconds <= 0.0 || leaseSeconds > 120.0)
			{
				throw new ArgumentOutOfRangeException("leaseSeconds");
			}
			_leaseSeconds = leaseSeconds;
		}

		public void Advance(double now)
		{
			if (double.IsNaN(now) || double.IsInfinity(now) || now < _lastObservedTime || double.IsInfinity(now + _leaseSeconds))
			{
				throw new ArgumentOutOfRangeException("now", "Use nonnegative monotonic host time.");
			}
			_lastObservedTime = now;
			if (Owner != 0L && now >= ExpiresAt)
			{
				Clear();
			}
		}

		public bool TryAcquire(long owner, double now, out string token)
		{
			Advance(now);
			token = string.Empty;
			if (owner == 0L || (Owner != 0L && Owner != owner))
			{
				return false;
			}
			if (Owner == 0L)
			{
				Owner = owner;
				Token = Guid.NewGuid().ToString("N");
			}
			ExpiresAt = now + _leaseSeconds;
			token = Token;
			return true;
		}

		public bool IsOwner(long owner, string token, double now)
		{
			Advance(now);
			return Matches(owner, token);
		}

		public bool Renew(long owner, string token, double now)
		{
			if (!IsOwner(owner, token, now))
			{
				return false;
			}
			ExpiresAt = now + _leaseSeconds;
			return true;
		}

		public bool Release(long owner, string token)
		{
			if (!Matches(owner, token))
			{
				return false;
			}
			Clear();
			return true;
		}

		private bool Matches(long owner, string token)
		{
			if (owner != 0L && Owner == owner)
			{
				return string.Equals(Token, token, StringComparison.Ordinal);
			}
			return false;
		}

		private void Clear()
		{
			Owner = 0L;
			Token = string.Empty;
			ExpiresAt = 0.0;
		}
	}
	public sealed class StrandedGuardTimeout
	{
		public const double Seconds = 30.0;

		private double? _since;

		private double _lastObserved;

		private float _health;

		public bool Observe(double now, float health, bool eligible)
		{
			if (!eligible || double.IsNaN(now) || double.IsInfinity(now) || now < 0.0 || float.IsNaN(health) || float.IsInfinity(health) || health <= 0f)
			{
				_since = null;
				return false;
			}
			if (!_since.HasValue || now < _lastObserved || health != _health)
			{
				_since = now;
			}
			_health = health;
			_lastObserved = now;
			return now - _since.Value >= 30.0;
		}
	}
	public enum TrialCreature
	{
		Greydwarf,
		Bear,
		Troll
	}
	public static class TrialSpawnRules
	{
		public const int HardEnemyLimit = 50;

		public const double MinimumInterval = 0.1;

		public const int MaximumModifiers = 5;

		public const int TrialMaximumModifiers = 3;

		public static TrialCreature CreatureAt(int spawnIndex)
		{
			if (spawnIndex < 0)
			{
				throw new ArgumentOutOfRangeException("spawnIndex");
			}
			if (spawnIndex < 5)
			{
				return TrialCreature.Greydwarf;
			}
			return ((spawnIndex - 5) % 20) switch
			{
				19 => TrialCreature.Troll, 
				9 => TrialCreature.Bear, 
				_ => TrialCreature.Greydwarf, 
			};
		}

		public static double Interval(double combatSeconds)
		{
			ValidateTime(combatSeconds);
			return Math.Max(0.1, 10.0 / Math.Pow(100.0, Math.Min(combatSeconds, 90.0) / 90.0));
		}

		public static int ModifierCeiling(double combatSeconds)
		{
			ValidateTime(combatSeconds);
			if (!(combatSeconds < 50.0))
			{
				if (!(combatSeconds < 85.0))
				{
					return 3;
				}
				return 2;
			}
			return 1;
		}

		public static int ModifierCount(double combatSeconds, int spawnIndex)
		{
			if (spawnIndex < 0)
			{
				throw new ArgumentOutOfRangeException("spawnIndex");
			}
			return 1 + spawnIndex % ModifierCeiling(combatSeconds);
		}

		private static void ValidateTime(double combatSeconds)
		{
			if (double.IsNaN(combatSeconds) || double.IsInfinity(combatSeconds) || combatSeconds < 0.0)
			{
				throw new ArgumentOutOfRangeException("combatSeconds");
			}
		}
	}
	public static class VoidAttackGeometry
	{
		public static (float[] Vertices, int[] Triangles, float[] UV) Shell(bool seed)
		{
			List<float> list = new List<float>();
			List<float> list2 = new List<float>();
			List<int> list3 = new List<int>();
			int num = (seed ? 5 : 3);
			int num2 = (seed ? 11 : 9);
			for (int i = 0; i < num; i++)
			{
				int num3 = list.Count / 3;
				for (int j = 0; j < num2; j++)
				{
					float num4 = (float)j / (float)(num2 - 1);
					float num5 = (float)Math.Sin((double)num4 * Math.PI);
					float num6 = (float)i * MathF.PI * 2f / (float)num + (seed ? 0.36f : 0.65f) * (num4 - 0.5f);
					float num7 = (seed ? (0.38f + 0.32f * num5) : (0.2f + 0.16f * num5));
					float num8 = (seed ? 0.3f : 0.13f) * (float)Math.Pow(num5, 0.6) + 0.008f;
					float item = (num4 - 0.5f) * (seed ? 1.65f : 2.7f) + ((i % 2 == 0) ? 0.06f : (-0.09f)) * num5;
					float num9 = (seed ? (0.08f * (float)Math.Sin((double)num4 * Math.PI * 2.0)) : (0.22f * (num4 * num4 - 0.3f)));
					for (int k = 0; k < 4; k++)
					{
						float num10 = ((k >= 2) ? 1 : (-1));
						float num11 = ((k == 0 || k == 3) ? (-0.035f) : 0.055f);
						float item2 = (num7 + num11) * (float)Math.Cos(num6) - num10 * num8 * (float)Math.Sin(num6) + num9;
						float item3 = (num7 + num11) * (float)Math.Sin(num6) + num10 * num8 * (float)Math.Cos(num6);
						list.Add(item2);
						list.Add(item);
						list.Add(item3);
						list2.Add(0.015f + 0.97f * ((float)i / (float)num + (float)k / (float)(4 * num)));
						list2.Add(0.015f + 0.97f * num4);
					}
				}
				for (int l = 0; l < num2 - 1; l++)
				{
					for (int m = 0; m < 4; m++)
					{
						int num12 = num3 + l * 4 + m;
						int num13 = num3 + l * 4 + (m + 1) % 4;
						int item4 = num12 + 4;
						int item5 = num13 + 4;
						list3.Add(num12);
						list3.Add(num13);
						list3.Add(item4);
						list3.Add(item4);
						list3.Add(num13);
						list3.Add(item5);
					}
				}
				int[] array = new int[2]
				{
					0,
					num2 - 1
				};
				foreach (int num14 in array)
				{
					int num15 = num3 + num14 * 4;
					if (num14 == 0)
					{
						list3.Add(num15);
						list3.Add(num15 + 2);
						list3.Add(num15 + 1);
						list3.Add(num15);
						list3.Add(num15 + 3);
						list3.Add(num15 + 2);
					}
					else
					{
						list3.Add(num15);
						list3.Add(num15 + 1);
						list3.Add(num15 + 2);
						list3.Add(num15);
						list3.Add(num15 + 2);
						list3.Add(num15 + 3);
					}
				}
			}
			for (int num16 = 0; num16 < list3.Count; num16 += 3)
			{
				int value = list3[num16];
				list3[num16] = list3[num16 + 2];
				list3[num16 + 2] = value;
			}
			return (Vertices: list.ToArray(), Triangles: list3.ToArray(), UV: list2.ToArray());
		}

		public static (float[] Vertices, int[] Triangles, float[] UV) Core(bool seed)
		{
			List<float> list = new List<float>();
			List<float> list2 = new List<float>();
			List<int> list3 = new List<int>();
			for (int i = 0; i < 11; i++)
			{
				for (int j = 0; j <= 16; j++)
				{
					float num = (float)i / 10f;
					float num2 = (float)j / 16f * MathF.PI * 2f;
					float num3 = (seed ? 0.44f : 0.17f) * (0.035f + 0.965f * (float)Math.Pow(Math.Sin((double)num * Math.PI), 0.75));
					num3 *= 1f + 0.1f * (float)Math.Sin(num2 * 3f + num * 9f) + 0.06f * (float)Math.Cos(num2 * 5f - num * 7f);
					list.Add(num3 * (float)Math.Cos(num2));
					list.Add((num - 0.5f) * (seed ? 1.4f : 2.25f));
					list.Add(num3 * (float)Math.Sin(num2));
					list2.Add(0.015f + 0.97f * (float)j / 16f);
					list2.Add(0.015f + 0.97f * num);
					if (i != 10 && j != 16)
					{
						int num4 = i * 17 + j;
						int num5 = num4 + 16 + 1;
						list3.Add(num4);
						list3.Add(num5);
						list3.Add(num4 + 1);
						list3.Add(num4 + 1);
						list3.Add(num5);
						list3.Add(num5 + 1);
					}
				}
			}
			return (Vertices: list.ToArray(), Triangles: list3.ToArray(), UV: list2.ToArray());
		}

		public static (float[] Vertices, int[] Triangles, float[] UV) ImpactBloom()
		{
			List<float> list = new List<float>();
			List<float> list2 = new List<float>();
			List<int> list3 = new List<int>();
			for (int i = 0; i < 9; i++)
			{
				for (int j = 0; j <= 24; j++)
				{
					float num = (float)i / 8f;
					float num2 = (float)j / 24f * MathF.PI * 2f;
					float num3 = (float)Math.Sin((double)num * Math.PI);
					float num4 = 1f + 0.18f * (float)Math.Sin(num2 * 5f + num * 4f) + 0.09f * (float)Math.Cos(num2 * 3f - num * 7f);
					float num5 = num3 * num4;
					list.Add(num5 * (float)Math.Cos(num2));
					list.Add(num * 1.65f + num3 * 0.13f * (float)Math.Sin(num2 * 5f + num * 3f));
					list.Add(num5 * (float)Math.Sin(num2));
					list2.Add(0.02f + 0.96f * (float)j / 24f);
					list2.Add(0.02f + 0.96f * num);
					if (i != 8 && j != 24)
					{
						int num6 = i * 25 + j;
						int num7 = num6 + 24 + 1;
						if (i > 0)
						{
							list3.Add(num6);
							list3.Add(num6 + 1);
							list3.Add(num7);
						}
						if (i < 7)
						{
							list3.Add(num6 + 1);
							list3.Add(num7 + 1);
							list3.Add(num7);
						}
					}
				}
			}
			return (Vertices: list.ToArray(), Triangles: list3.ToArray(), UV: list2.ToArray());
		}

		public static (float[] Vertices, int[] Triangles, float[] UV) Impact()
		{
			List<float> list = new List<float>();
			List<float> list2 = new List<float>();
			List<int> list3 = new List<int>();
			for (int i = 0; i < 7; i++)
			{
				for (int j = 0; j <= 32; j++)
				{
					float num = (float)i / 6f;
					float num2 = (float)j / 32f * MathF.PI * 2f;
					float num3 = 0.015f + 0.985f * num;
					list.Add(num3 * (float)Math.Cos(num2));
					list.Add((1f - num * num) * 0.45f);
					list.Add(num3 * (float)Math.Sin(num2));
					list2.Add(0.5f + 0.48f * num3 * (float)Math.Cos(num2));
					list2.Add(0.5f + 0.48f * num3 * (float)Math.Sin(num2));
					if (i != 6 && j != 32)
					{
						int num4 = i * 33 + j;
						int num5 = num4 + 32 + 1;
						list3.Add(num4);
						list3.Add(num4 + 1);
						list3.Add(num5);
						list3.Add(num4 + 1);
						list3.Add(num5 + 1);
						list3.Add(num5);
					}
				}
			}
			return (Vertices: list.ToArray(), Triangles: list3.ToArray(), UV: list2.ToArray());
		}
	}
	public static class VoidBlobRules
	{
		public const string Prefab = "Beyond_VoidBlob";

		public const float Scale = 0.5159053f;

		public const float Health = 400f;

		public const float SpiritDamage = 125f;

		public const float Radius = 3.2f;

		public const double Windup = 0.85;

		public const double ReleaseGrace = 0.25;

		public const double AttackInterval = 3.6;

		public static bool CanResolve(double age, bool resolved, bool ownedBeforeRelease)
		{
			if (!double.IsNaN(age) && !double.IsInfinity(age) && !resolved && ownedBeforeRelease && age >= 0.85)
			{
				return age <= 1.1;
			}
			return false;
		}

		public static string SummonPrefab(int lifetimeIndex)
		{
			if (lifetimeIndex < 0 || lifetimeIndex >= 6)
			{
				throw new ArgumentOutOfRangeException("lifetimeIndex");
			}
			return (lifetimeIndex % 3) switch
			{
				0 => "Beyond_VoidBlob", 
				1 => VoidCreatureRules.Prefab(VoidKind.Stalker), 
				_ => VoidCreatureRules.Prefab(VoidKind.Cantor), 
			};
		}
	}
	public static class VoidBroodRules
	{
		public const int Children = 6;

		public const int MaximumCasts = 2;

		public const int MaximumAttempts = 30;

		public const double InitialDelay = 10.0;

		public const double Cooldown = 40.0;

		public const double Lifetime = 4.0;

		public const double MaximumStep = 0.35;

		public const double QueueLifetime = 20.0;

		public const float Reach = 24f;

		public const float Gravity = 12f;

		public const float Radius = 0.42f;

		public static bool CanCast(double now, double nextCast, int casts, int living, int remaining, bool flying, bool ritualPending)
		{
			if (Finite(now) && Finite(nextCast) && now >= nextCast && casts >= 0 && casts < 2 && living == 0 && remaining == 0 && !flying)
			{
				return !ritualPending;
			}
			return false;
		}

		public static bool CanSweep(double age, double previous, bool continuousOwner)
		{
			if (continuousOwner && Finite(age) && Finite(previous) && previous >= 0.0 && age > previous && age <= 4.0)
			{
				return age - previous <= 0.35;
			}
			return false;
		}

		public static float FlightTime(float horizontalDistance)
		{
			return Math.Max(0.7f, Math.Min(1.8f, horizontalDistance / 12f));
		}

		public static float PlacementRadius(int attempt)
		{
			return 2.6f + (float)(Math.Max(0, attempt) % 3) * 0.85f + Math.Min(3f, (float)(Math.Max(0, attempt) / 6) * 0.75f);
		}

		public static Vector3 Velocity(Vector3 start, Vector3 aim)
		{
			Vector3 vector = aim - start;
			float num = FlightTime(new Vector2(vector.X, vector.Z).Length());
			return vector / num + Vector3.UnitY * (12f * num * 0.5f);
		}

		public static Vector3 Position(Vector3 start, Vector3 velocity, float age)
		{
			return start + velocity * age - Vector3.UnitY * (12f * age * age * 0.5f);
		}

		private static bool Finite(double value)
		{
			if (!double.IsNaN(value))
			{
				return !double.IsInfinity(value);
			}
			return false;
		}
	}
	public enum VoidKind
	{
		Eidolon,
		Stalker,
		Cantor
	}
	public enum VoidAttack
	{
		None,
		Sweep,
		ReturnSweep,
		Fracture,
		Pulse,
		Advance,
		Pounce,
		Claw,
		Shards,
		Rupture,
		Summon,
		Brood
	}
	public static class VoidCreatureRules
	{
		public const int MaximumAdds = 3;

		public const int LifetimeAdds = 6;

		public const float ClawReach = 4.2f;

		public const float ClawArc = 75f;

		public const float PounceReach = 8f;

		public const float PounceRadius = 2.2f;

		public const float SweepReach = 7f;

		public const float SweepArc = 100f;

		public const float FractureReach = 16f;

		public const float AdvanceReach = 10f;

		public const float PulseInner = 3f;

		public const float PulseOuter = 17f;

		public const float ShardReach = 44f;

		public const float ShardSpeed = 12f;

		public const float RuptureRadius = 3f;

		public static string Prefab(VoidKind kind)
		{
			return kind switch
			{
				VoidKind.Eidolon => "Beyond_VoidEidolon", 
				VoidKind.Stalker => "Beyond_Riftstalker", 
				_ => "Beyond_HollowCantor", 
			};
		}

		public static float Health(VoidKind kind)
		{
			return kind switch
			{
				VoidKind.Eidolon => 45000, 
				VoidKind.Stalker => 1800, 
				_ => 1400, 
			};
		}

		public static int Phase(float fraction)
		{
			if (!(fraction <= 0.3f))
			{
				return (fraction <= 0.65f) ? 1 : 0;
			}
			return 2;
		}

		public static int NewThresholds(float fraction, int handled)
		{
			return (int)(((Phase(fraction) >= 1) ? 1u : 0u) | (uint)((Phase(fraction) >= 2) ? 2 : 0)) & ~handled;
		}

		public static float Windup(VoidAttack attack)
		{
			return attack switch
			{
				VoidAttack.Sweep => 0.65f, 
				VoidAttack.ReturnSweep => 0.6f, 
				VoidAttack.Fracture => 1.05f, 
				VoidAttack.Pulse => 1.3f, 
				VoidAttack.Advance => 0.9f, 
				VoidAttack.Pounce => 0.3f, 
				VoidAttack.Claw => 0.5f, 
				VoidAttack.Shards => 0.7f, 
				VoidAttack.Rupture => 1.05f, 
				VoidAttack.Summon => 1.5f, 
				VoidAttack.Brood => 1.2f, 
				_ => 0f, 
			};
		}

		public static float Active(VoidAttack attack)
		{
			switch (attack)
			{
			case VoidAttack.Sweep:
			case VoidAttack.ReturnSweep:
				return 0.28f;
			case VoidAttack.Pulse:
				return 1.4f;
			case VoidAttack.Fracture:
				return 0.9f;
			case VoidAttack.Advance:
				return 0.85f;
			case VoidAttack.Pounce:
				return 0.7f;
			case VoidAttack.Claw:
				return 0.34f;
			case VoidAttack.Shards:
				return 4f;
			default:
				return 0.2f;
			}
		}

		public static float StrikeDelay(VoidAttack attack)
		{
			if (((uint)(attack - 1) > 1u && attack != VoidAttack.Claw) || 1 == 0)
			{
				return 0f;
			}
			return Active(attack) * 0.45f;
		}

		public static float Recovery(VoidAttack attack)
		{
			return attack switch
			{
				VoidAttack.Claw => 0.5f, 
				VoidAttack.Pounce => 0.75f, 
				VoidAttack.Sweep => 0.75f, 
				VoidAttack.ReturnSweep => 0.85f, 
				VoidAttack.Shards => 0.85f, 
				_ => 1.05f, 
			};
		}

		public static float Duration(VoidAttack attack)
		{
			return Windup(attack) + Active(attack) + Recovery(attack);
		}

		public static float Damage(VoidAttack attack)
		{
			return attack switch
			{
				VoidAttack.Sweep => 600, 
				VoidAttack.ReturnSweep => 575, 
				VoidAttack.Fracture => 900, 
				VoidAttack.Pulse => 700, 
				VoidAttack.Advance => 875, 
				VoidAttack.Pounce => 675, 
				VoidAttack.Claw => 600, 
				VoidAttack.Shards => 475, 
				VoidAttack.Rupture => 550, 
				_ => 0, 
			};
		}

		public static float SpiritShare(VoidAttack attack)
		{
			switch (attack)
			{
			case VoidAttack.Sweep:
			case VoidAttack.ReturnSweep:
			case VoidAttack.Pounce:
				return 0.25f;
			case VoidAttack.Fracture:
			case VoidAttack.Advance:
				return 0.3f;
			case VoidAttack.Pulse:
				return 0.7f;
			case VoidAttack.Claw:
				return 0.2f;
			case VoidAttack.Shards:
				return 0.6f;
			case VoidAttack.Rupture:
				return 0.65f;
			default:
				return 0f;
			}
		}

		public static bool IsWindowLive(double age, VoidAttack attack)
		{
			if (!double.IsNaN(age) && !double.IsInfinity(age) && age >= (double)Windup(attack))
			{
				return age <= (double)(Windup(attack) + Active(attack));
			}
			return false;
		}
	}
	public static class VoidLocomotion
	{
		public const float BossEngageRange = 6.5f;

		public const float BossCycleMetres = 3.2f;

		public const float HunterCycleMetres = 2.6f;

		public const float HunterSpeed = 5.85f;

		public const float HunterRunSpeed = 9.75f;

		public const float EngageFraction = 0.8f;

		public static float EngageDistance(VoidAttack attack)
		{
			float num;
			switch (attack)
			{
			case VoidAttack.Claw:
				num = 4.2f;
				break;
			case VoidAttack.Pounce:
				num = 8f;
				break;
			case VoidAttack.Shards:
			case VoidAttack.Rupture:
				num = 44f;
				break;
			default:
				num = 0f;
				break;
			}
			return 0.8f * num;
		}

		public static bool CanEngage(VoidAttack attack, float distance)
		{
			if (float.IsFinite(distance) && distance >= 0f && EngageDistance(attack) > 0f)
			{
				return distance <= EngageDistance(attack);
			}
			return false;
		}

		public static bool BossMustApproach(float distance)
		{
			if (float.IsFinite(distance))
			{
				return distance > 6.5f;
			}
			return false;
		}

		public static float PhaseStep(float horizontalSpeed, float dt, float cycleMetres = 3.2f)
		{
			if (!float.IsFinite(horizontalSpeed) || !float.IsFinite(dt) || !float.IsFinite(cycleMetres) || horizontalSpeed <= 0.04f || dt <= 0f || cycleMetres <= 0f)
			{
				return 0f;
			}
			return Math.Min(horizontalSpeed, 20f) * Math.Min(dt, 0.1f) * (MathF.PI * 2f / cycleMetres);
		}
	}
	public sealed class VoidBone
	{
		public string Name { get; }

		public string Parent { get; }

		public float[] Position { get; }

		public VoidBone(string name, string parent, float x, float y, float z)
		{
			Name = name;
			Parent = parent;
			Position = new float[3] { x, y, z };
		}
	}
	public sealed class VoidPart
	{
		public string Bone { get; }

		public string Shape { get; }

		public int Material { get; }

		public float[] Position { get; }

		public float[] Size { get; }

		public float[] Rotation { get; }

		public VoidPart(string bone, string shape, int material, float x, float y, float z, float sx, float sy, float sz, float rx, float ry, float rz)
		{
			Bone = bone;
			Shape = shape;
			Material = material;
			Position = new float[3] { x, y, z };
			Size = new float[3] { sx, sy, sz };
			Rotation = new float[3] { rx, ry, rz };
		}
	}
	public sealed class VoidModelBlueprint
	{
		public List<VoidBone> Bones { get; } = new List<VoidBone>();

		public List<VoidPart> Parts { get; } = new List<VoidPart>();

		private void Bone(string name, string parent, float x, float y, float z)
		{
			Bones.Add(new VoidBone(name, parent, x, y, z));
		}

		private void Part(string bone, float x, float y, float z, float sx, float sy, float sz, int mat = 0, string shape = "shell", float rx = 0f, float ry = 0f, float rz = 0f)
		{
			Parts.Add(new VoidPart(bone, shape, mat, x, y, z, sx, sy, sz, rx, ry, rz));
		}

		public static VoidModelBlueprint Create(VoidKind kind)
		{
			VoidModelBlueprint voidModelBlueprint = new VoidModelBlueprint();
			switch (kind)
			{
			case VoidKind.Eidolon:
				voidModelBlueprint.Boss();
				break;
			case VoidKind.Stalker:
				voidModelBlueprint.Hunter();
				break;
			default:
				voidModelBlueprint.Caster();
				break;
			}
			return voidModelBlueprint;
		}

		private void Boss()
		{
			Bone("body", "", 0f, 2.15f, 0f);
			Bone("chest", "body", 0f, 1f, 0f);
			Bone("head", "chest", 0f, 1.05f, 0f);
			Bone("core", "chest", 0f, 0f, 0.12f);
			Part("body", 0f, 0f, 0f, 1.15f, 0.62f, 0.65f);
			Part("body", 0f, -0.3f, 0.28f, 0.48f, 0.65f, 0.22f, 1, "shell", 0f, 0f, 180f);
			for (int i = -1; i <= 1; i += 2)
			{
				string text = ((i < 0) ? "L" : "R");
				Bone("arm" + text, "chest", (float)i * 0.92f, 0.43f, 0f);
				Bone("fore" + text, "arm" + text, (float)i * 0.12f, -0.9f, 0f);
				if (i > 0)
				{
					Bone("handR", "foreR", 0.24f, -0.7f, 0.31f);
				}
				Bone("leg" + text, "body", (float)i * 0.44f, -0.13f, 0f);
				Bone("shin" + text, "leg" + text, 0f, -0.98f, 0f);
				Bone("foot" + text, "shin" + text, 0f, -0.8f, 0.15f);
				Part("chest", (float)i * 0.57f, 0.1f, 0f, 0.36f, 1.15f, 0.62f, 0, "shell", 0f, 0f, i * -12);
				Part("chest", (float)i * 0.37f, 0.55f, 0.03f, 0.76f, 0.3f, 0.67f, 0, "shell", 0f, 0f, i * 20);
				Part("chest", (float)i * 0.4f, -0.47f, 0.07f, 0.64f, 0.3f, 0.59f, 0, "shell", 0f, 0f, i * -28);
				for (int j = 0; j < 3; j++)
				{
					Part("chest", (float)i * (0.49f - (float)j * 0.035f), 0.32f - (float)j * 0.3f, 0.32f, 0.42f, 0.105f, 0.27f, 1, "shell", 0f, 0f, i * (24 - j * 24));
				}
				Part("arm" + text, (float)i * 0.13f, -0.12f, 0f, 0.9f, 0.65f, 0.85f, 0, "shell", 0f, 0f, i * 20);
				Part("arm" + text, (float)i * 0.36f, 0.1f, -0.04f, 0.42f, 0.35f, 0.35f, 1, "shell", 0f, 0f, i * -25);
				Part("arm" + text, 0f, -0.57f, 0f, 0.44f, 0.82f, 0.48f, 0, "shell", 0f, 0f, i * -8);
				Part("arm" + text, 0f, -0.52f, 0.235f, 0.14f, 0.6f, 0.04f, 2, "shell", 0f, 0f, i * -8);
				Part("fore" + text, 0f, -0.48f, 0f, 0.55f, 0.95f, 0.57f, 0, "shell", 0f, 0f, i * 7);
				Part("fore" + text, 0f, -0.52f, 0.29f, 0.3f, 0.7f, 0.07f, 1, "shell", 0f, 0f, i * 7);
				Part("fore" + text, 0f, -0.99f, 0.08f, 0.44f, 0.34f, 0.48f);
				for (int k = 0; k < 3; k++)
				{
					Part("fore" + text, (float)(k - 1) * 0.13f, -1.16f, 0.2f, 0.12f, 0.3f, 0.15f, 1, "shell", -20f);
				}
				Part("body", (float)i * 0.52f, -0.3f, 0.02f, 0.44f, 0.84f, 0.7f, 0, "shell", 0f, 0f, i * 18);
				Part("leg" + text, 0f, -0.46f, 0f, 0.51f, 0.94f, 0.62f, 0, "shell", 0f, 0f, i * 4);
				Part("leg" + text, 0f, -0.51f, 0.31f, 0.18f, 0.53f, 0.045f, 1);
				Part("shin" + text, 0f, -0.43f, 0f, 0.42f, 0.87f, 0.48f);
				Part("shin" + text, 0f, -0.44f, 0.245f, 0.08f, 0.65f, 0.035f, 2);
				Part("foot" + text, 0f, -0.03f, 0.05f, 0.56f, 0.3f, 0.89f);
				Part("head", (float)i * 0.2f, 0.05f, 0f, 0.34f, 0.53f, 0.5f, 0, "shell", 0f, 0f, i * -9);
				Part("head", (float)i * 0.28f, 0.32f, -0.04f, 0.27f, 0.44f, 0.31f, 1, "shell", 0f, 0f, i * -18);
				Part("head", (float)i * 0.13f, 0.04f, 0.29f, 0.13f, 0.065f, 0.025f, 2, "shell", 0f, 0f, i * 14);
			}
			Part("head", 0f, -0.21f, 0.02f, 0.39f, 0.23f, 0.4f);
			Part("head", 0f, -0.05f, 0.28f, 0.065f, 0.42f, 0.06f, 2);
			Part("chest", 0f, 0.04f, -0.3f, 0.31f, 1.2f, 0.25f);
			Part("core", 0f, 0f, 0f, 0.42f, 0.62f, 0.42f, 2, "crystal", 0f, 0f, 18f);
			Part("core", 0f, 0f, 0f, 0.56f, 0.21f, 0.56f, 1, "crystal", 0f, 45f);
			Part("foreR", 0.37f, -0.55f, 0.08f, 0.33f, 1.85f, 0.3f, 0, "blade", 0f, 0f, -15f);
			Part("foreR", 0.57f, -0.54f, 0.08f, 0.1f, 1.7f, 0.13f, 2, "blade", 0f, 0f, -15f);
			for (int l = 0; l < 3; l++)
			{
				Part("chest", 0f, 0.4f - (float)l * 0.35f, -0.4f, 0.35f, 0.25f, 0.29f, 1, "shell", -20f);
			}
		}

		private void Hunter()
		{
			Bone("body", "", 0f, 0.98f, -0.12f);
			Bone("thorax", "body", 0f, 0.02f, 0.35f);
			Bone("abdomen", "body", 0f, 0f, -0.48f);
			Bone("head", "thorax", 0f, 0.02f, 0.67f);
			Bone("tail", "abdomen", 0f, 0.03f, -0.47f);
			Bone("tailtip", "tail", 0f, 0f, -0.72f);
			Part("thorax", 0f, 0.15f, 0.35f, 0.64f, 0.28f, 0.55f);
			Part("abdomen", 0f, 0.1f, -0.15f, 0.54f, 0.3f, 0.52f);
			Part("body", 0f, 0.02f, -0.08f, 0.12f, 1.15f, 0.12f, 2, "shell", 90f);
			for (int i = 0; i < 3; i++)
			{
				Part("body", 0f, 0.27f, -0.57f + (float)i * 0.35f, 0.39f, 0.18f, 0.4f, 1, "shell", 8f);
				Part("body", 0f, 0.37f, -0.57f + (float)i * 0.35f, 0.035f, 0.035f, 0.22f, 2);
			}
			for (int j = -1; j <= 1; j += 2)
			{
				string text = ((j < 0) ? "L" : "R");
				Bone("neck" + text, "head", (float)j * 0.24f, 0.045f, -0.08f);
				Bone("head" + text, "neck" + text, 0f, 0.025f, 0.16f);
				Bone("jaw" + text, "head" + text, 0f, -0.08f, 0.06f);
				Part("neck" + text, 0f, 0f, 0.04f, 0.24f, 0.22f, 0.35f);
				Part("thorax", (float)j * 0.23f, 0.02f, 0.41f, 0.22f, 0.26f, 0.6f, 0, "shell", 0f, j * 12);
				for (int k = 0; k < 4; k++)
				{
					Part("body", (float)j * 0.25f, -0.025f, -0.5f + (float)k * 0.3f, 0.15f, 0.39f, 0.18f, 1, "shell", 0f, 0f, j * -22);
				}
				for (int l = 0; l < 2; l++)
				{
					string text2 = ((l == 0) ? "front" : "rear") + text;
					Bone(text2, (l == 0) ? "thorax" : "abdomen", (float)j * 0.28f, -0.03f, (l == 0) ? (-0.03f) : (-0.14f));
					Bone(text2 + "lower", text2, (float)j * 0.28f, -0.35f, (l == 0) ? (-0.14f) : 0.14f);
					Bone(text2 + "foot", text2 + "lower", (float)j * 0.1f, -0.49f, 0.06f);
					Part(text2, (float)j * 0.12f, -0.12f, 0f, 0.24f, 0.58f, 0.26f, 0, "shell", rz: j * 38, rx: (l == 0) ? 18 : (-18));
					Part(text2 + "lower", (float)j * 0.07f, -0.24f, 0f, 0.19f, 0.65f, 0.2f, 0, "shell", rz: j * 12, rx: (l == 0) ? (-12) : 12);
					Part(text2 + "foot", (float)j * 0.04f, -0.02f, 0.11f, 0.25f, 0.13f, 0.4f, 1);
					Part(text2, (float)j * 0.17f, -0.09f, -0.02f, 0.24f, 0.23f, 0.28f, 1, "shell", 0f, 0f, j * -20);
				}
				Bone("sickle" + text, "thorax", (float)j * 0.37f, 0.12f, 0.27f);
				Bone("hook" + text, "sickle" + text, (float)j * 0.14f, -0.26f, 0.35f);
				Part("sickle" + text, (float)j * 0.08f, -0.12f, 0.16f, 0.24f, 0.58f, 0.25f, 0, "shell", -52f, 0f, j * 15);
				Part("hook" + text, (float)j * 0.06f, -0.19f, 0.19f, 0.2f, 0.65f, 0.26f, 0, "blade", -32f, 0f, j * -12);
				Part("hook" + text, (float)j * 0.12f, -0.16f, 0.23f, 0.04f, 0.56f, 0.08f, 2, "blade", -32f, 0f, j * -12);
				for (int m = -1; m <= 1; m += 2)
				{
					Part("head" + text, (float)m * 0.105f, 0.02f, 0.23f, 0.21f, 0.65f, 0.32f, 0, "shell", 90f, 0f, m * 7);
					Part("jaw" + text, (float)m * 0.1f, -0.06f, 0.22f, 0.105f, 0.4f, 0.14f, 1, "shell", 80f, 0f, m * -8);
				}
				Part("head" + text, 0f, 0.02f, 0.23f, 0.04f, 0.55f, 0.06f, 2, "shell", 90f);
			}
			Part("tail", 0f, 0f, -0.3f, 0.26f, 0.77f, 0.25f, 0, "shell", 90f);
			Part("tailtip", 0f, 0.01f, -0.28f, 0.18f, 0.68f, 0.19f, 1, "shell", 90f);
			Part("tailtip", 0f, 0.07f, -0.45f, 0.035f, 0.29f, 0.05f, 2, "shell", 90f);
		}

		private void Caster()
		{
			Bone("body", "", 0f, 1.25f, 0f);
			Bone("chest", "body", 0f, 0.26f, 0f);
			Bone("head", "chest", 0f, 0.6f, 0f);
			Bone("core", "chest", 0f, 0.27f, 0.05f);
			for (int i = -1; i <= 1; i += 2)
			{
				string text = ((i < 0) ? "L" : "R");
				Bone("veil" + text, "body", (float)i * 0.25f, -0.28f, 0f);
				Bone("arm" + text, "chest", (float)i * 0.48f, 0.26f, 0f);
				Bone("fore" + text, "arm" + text, (float)i * 0.14f, -0.42f, 0.06f);
				Part("chest", (float)i * 0.28f, 0f, -0.01f, 0.21f, 0.78f, 0.43f, 0, "shell", 0f, 0f, i * -8);
				Part("arm" + text, (float)i * 0.12f, -0.03f, 0f, 0.46f, 0.32f, 0.45f, 0, "shell", 0f, 0f, i * 22);
				Part("arm" + text, (float)i * 0.06f, -0.29f, 0f, 0.19f, 0.57f, 0.24f, 0, "shell", 0f, 0f, i * 14);
				Part("fore" + text, 0f, -0.24f, 0.01f, 0.18f, 0.53f, 0.22f, 0, "shell", -22f);
				Part("fore" + text, 0f, -0.48f, 0.14f, 0.22f, 0.23f, 0.23f, 1);
				for (int j = 0; j < 3; j++)
				{
					Part("fore" + text, (float)(j - 1) * 0.065f, -0.56f, 0.27f, 0.06f, 0.18f, 0.07f, 1, "shell", -55f);
				}
				Part("head", (float)i * 0.25f, 0.02f, 0f, 0.22f, 0.68f, 0.5f, 0, "shell", 0f, 0f, i * -13);
				Part("head", (float)i * 0.15f, 0.33f, -0.01f, 0.34f, 0.17f, 0.51f, 0, "shell", 0f, 0f, i * 26);
				Part("head", (float)i * 0.2f, 0.09f, 0.255f, 0.035f, 0.29f, 0.025f, 2, "shell", 0f, 0f, i * -13);
				for (int k = 0; k < 3; k++)
				{
					Part("chest", (float)i * 0.22f, 0.19f - (float)k * 0.19f, 0.25f, 0.26f, 0.055f, 0.14f, 1, "shell", 0f, 0f, i * (28 - k * 20));
				}
				for (int l = 0; l < 3; l++)
				{
					Part("veil" + text, (float)i * (-0.04f + (float)l * 0.07f), -0.11f, -0.08f + (float)l * 0.18f, 0.27f, 0.96f, 0.24f, (l == 1) ? 1 : 0, "shell", -8f, 0f, i * (8 + l * 5));
				}
			}
			Part("head", 0f, 0.08f, -0.21f, 0.47f, 0.61f, 0.14f);
			Part("head", 0f, 0.38f, -0.07f, 0.29f, 0.31f, 0.26f, 1);
			Part("core", 0f, 0f, 0f, 0.19f, 0.39f, 0.19f, 2, "crystal");
			Part("chest", 0f, -0.3f, 0.08f, 0.23f, 0.3f, 0.29f, 1, "crystal");
			Part("body", 0f, -0.55f, 0.18f, 0.1f, 0.53f, 0.08f, 2, "crystal");
		}

		public static (float[] Vertices, int[] Triangles, float[] UV) Geometry(string shape)
		{
			int sides = ((shape == "shell") ? 10 : ((shape == "plate") ? 8 : 6));
			float[] heights = ((!(shape == "shell")) ? ((!(shape == "spike")) ? new floa