Decompiled source of Simple EnemyScaler v1.0.0

Simple_EnemyScaler.dll

Decompiled 17 hours ago
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("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.Simple_EnemyScaler
{
	[BepInPlugin("REPOJP.Simple_EnemyScaler", "Simple_EnemyScaler", "1.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 = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<float> EnemyCountMultiplier;

		private void Awake()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			EnemyCountMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "EnemyCountMultiplier", 1.5f, new ConfigDescription("Default enemy count multiplier applied by host only. ホストのみで適用する敵数倍率", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			new Harmony("REPOJP.Simple_EnemyScaler").PatchAll();
			Log.LogInfo((object)$"EnemyCountMultiplier={EnemyCountMultiplier.Value:0.###}");
		}
	}
	[HarmonyPatch(typeof(EnemyDirector), "AmountSetup")]
	internal static class Patch_EnemyDirector_AmountSetup
	{
		private static readonly FieldRef<EnemyDirector, int> AmountCurve1ValueRef = AccessTools.FieldRefAccess<EnemyDirector, int>("amountCurve1Value");

		private static readonly FieldRef<EnemyDirector, int> AmountCurve2ValueRef = AccessTools.FieldRefAccess<EnemyDirector, int>("amountCurve2Value");

		private static readonly FieldRef<EnemyDirector, int> AmountCurve3ValueRef = AccessTools.FieldRefAccess<EnemyDirector, int>("amountCurve3Value");

		private static readonly FieldRef<EnemyDirector, int> TotalAmountRef = AccessTools.FieldRefAccess<EnemyDirector, int>("totalAmount");

		private static readonly FieldRef<EnemyDirector, List<EnemySetup>> EnemyListRef = AccessTools.FieldRefAccess<EnemyDirector, List<EnemySetup>>("enemyList");

		private static readonly FieldRef<EnemyDirector, List<EnemySetup>> EnemyListCurrentRef = AccessTools.FieldRefAccess<EnemyDirector, List<EnemySetup>>("enemyListCurrent");

		private static readonly FieldRef<EnemyDirector, int> EnemyListIndexRef = AccessTools.FieldRefAccess<EnemyDirector, int>("enemyListIndex");

		private static readonly MethodInfo PickEnemiesMethod = AccessTools.Method(typeof(EnemyDirector), "PickEnemies", (Type[])null, (Type[])null);

		private static void Postfix(EnemyDirector __instance)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || (Object)(object)__instance == (Object)null)
			{
				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 || PickEnemiesMethod == null || __instance.enemiesDifficulty1 == null || __instance.enemiesDifficulty2 == null || __instance.enemiesDifficulty3 == null)
			{
				return;
			}
			ref int reference = ref AmountCurve1ValueRef.Invoke(__instance);
			ref int reference2 = ref AmountCurve2ValueRef.Invoke(__instance);
			ref int reference3 = ref AmountCurve3ValueRef.Invoke(__instance);
			ref int reference4 = ref TotalAmountRef.Invoke(__instance);
			int num2 = Mathf.Max(0, reference);
			int num3 = Mathf.Max(0, reference2);
			int num4 = Mathf.Max(0, reference3);
			int num5 = Mathf.Max(0, reference4);
			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);
			if (targetTotal == num5 && target == num2 && target2 == num3 && target3 == num4)
			{
				return;
			}
			List<EnemySetup> list = EnemyListRef.Invoke(__instance);
			List<EnemySetup> list2 = EnemyListCurrentRef.Invoke(__instance);
			if (list != null && list2 != null)
			{
				list.Clear();
				list2.Clear();
				EnemyListIndexRef.Invoke(__instance) = 0;
				object[] array = new object[1] { __instance.enemiesDifficulty3 };
				for (int i = 0; i < target3; i++)
				{
					PickEnemiesMethod.Invoke(__instance, array);
				}
				array[0] = __instance.enemiesDifficulty2;
				for (int j = 0; j < target2; j++)
				{
					PickEnemiesMethod.Invoke(__instance, array);
				}
				array[0] = __instance.enemiesDifficulty1;
				for (int k = 0; k < target; k++)
				{
					PickEnemiesMethod.Invoke(__instance, array);
				}
				reference = target;
				reference2 = target2;
				reference3 = target3;
				reference4 = targetTotal;
				Simple_EnemyScalerPlugin.Log.LogInfo((object)$"EnemyCountMultiplier applied {num5} -> {targetTotal} x{num:0.###}");
			}
		}

		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;
			}
			float num = (float)baseTotal * multiplier;
			targetTotal = Mathf.Clamp(Mathf.RoundToInt(num), 0, Mathf.RoundToInt((float)baseTotal * 10f));
			float num2 = (float)base1 * multiplier;
			float num3 = (float)base2 * multiplier;
			float num4 = (float)base3 * multiplier;
			int num5 = Mathf.Max(0, Mathf.FloorToInt(num2));
			int num6 = Mathf.Max(0, Mathf.FloorToInt(num3));
			int num7 = Mathf.Max(0, Mathf.FloorToInt(num4));
			float num8 = Mathf.Max(0f, num2 - (float)num5);
			float num9 = Mathf.Max(0f, num3 - (float)num6);
			float num10 = Mathf.Max(0f, num4 - (float)num7);
			target1 = num5;
			target2 = num6;
			target3 = num7;
			int num11 = target1 + target2 + target3;
			int num12 = targetTotal - num11;
			if (num12 > 0)
			{
				int[] array = new int[3] { 1, 2, 3 };
				float[] frac2 = new float[3] { num8, num9, num10 };
				Array.Sort(array, (int a, int b) => frac2[b - 1].CompareTo(frac2[a - 1]));
				int num13 = 0;
				while (num12 > 0)
				{
					switch (array[num13 % 3])
					{
					case 1:
						target1++;
						break;
					case 2:
						target2++;
						break;
					default:
						target3++;
						break;
					}
					num12--;
					num13++;
				}
			}
			else if (num12 < 0)
			{
				int[] array2 = new int[3] { 1, 2, 3 };
				float[] frac = new float[3] { num8, num9, num10 };
				Array.Sort(array2, (int a, int b) => frac[a - 1].CompareTo(frac[b - 1]));
				int num14 = 0;
				while (num12 < 0 && target1 + target2 + target3 > 0)
				{
					int num15 = array2[num14 % 3];
					if (num15 == 1 && target1 > 0)
					{
						target1--;
						num12++;
					}
					else if (num15 == 2 && target2 > 0)
					{
						target2--;
						num12++;
					}
					else if (num15 == 3 && target3 > 0)
					{
						target3--;
						num12++;
					}
					num14++;
					if (num14 > 100000)
					{
						break;
					}
				}
			}
			target1 = Mathf.Max(0, target1);
			target2 = Mathf.Max(0, target2);
			target3 = Mathf.Max(0, target3);
			int num16 = target1 + target2 + target3;
			if (num16 != targetTotal)
			{
				int num17 = targetTotal - num16;
				target1 = Mathf.Max(0, target1 + num17);
			}
			targetTotal = Mathf.Max(0, target1 + target2 + target3);
		}
	}
}