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 CosmeticCompleteCashConfig v4.0.0
CosmeticCompleteCashConfig.dll
Decompiled a day agousing System; 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 UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("REPOJP")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("zabuMod")] [assembly: AssemblyTitle("zabuMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.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 REPOJP.CosmeticCompleteCashConfig { [BepInPlugin("REPOJP.CosmeticCompleteCashConfig", "CosmeticCompleteCashConfig", "4.0.0")] public class CosmeticCompleteCashConfigPlugin : BaseUnityPlugin { public enum RewardMode { Fixed, RandomRange, Multiplier, Disabled } private enum RarityKey { Common, Uncommon, Rare, UltraRare, Unknown } [HarmonyPatch] private static class CosmeticShopMachineRewardCurrencyPatch { private static Type cosmeticShopMachineType; private static FieldInfo stateImpulseField; private static FieldInfo stateTimerField; private static FieldInfo interactingRewardField; private static FieldInfo interactingRarityField; private static FieldInfo screenCurrencyParticlesField; private static FieldInfo animatorField; private static MethodInfo rewardSetMethod; private static MethodInfo updateStateMethod; private static Type stateType; private static object rewardCurrencyOutroState; private static bool reflectionReady; private static bool reflectionInitialized; private static bool reflectionErrorLogged; private static MethodBase TargetMethod() { InitializeReflection(); if (cosmeticShopMachineType == null) { return null; } return AccessTools.Method(cosmeticShopMachineType, "StateRewardCurrency", (Type[])null, (Type[])null); } private static void InitializeReflection() { if (reflectionInitialized) { return; } reflectionInitialized = true; cosmeticShopMachineType = AccessTools.TypeByName("CosmeticShopMachine"); if (cosmeticShopMachineType == null) { return; } stateImpulseField = AccessTools.Field(cosmeticShopMachineType, "stateImpulse"); stateTimerField = AccessTools.Field(cosmeticShopMachineType, "stateTimer"); interactingRewardField = AccessTools.Field(cosmeticShopMachineType, "interactingReward"); interactingRarityField = AccessTools.Field(cosmeticShopMachineType, "interactingRarity"); screenCurrencyParticlesField = AccessTools.Field(cosmeticShopMachineType, "screenCurrencyParticles"); animatorField = AccessTools.Field(cosmeticShopMachineType, "animator"); rewardSetMethod = AccessTools.Method(cosmeticShopMachineType, "RewardSet", (Type[])null, (Type[])null); updateStateMethod = AccessTools.Method(cosmeticShopMachineType, "UpdateState", (Type[])null, (Type[])null); stateType = AccessTools.Inner(cosmeticShopMachineType, "State"); if (stateType != null) { try { rewardCurrencyOutroState = Enum.Parse(stateType, "RewardCurrencyOutro"); } catch { rewardCurrencyOutroState = null; } } reflectionReady = stateImpulseField != null && stateTimerField != null && interactingRewardField != null && interactingRarityField != null && rewardSetMethod != null && updateStateMethod != null && stateType != null && rewardCurrencyOutroState != null; } private static bool Prefix(object __instance) { if (!IsEnabled()) { return true; } if (__instance == null) { return true; } InitializeReflection(); if (!reflectionReady) { LogReflectionErrorOnce(); return true; } if (!ReflectionGameApi.IsMasterClientOrSingleplayer()) { return true; } try { if (GetStateImpulse(__instance)) { int interactingReward = GetInteractingReward(__instance); if (interactingReward >= 0) { LogDebug("Skipped custom currency reward because interactingReward is not negative. interactingReward=" + interactingReward); return true; } SetStateImpulse(__instance, value: false); object interactingRarity = GetInteractingRarity(__instance); RarityKey rarityKey = GetRarityKey(interactingRarity); int rewardCashK = GetRewardCashK(rarityKey); SetScreenCurrencyParticlesActive(__instance, active: true); InvokeAnimatorCurrencyReward(__instance); InvokeRewardSet(__instance); if (rewardMode.Value != RewardMode.Disabled && rewardCashK > 0) { int runCurrency = ReflectionGameApi.GetRunCurrency(); ReflectionGameApi.SetRunCurrency(runCurrency + rewardCashK); ReflectionGameApi.FetchCurrencyUI(); ReflectionGameApi.ShowShopIncrease(rewardCashK, 3f); } else { ReflectionGameApi.FetchCurrencyUI(); } SetStateTimer(__instance, 1f); LogDebug("Complete cosmetic currency reward. Mode=" + rewardMode.Value.ToString() + " Rarity=" + rarityKey.ToString() + " AmountK=" + rewardCashK); } float stateTimer = GetStateTimer(__instance); stateTimer -= Time.deltaTime; SetStateTimer(__instance, stateTimer); if (stateTimer <= 0f) { InvokeUpdateState(__instance, rewardCurrencyOutroState); } return false; } catch (Exception ex) { LogError("Failure: Cosmetic complete currency patch failed\n" + ex); return true; } } private static void LogReflectionErrorOnce() { if (!reflectionErrorLogged) { reflectionErrorLogged = true; LogError("Failure: CosmeticShopMachine reflection target not found. Vanilla currency reward will be used."); } } private static bool GetStateImpulse(object instance) { if (!(stateImpulseField.GetValue(instance) is bool result)) { return false; } return result; } private static void SetStateImpulse(object instance, bool value) { stateImpulseField.SetValue(instance, value); } private static float GetStateTimer(object instance) { if (!(stateTimerField.GetValue(instance) is float result)) { return 0f; } return result; } private static void SetStateTimer(object instance, float value) { stateTimerField.SetValue(instance, value); } private static int GetInteractingReward(object instance) { if (!(interactingRewardField.GetValue(instance) is int result)) { return -1; } return result; } private static object GetInteractingRarity(object instance) { return interactingRarityField.GetValue(instance); } private static void SetScreenCurrencyParticlesActive(object instance, bool active) { if (!(screenCurrencyParticlesField == null)) { object value = screenCurrencyParticlesField.GetValue(instance); GameObject val = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val != (Object)null) { val.SetActive(active); } } } private static void InvokeAnimatorCurrencyReward(object instance) { if (animatorField == null) { return; } object value = animatorField.GetValue(instance); if (value != null) { MethodInfo methodInfo = AccessTools.Method(value.GetType(), "EventScreenCurrencyReward", (Type[])null, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(value, null); } } } private static void InvokeRewardSet(object instance) { rewardSetMethod.Invoke(instance, null); } private static void InvokeUpdateState(object instance, object state) { updateStateMethod.Invoke(instance, new object[1] { state }); } } private static class ReflectionGameApi { private static Type semiFuncType; private static MethodInfo isMasterClientOrSingleplayerMethod; private static MethodInfo statGetRunCurrencyMethod; private static MethodInfo statSetRunCurrencyMethod; private static Type currencyUiType; private static FieldInfo currencyUiInstanceField; private static MethodInfo currencyUiFetchCurrencyMethod; private static Type shopIncreaseUiType; private static FieldInfo shopIncreaseUiInstanceField; private static MethodInfo shopIncreaseUiShowIncreaseMethod; private static bool initialized; private static void Initialize() { if (!initialized) { initialized = true; semiFuncType = AccessTools.TypeByName("SemiFunc"); if (semiFuncType != null) { isMasterClientOrSingleplayerMethod = AccessTools.Method(semiFuncType, "IsMasterClientOrSingleplayer", (Type[])null, (Type[])null); statGetRunCurrencyMethod = AccessTools.Method(semiFuncType, "StatGetRunCurrency", (Type[])null, (Type[])null); statSetRunCurrencyMethod = AccessTools.Method(semiFuncType, "StatSetRunCurrency", new Type[1] { typeof(int) }, (Type[])null); } currencyUiType = AccessTools.TypeByName("CurrencyUI"); if (currencyUiType != null) { currencyUiInstanceField = AccessTools.Field(currencyUiType, "instance"); currencyUiFetchCurrencyMethod = AccessTools.Method(currencyUiType, "FetchCurrency", (Type[])null, (Type[])null); } shopIncreaseUiType = AccessTools.TypeByName("ShopIncreaseUI"); if (shopIncreaseUiType != null) { shopIncreaseUiInstanceField = AccessTools.Field(shopIncreaseUiType, "instance"); shopIncreaseUiShowIncreaseMethod = AccessTools.Method(shopIncreaseUiType, "ShowIncrease", new Type[2] { typeof(int), typeof(float) }, (Type[])null); } } } public static bool IsMasterClientOrSingleplayer() { Initialize(); if (isMasterClientOrSingleplayerMethod == null) { return false; } if (!(isMasterClientOrSingleplayerMethod.Invoke(null, null) is bool result)) { return false; } return result; } public static int GetRunCurrency() { Initialize(); if (statGetRunCurrencyMethod == null) { return 0; } if (!(statGetRunCurrencyMethod.Invoke(null, null) is int result)) { return 0; } return result; } public static void SetRunCurrency(int value) { Initialize(); if (statSetRunCurrencyMethod != null) { statSetRunCurrencyMethod.Invoke(null, new object[1] { value }); } } public static void FetchCurrencyUI() { Initialize(); if (!(currencyUiInstanceField == null) && !(currencyUiFetchCurrencyMethod == null)) { object value = currencyUiInstanceField.GetValue(null); if (value != null) { currencyUiFetchCurrencyMethod.Invoke(value, null); } } } public static void ShowShopIncrease(int amountK, float duration) { Initialize(); if (!(shopIncreaseUiInstanceField == null) && !(shopIncreaseUiShowIncreaseMethod == null)) { object value = shopIncreaseUiInstanceField.GetValue(null); if (value != null) { shopIncreaseUiShowIncreaseMethod.Invoke(value, new object[2] { amountK, duration }); } } } } public const string PluginGuid = "REPOJP.CosmeticCompleteCashConfig"; public const string PluginName = "CosmeticCompleteCashConfig"; public const string PluginVersion = "4.0.0"; private static ManualLogSource logger; private Harmony harmony; private static ConfigEntry<bool> enable; private static ConfigEntry<bool> showDebugLog; private static ConfigEntry<RewardMode> rewardMode; private static ConfigEntry<int> commonCash; private static ConfigEntry<int> uncommonCash; private static ConfigEntry<int> rareCash; private static ConfigEntry<int> ultraRareCash; private static ConfigEntry<int> commonMinCash; private static ConfigEntry<int> commonMaxCash; private static ConfigEntry<int> uncommonMinCash; private static ConfigEntry<int> uncommonMaxCash; private static ConfigEntry<int> rareMinCash; private static ConfigEntry<int> rareMaxCash; private static ConfigEntry<int> ultraRareMinCash; private static ConfigEntry<int> ultraRareMaxCash; private static ConfigEntry<float> commonMultiplier; private static ConfigEntry<float> uncommonMultiplier; private static ConfigEntry<float> rareMultiplier; private static ConfigEntry<float> ultraRareMultiplier; private void Awake() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown try { ((Component)this).transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); logger = ((BaseUnityPlugin)this).Logger; BindConfig(); harmony = new Harmony("REPOJP.CosmeticCompleteCashConfig"); harmony.PatchAll(); logger.LogInfo((object)"CosmeticCompleteCashConfig v4.0.0 loaded."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failure: Failed to load CosmeticCompleteCashConfig\n" + ex)); } } private void OnDestroy() { try { if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failure: Failed to unload CosmeticCompleteCashConfig\n" + ex)); } } private void BindConfig() { enable = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable", true, "Enable this mod.このMODを有効化"); showDebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowDebugLog", false, "Show debug logs.デバッグログを表示"); rewardMode = ((BaseUnityPlugin)this).Config.Bind<RewardMode>("Mode", "RewardMode", RewardMode.Fixed, "Currency reward mode after all cosmetics are owned.全コスメ取得後の通貨変換モード"); commonCash = ((BaseUnityPlugin)this).Config.Bind<int>("Fixed", "CommonCash", 2000, "Common complete duplicate cash reward.コモン全取得後重複報酬額"); uncommonCash = ((BaseUnityPlugin)this).Config.Bind<int>("Fixed", "UncommonCash", 4000, "Uncommon complete duplicate cash reward.アンコモン全取得後重複報酬額"); rareCash = ((BaseUnityPlugin)this).Config.Bind<int>("Fixed", "RareCash", 8000, "Rare complete duplicate cash reward.レア全取得後重複報酬額"); ultraRareCash = ((BaseUnityPlugin)this).Config.Bind<int>("Fixed", "UltraRareCash", 15000, "Ultra Rare complete duplicate cash reward.ウルトラレア全取得後重複報酬額"); commonMinCash = ((BaseUnityPlugin)this).Config.Bind<int>("RandomRange", "CommonMinCash", 0, "Common minimum complete duplicate cash reward.コモン全取得後最小重複報酬額"); commonMaxCash = ((BaseUnityPlugin)this).Config.Bind<int>("RandomRange", "CommonMaxCash", 2000, "Common maximum complete duplicate cash reward.コモン全取得後最大重複報酬額"); uncommonMinCash = ((BaseUnityPlugin)this).Config.Bind<int>("RandomRange", "UncommonMinCash", 1000, "Uncommon minimum complete duplicate cash reward.アンコモン全取得後最小重複報酬額"); uncommonMaxCash = ((BaseUnityPlugin)this).Config.Bind<int>("RandomRange", "UncommonMaxCash", 4000, "Uncommon maximum complete duplicate cash reward.アンコモン全取得後最大重複報酬額"); rareMinCash = ((BaseUnityPlugin)this).Config.Bind<int>("RandomRange", "RareMinCash", 2000, "Rare minimum complete duplicate cash reward.レア全取得後最小重複報酬額"); rareMaxCash = ((BaseUnityPlugin)this).Config.Bind<int>("RandomRange", "RareMaxCash", 8000, "Rare maximum complete duplicate cash reward.レア全取得後最大重複報酬額"); ultraRareMinCash = ((BaseUnityPlugin)this).Config.Bind<int>("RandomRange", "UltraRareMinCash", 4000, "Ultra Rare minimum complete duplicate cash reward.ウルトラレア全取得後最小重複報酬額"); ultraRareMaxCash = ((BaseUnityPlugin)this).Config.Bind<int>("RandomRange", "UltraRareMaxCash", 20000, "Ultra Rare maximum complete duplicate cash reward.ウルトラレア全取得後最大重複報酬額"); commonMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Multiplier", "CommonMultiplier", 0.8f, "Common complete duplicate cash multiplier.コモン全取得後重複報酬倍率"); uncommonMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Multiplier", "UncommonMultiplier", 0.8f, "Uncommon complete duplicate cash multiplier.アンコモン全取得後重複報酬倍率"); rareMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Multiplier", "RareMultiplier", 0.8f, "Rare complete duplicate cash multiplier.レア全取得後重複報酬倍率"); ultraRareMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Multiplier", "UltraRareMultiplier", 1.5f, "Ultra Rare complete duplicate cash multiplier.ウルトラレア全取得後重複報酬倍率"); } private static bool IsEnabled() { return enable != null && enable.Value; } private static void LogDebug(string message) { if (showDebugLog != null && showDebugLog.Value && logger != null) { logger.LogInfo((object)message); } } private static void LogError(string message) { if (logger != null) { logger.LogError((object)message); } } private static int GetRewardCashK(RarityKey rarity) { if (rewardMode.Value == RewardMode.Disabled) { return 0; } return CashToInternalCurrency(rewardMode.Value switch { RewardMode.RandomRange => GetRandomRangeCash(rarity), RewardMode.Multiplier => GetMultiplierCash(rarity), _ => GetFixedCash(rarity), }); } private static int GetFixedCash(RarityKey rarity) { return rarity switch { RarityKey.Common => Mathf.Max(0, commonCash.Value), RarityKey.Uncommon => Mathf.Max(0, uncommonCash.Value), RarityKey.Rare => Mathf.Max(0, rareCash.Value), RarityKey.UltraRare => Mathf.Max(0, ultraRareCash.Value), _ => 0, }; } private static int GetRandomRangeCash(RarityKey rarity) { GetRangeCash(rarity, out var minCash, out var maxCash); minCash = Mathf.Max(0, minCash); maxCash = Mathf.Max(0, maxCash); if (minCash > maxCash) { int num = minCash; minCash = maxCash; maxCash = num; LogDebug("RandomRange swapped. Rarity=" + rarity.ToString() + " Min=" + minCash + " Max=" + maxCash); } if (minCash == maxCash) { return minCash; } if (maxCash == int.MaxValue) { return Random.Range(minCash, maxCash); } return Random.Range(minCash, maxCash + 1); } private static void GetRangeCash(RarityKey rarity, out int minCash, out int maxCash) { switch (rarity) { case RarityKey.Common: minCash = commonMinCash.Value; maxCash = commonMaxCash.Value; break; case RarityKey.Uncommon: minCash = uncommonMinCash.Value; maxCash = uncommonMaxCash.Value; break; case RarityKey.Rare: minCash = rareMinCash.Value; maxCash = rareMaxCash.Value; break; case RarityKey.UltraRare: minCash = ultraRareMinCash.Value; maxCash = ultraRareMaxCash.Value; break; default: minCash = 0; maxCash = 0; break; } } private static int GetMultiplierCash(RarityKey rarity) { int vanillaCash = GetVanillaCash(rarity); float multiplier = GetMultiplier(rarity); multiplier = Mathf.Max(0f, multiplier); return Mathf.Max(0, Mathf.RoundToInt((float)vanillaCash * multiplier)); } private static float GetMultiplier(RarityKey rarity) { return rarity switch { RarityKey.Common => commonMultiplier.Value, RarityKey.Uncommon => uncommonMultiplier.Value, RarityKey.Rare => rareMultiplier.Value, RarityKey.UltraRare => ultraRareMultiplier.Value, _ => 0f, }; } private static int GetVanillaCash(RarityKey rarity) { return rarity switch { RarityKey.Common => 2000, RarityKey.Uncommon => 4000, RarityKey.Rare => 8000, RarityKey.UltraRare => 15000, _ => 0, }; } private static int CashToInternalCurrency(int cash) { cash = Mathf.Max(0, cash); if (cash <= 0) { return 0; } return Mathf.Max(0, Mathf.RoundToInt((float)cash / 1000f)); } private static RarityKey GetRarityKey(object rarityValue) { if (rarityValue == null) { return RarityKey.Unknown; } string a = rarityValue.ToString(); if (string.Equals(a, "Common", StringComparison.OrdinalIgnoreCase)) { return RarityKey.Common; } if (string.Equals(a, "Uncommon", StringComparison.OrdinalIgnoreCase)) { return RarityKey.Uncommon; } if (string.Equals(a, "Rare", StringComparison.OrdinalIgnoreCase)) { return RarityKey.Rare; } if (string.Equals(a, "UltraRare", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "Ultra Rare", StringComparison.OrdinalIgnoreCase)) { return RarityKey.UltraRare; } return RarityKey.Unknown; } } }