using System; using System.Collections.Generic; 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.Simple_EnemyScaler { [BepInPlugin("REPOJP.Simple_EnemyScaler", "Simple_EnemyScaler", "4.0.0")] public sealed class Simple_EnemyScalerPlugin : BaseUnityPlugin { public const string PluginGuid = "REPOJP.Simple_EnemyScaler"; public const string PluginName = "Simple_EnemyScaler"; public const string PluginVersion = "4.0.0"; internal static Simple_EnemyScalerPlugin Instance; internal static ManualLogSource Log; internal static ConfigEntry EnableMod; internal static ConfigEntry EnemyCountMultiplier; internal static ConfigEntry EnableLog; private Harmony _harmony; private void Awake() { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown try { Instance = this; Log = ((BaseUnityPlugin)this).Logger; ((Component)this).transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); EnableMod = ((BaseUnityPlugin)this).Config.Bind("General", "EnableMod", true, "Enable this mod. このMODの有効無効"); EnemyCountMultiplier = ((BaseUnityPlugin)this).Config.Bind("General", "EnemyCountMultiplier", 1.5f, new ConfigDescription("Default enemy count multiplier applied by host only. ホストのみで適用する敵数倍率", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); EnableLog = ((BaseUnityPlugin)this).Config.Bind("General", "EnableLog", true, "Enable log output. ログ出力有効無効"); _harmony = new Harmony("REPOJP.Simple_EnemyScaler"); _harmony.PatchAll(typeof(Simple_EnemyScalerPlugin).Assembly); WriteInfo("Loaded v4.0.0 EnemyCountMultiplier=" + EnemyCountMultiplier.Value.ToString("0.###")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failure: Awake\n" + ex)); throw; } } private void OnDestroy() { try { if (_harmony != null) { _harmony.UnpatchSelf(); _harmony = null; } } catch { } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } internal static bool IsEnabled() { return EnableMod != null && EnableMod.Value; } internal static bool IsHostOrSingle() { try { return SemiFunc.IsMasterClientOrSingleplayer(); } catch { return true; } } internal static void WriteInfo(string message) { if (Log != null && (EnableLog == null || EnableLog.Value)) { Log.LogInfo((object)message); } } internal static void WriteWarning(string message) { if (Log != null && (EnableLog == null || EnableLog.Value)) { Log.LogWarning((object)message); } } internal static void WriteError(string message) { if (Log != null && (EnableLog == null || EnableLog.Value)) { Log.LogError((object)message); } } } [HarmonyPatch(typeof(EnemyDirector), "AmountSetup")] internal static class Patch_EnemyDirector_AmountSetup { private static readonly FieldInfo FiAmountCurve1Value = AccessTools.Field(typeof(EnemyDirector), "amountCurve1Value"); private static readonly FieldInfo FiAmountCurve2Value = AccessTools.Field(typeof(EnemyDirector), "amountCurve2Value"); private static readonly FieldInfo FiAmountCurve3Value = AccessTools.Field(typeof(EnemyDirector), "amountCurve3Value"); private static readonly FieldInfo FiTotalAmount = AccessTools.Field(typeof(EnemyDirector), "totalAmount"); private static readonly FieldInfo FiEnemyList = AccessTools.Field(typeof(EnemyDirector), "enemyList"); private static readonly FieldInfo FiEnemyListCurrent = AccessTools.Field(typeof(EnemyDirector), "enemyListCurrent"); private static readonly FieldInfo FiEnemyListIndex = AccessTools.Field(typeof(EnemyDirector), "enemyListIndex"); private static readonly MethodInfo MiPickEnemies = AccessTools.Method(typeof(EnemyDirector), "PickEnemies", (Type[])null, (Type[])null); private static void Postfix(EnemyDirector __instance) { try { ApplyScaledEnemyCount(__instance); } catch (Exception ex) { Simple_EnemyScalerPlugin.WriteError("Failure: Enemy count scale\n" + ex); } } private static void ApplyScaledEnemyCount(EnemyDirector director) { if (!Simple_EnemyScalerPlugin.IsEnabled() || !Simple_EnemyScalerPlugin.IsHostOrSingle() || (Object)(object)director == (Object)null) { return; } if (FiAmountCurve1Value == null || FiAmountCurve2Value == null || FiAmountCurve3Value == null || FiTotalAmount == null || FiEnemyList == null || FiEnemyListCurrent == null || FiEnemyListIndex == null || MiPickEnemies == null) { Simple_EnemyScalerPlugin.WriteWarning("Required EnemyDirector reflection target is missing."); return; } if (director.enemiesDifficulty1 == null || director.enemiesDifficulty2 == null || director.enemiesDifficulty3 == null) { Simple_EnemyScalerPlugin.WriteWarning("Enemy difficulty list is missing."); return; } float num = 1f; if (Simple_EnemyScalerPlugin.EnemyCountMultiplier != null) { num = Simple_EnemyScalerPlugin.EnemyCountMultiplier.Value; } num = Mathf.Clamp(num, 0f, 10f); if (Mathf.Abs(num - 1f) < 0.0001f) { return; } int num2 = Mathf.Max(0, GetInt(director, FiAmountCurve1Value)); int num3 = Mathf.Max(0, GetInt(director, FiAmountCurve2Value)); int num4 = Mathf.Max(0, GetInt(director, FiAmountCurve3Value)); int num5 = Mathf.Max(0, GetInt(director, FiTotalAmount)); if (num5 != num2 + num3 + num4) { num5 = num2 + num3 + num4; } CalcScaledCounts(num2, num3, num4, num5, num, out var target, out var target2, out var target3, out var targetTotal); List enemyList = GetEnemyList(director, FiEnemyList); List enemyList2 = GetEnemyList(director, FiEnemyListCurrent); if (enemyList == null || enemyList2 == null) { Simple_EnemyScalerPlugin.WriteWarning("EnemyDirector enemy list is missing."); return; } enemyList.Clear(); enemyList2.Clear(); SetInt(director, FiEnemyListIndex, 0); if (targetTotal <= 0) { SetInt(director, FiAmountCurve1Value, 0); SetInt(director, FiAmountCurve2Value, 0); SetInt(director, FiAmountCurve3Value, 0); SetInt(director, FiTotalAmount, 0); Simple_EnemyScalerPlugin.WriteInfo("EnemyCountMultiplier applied " + num5 + " -> 0 x" + num.ToString("0.###")); return; } int num6 = PickEnemiesSafe(director, director.enemiesDifficulty3, target3, enemyList, enemyList2); int num7 = PickEnemiesSafe(director, director.enemiesDifficulty2, target2, enemyList, enemyList2); int num8 = PickEnemiesSafe(director, director.enemiesDifficulty1, target, enemyList, enemyList2); int value = num8 + num7 + num6; SetInt(director, FiAmountCurve1Value, num8); SetInt(director, FiAmountCurve2Value, num7); SetInt(director, FiAmountCurve3Value, num6); SetInt(director, FiTotalAmount, value); SetInt(director, FiEnemyListIndex, 0); Simple_EnemyScalerPlugin.WriteInfo("EnemyCountMultiplier applied " + num5 + " -> " + value + " x" + num.ToString("0.###") + " / D1 " + num2 + "->" + num8 + " / D2 " + num3 + "->" + num7 + " / D3 " + num4 + "->" + num6); } private static int PickEnemiesSafe(EnemyDirector director, List source, int count, List enemyList, List enemyListCurrent) { if ((Object)(object)director == (Object)null || source == null || count <= 0 || enemyList == null || enemyListCurrent == null) { return 0; } int num = 0; object[] parameters = new object[1] { source }; for (int i = 0; i < count; i++) { int count2 = enemyList.Count; int count3 = enemyListCurrent.Count; try { MiPickEnemies.Invoke(director, parameters); } catch (Exception ex) { Simple_EnemyScalerPlugin.WriteWarning("PickEnemies failed.\n" + ex); RemoveAddedRange(enemyList, count2); RemoveAddedRange(enemyListCurrent, count3); continue; } EnemySetup val = null; if (enemyList.Count > count2) { val = enemyList[enemyList.Count - 1]; } if ((Object)(object)val == (Object)null) { RemoveAddedRange(enemyList, count2); RemoveAddedRange(enemyListCurrent, count3); } else { num++; } } return num; } private static void RemoveAddedRange(List list, int originalCount) { if (list != null) { while (list.Count > originalCount) { list.RemoveAt(list.Count - 1); } } } private static int GetInt(object instance, FieldInfo field) { if (instance == null || field == null) { return 0; } try { object value = field.GetValue(instance); if (value is int) { return (int)value; } } catch { } return 0; } private static void SetInt(object instance, FieldInfo field, int value) { if (instance == null || field == null) { return; } try { field.SetValue(instance, value); } catch { } } private static List GetEnemyList(object instance, FieldInfo field) { if (instance == null || field == null) { return null; } try { return field.GetValue(instance) as List; } catch { return null; } } private static void CalcScaledCounts(int base1, int base2, int base3, int baseTotal, float multiplier, out int target1, out int target2, out int target3, out int targetTotal) { target1 = 0; target2 = 0; target3 = 0; targetTotal = 0; if (baseTotal <= 0 || (base1 <= 0 && base2 <= 0 && base3 <= 0)) { return; } targetTotal = Mathf.RoundToInt((float)baseTotal * multiplier); targetTotal = Mathf.Clamp(targetTotal, 0, Mathf.RoundToInt((float)baseTotal * 10f)); float num = (float)base1 * multiplier; float num2 = (float)base2 * multiplier; float num3 = (float)base3 * multiplier; int num4 = Mathf.Max(0, Mathf.FloorToInt(num)); int num5 = Mathf.Max(0, Mathf.FloorToInt(num2)); int num6 = Mathf.Max(0, Mathf.FloorToInt(num3)); float num7 = Mathf.Max(0f, num - (float)num4); float num8 = Mathf.Max(0f, num2 - (float)num5); float num9 = Mathf.Max(0f, num3 - (float)num6); target1 = num4; target2 = num5; target3 = num6; int num10 = targetTotal - (target1 + target2 + target3); if (num10 > 0) { int[] array = new int[3] { 1, 2, 3 }; float[] fractions2 = new float[3] { num7, num8, num9 }; Array.Sort(array, (int a, int b) => fractions2[b - 1].CompareTo(fractions2[a - 1])); int num11 = 0; while (num10 > 0) { switch (array[num11 % 3]) { case 1: target1++; break; case 2: target2++; break; default: target3++; break; } num10--; num11++; } } else if (num10 < 0) { int[] array2 = new int[3] { 1, 2, 3 }; float[] fractions = new float[3] { num7, num8, num9 }; Array.Sort(array2, (int a, int b) => fractions[a - 1].CompareTo(fractions[b - 1])); int num12 = 0; int num13 = 0; while (num10 < 0 && target1 + target2 + target3 > 0 && num13 < 100000) { int num14 = array2[num12 % 3]; if (num14 == 1 && target1 > 0) { target1--; num10++; } else if (num14 == 2 && target2 > 0) { target2--; num10++; } else if (num14 == 3 && target3 > 0) { target3--; num10++; } num12++; num13++; } } target1 = Mathf.Max(0, target1); target2 = Mathf.Max(0, target2); target3 = Mathf.Max(0, target3); targetTotal = Mathf.Max(0, target1 + target2 + target3); } } }