Decompiled source of LuckyUpgrades v1.0.5

LuckyUpgrades.dll

Decompiled 3 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LuckyUpgrades.Patches;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("REPOShareMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("R.E.P.O 업그레이드 확률 공유 모드 - 스탯 아이템 획득 시 설정된 확률에 따라 다른 플레이어에게도 적용")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyInformationalVersion("1.0.5+58fa60b808466df103f65d9e1e395dccdaa242a1")]
[assembly: AssemblyProduct("LuckyUpgrades")]
[assembly: AssemblyTitle("LuckyUpgrades")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.5.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 LuckyUpgrades
{
	[BepInPlugin("com.reposharemod.luckyupgrades", "LuckyUpgrades", "1.0.5")]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		public static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		public static UpgradeConfig UpgradeConfiguration { get; private set; }

		private void Awake()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"[LuckyUpgrades] Plugin loading...");
			UpgradeConfiguration = new UpgradeConfig(((BaseUnityPlugin)this).Config);
			Log.LogInfo((object)"[LuckyUpgrades] Configuration loaded");
			_harmony = new Harmony("com.reposharemod.luckyupgrades");
			UpgradePatcher.PatchAll(_harmony);
			Log.LogInfo((object)"[LuckyUpgrades] v1.0.5 loaded successfully!");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.reposharemod.luckyupgrades";

		public const string PLUGIN_NAME = "LuckyUpgrades";

		public const string PLUGIN_VERSION = "1.0.5";
	}
	public class UpgradeConfig
	{
		public ConfigEntry<bool> ModEnabled { get; private set; }

		public ConfigEntry<bool> HostOnly { get; private set; }

		public ConfigEntry<bool> UseOneChanceForAll { get; private set; }

		public ConfigEntry<int> GlobalChanceToActivate { get; private set; }

		public ConfigEntry<int> ChanceToWasteUpgrade { get; private set; }

		public ConfigEntry<int> ChanceToActivatePlayerHealth { get; private set; }

		public ConfigEntry<int> ChanceToActivatePlayerEnergy { get; private set; }

		public ConfigEntry<int> ChanceToActivatePlayerSprintSpeed { get; private set; }

		public ConfigEntry<int> ChanceToActivatePlayerExtraJump { get; private set; }

		public ConfigEntry<int> ChanceToActivatePlayerTumbleLaunch { get; private set; }

		public ConfigEntry<int> ChanceToActivatePlayerGrabRange { get; private set; }

		public ConfigEntry<int> ChanceToActivatePlayerGrabStrength { get; private set; }

		public ConfigEntry<int> ChanceToActivatePlayerGrabThrow { get; private set; }

		public ConfigEntry<int> ChanceToActivateMapPlayerCount { get; private set; }

		public UpgradeConfig(ConfigFile config)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Expected O, but got Unknown
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Expected O, but got Unknown
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Expected O, but got Unknown
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Expected O, but got Unknown
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Expected O, but got Unknown
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Expected O, but got Unknown
			ModEnabled = config.Bind<bool>("Global", "ModEnabled", true, "Enable or disable the mod");
			HostOnly = config.Bind<bool>("Global", "HostOnly", true, "Only the host will run the mod logic (recommended: true)");
			UseOneChanceForAll = config.Bind<bool>("Global", "UseOneChanceForAll", true, "If true, the GlobalChanceToActivate will be used for all upgrades");
			GlobalChanceToActivate = config.Bind<int>("Global", "GlobalChanceToActivate", 25, new ConfigDescription("% Chance to activate the upgrade for every player", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ChanceToWasteUpgrade = config.Bind<int>("Global", "ChanceToWasteUpgrade", 0, new ConfigDescription("% Chance to waste the upgrade and activate it for nobody", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ChanceToActivatePlayerHealth = config.Bind<int>("SpecificUpgrades", "ChanceToActivatePlayerHealth", 50, new ConfigDescription("% Chance to activate the Health upgrade for every player", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ChanceToActivatePlayerEnergy = config.Bind<int>("SpecificUpgrades", "ChanceToActivatePlayerEnergy", 25, new ConfigDescription("% Chance to activate the Energy (Stamina) upgrade for every player", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ChanceToActivatePlayerSprintSpeed = config.Bind<int>("SpecificUpgrades", "ChanceToActivatePlayerSprintSpeed", 25, new ConfigDescription("% Chance to activate the Sprint Speed upgrade for every player", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ChanceToActivatePlayerExtraJump = config.Bind<int>("SpecificUpgrades", "ChanceToActivatePlayerExtraJump", 25, new ConfigDescription("% Chance to activate the Extra Jump upgrade for every player", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ChanceToActivatePlayerTumbleLaunch = config.Bind<int>("SpecificUpgrades", "ChanceToActivatePlayerTumbleLaunch", 25, new ConfigDescription("% Chance to activate the Tumble Launch upgrade for every player", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ChanceToActivatePlayerGrabRange = config.Bind<int>("SpecificUpgrades", "ChanceToActivatePlayerGrabRange", 25, new ConfigDescription("% Chance to activate the Grab Range upgrade for every player", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ChanceToActivatePlayerGrabStrength = config.Bind<int>("SpecificUpgrades", "ChanceToActivatePlayerGrabStrength", 25, new ConfigDescription("% Chance to activate the Grab Strength upgrade for every player", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ChanceToActivatePlayerGrabThrow = config.Bind<int>("SpecificUpgrades", "ChanceToActivatePlayerGrabThrow", 25, new ConfigDescription("% Chance to activate the Grab Throw upgrade for every player", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			ChanceToActivateMapPlayerCount = config.Bind<int>("SpecificUpgrades", "ChanceToActivateMapPlayerCount", 25, new ConfigDescription("% Chance to activate the Map Player Count upgrade for every player", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
		}

		public int GetShareChance(string upgradeType)
		{
			if (UseOneChanceForAll.Value)
			{
				return GlobalChanceToActivate.Value;
			}
			string text = upgradeType.ToLower();
			if (text.Contains("health"))
			{
				return ChanceToActivatePlayerHealth.Value;
			}
			if (text.Contains("energy") || text.Contains("stamina"))
			{
				return ChanceToActivatePlayerEnergy.Value;
			}
			if (text.Contains("sprint") || text.Contains("speed"))
			{
				return ChanceToActivatePlayerSprintSpeed.Value;
			}
			if (text.Contains("jump"))
			{
				return ChanceToActivatePlayerExtraJump.Value;
			}
			if (text.Contains("tumble") || text.Contains("launch"))
			{
				return ChanceToActivatePlayerTumbleLaunch.Value;
			}
			if (text.Contains("range"))
			{
				return ChanceToActivatePlayerGrabRange.Value;
			}
			if (text.Contains("strength"))
			{
				return ChanceToActivatePlayerGrabStrength.Value;
			}
			if (text.Contains("throw"))
			{
				return ChanceToActivatePlayerGrabThrow.Value;
			}
			if (text.Contains("map") || text.Contains("count"))
			{
				return ChanceToActivateMapPlayerCount.Value;
			}
			return GlobalChanceToActivate.Value;
		}

		public bool ShouldWasteUpgrade()
		{
			if (ChanceToWasteUpgrade.Value <= 0)
			{
				return false;
			}
			return new Random().Next(0, 100) < ChanceToWasteUpgrade.Value;
		}
	}
}
namespace LuckyUpgrades.Patches
{
	[HarmonyPatch]
	public class UpgradePatch
	{
		private static readonly Random _random = new Random();

		[HarmonyTargetMethod]
		public static MethodBase TargetMethod()
		{
			string[] array = new string[13]
			{
				"ItemUpgradePlayerHealth", "ItemUpgradePlayerEnergy", "ItemUpgradePlayerSprintSpeed", "ItemUpgradePlayerExtraJump", "ItemUpgradePlayerTumbleLaunch", "ItemUpgradePlayerGrabRange", "ItemUpgradePlayerGrabStrength", "ItemUpgradePlayerGrabThrow", "ItemUpgradeMapPlayerCount", "ItemUpgrade",
				"UpgradeItem", "PlayerUpgrade", "StatsManager"
			};
			string[] array2 = new string[6] { "Upgrade", "ApplyUpgrade", "Apply", "AddUpgrade", "PickUp", "OnPickup" };
			string[] array3 = array;
			foreach (string text in array3)
			{
				Type type = AccessTools.TypeByName(text);
				if (type == null)
				{
					continue;
				}
				string[] array4 = array2;
				foreach (string text2 in array4)
				{
					MethodInfo methodInfo = AccessTools.Method(type, text2, (Type[])null, (Type[])null);
					if (methodInfo != null)
					{
						Plugin.Log.LogInfo((object)("[LuckyUpgrades] Patch target found: " + text + "." + text2));
						return methodInfo;
					}
				}
			}
			Plugin.Log.LogWarning((object)"[LuckyUpgrades] Could not find patch target method. Manual configuration required.");
			return null;
		}

		[HarmonyPostfix]
		public static void Postfix(object __instance)
		{
			try
			{
				if (!Plugin.UpgradeConfiguration.ModEnabled.Value || (Plugin.UpgradeConfiguration.HostOnly.Value && !IsHost()))
				{
					return;
				}
				if (Plugin.UpgradeConfiguration.ShouldWasteUpgrade())
				{
					Plugin.Log.LogInfo((object)"[LuckyUpgrades] Upgrade wasted - no one gets it!");
					return;
				}
				string upgradeType = GetUpgradeType(__instance);
				if (string.IsNullOrEmpty(upgradeType))
				{
					Plugin.Log.LogWarning((object)"[LuckyUpgrades] Could not determine upgrade type.");
					return;
				}
				object sourcePlayer = GetSourcePlayer(__instance);
				if (sourcePlayer == null)
				{
					Plugin.Log.LogWarning((object)"[LuckyUpgrades] Could not determine source player.");
				}
				else
				{
					ApplyUpgradeToOtherPlayers(upgradeType, sourcePlayer);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[LuckyUpgrades] Error in Postfix: " + ex.Message));
			}
		}

		private static bool IsHost()
		{
			try
			{
				Type type = AccessTools.TypeByName("Photon.Pun.PhotonNetwork");
				if (type != null)
				{
					PropertyInfo property = type.GetProperty("IsMasterClient");
					if (property != null)
					{
						return (bool)property.GetValue(null);
					}
				}
				Type type2 = AccessTools.TypeByName("GameManager");
				if (type2 != null)
				{
					PropertyInfo propertyInfo = type2.GetProperty("IsHost") ?? type2.GetProperty("isHost");
					if (propertyInfo != null)
					{
						object gameManagerInstance = GetGameManagerInstance();
						if (gameManagerInstance != null)
						{
							return (bool)propertyInfo.GetValue(gameManagerInstance);
						}
					}
				}
				return true;
			}
			catch
			{
				return true;
			}
		}

		private static object GetGameManagerInstance()
		{
			try
			{
				Type type = AccessTools.TypeByName("GameManager");
				if (type == null)
				{
					return null;
				}
				PropertyInfo propertyInfo = type.GetProperty("Instance") ?? type.GetProperty("instance");
				if (propertyInfo != null)
				{
					return propertyInfo.GetValue(null);
				}
				FieldInfo fieldInfo = type.GetField("Instance") ?? type.GetField("instance");
				if (fieldInfo != null)
				{
					return fieldInfo.GetValue(null);
				}
				return null;
			}
			catch
			{
				return null;
			}
		}

		private static string GetUpgradeType(object instance)
		{
			if (instance == null)
			{
				return null;
			}
			try
			{
				Type type = instance.GetType();
				string name = type.Name;
				if (name.Contains("Health"))
				{
					return "Health";
				}
				if (name.Contains("Energy") || name.Contains("Stamina"))
				{
					return "Energy";
				}
				if (name.Contains("Sprint") || name.Contains("Speed"))
				{
					return "SprintSpeed";
				}
				if (name.Contains("Jump"))
				{
					return "ExtraJump";
				}
				if (name.Contains("Tumble") || name.Contains("Launch"))
				{
					return "TumbleLaunch";
				}
				if (name.Contains("Range"))
				{
					return "GrabRange";
				}
				if (name.Contains("Strength"))
				{
					return "GrabStrength";
				}
				if (name.Contains("Throw"))
				{
					return "GrabThrow";
				}
				if (name.Contains("Map") || name.Contains("Count"))
				{
					return "MapPlayerCount";
				}
				PropertyInfo propertyInfo = type.GetProperty("upgradeType") ?? type.GetProperty("UpgradeType");
				if (propertyInfo != null)
				{
					return propertyInfo.GetValue(instance)?.ToString();
				}
				FieldInfo fieldInfo = type.GetField("upgradeType") ?? type.GetField("UpgradeType");
				if (fieldInfo != null)
				{
					return fieldInfo.GetValue(instance)?.ToString();
				}
				return name;
			}
			catch
			{
				return null;
			}
		}

		private static object GetSourcePlayer(object instance)
		{
			if (instance == null)
			{
				return null;
			}
			try
			{
				Type type = instance.GetType();
				string[] array = new string[8] { "player", "Player", "playerController", "PlayerController", "owner", "Owner", "playerAvatar", "PlayerAvatar" };
				foreach (string name in array)
				{
					PropertyInfo property = type.GetProperty(name);
					if (property != null)
					{
						return property.GetValue(instance);
					}
					FieldInfo field = type.GetField(name);
					if (field != null)
					{
						return field.GetValue(instance);
					}
				}
				return null;
			}
			catch
			{
				return null;
			}
		}

		private static void ApplyUpgradeToOtherPlayers(string upgradeType, object sourcePlayer)
		{
			try
			{
				int shareChance = Plugin.UpgradeConfiguration.GetShareChance(upgradeType);
				List<object> allPlayers = GetAllPlayers();
				if (allPlayers == null || allPlayers.Count <= 1)
				{
					Plugin.Log.LogDebug((object)"[LuckyUpgrades] No other players found.");
					return;
				}
				int num = 0;
				foreach (object item in allPlayers)
				{
					if (IsSamePlayer(item, sourcePlayer))
					{
						continue;
					}
					int num2 = _random.Next(0, 100);
					if (num2 < shareChance)
					{
						if (ApplyUpgradeToPlayer(item, upgradeType))
						{
							num++;
							Plugin.Log.LogInfo((object)$"[LuckyUpgrades] {upgradeType} upgrade shared to player (chance: {shareChance}%)");
						}
					}
					else
					{
						Plugin.Log.LogDebug((object)$"[LuckyUpgrades] {upgradeType} upgrade not shared (roll: {num2}, chance: {shareChance})");
					}
				}
				if (num > 0)
				{
					Plugin.Log.LogInfo((object)$"[LuckyUpgrades] {upgradeType} upgrade shared to {num} players total");
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[LuckyUpgrades] Error sharing upgrade: " + ex.Message));
			}
		}

		private static List<object> GetAllPlayers()
		{
			try
			{
				List<object> list = new List<object>();
				Type type = AccessTools.TypeByName("PlayerController");
				if (type != null)
				{
					MethodInfo methodInfo = type.GetMethod("GetAllPlayers") ?? type.GetMethod("GetAll");
					if (methodInfo != null && methodInfo.IsStatic && methodInfo.Invoke(null, null) is IEnumerable enumerable)
					{
						foreach (object item3 in enumerable)
						{
							list.Add(item3);
						}
						return list;
					}
				}
				object gameManagerInstance = GetGameManagerInstance();
				if (gameManagerInstance != null)
				{
					Type type2 = gameManagerInstance.GetType();
					PropertyInfo propertyInfo = type2.GetProperty("players") ?? type2.GetProperty("Players");
					if (propertyInfo != null && propertyInfo.GetValue(gameManagerInstance) is IEnumerable enumerable2)
					{
						foreach (object item4 in enumerable2)
						{
							list.Add(item4);
						}
						return list;
					}
				}
				if (type != null)
				{
					Object[] array = Object.FindObjectsOfType(type);
					foreach (Object item in array)
					{
						list.Add(item);
					}
					return list;
				}
				Type type3 = AccessTools.TypeByName("PlayerAvatar");
				if (type3 != null)
				{
					Object[] array = Object.FindObjectsOfType(type3);
					foreach (Object item2 in array)
					{
						list.Add(item2);
					}
					return list;
				}
				return list;
			}
			catch
			{
				return new List<object>();
			}
		}

		private static bool IsSamePlayer(object player1, object player2)
		{
			if (player1 == null || player2 == null)
			{
				return false;
			}
			if (!player1.Equals(player2))
			{
				return player1 == player2;
			}
			return true;
		}

		private static bool ApplyUpgradeToPlayer(object player, string upgradeType)
		{
			try
			{
				Type type = AccessTools.TypeByName("StatsManager");
				if (type != null)
				{
					object statsManagerForPlayer = GetStatsManagerForPlayer(player);
					if (statsManagerForPlayer != null)
					{
						MethodInfo methodInfo = type.GetMethod("AddUpgrade") ?? type.GetMethod("ApplyUpgrade") ?? type.GetMethod("IncreaseLevel");
						if (methodInfo != null)
						{
							methodInfo.Invoke(statsManagerForPlayer, new object[1] { upgradeType });
							return true;
						}
					}
				}
				return upgradeType.ToLower() switch
				{
					"health" => ModifyPlayerStat(player, "maxHealth", 20f, isAdditive: true), 
					"energy" => ModifyPlayerStat(player, "maxEnergy", 10f, isAdditive: true), 
					"sprintspeed" => ModifyPlayerStat(player, "sprintSpeed", 0.1f, isAdditive: true), 
					"extrajump" => ModifyPlayerStat(player, "extraJumps", 1f, isAdditive: true), 
					"tumblelaunch" => ModifyPlayerStat(player, "tumbleLaunchLevel", 1f, isAdditive: true), 
					"grabrange" => ModifyPlayerStat(player, "grabRange", 0.5f, isAdditive: true), 
					"grabstrength" => ModifyPlayerStat(player, "grabStrength", 1f, isAdditive: true), 
					"grabthrow" => ModifyPlayerStat(player, "throwStrength", 1f, isAdditive: true), 
					_ => false, 
				};
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[LuckyUpgrades] Failed to apply upgrade to player: " + ex.Message));
				return false;
			}
		}

		private static object GetStatsManagerForPlayer(object player)
		{
			if (player == null)
			{
				return null;
			}
			try
			{
				Type type = player.GetType();
				PropertyInfo propertyInfo = type.GetProperty("statsManager") ?? type.GetProperty("StatsManager") ?? type.GetProperty("stats");
				if (propertyInfo != null)
				{
					return propertyInfo.GetValue(player);
				}
				FieldInfo fieldInfo = type.GetField("statsManager") ?? type.GetField("StatsManager") ?? type.GetField("stats");
				if (fieldInfo != null)
				{
					return fieldInfo.GetValue(player);
				}
				Component val = (Component)((player is Component) ? player : null);
				if (val != null)
				{
					Type type2 = AccessTools.TypeByName("StatsManager");
					if (type2 != null)
					{
						MethodInfo methodInfo = typeof(Component).GetMethod("GetComponent", Type.EmptyTypes)?.MakeGenericMethod(type2);
						if (methodInfo != null)
						{
							return methodInfo.Invoke(val, null);
						}
					}
				}
				return null;
			}
			catch
			{
				return null;
			}
		}

		private static bool ModifyPlayerStat(object player, string statName, float amount, bool isAdditive)
		{
			if (player == null)
			{
				return false;
			}
			try
			{
				Type type = player.GetType();
				PropertyInfo property = type.GetProperty(statName);
				if (property != null && property.CanWrite)
				{
					float num = Convert.ToSingle(property.GetValue(player));
					float num2 = (isAdditive ? (num + amount) : (num * amount));
					property.SetValue(player, num2);
					return true;
				}
				FieldInfo field = type.GetField(statName);
				if (field != null)
				{
					float num3 = Convert.ToSingle(field.GetValue(player));
					float num4 = (isAdditive ? (num3 + amount) : (num3 * amount));
					field.SetValue(player, num4);
					return true;
				}
				return false;
			}
			catch
			{
				return false;
			}
		}
	}
	public static class UpgradePatcher
	{
		private static readonly Random _random = new Random();

		public static void PatchAll(Harmony harmony)
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected O, but got Unknown
			string[] obj = new string[9] { "ItemUpgradePlayerHealth", "ItemUpgradePlayerEnergy", "ItemUpgradePlayerSprintSpeed", "ItemUpgradePlayerExtraJump", "ItemUpgradePlayerTumbleLaunch", "ItemUpgradePlayerGrabRange", "ItemUpgradePlayerGrabStrength", "ItemUpgradePlayerGrabThrow", "ItemUpgradeMapPlayerCount" };
			int num = 0;
			MethodInfo method = typeof(UpgradePatcher).GetMethod("Postfix", BindingFlags.Static | BindingFlags.Public);
			string[] array = obj;
			foreach (string text in array)
			{
				Type type = AccessTools.TypeByName(text);
				if (!(type == null))
				{
					MethodInfo methodInfo = AccessTools.Method(type, "Upgrade", (Type[])null, (Type[])null) ?? AccessTools.Method(type, "ApplyUpgrade", (Type[])null, (Type[])null) ?? AccessTools.Method(type, "Apply", (Type[])null, (Type[])null);
					if (methodInfo != null)
					{
						harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Plugin.Log.LogInfo((object)("[LuckyUpgrades] Patch applied to: " + text + "." + methodInfo.Name));
						num++;
					}
				}
			}
			if (num != 0)
			{
				return;
			}
			Type type2 = AccessTools.TypeByName("ItemUpgrade");
			if (type2 != null)
			{
				MethodInfo methodInfo2 = AccessTools.Method(type2, "Upgrade", (Type[])null, (Type[])null) ?? AccessTools.Method(type2, "ApplyUpgrade", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)("[LuckyUpgrades] Patch applied to generic class: " + type2.Name));
				}
			}
		}

		public static void Postfix(object __instance)
		{
			try
			{
				if (!Plugin.UpgradeConfiguration.ModEnabled.Value || (Plugin.UpgradeConfiguration.HostOnly.Value && !IsHost()))
				{
					return;
				}
				if (Plugin.UpgradeConfiguration.ShouldWasteUpgrade())
				{
					Plugin.Log.LogInfo((object)"[LuckyUpgrades] Upgrade chance failed - Upgrade wasted!");
					return;
				}
				string upgradeType = GetUpgradeType(__instance);
				object sourcePlayer = GetSourcePlayer(__instance);
				if (!string.IsNullOrEmpty(upgradeType) && sourcePlayer != null)
				{
					ApplyUpgradeToOtherPlayers(upgradeType, sourcePlayer);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("[LuckyUpgrades] Error in Postfix patch: " + ex.Message));
			}
		}

		private static bool IsHost()
		{
			try
			{
				Type type = AccessTools.TypeByName("Photon.Pun.PhotonNetwork");
				if (type != null)
				{
					PropertyInfo property = type.GetProperty("IsMasterClient");
					if (property != null)
					{
						return (bool)property.GetValue(null);
					}
				}
				Type type2 = AccessTools.TypeByName("GameManager");
				if (type2 != null)
				{
					object obj = AccessTools.Property(type2, "Instance")?.GetValue(null) ?? AccessTools.Field(type2, "instance")?.GetValue(null);
					if (obj != null)
					{
						return (bool)(AccessTools.Property(type2, "IsHost")?.GetValue(obj) ?? AccessTools.Field(type2, "isHost")?.GetValue(obj) ?? ((object)true));
					}
				}
				return true;
			}
			catch
			{
				return true;
			}
		}

		private static string GetUpgradeType(object instance)
		{
			string name = instance.GetType().Name;
			if (name.Contains("Health"))
			{
				return "Health";
			}
			if (name.Contains("Energy") || name.Contains("Stamina"))
			{
				return "Energy";
			}
			if (name.Contains("Sprint") || name.Contains("Speed"))
			{
				return "SprintSpeed";
			}
			if (name.Contains("Jump"))
			{
				return "ExtraJump";
			}
			if (name.Contains("Tumble") || name.Contains("Launch"))
			{
				return "TumbleLaunch";
			}
			if (name.Contains("Range"))
			{
				return "GrabRange";
			}
			if (name.Contains("Strength"))
			{
				return "GrabStrength";
			}
			if (name.Contains("Throw"))
			{
				return "GrabThrow";
			}
			if (name.Contains("Map") || name.Contains("Count"))
			{
				return "MapPlayerCount";
			}
			return name;
		}

		private static object GetSourcePlayer(object instance)
		{
			Type type = instance.GetType();
			string[] array = new string[8] { "player", "Player", "playerController", "PlayerController", "owner", "Owner", "playerAvatar", "PlayerAvatar" };
			foreach (string text in array)
			{
				object obj = AccessTools.Property(type, text)?.GetValue(instance) ?? AccessTools.Field(type, text)?.GetValue(instance);
				if (obj != null)
				{
					return obj;
				}
			}
			return null;
		}

		private static void ApplyUpgradeToOtherPlayers(string upgradeType, object sourcePlayer)
		{
			int shareChance = Plugin.UpgradeConfiguration.GetShareChance(upgradeType);
			foreach (object allPlayer in GetAllPlayers())
			{
				if (allPlayer != null && !allPlayer.Equals(sourcePlayer) && _random.Next(0, 100) < shareChance && ApplyUpgradeToPlayer(allPlayer, upgradeType))
				{
					Plugin.Log.LogInfo((object)$"[LuckyUpgrades] Success! {upgradeType} upgrade shared with another player (Chance: {shareChance}%)");
				}
			}
		}

		private static List<object> GetAllPlayers()
		{
			List<object> list = new List<object>();
			Type type = AccessTools.TypeByName("PlayerController");
			if (type != null && (AccessTools.Method(type, "GetAllPlayers", (Type[])null, (Type[])null)?.Invoke(null, null) ?? AccessTools.Method(type, "GetAll", (Type[])null, (Type[])null)?.Invoke(null, null)) is IEnumerable enumerable)
			{
				{
					foreach (object item2 in enumerable)
					{
						list.Add(item2);
					}
					return list;
				}
			}
			Type type2 = AccessTools.TypeByName("GameManager");
			if (type2 != null)
			{
				object obj = AccessTools.Property(type2, "Instance")?.GetValue(null) ?? AccessTools.Field(type2, "instance")?.GetValue(null);
				if (obj != null && (AccessTools.Property(type2, "players")?.GetValue(obj) ?? AccessTools.Field(type2, "players")?.GetValue(obj)) is IEnumerable enumerable2)
				{
					{
						foreach (object item3 in enumerable2)
						{
							list.Add(item3);
						}
						return list;
					}
				}
			}
			if (type != null)
			{
				Object[] array = Object.FindObjectsOfType(type);
				foreach (Object item in array)
				{
					list.Add(item);
				}
			}
			return list;
		}

		private static bool ApplyUpgradeToPlayer(object player, string upgradeType)
		{
			try
			{
				Type type = AccessTools.TypeByName("StatsManager");
				if (type != null)
				{
					object obj = AccessTools.Property(player.GetType(), "statsManager")?.GetValue(player);
					if (obj == null)
					{
						obj = AccessTools.Field(player.GetType(), "statsManager")?.GetValue(player);
						if (obj == null)
						{
							object obj2 = ((player is Component) ? player : null);
							obj = ((obj2 != null) ? ((Component)obj2).GetComponent(type) : null);
						}
					}
					object obj3 = obj;
					if (obj3 != null)
					{
						MethodInfo methodInfo = AccessTools.Method(type, "AddUpgrade", (Type[])null, (Type[])null) ?? AccessTools.Method(type, "ApplyUpgrade", (Type[])null, (Type[])null) ?? AccessTools.Method(type, "IncreaseLevel", (Type[])null, (Type[])null);
						if (methodInfo != null)
						{
							methodInfo.Invoke(obj3, new object[1] { upgradeType });
							return true;
						}
					}
				}
				return false;
			}
			catch
			{
				return false;
			}
		}
	}
}