Decompiled source of AskaEnemyScaling v0.1.2

AskaEnemyScaling.Core.dll

Decompiled 2 days ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AskaEnemyScaling.Core")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AskaEnemyScaling.Core")]
[assembly: AssemblyTitle("AskaEnemyScaling.Core")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace AskaEnemyScaling.Core;

[Serializable]
public sealed class ScalingAxis
{
	public float Peak;

	public float Shape;

	public float Overdrive;

	public float Cap;

	public bool IsNoOp
	{
		get
		{
			if (Peak <= 1f)
			{
				return Overdrive <= 0f;
			}
			return false;
		}
	}

	public ScalingAxis()
		: this(1f, 1f, 0f, 1f)
	{
	}

	public ScalingAxis(float peak, float shape, float overdrive, float cap)
	{
		Peak = peak;
		Shape = shape;
		Overdrive = overdrive;
		Cap = cap;
	}

	public float Evaluate(float progress)
	{
		if (float.IsNaN(progress) || progress <= 0f)
		{
			return 1f;
		}
		float num = ((progress < 1f) ? progress : 1f);
		float num2 = ((progress > 1f) ? (progress - 1f) : 0f);
		float num3 = ((Shape > 0f) ? Shape : 1f);
		float num4 = (float)Math.Pow(num, num3);
		float num5 = 1f + (Peak - 1f) * num4 + num2 * Overdrive;
		if (num5 < 1f)
		{
			num5 = 1f;
		}
		float num6 = ((Cap < 1f) ? 1f : Cap);
		if (num5 > num6)
		{
			num5 = num6;
		}
		return num5;
	}

	public ScalingAxis Clone()
	{
		return new ScalingAxis(Peak, Shape, Overdrive, Cap);
	}
}
public readonly struct ProgressionSnapshot
{
	public readonly int DaysPassed;

	public readonly int VillagerCount;

	public ProgressionSnapshot(int daysPassed, int villagerCount)
	{
		DaysPassed = daysPassed;
		VillagerCount = villagerCount;
	}
}
public readonly struct EnemyMultipliers
{
	public readonly float Health;

	public readonly float Damage;

	public readonly float SpawnCount;

	public static readonly EnemyMultipliers None = new EnemyMultipliers(1f, 1f, 1f);

	public bool IsNoOp
	{
		get
		{
			if (Health <= 1f && Damage <= 1f)
			{
				return SpawnCount <= 1f;
			}
			return false;
		}
	}

	public EnemyMultipliers(float health, float damage, float spawnCount)
	{
		Health = health;
		Damage = damage;
		SpawnCount = spawnCount;
	}

	public EnemyMultipliers Dampen(float factor)
	{
		if (factor >= 1f)
		{
			return this;
		}
		if (factor < 0f)
		{
			factor = 0f;
		}
		return new EnemyMultipliers(1f + (Health - 1f) * factor, 1f + (Damage - 1f) * factor, 1f + (SpawnCount - 1f) * factor);
	}

	public override string ToString()
	{
		return $"HP x{Health:0.00}  DMG x{Damage:0.00}  COUNT x{SpawnCount:0.00}";
	}
}
public static class ScalingCalculator
{
	public static float NormaliseDriver(float value, float start, float full)
	{
		float num = full - start;
		if (num <= 0f)
		{
			if (!(value >= start))
			{
				return 0f;
			}
			return 1f;
		}
		float num2 = (value - start) / num;
		if (!(num2 > 0f))
		{
			return 0f;
		}
		return num2;
	}

	public static float ComputeProgress(ScalingProfile profile, ProgressionSnapshot snapshot)
	{
		float num = NormaliseDriver(snapshot.DaysPassed, profile.DayStart, profile.DayFull);
		float num2 = NormaliseDriver(snapshot.VillagerCount, profile.VillagerStart, profile.VillagerFull);
		switch (profile.Combine)
		{
		case CombineMode.DaysOnly:
			return num;
		case CombineMode.VillagersOnly:
			return num2;
		case CombineMode.Average:
			return (num + num2) * 0.5f;
		case CombineMode.Weighted:
		{
			float num3 = profile.DayWeight + profile.VillagerWeight;
			if (num3 <= 0f)
			{
				return 0f;
			}
			return (num * profile.DayWeight + num2 * profile.VillagerWeight) / num3;
		}
		default:
			if (!(num > num2))
			{
				return num2;
			}
			return num;
		}
	}

	public static EnemyMultipliers Compute(ScalingProfile profile, ProgressionSnapshot snapshot)
	{
		if (profile == null || profile.IsNoOp)
		{
			return EnemyMultipliers.None;
		}
		float progress = ComputeProgress(profile, snapshot);
		return new EnemyMultipliers(profile.Health.Evaluate(progress), profile.Damage.Evaluate(progress), profile.SpawnCount.Evaluate(progress));
	}

	public static int ScaleCount(int vanillaCount, float multiplier, int absoluteCeiling = 0)
	{
		if (vanillaCount <= 0 || multiplier <= 1f)
		{
			return vanillaCount;
		}
		int num = (int)Math.Round((double)vanillaCount * (double)multiplier, MidpointRounding.AwayFromZero);
		if (num < vanillaCount)
		{
			num = vanillaCount;
		}
		if (absoluteCeiling > 0 && num > absoluteCeiling)
		{
			num = absoluteCeiling;
		}
		return num;
	}
}
public enum PresetId
{
	Standard,
	RisingTide,
	Ragnarok,
	Custom
}
public static class ScalingPresets
{
	public static ScalingProfile Standard()
	{
		return new ScalingProfile
		{
			Name = "Standard",
			Enabled = false,
			DayStart = 10,
			DayFull = 175,
			VillagerStart = 5,
			VillagerFull = 125,
			Combine = CombineMode.Max,
			Health = new ScalingAxis(1f, 1f, 0f, 1f),
			Damage = new ScalingAxis(1f, 1f, 0f, 1f),
			SpawnCount = new ScalingAxis(1f, 1f, 0f, 1f),
			Categories = EnemyCategories.Default
		};
	}

	public static ScalingProfile RisingTide()
	{
		return new ScalingProfile
		{
			Name = "Rising Tide",
			Enabled = true,
			DayStart = 15,
			DayFull = 180,
			VillagerStart = 8,
			VillagerFull = 120,
			Combine = CombineMode.Max,
			Health = new ScalingAxis(2f, 1.3f, 0.35f, 3.5f),
			Damage = new ScalingAxis(1.5f, 1.3f, 0.2f, 2.25f),
			SpawnCount = new ScalingAxis(1.35f, 1.2f, 0.15f, 2f),
			BossDampening = 0.5f,
			ConcurrentEnemyCeiling = 1.4f,
			Categories = EnemyCategories.Default
		};
	}

	public static ScalingProfile Ragnarok()
	{
		return new ScalingProfile
		{
			Name = "Ragnarok",
			Enabled = true,
			DayStart = 10,
			DayFull = 175,
			VillagerStart = 5,
			VillagerFull = 125,
			Combine = CombineMode.Max,
			Health = new ScalingAxis(4f, 1.15f, 1.2f, 9f),
			Damage = new ScalingAxis(2.5f, 1.15f, 0.55f, 5f),
			SpawnCount = new ScalingAxis(2f, 1.1f, 0.45f, 3.5f),
			BossDampening = 0.5f,
			ConcurrentEnemyCeiling = 1.6f,
			Categories = EnemyCategories.Default
		};
	}

	public static ScalingProfile Get(PresetId id)
	{
		return id switch
		{
			PresetId.RisingTide => RisingTide(), 
			PresetId.Ragnarok => Ragnarok(), 
			_ => Standard(), 
		};
	}
}
public enum CombineMode
{
	Max,
	Average,
	Weighted,
	DaysOnly,
	VillagersOnly
}
[Flags]
public enum EnemyCategories
{
	None = 0,
	Invasion = 1,
	Roaming = 2,
	CaveAndDen = 4,
	Bosses = 8,
	Wildlife = 0x10,
	Default = 0xF
}
[Serializable]
public sealed class ScalingProfile
{
	public string Name = "Custom";

	public int DayStart = 10;

	public int DayFull = 175;

	public int VillagerStart = 5;

	public int VillagerFull = 125;

	public CombineMode Combine;

	public float DayWeight = 0.5f;

	public float VillagerWeight = 0.5f;

	public ScalingAxis Health = new ScalingAxis();

	public ScalingAxis Damage = new ScalingAxis();

	public ScalingAxis SpawnCount = new ScalingAxis();

	public float BossDampening = 0.5f;

	public float ConcurrentEnemyCeiling = 1.6f;

	public EnemyCategories Categories = EnemyCategories.Default;

	public bool Enabled = true;

	public bool IsNoOp
	{
		get
		{
			if (Enabled)
			{
				if (Health.IsNoOp && Damage.IsNoOp)
				{
					return SpawnCount.IsNoOp;
				}
				return false;
			}
			return true;
		}
	}

	public bool Affects(EnemyCategories category)
	{
		return (Categories & category) != 0;
	}

	public ScalingProfile Clone()
	{
		return new ScalingProfile
		{
			Name = Name,
			DayStart = DayStart,
			DayFull = DayFull,
			VillagerStart = VillagerStart,
			VillagerFull = VillagerFull,
			Combine = Combine,
			DayWeight = DayWeight,
			VillagerWeight = VillagerWeight,
			Health = Health.Clone(),
			Damage = Damage.Clone(),
			SpawnCount = SpawnCount.Clone(),
			BossDampening = BossDampening,
			ConcurrentEnemyCeiling = ConcurrentEnemyCeiling,
			Categories = Categories,
			Enabled = Enabled
		};
	}
}

AskaEnemyScaling.dll

Decompiled 2 days ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using AskaEnemyScaling.Config;
using AskaEnemyScaling.Core;
using AskaEnemyScaling.Runtime;
using AskaEnemyScaling.UI;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using SSSGame;
using SSSGame.Combat;
using SSSGame.Weather;
using SandSailorStudio.Attributes;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("AskaEnemyScaling")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AskaEnemyScaling")]
[assembly: AssemblyTitle("AskaEnemyScaling")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 AskaEnemyScaling
{
	[BepInPlugin("aska.enemy.scaling", "ASKA Enemy Scaling", "0.1.2")]
	public sealed class Plugin : BasePlugin
	{
		public const string PluginGuid = "aska.enemy.scaling";

		public const string PluginName = "ASKA Enemy Scaling";

		public const string PluginVersion = "0.1.2";

		private Harmony _harmony;

		internal static ManualLogSource Log { get; private set; }

		internal static ModSettings Settings { get; private set; }

		public override void Load()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			Log = ((BasePlugin)this).Log;
			Settings = new ModSettings(((BasePlugin)this).Config);
			ScalingState.SetProfile(Settings.BuildProfile());
			Settings.Preset.SettingChanged += OnSettingChanged;
			InstallPatches();
			CreatePanelHost();
			ManualLogSource log = Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(10, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("ASKA Enemy Scaling");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("0.1.2");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded. ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ScalingState.DescribeCurrent());
			}
			log.LogInfo(val);
		}

		public override bool Unload()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Settings.Preset.SettingChanged -= OnSettingChanged;
			return true;
		}

		private void InstallPatches()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			try
			{
				_harmony = new Harmony("aska.enemy.scaling");
				_harmony.PatchAll();
				Log.LogInfo((object)"Harmony patches installed.");
			}
			catch (Exception value)
			{
				Log.LogError((object)("Failed to install Harmony patches - enemy scaling will not apply. This usually means ASKA updated and the mod's interop assemblies " + $"need regenerating. Details: {value}"));
			}
		}

		private void CreatePanelHost()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ClassInjector.RegisterTypeInIl2Cpp<ScalingPanel>();
				GameObject val = new GameObject("AskaEnemyScaling.PanelHost");
				Object.DontDestroyOnLoad((Object)val);
				((Object)val).hideFlags = (HideFlags)61;
				val.AddComponent<ScalingPanel>();
				ManualLogSource log = Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(49, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Settings panel ready - press ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<KeyCode>(Settings.PanelHotkey.Value);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" in game to open it.");
				}
				log.LogInfo(val2);
			}
			catch (Exception value)
			{
				Log.LogError((object)("Could not create the in-game settings panel. Scaling still works; " + $"settings can be changed in the config file instead. Details: {value}"));
			}
		}

		private static void OnSettingChanged(object sender, EventArgs args)
		{
			ScalingState.SetProfile(Settings.BuildProfile());
		}
	}
}
namespace AskaEnemyScaling.UI
{
	public sealed class ScalingPanel : MonoBehaviour
	{
		private const int WindowId = 1163091761;

		private static readonly Rect DefaultBounds = new Rect(60f, 60f, 460f, 620f);

		private Rect _bounds = DefaultBounds;

		private bool _isOpen;

		private ScalingProfile _draft;

		private Vector2 _scroll;

		private CursorLockMode _cursorLockBeforeOpen;

		private bool _cursorVisibleBeforeOpen;

		private bool _inputFailureReported;

		private bool _useFallbackWindow;

		public ScalingPanel(IntPtr pointer)
			: base(pointer)
		{
		}//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)


		public void Update()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Input.GetKeyDown(Plugin.Settings.PanelHotkey.Value))
				{
					Toggle();
				}
			}
			catch (Exception ex)
			{
				if (!_inputFailureReported)
				{
					_inputFailureReported = true;
					Plugin.Log.LogError((object)("The settings panel hotkey cannot be read - this game build does not support the legacy Input class. The panel can still be configured through the config file. Details: " + ex.Message));
				}
			}
			if (_isOpen)
			{
				HoldCursorFree();
			}
		}

		[HideFromIl2Cpp]
		private void HoldCursorFree()
		{
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}

		[HideFromIl2Cpp]
		private void Toggle()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			_isOpen = !_isOpen;
			if (_isOpen)
			{
				_draft = ScalingState.Profile.Clone();
				_cursorLockBeforeOpen = Cursor.lockState;
				_cursorVisibleBeforeOpen = Cursor.visible;
				HoldCursorFree();
			}
			else
			{
				Cursor.lockState = _cursorLockBeforeOpen;
				Cursor.visible = _cursorVisibleBeforeOpen;
			}
		}

		public void OnGUI()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!_isOpen)
			{
				return;
			}
			if (_useFallbackWindow)
			{
				DrawFallbackWindow();
				return;
			}
			try
			{
				_bounds = GUI.Window(1163091761, _bounds, WindowFunction.op_Implicit((Action<int>)DrawWindow), "Enemy Scaling  -  0.1.2");
			}
			catch (Exception ex)
			{
				_useFallbackWindow = true;
				Plugin.Log.LogWarning((object)("GUI.Window is not usable in this build, so the settings panel will be drawn in a fixed position and cannot be dragged. Details: " + ex.Message));
			}
		}

		[HideFromIl2Cpp]
		private void DrawFallbackWindow()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			GUI.Box(_bounds, "Enemy Scaling  -  0.1.2");
			GUILayout.BeginArea(new Rect(((Rect)(ref _bounds)).x + 10f, ((Rect)(ref _bounds)).y + 24f, ((Rect)(ref _bounds)).width - 20f, ((Rect)(ref _bounds)).height - 34f));
			DrawWindow(1163091761);
			GUILayout.EndArea();
		}

		[HideFromIl2Cpp]
		private void DrawWindow(int id)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if (_draft == null)
			{
				_draft = ScalingState.Profile.Clone();
			}
			GUILayout.Space(4f);
			DrawReadout();
			GUILayout.Space(8f);
			_scroll = GUILayout.BeginScrollView(_scroll, (Il2CppReferenceArray<GUILayoutOption>)null);
			DrawPresetButtons();
			GUILayout.Space(8f);
			DrawTuning();
			GUILayout.Space(8f);
			DrawCategories();
			GUILayout.EndScrollView();
			GUILayout.Space(6f);
			DrawActions();
			if (!_useFallbackWindow)
			{
				GUI.DragWindow(new Rect(0f, 0f, 10000f, 22f));
			}
		}

		[HideFromIl2Cpp]
		private void DrawReadout()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("<b>Currently active</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
			if (!ScalingState.IsActive)
			{
				GUILayout.Label("Scaling is off - enemies are exactly as vanilla.", (Il2CppReferenceArray<GUILayoutOption>)null);
				return;
			}
			ProgressionSnapshot lastSnapshot = ScalingState.LastSnapshot;
			EnemyMultipliers current = ScalingState.Current;
			GUILayout.Label("Profile: " + ScalingState.Profile.Name, (Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label($"Day {lastSnapshot.DaysPassed}   |   {lastSnapshot.VillagerCount} villagers", (Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.Label($"Health x{current.Health:0.00}    Damage x{current.Damage:0.00}    Count x{current.SpawnCount:0.00}", (Il2CppReferenceArray<GUILayoutOption>)null);
		}

		[HideFromIl2Cpp]
		private void DrawPresetButtons()
		{
			GUILayout.Label("<b>Presets</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			if (GUILayout.Button("Standard", (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				_draft = ScalingPresets.Standard();
			}
			if (GUILayout.Button("Rising Tide", (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				_draft = ScalingPresets.RisingTide();
			}
			if (GUILayout.Button("Ragnarok", (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				_draft = ScalingPresets.Ragnarok();
			}
			GUILayout.EndHorizontal();
			GUILayout.Label(DescribePreset(_draft.Name), (Il2CppReferenceArray<GUILayoutOption>)null);
		}

		[HideFromIl2Cpp]
		private static string DescribePreset(string presetName)
		{
			return presetName switch
			{
				"Standard" => "Vanilla. Nothing is changed.", 
				"Rising Tide" => "Gentle. The late game stops being trivial, but you still outgrow the world.", 
				"Ragnarok" => "Aggressive. By the end of a long game, enemies hit like they did on day one.", 
				_ => "Custom values.", 
			};
		}

		[HideFromIl2Cpp]
		private void DrawTuning()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("<b>What counts as progress</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
			_draft.Combine = (CombineMode)Mathf.RoundToInt(LabelledSlider($"Driver: {_draft.Combine}", (float)_draft.Combine, 0f, 4f));
			_draft.DayStart = (int)LabelledSlider($"Scaling starts on day {_draft.DayStart}", _draft.DayStart, 0f, 200f);
			_draft.DayFull = (int)LabelledSlider($"Full difficulty by day {_draft.DayFull}", _draft.DayFull, _draft.DayStart + 1, 600f);
			_draft.VillagerStart = (int)LabelledSlider($"Scaling starts at {_draft.VillagerStart} villagers", _draft.VillagerStart, 0f, 100f);
			_draft.VillagerFull = (int)LabelledSlider($"Full difficulty at {_draft.VillagerFull} villagers", _draft.VillagerFull, _draft.VillagerStart + 1, 400f);
			GUILayout.Space(8f);
			GUILayout.Label("<b>How strong enemies get</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
			_draft.Health.Peak = LabelledSlider($"Health   x{_draft.Health.Peak:0.00}", _draft.Health.Peak, 1f, 8f);
			_draft.Damage.Peak = LabelledSlider($"Damage   x{_draft.Damage.Peak:0.00}", _draft.Damage.Peak, 1f, 5f);
			_draft.SpawnCount.Peak = LabelledSlider($"Spawns   x{_draft.SpawnCount.Peak:0.00}", _draft.SpawnCount.Peak, 1f, 3.5f);
			if (_draft.Damage.Peak > _draft.Health.Peak)
			{
				GUILayout.Label("<b>Warning:</b> damage is scaling faster than health. This tends to produce unavoidable one-shots rather than a harder fight.", (Il2CppReferenceArray<GUILayoutOption>)null);
			}
			_draft.Enabled = _draft.Health.Peak > 1f || _draft.Damage.Peak > 1f || _draft.SpawnCount.Peak > 1f;
		}

		[HideFromIl2Cpp]
		private void DrawCategories()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("<b>Which enemies</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
			_draft.Categories = ToggleCategory(_draft.Categories, (EnemyCategories)1, "Invasion monsters");
			_draft.Categories = ToggleCategory(_draft.Categories, (EnemyCategories)2, "Roaming hostiles");
			_draft.Categories = ToggleCategory(_draft.Categories, (EnemyCategories)4, "Cave and den monsters");
			_draft.Categories = ToggleCategory(_draft.Categories, (EnemyCategories)8, "Bosses (reduced scaling)");
			_draft.Categories = ToggleCategory(_draft.Categories, (EnemyCategories)16, "Passive wildlife");
		}

		[HideFromIl2Cpp]
		private static EnemyCategories ToggleCategory(EnemyCategories current, EnemyCategories category, string label)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			bool flag = (current & category) > 0;
			bool flag2 = GUILayout.Toggle(flag, "  " + label, (Il2CppReferenceArray<GUILayoutOption>)null);
			if (flag2 == flag)
			{
				return current;
			}
			if (!flag2)
			{
				return (EnemyCategories)(current & ~category);
			}
			return (EnemyCategories)(current | category);
		}

		[HideFromIl2Cpp]
		private void DrawActions()
		{
			GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
			if (GUILayout.Button("Apply", (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				ScalingState.SetProfile(_draft.Clone());
				Plugin.Settings.SaveAsCustom(_draft);
			}
			if (GUILayout.Button("Revert", (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				_draft = ScalingState.Profile.Clone();
			}
			if (GUILayout.Button("Close", (Il2CppReferenceArray<GUILayoutOption>)null))
			{
				_isOpen = false;
			}
			GUILayout.EndHorizontal();
			GUILayout.Label("Changes apply to enemies that spawn after you press Apply. Enemies already in the world keep the health they spawned with.", (Il2CppReferenceArray<GUILayoutOption>)null);
		}

		[HideFromIl2Cpp]
		private static float LabelledSlider(string label, float value, float min, float max)
		{
			GUILayout.Label(label, (Il2CppReferenceArray<GUILayoutOption>)null);
			return GUILayout.HorizontalSlider(value, min, max, (Il2CppReferenceArray<GUILayoutOption>)null);
		}
	}
}
namespace AskaEnemyScaling.Runtime
{
	internal static class EnemyClassifier
	{
		private sealed class CategoryBox
		{
			public EnemyCategories Value;
		}

		private static readonly ConditionalWeakTable<Creature, CategoryBox> Cache = new ConditionalWeakTable<Creature, CategoryBox>();

		public static EnemyCategories GetCategory(Creature creature)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)creature == (Object)null)
			{
				return (EnemyCategories)0;
			}
			if (Cache.TryGetValue(creature, out var value))
			{
				return value.Value;
			}
			EnemyCategories val = Classify(creature);
			Cache.Add(creature, new CategoryBox
			{
				Value = val
			});
			return val;
		}

		private static EnemyCategories Classify(Creature creature)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)((Component)creature).GetComponent<Boss>() != (Object)null)
				{
					return (EnemyCategories)8;
				}
				Monster val = ((Il2CppObjectBase)creature).TryCast<Monster>();
				if ((Object)(object)val == (Object)null)
				{
					return (EnemyCategories)16;
				}
				if (IsInvasionSpawned(val))
				{
					return (EnemyCategories)1;
				}
				return (EnemyCategories)(IsCaveOrDenBound(val) ? 4 : 2);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(29, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Could not classify creature: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
				}
				log.LogWarning(val2);
				return (EnemyCategories)0;
			}
		}

		private static bool IsInvasionSpawned(Monster monster)
		{
			return InvasionTagging.IsInvasionSpawn((Creature)(object)monster);
		}

		private static bool IsCaveOrDenBound(Monster monster)
		{
			CreatureSpawner spawner = ((Creature)monster).spawner;
			if ((Object)(object)spawner == (Object)null)
			{
				return false;
			}
			GameObject gameObject = ((Component)spawner).gameObject;
			if ((Object)(object)gameObject == (Object)null)
			{
				return false;
			}
			string text = ((Object)gameObject).name ?? string.Empty;
			if (text.IndexOf("Cave", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return text.IndexOf("Den", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}
	}
	internal static class InvasionTagging
	{
		private static readonly ConditionalWeakTable<Creature, object> Tagged = new ConditionalWeakTable<Creature, object>();

		private static readonly object Marker = new object();

		public static void Tag(Creature creature)
		{
			if (!((Object)(object)creature == (Object)null) && !Tagged.TryGetValue(creature, out var _))
			{
				Tagged.Add(creature, Marker);
			}
		}

		public static bool IsInvasionSpawn(Creature creature)
		{
			object value;
			if ((Object)(object)creature != (Object)null)
			{
				return Tagged.TryGetValue(creature, out value);
			}
			return false;
		}
	}
	internal static class ProgressionReader
	{
		private static WeatherSystem _weatherSystem;

		private static PopulationManager _populationManager;

		public static bool IsWorldReady
		{
			get
			{
				if ((Object)(object)ResolveWeatherSystem() != (Object)null)
				{
					return (Object)(object)ResolvePopulationManager() != (Object)null;
				}
				return false;
			}
		}

		public static void Reset()
		{
			_weatherSystem = null;
			_populationManager = null;
		}

		public static ProgressionSnapshot Read()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			return new ProgressionSnapshot(ReadDaysPassed(), ReadVillagerCount());
		}

		private static int ReadDaysPassed()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			WeatherSystem val = ResolveWeatherSystem();
			if ((Object)(object)val == (Object)null)
			{
				return 0;
			}
			try
			{
				return val.GetDaysPassed();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(28, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Could not read days passed: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
				}
				log.LogWarning(val2);
				return 0;
			}
		}

		private static int ReadVillagerCount()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			PopulationManager val = ResolvePopulationManager();
			if ((Object)(object)val == (Object)null)
			{
				return 0;
			}
			try
			{
				return val.GetPopulation()?.Count ?? 0;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(31, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Could not read villager count: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
				}
				log.LogWarning(val2);
				return 0;
			}
		}

		private static WeatherSystem ResolveWeatherSystem()
		{
			if ((Object)(object)_weatherSystem != (Object)null)
			{
				return _weatherSystem;
			}
			_weatherSystem = Object.FindObjectOfType<WeatherSystem>();
			return _weatherSystem;
		}

		private static PopulationManager ResolvePopulationManager()
		{
			if ((Object)(object)_populationManager != (Object)null)
			{
				return _populationManager;
			}
			_populationManager = Object.FindObjectOfType<PopulationManager>();
			return _populationManager;
		}
	}
	internal static class ScalingState
	{
		private const float RefreshIntervalSeconds = 2f;

		private static float _nextRefreshTime;

		private static ProgressionSnapshot _lastSnapshot;

		private static EnemyMultipliers _current = EnemyMultipliers.None;

		public static ScalingProfile Profile { get; private set; } = ScalingPresets.Standard();

		public static bool IsActive
		{
			get
			{
				if (Profile != null)
				{
					return !Profile.IsNoOp;
				}
				return false;
			}
		}

		public static ProgressionSnapshot LastSnapshot => _lastSnapshot;

		public static EnemyMultipliers Current
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				if (Time.unscaledTime >= _nextRefreshTime)
				{
					Refresh(force: false);
				}
				return _current;
			}
		}

		public static void SetProfile(ScalingProfile profile)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Profile = profile ?? ScalingPresets.Standard();
			_nextRefreshTime = 0f;
			Refresh(force: true);
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(28, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Scaling profile set to '");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Profile.Name);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' - ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<EnemyMultipliers>(Current);
			}
			log.LogInfo(val);
		}

		public static void ResetForNewWorld()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			ProgressionReader.Reset();
			_current = EnemyMultipliers.None;
			_lastSnapshot = new ProgressionSnapshot(0, 0);
			_nextRefreshTime = 0f;
		}

		public static EnemyMultipliers ForCategory(EnemyCategories category)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!IsActive)
			{
				return EnemyMultipliers.None;
			}
			if ((int)category == 0)
			{
				return EnemyMultipliers.None;
			}
			if (!Profile.Affects(category))
			{
				return EnemyMultipliers.None;
			}
			EnemyMultipliers result = Current;
			if ((int)category == 8)
			{
				result = ((EnemyMultipliers)(ref result)).Dampen(Profile.BossDampening);
			}
			return result;
		}

		private static void Refresh(bool force)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			_nextRefreshTime = Time.unscaledTime + 2f;
			if (!IsActive)
			{
				_current = EnemyMultipliers.None;
				return;
			}
			try
			{
				_lastSnapshot = ProgressionReader.Read();
				_current = ScalingCalculator.Compute(Profile, _lastSnapshot);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(33, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to refresh scaling state: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log.LogError(val);
				_current = EnemyMultipliers.None;
			}
		}

		public static string DescribeCurrent()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			if (!IsActive)
			{
				return "Enemy scaling: off (Standard)";
			}
			return $"{Profile.Name} | day {_lastSnapshot.DaysPassed}, {_lastSnapshot.VillagerCount} villagers | {Current}";
		}
	}
}
namespace AskaEnemyScaling.Patches
{
	internal static class IncomingDamageScaler
	{
		public static void Apply(DamageData damageData)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!ScalingState.IsActive || damageData == null)
			{
				return;
			}
			try
			{
				Creature val = ResolveAttacker(damageData);
				if (!((Object)(object)val == (Object)null))
				{
					EnemyMultipliers val2 = ScalingState.ForCategory(EnemyClassifier.GetCategory(val));
					if (!(val2.Damage <= 1f))
					{
						damageData.damageMultiplier *= val2.Damage;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(33, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Failed to scale incoming damage: ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Exception>(ex);
				}
				log.LogError(val3);
			}
		}

		private static Creature ResolveAttacker(DamageData damageData)
		{
			IDamageDealer damageDealer = damageData.damageDealer;
			if (damageDealer == null)
			{
				return null;
			}
			GameObject gameObject = damageDealer.gameObject;
			if ((Object)(object)gameObject == (Object)null)
			{
				return null;
			}
			return gameObject.GetComponentInParent<Creature>();
		}
	}
	[HarmonyPatch(typeof(PlayerCharacter), "TakeDamage")]
	internal static class PlayerDamagePatch
	{
		[HarmonyPrefix]
		private static void Prefix(DamageData __0)
		{
			IncomingDamageScaler.Apply(__0);
		}
	}
	[HarmonyPatch(typeof(Villager), "TakeDamage")]
	internal static class VillagerDamagePatch
	{
		[HarmonyPrefix]
		private static void Prefix(DamageData __0)
		{
			IncomingDamageScaler.Apply(__0);
		}
	}
	[HarmonyPatch(typeof(StructureDamageReceiver), "TakeDamage")]
	internal static class StructureDamagePatch
	{
		[HarmonyPrefix]
		private static void Prefix(DamageData __0)
		{
			IncomingDamageScaler.Apply(__0);
		}
	}
	internal static class HealthScaler
	{
		private static readonly ConditionalWeakTable<Creature, object> AlreadyScaled = new ConditionalWeakTable<Creature, object>();

		private static readonly object Marker = new object();

		public static void OnSpawned(Creature creature)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!ScalingState.IsActive || (Object)(object)creature == (Object)null)
			{
				return;
			}
			try
			{
				if (!AlreadyScaled.TryGetValue(creature, out var _))
				{
					EnemyMultipliers val = ScalingState.ForCategory(EnemyClassifier.GetCategory(creature));
					if (!(val.Health <= 1f) && ApplyHealthMultiplier(creature, val.Health))
					{
						AlreadyScaled.Add(creature, Marker);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(33, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to scale creature health: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				log.LogError(val2);
			}
		}

		private static bool ApplyHealthMultiplier(Creature creature, float multiplier)
		{
			VariableAttribute healthVAttr = creature._healthVAttr;
			if (healthVAttr == null)
			{
				return false;
			}
			float num = healthVAttr.max * multiplier;
			if (float.IsNaN(num) || float.IsInfinity(num) || num <= 0f)
			{
				return false;
			}
			healthVAttr.max = num;
			((Property)healthVAttr).SetValue(num);
			return true;
		}
	}
	[HarmonyPatch(typeof(Creature), "Spawned")]
	internal static class CreatureHealthPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Creature __instance)
		{
			HealthScaler.OnSpawned(__instance);
		}
	}
	[HarmonyPatch(typeof(Monster), "Spawned")]
	internal static class MonsterHealthPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Monster __instance)
		{
			HealthScaler.OnSpawned((Creature)(object)__instance);
		}
	}
	[HarmonyPatch(typeof(CreatureConfig), "GetCount")]
	internal static class CreatureCountPatch
	{
		private const int HardGroupCeiling = 120;

		[HarmonyPostfix]
		private static void Postfix(ref int __result)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (!ScalingState.IsActive || __result <= 0)
			{
				return;
			}
			try
			{
				EnemyMultipliers current = ScalingState.Current;
				if (!(current.SpawnCount <= 1f))
				{
					int num = ComputeCeiling(__result);
					__result = ScalingCalculator.ScaleCount(__result, current.SpawnCount, num);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(32, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to scale creature count: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				log.LogError(val);
			}
		}

		private static int ComputeCeiling(int vanillaCount)
		{
			float concurrentEnemyCeiling = ScalingState.Profile.ConcurrentEnemyCeiling;
			return Math.Min((concurrentEnemyCeiling > 1f) ? ((int)Math.Ceiling((double)vanillaCount * (double)concurrentEnemyCeiling)) : 120, 120);
		}
	}
	[HarmonyPatch(typeof(InvasionWavesList), "GetEnemyCount")]
	internal static class InvasionWaveCountPatch
	{
		private const int HardWaveCeiling = 200;

		[HarmonyPostfix]
		private static void Postfix(ref int __result)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!ScalingState.IsActive || __result <= 0)
			{
				return;
			}
			try
			{
				EnemyMultipliers val = ScalingState.ForCategory((EnemyCategories)1);
				if (!(val.SpawnCount <= 1f))
				{
					__result = ScalingCalculator.ScaleCount(__result, val.SpawnCount, 200);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(36, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Failed to scale invasion wave size: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				log.LogError(val2);
			}
		}
	}
	[HarmonyPatch(typeof(CreatureGroup), "SetInvading")]
	internal static class InvasionSpawnTaggingPatch
	{
		[HarmonyPostfix]
		private static void AfterSetInvading(CreatureGroup __instance, bool __0)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			if (!__0 || __instance == null)
			{
				return;
			}
			try
			{
				List<Creature> members = __instance._members;
				if (members != null)
				{
					Enumerator<Creature> enumerator = members.GetEnumerator();
					while (enumerator.MoveNext())
					{
						InvasionTagging.Tag(enumerator.Current);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(31, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not tag invasion spawns: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				log.LogWarning(val);
			}
		}
	}
}
namespace AskaEnemyScaling.Config
{
	internal sealed class ModSettings
	{
		public readonly ConfigEntry<PresetId> Preset;

		public readonly ConfigEntry<KeyCode> PanelHotkey;

		public readonly ConfigEntry<bool> ShowReadout;

		public readonly ConfigEntry<CombineMode> Combine;

		public readonly ConfigEntry<int> DayStart;

		public readonly ConfigEntry<int> DayFull;

		public readonly ConfigEntry<int> VillagerStart;

		public readonly ConfigEntry<int> VillagerFull;

		public readonly ConfigEntry<float> HealthPeak;

		public readonly ConfigEntry<float> DamagePeak;

		public readonly ConfigEntry<float> SpawnPeak;

		public readonly ConfigEntry<bool> ScaleInvasions;

		public readonly ConfigEntry<bool> ScaleRoaming;

		public readonly ConfigEntry<bool> ScaleCaveAndDen;

		public readonly ConfigEntry<bool> ScaleBosses;

		public readonly ConfigEntry<bool> ScaleWildlife;

		public ModSettings(ConfigFile config)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Expected O, but got Unknown
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Expected O, but got Unknown
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Expected O, but got Unknown
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Expected O, but got Unknown
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Expected O, but got Unknown
			ScalingProfile val = ScalingPresets.Ragnarok();
			Preset = config.Bind<PresetId>("1 - General", "Preset", (PresetId)0, "Which difficulty curve to use.\nStandard    - the mod changes nothing (default; safe on existing saves)\nRisingTide  - gentle: the late game stops being trivial\nRagnarok    - aggressive: the late game stays genuinely dangerous\nCustom      - use the values configured below");
			PanelHotkey = config.Bind<KeyCode>("1 - General", "PanelHotkey", (KeyCode)288, "Key that opens the in-game Enemy Scaling panel.");
			ShowReadout = config.Bind<bool>("1 - General", "ShowReadout", true, "Show a small readout of the current multipliers while the panel is open.");
			Combine = config.Bind<CombineMode>("2 - Progression", "CombineMode", val.Combine, "How days-survived and villager-count are combined.\nMax            - whichever you have pushed further sets the pace (recommended)\nAverage        - the mean of both\nWeighted       - a blend\nDaysOnly       - ignore villagers\nVillagersOnly  - ignore days");
			DayStart = config.Bind<int>("2 - Progression", "DayStart", val.DayStart, new ConfigDescription("In-game day at which scaling starts. Before this, enemies are vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 500), Array.Empty<object>()));
			DayFull = config.Bind<int>("2 - Progression", "DayFull", val.DayFull, new ConfigDescription("In-game day at which scaling reaches its peak - the end of a 'normal' playthrough. Playing past this pushes enemies beyond the peak.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 2000), Array.Empty<object>()));
			VillagerStart = config.Bind<int>("2 - Progression", "VillagerStart", val.VillagerStart, new ConfigDescription("Villager count at which scaling starts.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 500), Array.Empty<object>()));
			VillagerFull = config.Bind<int>("2 - Progression", "VillagerFull", val.VillagerFull, new ConfigDescription("Villager count at which scaling reaches its peak.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), Array.Empty<object>()));
			HealthPeak = config.Bind<float>("3 - Custom curve", "HealthPeak", val.Health.Peak, new ConfigDescription("Enemy health multiplier at full progression. 1.0 = unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			DamagePeak = config.Bind<float>("3 - Custom curve", "DamagePeak", val.Damage.Peak, new ConfigDescription("Enemy damage multiplier at full progression. Keep this below the health multiplier - high damage causes unavoidable one-shots rather than difficulty.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 6f), Array.Empty<object>()));
			SpawnPeak = config.Bind<float>("3 - Custom curve", "SpawnPeak", val.SpawnCount.Peak, new ConfigDescription("Enemy spawn-count multiplier at full progression. This is the setting most likely to affect framerate during large raids.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f), Array.Empty<object>()));
			ScaleInvasions = config.Bind<bool>("4 - Which enemies", "Invasions", true, "Scale monsters that attack the settlement during invasions.");
			ScaleRoaming = config.Bind<bool>("4 - Which enemies", "Roaming", true, "Scale hostile creatures roaming the overworld.");
			ScaleCaveAndDen = config.Bind<bool>("4 - Which enemies", "CavesAndDens", true, "Scale monsters that live in caves and dens.");
			ScaleBosses = config.Bind<bool>("4 - Which enemies", "Bosses", true, "Scale bosses. Bosses always receive a reduced share of the increase.");
			ScaleWildlife = config.Bind<bool>("4 - Which enemies", "Wildlife", false, "Scale passive animals. Off by default - scaling deer only makes hunting slower.");
		}

		public ScalingProfile BuildProfile()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Preset.Value != 3)
			{
				ScalingProfile obj = ScalingPresets.Get(Preset.Value);
				obj.Categories = ReadCategories();
				return obj;
			}
			return BuildCustomProfile();
		}

		private ScalingProfile BuildCustomProfile()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Expected O, but got Unknown
			ScalingProfile val = ScalingPresets.Ragnarok();
			return new ScalingProfile
			{
				Name = "Custom",
				Enabled = true,
				DayStart = DayStart.Value,
				DayFull = Math.Max(DayFull.Value, DayStart.Value + 1),
				VillagerStart = VillagerStart.Value,
				VillagerFull = Math.Max(VillagerFull.Value, VillagerStart.Value + 1),
				Combine = Combine.Value,
				Health = new ScalingAxis(HealthPeak.Value, val.Health.Shape, val.Health.Overdrive, val.Health.Cap),
				Damage = new ScalingAxis(DamagePeak.Value, val.Damage.Shape, val.Damage.Overdrive, val.Damage.Cap),
				SpawnCount = new ScalingAxis(SpawnPeak.Value, val.SpawnCount.Shape, val.SpawnCount.Overdrive, val.SpawnCount.Cap),
				BossDampening = val.BossDampening,
				ConcurrentEnemyCeiling = val.ConcurrentEnemyCeiling,
				Categories = ReadCategories()
			};
		}

		private EnemyCategories ReadCategories()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			EnemyCategories val = (EnemyCategories)0;
			if (ScaleInvasions.Value)
			{
				val = (EnemyCategories)(val | 1);
			}
			if (ScaleRoaming.Value)
			{
				val = (EnemyCategories)(val | 2);
			}
			if (ScaleCaveAndDen.Value)
			{
				val = (EnemyCategories)(val | 4);
			}
			if (ScaleBosses.Value)
			{
				val = (EnemyCategories)(val | 8);
			}
			if (ScaleWildlife.Value)
			{
				val = (EnemyCategories)(val | 0x10);
			}
			return val;
		}

		public void SaveAsCustom(ScalingProfile profile)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			Preset.Value = (PresetId)3;
			Combine.Value = profile.Combine;
			DayStart.Value = profile.DayStart;
			DayFull.Value = profile.DayFull;
			VillagerStart.Value = profile.VillagerStart;
			VillagerFull.Value = profile.VillagerFull;
			HealthPeak.Value = profile.Health.Peak;
			DamagePeak.Value = profile.Damage.Peak;
			SpawnPeak.Value = profile.SpawnCount.Peak;
			ScaleInvasions.Value = profile.Affects((EnemyCategories)1);
			ScaleRoaming.Value = profile.Affects((EnemyCategories)2);
			ScaleCaveAndDen.Value = profile.Affects((EnemyCategories)4);
			ScaleBosses.Value = profile.Affects((EnemyCategories)8);
			ScaleWildlife.Value = profile.Affects((EnemyCategories)16);
		}
	}
}