using 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 Enabled; internal static ConfigEntry SyncWithHost; internal static ConfigEntry Mode; internal static ConfigEntry IndoorFlatPerQuota; internal static ConfigEntry OutdoorFlatPerQuota; internal static ConfigEntry DaytimeFlatPerQuota; internal static ConfigEntry IndoorPercentPerQuota; internal static ConfigEntry OutdoorPercentPerQuota; internal static ConfigEntry DaytimePercentPerQuota; internal static ConfigEntry MaxIndoorBonus; internal static ConfigEntry MaxOutdoorBonus; internal static ConfigEntry MaxDaytimeBonus; internal static ConfigEntry GIMonitor; private static RuntimeSettings syncedHostSettings; internal static bool HasSyncedHostSettings => syncedHostSettings != null; internal static void Initialize(ConfigFile config) { Enabled = config.Bind("General", "Enabled", true, "Enables progressive enemy power scaling."); SyncWithHost = config.Bind("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("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("Flat Progression", "Indoor Power Per Quota", 1, "Indoor enemy power added per completed quota."); OutdoorFlatPerQuota = config.Bind("Flat Progression", "Outdoor Power Per Quota", 1, "Outdoor enemy power added per completed quota."); DaytimeFlatPerQuota = config.Bind("Flat Progression", "Daytime Power Per Quota", 1, "Daytime enemy power added per completed quota."); IndoorPercentPerQuota = config.Bind("Percentage Progression", "Indoor Percent Per Quota", 10f, "Percentage of the original indoor enemy power added per completed quota."); OutdoorPercentPerQuota = config.Bind("Percentage Progression", "Outdoor Percent Per Quota", 10f, "Percentage of the original outdoor enemy power added per completed quota."); DaytimePercentPerQuota = config.Bind("Percentage Progression", "Daytime Percent Per Quota", 10f, "Percentage of the original daytime enemy power added per completed quota."); MaxIndoorBonus = config.Bind("Limits", "Maximum Indoor Bonus", 0, "Maximum additional indoor enemy power. 0 = unlimited."); MaxOutdoorBonus = config.Bind("Limits", "Maximum Outdoor Bonus", 0, "Maximum additional outdoor enemy power. 0 = unlimited."); MaxDaytimeBonus = config.Bind("Limits", "Maximum Daytime Bonus", 0, "Maximum additional daytime enemy power. 0 = unlimited."); GIMonitor = config.Bind("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 Baselines = new Dictionary(); 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(((Component)instance.profitQuotaMonitorBGImage).gameObject, ((Component)instance.profitQuotaMonitorBGImage).transform.parent); ((Object)bmBackgroundObject).name = "BM_ProgressiveDifficulty_BG"; bmBackground = bmBackgroundObject.GetComponent(); ((Component)bmBackground).transform.localPosition = position + position2; ((Component)bmBackground).transform.localEulerAngles = rotation + rotation2; ((Behaviour)bmBackground).enabled = true; bmTextObject = Object.Instantiate(((Component)instance.profitQuotaMonitorText).gameObject, ((TMP_Text)instance.profitQuotaMonitorText).transform.parent); ((Object)bmTextObject).name = "BM_ProgressiveDifficulty_Text"; bmText = bmTextObject.GetComponent(); ((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(ref runtimeSettings.Enabled, default(ForPrimitives)); int mode = (int)runtimeSettings.Mode; ((FastBufferWriter)(ref val)).WriteValueSafe(ref mode, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref runtimeSettings.IndoorFlat, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref runtimeSettings.OutdoorFlat, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref runtimeSettings.DaytimeFlat, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref runtimeSettings.IndoorPercent, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref runtimeSettings.OutdoorPercent, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref runtimeSettings.DaytimePercent, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref runtimeSettings.MaxIndoorBonus, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref runtimeSettings.MaxOutdoorBonus, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref runtimeSettings.MaxDaytimeBonus, default(ForPrimitives)); mode = (int)runtimeSettings.Monitor; ((FastBufferWriter)(ref val)).WriteValueSafe(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(ref runtimeSettings.Enabled, default(ForPrimitives)); int mode = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref mode, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref runtimeSettings.IndoorFlat, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref runtimeSettings.OutdoorFlat, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref runtimeSettings.DaytimeFlat, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref runtimeSettings.IndoorPercent, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref runtimeSettings.OutdoorPercent, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref runtimeSettings.DaytimePercent, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref runtimeSettings.MaxIndoorBonus, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref runtimeSettings.MaxOutdoorBonus, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref runtimeSettings.MaxDaytimeBonus, default(ForPrimitives)); int monitor = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(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."); } } }