Decompiled source of FTKRandomItemsStats v1.0.0

FTKRandomItemsStats.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using GridEditor;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("FTKRandomItemsStats")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FTKRandomItemsStats")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8c0b2ff8-0930-423c-8133-4d99bd2527bb")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FTKRandomItemsStats;

[HarmonyPatch]
public class ChatCommands
{
	private static Dictionary<string, string> statColors = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
	{
		{ "toughness", "#8B4513" },
		{ "vitality", "#32CD32" },
		{ "awareness", "#4B0082" },
		{ "quickness", "#FFA500" },
		{ "talent", "#C2B280" },
		{ "evade", "#006400" },
		{ "focus", "#FFFF00" },
		{ "armor", "#87CEEB" },
		{ "resistance", "#FF69B4" },
		{ "strength", "#8B0000" },
		{ "intelligence", "#ADD8E6" },
		{ "speed", "#008080" },
		{ "critChance", "#FF0000" }
	};

	[HarmonyPatch(typeof(GameFlow), "ChatMessage")]
	[HarmonyPrefix]
	private static bool ChatMessagePrefix(string _s)
	{
		if (!_s.StartsWith("/"))
		{
			return true;
		}
		string text = _s.ToLower().Trim();
		if (text == "/estats" || text == "/stats")
		{
			ShowPlayerStatsDetailed();
			return false;
		}
		return true;
	}

	private static void ShowPlayerStatsDetailed()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		CharacterOverworld currentCOW = GameLogic.Instance.GetCurrentCOW();
		if ((Object)(object)currentCOW == (Object)null)
		{
			return;
		}
		List<PlayerStatsManager.EquippedItemStat> equippedItems = PlayerStatsManager.GetEquippedItems(currentCOW.m_FTKPlayerID);
		_ = currentCOW.m_CharacterStats;
		if (equippedItems.Count == 0)
		{
			GameFlow.Instance.ChatMessage("=== Tus stats extra: Ninguno ===");
			GameFlow.Instance.ChatMessage("=== Your extra stats: None ===");
			return;
		}
		GameFlow.Instance.ChatMessage("=== Tus stats extra ===");
		foreach (PlayerStatsManager.EquippedItemStat item in equippedItems)
		{
			if (item.stats.Count == 0)
			{
				continue;
			}
			string text = item.itemName + ": ";
			for (int i = 0; i < item.stats.Count; i++)
			{
				PlayerStatsManager.PlayerStat playerStat = item.stats[i];
				string text2 = (statColors.ContainsKey(playerStat.statName) ? statColors[playerStat.statName] : "#FFFFFF");
				string text3 = ((playerStat.value >= 0) ? "+" : "");
				text += $"<color={text2}>{text3}{playerStat.value} {playerStat.statName}</color>";
				if (i < item.stats.Count - 1)
				{
					text += ", ";
				}
			}
			GameFlow.Instance.ChatMessage(text);
		}
		GameFlow.Instance.ChatMessage("=== Your extra stats ===");
		foreach (PlayerStatsManager.EquippedItemStat item2 in equippedItems)
		{
			if (item2.stats.Count == 0)
			{
				continue;
			}
			string text4 = item2.itemName + ": ";
			for (int j = 0; j < item2.stats.Count; j++)
			{
				PlayerStatsManager.PlayerStat playerStat2 = item2.stats[j];
				string text5 = (statColors.ContainsKey(playerStat2.statName) ? statColors[playerStat2.statName] : "#FFFFFF");
				string text6 = ((playerStat2.value >= 0) ? "+" : "");
				text4 += $"<color={text5}>{text6}{playerStat2.value} {playerStat2.statName}</color>";
				if (j < item2.stats.Count - 1)
				{
					text4 += ", ";
				}
			}
			GameFlow.Instance.ChatMessage(text4);
		}
	}
}
public static class ExtraStatsData
{
	public class ExtraStat
	{
		public string statName;

		public int value;
	}

	public static Dictionary<int, List<ExtraStat>> ItemMods = new Dictionary<int, List<ExtraStat>>();
}
public static class PlayerStatsManager
{
	public class EquippedItemStat
	{
		public string itemName;

		public List<PlayerStat> stats;
	}

	public class PlayerStat
	{
		public string statName;

		public int value;
	}

	private static Dictionary<FTKPlayerID, List<PlayerStat>> playerStats = new Dictionary<FTKPlayerID, List<PlayerStat>>();

	private static Dictionary<FTKPlayerID, List<EquippedItemStat>> equippedItems = new Dictionary<FTKPlayerID, List<EquippedItemStat>>();

	public static void AddPlayerStat(FTKPlayerID playerID, PlayerStat stat)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		if (!playerStats.ContainsKey(playerID))
		{
			playerStats[playerID] = new List<PlayerStat>();
		}
		playerStats[playerID].Add(stat);
		Debug.Log((object)string.Format("\ud83d\udcca [PlayerStats] {0}{1} {2} added to {3}. Total: {4}", (stat.value >= 0) ? "+" : "", stat.value, stat.statName, playerID, playerStats[playerID].Count));
	}

	public static List<PlayerStat> GetPlayerStats(FTKPlayerID playerID)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		if (playerStats.ContainsKey(playerID))
		{
			return playerStats[playerID];
		}
		return new List<PlayerStat>();
	}

	public static void RemovePlayerStatsForItem(FTKPlayerID playerID, List<PlayerStat> statsToRemove)
	{
		//IL_0005: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		if (!playerStats.ContainsKey(playerID))
		{
			return;
		}
		List<PlayerStat> list = playerStats[playerID];
		foreach (PlayerStat item in statsToRemove)
		{
			for (int num = list.Count - 1; num >= 0; num--)
			{
				if (list[num].statName == item.statName)
				{
					Debug.Log((object)$"\ud83d\udcca [PlayerStats] -{item.value} {item.statName} removed from {playerID}");
					list.RemoveAt(num);
					break;
				}
			}
		}
		Debug.Log((object)$"\ud83d\udcca [PlayerStats] Remaining stats for {playerID}: {list.Count}");
	}

	public static void DebugPrintStats(FTKPlayerID playerID)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		if (!playerStats.ContainsKey(playerID))
		{
			Debug.Log((object)$"\ud83d\udcca [PlayerStats] {playerID} has no stats");
			return;
		}
		string text = "";
		foreach (PlayerStat item in playerStats[playerID])
		{
			text += string.Format("{0}{1} {2}, ", (item.value >= 0) ? "+" : "", item.value, item.statName);
		}
		Debug.Log((object)$"\ud83d\udcca [PlayerStats] {playerID} current stats ({playerStats[playerID].Count} total): {text}");
	}

	public static void ClearAllPlayerStats(FTKPlayerID playerID)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: 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_0054: Unknown result type (might be due to invalid IL or missing references)
		if (playerStats.ContainsKey(playerID))
		{
			playerStats[playerID].Clear();
			Debug.Log((object)$"\ud83d\udcca [PlayerStats] Cleared all stats for {playerID}");
		}
		if (equippedItems.ContainsKey(playerID))
		{
			equippedItems[playerID].Clear();
			Debug.Log((object)$"\ud83d\udce6 [PlayerStats] Cleared all equipped items for {playerID}");
		}
	}

	public static void AddEquippedItem(FTKPlayerID playerID, string itemName, List<PlayerStat> stats)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		if (!equippedItems.ContainsKey(playerID))
		{
			equippedItems[playerID] = new List<EquippedItemStat>();
		}
		equippedItems[playerID].Add(new EquippedItemStat
		{
			itemName = itemName,
			stats = stats
		});
		Debug.Log((object)$"\ud83d\udce6 [PlayerStats] Added {itemName} with {stats.Count} stats to {playerID}. Total items: {equippedItems[playerID].Count}");
	}

	public static void RemoveEquippedItem(FTKPlayerID playerID, string itemName)
	{
		//IL_0005: 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_0028: 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_005c: Unknown result type (might be due to invalid IL or missing references)
		if (!equippedItems.ContainsKey(playerID))
		{
			return;
		}
		for (int num = equippedItems[playerID].Count - 1; num >= 0; num--)
		{
			if (equippedItems[playerID][num].itemName == itemName)
			{
				Debug.Log((object)$"\ud83d\udce6 [PlayerStats] Removed {itemName} from {playerID}");
				equippedItems[playerID].RemoveAt(num);
				break;
			}
		}
	}

	public static List<EquippedItemStat> GetEquippedItems(FTKPlayerID playerID)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		if (equippedItems.ContainsKey(playerID))
		{
			return equippedItems[playerID];
		}
		return new List<EquippedItemStat>();
	}
}
[HarmonyPatch(typeof(FTK_weaponStats2DB), "GetEntry")]
public class ExtraStatsPatch
{
	private static HashSet<int> needsExtraStats = new HashSet<int>();

	private static HashSet<int> generatedItems = new HashSet<int>();

	private static bool hasMarkedAllItems = false;

	private static void Postfix(ref FTK_weaponStats2 __result, ID _enumID)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected I4, but got Unknown
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		if (Main.EnableRandomization.Value && !((Object)(object)GameLogic.Instance == (Object)null))
		{
			int num = (int)_enumID;
			if (!ExtraStatsData.ItemMods.ContainsKey(num) && !needsExtraStats.Contains(num))
			{
				needsExtraStats.Add(num);
				Debug.Log((object)$"\ud83d\udd16 [FTKRandomItemsStats] {_enumID}: Marcado para generar stats extra al equipar");
			}
		}
	}

	public static void MarkAllWeapons()
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected I4, but got Unknown
		if (hasMarkedAllItems || !Main.EnableRandomization.Value)
		{
			return;
		}
		try
		{
			FTK_weaponStats2DB dB = FTK_weaponStats2DB.GetDB();
			if (!((Object)(object)dB != (Object)null) || ((GEDataArray<FTK_weaponStats2>)(object)dB).m_Array == null)
			{
				return;
			}
			FTK_weaponStats2[] array = ((GEDataArray<FTK_weaponStats2>)(object)dB).m_Array;
			foreach (FTK_weaponStats2 val in array)
			{
				if (val != null)
				{
					int num = (int)FTK_itembase.GetEnum(((GEDataBase)val).m_ID);
					if (!needsExtraStats.Contains(num) && !ExtraStatsData.ItemMods.ContainsKey(num))
					{
						needsExtraStats.Add(num);
						Debug.Log((object)("\ud83d\udd16 [FTKRandomItemsStats] Marcado por lotes: " + ((GEDataBase)val).m_ID));
					}
				}
			}
			hasMarkedAllItems = true;
			Debug.Log((object)$"✅ [FTKRandomItemsStats] Marcadas {needsExtraStats.Count} armas para stats extra");
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("❌ Error marcando armas: " + ex.Message));
		}
	}

	public static bool NeedsExtraStats(int itemKey)
	{
		return needsExtraStats.Contains(itemKey);
	}

	public static void GenerateExtraStatsForItem(int itemKey, int playerLuckSeed)
	{
		if (generatedItems.Contains(itemKey) || ExtraStatsData.ItemMods.ContainsKey(itemKey) || !needsExtraStats.Contains(itemKey))
		{
			return;
		}
		try
		{
			Random.InitState(GameLogic.Instance.m_MapGenRandomSeed + itemKey + 10000 + playerLuckSeed);
			int num = Random.Range(Main.ExtraStatsMinCount.Value, Main.ExtraStatsMaxCount.Value + 1);
			string[] array = Main.PossibleStats.Value.Split(new char[1] { ',' });
			string text = "";
			for (int i = 0; i < array.Length; i++)
			{
				if (i > 0)
				{
					text += ", ";
				}
				text += array[i];
			}
			Debug.Log((object)$"\ud83d\udd0d Stats posibles ({array.Length}): {text}");
			List<string> list = new List<string>(array);
			List<ExtraStatsData.ExtraStat> list2 = new List<ExtraStatsData.ExtraStat>();
			int num2 = 0;
			int num3 = 4;
			for (int j = 0; j < num; j++)
			{
				if (list.Count <= 0)
				{
					break;
				}
				int index = Random.Range(0, list.Count);
				string text2 = list[index];
				list.RemoveAt(index);
				int num4;
				if (num2 < num3 && Random.value < 0.3f)
				{
					num4 = Random.Range(-4, 0);
					num2++;
					Debug.Log((object)$"\ud83d\udd3b Stat negativo generado: {text2} = {num4}");
				}
				else
				{
					num4 = Random.Range(1, 7);
				}
				list2.Add(new ExtraStatsData.ExtraStat
				{
					statName = text2,
					value = num4
				});
			}
			if (list2.Count > 0)
			{
				ExtraStatsData.ItemMods[itemKey] = list2;
				generatedItems.Add(itemKey);
				string text3 = "";
				for (int k = 0; k < list2.Count; k++)
				{
					ExtraStatsData.ExtraStat extraStat = list2[k];
					if (k > 0)
					{
						text3 += ", ";
					}
					text3 += string.Format("{0}{1}{2}", extraStat.statName, (extraStat.value >= 0) ? "+" : "", extraStat.value);
				}
				Debug.Log((object)$"✨ [FTKRandomItemsStats] Generados {list2.Count} stats extra para item {itemKey}: {text3}");
			}
			needsExtraStats.Remove(itemKey);
		}
		catch (Exception ex)
		{
			Debug.LogError((object)("❌ Error generando stats extra: " + ex.Message));
		}
	}
}
[HarmonyPatch(typeof(CharacterOverworld), "EquipItemRPC")]
public class ApplyExtraStatsOnEquip
{
	private static Dictionary<int, List<string>> appliedStatsKeys = new Dictionary<int, List<string>>();

	private static Dictionary<FTKPlayerID, int> currentWeapon = new Dictionary<FTKPlayerID, int>();

	private static bool hasMarkedAll = false;

	private static void Postfix(CharacterOverworld __instance, ID _item, bool _isSwapWeapon = false)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Expected I4, but got Unknown
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: Unknown result type (might be due to invalid IL or missing references)
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		//IL_038b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		Debug.Log((object)$"\ud83d\udd0d [DIAGNOSTICO] EquipItemRPC ejecutado para {_item} | Frame: {Time.frameCount} | Tiempo: {Time.time}");
		if (!Main.EnableRandomization.Value)
		{
			return;
		}
		if (!hasMarkedAll)
		{
			ExtraStatsPatch.MarkAllWeapons();
			hasMarkedAll = true;
		}
		int num = (int)_item;
		CharacterStats characterStats = __instance.m_CharacterStats;
		if ((Object)(object)characterStats == (Object)null)
		{
			return;
		}
		string localizedName = FTK_itembase.GetItemBase(_item).GetLocalizedName();
		Debug.Log((object)$"\ud83d\udd27 [Equip] Player {characterStats.m_CharacterName} equipando {localizedName} ({_item})");
		if (currentWeapon.ContainsKey(__instance.m_FTKPlayerID) && currentWeapon[__instance.m_FTKPlayerID] == num)
		{
			Debug.Log((object)("\ud83d\udd27 [Equip] Misma arma detectada (" + localizedName + "), no se aplicarán stats duplicados"));
			return;
		}
		if (currentWeapon.ContainsKey(__instance.m_FTKPlayerID))
		{
			int num2 = currentWeapon[__instance.m_FTKPlayerID];
			if (appliedStatsKeys.ContainsKey(num2))
			{
				Debug.Log((object)$"\ud83d\udd27 [Equip] Removing old stats from weapon {num2}");
				foreach (string item in appliedStatsKeys[num2])
				{
					RemoveStatByKey(characterStats, item);
				}
				appliedStatsKeys.Remove(num2);
			}
			if (ExtraStatsData.ItemMods.ContainsKey(num2))
			{
				List<PlayerStatsManager.PlayerStat> list = new List<PlayerStatsManager.PlayerStat>();
				foreach (ExtraStatsData.ExtraStat item2 in ExtraStatsData.ItemMods[num2])
				{
					list.Add(new PlayerStatsManager.PlayerStat
					{
						statName = item2.statName,
						value = item2.value
					});
				}
				PlayerStatsManager.RemovePlayerStatsForItem(__instance.m_FTKPlayerID, list);
				PlayerStatsManager.RemoveEquippedItem(__instance.m_FTKPlayerID, FTK_itembase.GetItemBase((ID)num2).GetLocalizedName());
			}
		}
		if (ExtraStatsPatch.NeedsExtraStats(num))
		{
			int playerLuckSeed = (int)characterStats.Luck;
			ExtraStatsPatch.GenerateExtraStatsForItem(num, playerLuckSeed);
		}
		if (!ExtraStatsData.ItemMods.ContainsKey(num))
		{
			Debug.Log((object)("\ud83d\udd27 [Equip] No extra stats for " + localizedName));
			currentWeapon[__instance.m_FTKPlayerID] = num;
			return;
		}
		List<string> list2 = new List<string>();
		List<PlayerStatsManager.PlayerStat> list3 = new List<PlayerStatsManager.PlayerStat>();
		HashSet<string> hashSet = new HashSet<string>();
		foreach (ExtraStatsData.ExtraStat item3 in ExtraStatsData.ItemMods[num])
		{
			if (hashSet.Contains(item3.statName))
			{
				continue;
			}
			hashSet.Add(item3.statName);
			try
			{
				string text = ApplyStatAndGetKey(characterStats, item3.statName, item3.value);
				if (text != null)
				{
					list2.Add(text);
				}
				list3.Add(new PlayerStatsManager.PlayerStat
				{
					statName = item3.statName,
					value = item3.value
				});
				_ = item3.value;
				_ = 0;
			}
			catch (Exception ex)
			{
				if ((Object)(object)characterStats != (Object)null && (Object)(object)characterStats.m_CharacterOverworld != (Object)null)
				{
					characterStats.UpdateAllCharacterStats(false);
					characterStats.m_CharacterOverworld.m_UIPlayMainHud.UpdateHud();
				}
				Debug.LogError((object)("❌ Error aplicando " + item3.statName + ": " + ex.Message));
			}
		}
		if (list2.Count > 0)
		{
			appliedStatsKeys[num] = list2;
		}
		currentWeapon[__instance.m_FTKPlayerID] = num;
		foreach (PlayerStatsManager.PlayerStat item4 in list3)
		{
			PlayerStatsManager.AddPlayerStat(__instance.m_FTKPlayerID, item4);
		}
		if (list3.Count > 0)
		{
			PlayerStatsManager.AddEquippedItem(__instance.m_FTKPlayerID, localizedName, list3);
		}
		PlayerStatsManager.DebugPrintStats(__instance.m_FTKPlayerID);
		Debug.Log((object)$"✨ Aplicados {list3.Count} modificadores a {characterStats.m_CharacterName}");
		characterStats.UpdateAllCharacterStats(false);
	}

	private static string ApplyStatAndGetKey(CharacterStats stats, string statName, int value)
	{
		string text = statName.ToLower();
		float num = (float)Math.Abs(value) / 100f;
		int num2 = Math.Sign(value);
		string result = $"{statName}_{value}_{DateTime.Now.Ticks}";
		switch (text)
		{
		case "strength":
			stats.AugmentCharacterStat((SkillType)0, num * (float)num2);
			Debug.Log((object)string.Format("\ud83d\udd27 Strength aplicado: {0}{1}", (num2 > 0) ? "+" : "", value));
			break;
		case "vitality":
			stats.AugmentCharacterStat((SkillType)3, num * (float)num2);
			Debug.Log((object)string.Format("\ud83d\udd27 Vitality aplicado: {0}{1}", (num2 > 0) ? "+" : "", value));
			break;
		case "awareness":
			stats.AugmentCharacterStat((SkillType)2, num * (float)num2);
			Debug.Log((object)string.Format("\ud83d\udd27 Awareness aplicado: {0}{1}", (num2 > 0) ? "+" : "", value));
			break;
		case "speed":
			stats.AugmentCharacterStat((SkillType)4, num * (float)num2);
			Debug.Log((object)string.Format("\ud83d\udd27 Speed aplicado: {0}{1}", (num2 > 0) ? "+" : "", value));
			break;
		case "talent":
			stats.AugmentCharacterStat((SkillType)5, num * (float)num2);
			Debug.Log((object)string.Format("\ud83d\udd27 Talent aplicado: {0}{1}", (num2 > 0) ? "+" : "", value));
			break;
		case "intelligence":
			stats.AugmentCharacterStat((SkillType)1, num * (float)num2);
			Debug.Log((object)string.Format("\ud83e\udde0 Intelligence aplicado: {0}{1}", (num2 > 0) ? "+" : "", value));
			break;
		case "armor":
			stats.AugmentCharacterOther((TrainerType)2, (float)value);
			Debug.Log((object)string.Format("\ud83d\udd27 Armor aplicado: {0}{1}", (num2 > 0) ? "+" : "", value));
			break;
		case "resistance":
			stats.AugmentCharacterOther((TrainerType)3, (float)value);
			Debug.Log((object)string.Format("\ud83d\udd27 Resistance aplicado: {0}{1}", (num2 > 0) ? "+" : "", value));
			break;
		case "evade":
			stats.AugmentCharacterOther((TrainerType)4, num * (float)num2);
			Debug.Log((object)string.Format("\ud83d\udd27 Evade aplicado: {0}{1}", (num2 > 0) ? "+" : "", value));
			break;
		case "focus":
			stats.AugmentCharacterOther((TrainerType)0, (float)value);
			Debug.Log((object)string.Format("✨ Focus aplicado: {0}{1}", (num2 > 0) ? "+" : "", value));
			break;
		case "maxhealth":
			stats.AugmentCharacterOther((TrainerType)1, (float)value);
			Debug.Log((object)string.Format("❤\ufe0f MaxHealth aplicado: {0}{1}", (num2 > 0) ? "+" : "", value));
			break;
		case "critchance":
		{
			FieldInfo field = typeof(CharacterStats).GetField("m_ModCritChance", BindingFlags.Instance | BindingFlags.NonPublic);
			if ((object)field == null)
			{
				return null;
			}
			float num3 = (float)field.GetValue(stats);
			field.SetValue(stats, num3 + (float)value / 100f);
			stats.UpdateAllCharacterStats(false);
			Debug.Log((object)string.Format("⚔\ufe0f CritChance aplicado: {0}{1}%", (value >= 0) ? "+" : "", value));
			break;
		}
		default:
			return null;
		}
		return result;
	}

	private static void RemoveStatByKey(CharacterStats stats, string key)
	{
		if (string.IsNullOrEmpty(key))
		{
			return;
		}
		string[] array = key.Split(new char[1] { '_' });
		if (array.Length < 2)
		{
			return;
		}
		string text = array[0];
		if (!int.TryParse(array[1], out var result))
		{
			return;
		}
		int num = Math.Sign(result);
		float num2 = (float)Math.Abs(result) / 100f;
		switch (text.ToLower())
		{
		case "strength":
			stats.AugmentCharacterStat((SkillType)0, (0f - num2) * (float)num);
			break;
		case "vitality":
			stats.AugmentCharacterStat((SkillType)3, (0f - num2) * (float)num);
			break;
		case "awareness":
			stats.AugmentCharacterStat((SkillType)2, (0f - num2) * (float)num);
			break;
		case "speed":
			stats.AugmentCharacterStat((SkillType)4, (0f - num2) * (float)num);
			break;
		case "talent":
			stats.AugmentCharacterStat((SkillType)5, (0f - num2) * (float)num);
			break;
		case "intelligence":
			stats.AugmentCharacterStat((SkillType)1, (0f - num2) * (float)num);
			break;
		case "armor":
			stats.AugmentCharacterOther((TrainerType)2, (float)(-result));
			break;
		case "resistance":
			stats.AugmentCharacterOther((TrainerType)3, (float)(-result));
			break;
		case "evade":
			stats.AugmentCharacterOther((TrainerType)4, (0f - num2) * (float)num);
			break;
		case "focus":
			stats.AugmentCharacterOther((TrainerType)0, (float)(-result));
			break;
		case "maxhealth":
			stats.AugmentCharacterOther((TrainerType)1, (float)(-result));
			break;
		case "critchance":
		{
			FieldInfo field = typeof(CharacterStats).GetField("m_ModCritChance", BindingFlags.Instance | BindingFlags.NonPublic);
			if ((object)field == null)
			{
				return;
			}
			float num3 = (float)field.GetValue(stats);
			field.SetValue(stats, num3 - (float)result / 100f);
			stats.UpdateAllCharacterStats(false);
			Debug.Log((object)string.Format("⚔\ufe0f CritChance removido: {0}{1}%", (result >= 0) ? "-" : "+", Math.Abs(result)));
			break;
		}
		}
		Debug.Log((object)("\ud83d\udd27 Stat removido: " + text));
		stats.UpdateAllCharacterStats(false);
	}
}
[HarmonyPatch(typeof(CharacterOverworld), "Start")]
public static class InitialWeaponPatch
{
	private static void Postfix(CharacterOverworld __instance)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Invalid comparison between Unknown and I4
		//IL_0047: 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_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Invalid comparison between Unknown and I4
		//IL_0036: 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)
		if (Main.EnableRandomization.Value && !((Object)(object)GameLogic.Instance == (Object)null))
		{
			ExtraStatsPatch.MarkAllWeapons();
			ID firstItemID = GetFirstItemID((ItemContainer)(object)__instance.m_PlayerInventory.m_ContainerRightHand);
			if ((int)firstItemID != -1)
			{
				ApplyStatsForWeapon(__instance, firstItemID);
			}
			ID firstItemID2 = GetFirstItemID((ItemContainer)(object)__instance.m_PlayerInventory.m_ContainerLeftHand);
			if ((int)firstItemID2 != -1)
			{
				ApplyStatsForWeapon(__instance, firstItemID2);
			}
			__instance.m_CharacterStats.UpdateAllCharacterStats(false);
		}
	}

	private static ID GetFirstItemID(ItemContainer container)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		if (((container != null) ? container.m_CountDictionary : null) == null)
		{
			return (ID)(-1);
		}
		Dictionary<ID, int>.KeyCollection.Enumerator enumerator = container.m_CountDictionary.Keys.GetEnumerator();
		if (enumerator.MoveNext())
		{
			return enumerator.Current;
		}
		return (ID)(-1);
	}

	private static void ApplyStatsForWeapon(CharacterOverworld character, ID weaponID)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Expected I4, but got Unknown
		//IL_0002: 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_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		int num = (int)weaponID;
		string localizedName = FTK_itembase.GetItemBase(weaponID).GetLocalizedName();
		if (ExtraStatsPatch.NeedsExtraStats(num))
		{
			int playerLuckSeed = (int)character.m_CharacterStats.Luck;
			ExtraStatsPatch.GenerateExtraStatsForItem(num, playerLuckSeed);
		}
		if (!ExtraStatsData.ItemMods.TryGetValue(num, out var value))
		{
			return;
		}
		List<PlayerStatsManager.PlayerStat> list = new List<PlayerStatsManager.PlayerStat>();
		foreach (ExtraStatsData.ExtraStat item in value)
		{
			ApplyStatDirectly(character.m_CharacterStats, item.statName, item.value);
			list.Add(new PlayerStatsManager.PlayerStat
			{
				statName = item.statName,
				value = item.value
			});
		}
		foreach (PlayerStatsManager.PlayerStat item2 in list)
		{
			PlayerStatsManager.AddPlayerStat(character.m_FTKPlayerID, item2);
		}
		if (list.Count > 0)
		{
			PlayerStatsManager.AddEquippedItem(character.m_FTKPlayerID, localizedName, list);
		}
		Debug.Log((object)$"✨ [InitialWeapon] Stats aplicadas y registradas para {localizedName} ({weaponID}) en {character.m_CharacterStats.m_CharacterName}");
		if ((Object)(object)character.m_CharacterStats != (Object)null && (Object)(object)character.m_CharacterStats.m_CharacterOverworld != (Object)null)
		{
			character.m_CharacterStats.UpdateAllCharacterStats(false);
			character.m_CharacterStats.m_CharacterOverworld.m_UIPlayMainHud.UpdateHud();
		}
	}

	private static void ApplyStatDirectly(CharacterStats stats, string statName, int value)
	{
		string text = statName.ToLower();
		float num = (float)Math.Abs(value) / 100f;
		int num2 = Math.Sign(value);
		switch (text)
		{
		case "strength":
			stats.AugmentCharacterStat((SkillType)0, num * (float)num2);
			break;
		case "vitality":
			stats.AugmentCharacterStat((SkillType)3, num * (float)num2);
			break;
		case "awareness":
			stats.AugmentCharacterStat((SkillType)2, num * (float)num2);
			break;
		case "speed":
			stats.AugmentCharacterStat((SkillType)4, num * (float)num2);
			break;
		case "talent":
			stats.AugmentCharacterStat((SkillType)5, num * (float)num2);
			break;
		case "intelligence":
			stats.AugmentCharacterStat((SkillType)1, num * (float)num2);
			break;
		case "armor":
			stats.AugmentCharacterOther((TrainerType)2, (float)value);
			break;
		case "resistance":
			stats.AugmentCharacterOther((TrainerType)3, (float)value);
			break;
		case "evade":
			stats.AugmentCharacterOther((TrainerType)4, num * (float)num2);
			break;
		case "focus":
			stats.AugmentCharacterOther((TrainerType)0, (float)value);
			break;
		case "maxhealth":
			stats.AugmentCharacterOther((TrainerType)1, (float)value);
			break;
		case "critchance":
		{
			FieldInfo field = typeof(CharacterStats).GetField("m_ModCritChance", BindingFlags.Instance | BindingFlags.NonPublic);
			if ((object)field != null)
			{
				float num3 = (float)field.GetValue(stats);
				field.SetValue(stats, num3 + (float)value / 100f);
			}
			break;
		}
		}
	}
}
public static class LuckHelper
{
	public static float GetCurrentPlayerLuck()
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)EncounterSessionMC.Instance != (Object)null && EncounterSessionMC.Instance.m_AllCombtatantsAlive != null && EncounterSessionMC.Instance.m_AllCombtatantsAlive.Count > 0)
			{
				FTKPlayerID val = EncounterSessionMC.Instance.m_AllCombtatantsAlive[0];
				if ((Object)(object)((FTKPlayerID)(ref val)).GetCow() != (Object)null && (Object)(object)((FTKPlayerID)(ref val)).GetCow().m_CharacterStats != (Object)null)
				{
					return ((FTKPlayerID)(ref val)).GetCow().m_CharacterStats.Luck;
				}
			}
		}
		catch (Exception ex)
		{
			Debug.LogWarning((object)("LuckHelper: Error obteniendo suerte - " + ex.Message));
		}
		return Main.BaseLuckValue.Value;
	}

	public static float GetLuckInfluenceFactor()
	{
		float currentPlayerLuck = GetCurrentPlayerLuck();
		float num = Main.BaseLuckValue.Value;
		float num2 = Main.LuckStepSize.Value;
		float num3 = Main.LuckStepPercent.Value / 100f;
		return Mathf.Clamp((float)(int)((currentPlayerLuck - num) / num2) * num3, -0.5f, 0.5f);
	}

	public static float GetPositiveProbability()
	{
		float luckInfluenceFactor = GetLuckInfluenceFactor();
		return Mathf.Clamp(0.5f + luckInfluenceFactor, 0.2f, 0.8f);
	}

	public static bool ShouldBePositive()
	{
		float positiveProbability = GetPositiveProbability();
		return Random.value < positiveProbability;
	}

	public static float GetRandomizedMultiplier(float minPercent, float maxPercent)
	{
		float num = minPercent / 100f;
		float num2 = maxPercent / 100f;
		if (ShouldBePositive())
		{
			float value = Random.value;
			return 1f + num2 * value;
		}
		float value2 = Random.value;
		return 1f + num * value2;
	}

	public static int GetExtraStatsCount(int minCount, int maxCount)
	{
		float luckInfluenceFactor = GetLuckInfluenceFactor();
		float num = (float)(minCount + maxCount) / 2f;
		float num2 = num + luckInfluenceFactor * (float)(maxCount - minCount) / 2f;
		int num3 = Mathf.RoundToInt(num2);
		num3 = Mathf.Clamp(num3, minCount, maxCount);
		Debug.Log((object)$"\ud83c\udfb2 ExtraStatsCount: influence={luckInfluenceFactor:F2}, base={num:F1}, final={num2:F1}, count={num3}");
		return num3;
	}

	public static int GetExtraStatValue(int minValue, int maxValue)
	{
		float luckInfluenceFactor = GetLuckInfluenceFactor();
		return Mathf.Clamp(Mathf.RoundToInt((float)(minValue + maxValue) / 2f + luckInfluenceFactor * (float)(maxValue - minValue) / 2f), minValue, maxValue);
	}
}
[BepInPlugin("FTKRandomItemsStats", "FTKRandomItemsStats", "1.0.0")]
public class Main : BaseUnityPlugin
{
	public static Main Instance;

	public static ConfigEntry<bool> EnableRandomization;

	public static ConfigEntry<bool> IncludeQuestItems;

	public static ConfigEntry<bool> IncludeLegendary;

	public static ConfigEntry<float> DamageMinPercent;

	public static ConfigEntry<float> DamageMaxPercent;

	public static ConfigEntry<int> ExtraStatsMinCount;

	public static ConfigEntry<int> ExtraStatsMaxCount;

	public static ConfigEntry<string> PossibleStats;

	public static ConfigEntry<int> ExtraStatValueMin;

	public static ConfigEntry<int> ExtraStatValueMax;

	public static ConfigEntry<int> BaseLuckValue;

	public static ConfigEntry<float> LuckStepPercent;

	public static ConfigEntry<int> LuckStepSize;

	private void Awake()
	{
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		Type typeFromHandle = typeof(FTK_weaponStats2DB);
		Debug.Log((object)("\ud83d\udfe2 Ensamblado FTK cargado: " + typeFromHandle.Assembly.FullName));
		EnableRandomization = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableRandomization", true, "Activar/desactivar randomización");
		IncludeQuestItems = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IncludeQuestItems", true, "Randomizar objetos de misión");
		IncludeLegendary = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IncludeLegendary", true, "Randomizar objetos legendarios/épicos");
		DamageMinPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "MinPercent", -35f, "Porcentaje mínimo de daño (-100 a 0)");
		DamageMaxPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "MaxPercent", 50f, "Porcentaje máximo de daño (0 a 200)");
		ExtraStatsMinCount = ((BaseUnityPlugin)this).Config.Bind<int>("ExtraStats", "MinCount", 0, "Cantidad mínima de stats extra (0-6)");
		ExtraStatsMaxCount = ((BaseUnityPlugin)this).Config.Bind<int>("ExtraStats", "MaxCount", 6, "Cantidad máxima de stats extra (0-6)");
		PossibleStats = ((BaseUnityPlugin)this).Config.Bind<string>("ExtraStats", "PossibleStats", "vitality,awareness,talent,evade,focus,armor,resistance,strength,intelligence,speed,critChance,maxHealth", "Stats posibles separados por coma");
		ExtraStatValueMin = ((BaseUnityPlugin)this).Config.Bind<int>("ExtraStats", "ValueMin", -4, "Valor mínimo del stat extra (-4 a 6, excluyendo 0)");
		ExtraStatValueMax = ((BaseUnityPlugin)this).Config.Bind<int>("ExtraStats", "ValueMax", 6, "Valor máximo del stat extra (-4 a 6, excluyendo 0)");
		BaseLuckValue = ((BaseUnityPlugin)this).Config.Bind<int>("Luck", "BaseLuckValue", 55, "Valor base de suerte (0% de bonus)");
		LuckStepPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Luck", "LuckStepPercent", 4f, "Cada X puntos de suerte da este % de bonus");
		LuckStepSize = ((BaseUnityPlugin)this).Config.Bind<int>("Luck", "LuckStepSize", 10, "Cada cuántos puntos de suerte se aplica el bonus");
		new Harmony("FTKRandomItemsStats").PatchAll();
		Debug.Log((object)"\ud83d\udfe2 Harmony PatchAll ejecutado");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"═══════════════════════════════════════");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"  FTKRandomItemsStats ha sido cargado");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"═══════════════════════════════════════");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"  Hecho por FINISHIM en el MEJOR pais de CHILE");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"═══════════════════════════════════════");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"  Versión: 1.0.0");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"═══════════════════════════════════════");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"FTKRandomItemsStats ha sido cargado correctamente!");
	}

	private void Update()
	{
		if (Input.GetKeyDown((KeyCode)289))
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"═══════════════════════════════════════");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"  CONFIGURACIÓN RECARGADA");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"═══════════════════════════════════════");
			((BaseUnityPlugin)this).Config.Reload();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Configuración recargada!");
		}
	}
}
[HarmonyPatch(typeof(FTK_weaponStats2DB), "GetEntry")]
public class WeaponStatsPatch
{
	private static HashSet<int> randomizedItems = new HashSet<int>();

	private const int UNARMED_ID = 100023;

	private static void Postfix(ref FTK_weaponStats2 __result, ID _enumID)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Expected I4, but got Unknown
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		int num = (int)_enumID;
		if (num == 100023)
		{
			Debug.Log((object)$"\ud83d\udd27 [FTKRandomItemsStats] {_enumID}: Excluido de randomización de daño (unarmed)");
		}
		else if (!randomizedItems.Contains(num) && Main.EnableRandomization.Value && !((Object)(object)GameLogic.Instance == (Object)null))
		{
			try
			{
				Random.InitState(GameLogic.Instance.m_MapGenRandomSeed + num);
				float randomizedMultiplier = LuckHelper.GetRandomizedMultiplier(Main.DamageMinPercent.Value, Main.DamageMaxPercent.Value);
				float num2 = __result._maxdmg * randomizedMultiplier;
				num2 = (float)Math.Round(num2, 1);
				__result._maxdmg = Mathf.Max(1f, num2);
				Debug.Log((object)$"\ud83d\udd27 [FTKRandomItemsStats] {_enumID}: Daño randomizado → {__result._maxdmg:F1}");
				randomizedItems.Add(num);
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("❌ Error: " + ex.Message));
			}
		}
	}
}