Decompiled source of Weapon Tiers v1.0.0

SulfurWeaponTiers.dll

Decompiled an hour ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PerfectRandom.Sulfur.Core;
using PerfectRandom.Sulfur.Core.CharacterStats;
using PerfectRandom.Sulfur.Core.Items;
using PerfectRandom.Sulfur.Core.Stats;
using PerfectRandom.Sulfur.Core.UI.ItemDescription;
using PerfectRandom.Sulfur.Core.Units;
using PerfectRandom.Sulfur.Core.Weapons;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SulfurWeaponTiers")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SulfurWeaponTiers")]
[assembly: AssemblyTitle("SulfurWeaponTiers")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SulfurWeaponTiers
{
	internal sealed class HeldWeaponGlint : MonoBehaviour
	{
		private sealed class Part
		{
			internal Renderer Renderer;

			internal int SubMeshes;
		}

		private readonly List<Part> parts = new List<Part>();

		private Material material;

		internal int Tier { get; private set; }

		internal void Configure(int tier, IList<Renderer> renderers)
		{
			if (tier != Tier)
			{
				Clear();
				material = TierGlint.CreateMaterial(tier, inventory: false);
				Tier = tier;
			}
			if ((Object)(object)material == (Object)null)
			{
				return;
			}
			parts.Clear();
			foreach (Renderer renderer in renderers)
			{
				if (!((Object)(object)renderer == (Object)null))
				{
					SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
					MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
					Mesh val2 = (((Object)(object)val != (Object)null) ? val.sharedMesh : (((Object)(object)component != (Object)null) ? component.sharedMesh : null));
					if ((Object)(object)val2 != (Object)null)
					{
						parts.Add(new Part
						{
							Renderer = renderer,
							SubMeshes = val2.subMeshCount
						});
					}
				}
			}
			material.SetFloat("_UseAlpha", 0f);
			material.SetFloat("_HeldGlint", 1f);
		}

		internal void Draw(CommandBuffer commands, int layerMask, uint renderingLayer)
		{
			if ((Object)(object)material == (Object)null)
			{
				return;
			}
			foreach (Part part in parts)
			{
				Renderer renderer = part.Renderer;
				if (!((Object)(object)renderer == (Object)null) && renderer.enabled && !renderer.forceRenderingOff && ((Component)renderer).gameObject.activeInHierarchy && (renderer.renderingLayerMask & renderingLayer) != 0 && ((1 << ((Component)renderer).gameObject.layer) & layerMask) != 0)
				{
					for (int i = 0; i < part.SubMeshes; i++)
					{
						commands.DrawRenderer(renderer, material, i, 0);
					}
				}
			}
		}

		internal void Clear()
		{
			Object.Destroy((Object)(object)material);
			material = null;
			parts.Clear();
			Tier = 0;
		}

		private void OnDestroy()
		{
			Clear();
		}
	}
	internal sealed class PickupWeaponGlint : MonoBehaviour
	{
		private MeshRenderer source;

		private MeshRenderer overlay;

		private Material material;

		internal void Configure(int tier, MeshRenderer artwork)
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			Clear();
			if (tier != 0 && !((Object)(object)artwork == (Object)null))
			{
				material = TierGlint.CreateMaterial(tier, inventory: false);
				if (!((Object)(object)material == (Object)null))
				{
					source = artwork;
					Material sharedMaterial = ((Renderer)source).sharedMaterial;
					material.SetTexture("_MainTex", sharedMaterial.GetTexture("_MainTex"));
					material.SetTextureOffset("_MainTex", sharedMaterial.GetTextureOffset("_MainTex"));
					material.SetTextureScale("_MainTex", sharedMaterial.GetTextureScale("_MainTex"));
					material.SetFloat("_Cull", 0f);
					material.SetFloat("_Billboard", sharedMaterial.IsKeywordEnabled("_BILLBOARD_FACECAMERA") ? 1f : 0f);
					material.SetFloat("_AlphaClipThreshold", sharedMaterial.HasProperty("_AlphaClipThreshold") ? sharedMaterial.GetFloat("_AlphaClipThreshold") : 0.01f);
					GameObject val = new GameObject("Weapon tier glint");
					val.transform.SetParent(((Component)source).transform, false);
					val.AddComponent<MeshFilter>().sharedMesh = ((Component)source).GetComponent<MeshFilter>().sharedMesh;
					overlay = val.AddComponent<MeshRenderer>();
					((Renderer)overlay).sharedMaterial = material;
					((Renderer)overlay).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)overlay).receiveShadows = false;
					LateUpdate();
				}
			}
		}

		private void LateUpdate()
		{
			if (!((Object)(object)overlay == (Object)null))
			{
				((Renderer)overlay).enabled = (Object)(object)source != (Object)null && ((Renderer)source).enabled && !((Renderer)source).forceRenderingOff && ((Component)source).gameObject.activeInHierarchy;
				if ((Object)(object)source != (Object)null)
				{
					((Renderer)overlay).renderingLayerMask = ((Renderer)source).renderingLayerMask;
					((Component)overlay).gameObject.layer = ((Component)source).gameObject.layer;
					((Renderer)overlay).sortingLayerID = ((Renderer)source).sortingLayerID;
					((Renderer)overlay).sortingOrder = ((Renderer)source).sortingOrder;
				}
			}
		}

		private void OnDisable()
		{
			if ((Object)(object)overlay != (Object)null)
			{
				((Renderer)overlay).enabled = false;
			}
		}

		internal void Clear()
		{
			if ((Object)(object)overlay != (Object)null)
			{
				((Renderer)overlay).enabled = false;
				Object.Destroy((Object)(object)((Component)overlay).gameObject);
			}
			Object.Destroy((Object)(object)material);
			source = null;
			overlay = null;
			material = null;
		}

		private void OnDestroy()
		{
			Clear();
		}
	}
	internal static class TierGlint
	{
		private static Shader worldShader;

		private static Shader inventoryShader;

		private static float strength;

		private static float speed;

		private static bool isReady;

		private static readonly int Clock = Shader.PropertyToID("_SwtGlintTime");

		internal static void Initialize(bool enabled, float glintStrength, float glintSpeed, float glintIntensityScale, ManualLogSource log)
		{
			if (!enabled)
			{
				return;
			}
			using (Stream stream = typeof(TierGlint).Assembly.GetManifestResourceStream("SulfurWeaponTiers.GlintShaders"))
			{
				if (stream == null)
				{
					log.LogError((object)"Tier glint shader resource missing!");
					return;
				}
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				AssetBundle val = AssetBundle.LoadFromMemory(memoryStream.ToArray());
				if ((Object)(object)val == (Object)null)
				{
					log.LogError((object)"Could not load tier glint shaders!");
					return;
				}
				worldShader = val.LoadAsset<Shader>("Assets/WorldGlint.shader");
				inventoryShader = val.LoadAsset<Shader>("Assets/InventoryGlint.shader");
				val.Unload(false);
			}
			if ((Object)(object)worldShader == (Object)null || (Object)(object)inventoryShader == (Object)null || !worldShader.isSupported || !inventoryShader.isSupported)
			{
				log.LogError((object)"Tier glint shaders unsupported on this graphics device, uh oh!");
				return;
			}
			strength = glintStrength * glintIntensityScale;
			speed = glintSpeed;
			isReady = true;
			log.LogInfo((object)"Tier glint shaders loaded!");
		}

		internal static void Tick()
		{
			if (isReady)
			{
				Shader.SetGlobalFloat(Clock, Time.unscaledTime);
			}
		}

		internal static Material CreateMaterial(int tier, bool inventory)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_0079: Expected O, but got Unknown
			if (!isReady || tier == 0)
			{
				return null;
			}
			Color val = default(Color);
			ColorUtility.TryParseHtmlString("#" + WeaponTierSystem.Colors[tier], ref val);
			Material val2 = new Material(inventory ? inventoryShader : worldShader)
			{
				name = "Weapon tier glint",
				hideFlags = (HideFlags)61
			};
			val2.SetColor("_TierColor", val);
			val2.SetFloat("_Strength", strength);
			val2.SetFloat("_Speed", speed);
			return val2;
		}

		internal static void ApplyPickup(Pickup pickup)
		{
			PickupWeaponGlint pickupWeaponGlint = ((Component)pickup).GetComponent<PickupWeaponGlint>();
			int num = ((pickup.ItemSO is WeaponSO) ? WeaponTierSystem.Read(pickup.inventoryData?.attributes) : 0);
			if (isReady && num > 0 && (Object)(object)pickupWeaponGlint == (Object)null)
			{
				pickupWeaponGlint = ((Component)pickup).gameObject.AddComponent<PickupWeaponGlint>();
			}
			if ((Object)(object)pickupWeaponGlint != (Object)null)
			{
				pickupWeaponGlint.Configure(num, pickup.itemSprite);
			}
		}

		internal static void ApplyHeld(Weapon weapon)
		{
			HeldWeaponGlint heldWeaponGlint = ((Component)weapon).GetComponent<HeldWeaponGlint>();
			int num = ((!((Object)(object)((Holdable)weapon).inventoryItem == (Object)null)) ? WeaponTierSystem.Read(((Holdable)weapon).inventoryItem.stats) : 0);
			if (isReady && num > 0 && (Object)(object)heldWeaponGlint == (Object)null)
			{
				heldWeaponGlint = ((Component)weapon).gameObject.AddComponent<HeldWeaponGlint>();
			}
			if ((Object)(object)heldWeaponGlint != (Object)null)
			{
				heldWeaponGlint.Configure(num, weapon.meshRenderersInWeapon);
			}
		}

		internal static void DrawHeld(CommandBuffer commands, Dictionary<Camera, Player> players, int layerMask, ref RenderingData renderingData)
		{
			if (!isReady || !players.TryGetValue(((CameraData)(ref renderingData.cameraData)).camera, out var value))
			{
				return;
			}
			Holdable activeHoldable = value.activeHoldable;
			Weapon val = (Weapon)(object)((activeHoldable is Weapon) ? activeHoldable : null);
			if (val == null)
			{
				return;
			}
			HeldWeaponGlint component = ((Component)val).GetComponent<HeldWeaponGlint>();
			int num = ((!((Object)(object)((Holdable)val).inventoryItem == (Object)null)) ? WeaponTierSystem.Read(((Holdable)val).inventoryItem.stats) : 0);
			if (num == 0)
			{
				if ((Object)(object)component != (Object)null && component.Tier != 0)
				{
					component.Clear();
				}
				return;
			}
			if ((Object)(object)component == (Object)null || component.Tier != num)
			{
				ApplyHeld(val);
				component = ((Component)val).GetComponent<HeldWeaponGlint>();
			}
			if ((Object)(object)component != (Object)null)
			{
				component.Draw(commands, layerMask, value.playerRenderLayer);
			}
		}

		internal static void ApplyInventory(InventoryItem item, Image artwork)
		{
			InventoryTierGlint inventoryTierGlint = ((Component)item).GetComponent<InventoryTierGlint>();
			int num = ((!((Object)(object)item.weaponDefinition == (Object)null)) ? WeaponTierSystem.Read(item.stats) : 0);
			if (isReady && num > 0 && (Object)(object)artwork != (Object)null && (Object)(object)inventoryTierGlint == (Object)null)
			{
				inventoryTierGlint = ((Component)item).gameObject.AddComponent<InventoryTierGlint>();
			}
			if ((Object)(object)inventoryTierGlint != (Object)null)
			{
				inventoryTierGlint.Configure(artwork, num);
			}
		}

		internal static void Shutdown()
		{
			PickupWeaponGlint[] array = Resources.FindObjectsOfTypeAll<PickupWeaponGlint>();
			foreach (PickupWeaponGlint obj in array)
			{
				obj.Clear();
				Object.Destroy((Object)(object)obj);
			}
			HeldWeaponGlint[] array2 = Resources.FindObjectsOfTypeAll<HeldWeaponGlint>();
			foreach (HeldWeaponGlint obj2 in array2)
			{
				obj2.Clear();
				Object.Destroy((Object)(object)obj2);
			}
			InventoryTierGlint[] array3 = Resources.FindObjectsOfTypeAll<InventoryTierGlint>();
			foreach (InventoryTierGlint obj3 in array3)
			{
				obj3.Clear();
				Object.Destroy((Object)(object)obj3);
			}
			isReady = false;
			Object.Destroy((Object)(object)worldShader);
			Object.Destroy((Object)(object)inventoryShader);
			worldShader = null;
			inventoryShader = null;
		}
	}
	internal sealed class InventoryTierGlint : MonoBehaviour
	{
		private Image source;

		private Image overlay;

		private Material material;

		internal void Configure(Image artwork, int tier)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			Clear();
			if (!((Object)(object)artwork == (Object)null) && tier != 0)
			{
				material = TierGlint.CreateMaterial(tier, inventory: true);
				if (!((Object)(object)material == (Object)null))
				{
					source = artwork;
					GameObject val = new GameObject("Weapon tier glint", new Type[3]
					{
						typeof(RectTransform),
						typeof(CanvasRenderer),
						typeof(Image)
					});
					val.layer = ((Component)source).gameObject.layer;
					val.transform.SetParent(((Component)source).transform, false);
					overlay = val.GetComponent<Image>();
					((Graphic)overlay).rectTransform.anchorMin = Vector2.zero;
					((Graphic)overlay).rectTransform.anchorMax = Vector2.one;
					((Graphic)overlay).rectTransform.offsetMin = Vector2.zero;
					((Graphic)overlay).rectTransform.offsetMax = Vector2.zero;
					((Graphic)overlay).material = material;
					((Graphic)overlay).raycastTarget = false;
					SyncArtwork();
				}
			}
		}

		private void SyncArtwork()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)source == (Object)null) && !((Object)(object)overlay == (Object)null))
			{
				overlay.sprite = source.overrideSprite;
				overlay.type = source.type;
				overlay.useSpriteMesh = source.useSpriteMesh;
				overlay.pixelsPerUnitMultiplier = source.pixelsPerUnitMultiplier;
				overlay.fillCenter = source.fillCenter;
				overlay.preserveAspect = source.preserveAspect;
				overlay.fillAmount = source.fillAmount;
				overlay.fillMethod = source.fillMethod;
				overlay.fillOrigin = source.fillOrigin;
				overlay.fillClockwise = source.fillClockwise;
				((MaskableGraphic)overlay).maskable = ((MaskableGraphic)source).maskable;
				((Graphic)overlay).color = ((Graphic)source).color;
				((Behaviour)overlay).enabled = ((Behaviour)source).enabled;
			}
		}

		private void LateUpdate()
		{
			SyncArtwork();
		}

		internal void Clear()
		{
			if ((Object)(object)overlay != (Object)null)
			{
				((Behaviour)overlay).enabled = false;
				Object.Destroy((Object)(object)((Component)overlay).gameObject);
			}
			Object.Destroy((Object)(object)material);
			source = null;
			overlay = null;
			material = null;
		}

		private void OnDestroy()
		{
			Clear();
		}
	}
	[HarmonyPatch(typeof(Weapon), "SetupRenderers")]
	internal static class HeldTierGlintPatch
	{
		private static void Postfix(Weapon __instance)
		{
			TierGlint.ApplyHeld(__instance);
		}
	}
	[HarmonyPatch(typeof(WeaponRendering), "Execute")]
	internal static class HeldGlintRenderingPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo drawList = AccessTools.Method(typeof(CommandBuffer), "DrawRendererList", (Type[])null, (Type[])null);
			MethodInfo drawGlint = AccessTools.Method(typeof(TierGlint), "DrawHeld", (Type[])null, (Type[])null);
			FieldInfo players = AccessTools.Field(typeof(WeaponRendering), "_playerCameras");
			FieldInfo layers = AccessTools.Field(typeof(WeaponRendering), "_weaponLayer");
			int draws = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				yield return instruction;
				if (CodeInstructionExtensions.Calls(instruction, drawList))
				{
					int num = draws + 1;
					draws = num;
					if (num == 2)
					{
						yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null);
						yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
						yield return new CodeInstruction(OpCodes.Ldfld, (object)players);
						yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
						yield return new CodeInstruction(OpCodes.Ldfld, (object)layers);
						yield return new CodeInstruction(OpCodes.Ldarg_3, (object)null);
						yield return new CodeInstruction(OpCodes.Call, (object)drawGlint);
					}
				}
			}
			if (draws != 2)
			{
				throw new InvalidOperationException("Weapon render pass has changed, could not set up glint draw!");
			}
		}
	}
	[HarmonyPatch(typeof(InventoryItem), "Setup", new Type[]
	{
		typeof(Vector2),
		typeof(ItemDefinition),
		typeof(ItemGrid),
		typeof(int),
		typeof(int),
		typeof(InventoryData),
		typeof(bool)
	})]
	internal static class InventoryTierGlintPatch
	{
		private static void Postfix(InventoryItem __instance, Image ___artworkSlot)
		{
			TierGlint.ApplyInventory(__instance, ___artworkSlot);
		}
	}
	[BepInPlugin("pseudotim.sulfur.weapontiers", "Weapon Tiers", "1.0.0")]
	public sealed class WeaponTiersPlugin : BaseUnityPlugin
	{
		public const string ModName = "Weapon Tiers";

		public const string ModVersion = "1.0.0";

		internal static double[] Weights = WeaponTierSystem.DefaultWeights;

		private Harmony harmony;

		private void Awake()
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Expected O, but got Unknown
			ConfigEntry<string> val = ((BaseUnityPlugin)this).Config.Bind<string>("Drops", "Weights", "70,20,7,2.5,0.5", "Relative weights: (Standard, Blessed, Hallowed, Sacred, Divine)");
			try
			{
				Weights = (from s in val.Value.Split(',')
					select double.Parse(s.Trim(), CultureInfo.InvariantCulture)).ToArray();
				WeaponTierSystem.Roll(0.0, Weights);
			}
			catch (Exception ex) when (ex is FormatException || ex is OverflowException || ex is ArgumentException)
			{
				Weights = WeaponTierSystem.DefaultWeights;
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Invalid tier weights, using defaults!" + ex.Message));
			}
			harmony = new Harmony("pseudotim.sulfur.weapontiers");
			bool value = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "GlintEnabled", true, "Show a subtle colored animated shimmer effect on tiered weapons").Value;
			float value2 = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "GlintStrength", 0.39f, new ConfigDescription("Glint brightness", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>())).Value;
			float value3 = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "GlintSpeed", 0.3f, new ConfigDescription("Glint shimmer speed", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 0.5f), Array.Empty<object>())).Value;
			float value4 = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "GlintIntensityScale", 0.5f, new ConfigDescription("Overall glint intensity multiplier for held weapons, pickups, and inventory icons. (0 disables brightness, 1 uses full GlintStrength)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())).Value;
			TierGlint.Initialize(value, value2, value3, value4, ((BaseUnityPlugin)this).Logger);
			try
			{
				harmony.PatchAll(typeof(WeaponTiersPlugin).Assembly);
			}
			catch (Exception ex2)
			{
				harmony.UnpatchSelf();
				TierGlint.Shutdown();
				((BaseUnityPlugin)this).Logger.LogError((object)("Weapon Tiers couldn't patch this game version, all patches removed!" + ex2));
				return;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Weapon Tiers v1.0.0 loaded!");
		}

		private void Update()
		{
			TierGlint.Tick();
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			TierGlint.Shutdown();
		}
	}
	[HarmonyPatch(typeof(Pickup), "SetupAndSpawn")]
	internal static class DropPatch
	{
		private static readonly MethodInfo SetData = AccessTools.PropertySetter(typeof(Pickup), "inventoryData");

		private static void Postfix(Pickup __instance, ItemDefinition item, InventoryData _inventoryData)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0094: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			WeaponSO val = (WeaponSO)(object)((item is WeaponSO) ? item : null);
			if (val == null)
			{
				TierGlint.ApplyPickup(__instance);
				return;
			}
			int num;
			if (_inventoryData != null)
			{
				num = WeaponTierSystem.Read(_inventoryData.attributes);
			}
			else
			{
				num = WeaponTierSystem.Roll(Random.value, WeaponTiersPlugin.Weights);
				if (num == 0)
				{
					TierGlint.ApplyPickup(__instance);
					return;
				}
				ItemStats val2 = new ItemStats();
				val2.SetBaseAttributes((ItemDefinition)(object)val);
				WeaponTierSystem.Apply(val2, num);
				int num2 = ((!val.startsEmpty) ? val.iAmmoMax : 0);
				ItemAttributeCollectionData val3 = val2.SerializedAttributeData();
				ItemId[] array = Array.Empty<ItemId>();
				ItemId[] array2 = Array.Empty<ItemId>();
				int x = ((Vector2Int)(ref item.inventorySize)).x;
				int y = ((Vector2Int)(ref item.inventorySize)).y;
				InventoryData val4 = new InventoryData(item.id, 0, 0, 1, num2, val.caliber, val3, array, array2, 0, x, y, false, false);
				SetData.Invoke(__instance, new object[1] { val4 });
			}
			if (num > 0 && (Object)(object)__instance.itemText != (Object)null)
			{
				((TMP_Text)__instance.itemText).text = ((TMP_Text)__instance.itemText).text + " " + WeaponTierSystem.Label(num);
			}
			TierGlint.ApplyPickup(__instance);
		}
	}
	[HarmonyPatch(typeof(ItemStats), "SerializedAttributeData")]
	internal static class SavePatch
	{
		private static void Postfix(ItemStats __instance, ItemAttributeCollectionData __result)
		{
			WeaponTierSystem.Write(__result, WeaponTierSystem.Read(__instance));
		}
	}
	[HarmonyPatch(typeof(ItemStats), "LoadAttributesFromData")]
	internal static class LoadPatch
	{
		private static void Postfix(ItemStats __instance, ItemAttributeCollectionData data)
		{
			WeaponTierSystem.Apply(__instance, WeaponTierSystem.Read(data));
		}
	}
	[HarmonyPatch(typeof(ItemStats), "SetAttributeBaseValue")]
	internal static class BaseValuePatch
	{
		private static void Prefix(ItemStats __instance, out int __state)
		{
			__state = WeaponTierSystem.Read(__instance);
		}

		private static void Postfix(ItemStats __instance, ItemAttributes attribute, int __state)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			WeaponTierSystem.Refresh(__instance, attribute, __state);
		}
	}
	[HarmonyPatch(typeof(ItemStats), "GetPelletDamage")]
	internal static class PelletPatch
	{
		private static void Postfix(ItemStats __instance, int pellets, ref float __result)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Invalid comparison between Unknown and I4
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Invalid comparison between Unknown and I4
			if (pellets <= 1 || WeaponTierSystem.Read(__instance) == 0)
			{
				return;
			}
			List<StatModifier> statModifiers = __instance.itemAttributes[6].statModifiers;
			float num = 0f;
			float num2 = 0f;
			float num3 = 1f;
			foreach (StatModifier item in statModifiers)
			{
				if (item.SourceId == 1398232113)
				{
					num += item.Value;
				}
				if ((int)item.Type == 200)
				{
					num2 += item.Value;
				}
				if ((int)item.Type == 300)
				{
					num3 *= 1f + item.Value;
				}
			}
			__result += num * (1f - 1f / (float)pellets) * Mathf.Clamp(1f + num2, 0.01f, 10f) * num3;
		}
	}
	[HarmonyPatch]
	internal static class TierBonusTooltipPatch
	{
		private static readonly MethodInfo AddAttribute = AccessTools.Method(typeof(ItemDescription), "AddAttribute", new Type[5]
		{
			typeof(string),
			typeof(int).MakeByRefType(),
			typeof(string),
			typeof(string),
			typeof(bool)
		}, (Type[])null);

		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(ItemDescription), "AddDurability", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ItemDescription), "AddFlavorText", (Type[])null, (Type[])null);
		}

		private static void Prefix(ItemDescription __instance, MethodBase __originalMethod, ref int childIndex, InventoryItem ___inventoryRepresentation)
		{
			if ((Object)(object)___inventoryRepresentation == (Object)null || (Object)(object)___inventoryRepresentation.weaponDefinition == (Object)null)
			{
				return;
			}
			WeaponSO weaponDefinition = ___inventoryRepresentation.weaponDefinition;
			if (!(__originalMethod.Name == "AddFlavorText") || weaponDefinition.IsMelee || weaponDefinition.IsThrowable)
			{
				int num = WeaponTierSystem.Read(___inventoryRepresentation.stats);
				if (num != 0)
				{
					AddBonus(__instance, "Tier damage", (ItemAttributes)6, num, ref childIndex);
					AddBonus(__instance, "Tier fire rate", (ItemAttributes)56, num, ref childIndex);
					AddBonus(__instance, "Tier reload speed", (ItemAttributes)55, num, ref childIndex);
					AddBonus(__instance, "Tier max durability", (ItemAttributes)21, num, ref childIndex);
				}
			}
		}

		private static void AddBonus(ItemDescription description, string label, ItemAttributes attribute, int tier, ref int childIndex)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			string text = "<color=#" + WeaponTierSystem.Colors[tier] + ">" + label + ":</color>";
			object[] array = new object[5]
			{
				text,
				childIndex,
				WeaponTierSystem.ColoredMultiplier(attribute, tier),
				"",
				true
			};
			AddAttribute.Invoke(description, array);
			childIndex = (int)array[1];
		}
	}
	[HarmonyPatch(typeof(ItemDescription), "Setup", new Type[] { typeof(InventoryItem) })]
	internal static class TooltipPatch
	{
		private static void Postfix(InventoryItem inventoryItem, TextMeshProUGUI ___titleTextFull, TextMeshProUGUI ___titleTextShort)
		{
			int num = WeaponTierSystem.Read(inventoryItem.stats);
			if (num != 0)
			{
				string text = " " + WeaponTierSystem.Label(num);
				((TMP_Text)___titleTextFull).text = ((TMP_Text)___titleTextFull).text + text;
				((TMP_Text)___titleTextShort).text = ((TMP_Text)___titleTextShort).text + text;
			}
		}
	}
	public static class WeaponTierSystem
	{
		public const uint Source = 1398232113u;

		public const int SaveSignature = 537200;

		public static readonly string[] Names = new string[5] { "Standard", "Blessed", "Hallowed", "Sacred", "Divine" };

		public static readonly string[] Colors = new string[5] { "FFFFFF", "469247", "48CAE4", "EC78CB", "FFD700" };

		public static readonly double[] DefaultWeights = new double[5] { 70.0, 20.0, 7.0, 2.5, 0.5 };

		public static readonly float[] DamageMultipliers = new float[5] { 1f, 1.25f, 1.5f, 1.75f, 2f };

		public static readonly float[] FireRateMultipliers = new float[5] { 1f, 1.05f, 1.1f, 1.15f, 1.2f };

		public static readonly float[] ReloadSpeedMultipliers = new float[5] { 1f, 1.05f, 1.1f, 1.15f, 1.2f };

		public static readonly float[] DurabilityMultipliers = new float[5] { 1f, 1.1f, 1.2f, 1.35f, 1.5f };

		public static int Roll(double sample, double[] weights)
		{
			if (weights.Length != 5 || weights.Any((double w) => double.IsNaN(w) || double.IsInfinity(w) || w < 0.0) || weights.Sum() <= 0.0)
			{
				throw new ArgumentException("Invalid weights!");
			}
			double num = Math.Max(0.0, Math.Min(sample, 0.9999999999999999)) * weights.Sum();
			for (int num2 = 0; num2 < weights.Length; num2++)
			{
				num -= weights[num2];
				if (num < 0.0)
				{
					return num2;
				}
			}
			return 4;
		}

		public static int Read(CharacterStat damage)
		{
			StatModifier val = damage?.statModifiers?.FirstOrDefault((Func<StatModifier, bool>)((StatModifier m) => m.SourceId == 1398232113 && m.Order >= 201 && m.Order <= 204));
			if (val != null)
			{
				return val.Order - 200;
			}
			return 0;
		}

		public static int Read(ItemStats stats)
		{
			if (stats != null)
			{
				return Read(stats.itemAttributes[6]);
			}
			return 0;
		}

		private static bool IsMarker(ItemAttributeData data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if ((int)data.id == 0 && data.value != null && data.value.BaseValue >= 537201f && data.value.BaseValue <= 537204f)
			{
				return data.value.BaseValue == (float)(int)data.value.BaseValue;
			}
			return false;
		}

		public static int Read(ItemAttributeCollectionData data)
		{
			ItemAttributeData val = data?.itemAttributes?.FirstOrDefault((Func<ItemAttributeData, bool>)IsMarker);
			if (val != null)
			{
				return (int)val.value.BaseValue - 537200;
			}
			return 0;
		}

		public static void Write(ItemAttributeCollectionData data, int tier)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			if (tier >= 1 && tier <= 4)
			{
				List<ItemAttributeData> list = data.itemAttributes.Where((ItemAttributeData a) => !IsMarker(a)).ToList();
				list.Add(new ItemAttributeData((ItemAttributes)0, new CharacterStat((float)(537200 + tier))));
				data.itemAttributes = list.ToArray();
			}
		}

		public static string Label(int tier)
		{
			return "<color=#" + Colors[tier] + ">(" + Names[tier] + ")</color>";
		}

		public static float Factor(ItemAttributes attribute, int tier)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			if ((int)attribute <= 21)
			{
				if ((int)attribute == 6)
				{
					return DamageMultipliers[tier];
				}
				if ((int)attribute == 21)
				{
					return DurabilityMultipliers[tier];
				}
			}
			else
			{
				if ((int)attribute == 55)
				{
					return ReloadSpeedMultipliers[tier];
				}
				if ((int)attribute == 56)
				{
					return FireRateMultipliers[tier];
				}
			}
			return 1f;
		}

		public static string ColoredMultiplier(ItemAttributes attribute, int tier)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (tier == 0)
			{
				return string.Empty;
			}
			string text = Factor(attribute, tier).ToString("0.##", CultureInfo.InvariantCulture);
			return "<color=#" + Colors[tier] + ">x" + text + "</color>";
		}

		public static void Apply(ItemStats stats, int tier)
		{
			if (tier >= 1 && tier <= 4)
			{
				for (int i = 0; i < stats.activeItemAttributes.Count; i++)
				{
					Refresh(stats, (ItemAttributes)stats.activeItemAttributes[i], tier);
				}
			}
		}

		public static void Refresh(ItemStats stats, ItemAttributes attribute, int tier)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			CharacterStat val = stats.itemAttributes[attribute];
			if (val != null && tier != 0)
			{
				val.RemoveAllModifiersFromSource(1398232113u);
				float num = Factor(attribute, tier);
				if (num != 1f || (int)attribute == 6)
				{
					val.AddModifier(new StatModifier(val.BaseValue * (num - 1f), (StatModType)100, 200 + tier, 1398232113u));
				}
			}
		}
	}
}