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