Decompiled source of CosmeticCompleteCashConfig v4.0.0

CosmeticCompleteCashConfig.dll

Decompiled a day ago
using 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;
		}
	}
}