Decompiled source of EpicLoot LuckTrinket v0.3.0

LuckyTrinket.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EpicLoot;
using EpicLoot.CraftingV2;
using EpicLoot_UnityLib;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("LuckyTrinket")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.0.0")]
[assembly: AssemblyInformationalVersion("0.3.0+ee29449de01293b6e97e8af3eb1ad15a817fc303")]
[assembly: AssemblyProduct("LuckyTrinket")]
[assembly: AssemblyTitle("LuckyTrinket")]
[assembly: AssemblyVersion("0.3.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 LuckyTrinket
{
	internal static class DropDebug
	{
		[ThreadStatic]
		private static Stack<int> s_countStack;

		[ThreadStatic]
		private static int s_contextCount;

		[ThreadStatic]
		private static Stack<bool> s_countItemsStack;

		[ThreadStatic]
		private static bool s_countItems;

		private static float s_baselineAncientPercent = -1f;

		private static int s_sessionKeptEquip;

		private static int s_sessionKeptEquipAncient;

		private static int s_sessionKeptInjectedEquip;

		private static bool _ratiosResolved;

		private static FieldInfo _fItem;

		private static FieldInfo _fShard;

		private static FieldInfo _fUnidentified;

		private static FieldInfo _fMaterials;

		private static FieldInfo _fGlobal;

		internal static bool Enabled
		{
			get
			{
				if (LuckyTrinketPlugin.DebugLog != null)
				{
					return LuckyTrinketPlugin.DebugLog.Value;
				}
				return false;
			}
		}

		internal static int ContextCount
		{
			get
			{
				if (s_countStack == null || s_countStack.Count <= 0)
				{
					return 0;
				}
				return s_contextCount;
			}
		}

		internal static void EnterContext(bool countItems)
		{
			if (s_countStack == null)
			{
				s_countStack = new Stack<int>();
			}
			s_countStack.Push(s_contextCount);
			s_contextCount = 0;
			if (s_countItemsStack == null)
			{
				s_countItemsStack = new Stack<bool>();
			}
			s_countItemsStack.Push(s_countItems);
			s_countItems = countItems;
		}

		internal static void ExitContext()
		{
			if (s_countItemsStack != null && s_countItemsStack.Count > 0)
			{
				s_countItems = s_countItemsStack.Pop();
			}
			if (s_countStack != null && s_countStack.Count > 0)
			{
				s_contextCount = s_countStack.Pop();
			}
		}

		internal static void SetBaselineAncientPercent(float percent)
		{
			s_baselineAncientPercent = percent;
		}

		internal static void OnItemKept(GameObject gameObject)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Invalid comparison between Unknown and I4
			if (!s_countItems)
			{
				return;
			}
			try
			{
				ItemDrop val = (((Object)(object)gameObject != (Object)null) ? gameObject.GetComponent<ItemDrop>() : null);
				ItemData val2 = (((Object)(object)val != (Object)null) ? val.m_itemData : null);
				if (val2 != null && val2.IsEquipable())
				{
					MagicItem magicItem = ItemDataExtensions.GetMagicItem(val2);
					bool num = magicItem != null && (int)magicItem.Rarity >= 5;
					GameObject dropPrefab = val2.m_dropPrefab;
					bool flag = RarityFloorSystem.IsInjectedItem((dropPrefab != null) ? ((Object)dropPrefab).name : null);
					s_sessionKeptEquip++;
					if (num)
					{
						s_sessionKeptEquipAncient++;
					}
					if (flag)
					{
						s_sessionKeptInjectedEquip++;
					}
				}
			}
			catch
			{
			}
		}

		internal static void LogCumulative()
		{
			if (Enabled && s_countItems && s_sessionKeptEquip > 0)
			{
				float num = (float)s_sessionKeptEquipAncient * 100f / (float)s_sessionKeptEquip;
				string arg = ((s_baselineAncientPercent >= 0f) ? $"原版池期望≈{s_baselineAncientPercent:0.#}%" : "原版池期望=?");
				LtrLog.Debug($"本局累计: 保留装备 {s_sessionKeptEquip} 件,Ancient {s_sessionKeptEquipAncient} 件" + $"({num:0.#}%,{arg}),其中穿戴注入 {s_sessionKeptInjectedEquip} 件");
			}
		}

		internal static void LogContextStart(string objectName, int level, Vector3? point)
		{
			if (Enabled)
			{
				LtrLog.Debug($"掉落开始: 表={objectName}, 等级={level}, 点={point}");
				LtrLog.Debug("  分类权重(EpicLoot Balance): " + GetRatios());
			}
		}

		internal static void LogCountTable(LootTable table, int level, List<KeyValuePair<int, float>> drops)
		{
			if (!Enabled || drops == null || drops.Count == 0)
			{
				return;
			}
			float num = 0f;
			foreach (KeyValuePair<int, float> drop in drops)
			{
				num += Math.Max(0f, drop.Value);
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append($"掉落数量几率: 表={table?.Object}, 等级={level}");
			foreach (KeyValuePair<int, float> drop2 in drops)
			{
				float num2 = ((num > 0f) ? (Math.Max(0f, drop2.Value) / num * 100f) : 0f);
				stringBuilder.Append($", {drop2.Key}件={num2:0.#}%");
			}
			LtrLog.Debug(stringBuilder.ToString());
		}

		internal static void OnDropTypeSelected(LootDrop lootDrop, bool isShardDrop, LootDropType type, bool injected = false)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			s_contextCount++;
			if (Enabled)
			{
				LtrLog.Debug("  掉落分类: " + (lootDrop?.Item ?? "?") + " → " + TypeName(type) + (injected ? "(穿戴注入)" : "") + (isShardDrop ? "(固定碎片石,不参与分类 roll)" : ""));
			}
		}

		internal static void LogRolledCount()
		{
			if (Enabled)
			{
				LtrLog.Debug($"本次实际 roll 出 {ContextCount} 件掉落,开始过滤。");
			}
		}

		internal static string Describe(GameObject gameObject)
		{
			//IL_0070: 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)
			try
			{
				ItemDrop val = (((Object)(object)gameObject != (Object)null) ? gameObject.GetComponent<ItemDrop>() : null);
				ItemData val2 = (((Object)(object)val != (Object)null) ? val.m_itemData : null);
				if (val2 == null)
				{
					return "?";
				}
				MagicItem magicItem = ItemDataExtensions.GetMagicItem(val2);
				string[] obj = new string[5]
				{
					$"{val2.m_shared?.m_name} [类型={val2.m_shared?.m_itemType}, ",
					$"品质={magicItem?.Rarity}, 未鉴定={magicItem?.IsUnidentified}, ",
					"prefab=",
					null,
					null
				};
				GameObject dropPrefab = val2.m_dropPrefab;
				obj[3] = ((dropPrefab != null) ? ((Object)dropPrefab).name : null);
				obj[4] = "]";
				return string.Concat(obj);
			}
			catch (Exception ex)
			{
				return "?(" + ex.Message + ")";
			}
		}

		internal unsafe static string TypeName(LootDropType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected I4, but got Unknown
			return (int)type switch
			{
				0 => "装备/物品", 
				1 => "碎片石", 
				2 => "未鉴定装备", 
				3 => "材料", 
				_ => ((object)(*(LootDropType*)(&type))/*cast due to .constrained prefix*/).ToString(), 
			};
		}

		private static string GetRatios()
		{
			try
			{
				ResolveRatios();
				return "装备=" + Ratio(_fItem) + ", 碎片石=" + Ratio(_fShard) + ", 未鉴定=" + Ratio(_fUnidentified) + ", 材料=" + Ratio(_fMaterials) + ", 全局掉率=" + Ratio(_fGlobal);
			}
			catch (Exception ex)
			{
				return "读取失败: " + ex.Message;
			}
		}

		private static void ResolveRatios()
		{
			if (!_ratiosResolved)
			{
				_ratiosResolved = true;
				Type type = AccessTools.TypeByName("EpicLoot.Config.ELConfig");
				if (!(type == null))
				{
					_fItem = AccessTools.Field(type, "ItemDropRatio");
					_fShard = AccessTools.Field(type, "ShardStoneDropRatio");
					_fUnidentified = AccessTools.Field(type, "ItemsUnidentifiedDropRatio");
					_fMaterials = AccessTools.Field(type, "MaterialsDropRatio");
					_fGlobal = AccessTools.Field(type, "GlobalDropRateModifier");
				}
			}
		}

		private static string Ratio(FieldInfo field)
		{
			if (field == null)
			{
				return "?";
			}
			if (!(field.GetValue(null) is ConfigEntry<float> val))
			{
				return "?";
			}
			return val.Value.ToString("0.###");
		}
	}
	internal static class ExtraSlotsCompat
	{
		private static bool _resolved;

		private static MethodInfo _getEquipmentSlotsItems;

		internal static bool IsAvailable => Resolve();

		private static bool Resolve()
		{
			if (_resolved)
			{
				return _getEquipmentSlotsItems != null;
			}
			_resolved = true;
			Type type = AccessTools.TypeByName("ExtraSlots.API");
			if (type == null)
			{
				LtrLog.Debug("未检测到 ExtraSlots.API。");
				return false;
			}
			_getEquipmentSlotsItems = AccessTools.Method(type, "GetEquipmentSlotsItems", (Type[])null, (Type[])null);
			if (_getEquipmentSlotsItems == null)
			{
				LtrLog.Warn("检测到 ExtraSlots 但 API 方法缺失,跳过额外槽检测。");
			}
			return _getEquipmentSlotsItems != null;
		}

		internal static List<ItemData> GetEquippedSlotItems()
		{
			if (!Resolve())
			{
				return null;
			}
			try
			{
				return _getEquipmentSlotsItems.Invoke(null, null) as List<ItemData>;
			}
			catch (Exception ex)
			{
				LtrLog.Debug("ExtraSlots.GetEquipmentSlotsItems 调用失败: " + ex.Message);
				return null;
			}
		}
	}
	internal static class LtrLog
	{
		internal static void Info(string message)
		{
			ManualLogSource log = LuckyTrinketPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)message);
			}
		}

		internal static void Warn(string message)
		{
			ManualLogSource log = LuckyTrinketPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)message);
			}
		}

		internal static void Error(string message, Exception exception = null)
		{
			if (exception == null)
			{
				ManualLogSource log = LuckyTrinketPlugin.Log;
				if (log != null)
				{
					log.LogError((object)message);
				}
			}
			else
			{
				ManualLogSource log2 = LuckyTrinketPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)$"{message} {exception}");
				}
			}
		}

		internal static void Debug(string message)
		{
			if (LuckyTrinketPlugin.DebugLog != null && LuckyTrinketPlugin.DebugLog.Value)
			{
				ManualLogSource log = LuckyTrinketPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[debug] " + message));
				}
			}
		}
	}
	internal static class LuckyTrinketItems
	{
		private const string BasePrefab = "TrinketBronzeHealth";

		private static bool _registered;

		internal static void Register()
		{
			PrefabManager.OnVanillaPrefabsAvailable += RegisterItem;
			LtrLog.Info("已订阅 PrefabManager.OnVanillaPrefabsAvailable(克隆基础物品 TrinketBronzeHealth)");
		}

		private static void RegisterItem()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			if (_registered)
			{
				return;
			}
			try
			{
				RegisterTrinket("LuckyTrinket", new Color(1f, 0.82f, 0.25f, 1f), 200, "$item_luckytrinket", "$item_luckytrinket_desc", (RequirementConfig[])(object)new RequirementConfig[3]
				{
					new RequirementConfig("Wood", 10, 0, true),
					new RequirementConfig("BoneFragments", 10, 0, true),
					new RequirementConfig("Coins", 50, 0, true)
				});
				RegisterTrinket("GreatLuckTrinket", new Color(0.85f, 0.2f, 0.85f, 1f), 500, "$item_greatlucktrinket", "$item_greatlucktrinket_desc", (RequirementConfig[])(object)new RequirementConfig[2]
				{
					new RequirementConfig("LuckyTrinket", 1, 0, true),
					new RequirementConfig("Iron", 10, 0, true)
				});
				_registered = true;
			}
			catch (Exception exception)
			{
				LtrLog.Error("注册护符失败: ", exception);
			}
		}

		private static void RegisterTrinket(string prefabName, Color tint, int value, string nameToken, string descToken, RequirementConfig[] requirements)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			ItemConfig val = new ItemConfig
			{
				Name = prefabName,
				Description = prefabName,
				CraftingStation = "piece_workbench",
				MinStationLevel = 1,
				Amount = 1,
				Requirements = requirements,
				Weight = 1.5f
			};
			CustomItem val2 = new CustomItem(prefabName, "TrinketBronzeHealth", val);
			if ((Object)(object)val2.ItemPrefab == (Object)null)
			{
				LtrLog.Error("[" + prefabName + "] CustomItem 克隆 TrinketBronzeHealth 失败。");
				return;
			}
			Sanitize(val2, prefabName, tint, value, nameToken, descToken);
			ItemManager.Instance.AddItem(val2);
			CustomRecipe recipe = val2.Recipe;
			string[] obj = new string[6] { "[", prefabName, "] 物品与配方注册完成(工作台=", null, null, null };
			object obj2;
			if (recipe == null)
			{
				obj2 = null;
			}
			else
			{
				Recipe recipe2 = recipe.Recipe;
				if (recipe2 == null)
				{
					obj2 = null;
				}
				else
				{
					CraftingStation craftingStation = recipe2.m_craftingStation;
					obj2 = ((craftingStation != null) ? ((Object)craftingStation).name : null);
				}
			}
			if (obj2 == null)
			{
				obj2 = "null";
			}
			obj[3] = (string)obj2;
			obj[4] = ", ";
			obj[5] = $"材料={requirements.Length} 项)。";
			LtrLog.Info(string.Concat(obj));
			ExportIconForModPackaging(val2.ItemDrop.m_itemData.m_shared, prefabName);
		}

		private static void ExportIconForModPackaging(SharedData shared, string prefabName)
		{
			try
			{
				Sprite val = ((shared?.m_icons != null && shared.m_icons.Length != 0) ? shared.m_icons[0] : null);
				Texture2D val2 = (((Object)(object)val != (Object)null) ? val.texture : null);
				if ((Object)(object)val2 == (Object)null)
				{
					LtrLog.Warn("护符图标导出跳过:纹理为空。");
					return;
				}
				byte[] array = ImageConversion.EncodeToPNG(val2);
				if (array == null || array.Length == 0)
				{
					LtrLog.Warn("护符图标导出失败:PNG 数据为空。");
					return;
				}
				string text = Path.Combine(Paths.PluginPath, "LuckyTrinket");
				Directory.CreateDirectory(text);
				string path = ((prefabName == "LuckyTrinket") ? "icon-export.png" : ("icon-export-" + prefabName + ".png"));
				string text2 = Path.Combine(text, path);
				File.WriteAllBytes(text2, array);
				LtrLog.Info($"护符图标已导出: {text2}({((Texture)val2).width}x{((Texture)val2).height}, {array.Length} bytes)");
			}
			catch (Exception ex)
			{
				LtrLog.Warn("护符图标导出失败: " + ex.Message);
			}
		}

		private static void Sanitize(CustomItem item, string prefabName, Color tint, int value, string nameToken, string descToken)
		{
			//IL_0036: 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_0091: 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)
			ItemDrop itemDrop = item.ItemDrop;
			if ((Object)(object)itemDrop == (Object)null)
			{
				LtrLog.Error("[" + prefabName + "] 没有 ItemDrop 组件。");
				return;
			}
			SharedData shared = itemDrop.m_itemData.m_shared;
			shared.m_itemType = (ItemType)18;
			shared.m_maxStackSize = 1;
			shared.m_maxQuality = 1;
			shared.m_weight = 1.5f;
			shared.m_value = value;
			shared.m_teleportable = true;
			shared.m_questItem = false;
			shared.m_name = nameToken;
			shared.m_description = descToken;
			StripInheritedEffects(shared, "注册");
			RecolorIcons(shared, tint);
			RecolorRenderers(item.ItemPrefab, tint);
			string text = $"[{prefabName}] 属性: type={shared.m_itemType}, ";
			object arg = shared.m_weight;
			Sprite[] icons = shared.m_icons;
			LtrLog.Info(text + $"weight={arg}, icons={((icons != null) ? icons.Length : 0)}, name={shared.m_name}");
		}

		internal static void StripInheritedEffects(SharedData shared, string context)
		{
			if (shared != null)
			{
				LtrLog.Info("[" + context + "] 清理前: equipSE=" + NameOf((Object)(object)shared.m_equipStatusEffect) + ", setSE=" + NameOf((Object)(object)shared.m_setStatusEffect) + ", attackSE=" + NameOf((Object)(object)shared.m_attackStatusEffect) + ", consumeSE=" + NameOf((Object)(object)shared.m_consumeStatusEffect) + ", perfectBlockSE=" + NameOf((Object)(object)shared.m_perfectBlockStatusEffect) + ", fullAdrenalineSE=" + NameOf((Object)(object)shared.m_fullAdrenalineSE) + ", appendToolTip=" + NameOf((Object)(object)shared.m_appendToolTip) + ", " + $"maxAdrenaline={shared.m_maxAdrenaline}, " + $"blockAdrenaline={shared.m_blockAdrenaline}, " + $"perfectBlockAdrenaline={shared.m_perfectBlockAdrenaline}");
				shared.m_equipStatusEffect = null;
				shared.m_setStatusEffect = null;
				shared.m_attackStatusEffect = null;
				shared.m_consumeStatusEffect = null;
				shared.m_perfectBlockStatusEffect = null;
				shared.m_fullAdrenalineSE = null;
				shared.m_appendToolTip = null;
				shared.m_setName = "";
				shared.m_setSize = 0;
				shared.m_maxAdrenaline = 0f;
				shared.m_blockAdrenaline = 0f;
				shared.m_perfectBlockAdrenaline = 0f;
				shared.m_eitrRegenModifier = 0f;
				shared.m_movementModifier = 0f;
				shared.m_homeItemsStaminaModifier = 0f;
				shared.m_heatResistanceModifier = 0f;
				shared.m_jumpStaminaModifier = 0f;
				shared.m_attackStaminaModifier = 0f;
				shared.m_blockStaminaModifier = 0f;
				shared.m_dodgeStaminaModifier = 0f;
				shared.m_swimStaminaModifier = 0f;
				shared.m_sneakStaminaModifier = 0f;
				shared.m_runStaminaModifier = 0f;
				shared.m_iceSkates = false;
				shared.m_iceShoes = false;
				shared.m_food = 0f;
				shared.m_foodStamina = 0f;
				shared.m_foodEitr = 0f;
				shared.m_foodBurnTime = 0f;
				shared.m_foodRegen = 0f;
				shared.m_isDrink = false;
			}
		}

		private static string NameOf(Object obj)
		{
			if (!(obj == (Object)null))
			{
				return obj.name;
			}
			return "null";
		}

		private static void RecolorIcons(SharedData shared, Color tint)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (shared.m_icons == null || shared.m_icons.Length == 0)
			{
				LtrLog.Warn("[LuckyTrinket] m_icons 为空,跳过图标染色。");
				return;
			}
			for (int i = 0; i < shared.m_icons.Length; i++)
			{
				shared.m_icons[i] = RecolorSprite(shared.m_icons[i], tint);
			}
		}

		private static Sprite RecolorSprite(Sprite src, Color tint)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: 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_00e7: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)src == (Object)null)
			{
				return null;
			}
			Texture2D texture = src.texture;
			if ((Object)(object)texture == (Object)null)
			{
				return src;
			}
			Rect textureRect = src.textureRect;
			int num = Mathf.Max(1, Mathf.RoundToInt(((Rect)(ref textureRect)).width));
			int num2 = Mathf.Max(1, Mathf.RoundToInt(((Rect)(ref textureRect)).height));
			int num3 = Mathf.Max(1, ((Texture)texture).width);
			int num4 = Mathf.Max(1, ((Texture)texture).height);
			RenderTexture temporary = RenderTexture.GetTemporary(num3, num4, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			RenderTexture active = RenderTexture.active;
			try
			{
				Graphics.Blit((Texture)(object)texture, temporary);
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false);
				val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0);
				val.Apply();
				Color32[] pixels = val.GetPixels32();
				for (int i = 0; i < pixels.Length; i++)
				{
					Color32 val2 = pixels[i];
					if (val2.a != 0)
					{
						float num5 = (float)Mathf.Max((int)val2.r, Mathf.Max((int)val2.g, (int)val2.b)) / 255f;
						num5 = Mathf.Clamp01(0.2f + 0.8f * num5);
						pixels[i] = new Color32((byte)(tint.r * 255f * num5), (byte)(tint.g * 255f * num5), (byte)(tint.b * 255f * num5), val2.a);
					}
				}
				val.SetPixels32(pixels);
				val.Apply();
				return Sprite.Create(val, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f), src.pixelsPerUnit, 0u, (SpriteMeshType)0);
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}

		private static void RecolorRenderers(GameObject root, Color tint)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] materials = componentsInChildren[i].materials;
				foreach (Material val in materials)
				{
					if (!((Object)(object)val == (Object)null))
					{
						if (val.HasProperty("_Color"))
						{
							val.SetColor("_Color", tint);
							num++;
						}
						if (val.HasProperty("_EmissionColor"))
						{
							val.SetColor("_EmissionColor", tint * 0.35f);
						}
					}
				}
			}
			LtrLog.Info(string.Format("[{0}] 模型材质染色: {1} 处。", "LuckyTrinket", num));
		}
	}
	internal static class LuckyTrinketLocalization
	{
		internal const string ItemName = "$item_luckytrinket";

		internal const string ItemDesc = "$item_luckytrinket_desc";

		internal const string GreatItemName = "$item_greatlucktrinket";

		internal const string GreatItemDesc = "$item_greatlucktrinket_desc";

		internal const string WornPoolLine = "$item_greatlucktrinket_wornpool";

		private static readonly (string, string, string, string)[] Translations = new(string, string, string, string)[5]
		{
			("$item_luckytrinket", "Lucky Trinket", "幸运护符", "幸運護符"),
			("$item_luckytrinket_desc", "A charm touched by fortune. While equipped: magic gear dropped near you never rolls below this charm's own rarity - it does not upgrade drop quality, it removes low-quality drops instead (equipment below the floor is discarded; materials one step below are kept). Starts unenchanted - enchant it at the enchanting table to choose its rarity, and re-enchant it later to upgrade.", "一枚被幸运眷顾的护符。佩戴时,附近掉落的魔法装备品质不会低于这枚护符——不会提升掉落物品品质,而是取消低品质物品掉落(低于门槛的装备不再掉落;材料允许低一级保留)。护符初始未附魔——在附魔台附魔选择品质,之后可重新附魔升级。", "一枚被幸運眷顧的護符。佩戴時,附近掉落的魔法裝備品質不會低於這枚護符——不會提升掉落物品品質,而是取消低品質物品掉落(低於門檻的裝備不再掉落;材料允許低一級保留)。護符初始未附魔——在附魔台附魔選擇品質,之後可重新附魔升級。"),
			("$item_greatlucktrinket", "Great Fortune Trinket", "强运护符", "強運護符"),
			("$item_greatlucktrinket_desc", "A charm overflowing with fortune. While equipped: magic gear dropped near you never rolls below this charm's own rarity (it does not upgrade drop quality, it removes low-quality drops instead), and your worn equipment is added to nearby drop pools, so you can find your own gear as loot (other loot is unaffected; injected gear rolls the pool's original rarity odds). Starts unenchanted - enchant it at the enchanting table to choose its rarity, and re-enchant it later to upgrade.", "一枚被强运笼罩的护符。佩戴时,附近掉落的魔法装备品质不会低于这枚护符(不会提升掉落物品品质,而是取消低品质物品掉落),并把你身上可附魔的穿戴装备加入附近掉落池,可以掉到自己穿的装备(其他掉落不受影响;注入装备按原池品质几率 roll)。护符初始未附魔——在附魔台附魔选择品质,之后可重新附魔升级。", "一枚被強運籠罩的護符。佩戴時,附近掉落的魔法裝備品質不會低於這枚護符(不會提升掉落物品品質,而是取消低品質物品掉落),並把你身上可附魔的穿戴裝備加入附近掉落池,可以掉到自己穿的裝備(其他掉落不受影響;注入裝備按原池品質機率 roll)。護符初始未附魔——在附魔台附魔選擇品質,之後可重新附魔升級。"),
			("$item_greatlucktrinket_wornpool", "Innate: your worn equipment is added to nearby drop pools", "固有:你身上穿戴的装备会加入附近掉落池", "固有:你身上穿戴的裝備會加入附近掉落池")
		};

		internal static void Register()
		{
			try
			{
				CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
				(string, string, string, string)[] translations = Translations;
				for (int i = 0; i < translations.Length; i++)
				{
					(string, string, string, string) tuple = translations[i];
					string text = "English";
					localization.AddTranslation(ref text, ref tuple.Item1, tuple.Item2);
					text = "Chinese";
					localization.AddTranslation(ref text, ref tuple.Item1, tuple.Item3);
					text = "Chinese_Trad";
					localization.AddTranslation(ref text, ref tuple.Item1, tuple.Item4);
				}
				LtrLog.Info($"本地化已注册:{Translations.Length} 个条目 × 3 种语言。");
			}
			catch (Exception exception)
			{
				LtrLog.Error("本地化注册失败: ", exception);
			}
		}

		internal static string L(string token)
		{
			Localization instance = Localization.instance;
			if (instance == null)
			{
				return token;
			}
			return instance.Localize(token);
		}
	}
	internal static class Patches
	{
		internal static void Install(Harmony harmony)
		{
			HarmonyMethod postfix = HarmonyMethodFor("EquipOrUnequip_Postfix");
			TryPatch(harmony, AccessTools.Method(typeof(Humanoid), "EquipItem", new Type[2]
			{
				typeof(ItemData),
				typeof(bool)
			}, (Type[])null), null, postfix, null, "Humanoid.EquipItem");
			TryPatch(harmony, AccessTools.Method(typeof(Humanoid), "UnequipItem", new Type[2]
			{
				typeof(ItemData),
				typeof(bool)
			}, (Type[])null), null, postfix, null, "Humanoid.UnequipItem");
			InstallLootContextPatches(harmony);
			InstallDropDebugPatches(harmony);
			TryPatch(harmony, AccessTools.Method(typeof(EnchantingUIController), "GetEnchantableItems", (Type[])null, (Type[])null), null, HarmonyMethodFor("GetEnchantableItems_Postfix"), null, "EnchantingUIController.GetEnchantableItems");
			TryPatch(harmony, AccessTools.Method(typeof(LootRoller), "RollMagicItem", new Type[4]
			{
				typeof(ItemRarity),
				typeof(ItemData),
				typeof(float),
				typeof(float)
			}, (Type[])null), null, HarmonyMethodFor("RollMagicItem_Postfix"), null, "LootRoller.RollMagicItem(ItemRarity, ItemData, float, float)");
			TryPatch(harmony, AccessTools.Method(typeof(ItemData), "GetTooltip", new Type[6]
			{
				typeof(ItemData),
				typeof(int),
				typeof(bool),
				typeof(float),
				typeof(int),
				typeof(bool)
			}, (Type[])null), null, HarmonyMethodFor("GetTooltip_Postfix"), null, "ItemDrop.ItemData.GetTooltip");
		}

		private static void InstallLootContextPatches(Harmony harmony)
		{
			HarmonyMethod prefix = HarmonyMethodFor("RollLootTableInternal_Prefix");
			HarmonyMethod finalizer = HarmonyMethodFor("RollLootTableInternal_Finalizer");
			int num = 0;
			foreach (MethodInfo item in from m in AccessTools.GetDeclaredMethods(typeof(LootRoller))
				where m.Name == "RollLootTableInternal"
				select m)
			{
				if (TryPatch(harmony, item, prefix, null, finalizer, "LootRoller.RollLootTableInternal(" + Describe(item.GetParameters()) + ")"))
				{
					num++;
				}
			}
			if (num == 0)
			{
				LtrLog.Error("未注入任何 RollLootTableInternal,掉落品质下限不生效(EpicLoot 版本可能不兼容)。");
			}
			TryPatch(harmony, AccessTools.Method(typeof(LootRoller), "GetLootForLevel", (Type[])null, (Type[])null), null, HarmonyMethodFor("GetLootForLevel_Postfix"), null, "LootRoller.GetLootForLevel");
		}

		private static void InstallDropDebugPatches(Harmony harmony)
		{
			TryPatch(harmony, AccessTools.Method(typeof(LootRoller), "GetDropsForLevel", (Type[])null, (Type[])null), null, HarmonyMethodFor("GetDropsForLevel_Postfix"), null, "LootRoller.GetDropsForLevel");
			TryPatch(harmony, AccessTools.Method(typeof(LootRoller), "SelectDropType", (Type[])null, (Type[])null), null, HarmonyMethodFor("SelectDropType_Postfix"), null, "LootRoller.SelectDropType");
		}

		private static void EquipOrUnequip_Postfix(Humanoid __instance)
		{
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val != null)
			{
				RarityFloorSystem.Refresh(val);
			}
		}

		private static void GetEnchantableItems_Postfix(ref List<InventoryItemListElement> __result)
		{
			//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_0079: Expected O, but got Unknown
			try
			{
				if (__result == null)
				{
					return;
				}
				InventoryManagement instance = InventoryManagement.Instance;
				List<ItemData> list = ((instance != null) ? instance.GetAllItems() : null);
				if (list == null)
				{
					return;
				}
				foreach (ItemData item in list)
				{
					if (RarityFloorSystem.IsAnyTrinket(item) && !__result.Any((InventoryItemListElement element) => element.Item == item))
					{
						__result.Add(new InventoryItemListElement
						{
							Item = item
						});
					}
				}
			}
			catch (Exception ex)
			{
				LtrLog.Debug("补充护符到附魔列表异常: " + ex.Message);
			}
		}

		private static void RollMagicItem_Postfix(ItemData baseItem, ref MagicItem __result)
		{
			if (__result != null && RarityFloorSystem.IsAnyTrinket(baseItem))
			{
				RarityFloorSystem.StripTrinketFlavor(__result);
			}
		}

		private static void GetTooltip_Postfix(ref string __result, ItemData item, bool appending)
		{
			if (!appending && item != null && !string.IsNullOrEmpty(__result) && RarityFloorSystem.IsAnyTrinket(item) && RarityFloorSystem.IsGreatTrinket(item))
			{
				string text = LuckyTrinketLocalization.L("$item_greatlucktrinket_wornpool");
				__result = __result + "\n<color=#C77DFF>" + text + "</color>";
			}
		}

		private static void RollLootTableInternal_Prefix(object[] __args)
		{
			//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_0047: Unknown result type (might be due to invalid IL or missing references)
			Vector3? val = null;
			string objectName = null;
			int level = 0;
			bool flag = false;
			if (__args != null)
			{
				flag = __args.Length != 0 && __args[0] is LootTable;
				foreach (object obj in __args)
				{
					if (obj is Vector3 value)
					{
						val = value;
					}
					else if (obj is string text)
					{
						objectName = text;
					}
					else if (obj is int num)
					{
						level = num;
					}
				}
			}
			DropDebug.EnterContext(flag);
			RarityFloorSystem.EnterDropContext(val);
			if (flag)
			{
				DropDebug.LogContextStart(objectName, level, val);
			}
		}

		private static void RollLootTableInternal_Finalizer(ref List<GameObject> __result)
		{
			RarityFloorSystem.FilterDroppedItems(ref __result);
			RarityFloorSystem.ExitDropContext();
			DropDebug.ExitContext();
		}

		private static void GetLootForLevel_Postfix(ref LootDrop[] __result)
		{
			RarityFloorSystem.InjectWornItems(ref __result);
		}

		private static void GetDropsForLevel_Postfix(LootTable lootTable, int level, ref List<KeyValuePair<int, float>> __result)
		{
			DropDebug.LogCountTable(lootTable, level, __result);
		}

		private static void SelectDropType_Postfix(LootDrop lootDrop, bool isShardDrop, ref LootDropType __result)
		{
			DropDebug.OnDropTypeSelected(lootDrop, isShardDrop, __result, RarityFloorSystem.IsInjectedItem(lootDrop?.Item));
		}

		private static bool TryPatch(Harmony harmony, MethodBase target, HarmonyMethod prefix, HarmonyMethod postfix, HarmonyMethod finalizer, string label)
		{
			if (target == null)
			{
				LtrLog.Warn("未找到目标方法,跳过: " + label);
				return false;
			}
			try
			{
				harmony.Patch(target, prefix, postfix, (HarmonyMethod)null, finalizer, (HarmonyMethod)null);
				LtrLog.Info("已注入: " + label);
				return true;
			}
			catch (Exception exception)
			{
				LtrLog.Error("注入失败 " + label + ": ", exception);
				return false;
			}
		}

		private static HarmonyMethod HarmonyMethodFor(string name)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(Patches), name, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				throw new MissingMethodException("Patches." + name + " 不存在");
			}
			return new HarmonyMethod(methodInfo);
		}

		private static string Describe(ParameterInfo[] parameters)
		{
			return string.Join(", ", parameters.Select((ParameterInfo p) => p.ParameterType.Name));
		}
	}
	[BepInPlugin("trigger.epicloot.luckytrinket", "EpicLoot Luck Trinket", "0.3.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class LuckyTrinketPlugin : BaseUnityPlugin
	{
		public const string Guid = "trigger.epicloot.luckytrinket";

		public const string PluginName = "EpicLoot Luck Trinket";

		public const string PluginVersion = "0.3.0";

		internal const string ItemPrefab = "LuckyTrinket";

		internal const string GreatItemPrefab = "GreatLuckTrinket";

		internal static LuckyTrinketPlugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> Range;

		internal static ConfigEntry<int> MaterialTolerance;

		internal static ConfigEntry<bool> DebugLog;

		internal static ConfigEntry<bool> WornPool;

		internal static ConfigEntry<float> WornPoolShare;

		internal static ConfigEntry<float> WornPoolWeight;

		internal static ConfigEntry<float> WornPoolHeldWeaponWeight;

		internal static ConfigEntry<float> WornPoolUtilityWeight;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Expected O, but got Unknown
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "启用幸运护符的掉落品质下限效果。");
			Range = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Range", 100f, new ConfigDescription("生效半径(米):掉落点附近该范围内的装备者护符参与门槛计算,取最高品质。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>()));
			MaterialTolerance = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaterialTolerance", 1, new ConfigDescription("带品质材料(碎片石/魔法材料/符文)允许低于门槛多少级保留:0 = 只保留达到门槛的材料,1 = 低一级的材料也保留,5 = 所有材料都保留。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 5), Array.Empty<object>()));
			DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLog", false, "输出详细调试日志(排查用,默认关闭)。");
			WornPool = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "WornPool", true, "强运护符的穿戴装备注入:把你身上穿戴的装备追加到附近掉落池,原掉落池条目不受影响;没有佩戴强运护符时无效果。");
			WornPoolShare = ((BaseUnityPlugin)this).Config.Bind<float>("General", "WornPoolShare", 0.2f, new ConfigDescription("注入装备占掉落池总权重的比例:0.2 = 我们的装备约 20%、原版池约 80%。0 = 关闭注入。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.95f), Array.Empty<object>()));
			WornPoolWeight = ((BaseUnityPlugin)this).Config.Bind<float>("General", "WornPoolWeight", 1f, new ConfigDescription("注入组内每件穿戴装备的相对权重(组内比例;实际占池比例由 WornPoolShare 控制)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
			WornPoolHeldWeaponWeight = ((BaseUnityPlugin)this).Config.Bind<float>("General", "WornPoolHeldWeaponWeight", 2f, new ConfigDescription("手持武器在注入组内的相对权重(组内比例)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
			WornPoolUtilityWeight = ((BaseUnityPlugin)this).Config.Bind<float>("General", "WornPoolUtilityWeight", 0.4f, new ConfigDescription("饰品(Utility 类型)在注入组内的相对权重;仅在安装 ExtraSlots 时生效。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
			LtrLog.Info("EpicLoot Luck Trinket v0.3.0 初始化中...");
			_harmony = new Harmony("trigger.epicloot.luckytrinket");
			Patches.Install(_harmony);
			LuckyTrinketLocalization.Register();
			LuckyTrinketItems.Register();
			RarityFloorSystem.Register();
			LtrLog.Info("EpicLoot Luck Trinket v0.3.0 初始化完成。" + $"Enabled={Enabled.Value}, Range={Range.Value}, " + $"WornPool={WornPool.Value}, WornPoolWeight={WornPoolWeight.Value}");
		}

		private void Update()
		{
			RarityFloorSystem.Update();
		}

		private void OnDestroy()
		{
			RarityFloorSystem.Unregister();
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}
	}
	internal static class RarityFloorSystem
	{
		internal const string ZdoKey = "ltr-floor";

		internal const string WornZdoKey = "ltr-worn";

		private const float AutoRefreshInterval = 5f;

		[ThreadStatic]
		private static Stack<int> s_floorStack;

		[ThreadStatic]
		private static int s_contextFloor;

		[ThreadStatic]
		private static Stack<Dictionary<string, float>> s_wornStack;

		[ThreadStatic]
		private static Dictionary<string, float> s_contextWorn;

		[ThreadStatic]
		private static Stack<HashSet<string>> s_injectedStack;

		[ThreadStatic]
		private static HashSet<string> s_contextInjected;

		[ThreadStatic]
		private static List<Player> s_playerBuffer;

		private static float s_nextAutoRefresh;

		private static bool s_prefabSanitized;

		internal static int ContextFloor
		{
			get
			{
				if (s_floorStack == null || s_floorStack.Count <= 0)
				{
					return -1;
				}
				return s_contextFloor;
			}
		}

		private static Dictionary<string, float> ContextWorn
		{
			get
			{
				if (s_wornStack == null || s_wornStack.Count <= 0)
				{
					return null;
				}
				return s_contextWorn;
			}
		}

		internal static bool IsInjectedItem(string itemName)
		{
			if (!string.IsNullOrEmpty(itemName) && s_contextInjected != null)
			{
				return s_contextInjected.Contains(itemName);
			}
			return false;
		}

		internal static void Register()
		{
			API.AddMagicItemChangedListener((Action<ItemData, string>)OnMagicItemChanged);
			LtrLog.Info("已注册 EpicLoot MagicItemChanged 监听器。");
		}

		internal static void Unregister()
		{
			API.RemoveMagicItemChangedListener((Action<ItemData, string>)OnMagicItemChanged);
		}

		internal static void Update()
		{
			if (!(Time.time < s_nextAutoRefresh))
			{
				s_nextAutoRefresh = Time.time + 5f;
				TrySanitizePrefabOnce();
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					Refresh(localPlayer);
				}
			}
		}

		private static void TrySanitizePrefabOnce()
		{
			if (s_prefabSanitized || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("LuckyTrinket");
			if (!((Object)(object)itemPrefab == (Object)null))
			{
				ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
				SharedData val = (((Object)(object)component != (Object)null) ? component.m_itemData.m_shared : null);
				if (val != null)
				{
					LuckyTrinketItems.StripInheritedEffects(val, "运行时兜底");
					s_prefabSanitized = true;
				}
			}
		}

		internal static void EnterDropContext(Vector3? dropPoint)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if (s_floorStack == null)
			{
				s_floorStack = new Stack<int>();
			}
			s_floorStack.Push(s_contextFloor);
			if (s_wornStack == null)
			{
				s_wornStack = new Stack<Dictionary<string, float>>();
			}
			s_wornStack.Push(s_contextWorn);
			if (s_injectedStack == null)
			{
				s_injectedStack = new Stack<HashSet<string>>();
			}
			s_injectedStack.Push(s_contextInjected);
			s_contextInjected = null;
			int num = -1;
			Dictionary<string, float> dictionary = null;
			try
			{
				if (dropPoint.HasValue)
				{
					num = ComputeNearbyFloor(dropPoint.Value);
					dictionary = ComputeNearbyWorn(dropPoint.Value);
				}
			}
			catch (Exception ex)
			{
				LtrLog.Debug("ComputeNearbyFloor/ComputeNearbyWorn 异常: " + ex.Message);
				num = -1;
				dictionary = null;
			}
			if (num > s_contextFloor)
			{
				s_contextFloor = num;
			}
			if (dictionary != null && dictionary.Count > 0)
			{
				s_contextWorn = dictionary;
			}
			LtrLog.Debug($"进入掉落上下文: dropPoint={dropPoint}, floor={num}, " + $"worn={dictionary?.Count ?? 0}, active={s_contextFloor}");
			if (dictionary != null && dictionary.Count > 0)
			{
				LtrLog.Debug($"  穿戴装备名单({dictionary.Count}): {DescribeWorn(dictionary)}");
			}
		}

		internal static void ExitDropContext()
		{
			if (s_injectedStack != null && s_injectedStack.Count > 0)
			{
				s_contextInjected = s_injectedStack.Pop();
			}
			if (s_wornStack != null && s_wornStack.Count > 0)
			{
				s_contextWorn = s_wornStack.Pop();
			}
			if (s_floorStack != null && s_floorStack.Count != 0)
			{
				s_contextFloor = s_floorStack.Pop();
			}
		}

		internal static void FilterDroppedItems(ref List<GameObject> items)
		{
			if (!LuckyTrinketPlugin.Enabled.Value || items == null || items.Count == 0)
			{
				return;
			}
			int contextFloor = ContextFloor;
			if (contextFloor < 0)
			{
				LtrLog.Debug("掉落无门槛(附近无装备护符的玩家),跳过过滤" + $"({items.Count} 个物品)。");
				return;
			}
			DropDebug.LogRolledCount();
			int num = 0;
			for (int num2 = items.Count - 1; num2 >= 0; num2--)
			{
				GameObject val = items[num2];
				if ((Object)(object)val == (Object)null)
				{
					items.RemoveAt(num2);
				}
				else if (ShouldExclude(val, contextFloor))
				{
					if (LuckyTrinketPlugin.DebugLog.Value)
					{
						LtrLog.Debug($"剔除(门槛<{contextFloor}): {DropDebug.Describe(val)}");
					}
					DestroyLoot(val);
					items.RemoveAt(num2);
					num++;
				}
				else
				{
					DropDebug.OnItemKept(val);
					if (LuckyTrinketPlugin.DebugLog.Value)
					{
						LtrLog.Debug("保留掉落: " + DropDebug.Describe(val));
					}
				}
			}
			if (!LuckyTrinketPlugin.DebugLog.Value)
			{
				return;
			}
			List<string> list = new List<string>();
			foreach (GameObject item in items)
			{
				list.Add(DropDebug.Describe(item));
			}
			LtrLog.Debug($"过滤结果: roll={DropDebug.ContextCount}, 剔除门槛={num}, " + $"保留={items.Count}");
			LtrLog.Debug("最终掉落: " + ((list.Count > 0) ? string.Join("; ", list) : "(空)"));
			DropDebug.LogCumulative();
		}

		private static bool ShouldExclude(GameObject gameObject, int floor)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Invalid comparison between Unknown and I4
			try
			{
				ItemData val = gameObject.GetComponent<ItemDrop>()?.m_itemData;
				if (val == null)
				{
					return false;
				}
				MagicItem magicItem = ItemDataExtensions.GetMagicItem(val);
				bool flag = magicItem != null && (magicItem.IsUnidentified || ((Object)(object)val.m_dropPrefab != (Object)null && ((Object)val.m_dropPrefab).name.EndsWith("_Unidentified", StringComparison.Ordinal)));
				if (val.IsEquipable() || flag)
				{
					return magicItem != null && (int)magicItem.Rarity < floor;
				}
				int num = -1;
				if (API.TryGetRarity(val, ref num))
				{
					int num2 = Math.Max(0, floor - LuckyTrinketPlugin.MaterialTolerance.Value);
					return num < num2;
				}
				return false;
			}
			catch (Exception ex)
			{
				LtrLog.Debug("ShouldExclude 异常: " + ex.Message);
				return false;
			}
		}

		internal static void InjectWornItems(ref LootDrop[] loot)
		{
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Expected O, but got Unknown
			if (!LuckyTrinketPlugin.Enabled.Value || !LuckyTrinketPlugin.WornPool.Value)
			{
				return;
			}
			Dictionary<string, float> contextWorn = ContextWorn;
			if (contextWorn == null || contextWorn.Count == 0)
			{
				return;
			}
			float num = Mathf.Clamp(LuckyTrinketPlugin.WornPoolShare.Value, 0f, 0.95f);
			if (num <= 0f)
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			float num2 = 0f;
			if (loot != null)
			{
				LootDrop[] array = loot;
				foreach (LootDrop val in array)
				{
					if (val != null)
					{
						if (!string.IsNullOrEmpty(val.Item))
						{
							hashSet.Add(val.Item);
						}
						num2 += Math.Max(0f, val.Weight);
					}
				}
			}
			float num3 = 0f;
			List<KeyValuePair<string, float>> list = new List<KeyValuePair<string, float>>();
			foreach (KeyValuePair<string, float> item in contextWorn)
			{
				if (!string.IsNullOrEmpty(item.Key) && !hashSet.Contains(item.Key))
				{
					float num4 = ((item.Value > 0f) ? item.Value : LuckyTrinketPlugin.WornPoolWeight.Value);
					list.Add(new KeyValuePair<string, float>(item.Key, num4));
					num3 += num4;
				}
			}
			if (list.Count == 0 || num3 <= 0f)
			{
				return;
			}
			float num5 = ((num2 > 0f) ? (num2 * num / (1f - num)) : num3);
			float num6 = num5 / num3;
			float[] array2 = BuildInjectedRarity(loot);
			List<LootDrop> list2 = new List<LootDrop>();
			foreach (KeyValuePair<string, float> item2 in list)
			{
				list2.Add(new LootDrop
				{
					Item = item2.Key,
					Weight = Math.Max(0.0001f, item2.Value * num6),
					Rarity = array2
				});
			}
			LootDrop[] obj = loot;
			int num7 = ((obj != null) ? obj.Length : 0);
			LootDrop[] array3 = (LootDrop[])(object)new LootDrop[num7 + list2.Count];
			if (loot != null)
			{
				Array.Copy(loot, array3, num7);
			}
			for (int j = 0; j < list2.Count; j++)
			{
				array3[num7 + j] = list2[j];
			}
			loot = array3;
			if (s_contextInjected == null)
			{
				s_contextInjected = new HashSet<string>(StringComparer.Ordinal);
			}
			foreach (LootDrop item3 in list2)
			{
				s_contextInjected.Add(item3.Item);
			}
			if (!LuckyTrinketPlugin.DebugLog.Value)
			{
				return;
			}
			List<string> list3 = new List<string>();
			foreach (LootDrop item4 in list2)
			{
				list3.Add(item4.Item + "(" + item4.Weight.ToString("0.###", CultureInfo.InvariantCulture) + ")");
			}
			float num8 = ((num2 > 0f) ? (num5 / (num2 + num5)) : 1f);
			LtrLog.Debug($"注入掉落池: 追加 {list2.Count} 件穿戴装备" + "(原池总权重=" + num2.ToString("0.###", CultureInfo.InvariantCulture) + ", 注入总权重=" + num5.ToString("0.###", CultureInfo.InvariantCulture) + ", " + $"占比={num8 * 100f:0.#}%): " + string.Join(", ", list3));
			float num9 = AncientPercent(array2);
			DropDebug.SetBaselineAncientPercent(num9);
			LtrLog.Debug($"  品质分布(原池=注入,未钳制)=[{JoinWeights(array2)}] Ancient≈{num9:0.#}%");
		}

		private static float AncientPercent(float[] weights)
		{
			if (weights == null || weights.Length == 0)
			{
				return 0f;
			}
			float num = 0f;
			float num2 = 0f;
			for (int i = 0; i < weights.Length; i++)
			{
				float num3 = Math.Max(0f, weights[i]);
				num += num3;
				if (i >= 5)
				{
					num2 += num3;
				}
			}
			if (!(num > 0f))
			{
				return 0f;
			}
			return num2 / num * 100f;
		}

		private static string JoinWeights(float[] weights)
		{
			if (weights == null)
			{
				return "无";
			}
			List<string> list = new List<string>(weights.Length);
			foreach (float num in weights)
			{
				list.Add(num.ToString("0.###", CultureInfo.InvariantCulture));
			}
			return string.Join(",", list);
		}

		private static string DescribeWorn(Dictionary<string, float> worn)
		{
			if (worn == null || worn.Count == 0)
			{
				return "";
			}
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, float> item in worn)
			{
				list.Add(item.Key + "(" + item.Value.ToString("0.##", CultureInfo.InvariantCulture) + ")");
			}
			list.Sort(StringComparer.Ordinal);
			return string.Join(", ", list);
		}

		private static float[] BuildInjectedRarity(LootDrop[] pool)
		{
			int count = Rarities.Count;
			float[] array = new float[count];
			float[] array2 = null;
			if (pool != null)
			{
				foreach (LootDrop val in pool)
				{
					if (val?.Rarity != null && val.Rarity.Length == count)
					{
						array2 = val.Rarity;
						break;
					}
				}
			}
			if (array2 != null)
			{
				Array.Copy(array2, array, count);
			}
			else
			{
				array[0] = 1f;
			}
			return array;
		}

		private static void DestroyLoot(GameObject gameObject)
		{
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				ZNetScene.instance.Destroy(gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)gameObject);
			}
		}

		private static int ComputeNearbyFloor(Vector3 point)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!LuckyTrinketPlugin.Enabled.Value)
			{
				return -1;
			}
			List<Player> list = s_playerBuffer ?? (s_playerBuffer = new List<Player>());
			list.Clear();
			Player.GetPlayersInRange(point, LuckyTrinketPlugin.Range.Value, list);
			int num = -1;
			foreach (Player item in list)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				ZDO zdo = GetZdo((Component)(object)item);
				if (zdo != null)
				{
					int num2 = zdo.GetInt("ltr-floor", -1);
					if (num2 > num)
					{
						num = num2;
					}
				}
			}
			return num;
		}

		private static Dictionary<string, float> ComputeNearbyWorn(Vector3 point)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (!LuckyTrinketPlugin.Enabled.Value || !LuckyTrinketPlugin.WornPool.Value)
			{
				return null;
			}
			List<Player> list = s_playerBuffer ?? (s_playerBuffer = new List<Player>());
			list.Clear();
			Player.GetPlayersInRange(point, LuckyTrinketPlugin.Range.Value, list);
			Dictionary<string, float> dictionary = null;
			foreach (Player item in list)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				ZDO zdo = GetZdo((Component)(object)item);
				if (zdo == null)
				{
					continue;
				}
				string text = zdo.GetString("ltr-worn", "");
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				if (dictionary == null)
				{
					dictionary = new Dictionary<string, float>(StringComparer.Ordinal);
				}
				string[] array = text.Split(new char[1] { ',' });
				foreach (string text2 in array)
				{
					if (!string.IsNullOrEmpty(text2))
					{
						string text3 = text2;
						float num = LuckyTrinketPlugin.WornPoolWeight.Value;
						int num2 = text2.LastIndexOf(':');
						if (num2 > 0 && float.TryParse(text2.Substring(num2 + 1), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
						{
							text3 = text2.Substring(0, num2);
							num = result;
						}
						if (!string.IsNullOrEmpty(text3) && (!dictionary.TryGetValue(text3, out var value) || num > value))
						{
							dictionary[text3] = num;
						}
					}
				}
			}
			return dictionary;
		}

		internal static void Refresh(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			try
			{
				ZDO zdo = GetZdo((Component)(object)player);
				if (zdo != null)
				{
					int num = ComputePlayerFloor(player);
					if (zdo.GetInt("ltr-floor", -1) != num)
					{
						zdo.Set("ltr-floor", num);
						LtrLog.Debug($"装备者门槛 ZDO 更新: {num}");
					}
					string text = ComputeWornList(player);
					if (zdo.GetString("ltr-worn", "") != text)
					{
						zdo.Set("ltr-worn", text);
						LtrLog.Debug("装备者穿戴名单 ZDO 更新: [" + text + "]");
					}
					SanitizeOwnedTrinkets(player);
				}
			}
			catch (Exception exception)
			{
				LtrLog.Error("刷新玩家门槛失败: ", exception);
			}
		}

		internal static void StripTrinketFlavor(MagicItem magicItem)
		{
			List<MagicItemEffect> effects = magicItem.Effects;
			if (effects != null && effects.Count > 0)
			{
				effects.Clear();
			}
			magicItem.DisplayName = null;
		}

		private static void SanitizeOwnedTrinkets(Player player)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return;
			}
			MagicItem val = default(MagicItem);
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (IsAnyTrinket(allItem) && ItemDataExtensions.IsMagic(allItem, ref val) && val != null)
				{
					bool num = val.Effects != null && val.Effects.Count > 0;
					bool flag = !string.IsNullOrEmpty(val.DisplayName);
					if (num || flag)
					{
						StripTrinketFlavor(val);
						ItemDataExtensions.SaveMagicItem(allItem, val);
						LtrLog.Debug("已清除护符的随机词条/装饰名(只保留品质)。");
					}
				}
			}
		}

		private static int ComputePlayerFloor(Player player)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected I4, but got Unknown
			int num = -1;
			MagicItem val = default(MagicItem);
			foreach (ItemData item in CollectEquippedItems(player))
			{
				if (IsAnyTrinket(item) && ItemDataExtensions.IsMagic(item, ref val) && val != null)
				{
					int num2 = (int)val.Rarity;
					if (num2 > num)
					{
						num = num2;
					}
				}
			}
			return num;
		}

		private static string ComputeWornList(Player player)
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Invalid comparison between Unknown and I4
			if (!IsGreatTrinketEquipped(player))
			{
				return "";
			}
			float value = LuckyTrinketPlugin.WornPoolWeight.Value;
			float value2 = LuckyTrinketPlugin.WornPoolHeldWeaponWeight.Value;
			float value3 = LuckyTrinketPlugin.WornPoolUtilityWeight.Value;
			bool isAvailable = ExtraSlotsCompat.IsAvailable;
			ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon();
			List<string> list = new List<string>();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			foreach (ItemData item in CollectEquippedItems(player))
			{
				if (item == null || IsAnyTrinket(item) || !EpicLoot.CanBeMagicItem(item))
				{
					continue;
				}
				GameObject dropPrefab = item.m_dropPrefab;
				if (!((Object)(object)dropPrefab == (Object)null) && !string.IsNullOrEmpty(((Object)dropPrefab).name) && hashSet.Add(((Object)dropPrefab).name))
				{
					float num = value;
					if (currentWeapon != null && item == currentWeapon)
					{
						num = value2;
					}
					else if (isAvailable && item.m_shared != null && (int)item.m_shared.m_itemType == 18)
					{
						num = value3;
					}
					list.Add(((Object)dropPrefab).name + ":" + num.ToString("0.###", CultureInfo.InvariantCulture));
				}
			}
			list.Sort(StringComparer.Ordinal);
			return string.Join(",", list);
		}

		internal static bool IsGreatTrinketEquipped(Player player)
		{
			return IsTrinketEquipped(player, IsGreatTrinket);
		}

		private static bool IsTrinketEquipped(Player player, Func<ItemData, bool> predicate)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			foreach (ItemData item in CollectEquippedItems(player))
			{
				if (predicate(item))
				{
					return true;
				}
			}
			return false;
		}

		private static List<ItemData> CollectEquippedItems(Player player)
		{
			List<ItemData> list = new List<ItemData>();
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory != null)
			{
				list.AddRange(inventory.GetEquippedItems());
			}
			List<ItemData> equippedSlotItems = ExtraSlotsCompat.GetEquippedSlotItems();
			if (equippedSlotItems != null)
			{
				foreach (ItemData item in equippedSlotItems)
				{
					if (item != null && !list.Contains(item))
					{
						list.Add(item);
					}
				}
			}
			return list;
		}

		internal static bool IsLuckyTrinket(ItemData item)
		{
			return IsTrinketPrefab(item, "LuckyTrinket");
		}

		internal static bool IsGreatTrinket(ItemData item)
		{
			return IsTrinketPrefab(item, "GreatLuckTrinket");
		}

		internal static bool IsAnyTrinket(ItemData item)
		{
			if (!IsLuckyTrinket(item))
			{
				return IsGreatTrinket(item);
			}
			return true;
		}

		private static bool IsTrinketPrefab(ItemData item, string target)
		{
			GameObject val = item?.m_dropPrefab;
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			string name = ((Object)val).name;
			if (!(name == target))
			{
				return name.StartsWith(target + "(Clone)", StringComparison.Ordinal);
			}
			return true;
		}

		private static ZDO GetZdo(Component component)
		{
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			ZNetView component2 = component.GetComponent<ZNetView>();
			if ((Object)(object)component2 == (Object)null || !component2.IsValid())
			{
				return null;
			}
			return component2.GetZDO();
		}

		private static void OnMagicItemChanged(ItemData item, string reason)
		{
			try
			{
				if (IsAnyTrinket(item))
				{
					Player localPlayer = Player.m_localPlayer;
					if (!((Object)(object)localPlayer == (Object)null) && ((Humanoid)localPlayer).GetInventory().GetEquippedItems().Contains(item))
					{
						LtrLog.Debug("护符魔法数据变化(" + reason + "),刷新门槛。");
						Refresh(localPlayer);
					}
				}
			}
			catch (Exception ex)
			{
				LtrLog.Debug("OnMagicItemChanged 异常: " + ex.Message);
			}
		}
	}
}