using System; 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 Microsoft.CodeAnalysis; using Photon.Pun; 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.1.6.0")] [assembly: AssemblyInformationalVersion("1.1.6+d994f5a6e98d91a06e77982ef5767def1bd5cc71")] [assembly: AssemblyProduct("LuckyUpgrades")] [assembly: AssemblyTitle("LuckyUpgrades")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.6.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("LuckyUpgrades", "LuckyUpgrades", "1.1.6")] [BepInProcess("REPO.exe")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger; private static bool _isApplyingSharedUpgrade = false; private static readonly Random _random = new Random(); internal static string _mySteamID = null; internal static readonly Dictionary _sharedUpgrades = new Dictionary(); private Harmony harmony; public static Plugin Instance { get; private set; } public static UpgradeConfig UpgradeConfiguration { get; private set; } private void Awake() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_005a: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin LuckyUpgrades is loaded!"); UpgradeConfiguration = new UpgradeConfig(((BaseUnityPlugin)this).Config); harmony = new Harmony("LuckyUpgrades"); harmony.PatchAll(typeof(Plugin)); GameObject val = new GameObject("LuckyUpgrades_UpdateRunner"); val.AddComponent(); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; Logger.LogInfo((object)"Harmony patches applied!"); } internal static string GetMySteamID() { if (string.IsNullOrEmpty(_mySteamID)) { PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val != (Object)null) { _mySteamID = SemiFunc.PlayerGetSteamID(val); } } return _mySteamID; } internal static void ReapplySharedUpgrades() { if (_sharedUpgrades.Count == 0) { return; } string mySteamID = GetMySteamID(); if (string.IsNullOrEmpty(mySteamID)) { return; } Logger.LogInfo((object)$"[LuckyUpgrades] Reapplying {_sharedUpgrades.Count} upgrade types..."); try { _isApplyingSharedUpgrade = true; foreach (KeyValuePair sharedUpgrade in _sharedUpgrades) { string key = sharedUpgrade.Key; int value = sharedUpgrade.Value; if (value <= 0) { continue; } try { switch (key) { case "Health": { for (int num4 = 0; num4 < value; num4++) { PunManager.instance.UpgradePlayerHealth(mySteamID, 1); } break; } case "Energy": { for (int j = 0; j < value; j++) { PunManager.instance.UpgradePlayerEnergy(mySteamID, 1); } break; } case "ExtraJump": { for (int n = 0; n < value; n++) { PunManager.instance.UpgradePlayerExtraJump(mySteamID, 1); } break; } case "GrabRange": { for (int num6 = 0; num6 < value; num6++) { PunManager.instance.UpgradePlayerGrabRange(mySteamID, 1); } break; } case "GrabStrength": { for (int num2 = 0; num2 < value; num2++) { PunManager.instance.UpgradePlayerGrabStrength(mySteamID, 1); } break; } case "GrabThrow": { for (int l = 0; l < value; l++) { PunManager.instance.UpgradePlayerThrowStrength(mySteamID, 1); } break; } case "SprintSpeed": { for (int num7 = 0; num7 < value; num7++) { PunManager.instance.UpgradePlayerSprintSpeed(mySteamID, 1); } break; } case "TumbleLaunch": { for (int num5 = 0; num5 < value; num5++) { PunManager.instance.UpgradePlayerTumbleLaunch(mySteamID, 1); } break; } case "MapPlayerCount": { for (int num3 = 0; num3 < value; num3++) { PunManager.instance.UpgradeMapPlayerCount(mySteamID, 1); } break; } case "TumbleClimb": { for (int num = 0; num < value; num++) { PunManager.instance.UpgradePlayerTumbleClimb(mySteamID, 1); } break; } case "TumbleWings": { for (int m = 0; m < value; m++) { PunManager.instance.UpgradePlayerTumbleWings(mySteamID, 1); } break; } case "CrouchRest": { for (int k = 0; k < value; k++) { PunManager.instance.UpgradePlayerCrouchRest(mySteamID, 1); } break; } case "DeathHeadBattery": { for (int i = 0; i < value; i++) { PunManager.instance.UpgradeDeathHeadBattery(mySteamID, 1); } break; } } Logger.LogInfo((object)$"[LuckyUpgrades] Reapplied: {key} +{value}"); } catch (Exception ex) { Logger.LogError((object)("[LuckyUpgrades] Error reapplying " + key + ": " + ex.Message)); } } } finally { _isApplyingSharedUpgrade = false; } } private static void TrackSharedUpgrade(string upgradeType, int amount) { if (_sharedUpgrades.ContainsKey(upgradeType)) { _sharedUpgrades[upgradeType] += amount; } else { _sharedUpgrades[upgradeType] = amount; } Logger.LogInfo((object)$"[LuckyUpgrades] Tracked: {upgradeType} (total: {_sharedUpgrades[upgradeType]})"); } [HarmonyPatch(typeof(PunManager), "UpgradePlayerHealth")] [HarmonyPostfix] public static void UpgradePlayerHealth_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("Health", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradePlayerHealth(mySteamID, amount); } }); } [HarmonyPatch(typeof(PunManager), "UpgradePlayerEnergy")] [HarmonyPostfix] public static void UpgradePlayerEnergy_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("Energy", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradePlayerEnergy(mySteamID, amount); } }); } [HarmonyPatch(typeof(PunManager), "UpgradePlayerExtraJump")] [HarmonyPostfix] public static void UpgradePlayerExtraJump_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("ExtraJump", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradePlayerExtraJump(mySteamID, amount); } }); } [HarmonyPatch(typeof(PunManager), "UpgradePlayerGrabRange")] [HarmonyPostfix] public static void UpgradePlayerGrabRange_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("GrabRange", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradePlayerGrabRange(mySteamID, amount); } }); } [HarmonyPatch(typeof(PunManager), "UpgradePlayerGrabStrength")] [HarmonyPostfix] public static void UpgradePlayerGrabStrength_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("GrabStrength", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradePlayerGrabStrength(mySteamID, amount); } }); } [HarmonyPatch(typeof(PunManager), "UpgradePlayerThrowStrength")] [HarmonyPostfix] public static void UpgradePlayerThrowStrength_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("GrabThrow", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradePlayerThrowStrength(mySteamID, amount); } }); } [HarmonyPatch(typeof(PunManager), "UpgradePlayerSprintSpeed")] [HarmonyPostfix] public static void UpgradePlayerSprintSpeed_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("SprintSpeed", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradePlayerSprintSpeed(mySteamID, amount); } }); } [HarmonyPatch(typeof(PunManager), "UpgradePlayerTumbleLaunch")] [HarmonyPostfix] public static void UpgradePlayerTumbleLaunch_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("TumbleLaunch", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradePlayerTumbleLaunch(mySteamID, amount); } }); } [HarmonyPatch(typeof(PunManager), "UpgradeMapPlayerCount")] [HarmonyPostfix] public static void UpgradeMapPlayerCount_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("MapPlayerCount", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradeMapPlayerCount(mySteamID, amount); } }); } [HarmonyPatch(typeof(PunManager), "UpgradePlayerTumbleClimb")] [HarmonyPostfix] public static void UpgradePlayerTumbleClimb_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("TumbleClimb", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradePlayerTumbleClimb(mySteamID, amount); } }); } [HarmonyPatch(typeof(PunManager), "UpgradePlayerTumbleWings")] [HarmonyPostfix] public static void UpgradePlayerTumbleWings_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("TumbleWings", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradePlayerTumbleWings(mySteamID, amount); } }); } [HarmonyPatch(typeof(PunManager), "UpgradePlayerCrouchRest")] [HarmonyPostfix] public static void UpgradePlayerCrouchRest_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("CrouchRest", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradePlayerCrouchRest(mySteamID, amount); } }); } [HarmonyPatch(typeof(PunManager), "UpgradeDeathHeadBattery")] [HarmonyPostfix] public static void UpgradeDeathHeadBattery_Postfix(string _steamID, int value) { ApplySharedUpgradeToSelf("DeathHeadBattery", _steamID, value, delegate(int amount) { string mySteamID = GetMySteamID(); if (!string.IsNullOrEmpty(mySteamID)) { PunManager.instance.UpgradeDeathHeadBattery(mySteamID, amount); } }); } private static void ApplySharedUpgradeToSelf(string upgradeType, string sourceSteamID, int amount, Action applyToSelf) { try { if (_isApplyingSharedUpgrade) { return; } string mySteamID = GetMySteamID(); if (string.IsNullOrEmpty(mySteamID) || mySteamID == sourceSteamID) { return; } int shareChance = UpgradeConfiguration.GetShareChance(upgradeType); int num = _random.Next(100); if (num < shareChance) { try { _isApplyingSharedUpgrade = true; applyToSelf(amount); TrackSharedUpgrade(upgradeType, amount); Logger.LogInfo((object)$"[LuckyUpgrades] Shared upgrade applied: {upgradeType} +{amount} (rolled: {num} | chance: {shareChance}%) ✓"); return; } finally { _isApplyingSharedUpgrade = false; } } Logger.LogInfo((object)$"[LuckyUpgrades] Shared upgrade missed: {upgradeType} (rolled: {num} | chance: {shareChance}%) ✗"); } catch (Exception ex) { Logger.LogError((object)("[LuckyUpgrades] Error in ApplySharedUpgradeToSelf: " + ex.Message)); } } } public class UpgradeReapplyRunner : MonoBehaviour { private static readonly HashSet SESSION_END_LEVELS = new HashSet { "Level - Main Menu", "Level - Lobby Menu" }; private string _lastLevelName = ""; private float _reapplyDelay; private bool _pendingReapply; private const float REAPPLY_DELAY_SECONDS = 3f; private void Update() { string text = ""; try { if ((Object)(object)RunManager.instance != (Object)null && (Object)(object)RunManager.instance.levelCurrent != (Object)null) { text = ((Object)RunManager.instance.levelCurrent).name; } } catch { } if (!string.IsNullOrEmpty(text) && text != _lastLevelName) { Plugin.Logger.LogInfo((object)("[LuckyUpgrades] Level changed: " + _lastLevelName + " -> " + text)); _lastLevelName = text; if (SESSION_END_LEVELS.Contains(text)) { Plugin._sharedUpgrades.Clear(); Plugin._mySteamID = null; Plugin.Logger.LogInfo((object)"[LuckyUpgrades] Session ended. All tracked data cleared."); return; } if (Plugin._sharedUpgrades.Count > 0) { _pendingReapply = true; _reapplyDelay = 3f; Plugin.Logger.LogInfo((object)$"[LuckyUpgrades] Scheduled reapply in {3f}s..."); } } if (!_pendingReapply) { return; } _reapplyDelay -= Time.deltaTime; if (_reapplyDelay <= 0f) { _pendingReapply = false; if (PhotonNetwork.IsMasterClient) { Plugin.Logger.LogInfo((object)"[LuckyUpgrades] Host detected, skipping reapply (upgrades persist on host)"); } else if ((Object)(object)SemiFunc.PlayerAvatarLocal() != (Object)null && !string.IsNullOrEmpty(Plugin.GetMySteamID())) { Plugin.ReapplySharedUpgrades(); } } } } public class UpgradeConfig { public ConfigEntry ChanceToActivatePlayerHealth { get; private set; } public ConfigEntry ChanceToActivatePlayerEnergy { get; private set; } public ConfigEntry ChanceToActivatePlayerSprintSpeed { get; private set; } public ConfigEntry ChanceToActivatePlayerExtraJump { get; private set; } public ConfigEntry ChanceToActivatePlayerTumbleLaunch { get; private set; } public ConfigEntry ChanceToActivatePlayerGrabRange { get; private set; } public ConfigEntry ChanceToActivatePlayerGrabStrength { get; private set; } public ConfigEntry ChanceToActivatePlayerGrabThrow { get; private set; } public ConfigEntry ChanceToActivatePlayerTumbleClimb { get; private set; } public ConfigEntry ChanceToActivatePlayerTumbleWings { get; private set; } public ConfigEntry ChanceToActivatePlayerCrouchRest { get; private set; } public ConfigEntry ChanceToActivateDeathHeadBattery { get; private set; } public ConfigEntry ChanceToActivateMapPlayerCount { get; private set; } public UpgradeConfig(ConfigFile config) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Expected O, but got Unknown //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Expected O, but got Unknown //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Expected O, but got Unknown //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Expected O, but got Unknown ChanceToActivatePlayerHealth = config.Bind("Upgrades", "ChanceToActivatePlayerHealth", 25, new ConfigDescription("% Chance to share the Health upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ChanceToActivatePlayerEnergy = config.Bind("Upgrades", "ChanceToActivatePlayerEnergy", 25, new ConfigDescription("% Chance to share the Energy (Stamina) upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ChanceToActivatePlayerSprintSpeed = config.Bind("Upgrades", "ChanceToActivatePlayerSprintSpeed", 25, new ConfigDescription("% Chance to share the Sprint Speed upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ChanceToActivatePlayerExtraJump = config.Bind("Upgrades", "ChanceToActivatePlayerExtraJump", 25, new ConfigDescription("% Chance to share the Extra Jump upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ChanceToActivatePlayerTumbleLaunch = config.Bind("Upgrades", "ChanceToActivatePlayerTumbleLaunch", 25, new ConfigDescription("% Chance to share the Tumble Launch upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ChanceToActivatePlayerGrabRange = config.Bind("Upgrades", "ChanceToActivatePlayerGrabRange", 25, new ConfigDescription("% Chance to share the Grab Range upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ChanceToActivatePlayerGrabStrength = config.Bind("Upgrades", "ChanceToActivatePlayerGrabStrength", 25, new ConfigDescription("% Chance to share the Grab Strength upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ChanceToActivatePlayerGrabThrow = config.Bind("Upgrades", "ChanceToActivatePlayerGrabThrow", 25, new ConfigDescription("% Chance to share the Grab Throw upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ChanceToActivatePlayerTumbleClimb = config.Bind("Upgrades", "ChanceToActivatePlayerTumbleClimb", 25, new ConfigDescription("% Chance to share the Tumble Climb upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ChanceToActivatePlayerTumbleWings = config.Bind("Upgrades", "ChanceToActivatePlayerTumbleWings", 25, new ConfigDescription("% Chance to share the Tumble Wings upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ChanceToActivatePlayerCrouchRest = config.Bind("Upgrades", "ChanceToActivatePlayerCrouchRest", 25, new ConfigDescription("% Chance to share the Crouch Rest upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ChanceToActivateDeathHeadBattery = config.Bind("Upgrades", "ChanceToActivateDeathHeadBattery", 25, new ConfigDescription("% Chance to share the Death Head Battery upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); ChanceToActivateMapPlayerCount = config.Bind("Upgrades", "ChanceToActivateMapPlayerCount", 25, new ConfigDescription("% Chance to share the Map Player Count upgrade", (AcceptableValueBase)(object)new AcceptableValueRange(0, 100), Array.Empty())); } public int GetShareChance(string upgradeType) { 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("tumblelaunch") || text.Contains("launch")) { return ChanceToActivatePlayerTumbleLaunch.Value; } if (text.Contains("tumbleclimb") || text.Contains("climb")) { return ChanceToActivatePlayerTumbleClimb.Value; } if (text.Contains("tumblewing") || text.Contains("wing")) { return ChanceToActivatePlayerTumbleWings.Value; } if (text.Contains("crouch") || text.Contains("rest")) { return ChanceToActivatePlayerCrouchRest.Value; } if (text.Contains("deathhead") || text.Contains("battery")) { return ChanceToActivateDeathHeadBattery.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 25; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "LuckyUpgrades"; public const string PLUGIN_NAME = "LuckyUpgrades"; public const string PLUGIN_VERSION = "1.1.6"; } }