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 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));
}
}
}
}