Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Arena Combat v0.1.13
BepInEx/plugins/ArenaCombat/ArenaCombat.dll
Decompiled an hour ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using ArenaCombat.Core; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ArenaCombat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.13.0")] [assembly: AssemblyInformationalVersion("0.1.13")] [assembly: AssemblyProduct("ArenaCombat")] [assembly: AssemblyTitle("ArenaCombat")] [assembly: AssemblyVersion("0.1.13.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ArenaCombat { internal sealed class ArenaMenu { private readonly Plugin plugin; private GameObject? panel; private GameObject? content; private GameObject? selectedFallback; private ScrollRect? enemyScroll; private Image? reserveFill; private Image? selectedIcon; private Text? selectedBiome; private Text? enemyCount; private readonly Dictionary<GameObject, string> rowPrefabs = new Dictionary<GameObject, string>(); private readonly Dictionary<string, Sprite?> icons = new Dictionary<string, Sprite>(StringComparer.Ordinal); private static readonly Color Gold = new Color(0.92f, 0.69f, 0.32f); private static readonly string[] FrameEdges = new string[4] { "Top", "Bottom", "Left", "Right" }; private static readonly Color RowNormal = new Color(0.21f, 0.245f, 0.28f); private static readonly Color RowSelected = new Color(0.38f, 0.29f, 0.14f); private static readonly Color Muted = new Color(0.8f, 0.82f, 0.82f); private const float CardCenterY = -51.5f; private const float CardHeight = 527f; private const float ListViewportHeight = 426f; private const float ListX = -220f; private const float EncounterX = 220f; private static readonly Color RowBorder = new Color(0.46f, 0.52f, 0.55f, 0.38f); private Text? balanceText; private Text? selectedText; private Text? quoteText; private Text? detailText; private Text? strengthText; private Button? weakerButton; private Button? strongerButton; private int strengthTenths = 10; private Button? summonButton; private Button? practiceButton; private Button? rewardsButton; private readonly List<Button> starButtons = new List<Button>(); private readonly List<GameObject> rows = new List<GameObject>(); private InputField? search; private Dropdown? biome; private MenuSnapshot? snapshot; private ZDOID target = ZDOID.None; private ZRoutedRpc? world; private int serial; private int lastApplied; private int stars; private int commandSerial; private bool loot; private bool commandPending; private string selected = ""; private string listSignature = ""; private float nextPoll; private float nextSettings; private MenuSnapshot? settings; private float commandStarted; internal bool HasServerSettings => settings != null; internal bool BuilderIsAdmin { get { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { return settings?.BuilderIsAdmin ?? false; } return true; } } internal bool AdminBuildOnly { get { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { return settings?.AdminBuildOnly ?? plugin.Settings.AdminBuildOnly.Value; } return plugin.Settings.AdminBuildOnly.Value; } } internal bool Invulnerable { get { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { return settings?.Invulnerable ?? plugin.Settings.Invulnerable.Value; } return plugin.Settings.Invulnerable.Value; } } internal int Maximum { get { if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer()) { return settings?.Maximum ?? plugin.Settings.MaximumActivators.Value; } return plugin.Settings.MaximumActivators.Value; } } internal int ActivatorCount => settings?.Count ?? 0; private static Vector2 Center => new Vector2(0.5f, 0.5f); internal void RefreshBuildPermissions() { nextSettings = 0f; } internal ArenaMenu(Plugin plugin) { //IL_003a: 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) this.plugin = plugin; } internal void Update() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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_013c: Unknown result type (might be due to invalid IL or missing references) if (GUIManager.IsHeadless()) { return; } if (world != ZRoutedRpc.instance) { world = ZRoutedRpc.instance; settings = null; nextSettings = 0f; Close(); } if (!Object.op_Implicit((Object)(object)ZNet.instance) || world == null) { return; } if (Time.unscaledTime >= nextSettings) { nextSettings = Time.unscaledTime + 5f; Send(2, ZDOID.None); } if (!Object.op_Implicit((Object)(object)panel)) { return; } Player localPlayer = Player.m_localPlayer; ZDOMan instance = ZDOMan.instance; ZDO val = ((instance != null) ? instance.GetZDO(target) : null); float num = settings?.InteractionDistance ?? plugin.Settings.InteractDistance.Value; if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting() || val == null || Vector3.Distance(((Component)localPlayer).transform.position, val.GetPosition()) > num + 1f) { Close(); return; } if (Input.GetKeyDown((KeyCode)27)) { Close(); return; } if (Time.unscaledTime >= nextPoll) { nextPoll = Time.unscaledTime + 1f; Send(0, target); } if (commandPending && Time.unscaledTime - commandStarted > 5f) { commandPending = false; Feedback("Request timed out. Refreshing the encounter status."); RefreshDetails(); } } internal void Open(ZDOID piece) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_03f3: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_0506: Unknown result type (might be due to invalid IL or missing references) //IL_0531: Unknown result type (might be due to invalid IL or missing references) //IL_061d: Unknown result type (might be due to invalid IL or missing references) //IL_06b6: Unknown result type (might be due to invalid IL or missing references) //IL_0706: Unknown result type (might be due to invalid IL or missing references) //IL_07d8: Unknown result type (might be due to invalid IL or missing references) //IL_080f: Unknown result type (might be due to invalid IL or missing references) //IL_0882: Unknown result type (might be due to invalid IL or missing references) //IL_08f8: Unknown result type (might be due to invalid IL or missing references) //IL_08fd: Unknown result type (might be due to invalid IL or missing references) //IL_090f: Unknown result type (might be due to invalid IL or missing references) //IL_091d: Unknown result type (might be due to invalid IL or missing references) //IL_0938: Unknown result type (might be due to invalid IL or missing references) //IL_0953: Unknown result type (might be due to invalid IL or missing references) //IL_0973: Unknown result type (might be due to invalid IL or missing references) //IL_0983: Unknown result type (might be due to invalid IL or missing references) //IL_09aa: Unknown result type (might be due to invalid IL or missing references) Close(); if (GUIManager.IsHeadless() || !Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront)) { return; } target = piece; snapshot = null; listSignature = ""; lastApplied = 0; commandPending = false; GUIManager instance = GUIManager.Instance; panel = instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 900f, 680f, false); ((Object)panel).name = "ArenaCombatMenu"; Label("ARENA COORDINATOR", 0f, 296f, 610f, 44f, 32); Divider(panel.transform, "Header divider", 0f, 270f, 820f, ornament: true); MakeButton("Close", 370f, 296f, 95f, 38f, Close); balanceText = Label("Connecting to the arena…", 0f, 246f, 820f, 26f, 18); Image val = Surface(panel.transform, "Reserve track", 0f, 224f, 810f, 5f, new Color(0.06f, 0.06f, 0.06f, 0.9f)); reserveFill = Surface(((Component)val).transform, "Reserve fill", 0f, 0f, 0f, 5f, Gold); RectTransform rectTransform = ((Graphic)reserveFill).rectTransform; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0f, 0.5f); rectTransform.anchorMax = val2; rectTransform.anchorMin = val2; rectTransform.pivot = new Vector2(0f, 0.5f); CreateScrollArea(); search = instance.CreateInputField(panel.transform, Center, Center, new Vector2(-322.5f, 150f), (ContentType)0, "Search enemies…", 16, 205f, 36f).GetComponent<InputField>(); ((UnityEvent<string>)(object)search.onValueChanged).AddListener((UnityAction<string>)delegate { RebuildList(); }); biome = instance.CreateDropDown(panel.transform, Center, Center, new Vector2(-112.5f, 150f), 15, 195f, 36f).GetComponent<Dropdown>(); biome.AddOptions(new List<string> { "All unlocked biomes" }); ((UnityEvent<int>)(object)biome.onValueChanged).AddListener((UnityAction<int>)delegate { RebuildList(); }); biome.captionText.font = instance.AveriaSerif; Surface(panel.transform, "Encounter border", 220f, -51.5f, 410f, 527f, new Color(0.64f, 0.48f, 0.26f, 0.75f)); Surface(panel.transform, "Encounter inset", 220f, -51.5f, 406f, 523f, new Color(0.075f, 0.08f, 0.09f)); Surface(panel.transform, "Encounter heading", 220f, 155f, 406f, 110f, new Color(0.13f, 0.15f, 0.17f)); Divider(panel.transform, "Portrait divider", 220f, 100f, 370f, ornament: false); Surface(panel.transform, "Portrait backing", 87f, 155f, 64f, 64f, new Color(0.05f, 0.055f, 0.06f)); selectedIcon = Surface(panel.transform, "Enemy portrait", 87f, 155f, 60f, 60f, Color.white); selectedIcon.preserveAspect = true; selectedFallback = Silhouette(panel.transform, 87f, 155f, 50f); selectedText = Label("Select an enemy", 268f, 168f, 255f, 52f, 24); selectedText.alignment = (TextAnchor)3; selectedText.resizeTextForBestFit = true; selectedText.resizeTextMinSize = 18; selectedText.resizeTextMaxSize = 24; selectedBiome = Label("", 268f, 130f, 255f, 24f, 16); selectedBiome.font = instance.AveriaSerif; selectedBiome.alignment = (TextAnchor)3; ((Graphic)selectedBiome).color = Muted; ((Graphic)Label("ENEMY LEVEL", 220f, 77f, 370f, 20f, 14)).color = Gold; starButtons.Clear(); for (int num = 0; num <= 2; num++) { int level = num; Button val3 = MakeButton(num + ((num == 1) ? " star" : " stars"), 96 + num * 124, 46f, 116f, 38f, delegate { stars = level; RefreshDetails(); }); AddButtonHighlight(val3, "Choice highlight"); starButtons.Add(val3); } Divider(panel.transform, "Level divider", 220f, 14f, 370f, ornament: false); ((Graphic)Label("STRENGTH - HEALTH & DAMAGE", 220f, -7f, 370f, 20f, 13)).color = Gold; weakerButton = MakeButton("-", 70f, -36f, 50f, 32f, delegate { ChangeStrength(-1); }); strongerButton = MakeButton("+", 370f, -36f, 50f, 32f, delegate { ChangeStrength(1); }); strengthText = Label("1.0x", 220f, -36f, 220f, 32f, 22); ((Graphic)strengthText).color = Gold; Divider(panel.transform, "Strength divider", 220f, -63f, 370f, ornament: false); ((Graphic)Label("FIGHT MODE", 220f, -84f, 370f, 20f, 13)).color = Gold; practiceButton = MakeButton("Practice", 124f, -113f, 178f, 34f, delegate { loot = false; RefreshDetails(); }); rewardsButton = MakeButton("Loot rewards", 316f, -113f, 178f, 34f, delegate { loot = true; RefreshDetails(); }); AddButtonHighlight(practiceButton, "Choice highlight"); AddButtonHighlight(rewardsButton, "Choice highlight"); Divider(panel.transform, "Loot divider", 220f, -141f, 370f, ornament: false); ((Graphic)Label("RESERVE COST", 220f, -160f, 370f, 20f, 13)).color = Muted; quoteText = Label("", 220f, -188f, 370f, 32f, 25); ((Graphic)quoteText).color = Gold; detailText = Label("", 220f, -228f, 370f, 52f, 14); detailText.font = instance.AveriaSerif; detailText.resizeTextForBestFit = true; detailText.resizeTextMinSize = 13; detailText.resizeTextMaxSize = 14; ((Graphic)detailText).color = GUIManager.Instance.ValheimBeige; Divider(panel.transform, "Summon divider", 220f, -259f, 370f, ornament: false); summonButton = MakeButton("Summon enemy", 220f, -287f, 370f, 44f, Summon); AddButtonHighlight(summonButton, "Action highlight"); ColorBlock colors = ((Selectable)summonButton).colors; ((ColorBlock)(ref colors)).normalColor = new Color(1.25f, 1.05f, 0.72f); ((ColorBlock)(ref colors)).selectedColor = ((ColorBlock)(ref colors)).normalColor; ((ColorBlock)(ref colors)).highlightedColor = new Color(1.45f, 1.22f, 0.82f); ((ColorBlock)(ref colors)).pressedColor = new Color(0.95f, 0.76f, 0.48f); ((ColorBlock)(ref colors)).disabledColor = new Color(0.5f, 0.5f, 0.5f, 0.65f); ((Selectable)summonButton).colors = colors; ((Component)summonButton).GetComponentInChildren<Text>().fontSize = 18; GUIManager.BlockInput(true); RefreshDetails(); Send(0, target); nextPoll = Time.unscaledTime + 1f; } internal void ActivatorSuppressed(ZDOID piece) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (target == piece) { Close(); } } internal void Close() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)panel)) { Object.Destroy((Object)(object)panel); GUIManager.BlockInput(false); } panel = null; content = null; enemyScroll = null; snapshot = null; reserveFill = null; selectedIcon = null; target = ZDOID.None; rows.Clear(); rowPrefabs.Clear(); icons.Clear(); starButtons.Clear(); commandPending = false; } internal void Receive(MenuSnapshot incoming) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) settings = incoming; if (((ZDOID)(ref incoming.Piece)).IsNone() || !Object.op_Implicit((Object)(object)panel) || incoming.Piece != target || incoming.Request < lastApplied) { return; } lastApplied = incoming.Request; snapshot = incoming; if (incoming.Request >= commandSerial) { commandPending = false; } if (!string.IsNullOrEmpty(incoming.Message)) { Feedback(incoming.Message); } if (Object.op_Implicit((Object)(object)balanceText)) { balanceText.text = "Reserve: " + ((decimal)incoming.Units / 1000000m).ToString("0.#", CultureInfo.InvariantCulture) + " / " + incoming.Capacity + " • +" + incoming.Regeneration.ToString("0.##", CultureInfo.InvariantCulture) + " tokens/minute"; } if (Object.op_Implicit((Object)(object)reserveFill)) { ((Graphic)reserveFill).rectTransform.sizeDelta = new Vector2(810f * Mathf.Clamp01((float)incoming.Units / (1000000f * (float)Math.Max(1, incoming.Capacity))), 5f); } string text = incoming.LatestTier + "|" + string.Join("|", incoming.Rows.Select((MenuRow row) => row.Prefab + ":" + string.Join(",", row.Costs))); if (text != listSignature) { listSignature = text; int value = biome.value; biome.ClearOptions(); List<string> list = new List<string> { "All unlocked biomes" }; list.AddRange(ArenaRules.Biomes.Take(incoming.LatestTier + 1)); biome.AddOptions(list); biome.SetValueWithoutNotify(Math.Min(value, list.Count - 1)); if (!incoming.Rows.Any((MenuRow row) => row.Prefab == selected)) { selected = incoming.Rows.FirstOrDefault()?.Prefab ?? ""; } RebuildList(); } RefreshDetails(); } private void RebuildList() { //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)content) || snapshot == null) { return; } foreach (GameObject row in rows) { row.SetActive(false); Object.Destroy((Object)(object)row); } rows.Clear(); rowPrefabs.Clear(); InputField? obj = search; string query = ((obj != null) ? obj.text.Trim() : null) ?? ""; List<MenuRow> list = snapshot.Rows.Where((MenuRow row) => (biome.value == 0 || row.Tier == biome.value - 1) && (Localized(row.Name).IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0 || row.Prefab.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0)).ToList(); int num = 0; foreach (MenuRow item in list) { MenuRow captured = item; GameObject val = GUIManager.Instance.CreateButton("", content.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, (float)(-36 - num * 64)), 386f, 58f); val.GetComponent<Image>().sprite = null; Button component = val.GetComponent<Button>(); ColorBlock colors = ((Selectable)component).colors; ((ColorBlock)(ref colors)).normalColor = Color.white; ((ColorBlock)(ref colors)).highlightedColor = new Color(1.18f, 1.18f, 1.18f); ((ColorBlock)(ref colors)).selectedColor = Color.white; ((ColorBlock)(ref colors)).pressedColor = new Color(0.82f, 0.82f, 0.82f); ((ColorBlock)(ref colors)).fadeDuration = 0.12f; ((Selectable)component).colors = colors; Frame(val.transform, "Row border", 386f, 58f, RowBorder); ((Component)val.GetComponentInChildren<Text>()).gameObject.SetActive(false); Image val2 = Surface(val.transform, "Icon backing", -156f, 0f, 48f, 48f, new Color(0.025f, 0.03f, 0.04f)); Sprite val3 = EnemyIcon(item.Prefab); if (Object.op_Implicit((Object)(object)val3)) { Image obj2 = Surface(((Component)val2).transform, "Trophy icon", 0f, 0f, 44f, 44f, Color.white); obj2.sprite = val3; obj2.preserveAspect = true; } else { Silhouette(((Component)val2).transform, 0f, 0f, 36f); } Text obj3 = ChildLabel(val.transform, SelectedHeading(item), 22f, 9f, 252f, 35f, 18, new Color(0.98f, 0.94f, 0.84f)); obj3.resizeTextForBestFit = true; obj3.resizeTextMinSize = 15; obj3.resizeTextMaxSize = 18; ChildLabel(val.transform, ArenaRules.Biomes[item.Tier] + (item.Aquatic ? " • Water" : ""), 22f, -19f, 252f, 18f, 13, Muted).font = GUIManager.Instance.AveriaSerif; Surface(val.transform, "Selection marker", -191f, 0f, 4f, 56f, Gold); ((UnityEvent)val.GetComponent<Button>().onClick).AddListener((UnityAction)delegate { selected = captured.Prefab; RefreshDetails(); }); rows.Add(val); rowPrefabs[val] = item.Prefab; num++; } if (num == 0) { Text val4 = ChildLabel(content.transform, "No enemies match your filters.", 0f, -55f, 345f, 60f, 18, Muted); RectTransform rectTransform = ((Graphic)val4).rectTransform; RectTransform rectTransform2 = ((Graphic)val4).rectTransform; Vector2 val5 = default(Vector2); ((Vector2)(ref val5))..ctor(0.5f, 1f); rectTransform2.anchorMax = val5; rectTransform.anchorMin = val5; val4.alignment = (TextAnchor)4; rows.Add(((Component)val4).gameObject); } content.GetComponent<RectTransform>().sizeDelta = new Vector2(0f, Math.Max(426f, num * 64 + 14)); if (Object.op_Implicit((Object)(object)enemyCount)) { enemyCount.text = list.Count + ((list.Count == snapshot.Rows.Count) ? " opponents" : " shown"); } if (Object.op_Implicit((Object)(object)enemyScroll)) { enemyScroll.StopMovement(); enemyScroll.verticalNormalizedPosition = 1f; } RefreshDetails(); } private Sprite? EnemyIcon(string prefab) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Invalid comparison between Unknown and I4 if (icons.TryGetValue(prefab, out Sprite value)) { return value; } GameObject prefab2 = PrefabManager.Instance.GetPrefab(prefab); CharacterDrop val = (Object.op_Implicit((Object)(object)prefab2) ? prefab2.GetComponent<CharacterDrop>() : null); Sprite val2 = null; if (Object.op_Implicit((Object)(object)val)) { foreach (Drop drop in val.m_drops) { ItemDrop val3 = (Object.op_Implicit((Object)(object)drop.m_prefab) ? drop.m_prefab.GetComponent<ItemDrop>() : null); if (Object.op_Implicit((Object)(object)val3) && (int)val3.m_itemData.m_shared.m_itemType == 13) { val2 = val3.m_itemData.GetIcon(); if (Object.op_Implicit((Object)(object)val2)) { break; } } } } icons[prefab] = val2; return val2; } private static bool EnemyDropsCoins(string prefabName) { GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab(prefabName) : null); CharacterDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<CharacterDrop>() : null); if (Object.op_Implicit((Object)(object)val2)) { return val2.m_drops.Any((Drop drop) => Object.op_Implicit((Object)(object)drop.m_prefab) && StringExtensionMethods.GetStableHashCode(((Object)drop.m_prefab).name) == Data.CoinPrefabHash); } return false; } private void RefreshDetails() { //IL_016e: 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_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_05bd: Unknown result type (might be due to invalid IL or missing references) //IL_05a7: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)panel)) { return; } MenuRow menuRow = snapshot?.Rows.FirstOrDefault((MenuRow r) => r.Prefab == selected); if (Object.op_Implicit((Object)(object)selectedText)) { selectedText.text = ((menuRow == null) ? "Select an enemy" : SelectedHeading(menuRow)); } if (Object.op_Implicit((Object)(object)selectedBiome)) { selectedBiome.text = ((menuRow == null) ? "Choose from the list" : (ArenaRules.Biomes[menuRow.Tier] + (menuRow.Aquatic ? " • Water arena" : ""))); } if (Object.op_Implicit((Object)(object)selectedIcon)) { selectedIcon.sprite = ((menuRow == null) ? null : EnemyIcon(menuRow.Prefab)); ((Behaviour)selectedIcon).enabled = (Object)(object)selectedIcon.sprite != (Object)null; } if (Object.op_Implicit((Object)(object)selectedFallback)) { selectedFallback.SetActive(!Object.op_Implicit((Object)(object)selectedIcon) || !Object.op_Implicit((Object)(object)selectedIcon.sprite)); } foreach (GameObject row in rows) { if (rowPrefabs.TryGetValue(row, out string value)) { bool flag = value == selected; ((Graphic)row.GetComponent<Image>()).color = (flag ? RowSelected : RowNormal); string[] frameEdges = FrameEdges; foreach (string text in frameEdges) { ((Graphic)((Component)row.transform.Find("Row border " + text)).GetComponent<Image>()).color = (flag ? Gold : RowBorder); } ((Component)row.transform.Find("Selection marker")).gameObject.SetActive(flag); } } for (int num2 = 0; num2 < starButtons.Count; num2++) { StyleChoice(starButtons[num2], stars == num2, num2 + ((num2 == 1) ? " star" : " stars")); } if (Object.op_Implicit((Object)(object)strengthText)) { strengthText.text = DifficultyRules.Strength(strengthTenths).ToString("0.0", CultureInfo.InvariantCulture) + "x"; } if (Object.op_Implicit((Object)(object)weakerButton)) { ((Selectable)weakerButton).interactable = strengthTenths > 10; } if (Object.op_Implicit((Object)(object)strongerButton)) { ((Selectable)strongerButton).interactable = strengthTenths < 30; } if (Object.op_Implicit((Object)(object)practiceButton)) { StyleChoice(practiceButton, !loot, "Practice"); } if (Object.op_Implicit((Object)(object)rewardsButton)) { StyleChoice(rewardsButton, loot, "Loot rewards"); } int num3 = menuRow?.Cost(stars, loot) ?? 0; if (Object.op_Implicit((Object)(object)quoteText)) { quoteText.text = ((menuRow == null) ? "" : ((num3 == 0) ? "FREE" : (num3 + " tokens"))); } if (Object.op_Implicit((Object)(object)detailText)) { detailText.text = ((menuRow == null) ? "" : (((!loot) ? "No item drops or trophies." : (DifficultyRules.LootPercent(strengthTenths) + "% native loot • " + ((snapshot.LatestTier == menuRow.Tier) ? "Full price" : (Math.Min(100m, (decimal)Math.Max(0, snapshot.LatestTier - menuRow.Tier) * (decimal)snapshot.DiscountPerTier * 100m).ToString("0.##", CultureInfo.InvariantCulture) + "% discount")) + "\n" + ((snapshot.CoinLimitEnabled && EnemyDropsCoins(menuRow.Prefab)) ? ("Coins: " + snapshot.CoinAvailable + "/" + snapshot.CoinCapacity + " shared • +" + snapshot.CoinsPerHour.ToString("0.#") + "/hour") : "Item drops and trophies enabled."))) + (menuRow.Aquatic ? "\nRequires suitable water." : ""))); } if (!Object.op_Implicit((Object)(object)summonButton)) { return; } ((Selectable)summonButton).interactable = menuRow != null && snapshot != null && snapshot.Phase == 0 && !commandPending && snapshot.Units >= (long)num3 * 1000000L; ((Component)((Component)summonButton).transform.Find("Action highlight")).gameObject.SetActive(((Selectable)summonButton).interactable); ((Graphic)((Component)summonButton).GetComponentInChildren<Text>()).color = (Color)(((Selectable)summonButton).interactable ? new Color(1f, 0.94f, 0.78f) : Muted); Text componentInChildren = ((Component)summonButton).GetComponentInChildren<Text>(); object text2; if (!commandPending) { MenuSnapshot? menuSnapshot = snapshot; if (menuSnapshot == null || menuSnapshot.Phase != 1) { MenuSnapshot? menuSnapshot2 = snapshot; text2 = ((menuSnapshot2 != null && menuSnapshot2.Phase == 2) ? "Encounter active" : "Summon enemy"); } else { text2 = "Counting down…"; } } else { text2 = "Requesting…"; } componentInChildren.text = (string)text2; } private void ChangeStrength(int direction) { strengthTenths = Math.Max(10, Math.Min(30, strengthTenths + direction)); RefreshDetails(); } private void Summon() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (snapshot != null && !commandPending && snapshot.Rows.Any((MenuRow row) => row.Prefab == selected)) { commandPending = true; commandStarted = Time.unscaledTime; commandSerial = serial + 1; Send(1, target); RefreshDetails(); } } private void Send(int operation, ZDOID piece) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(2); val.Write(piece); val.Write(++serial); val.Write(operation); val.Write((operation == 1) ? selected : ""); val.Write(stars); val.Write(loot); val.Write(strengthTenths); ZRoutedRpc.instance.InvokeRoutedRPC("ArenaCombat.Request.v1", new object[1] { val }); } } private void Feedback(string text) { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Character)Player.m_localPlayer).Message((MessageType)1, text, 0, (Sprite)null, false); } } private static string Localized(string text) { if (Localization.instance == null) { return text; } return Localization.instance.Localize(text); } private static string SelectedHeading(MenuRow row) { string text = Localized(row.Name); string text2 = " — " + ArenaRules.Biomes[row.Tier]; if (!text.EndsWith(text2, StringComparison.Ordinal)) { return text; } return text.Substring(0, text.Length - text2.Length); } private Text Label(string text, float x, float y, float width, float height, int size) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0039: Unknown result type (might be due to invalid IL or missing references) Text component = GUIManager.Instance.CreateText(text, panel.transform, Center, Center, new Vector2(x, y), GUIManager.Instance.AveriaSerifBold, size, GUIManager.Instance.ValheimBeige, true, Color.black, width, height, false).GetComponent<Text>(); component.alignment = (TextAnchor)4; component.horizontalOverflow = (HorizontalWrapMode)0; component.verticalOverflow = (VerticalWrapMode)0; ((Graphic)component).raycastTarget = false; return component; } private Button MakeButton(string text, float x, float y, float width, float height, Action click) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown Button component = GUIManager.Instance.CreateButton(text, panel.transform, Center, Center, new Vector2(x, y), width, height).GetComponent<Button>(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { click(); }); return component; } private static void AddButtonHighlight(Button button, string name) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_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_0048: Unknown result type (might be due to invalid IL or missing references) RectTransform component = ((Component)button).GetComponent<RectTransform>(); Transform transform = ((Component)button).transform; Rect rect = component.rect; float width = ((Rect)(ref rect)).width; rect = component.rect; Image obj = Surface(transform, name, 0f, 0f, width, ((Rect)(ref rect)).height, new Color(1f, 0.82f, 0.44f, 0.85f)); obj.sprite = GUIManager.Instance.GetSprite("button_highlight"); obj.type = (Type)1; ((Component)obj).transform.SetAsFirstSibling(); ((Component)obj).gameObject.SetActive(false); } private static void StyleChoice(Button button, bool selected, string text) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_00cf: Unknown result type (might be due to invalid IL or missing references) ColorBlock colors = ((Selectable)button).colors; ((ColorBlock)(ref colors)).normalColor = (selected ? new Color(1.15f, 1.02f, 0.75f) : new Color(0.7f, 0.73f, 0.76f)); ((ColorBlock)(ref colors)).selectedColor = ((ColorBlock)(ref colors)).normalColor; ((ColorBlock)(ref colors)).highlightedColor = (Color)(selected ? new Color(1.35f, 1.18f, 0.85f) : Color.white); ((ColorBlock)(ref colors)).pressedColor = new Color(0.65f, 0.65f, 0.65f); ((Selectable)button).colors = colors; ((Component)((Component)button).transform.Find("Choice highlight")).gameObject.SetActive(selected); Text componentInChildren = ((Component)button).GetComponentInChildren<Text>(); componentInChildren.text = (selected ? "✓ " : "") + text; ((Graphic)componentInChildren).color = (Color)(selected ? new Color(1f, 0.9f, 0.65f) : Muted); } private static GameObject Silhouette(Transform parent, float x, float y, float size) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_0098: Expected O, but got Unknown GameObject val = new GameObject("Creature silhouette", new Type[2] { typeof(RectTransform), typeof(CreatureSilhouette) }) { layer = 5 }; val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); Vector2 anchorMin = (component.anchorMax = Center); component.anchorMin = anchorMin; component.anchoredPosition = new Vector2(x, y); component.sizeDelta = new Vector2(size, size); CreatureSilhouette component2 = val.GetComponent<CreatureSilhouette>(); ((Graphic)component2).color = new Color(0.62f, 0.66f, 0.69f); ((Graphic)component2).raycastTarget = false; return val; } private Text ChildLabel(Transform parent, string text, float x, float y, float width, float height, int size, Color color) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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) Text component = GUIManager.Instance.CreateText(text, parent, Center, Center, new Vector2(x, y), GUIManager.Instance.AveriaSerifBold, size, color, true, Color.black, width, height, false).GetComponent<Text>(); component.alignment = (TextAnchor)3; component.horizontalOverflow = (HorizontalWrapMode)0; component.verticalOverflow = (VerticalWrapMode)0; ((Graphic)component).raycastTarget = false; return component; } private static Image Surface(Transform parent, string name, float x, float y, float width, float height, Color color) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(Image) }) { layer = 5 }; val.transform.SetParent(parent, false); Image component = val.GetComponent<Image>(); ((Graphic)component).color = color; ((Graphic)component).raycastTarget = false; RectTransform rectTransform = ((Graphic)component).rectTransform; Vector2 anchorMin = (rectTransform.anchorMax = Center); rectTransform.anchorMin = anchorMin; rectTransform.sizeDelta = new Vector2(width, height); rectTransform.anchoredPosition = new Vector2(x, y); return component; } private static void Frame(Transform parent, string name, float width, float height, Color color) { //IL_0024: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) Surface(parent, name + " Top", 0f, (height - 1f) / 2f, width, 1f, color); Surface(parent, name + " Bottom", 0f, (0f - (height - 1f)) / 2f, width, 1f, color); Surface(parent, name + " Left", (0f - (width - 1f)) / 2f, 0f, 1f, height, color); Surface(parent, name + " Right", (width - 1f) / 2f, 0f, 1f, height, color); } private static void Divider(Transform parent, string name, float x, float y, float width, bool ornament) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) Surface(parent, name, x, y, width, 1f, new Color(Gold.r, Gold.g, Gold.b, 0.65f)); if (ornament) { ((Transform)((Graphic)Surface(parent, name + " Diamond", x, y, 6f, 6f, Gold)).rectTransform).localRotation = Quaternion.Euler(0f, 0f, 45f); } } private void CreateScrollArea() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Expected O, but got Unknown //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) Image val = Surface(((Component)Surface(panel.transform, "Enemy list border", -220f, -51.5f, 430f, 527f, new Color(0.64f, 0.48f, 0.26f, 0.75f))).transform, "Enemy list inset", 0f, 0f, 426f, 523f, new Color(0.025f, 0.03f, 0.04f)); Surface(((Component)val).transform, "List heading", 0f, 243.5f, 422f, 36f, new Color(0.11f, 0.13f, 0.15f)); ChildLabel(((Component)val).transform, "CHOOSE OPPONENT", -91f, 243.5f, 220f, 24f, 14, Gold); enemyCount = ChildLabel(((Component)val).transform, "", 141f, 243.5f, 116f, 24f, 13, Muted); enemyCount.alignment = (TextAnchor)5; Divider(((Component)val).transform, "List heading divider", 0f, 225.5f, 410f, ornament: false); enemyScroll = ((Component)val).gameObject.AddComponent<ScrollRect>(); Image val2 = Surface(((Component)val).transform, "Viewport", -10f, -36.5f, 398f, 426f, Color.white); ((Graphic)val2).raycastTarget = true; ((Component)val2).gameObject.AddComponent<Mask>().showMaskGraphic = false; content = new GameObject("Enemies", new Type[1] { typeof(RectTransform) }); content.layer = 5; content.transform.SetParent(((Component)val2).transform, false); RectTransform component = content.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = Vector2.zero; Image obj = Surface(((Component)val).transform, "Scrollbar track", 201f, -36.5f, 12f, 422f, new Color(0f, 0f, 0f, 0.65f)); ((Graphic)obj).raycastTarget = true; Scrollbar val3 = ((Component)obj).gameObject.AddComponent<Scrollbar>(); Image val4 = Surface(((Component)obj).transform, "Scrollbar handle", 0f, 0f, 0f, 0f, Gold); ((Graphic)val4).raycastTarget = true; ((Graphic)val4).rectTransform.anchorMin = Vector2.zero; ((Graphic)val4).rectTransform.anchorMax = Vector2.one; ((Graphic)val4).rectTransform.offsetMin = new Vector2(2f, 2f); ((Graphic)val4).rectTransform.offsetMax = new Vector2(-2f, -2f); val3.handleRect = ((Graphic)val4).rectTransform; ((Selectable)val3).targetGraphic = (Graphic)(object)val4; val3.direction = (Direction)2; ColorBlock colors = ((Selectable)val3).colors; ((ColorBlock)(ref colors)).normalColor = Color.white; ((ColorBlock)(ref colors)).highlightedColor = new Color(1.15f, 1.15f, 1.15f); ((ColorBlock)(ref colors)).pressedColor = new Color(0.8f, 0.8f, 0.8f); ((Selectable)val3).colors = colors; enemyScroll.viewport = ((Graphic)val2).rectTransform; enemyScroll.content = component; enemyScroll.horizontal = false; enemyScroll.vertical = true; enemyScroll.movementType = (MovementType)2; enemyScroll.scrollSensitivity = 320f; enemyScroll.verticalScrollbar = val3; enemyScroll.verticalScrollbarVisibility = (ScrollbarVisibility)0; } } internal sealed class ArenaServer { internal const string RequestRpc = "ArenaCombat.Request.v1"; internal const string ReplyRpc = "ArenaCombat.Reply.v1"; internal const string DefeatRpc = "ArenaCombat.PlayerDefeated.v1"; private readonly Plugin plugin; private ZRoutedRpc? boundRpc; private ZDOMan? boundWorld; private Catalogue? catalogue; private string catalogueSettings = ""; private readonly Dictionary<string, ZDOID> controllers = new Dictionary<string, ZDOID>(StringComparer.Ordinal); private readonly Dictionary<ZDOID, ZDOID> controllersByPiece = new Dictionary<ZDOID, ZDOID>(); private readonly HashSet<ZDOID> creatures = new HashSet<ZDOID>(); private readonly DeathPresenceTracker<ZDOID> deaths = new DeathPresenceTracker<ZDOID>(); private readonly Dictionary<long, float> requestTimes = new Dictionary<long, float>(); private float nextScan; private float nextTick; private float nextPresenceTick; private bool loaded; private static readonly FieldInfo WorldObjects = AccessTools.Field(typeof(ZDOMan), "m_objectsByID"); private readonly Dictionary<ZDOID, PresenceGrace> presence = new Dictionary<ZDOID, PresenceGrace>(); internal const string CoinPayoutRpc = "ArenaCombat.CoinPayout.v1"; private readonly Dictionary<ZDOID, CoinSource> coinSources = new Dictionary<ZDOID, CoinSource>(); private ZDOID coinBankId = ZDOID.None; private CoinAllowance? coinAllowance; private Settings Settings => plugin.Settings; internal ArenaServer(Plugin plugin) { //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) this.plugin = plugin; } internal void Update() { if (ZRoutedRpc.instance != null && boundRpc != ZRoutedRpc.instance) { boundRpc = ZRoutedRpc.instance; boundRpc.Register<ZPackage>("ArenaCombat.Request.v1", (Action<long, ZPackage>)Request); boundRpc.Register<ZPackage>("ArenaCombat.Reply.v1", (Action<long, ZPackage>)Reply); boundRpc.Register<ZPackage>("ArenaCombat.CoinPayout.v1", (Action<long, ZPackage>)CoinPayout); boundRpc.Register<ZPackage>("ArenaCombat.PlayerDefeated.v1", (Action<long, ZPackage>)PlayerDefeated); controllers.Clear(); controllersByPiece.Clear(); creatures.Clear(); requestTimes.Clear(); boundWorld = null; catalogue = null; loaded = false; presence.Clear(); deaths.Clear(); ResetCoinWorld(); } if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || !Object.op_Implicit((Object)(object)ZNetScene.instance) || ZDOMan.instance == null || !Object.op_Implicit((Object)(object)ZoneSystem.instance)) { return; } if (boundWorld != ZDOMan.instance) { boundWorld = ZDOMan.instance; loaded = false; catalogue = null; controllers.Clear(); controllersByPiece.Clear(); creatures.Clear(); presence.Clear(); deaths.Clear(); ResetCoinWorld(); nextScan = (nextTick = (nextPresenceTick = 0f)); } try { if (Time.unscaledTime >= nextScan) { nextScan = Time.unscaledTime + 5f; Scan(); } if (loaded && Time.unscaledTime >= nextTick) { nextTick = Time.unscaledTime + 0.1f; bool flag = Time.unscaledTime >= nextPresenceTick; if (flag) { nextPresenceTick = Time.unscaledTime + 1f; } Tick(flag); } } catch (Exception error) { plugin.Error(error); } } private void Scan() { //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Invalid comparison between Unknown and I4 string text = Settings.TierOverrides.Value + "|" + Settings.ExcludedEnemies.Value; if (catalogue == null || text != catalogueSettings) { catalogue = new Catalogue(Settings); catalogueSettings = text; } ZDO[] array = ((Dictionary<ZDOID, ZDO>)WorldObjects.GetValue(ZDOMan.instance)).Values.ToArray(); ZDO[] array2 = array; foreach (ZDO val in array2) { if (val.IsValid() && (Data.IsController(val) || Data.IsEnemy(val))) { Observe(val); } } array2 = array; foreach (ZDO val2 in array2) { if (val2.IsValid() && Data.IsActivator(val2)) { EnsureController(val2); } } EnsureCoinBank(); if (loaded) { return; } foreach (ZDO item in CurrentControllers()) { EncounterState val3 = Data.Read(item); if ((int)val3.Phase == 1) { val3.Cancel(Settings.Capacity.Value); Data.Write(item, val3); item.Set("arena.remaining", 0); } } loaded = true; } internal void Observe(ZDO zdo) { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || !zdo.IsValid()) { return; } if (Data.IsController(zdo)) { string text = zdo.GetString("arena.key", ""); if (!(text == "")) { ZDOID key = Data.PieceId(zdo); if (controllersByPiece.TryGetValue(key, out var value) && value != zdo.m_uid && ZDOMan.instance.GetZDO(value) != null) { SilentDestroy(zdo); return; } controllers[text] = zdo.m_uid; controllersByPiece[key] = zdo.m_uid; } } else if (Data.IsEnemy(zdo)) { creatures.Add(zdo.m_uid); CacheCoinSource(zdo); } } private IEnumerable<ZDO> CurrentControllers() { ZDOID[] array = controllers.Values.ToArray(); foreach (ZDOID val in array) { ZDO zDO = ZDOMan.instance.GetZDO(val); if (zDO != null && zDO.IsValid()) { yield return zDO; } } } private ZDO? EnsureController(ZDO piece) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown if (controllersByPiece.TryGetValue(piece.m_uid, out var value)) { ZDO zDO = ZDOMan.instance.GetZDO(value); if (zDO != null) { return zDO; } controllersByPiece.Remove(piece.m_uid); } if (Settings.AdminBuildOnly.Value && !IsAuthorizedBuilder(piece)) { plugin.Warn("Removed an unauthorized Arena Coordinator: its original builder is not recognized as a server admin."); SilentDestroy(piece); return null; } if (Settings.MaximumActivators.Value > 0 && controllersByPiece.Count >= Settings.MaximumActivators.Value) { plugin.Warn("Removed an over-limit Arena Coordinator: the world placement limit has been reached."); SilentDestroy(piece); return null; } ZDO val = ZDOMan.instance.CreateNewZDO(piece.GetPosition(), StringExtensionMethods.GetStableHashCode("ArenaCombat_Reserve")); val.SetPrefab(StringExtensionMethods.GetStableHashCode("ArenaCombat_Reserve")); val.Persistent = true; val.Type = (ObjectType)2; val.SetRotation(piece.GetRotation()); val.SetConnection((ConnectionType)3, piece.m_uid); val.Set("arena.key", Guid.NewGuid().ToString("N")); Data.Write(val, new EncounterState(new ReserveBank(0L, Data.Now, 0), (EncounterPhase)0, 0L)); Observe(val); return val; } private unsafe bool IsAuthorizedBuilder(ZDO piece) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) long creator = piece.GetLong(ZDOVars.s_creator, 0L); if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && ZNet.instance.IsServer() && creator != 0L && creator == Player.m_localPlayer.GetPlayerID()) { return true; } ZNetPeer val = (ZNetPeer)((creator != 0L) ? ((object)((IEnumerable<ZNetPeer>)ZNet.instance.GetPeers()).FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer peer) => peer.IsReady() && peer.m_playerID == creator))) : ((object)ZNet.instance.GetPeer(((ZDOID)(ref piece.m_uid)).UserID))); if (val != null) { return IsAdmin(val.m_uid); } int num = piece.GetInt(ZDOVars.s_creatorIndex, -1); if (num >= 0 && ZNet.World != null && num < ZNet.World.m_playerHistory.Count) { PlatformUserID id = ZNet.World.m_playerHistory[num].m_id; if (((PlatformUserID)(ref id)).IsValid) { return ZNet.instance.IsAdmin(((object)(*(PlatformUserID*)(&id))/*cast due to .constrained prefix*/).ToString()); } } if (creator == 0L) { return ((ZDOID)(ref piece.m_uid)).UserID == ZDOMan.GetSessionID(); } return false; } private bool IsAdmin(long peerId) { if (peerId == ZDOMan.GetSessionID()) { return true; } ZNetPeer peer = ZNet.instance.GetPeer(peerId); if (peer != null) { return ZNet.instance.IsAdmin(peer.m_socket.GetHostName()); } return false; } private ZDOID CharacterForPeer(long sender) { //IL_000d: 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_0031: Unknown result type (might be due to invalid IL or missing references) if (sender == ZDOMan.GetSessionID()) { return ZNet.instance.LocalPlayerCharacterID; } ZNetPeer peer = ZNet.instance.GetPeer(sender); if (peer == null || !peer.IsReady()) { return ZDOID.None; } return peer.m_characterID; } private ZDO? PlayerForPeer(long sender) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = ZDOMan.instance.GetZDO(CharacterForPeer(sender)); if (zDO == null || !(zDO.GetFloat(ZDOVars.s_health, 100f) > 0f) || zDO.GetBool(ZDOVars.s_dead, false)) { return null; } return zDO; } internal void ReportPlayerDeath(ZDOID victim, ZDOID attacker, SpawnTag tag) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(victim); val.Write(attacker); val.Write(tag.Home); val.Write(tag.Encounter); ZRoutedRpc.instance.InvokeRoutedRPC("ArenaCombat.PlayerDefeated.v1", new object[1] { val }); } } private List<ZDO> LivingPlayers() { long now = Data.Now; deaths.Prune(now); return (from player in ZNet.instance.GetAllCharacterZDOS() where deaths.IsAlive(player.m_uid, player.GetFloat(ZDOVars.s_health, 100f) > 0f && !player.GetBool(ZDOVars.s_dead, false), now) select player).ToList(); } private void PlayerDefeated(long sender, ZPackage p) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || ZDOMan.instance == null || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return; } try { ZDOID val = p.ReadZDOID(); ZDOID val2 = p.ReadZDOID(); string text = p.ReadString(); string text2 = p.ReadString(); if (text.Length == 0 || text.Length > 80 || text2.Length == 0 || text2.Length > 80 || ((ZDOID)(ref val)).IsNone() || val != CharacterForPeer(sender)) { return; } ZDO zDO = ZDOMan.instance.GetZDO(val); ZDO attacker = ZDOMan.instance.GetZDO(val2); if (zDO == null || !zDO.IsValid() || zDO.GetOwner() != sender || !Data.IsEnemy(attacker) || attacker.GetBool("arena.suppress", false) || attacker.GetString("arena.home", "") != text || attacker.GetString("arena.encounter", "") != text2) { return; } if (!loaded) { Scan(); } ZDOID value; ZDO val3 = (controllers.TryGetValue(text, out value) ? ZDOMan.instance.GetZDO(value) : null); if (val3 != null && !val3.GetBool("arena.suppress", false) && val3.GetInt("arena.phase", 0) == 2 && !(val3.GetString("arena.encounter", "") != text2)) { deaths.Report(val, Data.Now); if (!LivingPlayers().Any((ZDO player) => Vector3.Distance(player.GetPosition(), attacker.GetPosition()) <= Settings.DefeatRadius.Value)) { FinishDefeatedEncounter(val3, text, text2); } } } catch (Exception error) { plugin.Error(error); } } private void FinishDefeatedEncounter(ZDO controller, string home, string encounter) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) controller.SetOwner(ZDOMan.GetSessionID()); EncounterState val = Data.Read(controller); val.Finish(); Data.Write(controller, val); controller.Set("arena.remaining", 0); controller.Set("arena.empty", 0L); controller.Set("arena.pending", ""); ZDO[] array = ((Dictionary<ZDOID, ZDO>)WorldObjects.GetValue(ZDOMan.instance)).Values.Where((ZDO z) => z.IsValid() && Data.IsEnemy(z) && z.GetString("arena.home", "") == home && z.GetString("arena.encounter", "") == encounter).ToArray(); foreach (ZDO val2 in array) { SilentDestroy(val2); presence.Remove(val2.m_uid); creatures.Remove(val2.m_uid); } plugin.LogInfo("Arena encounter ended after player defeat: no surviving player in range."); } private void Request(long sender, ZPackage p) { //IL_03e4: 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) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_010d: 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_0153: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || ZDOMan.instance == null || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return; } ZDOID val = ZDOID.None; int serial = 0; try { if (p.ReadInt() != 2) { return; } val = p.ReadZDOID(); serial = p.ReadInt(); int num = p.ReadInt(); string text = p.ReadString(); int num2 = p.ReadInt(); bool flag = p.ReadBool(); int num3 = p.ReadInt(); if (text.Length > 160 || (num != 0 && num != 1 && num != 2)) { return; } long key = sender ^ ((num == 1) ? long.MinValue : 0); if (requestTimes.TryGetValue(key, out var value) && Time.unscaledTime - value < 0.2f) { return; } requestTimes[key] = Time.unscaledTime; if (num == 2) { if (sender == ZDOMan.GetSessionID() || ZNet.instance.GetPeer(sender) != null) { if (!loaded) { Scan(); } Respond(sender, ZDOID.None, serial, null, ""); } return; } ZDO val2 = PlayerForPeer(sender); ZDO zDO = ZDOMan.instance.GetZDO(val); if (val2 == null || zDO == null || !Data.IsActivator(zDO) || Vector3.Distance(val2.GetPosition(), zDO.GetPosition()) > Settings.InteractDistance.Value) { Respond(sender, val, serial, null, "Move closer to the Arena Coordinator."); return; } if (!loaded) { Scan(); } ZDO val3 = EnsureController(zDO); if (val3 == null) { Respond(sender, val, serial, null, "Arena Coordinator unavailable."); return; } if (val3.GetLong("arena.hiddenUntil", 0L) > Data.WorldNow) { Respond(sender, val, serial, val3, "Arena Coordinator is briefly inactive after spawning."); return; } EncounterState val4 = Data.Read(val3); val4.Bank.Refill(Data.Now, Settings.Capacity.Value, (decimal)Settings.Regeneration.Value); string message = ""; if (num == 1) { int num4 = ArenaRules.LatestTier((Func<string, bool>)ZoneSystem.instance.GetGlobalKey); if (!DifficultyRules.IsValid(num3) || num2 < 0 || num2 > 2 || !catalogue.Enemies.TryGetValue(text, out EnemyDefinition value2) || value2.Tier > num4 || value2.Template.GetComponent<Character>().m_boss) { message = "That enemy, star level, or strength is unavailable."; } else { int num5 = ArenaRules.Cost(Settings.BaseCost(num2), Settings.LootCost.Value, flag, num4, value2.Tier, (decimal)Settings.Discount.Value); if ((int)val4.Phase != 0) { message = "This Arena Coordinator already has an encounter."; } else if (!val4.TryBegin(num5, Data.Now, Settings.Countdown.Value)) { message = "Not enough reserve tokens."; } else { val3.Set("arena.pending", text); val3.Set("arena.stars", num2); val3.Set("arena.strengthTenths", num3); val3.Set("arena.lootPercent", DifficultyRules.LootPercent(num3)); val3.Set("arena.loot", flag); val3.Set("arena.encounter", Guid.NewGuid().ToString("N")); val3.Set("arena.remaining", Settings.Countdown.Value); val3.Set("arena.empty", 0L); message = "Summon reserved. Prepare for battle!"; } } } Data.Write(val3, val4); Respond(sender, val, serial, val3, message); } catch (Exception error) { plugin.Error(error); if (!((ZDOID)(ref val)).IsNone()) { Respond(sender, val, serial, null, "The summon could not be processed."); } } } private void Respond(long sender, ZDOID piece, int serial, ZDO? controller, string message) { //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) RefillCoinBank(); MenuSnapshot s = new MenuSnapshot { Piece = piece, Request = serial, LatestTier = ArenaRules.LatestTier((Func<string, bool>)ZoneSystem.instance.GetGlobalKey), Capacity = Settings.Capacity.Value, Regeneration = Settings.Regeneration.Value, DiscountPerTier = Settings.Discount.Value, CoinLimitEnabled = Settings.CoinLimitEnabled.Value, CoinAvailable = coinAllowance.Available, CoinCapacity = Settings.CoinCapacity.Value, CoinsPerHour = Settings.CoinsPerHour.Value, Radius = Settings.Radius.Value, InteractionDistance = Settings.InteractDistance.Value, Grace = Settings.Grace.Value, AdminBuildOnly = Settings.AdminBuildOnly.Value, Invulnerable = Settings.Invulnerable.Value, BuilderIsAdmin = IsAdmin(sender), Count = controllersByPiece.Count, Maximum = Settings.MaximumActivators.Value, Message = message }; if (controller != null) { s.Units = controller.GetLong("arena.units", 0L); s.Phase = controller.GetInt("arena.phase", 0); s.Remaining = controller.GetInt("arena.remaining", 0); s.CurrentEnemy = controller.GetString("arena.pending", ""); foreach (EnemyDefinition item in (from e in catalogue.Enemies.Values where e.Tier <= s.LatestTier orderby e.Tier descending select e).ThenBy<EnemyDefinition, string>((EnemyDefinition e) => e.Name, StringComparer.Ordinal)) { MenuRow menuRow = new MenuRow { Prefab = item.Prefab, Name = item.Name, Tier = item.Tier, Aquatic = item.Aquatic }; for (int num = 0; num <= 2; num++) { for (int num2 = 0; num2 <= 1; num2++) { menuRow.Costs[num * 2 + num2] = ArenaRules.Cost(Settings.BaseCost(num), Settings.LootCost.Value, num2 == 1, s.LatestTier, item.Tier, (decimal)Settings.Discount.Value); } } s.Rows.Add(menuRow); } } boundRpc.InvokeRoutedRPC(sender, "ArenaCombat.Reply.v1", new object[1] { s.Pack() }); } private void Reply(long sender, ZPackage p) { if (!Object.op_Implicit((Object)(object)ZNet.instance) || boundRpc == null) { return; } long num = (ZNet.instance.IsServer() ? ZDOMan.GetSessionID() : (from peer in ZNet.instance.GetPeers() where peer.m_server select peer.m_uid).FirstOrDefault()); if (sender != num || num == 0L) { return; } try { plugin.Menu.Receive(MenuSnapshot.Unpack(p)); } catch (Exception error) { plugin.Error(error); } } private void Tick(bool checkPresence) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Invalid comparison between Unknown and I4 //IL_0591: Unknown result type (might be due to invalid IL or missing references) //IL_0596: Unknown result type (might be due to invalid IL or missing references) //IL_059e: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Invalid comparison between Unknown and I4 //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_015e: 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) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Expected O, but got Unknown //IL_01e4: Expected O, but got Unknown //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) long now = Data.Now; List<ZDO> source = LivingPlayers(); Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal); ZDOID[] array = (checkPresence ? creatures.ToArray() : Array.Empty<ZDOID>()); foreach (ZDOID val in array) { ZDO enemy = ZDOMan.instance.GetZDO(val); if (enemy == null || !enemy.IsValid()) { creatures.Remove(val); continue; } string key = enemy.GetString("arena.home", ""); ZDOID value; ZDO val2 = (controllers.TryGetValue(key, out value) ? ZDOMan.instance.GetZDO(value) : null); bool num = val2 != null && !val2.GetBool("arena.suppress", false) && val2.GetInt("arena.phase", 0) == 2 && enemy.GetString("arena.encounter", "") == val2.GetString("arena.encounter", ""); ZDO val3 = ((val2 == null) ? null : ZDOMan.instance.GetZDO(Data.PieceId(val2))); if (!num || val3 == null || enemy.GetBool("arena.suppress", false)) { SilentDestroy(enemy); creatures.Remove(val); continue; } if (enemy.GetBool(ZDOVars.s_tamed, false)) { plugin.Warn("Removed an arena creature with an unexpected tamed flag."); SilentDestroy(enemy); presence.Remove(val); creatures.Remove(val); continue; } if (!presence.TryGetValue(val, out PresenceGrace value2)) { Dictionary<ZDOID, PresenceGrace> dictionary2 = presence; PresenceGrace val4 = new PresenceGrace(0L); value2 = val4; dictionary2[val] = val4; } if (value2.Check(source.Any((ZDO player) => Vector3.Distance(player.GetPosition(), enemy.GetPosition()) <= Settings.Radius.Value), now, Settings.Grace.Value)) { SilentDestroy(enemy); presence.Remove(val); creatures.Remove(val); } else { dictionary[key] = ((!dictionary.TryGetValue(key, out var value3)) ? 1 : (value3 + 1)); } } foreach (ZDO item in CurrentControllers()) { if (item.GetBool("arena.suppress", false)) { continue; } ZDO piece = ZDOMan.instance.GetZDO(Data.PieceId(item)); if (piece == null || !Data.IsActivator(piece)) { string key2 = item.GetString("arena.key", ""); SilentDestroy(item); controllers.Remove(key2); controllersByPiece.Remove(Data.PieceId(item)); continue; } item.SetOwner(ZDOMan.GetSessionID()); EncounterState val5 = Data.Read(item); if (checkPresence) { val5.Bank.Refill(now, Settings.Capacity.Value, (decimal)Settings.Regeneration.Value); } if ((int)val5.Phase == 1) { item.Set("arena.remaining", (int)Math.Max(0.0, Math.Ceiling((double)(val5.DeadlineMs - now) / 1000.0))); if (val5.CanSpawn(now)) { if (!source.Any((ZDO p) => Vector3.Distance(p.GetPosition(), piece.GetPosition()) <= Settings.Radius.Value)) { val5.Cancel(Settings.Capacity.Value); } else { ZDO val6 = null; try { string key3 = item.GetString("arena.pending", ""); int num2 = ArenaRules.LatestTier((Func<string, bool>)ZoneSystem.instance.GetGlobalKey); if (!catalogue.Enemies.TryGetValue(key3, out EnemyDefinition value4) || value4.Tier > num2) { throw new InvalidOperationException("Enemy no longer available."); } val6 = Spawn(piece, item, value4); val5.SpawnSucceeded(); long num3 = Data.WorldNow + 5000; item.Set("arena.hiddenUntil", num3); Activator.Conceal(piece.m_uid, num3); } catch (Exception error) { if (val6 != null) { SilentDestroy(val6); } val5.Cancel(Settings.Capacity.Value); plugin.Error(error); } } } } else if ((int)val5.Phase == 2 && checkPresence) { string key4 = item.GetString("arena.key", ""); if (dictionary.ContainsKey(key4)) { item.Set("arena.empty", 0L); } else { long num4 = item.GetLong("arena.empty", 0L); if (num4 == 0L || num4 > now) { item.Set("arena.empty", now); } else if (now - num4 >= 3000) { val5.Finish(); item.Set("arena.empty", 0L); } } } Data.Write(item, val5); } if (checkPresence) { PruneCoinSources(); } array = presence.Keys.Where((ZDOID id) => !creatures.Contains(id)).ToArray(); foreach (ZDOID key5 in array) { presence.Remove(key5); } } private ZDO Spawn(ZDO piece, ZDO controller, EnemyDefinition definition) { //IL_0001: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) Vector3 val = piece.GetPosition() + piece.GetRotation() * Settings.Offset; ZNetView component = definition.Template.GetComponent<ZNetView>(); ZDO val2 = ZDOMan.instance.CreateNewZDO(val, StringExtensionMethods.GetStableHashCode(definition.Prefab)); try { val2.SetPrefab(StringExtensionMethods.GetStableHashCode(definition.Prefab)); val2.Persistent = true; val2.Type = component.m_type; val2.Distant = component.m_distant; val2.SetRotation(piece.GetRotation()); int num = controller.GetInt("arena.stars", 0) + 1; val2.Set(ZDOVars.s_level, num, false); float num2 = definition.Template.GetComponent<Character>().GetMaxHealthBase() * (float)num * (float)DifficultyRules.Strength(Data.Strength(controller)); val2.Set(ZDOVars.s_maxHealth, num2); val2.Set(ZDOVars.s_despawnInDay, false); val2.Set(ZDOVars.s_eventCreature, false); if (definition.Dvergr) { val2.Set(ZDOVars.s_aggravated, true); val2.Set(ZDOVars.s_huntPlayer, true); } SpawnTag.FromController(controller).Apply(val2); Observe(val2); return val2; } catch { SilentDestroy(val2); throw; } } internal static void SilentDestroy(ZDO zdo) { if (ZDOMan.instance != null && zdo.IsValid()) { zdo.SetOwner(ZDOMan.GetSessionID()); zdo.Set("arena.suppress", true); if (Data.IsEnemy(zdo)) { Plugin.Instance?.Server.CacheCoinSource(zdo); } ZDOMan.instance.DestroyZDO(zdo); } } private void ResetCoinWorld() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) coinSources.Clear(); coinBankId = ZDOID.None; coinAllowance = null; } internal void CacheCoinSource(ZDO zdo) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsServer() && Data.IsEnemy(zdo)) { coinSources[zdo.m_uid] = new CoinSource(zdo); } } private void EnsureCoinBank() { //IL_0006: 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_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_019f: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = ZDOMan.instance.GetZDO(coinBankId); if (zDO != null && zDO.IsValid() && coinAllowance != null) { zDO.SetOwner(ZDOMan.GetSessionID()); return; } ZDO val = ((IEnumerable<ZDO>)((Dictionary<ZDOID, ZDO>)WorldObjects.GetValue(ZDOMan.instance)).Values).FirstOrDefault((Func<ZDO, bool>)((ZDO z) => z.IsValid() && Data.IsCoinBank(z))); long now = Data.Now; if (val == null) { val = ZDOMan.instance.CreateNewZDO(Vector3.zero, StringExtensionMethods.GetStableHashCode("ArenaCombat_CoinAllowance")); val.SetPrefab(StringExtensionMethods.GetStableHashCode("ArenaCombat_CoinAllowance")); val.Persistent = true; val.Type = (ObjectType)2; val.Set("arena.units", (long)Settings.CoinCapacity.Value * 1000000L); val.Set("arena.updated", now); } val.SetOwner(ZDOMan.GetSessionID()); Dictionary<string, CoinClaim> dictionary = new Dictionary<string, CoinClaim>(StringComparer.Ordinal); byte[] byteArray = val.GetByteArray("arena.coinClaims", (byte[])null); if (byteArray != null && byteArray.Length != 0) { ZPackage val2 = new ZPackage(byteArray); if (val2.ReadInt() != 1) { throw new InvalidOperationException("Unsupported saved coin allowance."); } int num = val2.ReadInt(); if (num < 0 || num > 65536) { throw new InvalidOperationException("Invalid coin receipt count."); } for (int num2 = 0; num2 < num; num2++) { string text = val2.ReadString(); int num3 = val2.ReadInt(); long num4 = val2.ReadLong(); if (text.Length > 160 || num3 < 0 || num3 > 10000) { throw new InvalidOperationException("Invalid coin receipt."); } dictionary[text] = new CoinClaim(num3, num4); } } coinBankId = val.m_uid; coinAllowance = new CoinAllowance(val.GetLong("arena.units", 0L), val.GetLong("arena.updated", now), val.GetLong("arena.coinRemainder", 0L), (IEnumerable<KeyValuePair<string, CoinClaim>>)dictionary); } private void RefillCoinBank() { EnsureCoinBank(); coinAllowance.Refill(Data.Now, Settings.CoinCapacity.Value, (decimal)Settings.CoinsPerHour.Value); WriteCoinBank(receipts: false); } private void WriteCoinBank(bool receipts) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = ZDOMan.instance.GetZDO(coinBankId); if (zDO == null || coinAllowance == null) { throw new InvalidOperationException("Coin allowance unavailable."); } zDO.SetOwner(ZDOMan.GetSessionID()); zDO.Set("arena.units", coinAllowance.Units); zDO.Set("arena.updated", coinAllowance.UpdatedAtMs); zDO.Set("arena.coinRemainder", coinAllowance.Remainder); if (!receipts) { return; } ZPackage val = new ZPackage(); val.Write(1); val.Write(coinAllowance.Claims.Count); foreach (KeyValuePair<string, CoinClaim> claim in coinAllowance.Claims) { val.Write(claim.Key); CoinClaim value = claim.Value; val.Write(((CoinClaim)(ref value)).Charged); value = claim.Value; val.Write(((CoinClaim)(ref value)).AtMs); } zDO.Set("arena.coinClaims", val.GetArray()); } internal void RequestCoinPayout(SpawnTag tag, int amount, Vector3 position, bool cheated) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) ZDOID source = tag.Source; if (!((ZDOID)(ref source)).IsNone() && ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(tag.Source); val.Write(tag.Home); val.Write(tag.Encounter); val.Write(amount); val.Write(position); val.Write(cheated); ZRoutedRpc.instance.InvokeRoutedRPC("ArenaCombat.CoinPayout.v1", new object[1] { val }); } } private unsafe void CoinPayout(long sender, ZPackage p) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: 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_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer() || ZDOMan.instance == null || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return; } try { ZDOID val = p.ReadZDOID(); string text = p.ReadString(); string text2 = p.ReadString(); int num = p.ReadInt(); Vector3 val2 = p.ReadVector3(); bool flag = p.ReadBool(); if (((ZDOID)(ref val)).IsNone() || text.Length == 0 || text.Length > 80 || text2.Length == 0 || text2.Length > 80 || num < 1 || num > 10000 || (sender != ZDOMan.GetSessionID() && ZNet.instance.GetPeer(sender) == null)) { return; } if (!loaded) { Scan(); } ZDO zDO = ZDOMan.instance.GetZDO(val); if (zDO != null && zDO.IsValid()) { CacheCoinSource(zDO); } if (!coinSources.TryGetValue(val, out CoinSource value) || value.Owner != sender || !value.Loot || value.Suppressed || value.Home != text || value.Encounter != text2 || Data.Now < value.SeenAt || Data.Now - value.SeenAt >= 120000) { return; } ZDOID value2; ZDO val3 = (controllers.TryGetValue(text, out value2) ? ZDOMan.instance.GetZDO(value2) : null); if (val3 == null || val3.GetBool("arena.suppress", false) || val3.GetString("arena.encounter", "") != text2) { return; } if (!Finite(val2) || Vector3.Distance(val2, value.Position) > 100f) { val2 = value.Position + Vector3.up; } EnsureCoinBank(); string text3 = ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString(); int num2 = coinAllowance.Claim(text3, num, Data.Now, Settings.CoinCapacity.Value, (decimal)Settings.CoinsPerHour.Value, Settings.CoinLimitEnabled.Value); try { if (num2 > 0) { SpawnCoins(num2, val2, sender, flag || value.Cheated); } } catch { coinAllowance.Undo(text3, Settings.CoinCapacity.Value); WriteCoinBank(receipts: true); throw; } WriteCoinBank(receipts: true); } catch (Exception error) { plugin.Error(error); } } private static bool Finite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!float.IsNaN(value.x) && !float.IsNaN(value.y) && !float.IsNaN(value.z) && !float.IsInfinity(value.x) && !float.IsInfinity(value.y)) { return !float.IsInfinity(value.z); } return false; } private static void SpawnCoins(int amount, Vector3 position, long owner, bool cheated) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = ZNetScene.instance.GetPrefab(Data.CoinPrefabHash); ItemDrop val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<ItemDrop>() : null); if (!Object.op_Implicit((Object)(object)val)) { throw new InvalidOperationException("Native Coins prefab unavailable."); } ZNetView component = prefab.GetComponent<ZNetView>(); List<ZDO> list = new List<ZDO>(); try { int num = amount; while (num > 0) { ItemData val2 = val.m_itemData.Clone(); val2.m_dropPrefab = prefab; val2.m_stack = Math.Min(num, Math.Max(1, val2.m_shared.m_maxStackSize)); val2.m_worldLevel = (byte)Game.m_worldLevel; val2.m_cheated = cheated; ZDO val3 = ZDOMan.instance.CreateNewZDO(position, Data.CoinPrefabHash); list.Add(val3); val3.SetPrefab(Data.CoinPrefabHash); val3.Persistent = true; val3.Type = component.m_type; val3.Distant = component.m_distant; val3.SetRotation(Quaternion.identity); ItemDrop.SaveToZDO(val2, val3, -1); val3.SetOwner(owner); num -= val2.m_stack; } } catch { foreach (ZDO item in list) { SilentDestroy(item); } throw; } } private unsafe void PruneCoinSources() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) long now = Data.Now; KeyValuePair<ZDOID, CoinSource>[] array = coinSources.Where<KeyValuePair<ZDOID, CoinSource>>((KeyValuePair<ZDOID, CoinSource> s) => ZDOMan.instance.GetZDO(s.Key) == null && (now < s.Value.SeenAt || now - s.Value.SeenAt >= 120000)).ToArray(); foreach (KeyValuePair<ZDOID, CoinSource> keyValuePair in array) { coinSources.Remove(keyValuePair.Key); } if (coinAllowance != null && coinAllowance.Prune(now, (ISet<string>)new HashSet<string>(coinSources.Keys.Select((ZDOID id) => ((object)(*(ZDOID*)(&id))/*cast due to .constrained prefix*/).ToString()), StringComparer.Ordinal))) { WriteCoinBank(receipts: true); } } } internal sealed class EnemyDefinition { internal readonly string Prefab; internal readonly string Name; internal readonly int Tier; internal readonly GameObject Template; internal readonly bool Aquatic; internal readonly bool Dvergr; internal EnemyDefinition(GameObject prefab, int tier) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 Template = prefab; Prefab = ((Object)prefab).name; string name = prefab.GetComponent<Character>().m_name; Dvergr = (int)prefab.GetComponent<Character>().m_faction == 10; Name = (Dvergr ? RosterRules.DvergrName(Prefab, name) : RosterRules.BaseName(name)); Tier = tier; Aquatic = Prefab == "Serpent" || Prefab == "BonemawSerpent" || Prefab == "Leech" || Prefab == "Leech_cave"; } } internal sealed class Catalogue { internal readonly Dictionary<string, EnemyDefinition> Enemies = new Dictionary<string, EnemyDefinition>(StringComparer.Ordinal); private static readonly Dictionary<string, int> Known = BuildKnown(); private static readonly HashSet<string> BossNames = new HashSet<string>(StringComparer.Ordinal) { "Eikthyr", "gd_king", "Bonemass", "Dragon", "GoblinKing", "SeekerQueen", "Fader", "FrozenKing", "FrozenKing_p2", "FrozenKing_p3" }; private static Dictionary<string, int> BuildKnown() { Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal); string[] array = new string[8] { "Boar Neck Greyling", "Greydwarf Greydwarf_Elite Greydwarf_Shaman Troll Troll_sleeping Skeleton Skeleton_NoArcher Skeleton_Meadows Skeleton_Meadows_noarcher Ghost Ghost_sleeping Serpent", "Abomination Blob BlobElite Draugr Draugr_Elite Draugr_Ranged Draugr_sleeping Draugr_Elite_sleeping Draugr_Ranged_sleeping Leech Leech_cave Skeleton_Poison Skeleton_Swamps Skeleton_Swamps_noarcher Surtling Wraith Bat_Swamp", "Wolf Hatchling Fenring Fenring_Cultist Bat StoneGolem Ulv Skeleton_Mountains Skeleton_Mountains_noarcher", "Goblin GoblinArcher GoblinBrute GoblinShaman Lox Deathsquito BlobTar", "Seeker SeekerBrute SeekerBrood Gjall Tick", "Asksvin Charred_Archer Charred_Mage Charred_Melee Charred_Melee_Dyrnwyn Charred_Twitcher Morgen Morgen_NonSleeping Volture FallenValkyrie BlobLava BonemawSerpent", "Barka Bjorn Bjorn_sleeping BlobFrost BlobMork BlobMorkMini Elaking ElakingLantern ElakingMole FallenWarrior FrostWisp Frysling Ghost_Void GoblinDeepNorth Goblin_Gem Greydwarf_Frozen Greydwarf_Shaman_Frozen Hive JotunWarrior JotunWarriorDualWield JotunWitch Mistile Skeleton_DeepNorth TentaRoot_wild TheHive TrollFrost Unbjorn Writhan" }; for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(' '); foreach (string key in array2) { dictionary[key] = i; } } return dictionary; } internal Catalogue(Settings settings) { //IL_01eb: Unknown result type (might be due to invalid IL or missing references) HashSet<string> hashSet = new HashSet<string>(from x in settings.ExcludedEnemies.Value.Split(',') select x.Trim(), StringComparer.Ordinal); Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal); string[] array = settings.TierOverrides.Value.Split(','); for (int num = 0; num < array.Length; num++) { string[] array2 = array[num].Split('='); if (array2.Length == 2 && int.TryParse(array2[1], out var result) && result >= 0 && result < ArenaRules.Biomes.Length) { dictionary[array2[0].Trim()] = result; } } Dictionary<string, GameObject> dictionary2 = new Dictionary<string, GameObject>(StringComparer.Ordinal); foreach (GameObject prefab2 in ZNetScene.instance.m_prefabs) { if (Object.op_Implicit((Object)(object)prefab2)) { dictionary2[((Object)prefab2).name] = prefab2; } } foreach (string item in Known.Keys.Concat(RosterRules.DvergrPrefabs).Concat(dictionary.Keys).Distinct()) { GameObject prefab = PrefabManager.Instance.GetPrefab(item); if (Object.op_Implicit((Object)(object)prefab)) { dictionary2[item] = prefab; } } Dictionary<string, int> dictionary3 = new Dictionary<string, int>(StringComparer.Ordinal); SpawnSystemList[] array3 = Resources.FindObjectsOfTypeAll<SpawnSystemList>(); for (int num = 0; num < array3.Length; num++) { foreach (SpawnData spawner in array3[num].m_spawners) { if (!Object.op_Implicit((Object)(object)spawner.m_prefab) || !spawner.m_enabled) { continue; } int num2 = BiomeTier(spawner.m_biome); if (num2 >= 0) { dictionary2[((Object)spawner.m_prefab).name] = spawner.m_prefab; if (!dictionary3.TryGetValue(((Object)spawner.m_prefab).name, out var value) || num2 < value) { dictionary3[((Object)spawner.m_prefab).name] = num2; } } } } foreach (GameObject value3 in dictionary2.Values) { Character component = value3.GetComponent<Character>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)value3.GetComponent<MonsterAI>()) || !Object.op_Implicit((Object)(object)value3.GetComponent<ZNetView>()) || component.m_boss || hashSet.Contains(((Object)value3).name) || AlwaysExclude(((Object)value3).name, component)) { continue; } if (!dictionary.TryGetValue(((Object)value3).name, out var value2) && !RosterRules.TryDvergrTier(((Object)value3).name, ref value2) && !Known.TryGetValue(((Object)value3).name, out value2) && !dictionary3.TryGetValue(((Object)value3).name, out value2)) { if (!(((object)Unsafe.As<Faction, Faction>(ref component.m_faction)/*cast due to .constrained prefix*/).ToString() == "DeepNorth")) { Plugin.Instance.Warn("No arena tier for hostile prefab " + ((Object)value3).name + "; add an EnemyTierOverrides entry to include it."); continue; } value2 = 7; } Enemies[((Object)value3).name] = new EnemyDefinition(value3, value2); } if (Enemies.ContainsKey("DvergerMageFire") && Enemies.ContainsKey("DvergerMageIce") && Enemies.ContainsKey("DvergerMageSupport")) { Enemies.Remove("DvergerMage"); } HashSet<string> representatives = new HashSet<string>(from entry in RosterRules.Representatives(((IEnumerable<EnemyDefinition>)Enemies.Values).Select((Func<EnemyDefinition, RosterEntry>)((EnemyDefinition enemy) => new RosterEntry(enemy.Prefab, enemy.Name, enemy.Tier)))) select entry.Prefab, StringComparer.Ordinal); array = Enemies.Keys.Where((string name) => !representatives.Contains(name)).ToArray(); foreach (string key in array) { Enemies.Remove(key); } Plugin.Instance.LogInfo("Arena catalogue contains " + Enemies.Count + " distinct non-boss opponents."); } private static bool AlwaysExclude(string name, Character character) { string text = ((object)Unsafe.As<Faction, Faction>(ref character.m_faction)/*cast due to .constrained prefix*/).ToString(); if (!BossNames.Contains(name) && !name.EndsWith("_sleeping", StringComparison.OrdinalIgnoreCase) && !RosterRules.IsMiniboss(name) && !(name == "DvergerTest") && !(character is Player)) { switch (text) { default: if (name.StartsWith("Aspect_", StringComparison.Ordinal) || name.IndexOf("spiritcaller", StringComparison.OrdinalIgnoreCase) >= 0 || name.EndsWith("_Summoned", StringComparison.OrdinalIgnoreCase) || name.EndsWith("_Fader", StringComparison.Ordinal)) { break; } switch (name) { default: if (!name.EndsWith("_cub", StringComparison.Ordinal) && !name.EndsWith("_Calf", StringComparison.Ordinal) && !name.EndsWith("_calf", StringComparison.Ordinal) && !name.EndsWith("_piggy", StringComparison.Ordinal)) { return name.EndsWith("_hatchling", StringComparison.Ordinal); } break; case "Skeleton_Friendly": case "BlobAspect": case "Skeleton_aspect": case "TentaRoot": case "staff_greenroots_tentaroot": break; } break; case "Players": case "Boss": case "PlayerSpawned": case "TrainingDummy": break; } } return true; } private static int BiomeTier(Biome biomes) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or mi
BepInEx/plugins/ArenaCombat/ArenaCombat.Core.dll
Decompiled an hour agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ArenaCombat.Core")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ArenaCombat.Core")] [assembly: AssemblyTitle("ArenaCombat.Core")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ArenaCombat.Core { public static class ArenaRules { public static readonly string[] Biomes = new string[8] { "Meadows", "Black Forest", "Swamp", "Mountains", "Plains", "Mistlands", "Ashlands", "Deep North" }; public static readonly string[] UnlockKeys = new string[8] { "", "defeated_eikthyr", "defeated_gdking", "defeated_bonemass", "defeated_dragon", "defeated_goblinking", "defeated_queen", "defeated_fader" }; public static int LatestTier(Func<string, bool> hasKey) { int result = 0; for (int i = 1; i < UnlockKeys.Length; i++) { if (hasKey(UnlockKeys[i])) { result = i; } } return result; } public static int Cost(int baseCost, int lootCost, bool loot, int latestTier, int enemyTier, decimal discountPerTier = 0.20m) { if (baseCost < 0 || lootCost < 0) { throw new ArgumentOutOfRangeException("baseCost"); } if (enemyTier < 0 || enemyTier > latestTier) { throw new ArgumentOutOfRangeException("enemyTier"); } if (discountPerTier < 0m || discountPerTier > 1m) { throw new ArgumentOutOfRangeException("discountPerTier"); } if (!loot) { return 0; } decimal num = Math.Max(0m, 1m - (decimal)Math.Max(0, latestTier - enemyTier) * discountPerTier); return (int)Math.Ceiling(((decimal)baseCost + (decimal)lootCost) * num); } } public sealed class ReserveBank { public const long UnitsPerToken = 1000000L; public long Units { get; private set; } public long UpdatedAtMs { get; private set; } public int Reserved { get; private set; } public decimal Tokens => (decimal)Units / 1000000m; public ReserveBank(long units, long updatedAtMs, int reserved = 0) { Units = Math.Max(0L, units); UpdatedAtMs = updatedAtMs; Reserved = Math.Max(0, reserved); } public void Refill(long nowMs, int capacity, decimal tokensPerMinute) { if (capacity < 0 || tokensPerMinute < 0m) { throw new ArgumentOutOfRangeException("capacity"); } long num = Math.Max(0L, (long)capacity - (long)Reserved) * 1000000; Units = Math.Min(Units, num); if (nowMs < UpdatedAtMs) { UpdatedAtMs = nowMs; return; } decimal d = (decimal)(nowMs - UpdatedAtMs) * tokensPerMinute * 1000000m / 60000m; Units = (long)Math.Min(num, (decimal)Units + Math.Floor(d)); UpdatedAtMs = nowMs; } public bool TryReserve(int cost) { if (cost < 0) { throw new ArgumentOutOfRangeException("cost"); } if (Reserved != 0 || Units < (long)cost * 1000000L) { return false; } Units -= (long)cost * 1000000L; Reserved = cost; return true; } public void Commit() { Reserved = 0; } public void Refund(int capacity) { Units = Math.Min((long)Math.Max(0, capacity) * 1000000L, Units + (long)Reserved * 1000000L); Reserved = 0; } } public enum EncounterPhase { Ready, Countdown, Active } public sealed class EncounterState { public EncounterPhase Phase { get; private set; } public long DeadlineMs { get; private set; } public ReserveBank Bank { get; } public EncounterState(ReserveBank bank, EncounterPhase phase = EncounterPhase.Ready, long deadlineMs = 0L) { Bank = bank; Phase = phase; DeadlineMs = deadlineMs; } public bool TryBegin(int cost, long nowMs, int countdownSeconds) { if (Phase != EncounterPhase.Ready || !Bank.TryReserve(cost)) { return false; } Phase = EncounterPhase.Countdown; checked { DeadlineMs = nowMs + unchecked((long)Math.Max(0, countdownSeconds)) * 1000L; return true; } } public bool CanSpawn(long nowMs) { if (Phase == EncounterPhase.Countdown) { return nowMs >= DeadlineMs; } return false; } public void SpawnSucceeded() { if (Phase != EncounterPhase.Countdown) { throw new InvalidOperationException("No summon is pending."); } Bank.Commit(); Phase = EncounterPhase.Active; DeadlineMs = 0L; } public void Cancel(int capacity) { if (Phase == EncounterPhase.Countdown) { Bank.Refund(capacity); Phase = EncounterPhase.Ready; DeadlineMs = 0L; } } public void Finish() { if (Phase == EncounterPhase.Active) { Phase = EncounterPhase.Ready; } } } public sealed class PresenceGrace { public long AbsentSinceMs { get; private set; } public PresenceGrace(long absentSinceMs = 0L) { AbsentSinceMs = absentSinceMs; } public bool Check(bool playerNearby, long nowMs, int graceSeconds) { if (playerNearby) { AbsentSinceMs = 0L; return false; } if (AbsentSinceMs == 0L || nowMs < AbsentSinceMs) { AbsentSinceMs = nowMs; } return nowMs - AbsentSinceMs >= (long)Math.Max(0, graceSeconds) * 1000L; } } public readonly struct CoinClaim { public int Charged { get; } public long AtMs { get; } public CoinClaim(int charged, long atMs) { Charged = charged; AtMs = atMs; } } public sealed class CoinAllowance { public const long UnitsPerCoin = 1000000L; public const long HourMs = 3600000L; public const long ReceiptWindowMs = 120000L; private readonly Dictionary<string, CoinClaim> claims; public long Units { get; private set; } public long UpdatedAtMs { get; private set; } public long Remainder { get; private set; } public int Available => (int)(Units / 1000000); public IReadOnlyDictionary<string, CoinClaim> Claims => claims; public CoinAllowance(long units, long updatedAtMs, long remainder = 0L, IEnumerable<KeyValuePair<string, CoinClaim>>? savedClaims = null) { Units = Math.Max(0L, units); UpdatedAtMs = updatedAtMs; Remainder = Math.Max(0L, Math.Min(3599999L, remainder)); claims = savedClaims?.ToDictionary<KeyValuePair<string, CoinClaim>, string, CoinClaim>((KeyValuePair<string, CoinClaim> c) => c.Key, (KeyValuePair<string, CoinClaim> c) => c.Value, StringComparer.Ordinal) ?? new Dictionary<string, CoinClaim>(StringComparer.Ordinal); } public void Refill(long nowMs, int capacity, decimal perHour) { if (capacity < 0 || perHour < 0m) { throw new ArgumentOutOfRangeException("capacity"); } long num = (long)capacity * 1000000L; Units = Math.Min(Units, num); if (nowMs < UpdatedAtMs) { UpdatedAtMs = nowMs; Remainder = 0L; return; } long num2 = (long)Math.Round(perHour * 1000000m, MidpointRounding.AwayFromZero); decimal num3 = (decimal)(nowMs - UpdatedAtMs) * (decimal)num2 + (decimal)Remainder; decimal num4 = Math.Floor(num3 / 3600000m); if (num4 >= (decimal)(num - Units)) { Units = num; Remainder = 0L; } else { Units += (long)num4; Remainder = (long)(num3 % 3600000m); } UpdatedAtMs = nowMs; } public int Claim(string source, int requested, long nowMs, int capacity, decimal perHour, bool enabled = true) { if (string.IsNullOrEmpty(source) || requested < 0) { throw new ArgumentException("Invalid coin payout."); } Refill(nowMs, capacity, perHour); if (claims.ContainsKey(source)) { return 0; } int num = (enabled ? Math.Min(requested, Available) : requested); int num2 = (enabled ? num : 0); Units -= (long)num2 * 1000000L; claims[source] = new CoinClaim(num2, nowMs); return num; } public void Undo(string source, int capacity) { if (claims.TryGetValue(source, out var value)) { Units = Math.Min((long)capacity * 1000000L, Units + (long)value.Charged * 1000000L); claims.Remove(source); } } public bool Prune(long nowMs, ISet<string> validSources) { string[] array = (from c in claims where !validSources.Contains(c.Key) && (nowMs < c.Value.AtMs || nowMs - c.Value.AtMs >= 120000) select c.Key).ToArray(); string[] array2 = array; foreach (string key in array2) { claims.Remove(key); } return array.Length != 0; } } public sealed class DeathPresenceTracker<T> where T : notnull { private const long ReplicationWindowMs = 5000L; private readonly Dictionary<T, long> pending = new Dictionary<T, long>(); public void Report(T player, long nowMs) { pending[player] = nowMs; } public void Clear() { pending.Clear(); } public bool IsAlive(T player, bool replicatedAlive, long nowMs) { if (!replicatedAlive) { pending.Remove(player); return false; } if (!pending.TryGetValue(player, out var value)) { return true; } if (nowMs >= value && nowMs - value < 5000) { return false; } pending.Remove(player); return true; } public void Prune(long nowMs) { List<T> list = new List<T>(); foreach (KeyValuePair<T, long> item in pending) { if (nowMs < item.Value || nowMs - item.Value >= 5000) { list.Add(item.Key); } } foreach (T item2 in list) { pending.Remove(item2); } } } public static class DifficultyRules { public const int Minimum = 10; public const int Maximum = 30; public static bool IsValid(int tenths) { if (tenths >= 10) { return tenths <= 30; } return false; } public static decimal Strength(int tenths) { if (!IsValid(tenths)) { throw new ArgumentOutOfRangeException("tenths"); } return (decimal)tenths / 10m; } public static int LootPercent(int tenths) { if (!IsValid(tenths)) { throw new ArgumentOutOfRangeException("tenths"); } return tenths * 10 - 50; } public static int ScaleCount(int count, int percent, double sample) { if (count < 0 || percent < 0 || percent > 100 || double.IsNaN(sample) || sample < 0.0 || sample > 1.0) { throw new ArgumentOutOfRangeException("count"); } long num = (long)count * (long)percent; checked { return (int)(unchecked(num / 100) + ((sample < (double)unchecked(num % 100) / 100.0) ? 1 : 0)); } } } public sealed class RosterEntry { public string Prefab { get; } public string Name { get; } public int Tier { get; } public RosterEntry(string prefab, string name, int tier) { Prefab = prefab; Name = name; Tier = tier; } } public static class RosterRules { private static readonly Dictionary<string, int> DvergrTiers = new Dictionary<string, int>(StringComparer.Ordinal) { ["Dverger"] = 5, ["DvergerMage"] = 5, ["DvergerMageFire"] = 5, ["DvergerMageIce"] = 5, ["DvergerMageSupport"] = 5, ["DvergerAshlands"] = 6, ["DvergerDeepNorth"] = 7 }; public static IEnumerable<string> DvergrPrefabs => DvergrTiers.Keys; public static bool TryDvergrTier(string prefab, out int tier) { return DvergrTiers.TryGetValue(prefab, out tier); } public static bool IsMiniboss(string prefab) { if (!(prefab == "Charred_Melee_Dyrnwyn") && prefab.IndexOf("_Hildir", StringComparison.OrdinalIgnoreCase) < 0) { return prefab.StartsWith("GoblinBruteBros", StringComparison.OrdinalIgnoreCase); } return true; } public static string BaseName(string name) { int num = name.IndexOf('('); return ((num < 0) ? name : name.Substring(0, num)).Trim(); } public static string DvergrName(string prefab, string nativeName) { return prefab switch { "Dverger" => nativeName + " — Mistlands", "DvergerAshlands" => nativeName + " — Ashlands", "DvergerDeepNorth" => nativeName + " — Deep North", "DvergerMageFire" => nativeName + " — Fire", "DvergerMageIce" => nativeName + " — Frost", "DvergerMageSupport" => nativeName + " — Support", _ => nativeName, }; } public static IReadOnlyList<RosterEntry> Representatives(IEnumerable<RosterEntry> entries) { return (from @group in entries.GroupBy<RosterEntry, string>((RosterEntry entry) => BaseName(entry.Name), StringComparer.OrdinalIgnoreCase) select (from entry in @group orderby entry.Tier, (!(entry.Prefab == "Morgen_NonSleeping")) ? ((!entry.Prefab.Contains("_")) ? 1 : 2) : 0 select entry).ThenBy<RosterEntry, string>((RosterEntry entry) => entry.Prefab, StringComparer.Ordinal).First() into entry orderby entry.Tier descending select entry).ThenBy<RosterEntry, string>((RosterEntry entry) => entry.Name, StringComparer.Ordinal).ThenBy<RosterEntry, string>((RosterEntry entry) => entry.Prefab, StringComparer.Ordinal).ToList(); } } }