Decompiled source of Quads Arena v0.4.3

plugins/Arena.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DHack.Shared;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json.Linq;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially or fully created with the assistance of Generative AI (Claude Code).")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Arena
{
	internal static class Armoury
	{
		internal enum Slot
		{
			Weapon,
			Shield,
			Helmet,
			Chest,
			Legs
		}

		internal static readonly string[] SlotWords = new string[5] { "weapon", "shield", "helmet", "chest", "legs" };

		private static readonly int[] Base = new int[7] { 20, 80, 200, 400, 700, 1100, 1600 };

		private static readonly int[] CoinsByLand = new int[7] { 6, 12, 20, 30, 42, 56, 72 };

		internal static int Cap => Mathf.Min(Contest.Tier + 1, Roster.TierNames.Length - 1);

		private static string[] List(Slot slot, int style)
		{
			return slot switch
			{
				Slot.Weapon => Kit.Weapons[Mathf.Clamp(style, 0, Kit.Styles.Length - 1)], 
				Slot.Shield => Kit.Shields, 
				_ => Kit.Armour.Select((string[] a) => a[(int)(slot - 2)]).ToArray(), 
			};
		}

		private static string PrefabOf(string entry)
		{
			int num = entry.IndexOf(':');
			if (num <= 0)
			{
				return entry;
			}
			return entry.Substring(0, num);
		}

		private static int QualityOf(string entry)
		{
			int num = entry.IndexOf(':');
			if (num <= 0 || !int.TryParse(entry.Substring(num + 1), out var result))
			{
				return 2;
			}
			return result;
		}

		internal static List<Slot> Slots(int style, bool fists)
		{
			if (fists)
			{
				return new List<Slot>
				{
					Slot.Helmet,
					Slot.Chest,
					Slot.Legs
				};
			}
			List<Slot> list = new List<Slot>
			{
				Slot.Weapon,
				Slot.Shield,
				Slot.Helmet,
				Slot.Chest,
				Slot.Legs
			};
			if (style == 4)
			{
				list.Remove(Slot.Shield);
			}
			return list;
		}

		internal static int TierOf(Player player, Slot slot, int style)
		{
			string[] array = List(slot, style);
			int num = -1;
			foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems())
			{
				string text = (((Object)(object)allItem.m_dropPrefab != (Object)null) ? ((Object)allItem.m_dropPrefab).name : "");
				for (int num2 = array.Length - 1; num2 > num; num2--)
				{
					if (PrefabOf(array[num2]) == text && allItem.m_quality >= QualityOf(array[num2]))
					{
						num = num2;
						break;
					}
				}
			}
			return num;
		}

		internal static int Price(Slot slot, int tier)
		{
			return Mathf.RoundToInt((float)Base[Mathf.Clamp(tier, 0, Base.Length - 1)] * slot switch
			{
				Slot.Shield => 0.4f, 
				Slot.Weapon => 1f, 
				_ => 0.6f, 
			});
		}

		internal static bool Next(Player player, Slot slot, int style, out int tier, out string prefab, out int quality, bool capped = false)
		{
			tier = TierOf(player, slot, style) + 1;
			prefab = null;
			quality = 2;
			if ((capped && tier > Cap) || tier >= Roster.TierNames.Length)
			{
				return false;
			}
			string[] array = List(slot, style);
			prefab = PrefabOf(array[tier]);
			quality = QualityOf(array[tier]);
			return Roster.Has(prefab);
		}

		internal static string Name(Player player, Slot slot, int style)
		{
			int num = TierOf(player, slot, style);
			if (num < 0)
			{
				return Translations.T("arena_slot_none");
			}
			string[] array = List(slot, style);
			return Contest.ItemName(PrefabOf(array[num])) + ((QualityOf(array[num]) > 2) ? (" ★" + QualityOf(array[num])) : "");
		}

		internal static (string Prefab, int Amount, int Quality, string Loan)? Random(Player player, int style, bool fists, string loan)
		{
			int tier2;
			string prefab2;
			int quality2;
			List<Slot> list = (from s in Slots(style, fists)
				where Next(player, s, style, out tier2, out prefab2, out quality2, capped: true)
				select s).ToList();
			if (list.Count == 0)
			{
				return null;
			}
			Slot slot = list[Random.Range(0, list.Count)];
			Next(player, slot, style, out var _, out var prefab, out var quality, capped: true);
			return (prefab, 1, quality, loan);
		}

		internal static void Bought(Player player, Slot slot, string prefab, int style)
		{
			if (Next(player, slot, style, out var tier, out var prefab2, out var quality) && !(prefab2 != prefab))
			{
				ItemData val = ((IEnumerable<ItemData>)((Humanoid)player).GetInventory().GetAllItems()).LastOrDefault((Func<ItemData, bool>)((ItemData i) => (Object)(object)i.m_dropPrefab != (Object)null && ((Object)i.m_dropPrefab).name == prefab && !Kit.IsLoan(i)));
				if (val != null)
				{
					val.m_quality = Mathf.Clamp(quality, 1, val.m_shared.m_maxQuality);
					val.m_durability = val.GetMaxDurability();
					val.m_customData["dh_arena_loan"] = tier.ToString();
					((Humanoid)player).EquipItem(val, false);
					Tidy(player, style);
				}
			}
		}

		internal static void Tidy(Player player, int style)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			Slot[] array = new Slot[5]
			{
				Slot.Weapon,
				Slot.Shield,
				Slot.Helmet,
				Slot.Chest,
				Slot.Legs
			};
			foreach (Slot slot in array)
			{
				string[] array2 = List(slot, style);
				int num = TierOf(player, slot, style);
				if (num < 0)
				{
					continue;
				}
				foreach (ItemData item in inventory.GetAllItems().ToList())
				{
					if (Kit.IsLoan(item) && !item.m_equipped && !((Object)(object)item.m_dropPrefab == (Object)null))
					{
						string name = ((Object)item.m_dropPrefab).name;
						int num2 = Array.FindLastIndex(array2, (string e) => PrefabOf(e) == name && item.m_quality >= QualityOf(e));
						if (num2 >= 0 && num2 < num)
						{
							inventory.RemoveItem(item);
						}
					}
				}
			}
		}

		internal static int MealPrice(int land)
		{
			return 10 + 10 * land;
		}

		internal static int HealingPrice(int land)
		{
			return 15 + 12 * land;
		}

		internal static int StaminaPrice(int land)
		{
			return 12 + 8 * land;
		}

		internal static int ArrowsPrice(int land)
		{
			return 10 + 8 * land;
		}

		internal static int SwitchPrice(int tier)
		{
			return Mathf.Max(20, Price(Slot.Weapon, Mathf.Max(1, tier)) / 2);
		}

		internal static void Switched(Player player, int style, string prefab, int tier, int quality)
		{
			ItemData val = ((IEnumerable<ItemData>)((Humanoid)player).GetInventory().GetAllItems()).LastOrDefault((Func<ItemData, bool>)((ItemData i) => (Object)(object)i.m_dropPrefab != (Object)null && ((Object)i.m_dropPrefab).name == prefab && !Kit.IsLoan(i)));
			if (val == null)
			{
				return;
			}
			val.m_quality = Mathf.Clamp(quality, 1, val.m_shared.m_maxQuality);
			val.m_durability = val.GetMaxDurability();
			val.m_customData["dh_arena_loan"] = tier.ToString();
			Contest.Style = style;
			if (style == 4)
			{
				(string, int)[] array = new(string, int)[2]
				{
					(Kit.ArrowFor(tier), 60),
					(Kit.Knives[Mathf.Clamp(tier, 0, Kit.Knives.Length - 1)].Split(new char[1] { ':' })[0], 1)
				};
				for (int num = 0; num < array.Length; num++)
				{
					(string, int) tuple = array[num];
					if (tuple.Item1 != null && Roster.Has(tuple.Item1))
					{
						KeepApart.AddMarked(((Humanoid)player).GetInventory(), tuple.Item1, tuple.Item2, 2, tier.ToString());
					}
				}
			}
			((Humanoid)player).EquipItem(val, false);
		}

		internal static void Spill(Vector3 at, int land, int level, bool champion)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			float num = Rules.Multiplier * (1f + Crowd.Favour / 200f) * Plugin.Rewards.Value / 100f;
			int amount = Mathf.Max(1, Mathf.RoundToInt((float)CoinsByLand[Mathf.Clamp(land, 0, CoinsByLand.Length - 1)] * Random.Range(0.8f, 1.2f) * (1f + 0.5f * (float)(level - 1)) * (champion ? 5f : 1f) * num));
			Drop("Coins", amount, at);
		}

		internal static void Drop(string prefab, int amount, Vector3 at)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_00bc: 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_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)
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefab) : null);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val2 == (Object)null || amount <= 0)
			{
				return;
			}
			int num = Mathf.Max(1, val2.m_itemData.m_shared.m_maxStackSize);
			while (amount > 0)
			{
				int num2 = Mathf.Min(amount, num);
				amount -= num2;
				GameObject val3 = Object.Instantiate<GameObject>(val, at + Vector3.up * 0.8f + Random3(), Quaternion.identity);
				ItemDrop component = val3.GetComponent<ItemDrop>();
				if (component != null)
				{
					component.SetStack(num2);
				}
				Rigidbody component2 = val3.GetComponent<Rigidbody>();
				if (component2 != null)
				{
					component2.AddForce(Vector3.up * 3f + Random3() * 2f, (ForceMode)2);
				}
			}
		}

		private static Vector3 Random3()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(Random.Range(-0.4f, 0.4f), 0f, Random.Range(-0.4f, 0.4f));
		}
	}
	internal class Armourer : MonoBehaviour, Hoverable, Interactable
	{
		private Trader _trader;

		internal static readonly Dictionary<TradeItem, Armoury.Slot> Upgrades = new Dictionary<TradeItem, Armoury.Slot>();

		internal static readonly Dictionary<TradeItem, (int Style, int Tier, int Quality)> Switches = new Dictionary<TradeItem, (int, int, int)>();

		public string GetHoverText()
		{
			return Localization.instance.Localize("$arena_armourer\n[<color=yellow><b>$KEY_Use</b></color>] $arena_armourer_wares\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] $arena_armourer_ready");
		}

		public string GetHoverName()
		{
			return Translations.T("arena_armourer");
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			if (hold || (Object)(object)user != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			if (alt)
			{
				Contest.ReadyEarly();
				return true;
			}
			if ((Object)(object)_trader == (Object)null)
			{
				GameObject val = new GameObject("ArmourerStore");
				val.transform.SetParent(((Component)this).transform, false);
				_trader = val.AddComponent<Trader>();
				((Behaviour)_trader).enabled = false;
			}
			_trader.m_name = Translations.T("arena_armourer");
			Restock(_trader);
			StoreGui instance = StoreGui.instance;
			if (instance != null)
			{
				instance.Show(_trader);
			}
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		internal static bool Ours(Trader trader)
		{
			if ((Object)(object)trader != (Object)null && (Object)(object)((Component)trader).transform.parent != (Object)null)
			{
				return (Object)(object)((Component)((Component)trader).transform.parent).GetComponent<Armourer>() != (Object)null;
			}
			return false;
		}

		internal static void Restock(Trader trader)
		{
			Player localPlayer = Player.m_localPlayer;
			trader.m_items.Clear();
			Upgrades.Clear();
			Switches.Clear();
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			int tier = Contest.Tier;
			int style = Contest.Style;
			foreach (Armoury.Slot item in Armoury.Slots(style, Rules.Fists))
			{
				if (Armoury.Next(localPlayer, item, style, out var tier2, out var prefab, out var quality))
				{
					GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
					ItemDrop val = ((prefab2 != null) ? prefab2.GetComponent<ItemDrop>() : null);
					if (!((Object)(object)val == (Object)null))
					{
						ItemData val2 = val.m_itemData.Clone();
						val2.m_quality = Mathf.Clamp(quality, 1, val2.m_shared.m_maxQuality);
						TradeItem val3 = Item(val, 1, Armoury.Price(item, tier2), Translations.T("arena_upgrade_tip", "<color=orange>" + Translations.T("arena_upgrade_" + Armoury.SlotWords[(int)item]) + "</color>", Armoury.Name(localPlayer, item, style)) + "\n\n" + val2.GetTooltip(1));
						trader.m_items.Add(val3);
						Upgrades[val3] = item;
					}
				}
			}
			if (!Rules.Fists)
			{
				int num = Mathf.Max(0, Armoury.TierOf(localPlayer, Armoury.Slot.Weapon, style));
				for (int i = 0; i < Kit.Styles.Length; i++)
				{
					if (i != style)
					{
						string text = Kit.Weapons[i][num];
						string text2 = text.Split(new char[1] { ':' })[0];
						int result;
						int num2 = ((text.Contains(":") && int.TryParse(text.Split(new char[1] { ':' })[1], out result)) ? result : 2);
						GameObject prefab3 = ZNetScene.instance.GetPrefab(text2);
						ItemDrop val4 = ((prefab3 != null) ? prefab3.GetComponent<ItemDrop>() : null);
						if (!((Object)(object)val4 == (Object)null))
						{
							ItemData val5 = val4.m_itemData.Clone();
							val5.m_quality = Mathf.Clamp(num2, 1, val5.m_shared.m_maxQuality);
							TradeItem val6 = Item(val4, 1, Armoury.SwitchPrice(num), Translations.T("arena_switch_tip", "<color=orange>" + Translations.T($"arena_fight_with_{i}") + "</color>", Armoury.Name(localPlayer, Armoury.Slot.Weapon, style)) + "\n\n" + val5.GetTooltip(1));
							trader.m_items.Add(val6);
							Switches[val6] = (i, num, num2);
						}
					}
				}
			}
			if (!Rules.NoFood)
			{
				foreach (var item2 in Kit.Menu(tier))
				{
					Add(trader, item2.Prefab, 1, Armoury.MealPrice(tier));
				}
				Add(trader, Kit.Meads[Mathf.Clamp(tier, 0, Kit.Meads.Length - 1)], 1, Armoury.HealingPrice(tier));
				Add(trader, (tier < 3) ? "MeadStaminaMinor" : ((tier < 6) ? "MeadStaminaMedium" : "MeadStaminaLingering"), 1, Armoury.StaminaPrice(tier));
			}
			if (style == 4 && !Rules.Fists && Kit.ArrowFor(tier) != null)
			{
				Add(trader, Kit.ArrowFor(tier), 30, Armoury.ArrowsPrice(tier));
			}
		}

		private static void Add(Trader trader, string prefab, int stack, int price)
		{
			GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
			ItemDrop val = ((prefab2 != null) ? prefab2.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val != (Object)null)
			{
				trader.m_items.Add(Item(val, stack, price, Kit.Keeps(prefab, Contest.Tier) ? "" : (Translations.T("arena_lent_tip", "<color=orange>" + Translations.T("arena_lent") + "</color>") + "\n\n" + val.m_itemData.GetTooltip(stack))));
			}
		}

		private static TradeItem Item(ItemDrop drop, int stack, int price, string tooltip)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0035: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			return new TradeItem
			{
				m_prefab = drop,
				m_stack = stack,
				m_price = price,
				m_tooltip = (tooltip ?? ""),
				m_buyPlayerEffects = new EffectList(),
				m_name = ""
			};
		}
	}
	[HarmonyPatch(typeof(Trader), "OnBought")]
	internal static class Trader_OnBought_Armourer
	{
		private static bool Prefix(Trader __instance, TradeItem item)
		{
			if (!Armourer.Ours(__instance))
			{
				return true;
			}
			Player localPlayer = Player.m_localPlayer;
			(int, int, int) value2;
			if ((Object)(object)localPlayer != (Object)null && Armourer.Upgrades.TryGetValue(item, out var value))
			{
				Armoury.Bought(localPlayer, value, ((Object)((Component)item.m_prefab).gameObject).name, Contest.Style);
			}
			else if ((Object)(object)localPlayer != (Object)null && Armourer.Switches.TryGetValue(item, out value2))
			{
				Armoury.Switched(localPlayer, value2.Item1, ((Object)((Component)item.m_prefab).gameObject).name, value2.Item2, value2.Item3);
			}
			else if ((Object)(object)localPlayer != (Object)null)
			{
				Kit.LendIfFromBeyond(localPlayer, ((Object)((Component)item.m_prefab).gameObject).name, Contest.Tier);
			}
			Net.Sound("cheer");
			Armourer.Restock(__instance);
			return false;
		}
	}
	[HarmonyPatch(typeof(Trader), "OnSold")]
	internal static class Trader_OnSold_Armourer
	{
		private static bool Prefix(Trader __instance)
		{
			if (!Armourer.Ours(__instance))
			{
				return true;
			}
			Armourer.Restock(__instance);
			return false;
		}
	}
	internal static class Contest
	{
		internal enum PhaseKind
		{
			None,
			Ready,
			Arming,
			Countdown,
			Spawning,
			Fighting,
			Break,
			Victory
		}

		internal enum KindOf
		{
			Road,
			Champion,
			Endless,
			Trial
		}

		private enum Outcome
		{
			Win,
			CashOut,
			Yield,
			Died,
			TimeUp,
			LeftRing,
			Carried,
			Aborted,
			CalledOff
		}

		private struct Item
		{
			public string Prefab;

			public string Name;

			public int Level;

			public bool Champion;
		}

		private sealed class Foe
		{
			public GameObject Go;

			public Character Char;

			public bool Champion;

			public bool Counted;

			public string Prefab;

			public Vector3 LastPos;

			public int Level;
		}

		internal static PhaseKind Phase;

		internal static KindOf Kind;

		internal static string Title = "";

		internal static string TitleLine = "";

		internal static int Round;

		internal static int Rounds;

		internal static int Tier;

		internal static int Stake;

		internal static int Fee;

		internal static int Style;

		internal static bool Daily;

		private static bool _stowed;

		private static string _look = "";

		private static readonly List<string> Trophies = new List<string>();

		private static readonly List<Foe> Foes = new List<Foe>();

		private static readonly Queue<Item> Queue = new Queue<Item>();

		private const float ReadySeconds = 90f;

		private static int _nextPen;

		private static float _spawnedAt;

		private static float _timer;

		private static float _spawnTimer;

		private static float _lastKill;

		private static float _outside;

		private static float _closeAt;

		private static float _yieldAt;

		private static float _roundLeft;

		private static float _lastWarn;

		private static float _lastParryShout;

		private static float _peak;

		private static float _purseCoins;

		private static float _victoryAt;

		private static float _offFloor;

		private static float _nextChant;

		private static int _victoryStep;

		private static bool _toChest;

		private static bool _crowned;

		private static readonly List<(string Prefab, int Amount, int Quality, string Loan)> PrizeItems = new List<(string, int, int, string)>();

		private static readonly Dictionary<string, float> Mats = new Dictionary<string, float>();

		private static int _combo;

		private static int _kills;

		private static int _count;

		private static bool _knockedOut;

		private static bool _hurtThisRound;

		private static float _tombUntil;

		private static Vector3 _tombCentre;

		private static float _tombRadius;

		internal const string Stage = "Platform";

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

		internal static bool Active => Phase != PhaseKind.None;

		internal static bool Fighting
		{
			get
			{
				if (Phase != PhaseKind.Spawning)
				{
					return Phase == PhaseKind.Fighting;
				}
				return true;
			}
		}

		internal static bool Waiting => Phase == PhaseKind.Ready;

		internal static int FoesLeft => Queue.Count + Foes.Count((Foe f) => !f.Counted);

		internal static Vector3 Centre => Site.Centre;

		internal static int Kills => _kills;

		internal static float LastKillTime => _lastKill;

		internal static float RoundLeft => _roundLeft;

		internal static bool Endless => Kind == KindOf.Endless;

		internal static int PurseCoins => Mathf.RoundToInt(_purseCoins);

		internal static bool Lent
		{
			get
			{
				if (Kind != KindOf.Road)
				{
					return Kind == KindOf.Trial;
				}
				return true;
			}
		}

		internal static bool Lands
		{
			get
			{
				if (Kind != KindOf.Road)
				{
					return Kind == KindOf.Trial;
				}
				return true;
			}
		}

		internal static int LandRound => (Mathf.Max(1, Round) - 1) % 3 + 1;

		internal static bool TombPending => Time.time < _tombUntil;

		private static string FightCover()
		{
			string[] array = Layout.Props.Keys.Where((string k) => k != "Platform").ToArray();
			if (array.Length == 0 || !(Random.value < 0.85f))
			{
				return null;
			}
			return array[Random.Range(0, array.Length)];
		}

		internal static string TimerLabel(out float seconds)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			string result = Favours.DemandLabel(out seconds);
			if (seconds >= 0f)
			{
				return result;
			}
			seconds = _timer;
			string text = ((object)Plugin.YieldKey.Value/*cast due to .constrained prefix*/).ToString();
			switch (Phase)
			{
			case PhaseKind.Ready:
				return Translations.T("arena_walk_in");
			case PhaseKind.Arming:
				if (!Show.ChestEmptied)
				{
					return Translations.T("arena_timer_arming");
				}
				return Translations.T("arena_timer_arming_done");
			case PhaseKind.Break:
				if (!Lent)
				{
					return Translations.T("arena_timer_next_round") + "  ·  " + Translations.T("arena_timer_leave_purse", text);
				}
				return Translations.T(Show.ArmourerStanding ? "arena_timer_break_armourer" : "arena_timer_break_coins") + "  ·  " + Translations.T("arena_timer_leave_coins", text);
			default:
				seconds = -1f;
				return "";
			}
		}

		internal static bool FoeWithin(Vector3 at, float range)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return Foes.Any(delegate(Foe f)
			{
				//IL_0021: 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_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				if (!f.Counted && (Object)(object)f.Go != (Object)null)
				{
					Vector3 val = f.Go.transform.position - at;
					return ((Vector3)(ref val)).sqrMagnitude < range * range;
				}
				return false;
			});
		}

		internal static string KindName(KindOf kind)
		{
			return Translations.T(KindKey(kind));
		}

		internal static string KindKey(KindOf kind)
		{
			return "arena_kind_" + KindWord(kind);
		}

		private static string KindWord(KindOf kind)
		{
			return kind switch
			{
				KindOf.Endless => "endless", 
				KindOf.Champion => "champion", 
				KindOf.Road => "road", 
				_ => "trial", 
			};
		}

		internal static int FeeFor(KindOf kind, int tier)
		{
			if (Ladder.Get("fights") == 0)
			{
				return 0;
			}
			return Mathf.RoundToInt(kind switch
			{
				KindOf.Champion => 50f + 40f * (float)tier, 
				KindOf.Trial => 60f + 30f * (float)tier, 
				KindOf.Road => 150f, 
				_ => 40f + 30f * (float)tier, 
			} * Plugin.EntryFee.Value / 100f);
		}

		internal static void TodaysPlan(out int tier, out int style, out bool fists, out bool noFood, out bool hard, out bool timed)
		{
			Random random = new Random(Ladder.Today * 31 + 7);
			style = random.Next(Kit.Styles.Length);
			int num = Roster.Beaten();
			tier = Mathf.Max(0, num - random.Next(Mathf.Min(2, num + 1)));
			bool[] array = new bool[3];
			int num2 = 1 + random.Next(2);
			for (int i = 0; i < num2; i++)
			{
				array[random.Next(3)] = true;
			}
			fists = array[0];
			noFood = false;
			hard = array[1];
			timed = array[2];
		}

		internal static string Start(KindOf kind, int tier, int style, bool fists, bool noFood, bool hard, bool timed, int stake, bool daily)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || !Site.Known || !Scenery.Built)
			{
				return Translations.T("arena_not_ready");
			}
			if (Active)
			{
				return Translations.T("arena_contest_on");
			}
			if (Duel.Active)
			{
				return Translations.T("arena_in_duel");
			}
			if (Net.RemoteFight)
			{
				return Translations.T("arena_busy_wait", Net.BusyText);
			}
			if (kind == KindOf.Road)
			{
				tier = 0;
			}
			tier = Mathf.Clamp(tier, 0, Roster.TierNames.Length - 1);
			if (Roster.Pool(tier).Count == 0)
			{
				return Translations.T("arena_no_one");
			}
			if (kind == KindOf.Endless || kind == KindOf.Road)
			{
				stake = 0;
			}
			bool flag = kind == KindOf.Road || kind == KindOf.Trial;
			if (flag && Kit.Stowed(localPlayer))
			{
				return Translations.T("arena_still_held");
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			int num = FeeFor(kind, tier);
			if (inventory.CountItems("$item_coins", -1, true) < num + stake)
			{
				if (stake <= 0)
				{
					return Translations.T("arena_no_coins", num);
				}
				return Translations.T("arena_no_coins_stake", num, stake);
			}
			if (num + stake > 0)
			{
				inventory.RemoveItem("$item_coins", num + stake, -1, true);
			}
			Stake = stake;
			Fee = num;
			Daily = daily;
			Kind = kind;
			Tier = tier;
			Style = ((style < 0) ? Random.Range(0, Kit.Styles.Length) : Mathf.Clamp(style, 0, Kit.Styles.Length - 1));
			Rules.Set(fists, noFood, hard, timed);
			Rounds = kind switch
			{
				KindOf.Trial => 3, 
				KindOf.Road => 3 * Roster.TierNames.Length, 
				_ => (kind == KindOf.Champion) ? 1 : 0, 
			};
			Title = ((kind == KindOf.Road) ? "The Long Road" : (kind.ToString() + " - " + Roster.TierNames[Tier]));
			TitleLine = ((kind == KindOf.Road) ? Words.Line(KindKey(kind)) : Words.Line("arena_title", Words.Word(KindKey(kind)), Words.Land(Tier)));
			Round = 0;
			_kills = 0;
			_combo = 0;
			_outside = 0f;
			_knockedOut = false;
			_closeAt = 0f;
			_yieldAt = 0f;
			_purseCoins = 0f;
			_peak = 0f;
			_stowed = false;
			_look = "";
			Mats.Clear();
			Trophies.Clear();
			Foes.Clear();
			Queue.Clear();
			Net.Props(FightCover());
			Show.ClearFloor();
			Crowd.Open();
			Favours.Reset();
			Net.Gate(Scenery.MainGrate, 90f);
			Net.Door(90f);
			Net.Shout(Words.Line("arena_call_to_ring"), Words.Line("arena_call_to_ring_sub", localPlayer.GetPlayerName()), 6f);
			Phase = PhaseKind.Ready;
			_timer = 90f;
			_count = 4;
			if (flag)
			{
				Hud.Say(Translations.T("arena_say_lent"));
			}
			Hud.Say(Translations.T(flag ? "arena_say_play_lent" : "arena_say_play"));
			Plugin.Log.LogInfo((object)($"Contest started: {Title}, rules {Rules.Names()}, fee {num}, stake {stake}" + (flag ? (", " + Kit.Styles[Style]) : "")));
			return null;
		}

		internal static void Tick(float dt)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			if (_closeAt > 0f && Time.time >= _closeAt)
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null || !Site.OnFloor(((Component)localPlayer).transform.position, 2f) || Time.time > _closeAt + 45f)
				{
					_closeAt = 0f;
					if (!Duel.Active && !Net.RemoteFight)
					{
						Crowd.Close(bow: true);
					}
					Net.Props(null);
				}
			}
			if (!Active)
			{
				return;
			}
			Player localPlayer2 = Player.m_localPlayer;
			if ((Object)(object)localPlayer2 == (Object)null)
			{
				Abort("You left the world.");
				return;
			}
			if (Phase == PhaseKind.Victory)
			{
				TickVictory(localPlayer2, dt);
				return;
			}
			if (((Character)localPlayer2).IsDead())
			{
				End(Outcome.Died);
				return;
			}
			if (_knockedOut)
			{
				End(Outcome.Carried);
				return;
			}
			_peak = Mathf.Max(_peak, Crowd.Favour);
			KeyboardShortcut value = Plugin.YieldKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown() && !Window.IsOpen)
			{
				bool flag = Phase == PhaseKind.Break || Phase == PhaseKind.Arming;
				if (_yieldAt > 0f && Time.time - _yieldAt < 3f)
				{
					End(flag ? Outcome.CashOut : Outcome.Yield);
					return;
				}
				_yieldAt = Time.time;
				Hud.Say(Translations.T(Lent ? "arena_say_yield_coins" : (flag ? "arena_say_yield_purse" : "arena_say_yield_half")));
			}
			if (Phase == PhaseKind.Ready)
			{
				_timer -= dt;
				if (Site.OnFloor(((Component)localPlayer2).transform.position, -1f))
				{
					Net.Gate(Scenery.MainGrate, 0f);
					Net.Door(0f);
					if (Lent)
					{
						if (!Kit.Stow(localPlayer2))
						{
							End(Outcome.Aborted);
							Hud.Say(Translations.T("arena_say_stow_failed"));
							return;
						}
						_stowed = true;
						localPlayer2.ClearFood();
					}
					else
					{
						Rules.Strip(localPlayer2);
					}
					((Character)localPlayer2).Heal(((Character)localPlayer2).GetMaxHealth(), true);
					((Character)localPlayer2).AddStamina(((Character)localPlayer2).GetMaxStamina());
					_look = Figures.LookOf(localPlayer2);
					string text = Words.Line("arena_call_intro", Words.Word(KindKey(Kind)));
					Net.Sound("gong");
					if (Lent)
					{
						Show.PopChest(1, Kit.Outfit(Tier, Style, Rules.Fists, !Rules.NoFood));
						Net.Shout(text, Words.Then(Lines.Welcome(localPlayer2.GetPlayerName()), Words.Line("arena_call_arm")), 5f);
						Phase = PhaseKind.Arming;
						_timer = 40f;
					}
					else
					{
						string text2 = Words.Rules(Rules.Fists, Rules.NoFood, Rules.Hard, Rules.Timed);
						Net.Shout(text, Words.Then(Lines.Welcome(localPlayer2.GetPlayerName()), (Stake > 0) ? Words.Line("arena_call_rules_stake", text2, Stake) : Words.Line("arena_call_rules", text2)), 5f);
						Phase = PhaseKind.Countdown;
						_timer = 5f;
						_count = 4;
					}
				}
				else if (_timer <= 0f)
				{
					End(Outcome.Aborted);
					Hud.Say(Translations.T("arena_say_no_show"));
				}
				return;
			}
			if (!Site.OnFloor(((Component)localPlayer2).transform.position, 1.5f))
			{
				_outside += dt;
				if (Time.time - _lastWarn > 1f)
				{
					_lastWarn = Time.time;
					Hud.Say(Translations.T("arena_say_get_back", Mathf.CeilToInt(8f - _outside)));
				}
				if (_outside > 8f)
				{
					End(Outcome.LeftRing);
					return;
				}
			}
			else
			{
				_outside = Mathf.Max(0f, _outside - dt * 2f);
			}
			switch (Phase)
			{
			case PhaseKind.Arming:
				_timer -= dt;
				if (Show.ChestEmptied && _timer > 6f)
				{
					_timer = 6f;
				}
				if (_timer <= 0f)
				{
					Show.TakeChest();
					Phase = PhaseKind.Countdown;
					_timer = 3.5f;
					_count = 4;
				}
				break;
			case PhaseKind.Countdown:
			{
				_timer -= dt;
				int num = Mathf.CeilToInt(_timer);
				if (num < _count && num >= 1 && num <= 3)
				{
					_count = num;
					Hud.Count(num.ToString());
				}
				if (_timer <= 0f)
				{
					Hud.Count(Translations.T("arena_fight"));
					Net.Sound("cheer");
					BeginRound(1);
				}
				break;
			}
			case PhaseKind.Spawning:
			case PhaseKind.Fighting:
				if (Phase == PhaseKind.Spawning)
				{
					_spawnTimer -= dt;
					if (_spawnTimer <= 0f && Queue.Count > 0)
					{
						Spawn(Queue.Dequeue(), localPlayer2);
						_spawnTimer = 1.1f;
					}
					if (Queue.Count == 0)
					{
						Phase = PhaseKind.Fighting;
					}
				}
				CheckFoes(localPlayer2);
				if (Rules.Timed)
				{
					float roundLeft = _roundLeft;
					_roundLeft -= dt;
					if (roundLeft > 10f && _roundLeft <= 10f)
					{
						Net.Shout(Words.Line("arena_call_ten_seconds"), "", 1.5f);
					}
					if (_roundLeft <= 0f)
					{
						End(Outcome.TimeUp);
						break;
					}
				}
				if (Phase == PhaseKind.Fighting && Foes.All((Foe f) => f.Counted) && Queue.Count == 0)
				{
					RoundCleared(localPlayer2);
				}
				break;
			case PhaseKind.Break:
				_timer -= dt;
				if (!Lent && Show.ChestEmptied && _timer > 6f)
				{
					_timer = 6f;
				}
				if (_timer <= 0f)
				{
					Show.TakeChest();
					Show.Armourer(on: false);
					if (Lent)
					{
						Armoury.Tidy(localPlayer2, Style);
					}
					BeginRound(Round + 1);
				}
				break;
			}
		}

		private static void BeginRound(int n)
		{
			Round = n;
			Queue.Clear();
			Foes.Clear();
			_hurtThisRound = false;
			int num = (n - 1) % 3;
			if (Kind == KindOf.Road && num == 0 && n > 1)
			{
				Show.TakeChest();
				Net.Props(FightCover());
			}
			bool flag;
			int num2;
			float lean;
			int num3;
			if (Lands)
			{
				if (Kind == KindOf.Road)
				{
					Tier = Mathf.Min((n - 1) / 3, Roster.TierNames.Length - 1);
				}
				flag = num == 2;
				num2 = 3 + num + (Rules.Hard ? 2 : 0) - (flag ? 3 : 0);
				lean = (float)num / 2f;
				num3 = 1 + (Rules.Hard ? 1 : 0);
			}
			else if (Kind == KindOf.Champion)
			{
				flag = true;
				num2 = (Rules.Hard ? 2 : 0);
				lean = 0.5f;
				num3 = 1 + (Rules.Hard ? 1 : 0);
			}
			else
			{
				flag = n % 5 == 0;
				num2 = Mathf.Min(2 + n, 12) + (Rules.Hard ? 1 : 0) - (flag ? 2 : 0);
				lean = Mathf.Min(1f, (float)n / 8f);
				num3 = 1 + (n - 1) / 5 + (Rules.Hard ? 1 : 0);
			}
			for (int i = 0; i < num2; i++)
			{
				string text = Roster.Pick(Tier, lean);
				if (text != null)
				{
					int num4 = num3 + ((Lands && num >= 1 && Random.value < 0.3f) ? 1 : 0);
					Queue.Enqueue(new Item
					{
						Prefab = text,
						Level = Mathf.Clamp(num4, 1, 3)
					});
				}
			}
			if (flag)
			{
				string text2 = Roster.Champion(Tier);
				if (text2 != null)
				{
					Queue.Enqueue(new Item
					{
						Prefab = text2,
						Name = Roster.ChampionName(),
						Level = Roster.ChampionLevel(Tier, text2, Kind, n, Rules.Hard),
						Champion = true
					});
				}
			}
			if (Queue.Count == 0)
			{
				End(Outcome.CalledOff);
				return;
			}
			_roundLeft = 90f + (flag ? 30f : 0f);
			Phase = PhaseKind.Spawning;
			_spawnTimer = 1.4f;
			string text3 = Words.Land(Tier);
			string text4 = ((Kind == KindOf.Champion) ? Words.Line("arena_call_the_champion") : ((Kind == KindOf.Endless) ? Words.Line("arena_call_wave", n) : ((!flag) ? ((Kind == KindOf.Road) ? Words.Line("arena_call_land_round", text3, num + 1) : Words.Line("arena_call_round", n)) : ((Kind == KindOf.Road) ? Words.Line("arena_call_champion_of", text3) : Words.Line("arena_call_final_round")))));
			string sub = ((flag && Kind != KindOf.Champion) ? Words.Line("arena_call_champion_comes") : Lines.RoundCall(Queue.Count));
			Net.Shout(text4, sub, 3.5f);
			Net.Sound("gong");
			if (n > 1)
			{
				Net.Sound("cheer");
			}
		}

		private static void RoundCleared(Player player)
		{
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0470: Unknown result type (might be due to invalid IL or missing references)
			int num = (Round - 1) % 3;
			float units = (Lands ? (0.7f + 0.4f * (float)num) : ((Kind == KindOf.Endless) ? (0.5f + 0.15f * (float)Round) : 3f));
			if (!_hurtThisRound)
			{
				Crowd.Gain(12f, cheer: false);
				Net.Shout(Words.Line("arena_call_flawless"), Words.Line("arena_call_flawless_sub"), 2.2f);
			}
			if (!Lent)
			{
				AddToPurse(units);
			}
			if (Kind == KindOf.Endless)
			{
				Ladder.Best("bestwave" + Tier, Round);
			}
			else if (Kind == KindOf.Road)
			{
				Ladder.Best("road", Round);
			}
			else
			{
				Ladder.Best("bestround" + Tier, Round);
			}
			_look = Figures.LookOf(player);
			if (Rounds > 0 && Round >= Rounds)
			{
				StartVictory(player);
				return;
			}
			Crowd.Gain(8f, cheer: false);
			Net.Sound("applause");
			Phase = PhaseKind.Break;
			_timer = 12f;
			((Character)player).AddStamina(((Character)player).GetMaxStamina());
			if (Kind == KindOf.Road && num == 2)
			{
				int tier = Mathf.Min(Tier + 1, Roster.TierNames.Length - 1);
				((Character)player).Heal(((Character)player).GetMaxHealth(), true);
				Net.Props("Platform");
				if (Lent)
				{
					List<(string, int, int, string)> list = new List<(string, int, int, string)>();
					(string, int, int, string)? tuple = Armoury.Random(player, Style, Rules.Fists, Tier.ToString());
					if (tuple.HasValue)
					{
						list.Add(tuple.Value);
					}
					else
					{
						list.Add(("Coins", Mathf.RoundToInt(60f * (float)(Tier + 1) * Plugin.Rewards.Value / 100f), 1, null));
					}
					if (!Rules.NoFood && Random.value < 0.3f)
					{
						if (Random.value < 0.5f)
						{
							foreach (string item in Kit.Plate(Tier + 1, new Kit.Role[1]).Take(1))
							{
								list.Add((item, 1, 1, Tier.ToString()));
							}
						}
						else
						{
							list.Add((Kit.Meads[Mathf.Clamp(Tier + 1, 0, Kit.Meads.Length - 1)], 1, 1, Tier.ToString()));
						}
					}
					if (list.Count > 0)
					{
						Show.PopChest(3, list);
					}
					Show.Armourer(on: true);
				}
				Net.Sound("roar");
				Net.Shout(Words.Line("arena_call_land_beaten", Words.Land(Tier)), Words.Then(Words.Line("arena_call_on_to", Words.Land(tier)), "-", Words.Line("arena_call_leave_coins", ((object)Plugin.YieldKey.Value/*cast due to .constrained prefix*/).ToString())), 7f);
				_timer = 50f;
			}
			else if (Lent)
			{
				Net.Shout(Words.Line("arena_call_round_cleared", Round), Words.Then(Words.Line("arena_call_pick_up_coins"), "-", Words.Line("arena_call_leave_them", ((object)Plugin.YieldKey.Value/*cast due to .constrained prefix*/).ToString())), 4.5f);
				((Character)player).Heal(((Character)player).GetMaxHealth() * 0.3f, true);
			}
			else
			{
				Net.Shout(Words.Line((Kind == KindOf.Endless) ? "arena_call_wave_cleared" : "arena_call_round_cleared", Round), Words.Then(Words.Line("arena_call_your_purse", Words.Purse(PurseData())), "-", Words.Line("arena_call_leave_it", ((object)Plugin.YieldKey.Value/*cast due to .constrained prefix*/).ToString())), 4.5f);
				((Character)player).Heal(((Character)player).GetMaxHealth() * 0.3f, true);
			}
		}

		private static void AddToPurse(float units)
		{
			float num = Rules.Multiplier * (1f + Crowd.Favour / 200f) * Plugin.Rewards.Value / 100f;
			_purseCoins += (float)(20 + 30 * Tier) * units * num;
			string text = ((Tier <= Roster.Beaten()) ? Roster.Material(Tier) : null);
			if (text != null)
			{
				Mats[text] = (Mats.TryGetValue(text, out var value) ? value : 0f) + (float)(2 + Tier) * 0.5f * units * num;
			}
		}

		internal static string PurseText()
		{
			if (Lent)
			{
				return Translations.T("arena_purse_bag", ((Object)(object)Player.m_localPlayer != (Object)null) ? ((Humanoid)Player.m_localPlayer).GetInventory().CountItems("$item_coins", -1, true) : 0);
			}
			return PurseText(PurseData());
		}

		private static string PurseData()
		{
			return PurseCoins.ToString(CultureInfo.InvariantCulture) + ";" + string.Join(",", from m in Mats
				where Mathf.FloorToInt(m.Value) > 0
				select m.Key + "*" + Mathf.FloorToInt(m.Value).ToString(CultureInfo.InvariantCulture));
		}

		internal static string PurseText(string data)
		{
			string[] array = data.Split(new char[1] { ';' });
			string text = Translations.T("arena_coins", array[0]);
			if (array.Length > 1)
			{
				foreach (var item in Counted(array[1]))
				{
					text = text + ", " + Translations.T("arena_prize_item", item.Amount, ItemName(item.Prefab));
				}
			}
			return text;
		}

		private static IEnumerable<(string Prefab, int Amount)> Counted(string list)
		{
			string[] array = list.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text in array)
			{
				int num = text.IndexOf('*');
				if (num < 0)
				{
					yield return (Prefab: text, Amount: 1);
					continue;
				}
				int.TryParse(text.Substring(num + 1), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result);
				yield return (Prefab: text.Substring(0, num), Amount: result);
			}
		}

		internal static string ItemName(string prefab)
		{
			object obj;
			if (!((Object)(object)ZNetScene.instance != (Object)null))
			{
				obj = null;
			}
			else
			{
				GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab);
				obj = ((prefab2 != null) ? prefab2.GetComponent<ItemDrop>() : null);
			}
			ItemDrop val = (ItemDrop)obj;
			if (!((Object)(object)val != (Object)null) || Localization.instance == null)
			{
				return prefab;
			}
			return Localization.instance.Localize(val.m_itemData.m_shared.m_name);
		}

		private static void Spawn(Item item, Player player)
		{
			//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_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_011e: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(item.Prefab) : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Vector3 val2 = Site.Centre;
			if (Layout.Pens.Count > 0)
			{
				Layout.Mark mark = null;
				for (int i = 0; i < Layout.Pens.Count; i++)
				{
					Layout.Mark mark2 = Layout.Pens[(_nextPen + i) % Layout.Pens.Count];
					Vector3 val3 = Site.Point(mark2) - ((Component)player).transform.position;
					if (((Vector3)(ref val3)).magnitude > 8f || i == Layout.Pens.Count - 1)
					{
						mark = mark2;
						_nextPen = (_nextPen + i + 1) % Layout.Pens.Count;
						break;
					}
				}
				val2 = Site.Point(mark, 0.2f);
				Net.Gate(mark.Gate, 4f);
			}
			GameObject val4 = Object.Instantiate<GameObject>(val, val2, Quaternion.LookRotation(new Vector3(Site.Centre.x - val2.x, 0f, Site.Centre.z - val2.z)));
			Foe foe = new Foe
			{
				Go = val4,
				Char = val4.GetComponent<Character>(),
				Champion = item.Champion,
				Prefab = item.Prefab,
				LastPos = val2,
				Level = item.Level
			};
			if ((Object)(object)foe.Char != (Object)null)
			{
				foe.Char.SetLevel(item.Level);
				if (!string.IsNullOrEmpty(item.Name))
				{
					foe.Char.m_name = Words.Show(item.Name);
				}
			}
			CharacterDrop component = val4.GetComponent<CharacterDrop>();
			if (component != null)
			{
				component.SetDropsEnabled(false);
			}
			MonsterAI component2 = val4.GetComponent<MonsterAI>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.SetDespawnInDay(false);
				((BaseAI)component2).SetHuntPlayer(true);
				((BaseAI)component2).m_afraidOfFire = false;
				((BaseAI)component2).m_avoidFire = false;
				component2.m_fleeIfLowHealth = 0f;
				component2.m_fleeIfHurtWhenTargetCantBeReached = false;
				component2.m_fleeIfNotAlerted = false;
				((BaseAI)component2).Alert();
				SetTarget?.Invoke(component2, new object[1] { player });
			}
			else
			{
				BaseAI component3 = val4.GetComponent<BaseAI>();
				if (component3 != null)
				{
					component3.SetHuntPlayer(true);
				}
			}
			ZNetView component4 = val4.GetComponent<ZNetView>();
			if ((Object)(object)component4 != (Object)null && component4.IsValid())
			{
				component4.GetZDO().Set("dh_arena", true);
				if (item.Champion)
				{
					component4.SetLocalScale(Vector3.one * 1.18f);
				}
			}
			Foes.Add(foe);
			_spawnedAt = Time.time;
			if (item.Champion)
			{
				Net.Shout(item.Name, Words.Line(Roster.Origin(Tier)));
				Net.Sound("horn");
				Net.Sound("roar");
				Net.Effect("fx_fireball_staff_explosion", val2 + Vector3.up * 1.2f);
				Net.Effect("fx_fireskeleton_nova", val2);
			}
		}

		private static void CheckFoes(Player player)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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_00d4: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_011f: Unknown result type (might be due to invalid IL or missing references)
			foreach (Foe fo in Foes)
			{
				if (fo.Counted)
				{
					continue;
				}
				if ((Object)(object)fo.Go == (Object)null || (Object)(object)fo.Char == (Object)null || fo.Char.IsDead())
				{
					fo.Counted = true;
					OnKill(fo, player);
					continue;
				}
				fo.LastPos = fo.Go.transform.position;
				if (!Site.OnFloor(fo.Go.transform.position, 6f) && Time.time - _spawnedAt > 8f)
				{
					Vector3 val = Site.World(new Vector3(0f, 0f, 0f));
					Vector3 val2 = fo.Go.transform.position - Site.Centre;
					Vector3 val3 = val + ((Vector3)(ref val2)).normalized * (Layout.Floor - 3f);
					val3.y = Site.Ground(val3, Site.Centre.y) + 0.3f;
					fo.Go.transform.position = val3;
				}
			}
		}

		private static void OnKill(Foe f, Player player)
		{
			//IL_0093: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			_kills++;
			_combo = ((!(Time.time - _lastKill < 4f)) ? 1 : (_combo + 1));
			_lastKill = Time.time;
			Favours.OnKill();
			bool flag = ((Character)player).GetHealth() < ((Character)player).GetMaxHealth() * 0.25f;
			Crowd.Gain((f.Champion ? 30f : (4f + (float)_combo * 3f)) + (flag ? 8f : 0f), cheer: true);
			if (Lent)
			{
				Armoury.Spill(f.LastPos, Tier, f.Level, f.Champion);
				if (f.Champion && Tier <= Roster.Beaten())
				{
					string text = Roster.Trophy(f.Prefab);
					string text2 = Roster.Material(Tier);
					if (text != null)
					{
						Armoury.Drop(text, 1, f.LastPos);
					}
					if (text2 != null)
					{
						Armoury.Drop(text2, Mathf.RoundToInt((float)(2 + Tier) * 1.5f * Plugin.Rewards.Value / 100f), f.LastPos);
					}
				}
			}
			if (f.Champion)
			{
				string text3 = ((!Lent && Tier <= Roster.Beaten()) ? Roster.Trophy(f.Prefab) : null);
				if (text3 != null)
				{
					Trophies.Add(text3);
				}
				Net.Shout(Words.Line("arena_call_champion_falls"), Lines.ChampionDown(), 3f);
				Net.Sound("roar");
			}
			else if (flag)
			{
				Net.Shout(Words.Line("arena_call_close"), Words.Line("arena_call_close_sub"), 1.8f);
			}
			else if (_combo == 2)
			{
				Net.Shout(Words.Line("arena_call_double"), "", 1.5f);
			}
			else if (_combo == 3)
			{
				Net.Shout(Words.Line("arena_call_triple"), "", 1.5f);
			}
			else if (_combo >= 5)
			{
				Net.Shout(Words.Line("arena_call_unstoppable"), Words.Line("arena_call_in_a_row", _combo), 1.8f);
			}
		}

		internal static void OnBlock(bool perfect)
		{
			if (Fighting)
			{
				Favours.OnParry(perfect);
				Crowd.Gain(perfect ? 6f : 1f, perfect);
				if (perfect && Time.time - _lastParryShout > 4f)
				{
					_lastParryShout = Time.time;
					Net.Shout(Words.Line("arena_call_parry"), "", 1.2f);
				}
			}
		}

		internal static void OnHurt(float fraction)
		{
			if (Fighting && !(fraction <= 0f))
			{
				_hurtThisRound = true;
				Favours.OnHurt();
				Crowd.Hurt(Mathf.Min(3f, fraction * 15f));
			}
		}

		internal static void Knockout()
		{
			_knockedOut = true;
		}

		internal static void NoteDeath()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (Active)
			{
				_tombUntil = Time.time + 5f;
				_tombCentre = Site.Centre;
				_tombRadius = Layout.Floor;
			}
		}

		internal static Vector3 TombSpot(Vector3 died)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			_tombUntil = 0f;
			Vector3 val = Site.World(Layout.Arrival.Pos + new Vector3(Random.Range(-4f, 4f), 0f, 5f));
			val.y = Site.Ground(val, Site.Origin.y) + 0.6f;
			return val;
		}

		private static void ClearFoes()
		{
			foreach (Foe fo in Foes)
			{
				if (!((Object)(object)fo.Go == (Object)null) && !fo.Counted)
				{
					ZNetView component = fo.Go.GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.IsValid())
					{
						component.Destroy();
					}
					else
					{
						Object.Destroy((Object)(object)fo.Go);
					}
				}
			}
			Foes.Clear();
			Queue.Clear();
		}

		internal static void Abort(string why)
		{
			if (Active)
			{
				if (Phase == PhaseKind.Victory)
				{
					FinishVictory();
				}
				else
				{
					End(Outcome.Aborted);
				}
			}
		}

		private static void StartVictory(Player player)
		{
			Phase = PhaseKind.Victory;
			_victoryAt = Time.time;
			_victoryStep = 0;
			_offFloor = 0f;
			_nextChant = Time.time + 5f;
			_timer = 90f;
			ClearFoes();
			Crowd.Set(100f);
			PrizeItems.Clear();
			_toChest = true;
			Pay(player, Outcome.Win, beforeTheFight: false);
			_toChest = false;
			Net.Sound("roar");
			Net.Sound("horn");
			Net.Sound("applause");
			Net.Props("Platform");
			Net.Fireworks(18, 12f);
			Net.Celebrate();
		}

		private static void TickVictory(Player player, float dt)
		{
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			_timer -= dt;
			float num = Time.time - _victoryAt;
			string playerName = player.GetPlayerName();
			if (_victoryStep == 0 && num > 4f)
			{
				_victoryStep = 1;
				Net.Shout(_crowned ? Words.Line("arena_call_crowned_" + KindWord(Kind)) : Words.Line("arena_call_triumphs", playerName), Words.Line(_crowned ? "arena_call_chants_name_statue" : "arena_call_chants_name", playerName), 5f);
				Net.Sound("horn");
			}
			if (_victoryStep == 1 && num > 7f)
			{
				_victoryStep = 2;
				Show.PopChest(2, PrizeItems);
				Net.Sound("roar");
				Hud.Say(Translations.T("arena_say_prize_chest"));
			}
			if (_victoryStep == 2 && num > 11f)
			{
				_victoryStep = 3;
				Net.Gate(Scenery.MainGrate, 120f);
				Net.Door(120f);
				Net.Shout(Words.Line("arena_call_take_a_bow"), Words.Line("arena_call_take_a_bow_sub"), 3f);
				Net.Fireworks(12, 9f);
			}
			if (Time.time > _nextChant)
			{
				_nextChant = Time.time + Random.Range(7f, 10f);
				Net.Sound((Random.value < 0.5f) ? "horn" : "cheer");
			}
			if (!Site.OnFloor(((Component)player).transform.position, 2f))
			{
				_offFloor += dt;
			}
			else
			{
				_offFloor = 0f;
			}
			if (((Character)player).IsDead() || _timer <= 0f || (_victoryStep >= 3 && _offFloor > 1.5f))
			{
				FinishVictory();
			}
		}

		internal static void ReadyEarly()
		{
			if ((Phase == PhaseKind.Break || Phase == PhaseKind.Arming) && _timer > 3f)
			{
				_timer = 3f;
				Net.Sound("roar");
			}
		}

		private static void FinishVictory()
		{
			Player localPlayer = Player.m_localPlayer;
			Phase = PhaseKind.None;
			Show.Armourer(on: false);
			Show.TakeChest();
			if (_stowed && (Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead())
			{
				Kit.Return(localPlayer);
			}
			_stowed = false;
			Rules.Restore(localPlayer);
			Rules.Clear();
			Net.Gate(Scenery.MainGrate, 30f);
			Net.Door(45f);
			Guard.Grace(60f);
			_closeAt = Time.time + 6f;
		}

		private static void End(Outcome outcome)
		{
			Player localPlayer = Player.m_localPlayer;
			bool flag = Phase == PhaseKind.Ready;
			Phase = PhaseKind.None;
			ClearFoes();
			Show.TakeChest();
			Show.Armourer(on: false);
			if ((Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead() && !flag && _look.Length == 0)
			{
				_look = Figures.LookOf(localPlayer);
			}
			if (_stowed && (Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead())
			{
				Kit.Return(localPlayer);
			}
			_stowed = false;
			if ((Object)(object)localPlayer != (Object)null)
			{
				Pay(localPlayer, outcome, flag);
			}
			Rules.Restore(localPlayer);
			Rules.Clear();
			if ((Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead() && outcome == Outcome.Carried)
			{
				((Character)localPlayer).SetHealth(((Character)localPlayer).GetMaxHealth() * 0.35f);
			}
			_knockedOut = false;
			Net.Gate(Scenery.MainGrate, flag ? 0f : 30f);
			Net.Door(flag ? 0f : 45f);
			Guard.Grace(60f);
			bool flag2 = outcome == Outcome.Win || outcome == Outcome.CashOut;
			if (flag2)
			{
				Net.Sound("roar");
				Net.Sound("horn");
				Net.Sound("applause");
			}
			else
			{
				Net.Sound("boo");
			}
			_closeAt = Time.time + (flag2 ? 8f : 5f);
		}

		private static void Pay(Player player, Outcome outcome, bool beforeTheFight)
		{
			bool flag = outcome == Outcome.Win;
			if (beforeTheFight)
			{
				if (Fee + Stake > 0)
				{
					Give("Coins", Fee + Stake, player);
				}
				return;
			}
			Ladder.Add("kills", _kills);
			Ladder.Add("fights", 1);
			Ladder.Best("favour", Mathf.RoundToInt(_peak));
			if (outcome == Outcome.Died)
			{
				Ladder.Add("deaths", 1);
			}
			if (flag || (Kind == KindOf.Road && outcome == Outcome.CashOut && Round >= 3))
			{
				Ladder.Add("wins", 1);
				Ladder.Add((Kind == KindOf.Champion) ? "champions" : ((Kind == KindOf.Road) ? "roads" : ((Kind == KindOf.Trial) ? "trials" : "hordes")), 1);
			}
			int num = ((Humanoid)player).GetInventory().CountItems("$item_coins", -1, true);
			if (Lent)
			{
				_purseCoins = (flag ? (((Kind == KindOf.Road) ? 250f : 80f) * (float)(Tier + 1) * Rules.Multiplier * Plugin.Rewards.Value / 100f) : 0f);
				Mats.Clear();
			}
			float num2;
			switch (outcome)
			{
			default:
				num2 = 0.5f;
				break;
			case Outcome.Died:
				num2 = 0f;
				break;
			case Outcome.CashOut:
			case Outcome.CalledOff:
				num2 = 1f;
				break;
			case Outcome.Win:
				num2 = 1.25f;
				break;
			}
			float num3 = num2;
			bool flag2 = flag && Daily && !Ladder.DailyDone;
			if (flag2)
			{
				num3 *= 1.5f;
				Ladder.Set("daily", Ladder.Today);
			}
			int num4 = Mathf.RoundToInt(_purseCoins * num3);
			int num5 = (flag ? (Stake * 2) : ((outcome == Outcome.CalledOff) ? Stake : 0));
			List<string> list = ((outcome != Outcome.Died) ? Trophies.Distinct().ToList() : new List<string>());
			if (num4 + num5 > 0)
			{
				Hand("Coins", num4 + num5);
			}
			List<string> list2 = new List<string>();
			foreach (KeyValuePair<string, float> mat in Mats)
			{
				int num6 = Mathf.FloorToInt(mat.Value * num3);
				if (num6 > 0)
				{
					Hand(mat.Key, num6);
					list2.Add(mat.Key + "*" + num6.ToString(CultureInfo.InvariantCulture));
				}
			}
			foreach (string item in list)
			{
				Hand(item, 1);
				list2.Add(item);
			}
			string text = string.Join(";", new int[6]
			{
				num4,
				Lent ? 1 : 0,
				(Lent && outcome != Outcome.Died) ? num : 0,
				num5,
				flag ? 1 : 0,
				flag2 ? 1 : 0
			}.Select((int v) => v.ToString(CultureInfo.InvariantCulture))) + ";" + string.Join(",", list2);
			string text2 = Words.Prize(text);
			int num7 = num4 + ((Lent && outcome != Outcome.Died) ? num : 0) + _kills * 5 + (flag ? 150 : 0) + Mathf.RoundToInt(_peak) + Round * 20;
			string said = ((Kind != KindOf.Road) ? Words.Line((Kind == KindOf.Endless) ? "arena_run_endless" : ((Kind == KindOf.Trial) ? "arena_run_trial" : "arena_run_champion"), Words.Land(Tier), Round) : (flag ? Words.Line("arena_run_road_end") : Words.Line("arena_run_road", Words.Land(Tier), Round, Rounds)));
			bool flag3 = (_crowned = outcome != Outcome.Aborted && outcome != Outcome.CalledOff && Ladder.Enter(KindWord(Kind), player.GetPlayerName(), said, num7, _look));
			string text3 = (flag3 ? Words.Then("-", Words.Line("arena_call_new_champion_" + KindWord(Kind))) : "");
			if (flag3)
			{
				Net.Sound("roar");
			}
			string sub = Words.Line("arena_call_half_purse", text2);
			switch (outcome)
			{
			case Outcome.Win:
				Net.Shout(Words.Line("arena_call_victory"), Words.Then(Lines.Victory(), text2, text3), 7f);
				break;
			case Outcome.CashOut:
				Net.Shout(Words.Line("arena_call_cash_out"), Words.Then(text2, text3), 6f);
				break;
			case Outcome.Died:
				Net.Shout(Words.Line("arena_call_fallen"), Words.Line(Lent ? "arena_call_fallen_lent" : "arena_call_fallen_own"), 7f);
				break;
			case Outcome.TimeUp:
				Net.Shout(Words.Line("arena_call_time"), sub, 5f);
				break;
			case Outcome.LeftRing:
				Net.Shout(Words.Line("arena_call_left_ring"), sub, 5f);
				break;
			case Outcome.Yield:
				Net.Shout(Words.Line("arena_call_yield"), sub, 5f);
				break;
			case Outcome.Carried:
				Net.Shout(Words.Line("arena_call_carried"), sub, 5f);
				break;
			case Outcome.CalledOff:
				Net.Shout(Words.Line("arena_call_called_off"), Words.Line("arena_call_no_one", text2), 5f);
				break;
			}
			if (outcome != Outcome.Aborted && outcome != Outcome.Died && !_toChest)
			{
				((Character)player).Message((MessageType)2, Translations.T("arena_prize", PrizeText(text)), 0, (Sprite)null, false);
			}
			Plugin.Log.LogInfo((object)$"Contest ended: {outcome}, {_kills} kills, prize {text}, score {num7}");
			void Hand(string prefab, int amount)
			{
				if (_toChest)
				{
					PrizeItems.Add((prefab, amount, 1, null));
				}
				else
				{
					Give(prefab, amount, player);
				}
			}
		}

		internal static string PrizeText(string data)
		{
			string[] array = data.Split(new char[1] { ';' });
			if (array.Length < 7)
			{
				return data;
			}
			int[] array2 = new int[6];
			for (int i = 0; i < 6; i++)
			{
				int.TryParse(array[i], NumberStyles.Integer, CultureInfo.InvariantCulture, out array2[i]);
			}
			bool flag = array2[1] == 1;
			bool flag2 = array2[4] == 1;
			bool flag3 = array2[5] == 1;
			List<string> list = new List<string>();
			if (array2[0] > 0)
			{
				list.Add(Translations.T(flag ? "arena_prize_coins_win" : "arena_coins", array2[0]));
			}
			if (array2[2] > 0)
			{
				list.Add(Translations.T("arena_prize_picked_up", array2[2]));
			}
			foreach (var item in Counted(array[6]))
			{
				list.Add(item.Prefab.StartsWith("Trophy") ? ItemName(item.Prefab) : Translations.T("arena_prize_item", item.Amount, ItemName(item.Prefab)));
			}
			if (array2[3] > 0)
			{
				list.Add(Translations.T(flag2 ? "arena_prize_stake_doubled" : "arena_prize_stake_back", array2[3]));
			}
			if (flag3)
			{
				list.Add(Translations.T("arena_prize_daily"));
			}
			if (list.Count <= 0)
			{
				return Translations.T("arena_prize_nothing");
			}
			return string.Join(", ", list);
		}

		internal static void Give(string prefab, int amount, Player player)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefab) : null);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val2 == (Object)null || amount <= 0)
			{
				return;
			}
			int num = Mathf.Max(1, val2.m_itemData.m_shared.m_maxStackSize);
			Inventory inventory = ((Humanoid)player).GetInventory();
			while (amount > 0)
			{
				int num2 = Mathf.Min(amount, num);
				amount -= num2;
				if (inventory.CanAddItem(val, num2))
				{
					inventory.AddItem(val, num2);
				}
				else
				{
					Object.Instantiate<GameObject>(val, ((Component)player).transform.position + Vector3.up, Quaternion.identity).GetComponent<ItemDrop>().SetStack(num2);
				}
			}
		}
	}
	internal static class Guard
	{
		private static float _graceUntil;

		private static float _next;

		internal static void Grace(float seconds)
		{
			_graceUntil = Mathf.Max(_graceUntil, Time.time + seconds);
		}

		internal static void Tick()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00e5: 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)
			if (!(Time.time < _next))
			{
				_next = Time.time + 0.5f;
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsDead() && !((Character)localPlayer).IsTeleporting() && Site.Known && Scenery.Built && !Contest.Active && !Duel.Active && !(Time.time < _graceUntil) && Site.OnFloor(((Component)localPlayer).transform.position, -0.5f))
				{
					Vector3 val = Site.World(Layout.Arrival.Pos + new Vector3(0f, 0.3f, 3f));
					val.y = Mathf.Max(val.y, Site.Ground(val, Site.Origin.y) + 0.3f);
					((Character)localPlayer).TeleportTo(val, Site.Turn * Quaternion.Euler(0f, 180f, 0f), false);
					((Character)localPlayer).Message((MessageType)2, Translations.T("arena_guards"), 0, (Sprite)null, false);
					Plugin.Log.LogInfo((object)"Someone on the fighting floor without a challenge was shown out to the forecourt");
				}
			}
		}
	}
	internal static class Lines
	{
		private static string One(string key, params object[] args)
		{
			return Words.Line(key + "_" + Random.Range(1, 5), args);
		}

		internal static string Welcome(string name)
		{
			return One("arena_welcome", name);
		}

		internal static string RoundCall(int count)
		{
			return One("arena_round_call", count);
		}

		internal static string ChampionDown()
		{
			return One("arena_champion_down");
		}

		internal static string Victory()
		{
			return One("arena_victory_line");
		}
	}
	internal static class Crowd
	{
		private sealed class Spec
		{
			public GameObject Go;

			public Vector3 At;

			public float Angle;

			public float Next;

			public bool Sitting;
		}

		private static readonly List<Spec> Specs = new List<Spec>();

		private static GameObject _root;

		private static float _lastAction;

		private static float _lastBoo;

		private static float _waveAt;

		private static float _waveAngle;

		private static float _loudSince;

		private static float _nextBuild;

		private static bool _open;

		private static int _building;

		internal static float Favour { get; private set; }

		internal static float Excitement { get; private set; }

		internal static bool IsOpen => _open;

		internal static string Mood => Translations.T((Favour < 15f) ? "arena_mood_bored" : ((Favour < 35f) ? "arena_mood_restless" : ((Favour < 55f) ? "arena_mood_watching" : ((Favour < 75f) ? "arena_mood_excited" : ((Favour < 90f) ? "arena_mood_roaring" : "arena_mood_ecstatic")))));

		internal static void Open()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			Close(bow: false);
			_open = true;
			Favour = 25f;
			Excitement = 0.25f;
			_lastAction = Time.time;
			_waveAt = 0f;
			_loudSince = 0f;
			if (Plugin.Spectators.Value && Site.Known && (Object)(object)Scenery.Root != (Object)null)
			{
				_root = new GameObject("ArenaCrowd");
				_building = 0;
			}
		}

		internal static void Close(bool bow)
		{
			_open = false;
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			_root = null;
			Specs.Clear();
		}

		internal static void Clear()
		{
			Close(bow: false);
			Sound.Clear();
		}

		private static void FillSome()
		{
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: 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_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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root == (Object)null || Time.time < _nextBuild)
			{
				return;
			}
			int num = Mathf.RoundToInt((float)Layout.Seats.Count * Mathf.Clamp01(Plugin.CrowdSize.Value / 100f));
			if (Specs.Count >= num || _building >= Layout.Seats.Count)
			{
				return;
			}
			_nextBuild = Time.time + 0.05f;
			int num2 = Mathf.Max(1, Layout.Seats.Count / Mathf.Max(1, num));
			for (int i = 0; i < 3; i++)
			{
				if (Specs.Count >= num)
				{
					break;
				}
				if (_building >= Layout.Seats.Count)
				{
					break;
				}
				Random random = new Random(_building * 7919 + 13);
				int index = (_building * num2 + _building / Mathf.Max(1, Layout.Seats.Count / num2)) % Layout.Seats.Count;
				Layout.Mark mark = Layout.Seats[index];
				_building++;
				Vector3 val = mark.Pos + new Vector3((float)(random.NextDouble() - 0.5) * 0.4f, 0f, 0f);
				Vector3 val2 = Site.World(val);
				Vector3 val3 = Site.Centre - val2;
				val3.y = 0f;
				GameObject val4 = Figures.Make(_root.transform, val2, Quaternion.LookRotation(val3), Figures.Spectator(random), collider: false);
				if ((Object)(object)val4 == (Object)null)
				{
					break;
				}
				Behaviour[] componentsInChildren = val4.GetComponentsInChildren<Behaviour>(true);
				foreach (Behaviour val5 in componentsInChildren)
				{
					if ((Object)(object)val5 != (Object)null && ((object)val5).GetType().Name.Contains("MagicaCloth"))
					{
						val5.enabled = false;
					}
				}
				Spec spec = new Spec
				{
					Go = val4,
					At = val2,
					Angle = Mathf.Atan2(val.x, val.z),
					Next = Time.time + (float)random.NextDouble() * 4f
				};
				if (random.NextDouble() < 0.45)
				{
					spec.Sitting = true;
					Figures.Hold(val4, "sit", on: true);
				}
				Specs.Add(spec);
			}
		}

		internal static void Tick(float dt)
		{
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			Sound.Tick(_open, Excitement);
			if (!_open)
			{
				Excitement = Mathf.MoveTowards(Excitement, 0f, dt * 0.2f);
				return;
			}
			FillSome();
			float num = Mathf.Clamp01(0.2f + Favour / 140f + ((Time.time - _lastAction < 3f) ? 0.35f : 0f));
			Excitement = Mathf.MoveTowards(Excitement, num, dt * ((num > Excitement) ? 1.4f : 0.3f));
			if (Contest.Fighting && Time.time - _lastAction > 16f)
			{
				Favour = Mathf.Max(0f, Favour - dt * 0.6f);
				if (Favour < 10f && Time.time - _lastBoo > 18f)
				{
					_lastBoo = Time.time;
					Boo();
					Hud.Call(Translations.T("arena_call_boo"), Translations.T("arena_call_boo_sub"), big: false);
				}
			}
			Favours.Tick();
			if (Excitement > 0.72f)
			{
				if (_loudSince == 0f)
				{
					_loudSince = Time.time;
				}
			}
			else
			{
				_loudSince = 0f;
			}
			if (_loudSince > 0f && Time.time - _loudSince > 3f && _waveAt == 0f)
			{
				_waveAt = Time.time;
				_waveAngle = Random.value * (float)Math.PI * 2f;
			}
			float num2 = ((_waveAt > 0f) ? (_waveAngle + (Time.time - _waveAt) * 1.8f) : (-100f));
			if (_waveAt > 0f && Time.time - _waveAt > 3.4906588f)
			{
				_waveAt = 0f;
			}
			Player localPlayer = Player.m_localPlayer;
			Vector3 val = (((Object)(object)localPlayer != (Object)null && Site.OnFloor(((Component)localPlayer).transform.position, 2f)) ? ((Component)localPlayer).transform.position : Site.Centre);
			bool flag = Excitement > 0.5f;
			Vector3 val2 = default(Vector3);
			foreach (Spec spec in Specs)
			{
				if ((Object)(object)spec.Go == (Object)null)
				{
					continue;
				}
				((Vector3)(ref val2))..ctor(val.x - spec.At.x, 0f, val.z - spec.At.z);
				if (((Vector3)(ref val2)).sqrMagnitude > 0.01f)
				{
					spec.Go.transform.rotation = Quaternion.Slerp(spec.Go.transform.rotation, Quaternion.LookRotation(val2, Vector3.up), dt * 1.5f);
				}
				if (spec.Sitting && flag)
				{
					spec.Sitting = false;
					Figures.Hold(spec.Go, "sit", on: false);
					spec.Next = Time.time + Random.Range(0.2f, 1.5f);
				}
				else if (!spec.Sitting && !flag && Random.value < dt * 0.02f)
				{
					spec.Sitting = true;
					Figures.Hold(spec.Go, "sit", on: true);
				}
				if (_waveAt > 0f && Mathf.Abs(Mathf.DeltaAngle(spec.Angle * 57.29578f, num2 * 57.29578f)) < 10f && Time.time > spec.Next)
				{
					spec.Next = Time.time + 2.5f;
					Figures.Emote(spec.Go, "cheer");
				}
				else if (!spec.Sitting && Time.time > spec.Next && Random.value < 0.25f + 0.6f * Excitement)
				{
					spec.Next = Time.time + Random.Range(3f, 9f) * (1.4f - Excitement);
					if (Excitement > 0.35f)
					{
						Figures.Emote(spec.Go, Pick("cheer", "cheer", "roar", "toast", "flex", "challenge", "point", "thumbsup"));
					}
				}
			}
		}

		private static string Pick(params string[] list)
		{
			return list[Random.Range(0, list.Length)];
		}

		private static void React(float share, params string[] emotes)
		{
			foreach (Spec spec in Specs)
			{
				if (!((Object)(object)spec.Go == (Object)null) && !(Random.value > share))
				{
					if (spec.Sitting)
					{
						spec.Sitting = false;
						Figures.Hold(spec.Go, "sit", on: false);
					}
					spec.Next = Time.time + Random.Range(0f, 0.6f);
					Figures.Emote(spec.Go, emotes[Random.Range(0, emotes.Length)]);
				}
			}
		}

		internal static bool Throw(string item, int amount, Action<ItemDrop> setup = null)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || Layout.Seats.Count == 0)
			{
				return false;
			}
			GameObject val = ((item != null) ? ZNetScene.instance.GetPrefab(item) : null);
			if ((Object)(object)val == (Object)null || (Object)(object)val.GetComponent<ItemDrop>() == (Object)null)
			{
				return false;
			}
			Spec spec = ((Specs.Count > 0) ? Specs[Random.Range(0, Specs.Count)] : null);
			if ((Object)(object)spec?.Go != (Object)null)
			{
				Figures.Emote(spec.Go, "wave");
			}
			Vector3 val2 = (spec?.At ?? Site.World(Layout.Seats[Random.Range(0, Layout.Seats.Count)].Pos)) + Vector3.up * 2f;
			Vector3 val3 = ((Component)localPlayer).transform.position + new Vector3(Random.Range(-2f, 2f), 0f, Random.Range(-2f, 2f));
			GameObject val4 = Object.Instantiate<GameObject>(val, val2, Quaternion.identity);
			ItemDrop component = val4.GetComponent<ItemDrop>();
			if ((Object)(object)component != (Object)null)
			{
				setup?.Invoke(component);
				if (!Kit.IsLoan(component.m_itemData) && !Kit.Keeps(item, Contest.Tier))
				{
					component.m_itemData.m_customData["dh_arena_loan"] = "gift";
				}
				component.SetStack(Mathf.Max(1, amount));
			}
			Rigidbody component2 = val4.GetComponent<Rigidbody>();
			if ((Object)(object)component2 != (Object)null)
			{
				Vector3 val5 = default(Vector3);
				((Vector3)(ref val5))..ctor(val3.x - val2.x, 0f, val3.z - val2.z);
				float num = Mathf.Clamp(((Vector3)(ref val5)).magnitude / 9f, 0.8f, 1.8f);
				Vector3 linearVelocity = val5 / num;
				linearVelocity.y = (val3.y - val2.y) / num + 0.5f * (0f - Physics.gravity.y) * num;
				component2.linearVelocity = linearVelocity;
			}
			Cheer();
			return true;
		}

		internal static void Mirror(string emote)
		{
			if (emote == "laugh")
			{
				Sound.Boo();
				React(0.5f, "laugh", "point");
			}
			else
			{
				Sound.Cheer();
				React(0.55f, emote, emote, "cheer");
			}
		}

		internal static void Gain(float amount, bool cheer)
		{
			Favour = Mathf.Clamp(Favour + amount, 0f, 100f);
			_lastAction = Time.time;
			if (cheer)
			{
				Cheer();
			}
		}

		internal static void Set(float favour)
		{
			Favour = Mathf.Clamp(favour, 0f, 100f);
		}

		internal static void Hurt(float amount)
		{
			Favour = Mathf.Max(0f, Favour - amount);
		}

		internal static void Play(string name)
		{
			switch (name)
			{
			case "cheer":
				Cheer();
				break;
			case "roar":
				Roar();
				break;
			case "boo":
				Boo();
				break;
			case "applause":
				Applause();
				break;
			case "gong":
				Sound.Gong();
				break;
			case "horn":
				Sound.Chant();
				React(0.7f, "cheer", "roar", "toast");
				break;
			}
		}

		internal static void Celebrate()
		{
			Favour = 100f;
			Excitement = 1f;
			_lastAction = Time.time;
			foreach (Spec spec in Specs)
			{
				if ((Object)(object)spec.Go != (Object)null && spec.Sitting)
				{
					spec.Sitting = false;
					Figures.Hold(spec.Go, "sit", on: false);
				}
			}
			React(1f, "cheer", "roar", "toast", "flex", "challenge");
			_waveAt = Time.time;
			_waveAngle = Random.value * (float)Math.PI * 2f;
			_loudSince = Time.time;
		}

		internal static void Cheer()
		{
			Sound.Cheer();
			React(0.35f, "cheer", "roar", "flex", "toast");
		}

		internal static void Roar()
		{
			Sound.Roar();
			React(0.8f, "cheer", "roar", "challenge", "toast", "flex");
		}

		internal static void Boo()
		{
			Sound.Boo();
			React(0.3f, "nonono", "laugh", "point");
		}

		internal static void Applause()
		{
			Sound.Applause();
			React(0.4f, "cheer", "thumbsup");
		}

		internal static void Gong()
		{
			Sound.Gong();
		}

		internal static void Horn()
		{
			Play("horn");
		}
	}
	internal static class Duel
	{
		private enum PhaseKind
		{
			None,
			Walking,
			Countdown,
			Fighting
		}

		private const string RpcChallenge = "DHArenaChallenge";

		private const string RpcAnswer = "DHArenaAnswer";

		private const string RpcEnd = "DHArenaEnd";

		private static PhaseKind _phase;

		private static long _opponent;

		private static string _opponentName = "";

		private static int _wager;

		private static int _count;

		private static Vector3 _at;

		private static float _timer;

		private static float _outside;

		private static float _missing;

		private static float _closeAt;

		private static bool _prevPvp;

		private static bool _ending;

		private static bool _placed;

		private static bool _pvpSet;

		private const float Apart = 8f;

		private static long _inFrom;

		private static long _outTo;

		private static string _inName = "";

		private static int _inWager;

		private static int _outWager;

		private static Vector3 _inAt;

		private static Vector3 _outAt;

		private static float _inUntil;

		private static float _outUntil;

		private static ZRoutedRpc _registeredOn;

		private static int _awakeFrame = -100;

		internal static bool Active => _phase != PhaseKind.None;

		internal static bool Fighting => _phase == PhaseKind.Fighting;

		internal static string OpponentName => _opponentName;

		internal static int Wager => _wager;

		internal static Vector3 Centre => Site.Centre;

		internal static Player Opponent => ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => (Object)(object)p != (Object)null && ((Character)p).GetOwner() == _opponent));

		internal static bool HasIncoming
		{
			get
			{
				if (_inFrom != 0L)
				{
					return Time.unscaledTime < _inUntil;
				}
				return false;
			}
		}

		internal static string IncomingName => _inName;

		internal static int IncomingWager => _inWager;

		private static long MyId => ZDOMan.GetSessionID();

		internal static void Init()
		{
			_awakeFrame = Time.frameCount;
		}

		internal static bool Involves(long peer)
		{
			if (peer != 0L)
			{
				if (!Active || peer != _opponent)
				{
					if (peer == _outTo)
					{
						return Time.unscaledTime < _outUntil;
					}
					return false;
				}
				return true;
			}
			return false;
		}

		private static void Register()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance == null)
			{
				_registeredOn = null;
			}
			else if (Time.frameCount > _awakeFrame + 2 && instance != _registeredOn)
			{
				_registeredOn = instance;
				Unregister();
				instance.Register<ZPackage>("DHArenaChallenge", (Action<long, ZPackage>)OnChallenge);
				instance.Register<ZPackage>("DHArenaAnswer", (Action<long, ZPackage>)OnAnswer);
				instance.Register<ZPackage>("DHArenaEnd", (Action<long, ZPackage>)OnEnd);
			}
		}

		internal static void Unregister()
		{
			if (ZRoutedRpc.instance != null && AccessTools.Field(typeof(ZRoutedRpc), "m_functions").GetValue(ZRoutedRpc.instance) is IDictionary dictionary)
			{
				string[] array = new string[3] { "DHArenaChallenge", "DHArenaAnswer", "DHArenaEnd" };
				foreach (string text in array)
				{
					dictionary.Remove(StringExtensionMethods.GetStableHashCode(text));
				}
			}
		}

		private static void Send(long to, string rpc, ZPackage pkg)
		{
			if (ZRoutedRpc.instance == null)
			{
				return;
			}
			try
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(to, rpc, new object[1] { pkg });
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Arena duel message failed: " + ex.Message));
			}
		}

		private static string NameOf(long owner)
		{
			Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player x) => (Object)(object)x != (Object)null && ((Character)x).GetOwner() == owner));
			if (!((Object)(object)val != (Object)null))
			{
				return Translations.T("arena_your_opponent");
			}
			return val.GetPlayerName();
		}

		internal static string Challenge(Player other, int wager, Vector3 at)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)other == (Object)null)
			{
				return Translations.T("arena_not_now");
			}
			if (Active || Contest.Active)
			{
				return Translations.T("arena_already_fighting");
			}
			if (Net.RemoteFight)
			{
				return Translations.T("arena_busy_wait_ring", Net.BusyText);
			}
			if (((Humanoid)localPlayer).GetInventory().CountItems("$item_coins", -1, true) < wager)
			{
				return Translations.T("arena_no_coins_wager");
			}
			_outTo = ((Character)other).GetOwner();
			_outWager = wager;
			_outAt = at;
			_outUntil = Time.unscaledTime + 30f;
			ZPackage val = new ZPackage();
			val.Write(wager);
			val.Write(localPlayer.GetPlayerName());
			val.Write(at);
			Send(_outTo, "DHArenaChallenge", val);
			return null;
		}

		private static void OnChallenge(long sender, ZPackage pkg)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			int inWager = pkg.ReadInt();
			string text = pkg.ReadString();
			Vector3 inAt = pkg.ReadVector3();
			if (!((Object)(object)Player.m_localPlayer == (Object)null))
			{
				if (Active || Contest.Active || HasIncoming || Net.RemoteFight)
				{
					Reply(sender, accept: false);
					return;
				}
				_inFrom = sender;
				_inName = text;
				_inWager = inWager;
				_inAt = inAt;
				_inUntil = Time.unscaledTime + 30f;
				((Character)Player.m_localPlayer).Message((MessageType)2, Translations.T("arena_challenges_you", text), 0, (Sprite)null, false);
				Window.Open(Window.Context.Master, null, 1);
			}
		}

		private static void Reply(long to, bool accept)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(accept);
			Send(to, "DHArenaAnswer", val);
		}

		internal static string Accept()
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || !HasIncoming)
			{
				return Translations.T("arena_challenge_expired");
			}
			if (Active || Contest.Active)
			{
				return Translations.T("arena_already_fighting");
			}
			if (Net.RemoteFight)
			{
				Decline();
				return Translations.T("arena_busy_taken", Net.BusyText);
			}
			if (((Humanoid)localPlayer).GetInventory().CountItems("$item_coins", -1, true) < _inWager)
			{
				Decline();
				return Translations.T("arena_no_coins_wager");
			}
			if (Travel.Distance(((Component)localPlayer).transform.position) > 90f)
			{
				return Translations.T("arena_come_first");
			}
			long inFrom = _inFrom;
			string inName = _inName;
			int inWager = _inWager;
			Vector3 inAt = _inAt;
			_inFrom = 0L;
			Reply(inFrom, accept: true);
			Begin(inFrom, inName, inWager, inAt);
			Window.Close();
			return null;
		}

		internal static void Decline()
		{
			if (_inFrom != 0L)
			{
				Reply(_inFrom, accept: false);
			}
			_inFrom = 0L;
		}

		private static void OnAnswer(long sender, ZPackage pkg)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			bool flag = pkg.ReadBool();
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && sender == _outTo && !(Time.unscaledTime > _outUntil))
			{
				_outTo = 0L;
				if (!flag)
				{
					Hud.Say(Translations.T("arena_challenge_refused", NameOf(sender)));
				}
				else if (Active || Contest.Active || Net.RemoteFight || ((Humanoid)localPlayer).GetInventory().CountItems("$item_coins", -1, true) < _outWager)
				{
					End(sender, theyWin: false, "cancel");
				}
				else
				{
					Begin(sender, NameOf(sender), _outWager, _outAt);
				}
			}
		}

		private static void Begin(long opponent, string name, int wager, Vector3 at)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				if (wager > 0)
				{
					((Humanoid)localPlayer).GetInventory().RemoveItem("$item_coins", wager, -1, true);
				}
				_opponent = opponent;
				_opponentName = name;
				_wager = wager;
				_at = at;
				_phase = PhaseKind.Walking;
				_timer = 90f;
				_count = 6;
				_outside = 0f;
				_missing = 0f;
				_ending = false;
				_closeAt = 0f;
				_placed = false;
				((Character)localPlayer).Heal(((Character)localPlayer).GetMaxHealth(), true);
				Crowd.Open();
				Crowd.Gong();
				Scenery.OpenGate(Scenery.MainGrate, 90f);
				Net.Door(90f);
				Hud.Shout(Translations.T("arena_call_duel"), (wager > 0) ? Translations.T("arena_duel_begin_wager", name, wager) : Translations.T("arena_duel_begin", name), 5f);
			}
		}

		internal static void Tick(float dt)
		{
			//IL_0076: 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_030d: Unknown result type (might be due to invalid IL or missing references)
			Register();
			if (_closeAt > 0f && Time.time >= _closeAt)
			{
				_closeAt = 0f;
				if (!Contest.Active)
				{
					Crowd.Close(bow: true);
				}
			}
			if (!Active)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			if (_phase == PhaseKind.Walking)
			{
				_timer -= dt;
				Player opponent = Opponent;
				if (!_placed && Site.OnFloor(((Component)localPlayer).transform.position, -1f))
				{
					_placed = true;
					Place(localPlayer);
					Hud.Say(Translations.T("arena_duel_wait", _opponentName));
				}
				if (_placed)
				{
					Hold(localPlayer);
				}
				if (_placed && (Object)(object)opponent != (Object)null && Site.OnFloor(((Component)opponent).transform.position, -1f))
				{
					Scenery.CloseGate(Scenery.MainGrate);
					Net.Door(0f);
					_phase = PhaseKind.Countdown;
					_timer = 5.5f;
					_count = 6;
					Hud.Shout(Translations.T("arena_call_duel"), (_wager > 0) ? Translations.T("arena_duel_vs_pot", _opponentName, _wager * 2) : Translations.T("arena_duel_vs", _opponentName), 3.5f);
					Crowd.Gong();
				}
				else if (_timer <= 0f)
				{
					if (_wager > 0)
					{
						Contest.Give("Coins", _wager, localPlayer);
					}
					End(_opponent, theyWin: false, "cancel");
					Finish(null, Translations.T("arena_duel_timeout"));
				}
				return;
			}
			if (_phase == PhaseKind.Countdown)
			{
				Hold(localPlayer);
				_timer -= dt;
				int num = Mathf.CeilToInt(_timer);
				if (num < _count && num >= 1 && num <= 5)
				{
					_count = num;
					Hud.Count(num.ToString());
				}
				if (_timer <= 0f)
				{
					_prevPvp = ((Character)localPlayer).IsPVPEnabled();
					_pvpSet = true;
					localPlayer.SetPVP(true);
					_phase = PhaseKind.Fighting;
					Hud.Count(Translations.T("arena_fight"));
					Crowd.Cheer();
				}
				return;
			}
			if (!((Character)localPlayer).IsPVPEnabled())
			{
				localPlayer.SetPVP(true);
				Hud.Say(Translations.T("arena_pvp_stays"));
			}
			if (!Player.GetAllPlayers().Any((Player p) => (Object)(object)p != (Object)null && ((Character)p).GetOwner() == _opponent))
			{
				_missing += dt;
			}
			else
			{
				_missing = 0f;
			}
			if (_missing > 8f)
			{
				if (_wager > 0)
				{
					Contest.Give("Coins", _wager, localPlayer);
				}
				Finish(null, Translations.T("arena_duel_gone"));
			}
			else if (!Site.OnFloor(((Component)localPlayer).transform.position, 1.5f))
			{
				_outside += dt;
				if (_outside > 6f)
				{
					End(_opponent, theyWin: true, "forfeit");
					Finish(false, Translations.T("arena_duel_left"));
				}
			}
			else
			{
				_outside = Mathf.Max(0f, _outside - dt);
			}
		}

		private static Vector3 Mark(out Quaternion facing)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			float num = ((MyId < _opponent) ? (-1f) : 1f);
			float num2 = num * 8f;
			facing = Site.Turn * Quaternion.LookRotation(new Vector3(0f - num, 0f, 0f));
			return Site.World(new Vector3(num2, Layout.FloorHeight(num2, 0f) + 0.15f, 0f));
		}

		private static void Place(Player me)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			Quaternion facing;
			Vector3 val = Mark(out facing);
			val.y = Site.Ground(val, val.y) + 0.15f;
			((Component)me).transform.SetPositionAndRotation(val, facing);
			Rigidbody component = ((Component)me).GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				component.position = val;
				component.linearVelocity = Vector3.zero;
			}
			((Character)me).SetLookDir(facing * Vector3.forward, 0f);
			Fx.SpawnPuff(val);
			Crowd.Cheer();
		}

		private static void Hold(Player me)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Quaternion facing;
			Vector3 val = Mark(out facing);
			Vector3 val2 = ((Component)me).transform.position - val;
			val2.y = 0f;
			if (((Vector3)(ref val2)).magnitude > 1.5f)
			{
				Place(me);
			}
		}

		internal static void Lose()
		{
			if (_phase == PhaseKind.Fighting && !_ending)
			{
				_ending = true;
				End(_opponent, theyWin: true, "beaten");
				Finish(false, Translations.T("arena_duel_beaten"));
			}
		}

		private static void End(long to, bool theyWin, string reason)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(theyWin);
			val.Write(reason);
			Send(to, "DHArenaEnd", val);
		}

		private static void OnEnd(long sender, ZPackage pkg)
		{
			bool flag = pkg.ReadBool();
			string text = pkg.ReadString();
			if (!Active || sender != _opponent)
			{
				return;
			}
			if (text == "cancel")
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null && _wager > 0)
				{
					Contest.Give("Coins", _wager, localPlayer);
				}
				Finish(null, Translations.T("arena_duel_called_off"));
			}
			else
			{
				_ending = true;
				Finish(flag, flag ? Translations.T((text == "forfeit") ? "arena_duel_they_left" : "arena_duel_they_beaten", _opponentName) : Translations.T("arena_duel_beaten"));
			}
		}

		private static void Finish(bool? win, string why)
		{
			Player localPlayer = Player.m_localPlayer;
			bool flag = _phase == PhaseKind.Fighting;
			_phase = PhaseKind.None;
			Scenery.OpenGate(Scenery.MainGrate, 30f);
			Net.Door(45f);
			Guard.Grace(60f);
			if ((Object)(object)localPlayer != (Object)null)
			{
				if (_pvpSet)
				{
					localPlayer.SetPVP(_prevPvp);
				}
				_pvpSet = false;
				((Character)localPlayer).Heal(((Character)localPlayer).GetMaxHealth(), true);
				if (win == true)
				{
					int num = _wager * 2;
					int num2 = num / 10;
					if (num - num2 > 0)
					{
						Contest.Give("Coins", num - num2, localPlayer);
					}
					Ladder.Add("duelwins", 1);
					Hud.Shout(Translations.T("arena_call_you_win"), why + ((num > 0) ? ("   -   " + Translations.T("arena_coins", num - num2)) : ""), 5f);
					Crowd.Roar();
					Crowd.Horn();
				}
				else if (win == false)
				{
					Ladder.Add("duellosses", 1);
					Hud.Shout(Translations.T("arena_call_defeated"), why);
					Crowd.Boo();
				}
				else
				{
					Hud.Shout(Translations.T("arena_call_duel_off"), why, 3f);
				}
			}
			_closeAt = Time.time + 6f;
		}

		internal static void Abort(bool tell)
		{
			if (Active)
			{
				Player localPlayer = Player.m_localPlayer;
				if (tell)
				{
					End(_opponent, theyWin: true, "forfeit");
				}
				if ((Object)(object)localPlayer != (Object)null && _pvpSet)
				{
					localPlayer.SetPVP(_prevPvp);
				}
				_pvpSet = false;
				_phase = PhaseKind.None;
			}
		}
	}
	internal static class Favours
	{
		private enum Demand
		{
			None,
			Emote,
			Kill,
			Parry,
			Untouched
		}

		private static float _nextGift;

		private static bool _pitied;

		private static int _steelLand = -1;

		private static readonly string[] HealthMeads = new string[7] { "MeadHealthMinor", "MeadHealthMinor", "MeadHealthMinor", "MeadHealthMedium", "MeadHealthMedium", "MeadHealthMajor", "MeadHealthMajor" };

		private static readonly string[] StaminaMeads = new string[7] { "MeadStaminaMinor", "MeadStaminaMin