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 SandSailorStudio.WorldGen;
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+7f154477fb6a49aebb148d5904a411f5515481f7")]
[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.2.0")]
public sealed class Plugin : BasePlugin
{
public const string PluginGuid = "aska.enemy.scaling";
public const string PluginName = "ASKA Enemy Scaling";
public const string PluginVersion = "0.2.0";
private Harmony _harmony;
internal static ManualLogSource Log { get; private set; }
internal static ModSettings Settings { get; private set; }
public override void Load()
{
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Expected O, but got Unknown
Log = ((BasePlugin)this).Log;
Settings = new ModSettings(((BasePlugin)this).Config);
ScalingState.SetProfile(Settings.BuildProfile());
((BasePlugin)this).Config.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.2.0");
((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();
}
((BasePlugin)this).Config.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)
{
if (!Settings.IsSaving)
{
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, 40f, 540f, 700f);
private const float AxisColumnWidth = 122f;
private const float ValueColumnWidth = 74f;
private const float ArrowWidth = 26f;
private const float CoarseArrowWidth = 32f;
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;
private static GUIStyle _arrowStyle;
private static GUIStyle ArrowStyle
{
get
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
if (_arrowStyle == null)
{
_arrowStyle = new GUIStyle(GUI.skin.button);
_arrowStyle.richText = false;
}
return _arrowStyle;
}
}
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.2.0");
}
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.2.0");
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_00ca: 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);
DrawBossScaling();
GUILayout.Space(8f);
DrawRespawn();
GUILayout.Space(8f);
DrawCategories();
GUILayout.Space(8f);
DrawWorldSettings();
GUILayout.EndScrollView();
GUILayout.Space(6f);
DrawActions();
if (!_useFallbackWindow)
{
GUI.DragWindow(new Rect(0f, 0f, 10000f, 22f));
}
}
[HideFromIl2Cpp]
private void DrawReadout()
{
//IL_000b: 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_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
GUILayout.Label("<b>Currently applied</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
ProgressionSnapshot lastSnapshot = ScalingState.LastSnapshot;
GUILayout.Label($"Profile: {ScalingState.Profile.Name} Day {lastSnapshot.DaysPassed} | {lastSnapshot.VillagerCount} villagers", (Il2CppReferenceArray<GUILayoutOption>)null);
DrawComparisonTable();
GUILayout.Space(4f);
GUILayout.Label(DescribeCombinedEffect(), (Il2CppReferenceArray<GUILayoutOption>)null);
}
[HideFromIl2Cpp]
private static void DrawComparisonTable()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
EffectiveMultipliers effective = ScalingState.Effective;
GUILayout.Space(4f);
GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
GUILayout.Label("", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(122f) });
GUILayout.Label("<b>This mod</b>", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(74f) });
GUILayout.Label("<b>World setting</b>", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(94f) });
GUILayout.Label("<b>vs default world</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
GUILayout.EndHorizontal();
DrawComparisonRow("Enemy health", effective.Health);
DrawComparisonRow("Enemy damage", effective.Damage);
DrawComparisonRow("World spawns", effective.PopulationSpawn);
DrawComparisonRow("Invasion spawns", effective.InvasionSpawn);
}
[HideFromIl2Cpp]
private static void DrawComparisonRow(string axisName, AxisBreakdown axis)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
GUILayout.Label(axisName, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(122f) });
GUILayout.Label($"x{axis.Mod:0.00}", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(74f) });
GUILayout.Label(axis.GameKnown ? $"x{axis.Game:0.00}" : "not read yet", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(94f) });
GUILayout.Label(axis.GameKnown ? $"<b>x{((AxisBreakdown)(ref axis)).Effective:0.00}</b>" : $"x{axis.Mod:0.00} and up", (Il2CppReferenceArray<GUILayoutOption>)null);
GUILayout.EndHorizontal();
}
[HideFromIl2Cpp]
private static string DescribeCombinedEffect()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0168: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Unknown result type (might be due to invalid IL or missing references)
EffectiveMultipliers effective = ScalingState.Effective;
if (((AxisBreakdown)(ref effective.Health)).IsNeutral && ((AxisBreakdown)(ref effective.Damage)).IsNeutral && ((AxisBreakdown)(ref effective.PopulationSpawn)).IsNeutral && ((AxisBreakdown)(ref effective.InvasionSpawn)).IsNeutral)
{
return "Compared to a default world with no mod: no difference yet.";
}
string text = "Compared to a default world with no mod, enemies here have " + $"<b>{((AxisBreakdown)(ref effective.Health)).Effective:0.0}x</b> the health, deal " + $"<b>{((AxisBreakdown)(ref effective.Damage)).Effective:0.0}x</b> the damage, and arrive in " + $"<b>{((AxisBreakdown)(ref effective.PopulationSpawn)).Effective:0.0}x</b> the numbers " + $"(<b>{((AxisBreakdown)(ref effective.InvasionSpawn)).Effective:0.0}x</b> during invasions).";
if (!effective.Health.GameKnown)
{
text += "\nASKA's own difficulty options have not been read yet, so these figures currently show the mod's contribution only. They fill in once a world is loaded and enemies have spawned.";
}
return text;
}
[HideFromIl2Cpp]
private void DrawPresetButtons()
{
GUILayout.Label("<b>Presets</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
if (GUILayout.Button("Standard", (Il2CppReferenceArray<GUILayoutOption>)null))
{
AdoptPreset(ScalingPresets.Standard());
}
if (GUILayout.Button("Rising Tide", (Il2CppReferenceArray<GUILayoutOption>)null))
{
AdoptPreset(ScalingPresets.RisingTide());
}
if (GUILayout.Button("Ragnarok", (Il2CppReferenceArray<GUILayoutOption>)null))
{
AdoptPreset(ScalingPresets.Ragnarok());
}
GUILayout.EndHorizontal();
GUILayout.Label(DescribePreset(_draft.Name), (Il2CppReferenceArray<GUILayoutOption>)null);
}
[HideFromIl2Cpp]
private void AdoptPreset(ScalingProfile preset)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
preset.Categories = _draft.Categories;
preset.BossDampening = _draft.BossDampening;
preset.PoiRespawnCount = _draft.PoiRespawnCount;
preset.PoiRespawnFrequency = _draft.PoiRespawnFrequency;
preset.DenActivationCount = _draft.DenActivationCount;
preset.DenRevivalFrequency = _draft.DenRevivalFrequency;
preset.PoiPopulationCeiling = _draft.PoiPopulationCeiling;
_draft = preset;
}
[HideFromIl2Cpp]
private static string DescribePreset(string presetName)
{
return presetName switch
{
"Standard" => "Vanilla enemy strength. 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_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
//IL_0260: Unknown result type (might be due to invalid IL or missing references)
//IL_02de: Unknown result type (might be due to invalid IL or missing references)
//IL_035c: 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(Stepper($"Driver: {_draft.Combine}", (float)_draft.Combine, ControlRanges.CombineMode));
_draft.DayStart = (int)Stepper($"Scaling starts on day {_draft.DayStart}", _draft.DayStart, ControlRanges.DayStart);
_draft.DayFull = (int)Stepper($"Full difficulty by day {_draft.DayFull}", _draft.DayFull, ControlRanges.DayFull(_draft.DayStart));
_draft.VillagerStart = (int)Stepper($"Scaling starts at {_draft.VillagerStart} villagers", _draft.VillagerStart, ControlRanges.VillagerStart);
_draft.VillagerFull = (int)Stepper($"Full difficulty at {_draft.VillagerFull} villagers", _draft.VillagerFull, ControlRanges.VillagerFull(_draft.VillagerStart));
GUILayout.Space(8f);
GUILayout.Label("<b>How strong enemies get</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
GUILayout.Label("These are the multipliers this mod reaches at full progression. The figure in brackets is what that comes to once ASKA's own world settings are included.", (Il2CppReferenceArray<GUILayoutOption>)null);
_draft.Health.Peak = Stepper($"Health x{_draft.Health.Peak:0.00}" + DescribeProjectedPeak(_draft.Health.Peak, (GameSetting)0), _draft.Health.Peak, ControlRanges.HealthPeak);
_draft.Damage.Peak = Stepper($"Damage x{_draft.Damage.Peak:0.00}" + DescribeProjectedPeak(_draft.Damage.Peak, (GameSetting)1), _draft.Damage.Peak, ControlRanges.DamagePeak);
_draft.SpawnCount.Peak = Stepper($"Spawns x{_draft.SpawnCount.Peak:0.00}" + DescribeProjectedPeak(_draft.SpawnCount.Peak, (GameSetting)2), _draft.SpawnCount.Peak, ControlRanges.SpawnPeak);
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 static string DescribeProjectedPeak(float peak, GameSetting setting)
{
//IL_0005: 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)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
GameSettingReading val = ScalingState.GameSettings[setting];
if (!val.IsAvailable)
{
return string.Empty;
}
float relativeToDefault = ((GameSettingReading)(ref val)).RelativeToDefault;
float value = peak * relativeToDefault;
if (Math.Abs(relativeToDefault - 1f) < 0.005f)
{
return " (world setting is at its default)";
}
return $" (x{value:0.00} vs a default world, including the game's x{relativeToDefault:0.00})";
}
[HideFromIl2Cpp]
private void DrawBossScaling()
{
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
GUILayout.Label("<b>Bosses</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
_draft.BossDampening = Stepper($"Bosses receive {_draft.BossDampening * 100f:0}% of the increase", _draft.BossDampening, ControlRanges.BossDampening);
GUILayout.Label(DescribeBossScaling(_draft.BossDampening, _draft.Health.Peak), (Il2CppReferenceArray<GUILayoutOption>)null);
}
[HideFromIl2Cpp]
private static string DescribeBossScaling(float dampening, float healthPeak)
{
float value = 1f + (healthPeak - 1f) * dampening;
if (dampening <= 0.005f)
{
return "Bosses are left exactly as vanilla while the rest of the world scales. Safe, but boss fights will feel easy next to ordinary encounters.";
}
if (Math.Abs(dampening - 0.5f) < 0.005f)
{
return $"Default. At full progression a boss reaches x{value:0.00} health while ordinary enemies reach x{healthPeak:0.00}. Half the bonus is the " + "tuned value: bosses already have large health pools, and doubling them again turns a fight into a waiting game.";
}
if (dampening > 1.005f)
{
return $"<b>Warning:</b> bosses now scale HARDER than ordinary enemies, reaching x{value:0.00} health against x{healthPeak:0.00}. Expect very long " + "fights, and check that your damage output can still finish one before your food and stamina run out.";
}
if (dampening > 0.5f)
{
return $"<b>Above the tuned default.</b> A boss will reach x{value:0.00} " + "health at full progression. Boss health pools are already large, so this mostly lengthens the fight rather than making it more dangerous.";
}
return $"<b>Below the tuned default.</b> A boss will reach x{value:0.00} health against x{healthPeak:0.00} for ordinary enemies, so bosses will feel " + "comparatively easy late on.";
}
[HideFromIl2Cpp]
private void DrawRespawn()
{
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
GUILayout.Label("<b>Respawning at camps, caves and dens</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
GUILayout.Label("Applies whichever preset is selected, including Standard - respawn pacing is a separate choice from how strong enemies are.", (Il2CppReferenceArray<GUILayoutOption>)null);
_draft.PoiRespawnCount = Stepper($"How many come back x{_draft.PoiRespawnCount:0.00}", _draft.PoiRespawnCount, ControlRanges.PoiRespawnCount);
_draft.PoiRespawnFrequency = Stepper($"How often they come back x{_draft.PoiRespawnFrequency:0.00}" + DescribeFrequency(_draft.PoiRespawnFrequency), _draft.PoiRespawnFrequency, ControlRanges.PoiRespawnFrequency);
_draft.DenActivationCount = Stepper($"Creatures a den fields x{_draft.DenActivationCount:0.00}", _draft.DenActivationCount, ControlRanges.DenActivationCount);
_draft.DenRevivalFrequency = Stepper($"How quickly a cleared den revives x{_draft.DenRevivalFrequency:0.00}" + DescribeFrequency(_draft.DenRevivalFrequency), _draft.DenRevivalFrequency, ControlRanges.DenRevivalFrequency);
_draft.PoiPopulationCeiling = (int)Stepper($"Never more than {_draft.PoiPopulationCeiling} at one place (framerate guard)", _draft.PoiPopulationCeiling, ControlRanges.PoiPopulationCeiling);
DrawRespawnObservation();
}
[HideFromIl2Cpp]
private static string DescribeFrequency(float frequency)
{
if (Math.Abs(frequency - 1f) < 0.005f)
{
return " (vanilla)";
}
if (!(frequency > 1f))
{
return $" (the wait is {1f / frequency:0.0}x as long)";
}
return $" (the wait is {1f / frequency * 100f:0}% of vanilla)";
}
[HideFromIl2Cpp]
private static void DrawRespawnObservation()
{
RespawnObservation respawn = ScalingState.Respawn;
if (!respawn.HasPopulation && !respawn.HasDen)
{
GUILayout.Label("No camp or den has been set up since these settings were applied, so there is nothing measured from your world to show yet.", (Il2CppReferenceArray<GUILayoutOption>)null);
return;
}
GUILayout.Space(4f);
GUILayout.Label("<b>Measured in your world</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
if (respawn.HasPopulation)
{
GUILayout.Label($"Last point of interest: {respawn.VanillaSize} creatures became {respawn.EffectiveSize}; its refill timer went from {respawn.VanillaInterval:0.0} to {respawn.EffectiveInterval:0.0} " + "(ASKA's own time units, so read the ratio rather than the number).", (Il2CppReferenceArray<GUILayoutOption>)null);
}
if (respawn.HasDen)
{
GUILayout.Label($"Last cleared den: revival cooldown went from {respawn.VanillaDenCooldown} to {respawn.EffectiveDenCooldown}.", (Il2CppReferenceArray<GUILayoutOption>)null);
}
}
[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");
_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 static void DrawWorldSettings()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
GameDifficultySnapshot gameSettings = ScalingState.GameSettings;
GUILayout.Label("<b>ASKA's own world settings</b>", (Il2CppReferenceArray<GUILayoutOption>)null);
if (!gameSettings.HasAnyReading)
{
GUILayout.Label("None read yet. These fill in once a world is loaded; the enemy health and damage options are read from the first hostile creature that spawns.", (Il2CppReferenceArray<GUILayoutOption>)null);
return;
}
if (gameSettings.IsEntirelyDefault)
{
GUILayout.Label("Every option the mod can see is at its default, so the figures above are this mod's work alone.", (Il2CppReferenceArray<GUILayoutOption>)null);
}
DrawWorldSettingRow(gameSettings[(GameSetting)0]);
DrawWorldSettingRow(gameSettings[(GameSetting)1]);
DrawWorldSettingRow(gameSettings[(GameSetting)2]);
DrawWorldSettingRow(gameSettings[(GameSetting)3]);
DrawWorldSettingRow(gameSettings[(GameSetting)4]);
DrawWorldSettingRow(gameSettings[(GameSetting)5]);
DrawWorldSettingRow(gameSettings[(GameSetting)6]);
DrawWorldSettingRow(gameSettings[(GameSetting)7]);
}
[HideFromIl2Cpp]
private static void DrawWorldSettingRow(GameSettingReading reading)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: 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)
if (reading.IsAvailable)
{
string value = (((GameSettingReading)(ref reading)).IsAtDefault ? "at its default" : $"<b>x{((GameSettingReading)(ref reading)).RelativeToDefault:0.00} vs default</b>");
GUILayout.Label($" {reading.Label}: {reading.Current:0.##} (default {reading.Default:0.##}) - {value}", (Il2CppReferenceArray<GUILayoutOption>)null);
}
}
[HideFromIl2Cpp]
private void DrawActions()
{
GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
if (GUILayout.Button("Apply", (Il2CppReferenceArray<GUILayoutOption>)null))
{
Plugin.Settings.Save(_draft);
ScalingState.SetProfile(_draft.Clone());
}
if (GUILayout.Button("Revert", (Il2CppReferenceArray<GUILayoutOption>)null))
{
_draft = ScalingState.Profile.Clone();
}
if (GUILayout.Button("Close", (Il2CppReferenceArray<GUILayoutOption>)null))
{
_isOpen = false;
}
GUILayout.EndHorizontal();
GUILayout.Label("Health and damage changes apply to enemies that spawn after you press Apply; enemies already in the world keep what they spawned with. Respawn changes apply the next time a camp or den is set up.", (Il2CppReferenceArray<GUILayoutOption>)null);
}
[HideFromIl2Cpp]
private static float Stepper(string label, float value, SliderStep range)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
GUILayout.Label(label, (Il2CppReferenceArray<GUILayoutOption>)null);
GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null);
bool hasCoarseArrows = ((SliderStep)(ref range)).HasCoarseArrows;
if (hasCoarseArrows && Arrow("<<", 32f))
{
value = ((SliderStep)(ref range)).Nudge(value, -1, true);
}
if (Arrow("<", 26f))
{
value = ((SliderStep)(ref range)).Nudge(value, -1, false);
}
GUILayout.BeginVertical((Il2CppReferenceArray<GUILayoutOption>)null);
GUILayout.Space(6f);
value = ((SliderStep)(ref range)).Snap(GUILayout.HorizontalSlider(value, range.Min, range.Max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }));
GUILayout.EndVertical();
if (Arrow(">", 26f))
{
value = ((SliderStep)(ref range)).Nudge(value, 1, false);
}
if (hasCoarseArrows && Arrow(">>", 32f))
{
value = ((SliderStep)(ref range)).Nudge(value, 1, true);
}
GUILayout.EndHorizontal();
return value;
}
[HideFromIl2Cpp]
private static bool Arrow(string glyph, float width)
{
return GUILayout.Button(glyph, ArrowStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(width) });
}
}
}
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 GameSettingsReader
{
private static AttributeCustomizationSelector _healthSelector;
private static AttributeCustomizationSelector _damageSelector;
private static CreaturePopulationCustomizationData _populationSelector;
private static InvasionCustomizationData _invasionSelector;
private static DenCustomizationData _denSelector;
private static bool _failureReported;
public static bool NeedsHostileDataSheet
{
get
{
if (!((Object)(object)_healthSelector == (Object)null))
{
return (Object)(object)_damageSelector == (Object)null;
}
return true;
}
}
public static void Reset()
{
_healthSelector = null;
_damageSelector = null;
_populationSelector = null;
_invasionSelector = null;
_denSelector = null;
_failureReported = false;
}
public static void ObserveHostileDataSheet(CreatureDataSheet dataSheet)
{
if ((Object)(object)dataSheet == (Object)null || ((Object)(object)_healthSelector != (Object)null && (Object)(object)_damageSelector != (Object)null))
{
return;
}
try
{
if ((Object)(object)_healthSelector == (Object)null)
{
_healthSelector = dataSheet.vitalityCustomizationData;
}
if ((Object)(object)_damageSelector == (Object)null)
{
_damageSelector = dataSheet.damageMultiplierData;
}
}
catch (Exception error)
{
ReportOnce("read a creature data sheet's customisation options", error);
}
}
public static void ObservePopulationConfiguration(CreaturePopulationConfiguration configuration)
{
if ((Object)(object)configuration == (Object)null || (Object)(object)_populationSelector != (Object)null)
{
return;
}
try
{
_populationSelector = configuration.customizationData;
}
catch (Exception error)
{
ReportOnce("read a population configuration's customisation option", error);
}
}
public static void ObserveDenCustomization(DenCustomizationData selector)
{
if (!((Object)(object)selector == (Object)null) && !((Object)(object)_denSelector != (Object)null))
{
_denSelector = selector;
}
}
public static GameDifficultySnapshot Read()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Expected O, but got Unknown
GameDifficultySnapshot val = new GameDifficultySnapshot();
try
{
ResolveFromActiveConfig();
ReadAttributeOption(val, (GameSetting)0, _healthSelector, "Enemy health");
ReadAttributeOption(val, (GameSetting)1, _damageSelector, "Enemy damage");
ReadPopulationOption(val);
ReadInvasionOptions(val);
ReadDenOptions(val);
}
catch (Exception error)
{
ReportOnce("read ASKA's world settings", error);
}
return val;
}
private static void ResolveFromActiveConfig()
{
if ((Object)(object)_populationSelector != (Object)null && (Object)(object)_invasionSelector != (Object)null && (Object)(object)_denSelector != (Object)null)
{
return;
}
WorldCustomizationConfig active = WorldCustomizationConfig.GetActive();
if ((Object)(object)active == (Object)null)
{
return;
}
List<WorldCustomizationData> items = active.items;
if (items == null)
{
return;
}
Enumerator<WorldCustomizationData> enumerator = items.GetEnumerator();
while (enumerator.MoveNext())
{
WorldCustomizationData current = enumerator.Current;
if ((Object)(object)current == (Object)null)
{
continue;
}
if ((Object)(object)_populationSelector == (Object)null)
{
CreaturePopulationCustomizationData val = ((Il2CppObjectBase)current).TryCast<CreaturePopulationCustomizationData>();
if ((Object)(object)val != (Object)null)
{
_populationSelector = val;
continue;
}
}
if ((Object)(object)_invasionSelector == (Object)null)
{
InvasionCustomizationData val2 = ((Il2CppObjectBase)current).TryCast<InvasionCustomizationData>();
if ((Object)(object)val2 != (Object)null)
{
_invasionSelector = val2;
continue;
}
}
if ((Object)(object)_denSelector == (Object)null)
{
DenCustomizationData val3 = ((Il2CppObjectBase)current).TryCast<DenCustomizationData>();
if ((Object)(object)val3 != (Object)null)
{
_denSelector = val3;
}
}
}
}
private static void ReadAttributeOption(GameDifficultySnapshot snapshot, GameSetting setting, AttributeCustomizationSelector selector, string fallbackLabel)
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)selector == (Object)null)
{
return;
}
try
{
AttributeCustomizationSelector val = selector.OverriderVersionData ?? selector;
if (TryReadDefaultAttributeValue(val, out var value))
{
float modifiedValue = selector.GetModifiedValue(1f);
if (!float.IsNaN(modifiedValue) && !float.IsInfinity(modifiedValue))
{
snapshot.Set(setting, new GameSettingReading(DescribeOption((WorldCustomizationData)(object)selector, fallbackLabel), modifiedValue, value, ((WorldCustomizationSelector)selector).GetSelectedLevel(), ((WorldCustomizationSelector)val).defaultLevel, ((WorldCustomizationSelector)selector).GetLevelCount()));
}
}
}
catch (Exception error)
{
ReportOnce("read the '" + fallbackLabel + "' world setting", error);
}
}
private static bool TryReadDefaultAttributeValue(AttributeCustomizationSelector selector, out float value)
{
//IL_002b: 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_0031: 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_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Invalid comparison between Unknown and I4
//IL_0043: 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)
//IL_003e: Invalid comparison between Unknown and I4
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
value = 1f;
Il2CppStructArray<Slot> slots = selector.slots;
if (slots == null)
{
return false;
}
int defaultLevel = ((WorldCustomizationSelector)selector).defaultLevel;
if (defaultLevel < 0 || defaultLevel >= ((Il2CppArrayBase<Slot>)(object)slots).Length)
{
return false;
}
Slot val = ((Il2CppArrayBase<Slot>)(object)slots)[defaultLevel];
ModifierOperation operation = val.operation;
if ((int)operation != 1)
{
if ((int)operation == 2)
{
value = 1f + val.value;
return true;
}
return false;
}
value = val.value;
return true;
}
private static void ReadPopulationOption(GameDifficultySnapshot snapshot)
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
CreaturePopulationCustomizationData populationSelector = _populationSelector;
if ((Object)(object)populationSelector == (Object)null)
{
return;
}
try
{
CreaturePopulationCustomizationData val = populationSelector.OverriderVersionData ?? populationSelector;
List<SlotData> slots = val.slots;
if (TryValidateSlotIndex(((WorldCustomizationSelector)val).defaultLevel, slots?.Count ?? 0, out var level))
{
snapshot.Set((GameSetting)2, new GameSettingReading(DescribeOption((WorldCustomizationData)(object)populationSelector, "Creature spawns"), populationSelector.GetSpawnMultiplier(), slots[level].spawnMultiplier, ((WorldCustomizationSelector)populationSelector).GetSelectedLevel(), ((WorldCustomizationSelector)val).defaultLevel, ((WorldCustomizationSelector)populationSelector).GetLevelCount()));
}
}
catch (Exception error)
{
ReportOnce("read the creature-spawn world setting", error);
}
}
private static void ReadInvasionOptions(GameDifficultySnapshot snapshot)
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: 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_007d: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
InvasionCustomizationData invasionSelector = _invasionSelector;
if ((Object)(object)invasionSelector == (Object)null)
{
return;
}
try
{
InvasionCustomizationData val = invasionSelector.OverriderVersionData ?? invasionSelector;
List<InvasionSlotData> slots = val.slots;
if (TryValidateSlotIndex(((WorldCustomizationSelector)val).defaultLevel, slots?.Count ?? 0, out var level))
{
InvasionSlotData val2 = slots[level];
string text = DescribeOption((WorldCustomizationData)(object)invasionSelector, "Invasion size");
snapshot.Set((GameSetting)3, new GameSettingReading(text, invasionSelector.GetSpawnMultiplier(), val2.invasionSpawnsMultiplier, ((WorldCustomizationSelector)invasionSelector).GetSelectedLevel(), ((WorldCustomizationSelector)val).defaultLevel, ((WorldCustomizationSelector)invasionSelector).GetLevelCount()));
snapshot.Set((GameSetting)4, new GameSettingReading(text + " (winter)", invasionSelector.GetWinterInvasionSpawnMultiplier(), val2.winterInvasionSpawnsMultiplier, ((WorldCustomizationSelector)invasionSelector).GetSelectedLevel(), ((WorldCustomizationSelector)val).defaultLevel, ((WorldCustomizationSelector)invasionSelector).GetLevelCount()));
}
}
catch (Exception error)
{
ReportOnce("read the invasion world setting", error);
}
}
private static void ReadDenOptions(GameDifficultySnapshot snapshot)
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
DenCustomizationData denSelector = _denSelector;
if ((Object)(object)denSelector == (Object)null)
{
return;
}
try
{
DenCustomizationData val = denSelector.OverriderVersionData ?? denSelector;
List<DenSlotData> slots = val.slots;
if (TryValidateSlotIndex(((WorldCustomizationSelector)val).defaultLevel, slots?.Count ?? 0, out var level))
{
DenSlotData val2 = slots[level];
string text = DescribeOption((WorldCustomizationData)(object)denSelector, "Dens");
int selectedLevel = ((WorldCustomizationSelector)denSelector).GetSelectedLevel();
int defaultLevel = ((WorldCustomizationSelector)val).defaultLevel;
int levelCount = ((WorldCustomizationSelector)denSelector).GetLevelCount();
if (TryValidateSlotIndex(selectedLevel, slots.Count, out var level2))
{
DenSlotData val3 = slots[level2];
snapshot.Set((GameSetting)5, new GameSettingReading(text + " (starting creatures)", (float)val3.initialActiveCount, (float)val2.initialActiveCount, selectedLevel, defaultLevel, levelCount));
snapshot.Set((GameSetting)6, new GameSettingReading(text + " (creatures per cycle)", (float)val3.cycleActivationCount, (float)val2.cycleActivationCount, selectedLevel, defaultLevel, levelCount));
snapshot.Set((GameSetting)7, new GameSettingReading(text + " (stay dead after being killed)", (float)val3.exclusionCountAfterDeath, (float)val2.exclusionCountAfterDeath, selectedLevel, defaultLevel, levelCount));
}
}
}
catch (Exception error)
{
ReportOnce("read the den world setting", error);
}
}
private static bool TryValidateSlotIndex(int requestedLevel, int slotCount, out int level)
{
level = requestedLevel;
if (slotCount > 0 && requestedLevel >= 0)
{
return requestedLevel < slotCount;
}
return false;
}
private static string DescribeOption(WorldCustomizationData option, string fallback)
{
try
{
string name = option.GetName();
return string.IsNullOrEmpty(name) ? fallback : name;
}
catch
{
return fallback;
}
}
private static void ReportOnce(string action, Exception error)
{
if (!_failureReported)
{
_failureReported = true;
Plugin.Log.LogWarning((object)("Could not " + action + ". The panel will show the mod's own multipliers but cannot compare them against ASKA's world settings. This usually means the game updated and the option moved. Details: " + error.Message));
}
}
}
internal static class ProgressionReader
{
private static WeatherSystem _weatherSystem;
private static PopulationManager _populationManager;
private static bool _worldChanged;
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;
_worldChanged = false;
}
public static bool ConsumeWorldChanged()
{
if (!_worldChanged)
{
return false;
}
_worldChanged = false;
return true;
}
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>();
if ((Object)(object)_populationManager != (Object)null)
{
_worldChanged = true;
}
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;
private static GameDifficultySnapshot _gameSettings = GameDifficultySnapshot.Empty;
private static EffectiveMultipliers _effective = EffectiveMultipliers.None;
public static ScalingProfile Profile { get; private set; } = ScalingPresets.Standard();
public static bool IsActive
{
get
{
if (Profile != null)
{
return !Profile.AxesAreNoOp;
}
return false;
}
}
public static bool RespawnIsActive
{
get
{
if (Profile != null)
{
return !Profile.RespawnIsNoOp;
}
return false;
}
}
public static ProgressionSnapshot LastSnapshot => _lastSnapshot;
public static RespawnObservation Respawn { get; } = new RespawnObservation();
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 GameDifficultySnapshot GameSettings
{
get
{
if (Time.unscaledTime >= _nextRefreshTime)
{
Refresh(force: false);
}
return _gameSettings;
}
}
public static EffectiveMultipliers Effective
{
get
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
if (Time.unscaledTime >= _nextRefreshTime)
{
Refresh(force: false);
}
return _effective;
}
}
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()
{
ProgressionReader.Reset();
ForgetWorldState();
_nextRefreshTime = 0f;
}
private static void ForgetWorldState()
{
//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_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_002f: 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)
GameSettingsReader.Reset();
Respawn.Clear();
_current = EnemyMultipliers.None;
_gameSettings = GameDifficultySnapshot.Empty;
_effective = EffectiveMultipliers.None;
_lastSnapshot = new ProgressionSnapshot(0, 0);
}
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_0052: 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)
//IL_004c: 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)
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)
{
EnemyMultipliers val = ((EnemyMultipliers)(ref result)).Dampen(Profile.BossDampening);
result = ((EnemyMultipliers)(ref val)).ClampToCaps(Profile);
}
return result;
}
private static void Refresh(bool force)
{
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: 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_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: 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_0061: Unknown result type (might be due to invalid IL or missing references)
_nextRefreshTime = Time.unscaledTime + 2f;
try
{
ProgressionSnapshot lastSnapshot = ProgressionReader.Read();
if (ProgressionReader.ConsumeWorldChanged())
{
ForgetWorldState();
}
_lastSnapshot = lastSnapshot;
_gameSettings = GameSettingsReader.Read();
_current = (IsActive ? ScalingCalculator.Compute(Profile, _lastSnapshot) : EnemyMultipliers.None);
_effective = DifficultyCombiner.Combine(_current, _gameSettings);
}
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;
_effective = EffectiveMultipliers.None;
}
}
public static string DescribeCurrent()
{
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
if (!IsActive && !RespawnIsActive)
{
return "Enemy scaling: off (Standard)";
}
string value = (RespawnIsActive ? $" | respawn count x{Profile.PoiRespawnCount:0.00}, frequency x{Profile.PoiRespawnFrequency:0.00}" : string.Empty);
return $"{Profile.Name} | day {_lastSnapshot.DaysPassed}, {_lastSnapshot.VillagerCount} villagers | {Current}{value}";
}
}
}
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_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_009a: Expected O, but got Unknown
//IL_001f: 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_0028: 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_0052: 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)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)creature == (Object)null)
{
return;
}
bool isActive = ScalingState.IsActive;
bool needsHostileDataSheet = GameSettingsReader.NeedsHostileDataSheet;
if (!isActive && !needsHostileDataSheet)
{
return;
}
try
{
EnemyCategories category = EnemyClassifier.GetCategory(creature);
if (needsHostileDataSheet && IsHostile(category))
{
GameSettingsReader.ObserveHostileDataSheet(creature.dataSheet);
}
if (isActive && !AlreadyScaled.TryGetValue(creature, out var _))
{
EnemyMultipliers val = ScalingState.ForCategory(category);
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 IsHostile(EnemyCategories category)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Invalid comparison between Unknown and I4
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Invalid comparison between Unknown and I4
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Invalid comparison between Unknown and I4
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Invalid comparison between Unknown and I4
if ((int)category != 1 && (int)category != 2 && (int)category != 4)
{
return (int)category == 8;
}
return true;
}
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);
}
}
internal static class RespawnScaler
{
private const float MinimumIntervalFraction = 0.05f;
[ThreadStatic]
private static bool _insideComputeActualSize;
public static bool IsInsideComputeActualSize => _insideComputeActualSize;
public static void EnterComputeActualSize()
{
_insideComputeActualSize = true;
}
public static void LeaveComputeActualSize()
{
_insideComputeActualSize = false;
}
public static void ApplyIntervals(SpawnPopulation population)
{
float poiRespawnFrequency = ScalingState.Profile.PoiRespawnFrequency;
float respawnTargetTime = population._respawnTargetTime;
float spawnInterval = population._spawnInterval;
float num = ScalingCalculator.ScaleInterval(respawnTargetTime, poiRespawnFrequency, respawnTargetTime * 0.05f);
float spawnInterval2 = ScalingCalculator.ScaleInterval(spawnInterval, poiRespawnFrequency, spawnInterval * 0.05f);
population._respawnTargetTime = num;
population._spawnInterval = spawnInterval2;
ScalingState.Respawn.RecordInterval(respawnTargetTime, num);
}
}
[HarmonyPatch(typeof(SpawnPopulation), "Setup")]
internal static class PopulationSetupPatch
{
[HarmonyPostfix]
private static void Postfix(SpawnPopulation __instance)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
if (__instance == null)
{
return;
}
try
{
GameSettingsReader.ObservePopulationConfiguration(__instance.config);
if (ScalingState.RespawnIsActive)
{
RespawnScaler.ApplyIntervals(__instance);
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(37, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to adjust a respawn interval: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
log.LogError(val);
}
}
}
[HarmonyPatch(typeof(SpawnPopulation), "ComputeActualSize")]
internal static class PopulationSizePatch
{
[HarmonyPrefix]
private static void Prefix()
{
RespawnScaler.EnterComputeActualSize();
}
[HarmonyPostfix]
private static void Postfix(ref int __result)
{
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Expected O, but got Unknown
RespawnScaler.LeaveComputeActualSize();
if (!ScalingState.RespawnIsActive || __result <= 0)
{
return;
}
try
{
ScalingProfile profile = ScalingState.Profile;
int num = ScalingCalculator.ScalePopulationSize(__result, profile.PoiRespawnCount, profile.PoiPopulationCeiling);
ScalingState.Respawn.RecordSize(__result, num);
__result = num;
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(48, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to scale a point-of-interest population: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
log.LogError(val);
}
}
[HarmonyFinalizer]
private static void Finalizer()
{
RespawnScaler.LeaveComputeActualSize();
}
}
[HarmonyPatch(typeof(SpawnPopulation), "get_MaxPopulationSize")]
internal static class PopulationMaxSizePatch
{
[HarmonyPostfix]
private static void Postfix(ref int __result)
{
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Expected O, but got Unknown
if (RespawnScaler.IsInsideComputeActualSize || !ScalingState.RespawnIsActive || __result <= 0)
{
return;
}
try
{
ScalingProfile profile = ScalingState.Profile;
__result = ScalingCalculator.ScalePopulationSize(__result, profile.PoiRespawnCount, profile.PoiPopulationCeiling);
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(38, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to scale a population ceiling: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
log.LogError(val);
}
}
}
[HarmonyPatch(typeof(DenCustomizationData), "GetInitialActiveCount")]
internal static class DenInitialCountPatch
{
[HarmonyPostfix]
private static void Postfix(DenCustomizationData __instance, ref int __result)
{
DenScaler.ScaleActivationCount(__instance, ref __result);
}
}
[HarmonyPatch(typeof(DenCustomizationData), "GetCycleActivationCount")]
internal static class DenCycleCountPatch
{
[HarmonyPostfix]
private static void Postfix(DenCustomizationData __instance, ref int __result)
{
DenScaler.ScaleActivationCount(__instance, ref __result);
}
}
internal static class DenScaler
{
private const int HardDenCeiling = 40;
public static void ScaleActivationCount(DenCustomizationData selector, ref int count)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Expected O, but got Unknown
try
{
GameSettingsReader.ObserveDenCustomization(selector);
if (ScalingState.RespawnIsActive && count > 0)
{
count = ScalingCalculator.ScalePopulationSize(count, ScalingState.Profile.DenActivationCount, 40);
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(40, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to scale a den's creature count: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
log.LogError(val);
}
}
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
internal static class DenRevivalCooldownPatch
{
private const int MinimumCooldown = 1;
[HarmonyPrefix]
private static void Prefix(Den __instance, ref int __0)
{
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Expected O, but got Unknown
if (!ScalingState.RespawnIsActive || (Object)(object)__instance == (Object)null || __0 <= 0)
{
return;
}
try
{
if (__0 > __instance.ReviveCooldown)
{
int num = __0;
int num2 = (int)Math.Round(ScalingCalculator.ScaleInterval((float)num, ScalingState.Profile.DenRevivalFrequency, 1f), MidpointRounding.AwayFromZero);
if (num2 < 1)
{
num2 = 1;
}
ScalingState.Respawn.RecordDenCooldown(num, num2);
__0 = num2;
}
}
catch (Exception ex)
{
ManualLogSource log = Plugin.Log;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(43, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to adjust a den's revival cooldown: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
}
log.LogError(val);
}
}
}
[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<float> BossScaling;
public readonly ConfigEntry<float> PoiRespawnCount;
public readonly ConfigEntry<float> PoiRespawnFrequency;
public readonly ConfigEntry<float> DenActivationCount;
public readonly ConfigEntry<float> DenRevivalFrequency;
public readonly ConfigEntry<int> PoiPopulationCeiling;
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 bool IsSaving { get; private set; }
public ModSettings(ConfigFile config)
{
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Expected O, but got Unknown
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Expected O, but got Unknown
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_0116: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Expected O, but got Unknown
//IL_014c: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Expected O, but got Unknown
//IL_0177: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Expected O, but got Unknown
//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_01ca: Expected O, but got Unknown
//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
//IL_0204: Expected O, but got Unknown
//IL_023d: Unknown result type (might be due to invalid IL or missing references)
//IL_0247: Expected O, but got Unknown
//IL_0280: Unknown result type (might be due to invalid IL or missing references)
//IL_028a: Expected O, but got Unknown
//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
//IL_02cd: Expected O, but got Unknown
//IL_0306: Unknown result type (might be due to invalid IL or missing references)
//IL_0310: Expected O, but got Unknown
//IL_0349: Unknown result type (might be due to invalid IL or missing references)
//IL_0353: Expected O, but got Unknown
//IL_038b: Unknown result type (might be due to invalid IL or missing references)
//IL_0395: 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)IntRange(ControlRanges.DayStart), 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)IntRange(ControlRanges.VillagerStart), 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)FloatRange(ControlRanges.HealthPeak), 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)FloatRange(ControlRanges.DamagePeak), 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)FloatRange(ControlRanges.SpawnPeak), Array.Empty<object>()));
BossScaling = config.Bind<float>("3 - Custom curve", "BossScaling", 0.5f, new ConfigDescription("Share of the normal increase that bosses receive, applied on top of any preset.\n0.0 leaves bosses exactly as vanilla, 0.5 (the default) gives them half the bonus a regular enemy gets, and 1.0 makes them scale like everything else. Values above 1.0 make bosses scale harder than ordinary enemies.\nThe default is 0.5 because a boss carrying the full health multiplier stops being a fight and becomes a waiting game.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(ControlRanges.BossDampening.Min, ControlRanges.BossDampening.Max), Array.Empty<object>()));
PoiRespawnCount = config.Bind<float>("5 - Respawn", "PoiRespawnCount", 1f, new ConfigDescription("Multiplier on how many creatures a camp, cave or den population keeps alive - which is also how many come back when it refills.\n1.0 is vanilla. Applies whatever preset is selected.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(ControlRanges.PoiRespawnCount.Min, ControlRanges.PoiRespawnCount.Max), Array.Empty<object>()));
PoiRespawnFrequency = config.Bind<float>("5 - Respawn", "PoiRespawnFrequency", 1f, new ConfigDescription("Multiplier on how OFTEN a point of interest refills. Above 1.0 shortens the wait (2.0 means enemies return twice as often); below 1.0 lengthens it.\n1.0 is vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(ControlRanges.PoiRespawnFrequency.Min, ControlRanges.PoiRespawnFrequency.Max), Array.Empty<object>()));
DenActivationCount = config.Bind<float>("5 - Respawn", "DenActivationCount", 1f, new ConfigDescription("Multiplier on how many creatures a den has active at once and brings back each activation cycle. This is the den's own attached creatures, which the game counts separately from the population its spawners produce.\n1.0 is vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(ControlRanges.DenActivationCount.Min, ControlRanges.DenActivationCount.Max), Array.Empty<object>()));
DenRevivalFrequency = config.Bind<float>("5 - Respawn", "DenRevivalFrequency", 1f, new ConfigDescription("Multiplier on how quickly a den you have cleared comes back. Above 1.0 shortens the cooldown; below 1.0 lengthens it.\n1.0 is vanilla.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(ControlRanges.DenRevivalFrequency.Min, ControlRanges.DenRevivalFrequency.Max), Array.Empty<object>()));
PoiPopulationCeiling = config.Bind<int>("5 - Respawn", "PoiPopulationCeiling", 60, new ConfigDescription("Hard limit on one point of interest's population after the respawn count multiplier is applied. Exists to protect framerate: a large multiplier on a busy late-game map is the setting most likely to cost performance.", (AcceptableValueBase)(object)new AcceptableValueRange<int>((int)ControlRanges.PoiPopulationCeiling.Min, (int)ControlRanges.PoiPopulationCeiling.Max), 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.");
}
private static AcceptableValueRange<int> IntRange(SliderStep range)
{
//IL_0000: 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)
return new AcceptableValueRange<int>((int)range.Min, (int)range.Max);
}
private static AcceptableValueRange<float> FloatRange(SliderStep range)
{
//IL_0000: 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)
return new AcceptableValueRange<float>(range.Min, range.Max);
}
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_001c: Unknown result type (might be due to invalid IL or missing references)
ScalingProfile val = (((int)Preset.Value != 3) ? ScalingPresets.Get(Preset.Value) : BuildCustomProfile());
ApplyLayeredSettings(val);
return val;
}
private void ApplyLayeredSettings(ScalingProfile profile)
{
//IL_0002: 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)
profile.Categories = ReadCategories();
profile.BossDampening = BossScaling.Value;
profile.PoiRespawnCount = PoiRespawnCount.Value;
profile.PoiRespawnFrequency = PoiRespawnFrequency.Value;
profile.DenActivationCount = DenActivationCount.Value;
profile.DenRevivalFrequency = DenRevivalFrequency.Value;
profile.PoiPopulationCeiling = PoiPopulationCeiling.Value;
}
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_0148: 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),
ConcurrentEnemyCeiling = val.ConcurrentEnemyCeiling
};
}
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 Save(ScalingProfile profile)
{
IsSaving = true;
try
{
WriteSettings(profile);
}
finally
{
IsSaving = false;
}
}
private void WriteSettings(ScalingProfile profile)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
Preset.Value = IdentifyPreset(profile);
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;
BossScaling.Value = profile.BossDampening;
PoiRespawnCount.Value = profile.PoiRespawnCount;
PoiRespawnFrequency.Value = profile.PoiRespawnFrequency;
DenActivationCount.Value = profile.DenActivationCount;
DenRevivalFrequency.Value = profile.DenRevivalFrequency;
PoiPopulationCeiling.Value = profile.PoiPopulationCeiling;
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);
}
private static PresetId IdentifyPreset(ScalingProfile profile)
{
if (!MatchesPreset(profile, ScalingPresets.Standard()))
{
if (!MatchesPreset(profile, ScalingPresets.RisingTide()))
{
if (!MatchesPreset(profile, ScalingPresets.Ragnarok()))
{
return (PresetId)3;
}
return (PresetId)2;
}
return (PresetId)1;
}
return (PresetId)0;
}
private static bool MatchesPreset(ScalingProfile candidate, ScalingProfile preset)
{
//IL_000f: 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)
if (candidate.Enabled == preset.Enabled && candidate.Combine == preset.Combine && candidate.DayStart == preset.DayStart && candidate.DayFull == preset.DayFull && candidate.VillagerStart == preset.VillagerStart && candidate.VillagerFull == preset.VillagerFull && MatchesAxis(candidate.Health, preset.Health) && MatchesAxis(candidate.Damage, preset.Damage))
{
return MatchesAxis(candidate.SpawnCount, preset.SpawnCount);
}
return false;
}
private static bool MatchesAxis(ScalingAxis candidate, ScalingAxis preset)
{
if (Math.Abs(candidate.Peak - preset.Peak) < 0.005f && Math.Abs(candidate.Shape - preset.Shape) < 0.005f && Math.Abs(candidate.Overdrive - preset.Overdrive) < 0.005f)
{
return Math.Abs(candidate.Cap - preset.Cap) < 0.005f;
}
return false;
}
}
}