Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CustomApparatusValues v1.5.0
plugins/CustomApparatusValues/CustomApparatusValues.dll
Decompiled 3 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Unity.Collections; using Unity.Netcode; 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("CustomApparatusValues")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CustomApparatusValues")] [assembly: AssemblyTitle("CustomApparatusValues")] [assembly: AssemblyVersion("1.0.0.0")] namespace CustomApparatusValues; internal static class ApparatusValueSync { private const string SyncMessageName = "CustomApparatusValues.SyncValue"; private static bool handlersRegistered = false; private static readonly Dictionary<ulong, int> PendingValues = new Dictionary<ulong, int>(); private static readonly HashSet<ulong> AppliedValues = new HashSet<ulong>(); internal static void EnsureHandlersRegistered() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && !handlersRegistered && singleton.CustomMessagingManager != null) { singleton.CustomMessagingManager.RegisterNamedMessageHandler("CustomApparatusValues.SyncValue", new HandleNamedMessageDelegate(OnReceiveSyncValueMessage)); handlersRegistered = true; Plugin.LogVerbose("Handler de synchronisation enregistré."); } } internal static void ResetState() { PendingValues.Clear(); AppliedValues.Clear(); handlersRegistered = false; } internal static bool HasAlreadyBeenApplied(ulong networkObjectId) { return AppliedValues.Contains(networkObjectId); } internal static void MarkApplied(ulong networkObjectId) { if (!AppliedValues.Contains(networkObjectId)) { AppliedValues.Add(networkObjectId); } } internal static void SyncToClients(GrabbableObject grabbableObject, int value) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)grabbableObject == (Object)null) { return; } NetworkObject networkObject = ((NetworkBehaviour)grabbableObject).NetworkObject; if ((Object)(object)networkObject == (Object)null) { Plugin.LogWarning("Impossible de synchroniser un objet sans NetworkObject."); return; } NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.CustomMessagingManager == null) { return; } EnsureHandlersRegistered(); ulong networkObjectId = networkObject.NetworkObjectId; MarkApplied(networkObjectId); Plugin.LogVerbose("Sync envoyée pour l'objet réseau " + networkObjectId + " avec valeur " + value + "."); FastBufferWriter val = default(FastBufferWriter); try { val = new FastBufferWriter(12, (Allocator)2, -1); ((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref value, default(ForPrimitives)); foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { if (connectedClientsId != singleton.LocalClientId) { singleton.CustomMessagingManager.SendNamedMessage("CustomApparatusValues.SyncValue", connectedClientsId, val, (NetworkDelivery)3); } } } catch (Exception ex) { Plugin.LogError("Erreur lors de l'envoi de la synchronisation: " + ex); } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveSyncValueMessage(ulong senderClientId, FastBufferReader reader) { //IL_0006: 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_0018: 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) try { ulong num = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives)); int value = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref value, default(ForPrimitives)); Plugin.LogVerbose("Sync reçue depuis " + senderClientId + " pour objet " + num + " => " + value); if (!TryApplyValueToSpawnedObject(num, value)) { PendingValues[num] = value; Plugin.LogVerbose("Objet " + num + " pas encore disponible côté client. Sync mise en attente."); } } catch (Exception ex) { Plugin.LogError("Erreur lors de la réception d'une synchronisation: " + ex); } } internal static void TryApplyPendingValue(GrabbableObject grabbableObject) { if (!((Object)(object)grabbableObject == (Object)null) && !((Object)(object)((NetworkBehaviour)grabbableObject).NetworkObject == (Object)null)) { ulong networkObjectId = ((NetworkBehaviour)grabbableObject).NetworkObject.NetworkObjectId; if (PendingValues.TryGetValue(networkObjectId, out var value)) { ApplyValue(grabbableObject, value); PendingValues.Remove(networkObjectId); Plugin.LogVerbose("Valeur en attente appliquée à l'objet " + networkObjectId + "."); } } } internal static bool TryApplyValueToSpawnedObject(ulong objectId, int value) { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.SpawnManager == null) { return false; } if (!singleton.SpawnManager.SpawnedObjects.TryGetValue(objectId, out var value2)) { return false; } if ((Object)(object)value2 == (Object)null) { return false; } GrabbableObject component = ((Component)value2).GetComponent<GrabbableObject>(); if ((Object)(object)component == (Object)null) { return false; } ApplyValue(component, value); return true; } internal static void ApplyValue(GrabbableObject grabbableObject, int value) { if ((Object)(object)grabbableObject == (Object)null) { return; } try { grabbableObject.SetScrapValue(value); if (grabbableObject.scrapValue != value) { grabbableObject.scrapValue = value; } if ((Object)(object)grabbableObject.itemProperties != (Object)null) { grabbableObject.itemProperties.creditsWorth = value; } if ((Object)(object)((NetworkBehaviour)grabbableObject).NetworkObject != (Object)null) { MarkApplied(((NetworkBehaviour)grabbableObject).NetworkObject.NetworkObjectId); } string text = (((Object)(object)grabbableObject.itemProperties != (Object)null) ? grabbableObject.itemProperties.itemName : "<unknown>"); Plugin.LogVerbose("Valeur appliquée à '" + text + "' => " + value); } catch (Exception ex) { Plugin.LogError("Erreur lors de l'application d'une valeur synchronisée: " + ex); } } } [HarmonyPatch(typeof(StartOfRound))] internal static class StartOfRoundPatch { [HarmonyPostfix] [HarmonyPatch("Awake")] private static void AwakePostfix() { Plugin.ResetRuntimeState(); ApparatusValueSync.ResetState(); ApparatusValueSync.EnsureHandlersRegistered(); Plugin.LogVerbose("Initialisation réseau du mod terminée."); } } [HarmonyPatch(typeof(GameNetworkManager))] internal static class GameNetworkManagerPatch { [HarmonyPostfix] [HarmonyPatch("Start")] private static void StartPostfix() { ApparatusValueSync.EnsureHandlersRegistered(); } } [HarmonyPatch(typeof(GrabbableObject))] internal static class GrabbableObjectPatch { [HarmonyPostfix] [HarmonyPatch("Start")] private static void StartPostfix(GrabbableObject __instance) { if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.itemProperties == (Object)null) { return; } string itemName = __instance.itemProperties.itemName; Plugin.LogVerbose("Objet détecté : '" + itemName + "' | scrap actuel : " + __instance.scrapValue); NetworkObject networkObject = ((NetworkBehaviour)__instance).NetworkObject; if ((Object)(object)networkObject == (Object)null) { Plugin.LogVerbose("Objet sans NetworkObject ignoré : '" + itemName + "'"); return; } ulong networkObjectId = networkObject.NetworkObjectId; if (Plugin.IsHostOrServer()) { if (ApparatusValueSync.HasAlreadyBeenApplied(networkObjectId)) { return; } int value; bool flag = Plugin.TryGetWantedValue(itemName, out value); bool flag2 = Plugin.IsMidasOnlyTrackedItem(itemName); if (!flag && !flag2) { return; } int scrapValue = __instance.scrapValue; if (flag) { if (__instance.isInShipRoom && Plugin.IsRecognizedTrackedValue(itemName, scrapValue)) { ApparatusValueSync.ApplyValue(__instance, scrapValue); ApparatusValueSync.SyncToClients(__instance, scrapValue); Plugin.LogInfo("Host: valeur sauvegardée conservée pour '" + itemName + "' => " + scrapValue); return; } int value2 = Plugin.ApplyMidasTouchIfNeeded(value, itemName); ApparatusValueSync.ApplyValue(__instance, value2); ApparatusValueSync.SyncToClients(__instance, value2); Plugin.LogInfo("Host: valeur fixée pour '" + itemName + "' => " + value2 + " (base " + value + ")"); return; } if (flag2) { if (__instance.isInShipRoom && scrapValue > 0) { ApparatusValueSync.ApplyValue(__instance, scrapValue); ApparatusValueSync.SyncToClients(__instance, scrapValue); Plugin.LogInfo("Host: valeur sauvegardée conservée pour '" + itemName + "' => " + scrapValue); return; } int num = ((scrapValue > 0) ? scrapValue : 0); if (num > 0) { int value3 = Plugin.ApplyMidasTouchIfNeeded(num, itemName); ApparatusValueSync.ApplyValue(__instance, value3); ApparatusValueSync.SyncToClients(__instance, value3); Plugin.LogInfo("Host: compatibilité Midas-only appliquée pour '" + itemName + "' => " + value3 + " (base détectée " + num + ")"); } return; } } if (Plugin.IsClientOnly()) { ApparatusValueSync.TryApplyPendingValue(__instance); } } } internal static class MidasTouchRuntimePatch { private static bool _installed; internal static void Install(Harmony harmony) { //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Expected O, but got Unknown //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Expected O, but got Unknown if (_installed || harmony == null) { return; } _installed = true; try { Assembly moreShipUpgradesAssembly = Plugin.GetMoreShipUpgradesAssembly(); Type midasType = Plugin.GetMidasType(); Type baseUpgradeType = Plugin.GetBaseUpgradeType(); Type tierUpgradeType = Plugin.GetTierUpgradeType(); if (moreShipUpgradesAssembly == null) { Plugin.LogWarning("Compatibilité Midas Touch: assembly MoreShipUpgrades introuvable pour les patches runtime."); return; } List<MethodInfo> list = new List<MethodInfo>(); List<MethodInfo> list2 = new List<MethodInfo>(); Type[] types; try { types = moreShipUpgradesAssembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { types = ex.Types; } if (types == null) { return; } foreach (Type type in types) { if (type == null) { continue; } bool flag = false; if (midasType != null && (type == midasType || midasType.IsAssignableFrom(type))) { flag = true; } if (baseUpgradeType != null && (type == baseUpgradeType || baseUpgradeType.IsAssignableFrom(type))) { flag = true; } if (tierUpgradeType != null && (type == tierUpgradeType || tierUpgradeType.IsAssignableFrom(type))) { flag = true; } if (!flag && type.FullName != null && type.FullName.IndexOf("MidasTouch", StringComparison.OrdinalIgnoreCase) >= 0) { flag = true; } if (!flag) { continue; } MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo == null)) { if (string.Equals(methodInfo.Name, "load", StringComparison.OrdinalIgnoreCase) || string.Equals(methodInfo.Name, "Load", StringComparison.OrdinalIgnoreCase)) { list.Add(methodInfo); } else if (string.Equals(methodInfo.Name, "Increment", StringComparison.OrdinalIgnoreCase)) { list2.Add(methodInfo); } } } } HarmonyMethod postfix = new HarmonyMethod(typeof(MidasTouchRuntimePatch).GetMethod("LoadPostfix", BindingFlags.Static | BindingFlags.NonPublic)); HarmonyMethod postfix2 = new HarmonyMethod(typeof(MidasTouchRuntimePatch).GetMethod("IncrementPostfix", BindingFlags.Static | BindingFlags.NonPublic)); PatchMethodList(harmony, list, postfix, "load"); PatchMethodList(harmony, list2, postfix2, "Increment"); if (list.Count == 0) { Plugin.LogWarning("Compatibilité Midas Touch: aucun load()/Load() pertinent trouvé pour patch runtime."); } if (list2.Count == 0) { Plugin.LogWarning("Compatibilité Midas Touch: aucun Increment() pertinent trouvé pour patch runtime."); } } catch (Exception ex2) { Plugin.LogError("Erreur lors de l'installation des patches runtime Midas Touch: " + ex2); } } private static void PatchMethodList(Harmony harmony, List<MethodInfo> methods, HarmonyMethod postfix, string label) { if (methods == null || postfix == null) { return; } HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); for (int i = 0; i < methods.Count; i++) { MethodInfo methodInfo = methods[i]; if (methodInfo == null || methodInfo.DeclaringType == null) { continue; } string item = BuildMethodKey(methodInfo); if (!hashSet.Contains(item)) { hashSet.Add(item); try { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, postfix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.LogInfo("Compatibilité Midas Touch: patch runtime installé sur " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name + "()"); } catch (Exception ex) { Plugin.LogError("Erreur lors du patch runtime sur " + methodInfo.DeclaringType.FullName + "." + methodInfo.Name + "(): " + ex); } } } } private static string BuildMethodKey(MethodInfo method) { ParameterInfo[] parameters = method.GetParameters(); string[] array = new string[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { array[i] = parameters[i].ParameterType.FullName; } return method.DeclaringType.FullName + "::" + method.Name + "(" + string.Join(",", array) + ")"; } private static void LoadPostfix(object __instance) { try { Plugin.NotifyMidasLoad(__instance); } catch (Exception ex) { Plugin.LogError("Erreur dans le postfix runtime load()/Load() de Midas Touch: " + ex); } } private static void IncrementPostfix(object __instance) { try { Plugin.NotifyMidasIncrement(__instance); } catch (Exception ex) { Plugin.LogError("Erreur dans le postfix runtime Increment() de Midas Touch: " + ex); } } } [BepInPlugin("lc.mod.customapparatusvalues", "Custom Apparatus Values", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string ModGuid = "lc.mod.customapparatusvalues"; public const string ModName = "Custom Apparatus Values"; public const string ModVersion = "1.0.0"; internal static Plugin Instance = null; internal static Harmony Harmony = null; internal static ConfigEntry<int> ApparatusValue = null; internal static ConfigEntry<int> PlasmaApparatusValue = null; internal static ConfigEntry<int> PinkApparatusValue = null; internal static ConfigEntry<int> HauntedApparatusValue = null; internal static ConfigEntry<int> ToxicApparatusValue = null; internal static ConfigEntry<int> BeholderEyeValue = null; internal static ConfigEntry<int> ThePaintingValue = null; internal static ConfigEntry<int> PowerStarValue = null; internal static ConfigEntry<int> BloodyApparatusValue = null; internal static ConfigEntry<int> CosmicApparatusValue = null; internal static ConfigEntry<int> RoyalApparatusValue = null; internal static ConfigEntry<int> SoulOrbValue = null; internal static ConfigEntry<bool> EnableVerboseLogs = null; internal static ConfigEntry<bool> EnableMidasTouchCompatibility = null; private static Assembly _moreShipUpgradesAssembly = null; private static Type _midasType = null; private static Type _baseUpgradeType = null; private static Type _tierUpgradeType = null; private static MethodInfo _assemblyGetUpgradeLevelMethod = null; private static bool _midasReflectionInitialized = false; private static readonly string[] _midasCandidates = new string[5] { "Midas Touch", "MidasTouch", "midas", "midas touch", "MoreShipUpgrades.UpgradeComponents.TierUpgrades.Ship.MidasTouch" }; private static readonly HashSet<string> MidasOnlyItems = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Human heart" }; private static int _cachedMidasLevel = -1; internal static readonly Dictionary<string, Func<int>> TargetValues = new Dictionary<string, Func<int>>(StringComparer.OrdinalIgnoreCase) { { "Apparatus", () => ApparatusValue.Value }, { "Plasma apparatus", () => PlasmaApparatusValue.Value }, { "Pink Apparatus", () => PinkApparatusValue.Value }, { "Haunted apparatus", () => HauntedApparatusValue.Value }, { "Toxic Apparatus", () => ToxicApparatusValue.Value }, { "Beholder's eye", () => BeholderEyeValue.Value }, { "The painting", () => ThePaintingValue.Value }, { "Power Star", () => PowerStarValue.Value }, { "Bloody apparatus", () => BloodyApparatusValue.Value }, { "Cosmic apparatus", () => CosmicApparatusValue.Value }, { "Royal apparatus", () => RoyalApparatusValue.Value }, { "Soul orb", () => SoulOrbValue.Value } }; private void Awake() { //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Expected O, but got Unknown Instance = this; ApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "Apparatus", 200, "Valeur de l'Apparatus vanilla."); PlasmaApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "PlasmaApparatus", 240, "Valeur du Plasma apparatus (Greenhouse)."); PinkApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "PinkApparatus", 210, "Valeur du Pink Apparatus (Toy Store)."); HauntedApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "HauntedApparatus", 225, "Valeur du Haunted apparatus (Rubber Rooms)."); ToxicApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "ToxicApparatus", 280, "Valeur du Toxic Apparatus (Grand Armory)."); BeholderEyeValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "BeholdersEye", 320, "Valeur du Beholder's eye (Atlantean Citadel)."); ThePaintingValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "ThePainting", 400, "Valeur de The painting (Art Gallery)."); PowerStarValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "PowerStar", 200, "Valeur du Power Star."); BloodyApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "BloodyApparatus", 300, "Valeur du Bloody apparatus."); CosmicApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "CosmicApparatus", 1600, "Valeur du Cosmic apparatus."); RoyalApparatusValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "RoyalApparatus", 400, "Valeur du Royal apparatus."); SoulOrbValue = ((BaseUnityPlugin)this).Config.Bind<int>("Values", "SoulOrb", 2000, "Valeur du Soul orb."); EnableVerboseLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableVerboseLogs", true, "Active les logs détaillés."); EnableMidasTouchCompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "EnableMidasTouchCompatibility", true, "Applique Midas Touch après la valeur de base du générateur."); InitializeMidasReflection(); Harmony = new Harmony("lc.mod.customapparatusvalues"); Harmony.PatchAll(); MidasTouchRuntimePatch.Install(Harmony); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Custom Apparatus Values chargé."); } internal static void ResetRuntimeState() { _cachedMidasLevel = -1; LogVerbose("Etat runtime Midas Touch réinitialisé."); } internal static bool TryGetWantedValue(string itemName, out int value) { value = 0; if (string.IsNullOrWhiteSpace(itemName)) { return false; } string key = itemName.Trim(); if (!TargetValues.TryGetValue(key, out var value2)) { return false; } value = value2(); return true; } internal static bool IsMidasOnlyTrackedItem(string itemName) { if (string.IsNullOrWhiteSpace(itemName)) { return false; } return MidasOnlyItems.Contains(itemName.Trim()); } internal static bool IsTrackedItem(string itemName) { if (IsMidasOnlyTrackedItem(itemName)) { return true; } int value; return TryGetWantedValue(itemName, out value); } internal static bool IsRecognizedTrackedValue(string itemName, int currentValue) { if (currentValue <= 0) { return false; } if (!TryGetWantedValue(itemName, out var value)) { return false; } for (int i = 0; i <= 5; i++) { if (((i <= 0) ? value : Mathf.RoundToInt((float)value * (1f + 0.2f * (float)i))) == currentValue) { return true; } } return false; } internal static bool IsHostOrServer() { if ((Object)(object)NetworkManager.Singleton == (Object)null) { return false; } return NetworkManager.Singleton.IsServer; } internal static bool IsClientOnly() { if ((Object)(object)NetworkManager.Singleton == (Object)null) { return false; } if (NetworkManager.Singleton.IsClient) { return !NetworkManager.Singleton.IsServer; } return false; } internal static void LogInfo(string message) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)message); } } internal static void LogWarning(string message) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)message); } } internal static void LogError(string message) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogError((object)message); } } internal static void LogVerbose(string message) { if ((Object)(object)Instance != (Object)null && EnableVerboseLogs.Value) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)message); } } internal static Type FindTypeInLoadedAssemblies(string fullName) { if (string.IsNullOrWhiteSpace(fullName)) { return null; } Type type = Type.GetType(fullName); if (type != null) { return type; } type = AccessTools.TypeByName(fullName); if (type != null) { return type; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (!(assembly == null)) { type = assembly.GetType(fullName, throwOnError: false); if (type != null) { return type; } } } return null; } internal static Assembly GetMoreShipUpgradesAssembly() { return _moreShipUpgradesAssembly; } internal static Type GetMidasType() { return _midasType; } internal static Type GetBaseUpgradeType() { return _baseUpgradeType; } internal static Type GetTierUpgradeType() { return _tierUpgradeType; } private static MethodInfo FindMethodInAssembly(Assembly assembly, string methodName) { if (assembly == null || string.IsNullOrWhiteSpace(methodName)) { return null; } Type[] types; try { types = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { types = ex.Types; } if (types == null) { return null; } foreach (Type type in types) { if (type == null) { continue; } MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo == null) && string.Equals(methodInfo.Name, methodName, StringComparison.Ordinal)) { return methodInfo; } } } return null; } private static string GetMethodSignature(MethodInfo method) { if (method == null) { return "<null>"; } ParameterInfo[] parameters = method.GetParameters(); string[] array = new string[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { array[i] = parameters[i].ParameterType.Name + " " + parameters[i].Name; } string text = ((method.DeclaringType != null) ? method.DeclaringType.FullName : "<no declaring type>"); string text2 = (method.IsStatic ? "static " : "instance "); return text + " :: " + text2 + method.ReturnType.Name + " " + method.Name + "(" + string.Join(", ", array) + ")"; } private static void InitializeMidasReflection() { if (_midasReflectionInitialized) { return; } _midasReflectionInitialized = true; try { _midasType = FindTypeInLoadedAssemblies("MoreShipUpgrades.UpgradeComponents.TierUpgrades.Ship.MidasTouch"); _baseUpgradeType = FindTypeInLoadedAssemblies("MoreShipUpgrades.Misc.Upgrades.BaseUpgrade"); _tierUpgradeType = FindTypeInLoadedAssemblies("MoreShipUpgrades.Misc.Upgrades.TierUpgrade"); if (_midasType == null) { LogWarning("Compatibilité Midas Touch: type MidasTouch introuvable."); return; } _moreShipUpgradesAssembly = _midasType.Assembly; LogInfo("Compatibilité Midas Touch: type MidasTouch trouvé: " + _midasType.FullName); LogInfo("Compatibilité Midas Touch: assembly détecté: " + _moreShipUpgradesAssembly.GetName().Name); _assemblyGetUpgradeLevelMethod = FindMethodInAssembly(_moreShipUpgradesAssembly, "GetUpgradeLevel"); if (_assemblyGetUpgradeLevelMethod != null) { LogInfo("Compatibilité Midas Touch: méthode GetUpgradeLevel trouvée."); LogInfo("Signature trouvée: " + GetMethodSignature(_assemblyGetUpgradeLevelMethod)); } else { LogWarning("Compatibilité Midas Touch: méthode GetUpgradeLevel introuvable."); } } catch (Exception ex) { LogError("Erreur lors de l'initialisation de la compatibilité Midas Touch: " + ex); } } private static bool TryExtractInt(object value, out int intValue) { intValue = 0; if (value == null) { return false; } if (value is int) { intValue = (int)value; return true; } return int.TryParse(value.ToString(), out intValue); } private static bool TryGetRawMidasUpgradeLevel(out int rawLevel) { rawLevel = -1; if (_assemblyGetUpgradeLevelMethod == null) { return false; } try { ParameterInfo[] parameters = _assemblyGetUpgradeLevelMethod.GetParameters(); if (parameters.Length != 1 || parameters[0].ParameterType != typeof(string)) { return false; } int num = int.MinValue; bool flag = false; for (int i = 0; i < _midasCandidates.Length; i++) { string text = _midasCandidates[i]; if (TryExtractInt(_assemblyGetUpgradeLevelMethod.Invoke(null, new object[1] { text }), out var intValue)) { flag = true; LogVerbose("GetUpgradeLevel(\"" + text + "\") => " + intValue); if (intValue > num) { num = intValue; } } } if (!flag) { return false; } rawLevel = num; LogVerbose("Niveau Midas Touch brut retenu via GetUpgradeLevel = " + rawLevel); return true; } catch (Exception ex) { LogError("Erreur lors de GetUpgradeLevel pour Midas Touch: " + ex); return false; } } internal static bool IsMidasTouchInstance(object instance) { if (instance == null || _midasType == null) { return false; } Type type = instance.GetType(); if (_midasType.IsAssignableFrom(type)) { return true; } if (type.FullName != null && type.FullName.IndexOf("MidasTouch", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } return false; } internal static void NotifyMidasLoad(object instance) { if (!IsMidasTouchInstance(instance)) { return; } if (TryGetRawMidasUpgradeLevel(out var rawLevel)) { if (rawLevel >= 1) { _cachedMidasLevel = rawLevel + 1; if (_cachedMidasLevel > 5) { _cachedMidasLevel = 5; } LogInfo("Compatibilité Midas Touch: niveau restauré via load() => " + _cachedMidasLevel); } else { _cachedMidasLevel = 1; LogInfo("Compatibilité Midas Touch: rang 1 détecté via load()."); } } else { if (_cachedMidasLevel < 1) { _cachedMidasLevel = 1; } LogInfo("Compatibilité Midas Touch: fallback rang 1 via load()."); } } internal static void NotifyMidasIncrement(object instance) { if (IsMidasTouchInstance(instance)) { if (TryGetRawMidasUpgradeLevel(out var rawLevel) && rawLevel >= 1) { _cachedMidasLevel = rawLevel + 1; } else if (_cachedMidasLevel < 1) { _cachedMidasLevel = 2; } else { _cachedMidasLevel = Mathf.Min(_cachedMidasLevel + 1, 5); } LogInfo("Compatibilité Midas Touch: rang détecté via Increment() => " + _cachedMidasLevel); } } private static bool TryResolveMidasTouchLevel(out int level) { level = 0; if (_cachedMidasLevel > 0) { level = _cachedMidasLevel; LogVerbose("Résolution niveau Midas Touch via cache runtime = " + level); return true; } if (!TryGetRawMidasUpgradeLevel(out var rawLevel)) { return false; } if (rawLevel >= 1) { level = rawLevel + 1; if (level > 5) { level = 5; } if (_cachedMidasLevel < level) { _cachedMidasLevel = level; } LogVerbose("Résolution niveau Midas Touch via GetUpgradeLevel : rawLevel = " + rawLevel + ", niveau final = " + level); return true; } level = 0; LogVerbose("Résolution niveau Midas Touch : aucun achat détecté (rawLevel = " + rawLevel + ")"); return true; } internal static int ApplyMidasTouchIfNeeded(int baseValue, string itemName) { if (!EnableMidasTouchCompatibility.Value) { return baseValue; } if (!_midasReflectionInitialized) { InitializeMidasReflection(); } if (TryResolveMidasTouchLevel(out var level)) { if (level <= 0) { LogVerbose("Midas Touch non acheté pour '" + itemName + "' | niveau = " + level + " | valeur conservée = " + baseValue); return baseValue; } float num = 1f + 0.2f * (float)level; int result = Mathf.RoundToInt((float)baseValue * num); LogVerbose("Midas Touch appliqué à '" + itemName + "' | niveau = " + level + " | base = " + baseValue + " | multiplicateur = " + num.ToString("0.###") + " | final = " + result); return result; } return baseValue; } }