Decompiled source of DarkFogAwakening v1.0.0

BepInEx/plugins/DarkFogAwakening/DarkFogAwakening.dll

Decompiled 13 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("DarkFogAwakening")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e311995cd5b2f17f628dc506198bfef05d86e80b")]
[assembly: AssemblyProduct("DarkFogAwakening")]
[assembly: AssemblyTitle("DarkFogAwakening")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DarkFogAwakening
{
	internal static class DarkFogAwakener
	{
		private static bool _awakened;

		private const BindingFlags ALL_INSTANCE = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly FieldInfo? _spaceSectorIsCombatMode = typeof(SpaceSector).GetField("isCombatMode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly MethodInfo? _tryCreateNewHive = typeof(SpaceSector).GetMethod("TryCreateNewHive", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(StarData) }, null);

		private static readonly string[] InitMethodNames = new string[6] { "InitForNewGame", "NewGame", "Init", "GameInit", "InitNewGame", "LoadPattern" };

		internal static bool HasAwakened => _awakened;

		internal static void Awaken()
		{
			if (_awakened)
			{
				return;
			}
			_awakened = true;
			GameData data = GameMain.data;
			if (data == null)
			{
				Plugin.Log.LogError((object)"[DarkFogAwakener] GameMain.data is null — cannot awaken.");
				return;
			}
			Plugin.Log.LogInfo((object)"[DarkFogAwakener] Awakening the Dark Fog…");
			SetBoolField(data.gameDesc, "isPeaceMode", value: false);
			SetBoolField(data.spaceSector, "isCombatMode", value: true);
			SetCombatSettingsDefaults(data.gameDesc);
			SeedHives(data, GetColonisedStarIds(data));
			int num = 0;
			PlanetFactory[] factories = data.factories;
			foreach (PlanetFactory val in factories)
			{
				if (val != null)
				{
					if (IsPlanetBuiltOn(val))
					{
						num++;
					}
					else
					{
						TryInvokeInit(val.enemySystem, "ground-enemy system");
					}
				}
			}
			Plugin.Log.LogInfo((object)("[DarkFogAwakener] The Dark Fog has awakened. " + $"({num} planet(s) protected from ground spawns.)"));
		}

		internal static void ResetOnLoad()
		{
			GameData data = GameMain.data;
			if (data == null)
			{
				_awakened = false;
			}
			else
			{
				_awakened = _spaceSectorIsCombatMode != null && (bool)(_spaceSectorIsCombatMode.GetValue(data.spaceSector) ?? ((object)false));
			}
		}

		private static void SetCombatSettingsDefaults(GameDesc gameDesc)
		{
			FieldInfo field = typeof(GameDesc).GetField("combatSettings", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				Plugin.Log.LogWarning((object)"[DarkFogAwakener] combatSettings field not found on GameDesc.");
				return;
			}
			object value = field.GetValue(gameDesc);
			Type type = value.GetType();
			float value2 = Plugin.Aggressiveness.Value;
			string[] array = new string[9] { "aggressiveness", "initialLevel", "initialGrowth", "initialColonize", "maxDensity", "growthSpeedFactor", "powerThreatFactor", "battleThreatFactor", "battleExpFactor" };
			foreach (string name in array)
			{
				FieldInfo field2 = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field2?.FieldType != typeof(float)))
				{
					float num = (float)field2.GetValue(value);
					field2.SetValue(value, ((num == 0f) ? 1f : num) * value2);
				}
			}
			field.SetValue(gameDesc, value);
			Plugin.Log.LogInfo((object)$"[DarkFogAwakener] CombatSettings set with aggressiveness x{value2:F1}.");
		}

		private static void SeedHives(GameData game, HashSet<int> colonisedStarIds)
		{
			if (_tryCreateNewHive == null)
			{
				Plugin.Log.LogWarning((object)"[DarkFogAwakener] TryCreateNewHive(StarData) not found on SpaceSector.");
				return;
			}
			int value = Plugin.HiveCount.Value;
			List<(StarData, double)> list = new List<(StarData, double)>();
			StarData[] stars = game.galaxy.stars;
			foreach (StarData val in stars)
			{
				if (val != null && !colonisedStarIds.Contains(val.id))
				{
					double item = val.position.x * val.position.x + val.position.y * val.position.y + val.position.z * val.position.z;
					list.Add((val, item));
				}
			}
			list.Sort(((StarData star, double distSq) a, (StarData star, double distSq) b) => b.distSq.CompareTo(a.distSq));
			MethodInfo methodInfo = null;
			MethodInfo methodInfo2 = null;
			int num = 0;
			for (int j = 0; j < list.Count; j++)
			{
				if (num >= value)
				{
					break;
				}
				(StarData, double) tuple = list[j];
				StarData item2 = tuple.Item1;
				double item3 = tuple.Item2;
				object obj = _tryCreateNewHive.Invoke(game.spaceSector, new object[1] { item2 });
				if (obj != null)
				{
					if (methodInfo == null)
					{
						Type type = obj.GetType();
						methodInfo = type.GetMethod("SetForNewGame", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
						methodInfo2 = type.GetMethod("Realize", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
					}
					methodInfo?.Invoke(obj, null);
					methodInfo2?.Invoke(obj, null);
					Plugin.Log.LogInfo((object)($"[DarkFogAwakener]   Hive {num + 1}/{value} at '{item2.displayName}' " + $"({Math.Sqrt(item3):F1} ly from centre)."));
					num++;
				}
			}
			Plugin.Log.LogInfo((object)$"[DarkFogAwakener] Hives: {num}/{value} seeded at the farthest stars.");
		}

		private static bool IsPlanetBuiltOn(PlanetFactory factory)
		{
			EntityData[] entityPool = factory.entityPool;
			for (int i = 1; i < factory.entityCursor; i++)
			{
				if (entityPool[i].id == i)
				{
					return true;
				}
			}
			return false;
		}

		private static HashSet<int> GetColonisedStarIds(GameData game)
		{
			HashSet<int> hashSet = new HashSet<int>();
			PlanetFactory[] factories = game.factories;
			foreach (PlanetFactory val in factories)
			{
				if (((val == null) ? null : val.planet?.star) != null && IsPlanetBuiltOn(val))
				{
					hashSet.Add(val.planet.star.id);
				}
			}
			return hashSet;
		}

		private static bool TryInvokeInit(object? obj, string label)
		{
			if (obj == null)
			{
				return false;
			}
			Type type = obj.GetType();
			string[] initMethodNames = InitMethodNames;
			foreach (string text in initMethodNames)
			{
				MethodInfo method = type.GetMethod(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (!(method == null))
				{
					method.Invoke(obj, null);
					Plugin.Log.LogDebug((object)("[DarkFogAwakener] Called " + type.Name + "." + text + "() on " + label + "."));
					return true;
				}
			}
			Plugin.Log.LogWarning((object)("[DarkFogAwakener] No init method found on " + type.Name + " (" + label + "). Tried: " + string.Join(", ", InitMethodNames) + "."));
			return false;
		}

		private static bool SetBoolField(object obj, string fieldName, bool value)
		{
			FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field?.FieldType == typeof(bool))
			{
				field.SetValue(obj, value);
				Plugin.Log.LogDebug((object)$"[DarkFogAwakener] Set {obj.GetType().Name}.{fieldName} = {value}");
				return true;
			}
			Plugin.Log.LogWarning((object)("[DarkFogAwakener] Bool field '" + fieldName + "' not found on " + obj.GetType().Name + "."));
			return false;
		}
	}
	[HarmonyPatch(typeof(GameData), "Import")]
	internal static class Patch_GameData_Import
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			DarkFogAwakener.ResetOnLoad();
			if (!DarkFogAwakener.HasAwakened && Plugin.AutoActivate.Value)
			{
				Plugin.Log.LogInfo((object)"[Patches] AutoActivate is enabled — awakening Dark Fog on load.");
				DarkFogAwakener.Awaken();
			}
		}
	}
	[BepInPlugin("com.darkfogawakening.mod", "Dark Fog Awakening", "1.0.0")]
	[BepInProcess("DSPGAME.exe")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> AutoActivate;

		internal static ConfigEntry<bool> ShowButton;

		internal static ConfigEntry<int> HiveCount;

		internal static ConfigEntry<float> Aggressiveness;

		private Harmony _harmony;

		private bool _showConfirm;

		private Rect _windowRect = new Rect(0f, 0f, 360f, 0f);

		private GUIStyle? _labelStyle;

		private void Awake()
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			AutoActivate = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AutoActivate", false, "When true the Dark Fog awakens automatically the moment a save is loaded. No button press required.");
			ShowButton = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowButton", true, "Show the in-game 'Awaken the Dark Fog' button when combat is disabled.");
			HiveCount = ((BaseUnityPlugin)this).Config.Bind<int>("Combat", "HiveCount", 4, "How many hives to spawn. They are placed at the stars farthest from the galactic centre so the threat starts distant and spreads inward.");
			Aggressiveness = ((BaseUnityPlugin)this).Config.Bind<float>("Combat", "Aggressiveness", 2f, "Multiplier applied to all CombatSettings difficulty values (growth speed, expansion rate, colonisation rate, etc.). 1.0 = vanilla normal difficulty. 2.0 = twice as fast/aggressive.");
			_harmony = new Harmony("com.darkfogawakening.mod");
			_harmony.PatchAll();
			Log.LogInfo((object)"Dark Fog Awakening v1.0.0 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void OnGUI()
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			if (!ShowButton.Value || DarkFogAwakener.HasAwakened)
			{
				return;
			}
			UIRoot instance = UIRoot.instance;
			if (instance == null)
			{
				return;
			}
			UIGame uiGame = instance.uiGame;
			if (((uiGame != null) ? new bool?(((Component)uiGame).gameObject.activeSelf) : null).GetValueOrDefault())
			{
				if (((Rect)(ref _windowRect)).x == 0f && ((Rect)(ref _windowRect)).y == 0f)
				{
					((Rect)(ref _windowRect)).x = ((float)Screen.width - ((Rect)(ref _windowRect)).width) / 2f;
					((Rect)(ref _windowRect)).y = ((float)Screen.height - 180f) / 2f;
				}
				_windowRect = GUILayout.Window(234487809, _windowRect, new WindowFunction(DrawWindow), "Dark Fog Awakening", Array.Empty<GUILayoutOption>());
			}
		}

		private void DrawWindow(int _)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_003e: Expected O, but got Unknown
			GUILayout.Space(6f);
			GUIStyle obj = _labelStyle;
			if (obj == null)
			{
				GUIStyle val = new GUIStyle(GUI.skin.label)
				{
					wordWrap = true,
					richText = true
				};
				GUIStyle val2 = val;
				_labelStyle = val;
				obj = val2;
			}
			GUILayout.Label("This save was started with the Dark Fog disabled.\nYou can awaken them now.\n\n<b>Warning: this cannot be undone.</b>", obj, Array.Empty<GUILayoutOption>());
			GUILayout.Space(8f);
			if (!_showConfirm)
			{
				if (GUILayout.Button("Awaken the Dark Fog", Array.Empty<GUILayoutOption>()))
				{
					_showConfirm = true;
				}
			}
			else
			{
				GUILayout.Label("Are you sure? The Dark Fog will spread immediately.", Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Yes — Awaken Now", Array.Empty<GUILayoutOption>()))
				{
					_showConfirm = false;
					DarkFogAwakener.Awaken();
				}
				if (GUILayout.Button("Cancel", Array.Empty<GUILayoutOption>()))
				{
					_showConfirm = false;
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.Space(4f);
			GUI.DragWindow();
		}
	}
	internal static class PluginInfo
	{
		public const string GUID = "com.darkfogawakening.mod";

		public const string NAME = "Dark Fog Awakening";

		public const string VERSION = "1.0.0";
	}
}