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 ExtractionGoalEscalation v1.0.1
ExtractionGoalEscalation.dll
Decompiled 2 months 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 HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; using UnityEngine.SceneManagement; [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("zabu")] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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.ExtractionGoalEscalation { [BepInPlugin("REPOJP.ExtractionGoalEscalation", "ExtractionGoalEscalation", "1.0.0")] public sealed class ExtractionGoalEscalationPlugin : BaseUnityPlugin { public const string PluginGuid = "REPOJP.ExtractionGoalEscalation"; public const string PluginName = "ExtractionGoalEscalation"; public const string PluginVersion = "1.0.0"; internal static ExtractionGoalEscalationPlugin Instance; private ConfigEntry<bool> enableMod; private ConfigEntry<int> startDelayMinutes; private ConfigEntry<int> increaseIntervalSeconds; private ConfigEntry<float> increaseAmountK; private ConfigEntry<int> maximumGoalK; private ConfigEntry<bool> stopWhenGoalMet; private ConfigEntry<bool> logGoalIncrease; private ConfigEntry<bool> enableDebugLog; private Harmony harmony; private object trackedExtractionPoint; private object suspendedExtractionPoint; private float trackingStartTime; private float nextIncreaseTime; private int baseGoal; private int increaseCount; private Type roundDirectorType; private Type semiFuncType; private Type runManagerType; private MethodInfo semiFuncIsMasterClientOrSingleplayerMethod; private MethodInfo semiFuncRunIsShopMethod; private MethodInfo semiFuncShopIsOpenMethod; private MethodInfo semiFuncLevelIsShopMethod; private MethodInfo semiFuncSceneIsShopMethod; private FieldInfo roundDirectorInstanceField; private FieldInfo roundDirectorExtractionPointCurrentField; private FieldInfo roundDirectorExtractionHaulGoalField; private FieldInfo roundDirectorCurrentHaulField; private FieldInfo runManagerInstanceField; private FieldInfo runManagerLevelCurrentField; private FieldInfo extractionPointHaulGoalField; private MethodInfo extractionPointHaulGoalSetMethod; private MethodInfo extractionPointHaulGoalSetRpcMethod; private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown Instance = this; InitializeConfig(); CacheTypes(); CacheReflectionMembers(); harmony = new Harmony("REPOJP.ExtractionGoalEscalation"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"ExtractionGoalEscalation 1.0.0 loaded"); } private void OnDestroy() { if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { if (!enableMod.Value) { ResetTracking(clearSuspended: false); return; } if (!IsHost()) { ResetTracking(clearSuspended: false); return; } if (IsInShop()) { ResetTracking(clearSuspended: false); return; } object currentExtractionPoint = GetCurrentExtractionPoint(); if (!IsAliveUnityObject(currentExtractionPoint)) { ResetTracking(clearSuspended: true); return; } int currentExtractionGoal = GetCurrentExtractionGoal(currentExtractionPoint); int currentHaul = GetCurrentHaul(); if (stopWhenGoalMet.Value && currentExtractionGoal > 0 && currentHaul >= currentExtractionGoal) { suspendedExtractionPoint = currentExtractionPoint; if (trackedExtractionPoint == currentExtractionPoint) { DebugLog("Tracking suspended because current haul already met current goal"); } ResetTracking(clearSuspended: false); return; } if (suspendedExtractionPoint != null && suspendedExtractionPoint != currentExtractionPoint) { suspendedExtractionPoint = null; } if (suspendedExtractionPoint == null || suspendedExtractionPoint != currentExtractionPoint) { if (trackedExtractionPoint != currentExtractionPoint) { BeginTracking(currentExtractionPoint); } else if (!(Time.time < nextIncreaseTime)) { ApplyEscalation(currentExtractionPoint); } } } private void InitializeConfig() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown enableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "EnableMod", true, "Enable or disable this mod.このMODの有効無効"); startDelayMinutes = ((BaseUnityPlugin)this).Config.Bind<int>("B Escalation", "StartDelayMinutes", 5, new ConfigDescription("Minutes to wait after extraction point appears before escalation starts.納品所出現後に増額開始まで待機する分数", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 30), Array.Empty<object>())); increaseIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("B Escalation", "IncreaseIntervalSeconds", 1, new ConfigDescription("Seconds between each goal increase after the start delay.増額開始後に何秒ごとに必要金額を増やすか", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 300), Array.Empty<object>())); increaseAmountK = ((BaseUnityPlugin)this).Config.Bind<float>("B Escalation", "IncreaseAmountK", 0.01f, new ConfigDescription("Increase amount in k$. 0.01 means +10 each interval.増額量のk$指定 0.01なら毎回+10", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 10f), Array.Empty<object>())); maximumGoalK = ((BaseUnityPlugin)this).Config.Bind<int>("C Safety", "MaximumGoalK", 50, new ConfigDescription("Maximum extraction goal in k$. 50 means 50000.必要金額の上限k$指定 50なら50000", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); stopWhenGoalMet = ((BaseUnityPlugin)this).Config.Bind<bool>("C Safety", "StopWhenGoalMet", true, "Stop escalating when current haul already meets the current goal.現在納品額が現在目標額を満たしたら増額停止"); logGoalIncrease = ((BaseUnityPlugin)this).Config.Bind<bool>("C Safety", "LogGoalIncrease", false, "Log each goal increase.金額が増えるたびにログ出力"); enableDebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Z Debug", "EnableDebugLog", false, "Enable debug logs.デバッグログ出力"); } private void CacheTypes() { roundDirectorType = AccessTools.TypeByName("RoundDirector"); semiFuncType = AccessTools.TypeByName("SemiFunc"); runManagerType = AccessTools.TypeByName("RunManager"); } private void CacheReflectionMembers() { semiFuncIsMasterClientOrSingleplayerMethod = FindStaticBoolMethodSilently(semiFuncType, "IsMasterClientOrSingleplayer"); semiFuncRunIsShopMethod = FindStaticBoolMethodSilently(semiFuncType, "RunIsShop"); semiFuncShopIsOpenMethod = FindStaticBoolMethodSilently(semiFuncType, "ShopIsOpen"); semiFuncLevelIsShopMethod = FindStaticBoolMethodSilently(semiFuncType, "LevelIsShop"); semiFuncSceneIsShopMethod = FindStaticBoolMethodSilently(semiFuncType, "SceneIsShop"); roundDirectorInstanceField = FindFieldSilently(roundDirectorType, "instance"); roundDirectorExtractionPointCurrentField = FindFieldSilently(roundDirectorType, "extractionPointCurrent"); roundDirectorExtractionHaulGoalField = FindFieldSilently(roundDirectorType, "extractionHaulGoal"); roundDirectorCurrentHaulField = FindFieldSilently(roundDirectorType, "currentHaul"); runManagerInstanceField = FindFieldSilently(runManagerType, "instance"); runManagerLevelCurrentField = FindFieldSilently(runManagerType, "levelCurrent"); } private void BeginTracking(object extractionPoint) { int currentExtractionGoal = GetCurrentExtractionGoal(extractionPoint); if (currentExtractionGoal <= 0) { DebugLog("BeginTracking skipped because current goal <= 0"); ResetTracking(clearSuspended: false); return; } CacheExtractionPointMembers(extractionPoint.GetType()); trackedExtractionPoint = extractionPoint; trackingStartTime = Time.time; baseGoal = currentExtractionGoal; increaseCount = 0; nextIncreaseTime = trackingStartTime + GetStartDelaySeconds(); DebugLog($"Start tracking extraction goal escalation | baseGoal={baseGoal} startDelayMinutes={startDelayMinutes.Value} intervalSeconds={increaseIntervalSeconds.Value} increaseK={increaseAmountK.Value:0.00}"); } private void CacheExtractionPointMembers(Type extractionPointRuntimeType) { if (!(extractionPointRuntimeType == null) && (!(extractionPointHaulGoalField != null) || !(extractionPointHaulGoalField.DeclaringType == extractionPointRuntimeType) || !(extractionPointHaulGoalSetMethod != null) || !(extractionPointHaulGoalSetMethod.DeclaringType == extractionPointRuntimeType))) { extractionPointHaulGoalField = FindFieldSilently(extractionPointRuntimeType, "haulGoal"); extractionPointHaulGoalSetMethod = FindMethodSilently(extractionPointRuntimeType, "HaulGoalSet", new Type[1] { typeof(int) }); extractionPointHaulGoalSetRpcMethod = FindMethodSilently(extractionPointRuntimeType, "HaulGoalSetRPC", new Type[1] { typeof(int) }); } } private void ApplyEscalation(object extractionPoint) { if (IsInShop()) { ResetTracking(clearSuspended: false); return; } int currentExtractionGoal = GetCurrentExtractionGoal(extractionPoint); if (currentExtractionGoal <= 0) { DebugLog("ApplyEscalation skipped because current goal <= 0"); ResetTracking(clearSuspended: false); return; } increaseCount++; int increaseAmountValue = GetIncreaseAmountValue(); int num; try { num = checked(baseGoal + increaseCount * increaseAmountValue); } catch (OverflowException) { num = int.MaxValue; } int maximumGoalValue = GetMaximumGoalValue(); if (num > maximumGoalValue) { num = maximumGoalValue; } if (num <= currentExtractionGoal) { nextIncreaseTime = Time.time + GetIncreaseIntervalSeconds(); DebugLog($"ApplyEscalation skipped because newGoal <= currentGoal | current={currentExtractionGoal} new={num}"); return; } if (!SetExtractionGoal(extractionPoint, num)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Failed to set extraction goal to {num}"); nextIncreaseTime = Time.time + GetIncreaseIntervalSeconds(); return; } nextIncreaseTime = Time.time + GetIncreaseIntervalSeconds(); if (logGoalIncrease.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Extraction goal escalated | count={increaseCount} baseGoal={baseGoal} currentGoal={currentExtractionGoal} newGoal={num} elapsed={Time.time - trackingStartTime:0.00}s"); } if (stopWhenGoalMet.Value) { int currentHaul = GetCurrentHaul(); if (currentHaul >= num) { suspendedExtractionPoint = extractionPoint; ResetTracking(clearSuspended: false); DebugLog("Tracking suspended immediately after escalation because current haul already met new goal"); } } } private void ResetTracking(bool clearSuspended) { trackedExtractionPoint = null; trackingStartTime = 0f; nextIncreaseTime = 0f; baseGoal = 0; increaseCount = 0; if (clearSuspended) { suspendedExtractionPoint = null; } } private bool IsHost() { try { if (semiFuncIsMasterClientOrSingleplayerMethod != null) { object obj = semiFuncIsMasterClientOrSingleplayerMethod.Invoke(null, null); if (obj is bool) { bool result = (bool)obj; if (true) { return result; } } } } catch (Exception arg) { DebugLog($"IsHost SemiFunc fallback | {arg}"); } try { return PhotonNetwork.IsMasterClient || PhotonNetwork.OfflineMode; } catch { return false; } } private bool IsInShop() { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) try { if (InvokeStaticBoolIfExists(semiFuncRunIsShopMethod)) { return true; } if (InvokeStaticBoolIfExists(semiFuncShopIsOpenMethod)) { return true; } if (InvokeStaticBoolIfExists(semiFuncLevelIsShopMethod)) { return true; } if (InvokeStaticBoolIfExists(semiFuncSceneIsShopMethod)) { return true; } } catch (Exception arg) { DebugLog($"IsInShop SemiFunc fallback | {arg}"); } try { Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (!string.IsNullOrWhiteSpace(name) && name.IndexOf("shop", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } catch (Exception arg2) { DebugLog($"IsInShop SceneManager fallback | {arg2}"); } try { object runManagerInstance = GetRunManagerInstance(); if (runManagerInstance != null && runManagerLevelCurrentField != null) { object value = runManagerLevelCurrentField.GetValue(runManagerInstance); Object val = (Object)((value is Object) ? value : null); if (val != null && val != (Object)null) { string name2 = val.name; if (!string.IsNullOrWhiteSpace(name2) && name2.IndexOf("shop", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } } } catch (Exception arg3) { DebugLog($"IsInShop RunManager fallback | {arg3}"); } return false; } private object GetCurrentExtractionPoint() { object roundDirectorInstance = GetRoundDirectorInstance(); if (roundDirectorInstance == null || roundDirectorExtractionPointCurrentField == null) { return null; } return roundDirectorExtractionPointCurrentField.GetValue(roundDirectorInstance); } private int GetCurrentExtractionGoal(object extractionPoint) { if (extractionPoint != null) { CacheExtractionPointMembers(extractionPoint.GetType()); } if (extractionPoint != null && extractionPointHaulGoalField != null) { object value = extractionPointHaulGoalField.GetValue(extractionPoint); return ConvertToInt(value); } object roundDirectorInstance = GetRoundDirectorInstance(); if (roundDirectorInstance != null && roundDirectorExtractionHaulGoalField != null) { object value2 = roundDirectorExtractionHaulGoalField.GetValue(roundDirectorInstance); return ConvertToInt(value2); } return 0; } private int GetCurrentHaul() { object roundDirectorInstance = GetRoundDirectorInstance(); if (roundDirectorInstance == null || roundDirectorCurrentHaulField == null) { return 0; } object value = roundDirectorCurrentHaulField.GetValue(roundDirectorInstance); return ConvertToInt(value); } private bool SetExtractionGoal(object extractionPoint, int newGoal) { try { CacheExtractionPointMembers(extractionPoint.GetType()); if (extractionPointHaulGoalSetMethod != null) { extractionPointHaulGoalSetMethod.Invoke(extractionPoint, new object[1] { newGoal }); return true; } if (extractionPointHaulGoalSetRpcMethod != null) { extractionPointHaulGoalSetRpcMethod.Invoke(extractionPoint, new object[1] { newGoal }); return true; } bool flag = false; if (extractionPointHaulGoalField != null) { extractionPointHaulGoalField.SetValue(extractionPoint, newGoal); flag = true; } object roundDirectorInstance = GetRoundDirectorInstance(); bool flag2 = false; if (roundDirectorInstance != null && roundDirectorExtractionHaulGoalField != null) { roundDirectorExtractionHaulGoalField.SetValue(roundDirectorInstance, newGoal); flag2 = true; } return flag || flag2; } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"SetExtractionGoal failed | newGoal={newGoal} | {arg}"); return false; } } private object GetRoundDirectorInstance() { if (roundDirectorInstanceField == null) { return null; } return roundDirectorInstanceField.GetValue(null); } private object GetRunManagerInstance() { if (runManagerInstanceField == null) { return null; } return runManagerInstanceField.GetValue(null); } private float GetStartDelaySeconds() { return (float)startDelayMinutes.Value * 60f; } private float GetIncreaseIntervalSeconds() { return Mathf.Max(1f, (float)increaseIntervalSeconds.Value); } private int GetIncreaseAmountValue() { return Mathf.Max(1, Mathf.RoundToInt(increaseAmountK.Value * 1000f)); } private int GetMaximumGoalValue() { return Mathf.Max(1, maximumGoalK.Value) * 1000; } private static MethodInfo FindStaticBoolMethodSilently(Type type, string methodName) { if (type == null || string.IsNullOrWhiteSpace(methodName)) { return null; } MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method != null && method.ReturnType == typeof(bool)) { return method; } return null; } private static MethodInfo FindMethodSilently(Type type, string methodName, Type[] parameterTypes) { if (type == null || string.IsNullOrWhiteSpace(methodName)) { return null; } return type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes ?? Type.EmptyTypes, null); } private static FieldInfo FindFieldSilently(Type type, string fieldName) { if (type == null || string.IsNullOrWhiteSpace(fieldName)) { return null; } return type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } private static bool InvokeStaticBoolIfExists(MethodInfo method) { if (method == null) { return false; } object obj = method.Invoke(null, null); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static int ConvertToInt(object value) { if (value == null) { return 0; } try { return Convert.ToInt32(value); } catch { return 0; } } private static bool IsAliveUnityObject(object target) { if (target == null) { return false; } Object val = (Object)((target is Object) ? target : null); if (val != null) { return val != (Object)null; } return true; } private void DebugLog(string message) { if (enableDebugLog.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[Debug] " + message)); } } } }