Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BM ProgressiveDifficulty v0.2.0
BM_ProgressiveDifficulty.dll
Decompiled 8 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using LethalConfig; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("BM_ProgressiveDifficulty")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BM_ProgressiveDifficulty")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("407238f6-9600-4456-9174-5c96a0db678a")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace BM_ProgressiveDifficulty; internal enum ProgressionMode { Flat, Percentage } internal enum GIMonitorSelection { Disabled, Monitor1, Monitor2, Monitor3, Monitor4, Monitor5, Monitor6, Monitor7, Monitor8, Monitor9, Monitor10, Monitor11, Monitor12, Monitor13, Monitor14 } internal sealed class RuntimeSettings { public bool Enabled; public ProgressionMode Mode; public int IndoorFlat; public int OutdoorFlat; public int DaytimeFlat; public float IndoorPercent; public float OutdoorPercent; public float DaytimePercent; public int MaxIndoorBonus; public int MaxOutdoorBonus; public int MaxDaytimeBonus; public GIMonitorSelection Monitor; } internal static class Configuration { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> SyncWithHost; internal static ConfigEntry<ProgressionMode> Mode; internal static ConfigEntry<int> IndoorFlatPerQuota; internal static ConfigEntry<int> OutdoorFlatPerQuota; internal static ConfigEntry<int> DaytimeFlatPerQuota; internal static ConfigEntry<float> IndoorPercentPerQuota; internal static ConfigEntry<float> OutdoorPercentPerQuota; internal static ConfigEntry<float> DaytimePercentPerQuota; internal static ConfigEntry<int> MaxIndoorBonus; internal static ConfigEntry<int> MaxOutdoorBonus; internal static ConfigEntry<int> MaxDaytimeBonus; internal static ConfigEntry<GIMonitorSelection> GIMonitor; private static RuntimeSettings syncedHostSettings; internal static bool HasSyncedHostSettings => syncedHostSettings != null; internal static void Initialize(ConfigFile config) { Enabled = config.Bind<bool>("General", "Enabled", true, "Enables progressive enemy power scaling."); SyncWithHost = config.Bind<bool>("General", "Sync With Host", true, "When enabled on a client, BM_ProgressiveDifficulty uses the host's runtime settings for this lobby. Your local config file is not overwritten."); Mode = config.Bind<ProgressionMode>("Progression", "Mode", ProgressionMode.Flat, "Flat adds a fixed amount per completed quota. Percentage adds a percentage of the moon's original enemy power per completed quota."); IndoorFlatPerQuota = config.Bind<int>("Flat Progression", "Indoor Power Per Quota", 1, "Indoor enemy power added per completed quota."); OutdoorFlatPerQuota = config.Bind<int>("Flat Progression", "Outdoor Power Per Quota", 1, "Outdoor enemy power added per completed quota."); DaytimeFlatPerQuota = config.Bind<int>("Flat Progression", "Daytime Power Per Quota", 1, "Daytime enemy power added per completed quota."); IndoorPercentPerQuota = config.Bind<float>("Percentage Progression", "Indoor Percent Per Quota", 10f, "Percentage of the original indoor enemy power added per completed quota."); OutdoorPercentPerQuota = config.Bind<float>("Percentage Progression", "Outdoor Percent Per Quota", 10f, "Percentage of the original outdoor enemy power added per completed quota."); DaytimePercentPerQuota = config.Bind<float>("Percentage Progression", "Daytime Percent Per Quota", 10f, "Percentage of the original daytime enemy power added per completed quota."); MaxIndoorBonus = config.Bind<int>("Limits", "Maximum Indoor Bonus", 0, "Maximum additional indoor enemy power. 0 = unlimited."); MaxOutdoorBonus = config.Bind<int>("Limits", "Maximum Outdoor Bonus", 0, "Maximum additional outdoor enemy power. 0 = unlimited."); MaxDaytimeBonus = config.Bind<int>("Limits", "Maximum Daytime Bonus", 0, "Maximum additional daytime enemy power. 0 = unlimited."); GIMonitor = config.Bind<GIMonitorSelection>("General Improvements", "Enemy Power Monitor", GIMonitorSelection.Monitor1, "General Improvements monitor position used for Enemy Power. Set the matching GI monitor to None."); LethalConfigManager.SetModDescription("Progressively increases moon enemy power after completed quotas and can display the values on a General Improvements ship monitor."); } internal static RuntimeSettings CaptureLocalSettings() { RuntimeSettings runtimeSettings = new RuntimeSettings(); runtimeSettings.Enabled = Enabled.Value; runtimeSettings.Mode = Mode.Value; runtimeSettings.IndoorFlat = IndoorFlatPerQuota.Value; runtimeSettings.OutdoorFlat = OutdoorFlatPerQuota.Value; runtimeSettings.DaytimeFlat = DaytimeFlatPerQuota.Value; runtimeSettings.IndoorPercent = IndoorPercentPerQuota.Value; runtimeSettings.OutdoorPercent = OutdoorPercentPerQuota.Value; runtimeSettings.DaytimePercent = DaytimePercentPerQuota.Value; runtimeSettings.MaxIndoorBonus = MaxIndoorBonus.Value; runtimeSettings.MaxOutdoorBonus = MaxOutdoorBonus.Value; runtimeSettings.MaxDaytimeBonus = MaxDaytimeBonus.Value; runtimeSettings.Monitor = GIMonitor.Value; return runtimeSettings; } internal static RuntimeSettings GetEffectiveSettings() { if (SyncWithHost.Value && syncedHostSettings != null) { return syncedHostSettings; } return CaptureLocalSettings(); } internal static void ApplyHostSettings(RuntimeSettings settings) { syncedHostSettings = settings; } internal static void ClearHostSettings() { syncedHostSettings = null; } } internal static class DifficultyManager { private sealed class LevelBaseline { public int Indoor; public int Outdoor; public int Daytime; } private static readonly Dictionary<SelectableLevel, LevelBaseline> Baselines = new Dictionary<SelectableLevel, LevelBaseline>(); internal static void Initialize() { Baselines.Clear(); } internal static void CaptureAllBaselines(StartOfRound round) { if ((Object)(object)round == (Object)null || round.levels == null) { return; } Baselines.Clear(); SelectableLevel[] levels = round.levels; foreach (SelectableLevel val in levels) { if (!((Object)(object)val == (Object)null)) { CaptureBaseline(val); } } Plugin.Log.LogInfo((object)("BM captured original enemy power for " + Baselines.Count + " moon(s).")); } private static LevelBaseline CaptureBaseline(SelectableLevel level) { if ((Object)(object)level == (Object)null) { return null; } LevelBaseline levelBaseline = new LevelBaseline(); levelBaseline.Indoor = level.maxEnemyPowerCount; levelBaseline.Outdoor = level.maxOutsideEnemyPowerCount; levelBaseline.Daytime = level.maxDaytimeEnemyPowerCount; Baselines[level] = levelBaseline; return levelBaseline; } private static LevelBaseline GetOrCreateBaseline(SelectableLevel level) { if ((Object)(object)level == (Object)null) { return null; } if (Baselines.TryGetValue(level, out var value)) { return value; } return CaptureBaseline(level); } internal static int GetCompletedQuotas() { if ((Object)(object)TimeOfDay.Instance == (Object)null) { return 0; } return Mathf.Max(0, TimeOfDay.Instance.timesFulfilledQuota); } internal static void ApplyToAllLevels(StartOfRound round, int completedQuotas) { if ((Object)(object)round == (Object)null || round.levels == null) { return; } SelectableLevel[] levels = round.levels; foreach (SelectableLevel val in levels) { if (!((Object)(object)val == (Object)null)) { ApplyToLevelInternal(val, completedQuotas); } } Plugin.Log.LogInfo((object)("BM applied progressive difficulty to all moons. Completed quotas=" + completedQuotas)); } internal static void ApplyToLevel(SelectableLevel level, int completedQuotas) { ApplyToLevelInternal(level, completedQuotas); } private static void ApplyToLevelInternal(SelectableLevel level, int completedQuotas) { if (!((Object)(object)level == (Object)null)) { LevelBaseline orCreateBaseline = GetOrCreateBaseline(level); if (orCreateBaseline != null) { RuntimeSettings effectiveSettings = Configuration.GetEffectiveSettings(); level.maxEnemyPowerCount = CalculatePower(orCreateBaseline.Indoor, completedQuotas, effectiveSettings.IndoorFlat, effectiveSettings.IndoorPercent, effectiveSettings.MaxIndoorBonus, effectiveSettings.Mode); level.maxOutsideEnemyPowerCount = CalculatePower(orCreateBaseline.Outdoor, completedQuotas, effectiveSettings.OutdoorFlat, effectiveSettings.OutdoorPercent, effectiveSettings.MaxOutdoorBonus, effectiveSettings.Mode); level.maxDaytimeEnemyPowerCount = CalculatePower(orCreateBaseline.Daytime, completedQuotas, effectiveSettings.DaytimeFlat, effectiveSettings.DaytimePercent, effectiveSettings.MaxDaytimeBonus, effectiveSettings.Mode); } } } internal static void RestoreAllBaselines(StartOfRound round) { if ((Object)(object)round == (Object)null || round.levels == null) { return; } SelectableLevel[] levels = round.levels; foreach (SelectableLevel val in levels) { if (!((Object)(object)val == (Object)null) && Baselines.TryGetValue(val, out var value)) { val.maxEnemyPowerCount = value.Indoor; val.maxOutsideEnemyPowerCount = value.Outdoor; val.maxDaytimeEnemyPowerCount = value.Daytime; } } } internal static bool TryGetDisplayValues(SelectableLevel level, int completedQuotas, out int originalIndoor, out int currentIndoor, out int originalOutdoor, out int currentOutdoor, out int originalDaytime, out int currentDaytime) { originalIndoor = 0; currentIndoor = 0; originalOutdoor = 0; currentOutdoor = 0; originalDaytime = 0; currentDaytime = 0; if ((Object)(object)level == (Object)null) { return false; } LevelBaseline orCreateBaseline = GetOrCreateBaseline(level); if (orCreateBaseline == null) { return false; } RuntimeSettings effectiveSettings = Configuration.GetEffectiveSettings(); originalIndoor = orCreateBaseline.Indoor; originalOutdoor = orCreateBaseline.Outdoor; originalDaytime = orCreateBaseline.Daytime; currentIndoor = CalculatePower(orCreateBaseline.Indoor, completedQuotas, effectiveSettings.IndoorFlat, effectiveSettings.IndoorPercent, effectiveSettings.MaxIndoorBonus, effectiveSettings.Mode); currentOutdoor = CalculatePower(orCreateBaseline.Outdoor, completedQuotas, effectiveSettings.OutdoorFlat, effectiveSettings.OutdoorPercent, effectiveSettings.MaxOutdoorBonus, effectiveSettings.Mode); currentDaytime = CalculatePower(orCreateBaseline.Daytime, completedQuotas, effectiveSettings.DaytimeFlat, effectiveSettings.DaytimePercent, effectiveSettings.MaxDaytimeBonus, effectiveSettings.Mode); return true; } private static int CalculatePower(int originalPower, int completedQuotas, int flatPerQuota, float percentPerQuota, int maximumBonus, ProgressionMode mode) { if (completedQuotas <= 0) { return originalPower; } int num2; if (mode == ProgressionMode.Percentage) { float num = percentPerQuota * (float)completedQuotas; num2 = Mathf.RoundToInt((float)originalPower * num / 100f); } else { num2 = flatPerQuota * completedQuotas; } if (maximumBonus > 0) { num2 = Mathf.Min(num2, maximumBonus); } return originalPower + num2; } } internal static class GeneralImprovementsCompat { private const string GIGuid = "ShaosilGaming.GeneralImprovements"; private static bool giInstalled; private static Assembly giAssembly; private static Type giPluginType; private static Type monitorsApiType; private static PropertyInfo useBetterMonitorsProperty; private static PropertyInfo addMoreBetterMonitorsProperty; private static PropertyInfo shipMonitorAssignmentsProperty; private static MethodInfo getMonitorAtIndexMethod; private static object betterMonitorInfo; private static MethodInfo betterQueueRenderMethod; private static TextMeshProUGUI bmText; private static Image bmBackground; private static GameObject bmTextObject; private static GameObject bmBackgroundObject; private static int activeMonitorIndex = -1; private static bool usingBetterMonitor; private static string lastDisplayText = "ENEMY POWER"; internal static void Initialize() { giInstalled = Chainloader.PluginInfos.ContainsKey("ShaosilGaming.GeneralImprovements"); if (!giInstalled) { Plugin.Log.LogInfo((object)"General Improvements not detected."); return; } try { object instance = Chainloader.PluginInfos["ShaosilGaming.GeneralImprovements"].Instance; if (instance != null) { giAssembly = instance.GetType().Assembly; giPluginType = instance.GetType(); monitorsApiType = giAssembly.GetType("GeneralImprovements.API.MonitorsAPI"); useBetterMonitorsProperty = giPluginType.GetProperty("UseBetterMonitors", BindingFlags.Static | BindingFlags.Public); addMoreBetterMonitorsProperty = giPluginType.GetProperty("AddMoreBetterMonitors", BindingFlags.Static | BindingFlags.Public); shipMonitorAssignmentsProperty = giPluginType.GetProperty("ShipMonitorAssignments", BindingFlags.Static | BindingFlags.Public); if (monitorsApiType != null) { getMonitorAtIndexMethod = monitorsApiType.GetMethod("GetMonitorAtIndex", BindingFlags.Static | BindingFlags.Public); } Plugin.Log.LogInfo((object)"General Improvements compatibility initialized."); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed initializing GI compatibility: " + ex.Message)); } } internal static bool TryCreateMonitor() { RuntimeSettings effectiveSettings = Configuration.GetEffectiveSettings(); int monitor = (int)effectiveSettings.Monitor; if (monitor <= 0) { DestroyMonitor(); return false; } int num = monitor - 1; if (activeMonitorIndex == num && (Object)(object)bmText != (Object)null) { return true; } DestroyMonitor(); if (!giInstalled) { Plugin.Log.LogWarning((object)"Enemy Power Monitor requires General Improvements."); return false; } if (!IsGIPositionFree(num)) { string gIAssignmentName = GetGIAssignmentName(num); Plugin.Log.LogWarning((object)("BM Enemy Power wants Monitor " + monitor + ", but General Improvements has '" + gIAssignmentName + "' assigned there. Set GI ShipMonitor" + monitor + " to None.")); return false; } if (IsBetterMonitorsEnabled()) { return TryCreateBetterMonitor(num); } return TryCreateOldStyleMonitor(num); } private static bool TryCreateBetterMonitor(int monitorIndex) { //IL_01f8: Unknown result type (might be due to invalid IL or missing references) try { int num = (IsAddMoreBetterMonitorsEnabled() ? 14 : 9); if (monitorIndex < 0 || monitorIndex >= num) { Plugin.Log.LogWarning((object)("GI Better Monitors currently exposes " + num + " monitor positions. Monitor " + (monitorIndex + 1) + " is not available.")); return false; } if (getMonitorAtIndexMethod == null) { Plugin.Log.LogWarning((object)"GI MonitorsAPI.GetMonitorAtIndex was not found."); return false; } object obj = getMonitorAtIndexMethod.Invoke(null, new object[1] { monitorIndex }); if (obj == null) { Plugin.Log.LogDebug((object)("GI Better Monitor " + (monitorIndex + 1) + " is not initialized yet.")); return false; } Type type = obj.GetType(); PropertyInfo property = type.GetProperty("TextCanvas", BindingFlags.Instance | BindingFlags.Public); if (property == null) { return false; } object? value = property.GetValue(obj, null); bmText = (TextMeshProUGUI)((value is TextMeshProUGUI) ? value : null); if ((Object)(object)bmText == (Object)null) { Plugin.Log.LogWarning((object)("GI Monitor " + (monitorIndex + 1) + " does not have a text canvas.")); return false; } betterQueueRenderMethod = type.GetMethod("QueueRender", BindingFlags.Instance | BindingFlags.Public); betterMonitorInfo = obj; usingBetterMonitor = true; activeMonitorIndex = monitorIndex; ((TMP_Text)bmText).enableWordWrapping = false; ((TMP_Text)bmText).enableAutoSizing = true; ((TMP_Text)bmText).fontSizeMin = 8f; ((TMP_Text)bmText).fontSizeMax = 26f; ((TMP_Text)bmText).alignment = (TextAlignmentOptions)514; ((TMP_Text)bmText).margin = new Vector4(8f, 6f, 8f, 6f); ((TMP_Text)bmText).lineSpacing = -4f; Plugin.Log.LogWarning((object)("### BM BETTER MONITOR " + (monitorIndex + 1) + " ACQUIRED ###")); SetText(lastDisplayText); return true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not acquire GI Better Monitor: " + ex.Message)); return false; } } private static bool TryCreateOldStyleMonitor(int monitorIndex) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) if (monitorIndex < 0 || monitorIndex >= 8) { Plugin.Log.LogWarning((object)"Old-style General Improvements monitors only support BM positions 1-8. Use Better Monitors for positions 9-14."); return false; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.profitQuotaMonitorText == (Object)null || (Object)(object)instance.profitQuotaMonitorBGImage == (Object)null) { return false; } Vector3 position = ((Component)instance.profitQuotaMonitorBGImage).transform.localPosition; Vector3 rotation = ((Component)instance.profitQuotaMonitorBGImage).transform.localEulerAngles; TryGetGIOldMonitorBase(ref position, ref rotation); GetOldMonitorOffset(monitorIndex, out var position2, out var rotation2); bmBackgroundObject = Object.Instantiate<GameObject>(((Component)instance.profitQuotaMonitorBGImage).gameObject, ((Component)instance.profitQuotaMonitorBGImage).transform.parent); ((Object)bmBackgroundObject).name = "BM_ProgressiveDifficulty_BG"; bmBackground = bmBackgroundObject.GetComponent<Image>(); ((Component)bmBackground).transform.localPosition = position + position2; ((Component)bmBackground).transform.localEulerAngles = rotation + rotation2; ((Behaviour)bmBackground).enabled = true; bmTextObject = Object.Instantiate<GameObject>(((Component)instance.profitQuotaMonitorText).gameObject, ((TMP_Text)instance.profitQuotaMonitorText).transform.parent); ((Object)bmTextObject).name = "BM_ProgressiveDifficulty_Text"; bmText = bmTextObject.GetComponent<TextMeshProUGUI>(); ((TMP_Text)bmText).transform.localPosition = position + position2 + new Vector3(0f, 0f, -1f); ((TMP_Text)bmText).transform.localEulerAngles = rotation + rotation2 + new Vector3(1f, 0f, 0f); float fontSize = ((TMP_Text)instance.profitQuotaMonitorText).fontSize; ((TMP_Text)bmText).alignment = (TextAlignmentOptions)514; ((TMP_Text)bmText).enableWordWrapping = false; ((TMP_Text)bmText).enableAutoSizing = false; ((TMP_Text)bmText).fontSize = Mathf.Max(8f, fontSize * 0.62f); ((TMP_Text)bmText).lineSpacing = -5f; ((TMP_Text)bmText).characterSpacing = 0f; ((TMP_Text)bmText).wordSpacing = 0f; ((TMP_Text)bmText).margin = new Vector4(10f, 5f, 10f, 5f); ((Behaviour)bmText).enabled = true; usingBetterMonitor = false; activeMonitorIndex = monitorIndex; SetText(lastDisplayText); Plugin.Log.LogWarning((object)("### BM OLD-STYLE MONITOR " + (monitorIndex + 1) + " CREATED ###")); return true; } internal static void UpdateDisplay(SelectableLevel level, int completedQuotas, int originalIndoor, int currentIndoor, int originalOutdoor, int currentOutdoor, int originalDaytime, int currentDaytime) { string text = "ENEMY POWER\n\nIN " + originalIndoor + " > " + currentIndoor + "\nOUT " + originalOutdoor + " > " + currentOutdoor + "\nDAY " + originalDaytime + " > " + currentDaytime; SetText(text); if ((Object)(object)level != (Object)null) { Plugin.Log.LogInfo((object)("BM Enemy Power display updated: " + level.PlanetName + " | quota=" + completedQuotas)); } } internal static void SetText(string text) { lastDisplayText = text ?? string.Empty; if ((Object)(object)bmText == (Object)null) { return; } if (usingBetterMonitor && betterMonitorInfo != null && betterQueueRenderMethod != null) { try { betterQueueRenderMethod.Invoke(betterMonitorInfo, new object[1] { lastDisplayText }); return; } catch (Exception ex) { Plugin.Log.LogWarning((object)("GI Better Monitor QueueRender failed: " + ex.Message)); } } ((TMP_Text)bmText).text = lastDisplayText; } internal static void RebuildMonitor() { DestroyMonitor(); TryCreateMonitor(); if ((Object)(object)StartOfRound.Instance != (Object)null) { Patches.RefreshCurrentDisplay(StartOfRound.Instance); } } internal static void DestroyMonitor() { if (!usingBetterMonitor) { if ((Object)(object)bmTextObject != (Object)null) { Object.Destroy((Object)(object)bmTextObject); } if ((Object)(object)bmBackgroundObject != (Object)null) { Object.Destroy((Object)(object)bmBackgroundObject); } } bmText = null; bmBackground = null; bmTextObject = null; bmBackgroundObject = null; betterMonitorInfo = null; betterQueueRenderMethod = null; activeMonitorIndex = -1; usingBetterMonitor = false; } private static bool IsBetterMonitorsEnabled() { return GetGIBoolConfigValue(useBetterMonitorsProperty); } private static bool IsAddMoreBetterMonitorsEnabled() { return GetGIBoolConfigValue(addMoreBetterMonitorsProperty); } private static bool GetGIBoolConfigValue(PropertyInfo property) { if (property == null) { return false; } try { object value = property.GetValue(null, null); if (value == null) { return false; } PropertyInfo property2 = value.GetType().GetProperty("Value"); if (property2 == null) { return false; } if (property2.GetValue(value, null) is bool result) { return result; } } catch { } return false; } private static bool IsGIPositionFree(int monitorIndex) { string gIAssignmentName = GetGIAssignmentName(monitorIndex); return string.IsNullOrEmpty(gIAssignmentName) || gIAssignmentName.Equals("None", StringComparison.OrdinalIgnoreCase); } private static string GetGIAssignmentName(int monitorIndex) { if (shipMonitorAssignmentsProperty == null) { return null; } try { if (!(shipMonitorAssignmentsProperty.GetValue(null, null) is Array array) || monitorIndex < 0 || monitorIndex >= array.Length) { return null; } object value = array.GetValue(monitorIndex); if (value == null) { return null; } PropertyInfo property = value.GetType().GetProperty("Value"); if (property == null) { return null; } return property.GetValue(value, null)?.ToString(); } catch { return null; } } private static void TryGetGIOldMonitorBase(ref Vector3 position, ref Vector3 rotation) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) if (giAssembly == null) { return; } try { Type type = giAssembly.GetType("GeneralImprovements.Utilities.MonitorsHelper"); if (type == null) { return; } FieldInfo field = type.GetField("_originalProfitQuotaLocation", BindingFlags.Static | BindingFlags.NonPublic); FieldInfo field2 = type.GetField("_originalProfitQuotaRotation", BindingFlags.Static | BindingFlags.NonPublic); if (field != null) { Vector3 val = (Vector3)field.GetValue(null); if (val != Vector3.zero) { position = val; } } if (field2 != null) { Vector3 val2 = (Vector3)field2.GetValue(null); if (val2 != Vector3.zero) { rotation = val2; } } } catch { } } private static void GetOldMonitorOffset(int index, out Vector3 position, out Vector3 rotation) { //IL_0040: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0098: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: 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) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) switch (index) { case 0: position = new Vector3(0f, 465f, -22f); rotation = new Vector3(-18f, 0f, 0f); break; case 1: position = new Vector3(470f, 465f, -22f); rotation = new Vector3(-18f, 0f, 0f); break; case 2: position = new Vector3(970f, 485f, -128f); rotation = new Vector3(-18f, 25f, 5f); break; case 3: position = new Vector3(1390f, 525f, -329f); rotation = new Vector3(-18f, 25f, 5f); break; case 4: position = Vector3.zero; rotation = Vector3.zero; break; case 5: position = new Vector3(470f, 0f, 0f); rotation = Vector3.zero; break; case 6: position = new Vector3(1025f, 30f, -115f); rotation = new Vector3(-1f, 25f, 5f); break; case 7: position = new Vector3(1445f, 72f, -320f); rotation = new Vector3(-1f, 27f, 5f); break; default: position = Vector3.zero; rotation = Vector3.zero; break; } } } internal static class NetworkSync { private const string RequestMessage = "BM_PD.Settings.Request"; private const string SettingsMessage = "BM_PD.Settings.Response"; private static CustomMessagingManager registeredManager; private static bool receivedHostSettings; internal static void BeginSession(StartOfRound round) { Configuration.ClearHostSettings(); receivedHostSettings = false; RegisterHandlers(); NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsListening) { if (singleton.IsServer) { Plugin.Log.LogInfo((object)"BM host settings are authoritative."); } else if (!Configuration.SyncWithHost.Value) { Plugin.Log.LogInfo((object)"BM Sync With Host is disabled locally."); } else if ((Object)(object)round != (Object)null) { ((MonoBehaviour)round).StartCoroutine(RequestSettingsLoop()); } } } private static void RegisterHandlers() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null)) { CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager != null && registeredManager != customMessagingManager) { registeredManager = customMessagingManager; TryUnregister(customMessagingManager, "BM_PD.Settings.Request"); TryUnregister(customMessagingManager, "BM_PD.Settings.Response"); customMessagingManager.RegisterNamedMessageHandler("BM_PD.Settings.Request", new HandleNamedMessageDelegate(HandleRequest)); customMessagingManager.RegisterNamedMessageHandler("BM_PD.Settings.Response", new HandleNamedMessageDelegate(HandleSettings)); Plugin.Log.LogInfo((object)"BM network sync handlers registered."); } } } private static void TryUnregister(CustomMessagingManager manager, string name) { try { manager.UnregisterNamedMessageHandler(name); } catch { } } private static IEnumerator RequestSettingsLoop() { yield return (object)new WaitForSecondsRealtime(1f); for (int attempt = 0; attempt < 5; attempt++) { if (receivedHostSettings) { yield break; } SendSettingsRequest(); yield return (object)new WaitForSecondsRealtime(1f); } if (!receivedHostSettings) { Plugin.Log.LogWarning((object)"BM did not receive settings from host. Using local settings."); } } private unsafe static void SendSettingsRequest() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) RegisterHandlers(); NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsListening && !singleton.IsServer) { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); try { singleton.CustomMessagingManager.SendNamedMessage("BM_PD.Settings.Request", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } Plugin.Log.LogDebug((object)"Requested BM settings from host."); } } private static void HandleRequest(ulong senderClientId, FastBufferReader reader) { NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsServer) { SendSettingsToClient(senderClientId); } } private unsafe static void SendSettingsToClient(ulong clientId) { //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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsServer) { RuntimeSettings runtimeSettings = Configuration.CaptureLocalSettings(); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(128, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref runtimeSettings.Enabled, default(ForPrimitives)); int mode = (int)runtimeSettings.Mode; ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref mode, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref runtimeSettings.IndoorFlat, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref runtimeSettings.OutdoorFlat, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref runtimeSettings.DaytimeFlat, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref runtimeSettings.IndoorPercent, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref runtimeSettings.OutdoorPercent, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref runtimeSettings.DaytimePercent, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref runtimeSettings.MaxIndoorBonus, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref runtimeSettings.MaxOutdoorBonus, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref runtimeSettings.MaxDaytimeBonus, default(ForPrimitives)); mode = (int)runtimeSettings.Monitor; ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref mode, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("BM_PD.Settings.Response", clientId, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } Plugin.Log.LogInfo((object)("Sent BM settings to client " + clientId + ".")); } } private static void HandleSettings(ulong senderClientId, FastBufferReader reader) { //IL_005f: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0091: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && !singleton.IsServer && senderClientId == 0 && Configuration.SyncWithHost.Value) { RuntimeSettings runtimeSettings = new RuntimeSettings(); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref runtimeSettings.Enabled, default(ForPrimitives)); int mode = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref mode, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref runtimeSettings.IndoorFlat, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref runtimeSettings.OutdoorFlat, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref runtimeSettings.DaytimeFlat, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref runtimeSettings.IndoorPercent, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref runtimeSettings.OutdoorPercent, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref runtimeSettings.DaytimePercent, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref runtimeSettings.MaxIndoorBonus, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref runtimeSettings.MaxOutdoorBonus, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref runtimeSettings.MaxDaytimeBonus, default(ForPrimitives)); int monitor = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref monitor, default(ForPrimitives)); runtimeSettings.Mode = (ProgressionMode)mode; runtimeSettings.Monitor = (GIMonitorSelection)monitor; Configuration.ApplyHostSettings(runtimeSettings); receivedHostSettings = true; Plugin.Log.LogWarning((object)"### BM SETTINGS SYNCED FROM HOST ###"); GeneralImprovementsCompat.RebuildMonitor(); StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null) { Patches.RefreshCurrentDisplay(instance); } } } } internal static class Patches { internal static void RefreshCurrentDisplay(StartOfRound round) { if ((Object)(object)round == (Object)null) { return; } SelectableLevel currentLevel = round.currentLevel; if ((Object)(object)currentLevel == (Object)null) { GeneralImprovementsCompat.SetText("ENEMY POWER\n\nNO MOON\nDATA"); return; } int completedQuotas = DifficultyManager.GetCompletedQuotas(); if (DifficultyManager.TryGetDisplayValues(currentLevel, completedQuotas, out var originalIndoor, out var currentIndoor, out var originalOutdoor, out var currentOutdoor, out var originalDaytime, out var currentDaytime)) { RuntimeSettings effectiveSettings = Configuration.GetEffectiveSettings(); if (!effectiveSettings.Enabled) { currentIndoor = originalIndoor; currentOutdoor = originalOutdoor; currentDaytime = originalDaytime; } GeneralImprovementsCompat.UpdateDisplay(currentLevel, completedQuotas, originalIndoor, currentIndoor, originalOutdoor, currentOutdoor, originalDaytime, currentDaytime); Plugin.Log.LogInfo((object)("BM display refreshed for " + currentLevel.PlanetName + ". Completed quotas=" + completedQuotas)); } } internal static void ApplyCurrentDifficulty(StartOfRound round) { if ((Object)(object)round == (Object)null) { return; } NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton != (Object)null) || !singleton.IsListening || singleton.IsServer) { RuntimeSettings effectiveSettings = Configuration.GetEffectiveSettings(); if (!effectiveSettings.Enabled) { DifficultyManager.RestoreAllBaselines(round); return; } int completedQuotas = DifficultyManager.GetCompletedQuotas(); DifficultyManager.ApplyToAllLevels(round, completedQuotas); } } } [HarmonyPatch(typeof(StartOfRound), "Start")] internal static class StartOfRoundStartPatch { [HarmonyPostfix] private static void Postfix(StartOfRound __instance) { Plugin.Log.LogWarning((object)"### BM STARTOFROUND START POSTFIX HIT ###"); if (!((Object)(object)__instance == (Object)null)) { DifficultyManager.CaptureAllBaselines(__instance); Plugin.Log.LogWarning((object)"### BM BASELINES CAPTURED ###"); NetworkSync.BeginSession(__instance); Patches.ApplyCurrentDifficulty(__instance); bool flag = GeneralImprovementsCompat.TryCreateMonitor(); Plugin.Log.LogWarning((object)(flag ? "### BM MONITOR CREATED ###" : "### BM MONITOR NOT READY ###")); Patches.RefreshCurrentDisplay(__instance); } } } [HarmonyPatch(typeof(StartOfRound), "ChangeLevel", new Type[] { typeof(int) })] internal static class StartOfRoundChangeLevelPatch { [HarmonyPostfix] private static void Postfix(StartOfRound __instance, int levelID) { Plugin.Log.LogWarning((object)("### BM CHANGELEVEL POSTFIX HIT ### levelID=" + levelID)); if (!((Object)(object)__instance == (Object)null)) { GeneralImprovementsCompat.TryCreateMonitor(); Patches.RefreshCurrentDisplay(__instance); } } } [HarmonyPatch(typeof(TimeOfDay), "SetNewProfitQuota")] internal static class TimeOfDaySetNewProfitQuotaPatch { [HarmonyPostfix] private static void Postfix() { Plugin.Log.LogWarning((object)"### BM NEW PROFIT QUOTA POSTFIX HIT ###"); StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance == (Object)null)) { Patches.ApplyCurrentDifficulty(instance); Patches.RefreshCurrentDisplay(instance); } } } [HarmonyPatch(typeof(RoundManager), "LoadNewLevel", new Type[] { typeof(int), typeof(SelectableLevel) })] internal static class RoundManagerLoadNewLevelPatch { [HarmonyPrefix] private static void Prefix(int randomSeed, SelectableLevel newLevel) { Plugin.Log.LogWarning((object)"### BM LOADNEWLEVEL PREFIX HIT ###"); if ((Object)(object)newLevel == (Object)null) { return; } NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton != (Object)null) || !singleton.IsListening || singleton.IsServer) { RuntimeSettings effectiveSettings = Configuration.GetEffectiveSettings(); if (effectiveSettings.Enabled) { int completedQuotas = DifficultyManager.GetCompletedQuotas(); DifficultyManager.ApplyToLevel(newLevel, completedQuotas); Plugin.Log.LogInfo((object)("BM gameplay difficulty applied to " + newLevel.PlanetName + " before level loading.")); } } } } [BepInPlugin("com.brox.BM_ProgressiveDifficulty", "BM_ProgressiveDifficulty", "0.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string ModGuid = "com.brox.BM_ProgressiveDifficulty"; public const string ModName = "BM_ProgressiveDifficulty"; public const string ModVersion = "0.2.0"; internal static ManualLogSource Log; internal static ConfigFile PluginConfig; private static Harmony harmony; private static bool initialized; private void Awake() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown if (!initialized) { initialized = true; Log = ((BaseUnityPlugin)this).Logger; PluginConfig = ((BaseUnityPlugin)this).Config; Log.LogInfo((object)"BM_ProgressiveDifficulty v0.2.0 initializing..."); Configuration.Initialize(PluginConfig); DifficultyManager.Initialize(); GeneralImprovementsCompat.Initialize(); harmony = new Harmony("com.brox.BM_ProgressiveDifficulty"); harmony.PatchAll(typeof(Plugin).Assembly); Log.LogWarning((object)"### BM HARMONY PATCHES INSTALLED ###"); Log.LogInfo((object)"BM_ProgressiveDifficulty loaded."); } } }