Decompiled source of MuckReplayable v1.1.11

MuckReplayable.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Steamworks;
using Steamworks.Data;
using TMPro;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("MuckReplayable")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.11.0")]
[assembly: AssemblyInformationalVersion("1.1.11")]
[assembly: AssemblyProduct("MuckReplayable")]
[assembly: AssemblyTitle("MuckReplayable")]
[assembly: AssemblyVersion("1.1.11.0")]
namespace MuckReforged;

internal static class AccessoryCombatRules
{
	internal static bool Harvesting;

	internal static bool SpawningProjectileImpact;

	internal static bool ProjectileDamage;

	internal static float AttacksPerSecond(bool haste, bool juice)
	{
		if (!juice)
		{
			if (!haste)
			{
				return 3.5f;
			}
			return 4f;
		}
		if (!haste)
		{
			return 5f;
		}
		return 5.5f;
	}
}
[HarmonyPatch(typeof(LootExtra), "CheckDrop")]
internal static class AccessoryHarvestContext
{
	private static void Prefix(out bool __state)
	{
		__state = AccessoryCombatRules.Harvesting;
		AccessoryCombatRules.Harvesting = true;
	}

	private static void Finalizer(bool __state)
	{
		AccessoryCombatRules.Harvesting = __state;
	}
}
internal sealed class DeflectableProjectileImpact : MonoBehaviour
{
}
[HarmonyPatch(typeof(EnemyProjectile), "OnCollisionEnter")]
internal static class AccessoryProjectileContext
{
	private static void Prefix(out bool __state)
	{
		__state = AccessoryCombatRules.SpawningProjectileImpact;
		AccessoryCombatRules.SpawningProjectileImpact = true;
	}

	private static void Finalizer(bool __state)
	{
		AccessoryCombatRules.SpawningProjectileImpact = __state;
	}
}
[HarmonyPatch(typeof(ImpactDamage), "SetDamage")]
internal static class AccessoryMarkProjectileImpact
{
	private static void Postfix(ImpactDamage __instance)
	{
		if (AccessoryCombatRules.SpawningProjectileImpact && (Object)(object)((Component)__instance).GetComponent<DeflectableProjectileImpact>() == (Object)null)
		{
			((Component)__instance).gameObject.AddComponent<DeflectableProjectileImpact>();
		}
	}
}
[HarmonyPatch(typeof(ImpactDamage), "Start")]
internal static class AccessoryImpactContext
{
	private static void Prefix(ImpactDamage __instance, out bool __state)
	{
		__state = AccessoryCombatRules.ProjectileDamage;
		AccessoryCombatRules.ProjectileDamage = (Object)(object)((Component)__instance).GetComponent<DeflectableProjectileImpact>() != (Object)null;
	}

	private static void Finalizer(bool __state)
	{
		AccessoryCombatRules.ProjectileDamage = __state;
	}
}
[HarmonyPatch(typeof(ClientSend), "PlayerHit")]
internal static class AccessoryProjectileReduction
{
	private static void Prefix(ref int damage, int hurtPlayer)
	{
		if (AccessoryCombatRules.ProjectileDamage)
		{
			damage = Mathf.CeilToInt((float)damage * (1f - AccessoryNetwork.ValueForPlayer(AccessoryEffect.Deflection, hurtPlayer)));
		}
	}
}
[HarmonyPatch(typeof(Arrow), "OnCollisionEnter")]
internal static class AccessoryArrowContext
{
	private static void Prefix(out bool __state)
	{
		__state = AccessoryCombatRules.ProjectileDamage;
		AccessoryCombatRules.ProjectileDamage = true;
	}

	private static void Finalizer(bool __state)
	{
		AccessoryCombatRules.ProjectileDamage = __state;
	}
}
internal enum AccessorySlot
{
	Ring,
	Necklace
}
internal enum AccessoryEffect
{
	Strength,
	Haste,
	Swiftness,
	Defense,
	Deflection,
	Fortune
}
internal sealed class ReplayableAccessory
{
	internal string Name;

	internal AccessorySlot Slot;

	internal AccessoryEffect Effect;

	internal string PrimaryMaterial;

	internal int PrimaryCost;

	internal string SecondaryMaterial;

	internal int SecondaryCost;

	internal float Value;

	internal Color Color;

	internal string EffectText;

	internal InventoryItem Item;
}
internal static class AccessoryRegistry
{
	private const string AssetPrefix = "MuckReplayable_Accessory_";

	private static readonly Dictionary<int, ReplayableAccessory> ById = new Dictionary<int, ReplayableAccessory>();

	private static ItemManager installedManager;

	private static Mesh ringMesh;

	private static Mesh necklaceMesh;

	private static readonly ReplayableAccessory[] Definitions = new ReplayableAccessory[6]
	{
		Necklace("Necklace Of Greed", AccessoryEffect.Fortune, "AncientCore", 1, "Gold bar", 69, 0.5f, new Color(1f, 0.72f, 0.08f), "+50% harvested resources"),
		Necklace("Necklace Of Deflection", AccessoryEffect.Deflection, "AncientCore", 1, "Mithril bar", 69, 0.5f, new Color(0.2f, 0.72f, 0.96f), "50% less incoming projectile damage"),
		Ring("Ring Of Power", AccessoryEffect.Strength, "Fireball", 10, "Chunkium bar", 25, 1f, new Color(0.96f, 0.18f, 0.08f), "+1 effective Massgainer stack"),
		Ring("Ring Of Speed", AccessoryEffect.Swiftness, "Lightningball", 10, "Chunkium bar", 25, 0.5f, new Color(0.9f, 0.78f, 0.12f), "+50% movement speed"),
		Ring("Ring Of Haste", AccessoryEffect.Haste, "Wyvern Claws", 1, "Chunkium bar", 25, 0.5f, new Color(0.32f, 0.84f, 0.92f), "+50% attack speed; cap 4 attacks/s (5.5 with Juice)"),
		Ring("Ring Of Defense", AccessoryEffect.Defense, "Waterball", 10, "Chunkium bar", 25, 10f, new Color(0.12f, 0.42f, 0.96f), "+10 percentage points of defense")
	};

	internal static IEnumerable<ReplayableAccessory> All => Definitions.Where((ReplayableAccessory value) => (Object)(object)value.Item != (Object)null);

	internal static void Install(ItemManager manager)
	{
		//IL_0327: Unknown result type (might be due to invalid IL or missing references)
		//IL_032f: Unknown result type (might be due to invalid IL or missing references)
		//IL_040f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0480: Unknown result type (might be due to invalid IL or missing references)
		//IL_046a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0485: Unknown result type (might be due to invalid IL or missing references)
		//IL_049b: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
		if (manager?.allItems == null || manager.allScriptableItems == null || ((Object)(object)installedManager == (Object)(object)manager && Definitions.All((ReplayableAccessory definition) => (Object)(object)definition.Item != (Object)null && manager.allItems.TryGetValue(definition.Item.id, out var value) && value == definition.Item)))
		{
			return;
		}
		installedManager = manager;
		ById.Clear();
		ReplayableAccessory[] definitions = Definitions;
		for (int num = 0; num < definitions.Length; num++)
		{
			definitions[num].Item = null;
		}
		List<InventoryItem> list = manager.allScriptableItems.Where((InventoryItem item) => (Object)(object)item != (Object)null && !(((Object)item).name ?? string.Empty).StartsWith("MuckReplayable_Accessory_", StringComparison.Ordinal)).ToList();
		int[] array = (from pair in manager.allItems
			where (Object)(object)pair.Value != (Object)null && (((Object)pair.Value).name ?? string.Empty).StartsWith("MuckReplayable_Accessory_", StringComparison.Ordinal)
			select pair.Key).ToArray();
		foreach (int key in array)
		{
			manager.allItems.Remove(key);
		}
		InventoryItem val = Find(manager, "Anvil");
		InventoryItem val2 = Find(manager, "Chunkium bar") ?? Find(manager, "Gold bar");
		if ((Object)(object)val == (Object)null || (Object)(object)val2?.material == (Object)null)
		{
			Plugin.Log.LogWarning((object)"Accessory registration skipped because Anvil or a visual material was unavailable.");
			return;
		}
		ringMesh = (((Object)(object)ringMesh != (Object)null) ? ringMesh : CreateTorusMesh());
		necklaceMesh = (((Object)(object)necklaceMesh != (Object)null) ? necklaceMesh : CreatePendantMesh());
		int num2 = ItemCatalogUtilities.NextId(manager);
		definitions = Definitions;
		foreach (ReplayableAccessory replayableAccessory in definitions)
		{
			InventoryItem val3 = Find(manager, replayableAccessory.PrimaryMaterial);
			InventoryItem val4 = Find(manager, replayableAccessory.SecondaryMaterial);
			if ((Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null)
			{
				Plugin.Log.LogWarning((object)("Skipped " + replayableAccessory.Name + ": " + replayableAccessory.PrimaryMaterial + " or " + replayableAccessory.SecondaryMaterial + " was unavailable."));
				continue;
			}
			InventoryItem val5 = ScriptableObject.CreateInstance<InventoryItem>();
			((Object)val5).name = "MuckReplayable_Accessory_" + replayableAccessory.Name.Replace(" ", string.Empty);
			val5.id = num2++;
			val5.name = replayableAccessory.Name;
			val5.description = replayableAccessory.EffectText + ". Right-click in your inventory to equip permanently for this run. Only one " + replayableAccessory.Slot.ToString().ToLowerInvariant() + " can be equipped.";
			val5.type = (ItemType)0;
			val5.tag = (ItemTag)0;
			val5.tier = 5;
			val5.stackable = false;
			val5.max = 1;
			val5.amount = 1;
			val5.craftable = true;
			val5.craftAmount = 1;
			val5.unlockWithFirstRequirementOnly = true;
			val5.stationRequirement = val;
			val5.requirements = (CraftRequirement[])(object)new CraftRequirement[2]
			{
				Requirement(val3, replayableAccessory.PrimaryCost),
				Requirement(val4, replayableAccessory.SecondaryCost)
			};
			val5.mesh = ((replayableAccessory.Slot == AccessorySlot.Ring) ? ringMesh : necklaceMesh);
			val5.material = Object.Instantiate<Material>(val2.material);
			((Object)val5.material).name = "MuckReplayable_Accessory_" + replayableAccessory.Name + " Material";
			if (val5.material.HasProperty("_Color"))
			{
				val5.material.color = replayableAccessory.Color;
			}
			if (val5.material.HasProperty("_Glossiness"))
			{
				val5.material.SetFloat("_Glossiness", 0.72f);
			}
			val5.sprite = CreateIcon(replayableAccessory);
			val5.rotationOffset = ((replayableAccessory.Slot == AccessorySlot.Ring) ? new Vector3(18f, 0f, -22f) : new Vector3(8f, 0f, 0f));
			val5.positionOffset = new Vector3(0f, -0.08f, 0.35f);
			val5.scale = ((replayableAccessory.Slot == AccessorySlot.Ring) ? 0.7f : 0.62f);
			val5.rarity = (ItemRarity)2;
			val5.attackTypes = Array.Empty<Weakness>();
			Object.DontDestroyOnLoad((Object)(object)val5);
			Object.DontDestroyOnLoad((Object)(object)val5.material);
			list.Add(val5);
			manager.allItems[val5.id] = val5;
			replayableAccessory.Item = val5;
			ById[val5.id] = replayableAccessory;
		}
		manager.allScriptableItems = list.ToArray();
		CraftingUI[] array2 = Resources.FindObjectsOfTypeAll<CraftingUI>();
		for (int num = 0; num < array2.Length; num++)
		{
			InjectCrafting(array2[num]);
		}
		Plugin.Log.LogInfo((object)$"Registered {ById.Count} permanent accessories with anvil recipes.");
	}

	internal static bool TryGet(InventoryItem item, out ReplayableAccessory accessory)
	{
		return ById.TryGetValue(((Object)(object)item != (Object)null) ? item.id : (-1), out accessory);
	}

	internal static ReplayableAccessory FindDefinition(string name)
	{
		switch (name)
		{
		case "Ruby Ring":
			name = "Ring Of Power";
			break;
		case "Black Shard Ring":
			name = "Ring Of Haste";
			break;
		case "Wyvern Ring":
			name = "Ring Of Speed";
			break;
		case "Dragon Ring":
			name = "Ring Of Defense";
			break;
		case "Fortune Necklace":
			name = "Necklace Of Greed";
			break;
		case "Guardian Necklace":
			name = "Necklace Of Deflection";
			break;
		}
		return Definitions.FirstOrDefault((ReplayableAccessory value) => string.Equals(value.Name, name, StringComparison.OrdinalIgnoreCase));
	}

	internal static void InjectCrafting(CraftingUI crafting)
	{
		if (crafting?.tabs == null || ById.Count == 0 || ((object)OtherInput.Instance?.anvil != crafting && !crafting.tabs.Any((Tab tab) => (tab?.items ?? Array.Empty<InventoryItem>()).Any((InventoryItem item) => (Object)(object)item != (Object)null && item.name == "Gold Sword"))))
		{
			return;
		}
		int num = Array.FindIndex(crafting.tabs, (Tab tab) => (tab?.items ?? Array.Empty<InventoryItem>()).Any((InventoryItem item) => (Object)(object)item != (Object)null && (int)item.type == 3));
		if (num < 0 && crafting.tabs.Length != 0)
		{
			num = 0;
		}
		if (num >= 0)
		{
			crafting.tabs[num].items = (from item in (crafting.tabs[num].items ?? Array.Empty<InventoryItem>()).Concat(All.Select((ReplayableAccessory value) => value.Item))
				where (Object)(object)item != (Object)null
				group item by item.id into @group
				select @group.First()).ToArray();
		}
	}

	private static ReplayableAccessory Ring(string name, AccessoryEffect effect, string primary, int primaryCost, string secondary, int secondaryCost, float value, Color color, string text)
	{
		//IL_0041: 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)
		return new ReplayableAccessory
		{
			Name = name,
			Slot = AccessorySlot.Ring,
			Effect = effect,
			PrimaryMaterial = primary,
			PrimaryCost = primaryCost,
			SecondaryMaterial = secondary,
			SecondaryCost = secondaryCost,
			Value = value,
			Color = color,
			EffectText = text
		};
	}

	private static ReplayableAccessory Necklace(string name, AccessoryEffect effect, string primary, int primaryCost, string secondary, int secondaryCost, float value, Color color, string text)
	{
		//IL_0041: 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)
		return new ReplayableAccessory
		{
			Name = name,
			Slot = AccessorySlot.Necklace,
			Effect = effect,
			PrimaryMaterial = primary,
			PrimaryCost = primaryCost,
			SecondaryMaterial = secondary,
			SecondaryCost = secondaryCost,
			Value = value,
			Color = color,
			EffectText = text
		};
	}

	private static InventoryItem Find(ItemManager manager, string name)
	{
		return ((IEnumerable<InventoryItem>)manager.allItems.Values).FirstOrDefault((Func<InventoryItem, bool>)((InventoryItem item) => (Object)(object)item != (Object)null && string.Equals(item.name, name, StringComparison.OrdinalIgnoreCase)));
	}

	private static CraftRequirement Requirement(InventoryItem item, int amount)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Expected O, but got Unknown
		return new CraftRequirement
		{
			item = item,
			amount = amount
		};
	}

	private static Mesh CreateTorusMesh()
	{
		//IL_0147: 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_0157: 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_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Expected O, but got Unknown
		//IL_0179: Expected O, but got Unknown
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		Vector3[] array = (Vector3[])(object)new Vector3[192];
		Vector3[] array2 = (Vector3[])(object)new Vector3[array.Length];
		int[] array3 = new int[1152];
		Vector3 val = default(Vector3);
		Vector3 val2 = default(Vector3);
		for (int i = 0; i < 24; i++)
		{
			float num = (float)i * (float)Math.PI * 2f / 24f;
			((Vector3)(ref val))..ctor(Mathf.Cos(num) * 0.42f, Mathf.Sin(num) * 0.42f, 0f);
			for (int j = 0; j < 8; j++)
			{
				float num2 = (float)j * (float)Math.PI * 2f / 8f;
				((Vector3)(ref val2))..ctor(Mathf.Cos(num) * Mathf.Cos(num2), Mathf.Sin(num) * Mathf.Cos(num2), Mathf.Sin(num2));
				int num3 = i * 8 + j;
				array2[num3] = val2;
				array[num3] = val + val2 * 0.11f;
				int num4 = (i + 1) % 24 * 8;
				int num5 = (j + 1) % 8;
				int num6 = num3 * 6;
				array3[num6] = num3;
				array3[num6 + 1] = num4 + j;
				array3[num6 + 2] = num4 + num5;
				array3[num6 + 3] = num3;
				array3[num6 + 4] = num4 + num5;
				array3[num6 + 5] = i * 8 + num5;
			}
		}
		Mesh val3 = new Mesh
		{
			name = "MuckReplayable_Accessory_RingMesh",
			vertices = array,
			normals = array2,
			triangles = array3
		};
		val3.RecalculateBounds();
		Object.DontDestroyOnLoad((Object)val3);
		return val3;
	}

	private static Mesh CreatePendantMesh()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Expected O, but got Unknown
		//IL_00ed: Expected O, but got Unknown
		Vector3[] vertices = (Vector3[])(object)new Vector3[6]
		{
			new Vector3(0f, 0.55f, 0f),
			new Vector3(-0.38f, 0.05f, 0f),
			new Vector3(0f, -0.55f, 0f),
			new Vector3(0.38f, 0.05f, 0f),
			new Vector3(0f, 0.05f, 0.2f),
			new Vector3(0f, 0.05f, -0.2f)
		};
		int[] triangles = new int[24]
		{
			0, 1, 4, 1, 2, 4, 2, 3, 4, 3,
			0, 4, 1, 0, 5, 2, 1, 5, 3, 2,
			5, 0, 3, 5
		};
		Mesh val = new Mesh
		{
			name = "MuckReplayable_Accessory_NecklaceMesh",
			vertices = vertices,
			triangles = triangles
		};
		val.RecalculateNormals();
		val.RecalculateBounds();
		Object.DontDestroyOnLoad((Object)val);
		return val;
	}

	private static Sprite CreateIcon(ReplayableAccessory definition)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0035: Expected O, but got Unknown
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: 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_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(96, 96, (TextureFormat)4, false)
		{
			name = "MuckReplayable_Accessory_" + definition.Name + " Icon",
			filterMode = (FilterMode)1,
			wrapMode = (TextureWrapMode)1
		};
		Color[] array = Enumerable.Repeat<Color>(new Color(0f, 0f, 0f, 0f), 9216).ToArray();
		Color val2 = Color.Lerp(definition.Color, Color.white, 0.42f);
		for (int i = 0; i < 96; i++)
		{
			for (int j = 0; j < 96; j++)
			{
				float num = (float)j - 47.5f;
				float num2 = (float)i - 47.5f;
				if (definition.Slot == AccessorySlot.Ring)
				{
					float num3 = Mathf.Sqrt(num * num + num2 * num2);
					if (num3 >= 24f && num3 <= 34f)
					{
						array[i * 96 + j] = ((num3 < 27f) ? val2 : definition.Color);
					}
					if (Mathf.Abs(num) + Mathf.Abs(num2 - 30f) < 13f)
					{
						array[i * 96 + j] = val2;
					}
				}
				else
				{
					float num4 = Mathf.Abs(Mathf.Sqrt(num * num + (num2 - 8f) * (num2 - 8f) * 0.72f) - 30f);
					if (num2 > -17f && num4 < 2.2f)
					{
						array[i * 96 + j] = val2;
					}
					if (Mathf.Abs(num) + Mathf.Abs(num2 + 22f) * 0.72f < 18f)
					{
						array[i * 96 + j] = definition.Color;
					}
				}
			}
		}
		val.SetPixels(array);
		val.Apply(false, true);
		Object.DontDestroyOnLoad((Object)(object)val);
		Sprite obj = Sprite.Create(val, new Rect(0f, 0f, 96f, 96f), new Vector2(0.5f, 0.5f), 96f);
		((Object)obj).name = "MuckReplayable_Accessory_" + definition.Name + " Sprite";
		Object.DontDestroyOnLoad((Object)(object)obj);
		return obj;
	}
}
internal static class AccessoryState
{
	internal static string Ring { get; private set; }

	internal static string Necklace { get; private set; }

	internal static bool Equip(ReplayableAccessory accessory)
	{
		if (accessory == null)
		{
			return false;
		}
		if (accessory.Slot == AccessorySlot.Ring)
		{
			if (!string.IsNullOrEmpty(Ring))
			{
				return false;
			}
			Ring = accessory.Name;
		}
		else
		{
			if (!string.IsNullOrEmpty(Necklace))
			{
				return false;
			}
			Necklace = accessory.Name;
		}
		PlayerStatus instance = PlayerStatus.Instance;
		if (instance != null)
		{
			instance.UpdateStats();
		}
		AccessoryNetwork.SendLocalState();
		return true;
	}

	internal static bool Has(AccessoryEffect effect)
	{
		return Equipped().Any((ReplayableAccessory value) => value.Effect == effect);
	}

	internal static float Value(AccessoryEffect effect, int[] playerPowerups = null)
	{
		if (playerPowerups != null)
		{
			return AccessoryNetwork.ValueForPowerups(effect, playerPowerups);
		}
		return (from value in Equipped()
			where value.Effect == effect
			select value).Sum((ReplayableAccessory value) => value.Value);
	}

	internal static void Reset()
	{
		Ring = null;
		Necklace = null;
	}

	internal static void Import(string ring, string necklace)
	{
		ReplayableAccessory replayableAccessory = AccessoryRegistry.FindDefinition(ring);
		ReplayableAccessory replayableAccessory2 = AccessoryRegistry.FindDefinition(necklace);
		Ring = ((replayableAccessory != null && replayableAccessory.Slot == AccessorySlot.Ring) ? replayableAccessory.Name : null);
		Necklace = ((replayableAccessory2 != null && replayableAccessory2.Slot == AccessorySlot.Necklace) ? replayableAccessory2.Name : null);
	}

	private static IEnumerable<ReplayableAccessory> Equipped()
	{
		ReplayableAccessory replayableAccessory = AccessoryRegistry.FindDefinition(Ring);
		ReplayableAccessory necklace = AccessoryRegistry.FindDefinition(Necklace);
		if (replayableAccessory != null)
		{
			yield return replayableAccessory;
		}
		if (necklace != null)
		{
			yield return necklace;
		}
	}
}
internal static class AccessoryNetwork
{
	private sealed class Equipment
	{
		internal string Ring;

		internal string Necklace;
	}

	internal const int RequestPacketId = 236;

	internal const int SyncPacketId = 237;

	private static readonly Dictionary<int, Equipment> Players = new Dictionary<int, Equipment>();

	private static readonly MethodInfo ClientSendTcp = AccessTools.Method(typeof(ClientSend), "SendTCPData", new Type[1] { typeof(Packet) }, (Type[])null);

	private static readonly MethodInfo ServerSendAll = AccessTools.Method(typeof(ServerSend), "SendTCPDataToAll", new Type[1] { typeof(Packet) }, (Type[])null);

	internal static void Reset()
	{
		Players.Clear();
	}

	internal static void Remove(int playerId)
	{
		Players.Remove(playerId);
	}

	internal static void SendLocalState()
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Expected O, but got Unknown
		if ((Object)(object)LocalClient.instance == (Object)null || (Object)(object)GameManager.instance == (Object)null)
		{
			return;
		}
		int myId = LocalClient.instance.myId;
		if (LocalClient.serverOwner)
		{
			SetServer(myId, AccessoryState.Ring, AccessoryState.Necklace);
			return;
		}
		Packet val = new Packet(236);
		try
		{
			val.Write(AccessoryState.Ring ?? string.Empty);
			val.Write(AccessoryState.Necklace ?? string.Empty);
			ClientSendTcp?.Invoke(null, new object[1] { val });
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}

	internal static void ReceiveRequest(int fromClient, Packet packet)
	{
		try
		{
			SetServer(fromClient, packet.ReadString(true), packet.ReadString(true));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Rejected accessory state: " + ex.Message));
		}
	}

	private static void SetServer(int playerId, string requestedRing, string requestedNecklace)
	{
		if (Server.clients != null && Server.clients.TryGetValue(playerId, out var value) && value?.player != null)
		{
			Players.TryGetValue(playerId, out var value2);
			string text = Valid(requestedRing, AccessorySlot.Ring);
			string text2 = Valid(requestedNecklace, AccessorySlot.Necklace);
			if (!string.IsNullOrEmpty(value2?.Ring) && value2.Ring != text)
			{
				text = value2.Ring;
			}
			if (!string.IsNullOrEmpty(value2?.Necklace) && value2.Necklace != text2)
			{
				text2 = value2.Necklace;
			}
			Equipment equipment = new Equipment
			{
				Ring = text,
				Necklace = text2
			};
			Players[playerId] = equipment;
			Broadcast(playerId, equipment);
		}
	}

	private static string Valid(string name, AccessorySlot slot)
	{
		ReplayableAccessory replayableAccessory = AccessoryRegistry.FindDefinition(name);
		if (replayableAccessory == null || replayableAccessory.Slot != slot)
		{
			return string.Empty;
		}
		return replayableAccessory.Name;
	}

	private static void Broadcast(int playerId, Equipment state)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		Packet val = new Packet(237);
		try
		{
			val.Write(playerId);
			val.Write(state.Ring ?? string.Empty);
			val.Write(state.Necklace ?? string.Empty);
			ServerSendAll?.Invoke(null, new object[1] { val });
			Apply(playerId, state.Ring, state.Necklace);
		}
		finally
		{
			((IDisposable)val)?.Dispose();
		}
	}

	internal static void ReceiveSync(Packet packet)
	{
		try
		{
			Apply(packet.ReadInt(true), packet.ReadString(true), packet.ReadString(true));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Rejected accessory sync: " + ex.Message));
		}
	}

	private static void Apply(int playerId, string ring, string necklace)
	{
		Players[playerId] = new Equipment
		{
			Ring = Valid(ring, AccessorySlot.Ring),
			Necklace = Valid(necklace, AccessorySlot.Necklace)
		};
		if ((Object)(object)LocalClient.instance != (Object)null && playerId == LocalClient.instance.myId)
		{
			AccessoryState.Import(ring, necklace);
			PlayerStatus instance = PlayerStatus.Instance;
			if (instance != null)
			{
				instance.UpdateStats();
			}
		}
	}

	internal static float ValueForPowerups(AccessoryEffect effect, int[] playerPowerups)
	{
		if (playerPowerups == null || Server.clients == null)
		{
			return 0f;
		}
		foreach (KeyValuePair<int, Client> client in Server.clients)
		{
			if (client.Value?.player?.powerups != null && client.Value.player.powerups == playerPowerups && Players.TryGetValue(client.Key, out var value))
			{
				ReplayableAccessory replayableAccessory = AccessoryRegistry.FindDefinition(value.Ring);
				ReplayableAccessory replayableAccessory2 = AccessoryRegistry.FindDefinition(value.Necklace);
				float num = ((replayableAccessory != null && replayableAccessory.Effect == effect) ? replayableAccessory.Value : 0f);
				if (replayableAccessory2 != null && replayableAccessory2.Effect == effect)
				{
					num += replayableAccessory2.Value;
				}
				return num;
			}
		}
		return 0f;
	}

	internal static float ValueForPlayer(AccessoryEffect effect, int playerId)
	{
		if ((Object)(object)LocalClient.instance != (Object)null && playerId == LocalClient.instance.myId)
		{
			return AccessoryState.Value(effect);
		}
		if (!Players.TryGetValue(playerId, out var value))
		{
			return 0f;
		}
		ReplayableAccessory replayableAccessory = AccessoryRegistry.FindDefinition(value.Necklace);
		if (replayableAccessory == null || replayableAccessory.Effect != effect)
		{
			return 0f;
		}
		return replayableAccessory.Value;
	}
}
internal sealed class AccessoryHud : MonoBehaviour
{
	private GUIStyle title;

	private GUIStyle text;

	private void OnGUI()
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		InventoryUI instance = InventoryUI.Instance;
		if (!((Object)(object)instance == (Object)null) && ((Component)instance).gameObject.activeInHierarchy && !((Object)(object)instance.backDrop == (Object)null) && instance.backDrop.activeInHierarchy)
		{
			EnsureStyles();
			float num = 270f;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor((float)Screen.width - num - 24f, 24f, num, 104f);
			GUI.Box(val, GUIContent.none);
			GUI.Label(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 8f, num - 24f, 24f), "PERMANENT ACCESSORIES", title);
			DrawSlot(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 38f, num - 24f, 25f), "Ring", AccessoryState.Ring);
			DrawSlot(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 67f, num - 24f, 25f), "Necklace", AccessoryState.Necklace);
		}
	}

	private void DrawSlot(Rect rect, string slot, string equipped)
	{
		//IL_0000: 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)
		GUI.Box(rect, GUIContent.none);
		GUI.Label(new Rect(((Rect)(ref rect)).x + 8f, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width - 16f, ((Rect)(ref rect)).height - 4f), slot + ": " + (string.IsNullOrEmpty(equipped) ? "Empty — right-click an accessory" : equipped), text);
	}

	private void EnsureStyles()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Expected O, but got Unknown
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Expected O, but got Unknown
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		if (title == null)
		{
			title = new GUIStyle(GUI.skin.label)
			{
				fontSize = 14,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4
			};
			title.normal.textColor = new Color(1f, 0.72f, 0.25f);
			text = new GUIStyle(GUI.skin.label)
			{
				fontSize = 12,
				alignment = (TextAnchor)3
			};
			text.normal.textColor = Color.white;
		}
	}
}
[HarmonyPatch(typeof(ItemManager), "InitAllItems")]
[HarmonyPriority(0)]
internal static class AccessoryItemRegistrationPatch
{
	private static void Postfix(ItemManager __instance)
	{
		AccessoryRegistry.Install(__instance);
	}
}
[HarmonyPatch(typeof(CraftingUI), "Awake")]
internal static class AccessoryCraftingAwakePatch
{
	private static void Postfix(CraftingUI __instance)
	{
		AccessoryRegistry.InjectCrafting(__instance);
	}
}
[HarmonyPatch(typeof(CraftingUI), "Start")]
internal static class AccessoryCraftingStartPatch
{
	private static void Postfix(CraftingUI __instance)
	{
		AccessoryRegistry.InjectCrafting(__instance);
	}
}
[HarmonyPatch(typeof(CraftingUI), "UpdateCraftables")]
internal static class AccessoryCraftingRefreshPatch
{
	private static void Prefix(CraftingUI __instance)
	{
		AccessoryRegistry.InjectCrafting(__instance);
	}
}
[HarmonyPatch(typeof(InventoryCell), "OnPointerDown")]
internal static class PermanentAccessoryEquipPatch
{
	private static bool Prefix(InventoryCell __instance, PointerEventData eventData)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Invalid comparison between Unknown and I4
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)__instance == (Object)null || eventData == null || (int)eventData.button != 1 || (int)__instance.cellType != 0 || (Object)(object)InventoryUI.Instance == (Object)null || InventoryUI.Instance.HoldingItem() || !AccessoryRegistry.TryGet(__instance.currentItem, out var accessory))
		{
			return true;
		}
		if (!AccessoryState.Equip(accessory))
		{
			Notify("Your " + accessory.Slot.ToString().ToLowerInvariant() + " slot is permanent and already occupied.");
			return false;
		}
		__instance.RemoveItem();
		Hotbar instance = Hotbar.Instance;
		if (instance != null)
		{
			instance.UpdateHotbar();
		}
		Notify("Equipped " + accessory.Name + " permanently: " + accessory.EffectText + ".");
		return false;
	}

	private static void Notify(string message)
	{
		ReforgedRuntime.Instance?.Notify(message, 5f);
		try
		{
			ChatBox instance = ChatBox.Instance;
			if (instance != null)
			{
				instance.AppendMessage(-1, "<color=orange>[Accessory]</color> " + message, string.Empty);
			}
		}
		catch
		{
		}
	}
}
internal static class AccessoryDefensePatch
{
	[HarmonyPatch(typeof(PowerupInventory), "GetDefenseMultiplier")]
	[HarmonyPostfix]
	private static void Apply(int[] playerPowerups, ref float __result)
	{
		__result = Mathf.Min(90f, __result + AccessoryState.Value(AccessoryEffect.Defense, playerPowerups));
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetAttackSpeedMultiplier")]
internal static class AccessoryAttackSpeedPatch
{
	[HarmonyPriority(0)]
	private static void Postfix(int[] playerPowerups, ref float __result)
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Invalid comparison between Unknown and I4
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Invalid comparison between Unknown and I4
		__result *= 1f + AccessoryState.Value(AccessoryEffect.Haste, playerPowerups);
		if (playerPowerups == null && (Object)(object)UseInventory.Instance != (Object)null && (Object)(object)Hotbar.Instance?.currentItem != (Object)null)
		{
			InventoryItem currentItem = Hotbar.Instance.currentItem;
			if ((int)currentItem.type != 9 && (int)currentItem.tag != 2)
			{
				float num = (float)AccessTools.Field(typeof(UseInventory), "attackTime").GetValue(UseInventory.Instance);
				bool haste = AccessoryState.Value(AccessoryEffect.Haste) > 0f;
				bool juice = ArtifactBalance.JuiceSpeedMultiplier(PowerupInventory.Instance) > 1.01f;
				__result = Mathf.Min(__result, AccessoryCombatRules.AttacksPerSecond(haste, juice) * Mathf.Max(0.01f, num) / Mathf.Max(0.01f, currentItem.attackSpeed));
			}
		}
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetSpeedMultiplier")]
internal static class AccessoryMovementPatch
{
	private static void Postfix(int[] playerPowerups, ref float __result)
	{
		__result *= 1f + AccessoryState.Value(AccessoryEffect.Swiftness, playerPowerups);
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetLootMultiplier")]
internal static class AccessoryLootPatch
{
	private static void Postfix(int[] playerPowerups, ref float __result)
	{
		if (AccessoryCombatRules.Harvesting)
		{
			__result *= 1f + AccessoryState.Value(AccessoryEffect.Fortune, playerPowerups);
		}
	}
}
[HarmonyPatch(typeof(Server), "InitializeServerPackets")]
internal static class AccessoryServerPacketPatch
{
	private static void Postfix()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		if (Server.PacketHandlers != null)
		{
			Server.PacketHandlers[236] = new PacketHandler(AccessoryNetwork.ReceiveRequest);
		}
	}
}
[HarmonyPatch(typeof(LocalClient), "InitializeClientData")]
internal static class AccessoryClientPacketPatch
{
	private static void Postfix()
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		if (LocalClient.packetHandlers != null)
		{
			LocalClient.packetHandlers[237] = new PacketHandler(AccessoryNetwork.ReceiveSync);
		}
	}
}
[HarmonyPatch(typeof(ServerHandle), "DisconnectPlayer", new Type[] { typeof(int) })]
internal static class AccessoryDisconnectPatch
{
	private static void Postfix(int fromClient)
	{
		AccessoryNetwork.Remove(fromClient);
	}
}
public sealed class AggroController : MonoBehaviour
{
	private enum AggroState
	{
		Idle,
		Chasing,
		Searching,
		Returning
	}

	private Mob _mob;

	private Vector3 _homePosition;

	private Vector3 _lastSeenPosition;

	private int _currentPlayerId = -1;

	private float _lastSeenAt = float.NegativeInfinity;

	private float _farSince = -1f;

	private float _returnStartedAt = float.NegativeInfinity;

	private float _nextBlockingBuildScanAt;

	private Transform _cachedBlockingBuild;

	private int _lineOfSightFrame = -1;

	private int _lineOfSightPlayerId = -1;

	private bool _lineOfSightResult;

	private AggroState _state;

	private bool IsBoss
	{
		get
		{
			if ((Object)(object)_mob != (Object)null && (Object)(object)_mob.mobType != (Object)null)
			{
				return _mob.mobType.boss;
			}
			return false;
		}
	}

	private bool IsRanged
	{
		get
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			if ((Object)(object)_mob != (Object)null && (Object)(object)_mob.mobType != (Object)null)
			{
				if (!_mob.mobType.ranged)
				{
					return (int)_mob.mobType.behaviour == 2;
				}
				return true;
			}
			return false;
		}
	}

	private void Awake()
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		_mob = ((Component)this).GetComponent<Mob>();
		_homePosition = ((Component)this).transform.position;
		_lastSeenPosition = _homePosition;
		_state = AggroState.Idle;
	}

	internal void MarkDamagedBy(int playerId)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		if (TryGetLivingPlayer(playerId, out var player))
		{
			_currentPlayerId = playerId;
			_lastSeenPosition = ((Component)player).transform.position;
			_lastSeenAt = Time.time;
			_farSince = -1f;
			_state = AggroState.Chasing;
			SetPlayerTarget(player);
		}
	}

	internal Vector3 GetNextDestination()
	{
		//IL_0021: 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_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_mob == (Object)null || (Object)(object)_mob.mobType == (Object)null)
		{
			return Vector3.zero;
		}
		if ((_mob.IsAttacking() && _mob.stopOnAttack) || _mob.knocked || !_mob.ready)
		{
			return Vector3.zero;
		}
		return (Vector3)(_state switch
		{
			AggroState.Idle => TickIdle(), 
			AggroState.Chasing => TickChasing(), 
			AggroState.Searching => TickSearching(), 
			AggroState.Returning => TickReturning(), 
			_ => Vector3.zero, 
		});
	}

	internal float GetNextThinkDelay()
	{
		float num;
		switch (_state)
		{
		case AggroState.Chasing:
		case AggroState.Searching:
			num = 0.5f;
			break;
		case AggroState.Returning:
			num = 1f;
			break;
		default:
			num = 0.75f;
			break;
		}
		return num + (float)Mathf.Abs(((Object)this).GetInstanceID() % 23) * 0.011f;
	}

	private Vector3 TickIdle()
	{
		//IL_002b: 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)
		PlayerManager val = FindClosestVisiblePlayer(AcquireDistance());
		if ((Object)(object)val == (Object)null)
		{
			ClearTarget();
			return Vector3.zero;
		}
		BeginChasing(val);
		return DestinationFor(val);
	}

	private Vector3 TickChasing()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		if (!TryGetLivingPlayer(_currentPlayerId, out var player))
		{
			BeginReturning();
			return _homePosition;
		}
		float num = Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position);
		float num2 = Vector3.Distance(_homePosition, ((Component)this).transform.position);
		if (num > DisengageDistance() || num2 > HomeLeashDistance())
		{
			if (_farSince < 0f)
			{
				_farSince = Time.time;
			}
			else if (Time.time - _farSince >= Plugin.Settings.FarTargetGraceSeconds.Value)
			{
				BeginReturning();
				return _homePosition;
			}
		}
		else
		{
			_farSince = -1f;
		}
		if (HasLineOfSight(player) || num <= Plugin.Settings.ProximityAcquireDistance.Value)
		{
			_lastSeenPosition = ((Component)player).transform.position;
			_lastSeenAt = Time.time;
			SetPlayerTarget(player);
			return DestinationFor(player);
		}
		_state = AggroState.Searching;
		ClearTarget();
		return _lastSeenPosition;
	}

	private Vector3 TickSearching()
	{
		//IL_0016: 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_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		if (TryGetLivingPlayer(_currentPlayerId, out var player))
		{
			float num = Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position);
			if (num <= AcquireDistance() && (num <= Plugin.Settings.ProximityAcquireDistance.Value || HasLineOfSight(player)))
			{
				BeginChasing(player);
				return DestinationFor(player);
			}
		}
		if (Time.time - _lastSeenAt <= LostSightSeconds())
		{
			ClearTarget();
			return _lastSeenPosition;
		}
		BeginReturning();
		return _homePosition;
	}

	private Vector3 TickReturning()
	{
		//IL_0006: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: 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)
		if (Vector3.Distance(((Component)this).transform.position, _homePosition) <= Plugin.Settings.ReturnArrivalDistance.Value)
		{
			_state = AggroState.Idle;
			_currentPlayerId = -1;
			_farSince = -1f;
			ClearTarget();
			if ((Object)(object)_mob.agent != (Object)null && _mob.agent.isOnNavMesh)
			{
				_mob.agent.ResetPath();
			}
			return Vector3.zero;
		}
		if (Time.time - _returnStartedAt >= Plugin.Settings.ReturnReacquireCooldown.Value)
		{
			PlayerManager val = FindClosestVisiblePlayer(AcquireDistance());
			if ((Object)(object)val != (Object)null && Vector3.Distance(_homePosition, ((Component)val).transform.position) <= HomeLeashDistance())
			{
				BeginChasing(val);
				return DestinationFor(val);
			}
		}
		ClearTarget();
		return _homePosition;
	}

	private void BeginChasing(PlayerManager player)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		_state = AggroState.Chasing;
		_currentPlayerId = player.id;
		_lastSeenPosition = ((Component)player).transform.position;
		_lastSeenAt = Time.time;
		_farSince = -1f;
		SetPlayerTarget(player);
	}

	private void BeginReturning()
	{
		_state = AggroState.Returning;
		_returnStartedAt = Time.time;
		_currentPlayerId = -1;
		_farSince = -1f;
		ClearTarget();
	}

	private Vector3 DestinationFor(PlayerManager player)
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: 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)
		if (Plugin.Settings.AttackBlockingBuildings.Value && TryFindBlockingBuild(player, out var result))
		{
			_mob.target = result;
			_mob.targetPlayerId = -1;
			return result.position;
		}
		SetPlayerTarget(player);
		float num = Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position);
		if (num <= 12f || _mob.mobType.followPlayerAccuracy >= 0.999f)
		{
			return ((Component)player).transform.position;
		}
		Vector3 val = default(Vector3);
		((Vector3)(ref val))..ctor(Random.Range(-1f, 1f), 0f, Random.Range(-1f, 1f));
		val *= num * (1f - _mob.mobType.followPlayerAccuracy);
		return ((Component)player).transform.position + val;
	}

	private bool TryFindBlockingBuild(PlayerManager player, out Transform result)
	{
		//IL_0064: 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_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		result = null;
		if (_mob.mobType.ignoreBuilds || HasLineOfSight(player) || (Object)(object)ResourceManager.Instance == (Object)null || ResourceManager.Instance.builds == null)
		{
			_cachedBlockingBuild = null;
			return false;
		}
		float value = Plugin.Settings.BuildingAttackDistance.Value;
		if ((Object)(object)_cachedBlockingBuild != (Object)null)
		{
			Vector3 val = _cachedBlockingBuild.position - ((Component)this).transform.position;
			if (((Vector3)(ref val)).sqrMagnitude <= value * value)
			{
				result = _cachedBlockingBuild;
				return true;
			}
			_cachedBlockingBuild = null;
		}
		if (Time.time < _nextBlockingBuildScanAt)
		{
			return false;
		}
		_nextBlockingBuildScanAt = Time.time + 2.1f + (float)Mathf.Abs(((Object)this).GetInstanceID() % 29) * 0.037f;
		float num = value;
		Vector3 val2 = ((Component)player).transform.position - ((Component)this).transform.position;
		Vector3 normalized = ((Vector3)(ref val2)).normalized;
		foreach (KeyValuePair<int, GameObject> build in ResourceManager.Instance.builds)
		{
			GameObject value2 = build.Value;
			if (!((Object)(object)value2 == (Object)null))
			{
				Vector3 val3 = value2.transform.position - ((Component)this).transform.position;
				float magnitude = ((Vector3)(ref val3)).magnitude;
				if (!(magnitude >= num) && !(Vector3.Dot(normalized, ((Vector3)(ref val3)).normalized) < 0.35f))
				{
					num = magnitude;
					result = value2.transform;
				}
			}
		}
		_cachedBlockingBuild = result;
		return (Object)(object)result != (Object)null;
	}

	private PlayerManager FindClosestVisiblePlayer(float maxDistance)
	{
		//IL_0046: 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)
		if (GameManager.players == null)
		{
			return null;
		}
		PlayerManager result = null;
		float num = maxDistance;
		foreach (PlayerManager value in GameManager.players.Values)
		{
			if (!((Object)(object)value == (Object)null) && !value.dead && !value.disconnected)
			{
				float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)value).transform.position);
				if (!(num2 >= num) && (!(num2 > Plugin.Settings.ProximityAcquireDistance.Value) || HasLineOfSight(value)))
				{
					result = value;
					num = num2;
				}
			}
		}
		return result;
	}

	private bool HasLineOfSight(PlayerManager player)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null)
		{
			return false;
		}
		if (CaveNetwork.IsInside(((Component)this).transform.position) && CaveNetwork.IsInside(((Component)player).transform.position))
		{
			return true;
		}
		if (_lineOfSightFrame == Time.frameCount && _lineOfSightPlayerId == player.id)
		{
			return _lineOfSightResult;
		}
		Vector3 val = ((Component)this).transform.position + Vector3.up * 1.2f;
		Vector3 val2 = ((Component)player).transform.position + Vector3.up * 1.2f - val;
		float magnitude = ((Vector3)(ref val2)).magnitude;
		if (magnitude <= 0.01f)
		{
			return CacheLineOfSight(player.id, result: true);
		}
		int num = -5;
		if ((Object)(object)MobManager.Instance != (Object)null && ((LayerMask)(ref MobManager.Instance.whatIsRaycastable)).value != 0)
		{
			num = ((LayerMask)(ref MobManager.Instance.whatIsRaycastable)).value;
		}
		RaycastHit val3 = default(RaycastHit);
		if (!Physics.Raycast(val, ((Vector3)(ref val2)).normalized, ref val3, magnitude + 0.5f, num, (QueryTriggerInteraction)1))
		{
			return CacheLineOfSight(player.id, result: true);
		}
		PlayerManager componentInParent = ((Component)((RaycastHit)(ref val3)).transform).GetComponentInParent<PlayerManager>();
		return CacheLineOfSight(player.id, (Object)(object)componentInParent == (Object)(object)player);
	}

	private bool CacheLineOfSight(int playerId, bool result)
	{
		_lineOfSightFrame = Time.frameCount;
		_lineOfSightPlayerId = playerId;
		_lineOfSightResult = result;
		return result;
	}

	private bool TryGetLivingPlayer(int playerId, out PlayerManager player)
	{
		player = null;
		if (playerId < 0 || GameManager.players == null || !GameManager.players.TryGetValue(playerId, out player))
		{
			return false;
		}
		if ((Object)(object)player != (Object)null && !player.dead)
		{
			return !player.disconnected;
		}
		return false;
	}

	private void SetPlayerTarget(PlayerManager player)
	{
		_mob.target = ((Component)player).transform;
		_mob.targetPlayerId = player.id;
	}

	private void ClearTarget()
	{
		_mob.target = null;
		_mob.targetPlayerId = -1;
	}

	private float AcquireDistance()
	{
		if (IsBoss)
		{
			return Plugin.Settings.BossAcquireDistance.Value;
		}
		if (!IsRanged)
		{
			return Plugin.Settings.MeleeAcquireDistance.Value;
		}
		return Plugin.Settings.RangedAcquireDistance.Value;
	}

	private float DisengageDistance()
	{
		if (IsBoss)
		{
			return Plugin.Settings.BossDisengageDistance.Value;
		}
		if (!IsRanged)
		{
			return Plugin.Settings.MeleeDisengageDistance.Value;
		}
		return Plugin.Settings.RangedDisengageDistance.Value;
	}

	private float HomeLeashDistance()
	{
		if (IsBoss)
		{
			return Plugin.Settings.BossHomeLeash.Value;
		}
		if (!IsRanged)
		{
			return Plugin.Settings.MeleeHomeLeash.Value;
		}
		return Plugin.Settings.RangedHomeLeash.Value;
	}

	private float LostSightSeconds()
	{
		if (IsBoss)
		{
			return Plugin.Settings.BossLostSightSeconds.Value;
		}
		if (!IsRanged)
		{
			return Plugin.Settings.MeleeLostSightSeconds.Value;
		}
		return Plugin.Settings.RangedLostSightSeconds.Value;
	}
}
[HarmonyPatch(typeof(MobServerEnemy), "FindNextPosition")]
internal static class MobServerEnemyFindNextPositionPatch
{
	private static bool Prefix(MobServerEnemy __instance, ref Vector3 __result)
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)__instance == (Object)null || Plugin.Settings == null || !Plugin.Settings.EnableAggro.Value)
		{
			return true;
		}
		AggroController aggroController = ((Component)__instance).GetComponent<AggroController>();
		if ((Object)(object)aggroController == (Object)null)
		{
			aggroController = ((Component)__instance).gameObject.AddComponent<AggroController>();
		}
		((MonoBehaviour)__instance).Invoke("SyncFindNextPosition", aggroController.GetNextThinkDelay());
		__result = aggroController.GetNextDestination();
		return false;
	}
}
[HarmonyPatch(typeof(Hitable), "Damage")]
internal static class HitableDamageAggroPatch
{
	private static void Prefix(Hitable __instance, int newHp, int fromClient)
	{
		if ((Object)(object)__instance == (Object)null || Plugin.Settings == null || !Plugin.Settings.EnableAggro.Value || !LocalClient.serverOwner || newHp >= __instance.hp)
		{
			return;
		}
		HitableMob val = (HitableMob)(object)((__instance is HitableMob) ? __instance : null);
		if (!((Object)(object)val == (Object)null))
		{
			AggroController aggroController = ((Component)val).GetComponent<AggroController>();
			if ((Object)(object)aggroController == (Object)null)
			{
				aggroController = ((Component)val).gameObject.AddComponent<AggroController>();
			}
			aggroController.MarkDamagedBy(fromClient);
		}
	}
}
[HarmonyPatch(typeof(Mob), "SetTarget")]
internal static class MobSetTargetPatch
{
	private static bool Prefix(Mob __instance, int targetId)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return false;
		}
		if ((Object)(object)__instance.agent != (Object)null && __instance.agent.isOnNavMesh && targetId >= 0 && GameManager.players != null && GameManager.players.TryGetValue(targetId, out var value) && (Object)(object)value != (Object)null)
		{
			__instance.targetPlayerId = targetId;
			__instance.target = ((Component)value).transform;
			return false;
		}
		__instance.targetPlayerId = -1;
		__instance.target = null;
		return false;
	}
}
internal static class ArmorAuditMode
{
	internal static readonly bool Enabled;

	internal static readonly bool AutoExit;

	internal static readonly string OutputDirectory;

	internal static readonly int Seed;

	static ArmorAuditMode()
	{
		string[] commandLineArgs = Environment.GetCommandLineArgs();
		Enabled = Array.Exists(commandLineArgs, (string value) => string.Equals(value, "-mr-armor-audit", StringComparison.OrdinalIgnoreCase));
		AutoExit = Array.Exists(commandLineArgs, (string value) => string.Equals(value, "-mr-armor-audit-exit", StringComparison.OrdinalIgnoreCase));
		OutputDirectory = FindValue(commandLineArgs, "-mr-armor-audit-output=");
		if (string.IsNullOrWhiteSpace(OutputDirectory))
		{
			OutputDirectory = Path.Combine(Path.GetTempPath(), "MuckReplayable-ArmorAudit");
		}
		if (!int.TryParse(FindValue(commandLineArgs, "-mr-armor-audit-seed="), out var result) || result == 0)
		{
			result = 948271;
		}
		Seed = result;
	}

	internal static void WriteFailure(string message)
	{
		if (!Enabled)
		{
			return;
		}
		try
		{
			Directory.CreateDirectory(OutputDirectory);
			File.WriteAllText(Path.Combine(OutputDirectory, "audit-failed.txt"), message ?? "Unknown armor audit failure");
		}
		catch
		{
		}
	}

	private static string FindValue(string[] args, string prefix)
	{
		return Array.Find(args, (string argument) => argument?.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) ?? false)?.Substring(prefix.Length).Trim(new char[1] { '"' });
	}
}
internal static class ArtifactBalance
{
	private static readonly FieldInfo JuiceSpeed = AccessTools.Field(typeof(PowerupInventory), "juiceSpeed");

	internal static int Stacks(int[] powerups, string name)
	{
		if (powerups == null && (Object)(object)PowerupInventory.Instance != (Object)null)
		{
			powerups = (int[])AccessTools.Field(typeof(PowerupInventory), "powerups")?.GetValue(PowerupInventory.Instance);
		}
		if (powerups == null || ItemManager.Instance?.stringToPowerupId == null || !ItemManager.Instance.stringToPowerupId.TryGetValue(name, out var value) || value < 0 || value >= powerups.Length)
		{
			return 0;
		}
		return Mathf.Max(0, powerups[value]);
	}

	internal static float Curve(int stacks, float speed, float maximum)
	{
		stacks = Mathf.Max(0, stacks);
		float num = PowerupInventory.CumulativeDistribution(Mathf.Min(stacks, 12), speed, maximum);
		if (stacks <= 12)
		{
			return num;
		}
		float num2 = PowerupInventory.CumulativeDistribution(1, speed, maximum);
		return num + (float)(stacks - 12) * num2 * 0.18f;
	}

	internal static float Defense(int stacks)
	{
		return PowerupInventory.CumulativeDistribution(Mathf.Max(0, stacks), 0.1f, 40f);
	}

	internal static float Dumbbell(int stacks)
	{
		return 1f + (float)Mathf.Max(0, stacks) * 0.1f;
	}

	internal static float Berserk(int stacks, float missingHp)
	{
		return 1f + (float)Mathf.Max(0, stacks) * Mathf.Clamp01(missingHp);
	}

	internal static float Stamina(int stacks)
	{
		return 1f + (float)Mathf.Max(0, stacks) * 0.15f;
	}

	internal static float Healing(int stacks)
	{
		return Mathf.Min(0.2f, (float)Mathf.Max(0, stacks) * 0.005f);
	}

	internal static float Resource(int stacks)
	{
		return 1f + PowerupInventory.CumulativeDistribution(Mathf.Max(0, stacks), 0.3f, 4f);
	}

	internal static float Loot(int stacks)
	{
		if (stacks > 0)
		{
			return 1f + Mathf.Min(1f, 0.2f + (float)Mathf.Max(0, stacks - 1) * 0.1f);
		}
		return 1f;
	}

	internal static float AttackSpeed(int stacks)
	{
		return 1f + (float)Mathf.Max(0, stacks) * 0.05f;
	}

	internal static float Hunger(int stacks)
	{
		return 1f - PowerupInventory.CumulativeDistribution(Mathf.Max(0, stacks), 0.2f, 0.5f);
	}

	internal static float Juice(int stacks)
	{
		if (stacks > 0)
		{
			return 1f + Mathf.Min(1.5f, 0.5f + (float)(stacks - 1) * 0.1f);
		}
		return 1f;
	}

	internal static float JuiceDuration(int stacks)
	{
		if (stacks > 0)
		{
			return Mathf.Min(3f, 2f + (float)(stacks - 1) * 0.1f);
		}
		return 0f;
	}

	internal static float Robin(int stacks)
	{
		return 1f + PowerupInventory.CumulativeDistribution(Mathf.Max(0, stacks), 0.06f, 2f);
	}

	internal static float Speed(int stacks)
	{
		return 1f + (float)Mathf.Max(0, stacks) * 0.05f;
	}

	internal static float Adrenaline(int stacks)
	{
		if (stacks > 0)
		{
			return Mathf.Min(3f, 2f + (float)stacks * 0.1f);
		}
		return 1f;
	}

	internal static float Crit(int stacks)
	{
		return 0.14f + (float)Mathf.Max(0, stacks) * 0.1f;
	}

	internal static float Jump(int stacks)
	{
		return 1f + PowerupInventory.CumulativeDistribution(Mathf.Max(0, stacks), 0.075f, 2.5f);
	}

	internal static float Wings(int stacks)
	{
		if (stacks > 0)
		{
			return 1f + PowerupInventory.CumulativeDistribution(stacks, 0.45f, 2.5f);
		}
		return 1f;
	}

	internal static float Lifesteal(int stacks)
	{
		return Mathf.Min(0.8f, Curve(stacks, 0.11f, 0.35f));
	}

	internal static float KnockbackChance(int stacks)
	{
		return PowerupInventory.CumulativeDistribution(Mathf.Max(0, stacks), 0.15f, 1f);
	}

	internal static float SniperChance(int stacks)
	{
		return Mathf.Min(0.1f, (float)Mathf.Max(0, stacks) * 0.01f);
	}

	internal static float SniperDamage(int stacks)
	{
		if (stacks > 0)
		{
			return 5f;
		}
		return 1f;
	}

	internal static float LightningChance(int stacks)
	{
		return Mathf.Min(0.2f, (float)Mathf.Max(0, stacks) * 0.02f);
	}

	internal static float LightningDamage(int stacks)
	{
		if (stacks > 0)
		{
			return Mathf.Min(3f, 2f + (float)(stacks - 1) * 0.1f);
		}
		return -1f;
	}

	internal static float Enforcer(int stacks, float speed)
	{
		if (stacks > 0)
		{
			return 1f + PowerupInventory.CumulativeDistribution(stacks, 0.4f, 2f) * Mathf.Clamp01(Mathf.Max(0f, speed) / 20f);
		}
		return 1f;
	}

	internal static int BonusHp(int stacks)
	{
		return Mathf.Clamp(stacks, 0, 50) * 10;
	}

	internal static int BonusShield(int stacks)
	{
		return Mathf.Clamp(stacks, 0, 50) * 10;
	}

	internal static int MaxStacks(string name)
	{
		switch (name)
		{
		case "Blue Pill":
		case "Red Pill":
			return 50;
		case "Broccoli":
			return 40;
		case "Sneaker":
			return 20;
		case "Orange Juice":
			return 40;
		case "Juice":
			return 11;
		case "Piggybank":
			return 9;
		case "Sniper Scope":
			return 10;
		case "Knuts Hammer":
		case "Knut's Hammer":
			return 10;
		default:
			return -1;
		}
	}

	internal static float JuiceSpeedMultiplier(PowerupInventory instance)
	{
		if (!((Object)(object)instance != (Object)null) || !(JuiceSpeed != null))
		{
			return 1f;
		}
		return Mathf.Max(1f, (float)JuiceSpeed.GetValue(instance));
	}

	internal static bool StartJuice(PowerupInventory instance)
	{
		if ((Object)(object)instance == (Object)null)
		{
			return false;
		}
		int num = Stacks(null, "Juice");
		if (num <= 0)
		{
			return false;
		}
		JuiceSpeed?.SetValue(instance, Juice(num));
		((MonoBehaviour)instance).CancelInvoke("StopJuice");
		((MonoBehaviour)instance).Invoke("StopJuice", JuiceDuration(num));
		return true;
	}

	internal static float LowHpRatio()
	{
		PlayerStatus instance = PlayerStatus.Instance;
		if (!((Object)(object)instance == (Object)null) && instance.maxHp > 0)
		{
			return ((float)instance.maxHp - instance.hp) / (float)instance.maxHp;
		}
		return 0f;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetDefenseMultiplier")]
internal static class BalancedDefenseArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		float num = ArtifactBalance.Defense(ArtifactBalance.Stacks(playerPowerups, "Danis Milk")) + MythicalArtifactService.AuxiliaryDefense(playerPowerups);
		__result = Mathf.Min(MythicalArtifactService.DefenseCap(playerPowerups), num);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetStrengthMultiplier")]
internal static class BalancedStrengthArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		int num = ArtifactBalance.Stacks(playerPowerups, "Dumbbell");
		int num2 = MythicalArtifactService.Stacks(playerPowerups, "Dumbbell") + ((AccessoryState.Value(AccessoryEffect.Strength, playerPowerups) > 0f) ? 1 : 0);
		float num3 = ((num2 > 0) ? (1f + (float)num * 0.125f * Mathf.Pow(2f, (float)num2)) : ArtifactBalance.Dumbbell(num));
		__result = 1.3f * num3 * ArtifactBalance.Berserk(ArtifactBalance.Stacks(playerPowerups, "Berserk"), ArtifactBalance.LowHpRatio());
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetAttackSpeedMultiplier")]
internal static class BalancedAttackSpeedArtifactPatch
{
	private static bool Prefix(PowerupInventory __instance, int[] playerPowerups, ref float __result)
	{
		float num = (((Object)(object)PlayerStatus.Instance != (Object)null && PlayerStatus.Instance.adrenalineBoost) ? ArtifactBalance.Adrenaline(ArtifactBalance.Stacks(playerPowerups, "Adrenaline")) : 1f);
		float num2 = ArtifactBalance.AttackSpeed(ArtifactBalance.Stacks(playerPowerups, "Orange Juice")) * MythicalArtifactService.AttackSpeedBonus(playerPowerups) * num * ArtifactBalance.JuiceSpeedMultiplier(__instance) * MythicalArtifactService.AuxiliaryAttackSpeed(playerPowerups);
		__result = num2;
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetStaminaMultiplier")]
internal static class BalancedStaminaArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		float num = (((Object)(object)PlayerStatus.Instance != (Object)null && PlayerStatus.Instance.adrenalineBoost) ? ArtifactBalance.Adrenaline(ArtifactBalance.Stacks(playerPowerups, "Adrenaline")) : 1f);
		__result = ArtifactBalance.Stamina(ArtifactBalance.Stacks(playerPowerups, "Peanut Butter")) * num * MythicalArtifactService.AuxiliaryStamina(playerPowerups);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetHealingMultiplier")]
internal static class BalancedHealingArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Healing(ArtifactBalance.Stacks(playerPowerups, "Broccoli")) + MythicalArtifactService.AuxiliaryHealing(playerPowerups) - 1f;
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetResourceMultiplier")]
internal static class BalancedResourceArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Invalid comparison between Unknown and I4
		__result = ArtifactBalance.Resource(ArtifactBalance.Stacks(playerPowerups, "Checkered Shirt")) * MythicalArtifactService.AuxiliaryEconomy(playerPowerups);
		if (WorldModifierState.Active.ResourceBounty)
		{
			__result *= 2f;
		}
		if (GameManager.gameSettings != null && (int)GameManager.gameSettings.gameMode == 1)
		{
			__result += 1.25f;
		}
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetLootMultiplier")]
internal static class BalancedLootArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Loot(ArtifactBalance.Stacks(playerPowerups, "Piggybank")) * MythicalArtifactService.AuxiliaryEconomy(playerPowerups);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetSniperScopeMultiplier")]
internal static class BalancedSniperArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		int num = ArtifactBalance.Stacks(playerPowerups, "Sniper Scope");
		__result = ((num > 0 && Random.value < ArtifactBalance.SniperChance(num)) ? ArtifactBalance.SniperDamage(num) : 1f);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetSniperScopeDamageMultiplier")]
internal static class BalancedSniperDamageArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.SniperDamage(ArtifactBalance.Stacks(playerPowerups, "Sniper Scope"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetLightningMultiplier")]
internal static class BalancedLightningArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		int num = ArtifactBalance.Stacks(playerPowerups, "Knuts Hammer");
		__result = ((num > 0 && Random.value < ArtifactBalance.LightningChance(num)) ? ArtifactBalance.LightningDamage(num) : (-1f));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetHpMultiplier")]
internal static class BalancedHpArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref int __result)
	{
		__result = ArtifactBalance.BonusHp(ArtifactBalance.Stacks(playerPowerups, "Red Pill")) + MythicalArtifactService.AuxiliaryMaxHp(playerPowerups);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetShield")]
internal static class BalancedShieldArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref int __result)
	{
		__result = ArtifactBalance.BonusShield(ArtifactBalance.Stacks(playerPowerups, "Blue Pill"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetHungerMultiplier")]
internal static class BalancedHungerArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Hunger(ArtifactBalance.Stacks(playerPowerups, "Spooo Bean"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetJuiceMultiplier")]
internal static class BalancedJuiceArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Juice(ArtifactBalance.Stacks(playerPowerups, "Juice"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "StartJuice")]
internal static class BalancedJuiceDurationPatch
{
	private static bool Prefix(PowerupInventory __instance)
	{
		ArtifactBalance.StartJuice(__instance);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetRobinMultiplier")]
internal static class BalancedRobinArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Robin(ArtifactBalance.Stacks(playerPowerups, "Robin Hood Hat"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetEnforcerMultiplier")]
internal static class BalancedEnforcerArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, float speed, ref float __result)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		float num;
		if (!(speed >= 0f))
		{
			PlayerMovement instance = PlayerMovement.Instance;
			if (instance == null)
			{
				num = 0f;
			}
			else
			{
				Vector3 velocity = instance.GetVelocity();
				num = ((Vector3)(ref velocity)).magnitude;
			}
		}
		else
		{
			num = speed;
		}
		float speed2 = num;
		__result = ArtifactBalance.Enforcer(ArtifactBalance.Stacks(playerPowerups, "Enforcer"), speed2);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetSpeedMultiplier")]
internal static class BalancedSpeedArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		float num = (((Object)(object)PlayerStatus.Instance != (Object)null && PlayerStatus.Instance.adrenalineBoost) ? ArtifactBalance.Adrenaline(ArtifactBalance.Stacks(playerPowerups, "Adrenaline")) : 1f);
		float num2 = PlayerStatus.Instance?.currentSpeedArmorMultiplier ?? 1f;
		float num3 = ArtifactBalance.Speed(ArtifactBalance.Stacks(playerPowerups, "Sneaker")) * num * num2 * MythicalArtifactService.AuxiliaryMoveSpeed(playerPowerups);
		MythicalArtifactService.Stacks(playerPowerups, "Sneaker");
		__result = Mathf.Min(2f, num3);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetAdrenalineBoost")]
internal static class BalancedAdrenalineArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Adrenaline(ArtifactBalance.Stacks(playerPowerups, "Adrenaline"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetCritChance")]
internal static class BalancedCritArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		float num = ArtifactBalance.Crit(ArtifactBalance.Stacks(playerPowerups, "Horseshoe")) + MythicalArtifactService.CritBonus(playerPowerups);
		__result = Mathf.Min(MythicalArtifactService.CritCap(playerPowerups), num);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetJumpMultiplier")]
internal static class BalancedJumpArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Jump(ArtifactBalance.Stacks(playerPowerups, "Jetpack"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetExtraJumps")]
internal static class BalancedFrogArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref int __result)
	{
		__result = ArtifactBalance.Stacks(playerPowerups, "Janniks Frog");
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetFallWingsMultiplier")]
internal static class BalancedWingsArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Wings(ArtifactBalance.Stacks(playerPowerups, "Wings of Glory"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetKnockbackMultiplier")]
internal static class BalancedBulldozerArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ((Random.value < ArtifactBalance.KnockbackChance(ArtifactBalance.Stacks(playerPowerups, "Bulldozer"))) ? 1f : 0f);
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetLifestealMultiplier")]
internal static class BalancedLifestealArtifactPatch
{
	private static bool Prefix(int[] playerPowerups, ref float __result)
	{
		__result = ArtifactBalance.Lifesteal(ArtifactBalance.Stacks(playerPowerups, "Crimson Dagger"));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetMaxDraculaStacks")]
internal static class BalancedDraculaCapPatch
{
	private static bool Prefix(ref int __result)
	{
		__result = (MythicalArtifactService.HasFang(null) ? int.MaxValue : (ArtifactBalance.Stacks(null, "Dracula") * 25));
		return false;
	}
}
[HarmonyPatch(typeof(PowerupInventory), "GetHpIncreasePerKill")]
internal static class DraculaFangHealingPatch
{
	private static bool Prefix(int[] playerPowerups, ref int __result)
	{
		int num = ArtifactBalance.Stacks(playerPowerups, "Dracula");
		__result = (MythicalArtifactService.HasFang(playerPowerups) ? Mathf.CeilToInt((float)num * 1.5f) : num);
		return false;
	}
}
internal sealed class ArtifactOffer
{
	internal int ChestId;

	internal int PlayerId;

	internal int[] Choices;

	internal bool Mythical;

	internal float ExpiresAt;
}
internal static class ArtifactChoiceService
{
	private sealed class DeterministicRoll
	{
		private uint state;

		internal DeterministicRoll(int seed)
		{
			state = ((seed == 0) ? 2738958700u : ((uint)seed));
		}

		internal uint Next()
		{
			state ^= state << 13;
			state ^= state >> 17;
			state ^= state << 5;
			return state;
		}

		internal int Range(int max)
		{
			if (max > 1)
			{
				return (int)(Next() % (uint)max);
			}
			return 0;
		}

		internal float NextFloat()
		{
			return (float)(Next() & 0xFFFFFF) / 16777216f;
		}
	}

	internal const int ChoicePacketId = 240;

	private static readonly Dictionary<long, ArtifactOffer> ServerOffers = new Dictionary<long, ArtifactOffer>();

	private static readonly MethodInfo SendTcp = AccessTools.Method(typeof(ClientSend), "SendTCPData", (Type[])null, (Type[])null);

	private static readonly FieldInfo PowerupsField = AccessTools.Field(typeof(PowerupInventory), "powerups");

	internal static int[] GenerateChoices(LootContainerInteract chest, int playerId = -1)
	{
		if ((Object)(object)chest == (Object)null || (Object)(object)ItemManager.Instance == (Object)null)
		{
			return Array.Empty<int>();
		}
		int[] array = (MythicalArtifactService.IsMythicalChest(chest) ? GenerateMythicalChoices(chest.GetId(), playerId) : GenerateChoices(chest.GetId(), chest.white, chest.blue, chest.gold, playerId));
		if (chest.testPowerup && (Object)(object)chest.powerupToTest != (Object)null && array.Length != 0 && ItemManager.Instance.allPowerups != null && ItemManager.Instance.allPowerups.ContainsKey(chest.powerupToTest.id))
		{
			int id = chest.powerupToTest.id;
			if (IsAtCap(id, playerId))
			{
				return array;
			}
			int num = Array.IndexOf(array, id);
			if (num > 0)
			{
				array[num] = array[0];
			}
			array[0] = id;
		}
		return array;
	}

	private static int[] GenerateMythicalChoices(int chestId, int playerId)
	{
		List<int> list = (from id in MythicalArtifactService.GetMythicalChoiceIds()
			where !IsAtCap(id, playerId)
			select id).ToList();
		if (list == null || list.Count == 0)
		{
			return Array.Empty<int>();
		}
		DeterministicRoll deterministicRoll = new DeterministicRoll(GameManager.GetSeed() * 16777619 + chestId * 486187739 + 1597463007);
		List<int> list2 = new List<int>(Mathf.Min(3, list.Count));
		while (list2.Count < Mathf.Min(3, list.Count))
		{
			int item = list[deterministicRoll.Range(list.Count)];
			if (!list2.Contains(item))
			{
				list2.Add(item);
			}
		}
		return list2.ToArray();
	}

	internal static int[] GenerateChoices(int chestId, float white, float blue, float gold, int playerId = -1)
	{
		Dictionary<int, Powerup> all = ItemManager.Instance?.allPowerups;
		if (all == null)
		{
			return Array.Empty<int>();
		}
		List<int> list = (from pair in all
			where (Object)(object)pair.Value != (Object)null && !IsAtCap(pair.Key, playerId)
			select pair.Key into value
			orderby value
			select value).ToList();
		if (list.Count == 0)
		{
			return Array.Empty<int>();
		}
		List<int> white2 = list.Where((int id) => (int)all[id].tier == 0).ToList();
		List<int> blue2 = list.Where((int id) => (int)all[id].tier == 1).ToList();
		List<int> orange = list.Where((int id) => (int)all[id].tier == 2).ToList();
		DeterministicRoll deterministicRoll = new DeterministicRoll(GameManager.GetSeed() * 486187739 + chestId * 16777619 + 219671);
		List<int> list2 = new List<int>(Mathf.Min(3, list.Count));
		for (int num = 0; num < Mathf.Min(3, list.Count); num++)
		{
			int num2 = -1;
			for (int num3 = 0; num3 < 20; num3++)
			{
				if (num2 >= 0 && !list2.Contains(num2))
				{
					break;
				}
				List<int> list3 = PickTier(deterministicRoll, white2, blue2, orange, white, blue, gold);
				if (list3.Count > 0)
				{
					num2 = list3[deterministicRoll.Range(list3.Count)];
				}
			}
			if (num2 < 0 || list2.Contains(num2))
			{
				num2 = -1;
				foreach (int item in list)
				{
					if (!list2.Contains(item))
					{
						num2 = item;
						break;
					}
				}
			}
			if (num2 < 0)
			{
				break;
			}
			list2.Add(num2);
		}
		return list2.ToArray();
	}

	private static List<int> PickTier(DeterministicRoll random, List<int> white, List<int> blue, List<int> orange, float whiteWeight, float blueWeight, float orangeWeight)
	{
		whiteWeight = ((white.Count > 0) ? Mathf.Max(0f, whiteWeight) : 0f);
		blueWeight = ((blue.Count > 0) ? Mathf.Max(0f, blueWeight) : 0f);
		orangeWeight = ((orange.Count > 0) ? Mathf.Max(0f, orangeWeight) : 0f);
		float num = whiteWeight + blueWeight + orangeWeight;
		if (num <= 0f)
		{
			whiteWeight = ((white.Count > 0) ? 1f : 0f);
			blueWeight = ((blue.Count > 0) ? 1f : 0f);
			orangeWeight = ((orange.Count > 0) ? 1f : 0f);
			num = whiteWeight + blueWeight + orangeWeight;
		}
		float num2 = random.NextFloat() * num;
		if (num2 < whiteWeight)
		{
			return white;
		}
		if (num2 < whiteWeight + blueWeight)
		{
			return blue;
		}
		return orange;
	}

	internal static bool RegisterServerOffer(LootContainerInteract chest, int fromClient)
	{
		if ((Object)(object)chest == (Object)null || fromClient < 0)
		{
			return false;
		}
		int[] array = GenerateChoices(chest, fromClient);
		if (array.Length == 0)
		{
			return false;
		}
		long[] array2 = (from pair in ServerOffers
			where pair.Value.PlayerId == fromClient
			select pair.Key).ToArray();
		foreach (long key in array2)
		{
			ServerOffers.Remove(key);
		}
		ArtifactOffer artifactOffer = new ArtifactOffer
		{
			ChestId = chest.GetId(),
			PlayerId = fromClient,
			Choices = array,
			Mythical = MythicalArtifactService.IsMythicalChest(chest),
			ExpiresAt = Time.unscaledTime + 1800f
		};
		ServerOffers[OfferKey(fromClient, artifactOffer.ChestId)] = artifactOffer;
		Plugin.Log.LogInfo((object)string.Format("Artifact offer chest={0}, player={1}, choices={2}", artifactOffer.ChestId, fromClient, string.Join(",", array)));
		return true;
	}

	internal static void RegisterRainbowOffer(int chestId, int playerId, int[] choices)
	{
		long[] array = (from pair in ServerOffers
			where pair.Value.PlayerId == playerId
			select pair.Key).ToArray();
		foreach (long key in array)
		{
			ServerOffers.Remove(key);
		}
		ServerOffers[OfferKey(playerId, chestId)] = new ArtifactOffer
		{
			ChestId = chestId,
			PlayerId = playerId,
			Choices = choices,
			ExpiresAt = Time.unscaledTime + 1800f
		};
	}

	internal static void Reset()
	{
		ServerOffers.Clear();
	}

	internal static void ForgetPlayer(int playerId)
	{
		long[] array = (from pair in ServerOffers
			where pair.Value.PlayerId == playerId
			select pair.Key).ToArray();
		foreach (long key in array)
		{
			ServerOffers.Remove(key);
		}
	}

	internal static void SubmitChoice(int chestId, int powerupId)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		if ((Object)(object)LocalClient.instance == (Object)null)
		{
			return;
		}
		if (LocalClient.serverOwner)
		{
			HandleChoice(LocalClient.instance.myId, chestId, powerupId);
			return;
		}
		try
		{
			Packet val = new Packet(240);
			try
			{
				val.Write(chestId);
				val.Write(powerupId);
				SendTcp?.Invoke(null, new object[1] { val });
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Could not send artifact choice: " + ex));
		}
	}

	internal static void HandleChoicePacket(int fromClient, Packet packet)
	{
		try
		{
			HandleChoice(fromClient, packet.ReadInt(true), packet.ReadInt(true));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)$"Rejected malformed artifact choice from {fromClient}: {ex.Message}");
		}
	}

	private static void HandleChoice(int fromClient, int chestId, int powerupId)
	{
		long key = OfferKey(fromClient, chestId);
		Client value2;
		Powerup value3;
		if (!ServerOffers.TryGetValue(key, out var value) || value.ExpiresAt < Time.unscaledTime || value.Choices == null || !value.Choices.Contains(powerupId))
		{
			Plugin.Log.LogWarning((object)$"Rejected unoffered artifact {powerupId} from player {fromClient}, chest {chestId}");
			ServerOffers.Remove(key);
		}
		else if (Server.clients == null || !Server.clients.TryGetValue(fromClient, out value2) || value2?.player == null || ItemManager.Instance?.allPowerups == null || !ItemManager.Instance.allPowerups.TryGetValue(powerupId, out value3))
		{
			ServerOffers.Remove(key);
		}
		else if (IsAtCap(powerupId, fromClient))
		{
			Plugin.Log.LogWarning((object)$"Rejected capped artifact {powerupId} from player {fromClient}, chest {chestId}");
			ServerOffers.Remove(key);
		}
		else
		{
			ServerOffers.Remove(key);
			Grant(fromClient, value2.player, value3, value.Mythical);
		}
	}

	private static void Grant(int fromClient, Player serverPlayer, Powerup powerup, bool mythical)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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)
		PlayerManager value;
		Vector3 val = ((GameManager.players != null && GameManager.players.TryGetValue(fromClient, out value) && (Object)(object)value != (Object)null) ? (((Component)value).transform.position + Vector3.up * 1.2f) : Vector3.zero);
		int nextId = ItemManager.Instance.GetNextId();
		if (mythical)
		{
			MythicalArtifactService.RegisterDrop(nextId, powerup.id, broadcast: true);
		}
		ItemManager.Instance.DropPowerupAtPosition(powerup.id, val, nextId);
		ServerSend.DropPowerupAtPosition(powerup.id, nextId, val);
		if (serverPlayer.powerups != null && powerup.id >= 0 && powerup.id < serverPlayer.powerups.Length)
		{
			serverPlayer.powerups[powerup.id] += ((!mythical) ? 1 : 5);
		}
		if (mythical)
		{
			MythicalArtifactService.RegisterServerPickup(fromClient, powerup.id);
		}
		if ((Object)(object)GameManager.instance != (Object)null)
		{
			GameManager.instance.powerupsPickedup = true;
		}
		if (serverPlayer.stats != null)
		{
			serverPlayer.stats.TryGetValue("Powerups", out var value2);
			serverPlayer.stats["Powerups"] = value2 + 1;
		}
		if ((Object)(object)LocalClient.instance != (Object)null && fromClient == LocalClient.instance.myId && (Object)(object)PowerupInventory.Instance != (Object)null)
		{
			PowerupInventory.Instance.AddPowerup(powerup.name, powerup.id, nextId);
			if (mythical)
			{
				MythicalArtifactService.ApplyLocalPickup(powerup.id);
			}
		}
		ItemManager.Instance.PickupItem(nextId);
		ServerSend.PickupItem(fromClient, nextId);
		MythicalArtifactService.ForgetDrop(nextId);
		Plugin.Log.LogInfo((object)string.Format("Granted chosen {0}artifact {1} ({2}) to player {3}", mythical ? "mythical " : string.Empty, powerup.name, powerup.id, fromClient));
	}

	internal static int CurrentStacks(int powerupId)
	{
		if ((Object)(object)PowerupInventory.Instance == (Object)null || PowerupsField == null)
		{
			return 0;
		}
		int[] array = (int[])PowerupsField.GetValue(PowerupInventory.Instance);
		if (array == null || powerupId < 0 || powerupId >= array.Length)
		{
			return 0;
		}
		return array[powerupId];
	}

	internal static bool IsAtCap(int powerupId, int playerId = -1)
	{
		if (ItemManager.Instance?.allPowerups == null || !ItemManager.Instance.allPowerups.TryGetValue(powerupId, out var value) || (Object)(object)value == (Object)null)
		{
			return false;
		}
		string text = value.name ?? string.Empty;
		int num = MythicalArtifactService.MaxStacks(text);
		int num2 = ((playerId >= 0) ? MythicalArtifactService.ServerCount(playerId, powerupId) : MythicalArtifactService.Count(powerupId));
		if (num > 0 && num2 >= num)
		{
			return true;
		}
		int num3 = ArtifactBalance.MaxStacks(text);
		if (num3 < 0)
		{
			return false;
		}
		return ((playerId >= 0) ? ServerStackCount(playerId, powerupId) : CurrentStacks(powerupId)) >= num3;
	}

	private static int ServerStackCount(int playerId, int powerupId)
	{
		if (Server.clients == null || !Server.clients.TryGetValue(playerId, out var value) || value?.player?.powerups == null || powerupId < 0 || powerupId >= value.player.powerups.Length)
		{
			return 0;
		}
		return Mathf.Max(0, value.player.powerups[powerupId]);
	}

	private static long OfferKey(int playerId, int chestId)
	{
		return ((long)playerId << 32) ^ (uint)chestId;
	}
}
internal sealed class ArtifactChoiceOverlay : MonoBehaviour
{
	private static ArtifactChoiceOverlay instance;

	private int chestId;

	private Powerup[] choices;

	private CursorLockMode previousLock;

	private bool previousCursor;

	private bool previousInputActive;

	private bool inputCaptured;

	private GUIStyle titleStyle;

	private GUIStyle nameStyle;

	private GUIStyle bodyStyle;

	private GUIStyle tierStyle;

	private Vector2 compactScroll;

	private bool mythical;

	private float rainbowStarted = -1f;

	private int rainbowCost;

	private int rainbowWallet;

	private Powerup[] reelPool;

	private bool rainbowMode;

	private RainbowSlotAudio slotAudio;

	internal static void ShowRainbow(int id, int[] ids, int cost, int wallet)
	{
		//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_001d: Expected O, but got Unknown
		if ((Object)(object)instance == (Object)null)
		{
			GameObject val = new GameObject("Muck Replayable Artifact Choice");
			Object.DontDestroyOnLoad((Object)val);
			instance = val.AddComponent<ArtifactChoiceOverlay>();
		}
		instance.Open(id, ids.Select((int value) => ItemManager.Instance.allPowerups[value]).ToArray(), isMythical: false);
		instance.rainbowStarted = Time.unscaledTime;
		instance.rainbowMode = true;
		instance.slotAudio = ((Component)instance).GetComponent<RainbowSlotAudio>() ?? ((Component)instance).gameObject.AddComponent<RainbowSlotAudio>();
		instance.slotAudio.Begin();
		instance.rainbowCost = cost;
		instance.rainbowWallet = wallet;
		instance.reelPool = ItemManager.Instance.allPowerups.Values.Where((Powerup value) => (Object)(object)value != (Object)null).ToArray();
	}

	internal static void Show(LootContainerInteract chest)
	{
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		if ((Object)(object)chest == (Object)null || (Object)(object)ItemManager.Instance == (Object)null)
		{
			return;
		}
		int playerId = (((Object)(object)LocalClient.instance != (Object)null) ? LocalClient.instance.myId : (-1));
		int[] array = ArtifactChoiceService.GenerateChoices(chest, playerId);
		if (array.Length == 0)
		{
			return;
		}
		if ((Object)(object)instance == (Object)null)
		{
			GameObject val = new GameObject("Muck Replayable Artifact Choice");
			Object.DontDestroyOnLoad((Object)val);
			instance = val.AddComponent<ArtifactChoiceOverlay>();
		}
		Dictionary<int, Powerup> allPowerups = ItemManager.Instance.allPowerups;
		if (allPowerups == null)
		{
			return;
		}
		List<Powerup> list = new List<Powerup>(Mathf.Min(3, array.Length));
		int[] array2 = array;
		foreach (int key in array2)
		{
			if (!allPowerups.TryGetValue(key, out var value) || (Object)(object)value == (Object)null)
			{
				return;
			}
			list.Add(value);
		}
		instance.Open(chest.GetId(), list.ToArray(), MythicalArtifactService.IsMythicalChest(chest));
	}

	private void Open(int id, Powerup[] offered, bool isMythical)
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		if (offered != null && offered.Length != 0 && offered.Length <= 3 && !offered.Any((Powerup powerup) => (Object)(object)powerup == (Object)null))
		{
			if (!inputCaptured)
			{
				previousLock = Cursor.lockState;
				previousCursor = Cursor.visible;
				previousInputActive = (Object)(object)PlayerInput.Instance != (Object)null && PlayerInput.Instance.active;
				inputCaptured = true;
			}
			chestId = id;
			slotAudio?.End();
			choices = offered;
			mythical = isMythical;
			rainbowStarted = -1f;
			rainbowMode = false;
			compactScroll = Vector2.zero;
			UiOverlayInputBlocker.SetBlocked(925111, blocked: true);
			if ((Object)(object)PlayerInput.Instance != (Object)null)
			{
				PlayerInput.Instance.active = false;
			}
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}
	}

	private void Update()
	{
		if (choices != null && (Object)(object)GameManager.instance == (Object)null)
		{
			Close();
		}
		else if (choices != null && (Object)(object)PlayerInput.Instance != (Object)null && PlayerInput.Instance.active)
		{
			PlayerInput.Instance.active = false;
		}
	}

	private void OnGUI()
	{
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_039f: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_0452: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_029e: Unknown result type (might be due to invalid IL or missing references)
		if (choices == null || choices.Length == 0)
		{
			return;
		}
		Powerup[] array = choices;
		LocalizationService.ApplyGuiFont();
		ReforgedGuiTheme.Ensure();
		EnsureStyles();
		GUI.depth = -2000;
		ReforgedGuiTheme.DrawDim();
		float num = Mathf.Min(Mathf.Max(220f, (float)Screen.width - 24f), 1280f);
		float num2 = Mathf.Min(Mathf.Max(190f, (float)Screen.height - 24f), 690f);
		Rect val = default(Rect);
		((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num2) * 0.5f, num, num2);
		GUI.Box(val, GUIContent.none, ReforgedGuiTheme.Window);
		bool flag = rainbowMode;
		float num3 = ((rainbowStarted >= 0f) ? (Time.unscaledTime - rainbowStarted) : (-1f));
		float num4 = (flag ? 140f : 92f);
		float num5 = ((Rect)(ref val)).width - 40f;
		GUI.Label(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).y + 18f, ((Rect)(ref val)).width - 48f, 44f), flag ? "RAINBOW CHEST" : Header(), titleStyle);
		if (flag)
		{
			RainbowSlotPresentation.Lamps(val, num3);
			int num6 = ((num3 >= 0f && num3 < 2.65f) ? RainbowChestRules.RollCost(rainbowWallet, (uint)(num3 * 17321f)) : rainbowCost);
			string text = ((num3 < 2.65f) ? ("COST  " + num6.ToString("N0") + " GOLD  •  ROLLING") : ("PAID  " + rainbowCost.ToString("N0") + " GOLD"));
			GUI.Box(new Rect(((Rect)(ref val)).x + 22f, ((Rect)(ref val)).y + 65f, num5 - 4f, 34f), GUIContent.none);
			GUI.Label(new Rect(((Rect)(ref val)).x + 28f, ((Rect)(ref val)).y + 69f, num5 - 16f, 28f), text, nameStyle);
			string text2 = ((num3 < 5.15f) ? "Reels slowing down..." : ("GOLD LEFT  " + (rainbowWallet - rainbowCost).ToString("N0") + "  •  CHOOSE ONE ARTIFACT"));
			GUI.Label(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).y + 106f, num5 - 8f, 30f), text2, bodyStyle);
		}
		else
		{
			GUI.Label(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).y + 59f, ((Rect)(ref val)).width - 48f, 26f), Subtitle(), bodyStyle);
		}
		float num7 = 14f;
		if (((Rect)(ref val)).width < 760f || ((Rect)(ref val)).height < 430f)
		{
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + num4, num5, Mathf.Max(70f, ((Rect)(ref val)).height - num4 - 20f));
			float num8 = 260f;
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(0f, 0f, Mathf.Max(180f, ((Rect)(ref val2)).width - 18f), num8 * (float)array.Length + num7 * (float)Mathf.Max(0, array.Length - 1));
			compactScroll = GUI.BeginScrollView(val2, compactScroll, val3);
			for (int i = 0; i < array.Length; i++)
			{
				DrawCard(new Rect(0f, (float)i * (num8 + num7), ((Rect)(ref val3)).width, num8), array[i]);
				if (choices == null)
				{
					GUI.EndScrollView();
					return;
				}
			}
			GUI.EndScrollView();
			return;
		}
		float num9 = (num5 - num7 * (float)(array.Length - 1)) / (float)array.Length;
		Rect card = default(Rect);
		for (int j = 0; j < array.Length; j++)
		{
			((Rect)(ref card))..ctor(((Rect)(ref val)).x + 20f + (float)j * (num9 + num7), ((Rect)(ref val)).y + num4, num9, ((Rect)(ref val)).height - num4 - 20f);
			DrawCard(card, array[j]);
			if (choices == null)
			{
				break;
			}
		}
	}

	private void DrawCard(Rect card, Powerup powerup)
	{
		//IL_007f: 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_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: