Decompiled source of HardFog v0.0.24
HardFog.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UXAssist.Common; using UXAssist.UI; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("HardFog")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("HardFog")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("8cf264f1-e863-4eaf-b956-c8330da40ba6")] [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 HardFog; [BepInPlugin("me.liantian.plugin.HardFog", "HardFog", "0.0.24")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class HardFogWindow : BaseUnityPlugin { private const string WindowTitleKey = "hard_fog_control"; private const string ClearCurrentPlanetKey = "clear_current_planet"; private const string ClearCurrentStarKey = "clear_current_star"; private const string FillGalaxyHivesKey = "fill_hive"; private const string SuperThreatReducerHiveKey = "super-threat-reducer-hive-enabled"; private const string SuperThreatReducerGroundKey = "super-threat-reducer-ground-enabled"; private const string SmartRelayDispatchKey = "smart-relay-dispatch-enabled"; private const string FasterRelayLaunchKey = "faster-relay-launch-enabled"; private const string FasterResearchKey = "faster-research-enabled"; private const string BuildAnywhereOnWaterKey = "build-anywhere-on-water-enabled"; private const string VeinPlacementKey = "vein-placement-enabled"; private const string OverpoweredMechaFightersKey = "overpowered-mecha-fighters-enabled"; private const string ConstructLowLatitudeRuinsKey = "surface-ruins-construct-low-latitude"; private const string ConstructMidLatitudeRuinsKey = "surface-ruins-construct-mid-latitude"; private const string ConstructHighLatitudeRuinsKey = "surface-ruins-construct-high-latitude"; private const string BuildGeothermalOnIdleRuinsKey = "surface-ruins-build-geothermal-on-idle-ruins"; private static UIButton clearCurrentPlanetButton; private static UIButton clearCurrentStarButton; private static UIButton fillGalaxyHivesButton; private static UIButton constructLowLatitudeRuinsButton; private static UIButton constructMidLatitudeRuinsButton; private static UIButton constructHighLatitudeRuinsButton; private static UIButton buildGeothermalOnIdleRuinsButton; internal static ManualLogSource Log; public void Awake() { Log = ((BaseUnityPlugin)this).Logger; DarkFogControl.Log = ((BaseUnityPlugin)this).Logger; SurfaceRuinControl.Log = ((BaseUnityPlugin)this).Logger; SuperThreatReducerControl.Init(((BaseUnityPlugin)this).Config.Bind<bool>("DarkFog", "SuperThreatReducerHiveEnabled", false, "Enable Space Hive Suppression. Zeros space hive threat and skips assault scans."), ((BaseUnityPlugin)this).Config.Bind<bool>("DarkFog", "SuperThreatReducerGroundEnabled", false, "Enable Ground Base Suppression. Skips ground base threat accumulation and assault scans."), ((BaseUnityPlugin)this).Logger); RelayControl.Init(((BaseUnityPlugin)this).Config.Bind<bool>("DarkFog", "FasterRelayLaunchEnabled", false, "Enable faster relay station launch. Checks every 120 hive ticks and dispatches one idle relay when none is already outbound."), ((BaseUnityPlugin)this).Config.Bind<bool>("DarkFog", "SmartRelayDispatchEnabled", false, "Only applies when faster relay station launch is enabled. Dispatch relay stations only to markers."), ((BaseUnityPlugin)this).Logger); FasterResearchControl.Init(((BaseUnityPlugin)this).Config.Bind<bool>("HardFog", "FasterResearchEnabled", false, "Enable research speed multiplier. Reduces tech hash needed to about 1/36."), ((BaseUnityPlugin)this).Logger); BuildAnywhereOnWaterControl.Init(((BaseUnityPlugin)this).Config.Bind<bool>("HardFog", "BuildAnywhereOnWaterEnabled", true, "Enable ignoring missing ground support build failures, including water placement."), ((BaseUnityPlugin)this).Logger); VeinPlacementControl.Init(((BaseUnityPlugin)this).Config.Bind<bool>("HardFog", "VeinPlacementEnabled", true, "Enable better vein placement for future planet vein generation."), ((BaseUnityPlugin)this).Logger); OverpoweredMechaFightersControl.Init(((BaseUnityPlugin)this).Config.Bind<bool>("HardFog", "OverpoweredMechaFightersEnabled", false, "Enable stronger mecha fighters: 10x range, 10x damage, and invincibility."), ((BaseUnityPlugin)this).Logger); I18N.Add("hard_fog_control", "Dark Fog Control", "黑雾操控"); I18N.Add("clear_current_planet", "Clear Dark Fog ground bases on current planet", "清理当前星球的地面黑雾基地"); I18N.Add("clear_current_star", "Clear space Dark Fog hives in current star system", "清理当前恒星的太空黑雾巢穴"); I18N.Add("fill_hive", "Fill the galaxy with Dark Fog hives", "为整个星系填满黑雾巢穴"); I18N.Add("super-threat-reducer-hive-enabled", "Space Hive Suppression", "太空巢穴降压"); I18N.Add("super-threat-reducer-ground-enabled", "Ground Base Suppression", "地面基地降压"); I18N.Add("smart-relay-dispatch-enabled", "Relay stations only dispatch to markers", "中继站只发往信标"); I18N.Add("faster-relay-launch-enabled", "Launch relay stations faster", "更快的发射中继站"); I18N.Add("faster-research-enabled", "Research Speed Multiplier", "研究倍速器"); I18N.Add("vein-placement-enabled", "Better vein placement", "更好的矿物位置"); I18N.Add("overpowered-mecha-fighters-enabled", "Fighters fly farther", "战斗机更远的飞行距离"); I18N.Add("surface-ruins-construct-low-latitude", "Construct low-latitude ruins", "构造低纬度废墟"); I18N.Add("surface-ruins-construct-mid-latitude", "Construct mid-latitude ruins", "构造中纬度废墟"); I18N.Add("surface-ruins-construct-high-latitude", "Construct high-latitude ruins", "构造高纬度废墟"); I18N.Add("surface-ruins-build-geothermal-on-idle-ruins", "Build geothermal power stations on idle ruins", "在空闲废墟上建造地热发电站"); I18N.Add("build-anywhere-on-water-enabled", "Ignore ground support requirement", "无需地基支撑建造"); I18N.Apply(); MyConfigWindow.OnUICreated = (Action<MyConfigWindow, RectTransform>)Delegate.Combine(MyConfigWindow.OnUICreated, new Action<MyConfigWindow, RectTransform>(CreateUI)); Log.LogInfo((object)"HardFog 初始化"); } public void OnDestroy() { MyConfigWindow.OnUICreated = (Action<MyConfigWindow, RectTransform>)Delegate.Remove(MyConfigWindow.OnUICreated, new Action<MyConfigWindow, RectTransform>(CreateUI)); SuperThreatReducerControl.Uninit(); RelayControl.Uninit(); FasterResearchControl.Uninit(); BuildAnywhereOnWaterControl.Uninit(); VeinPlacementControl.Uninit(); OverpoweredMechaFightersControl.Uninit(); } private static void CreateUI(MyConfigWindow wnd, RectTransform trans) { //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Expected O, but got Unknown //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Expected O, but got Unknown //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Expected O, but got Unknown //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Expected O, but got Unknown //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Expected O, but got Unknown //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Expected O, but got Unknown float num = 10f; ((MyWindowWithTabs)wnd).AddSplitter(trans, 10f); ((MyWindowWithTabs)wnd).AddTabGroup(trans, "hard_fog_control", "tab-group-hard-fog"); RectTransform val = ((MyWindowWithTabs)wnd).AddTab(trans, "hard_fog_control"); ((MyWindow)wnd).AddCheckBox(10f, num, val, SuperThreatReducerControl.EnabledConfigHive, "super-threat-reducer-hive-enabled", 16); num += 36f; ((MyWindow)wnd).AddCheckBox(10f, num, val, SuperThreatReducerControl.EnabledConfigGround, "super-threat-reducer-ground-enabled", 16); num += 36f; ((MyWindow)wnd).AddCheckBox(10f, num, val, RelayControl.FasterRelayLaunchEnabledConfig, "faster-relay-launch-enabled", 16); num += 36f; MyCheckBox smartRelayDispatchCheckBox = ((MyWindow)wnd).AddCheckBox(30f, num, val, RelayControl.SmartRelayDispatchEnabledConfig, "smart-relay-dispatch-enabled", 13); RelayControl.FasterRelayLaunchEnabledConfig.SettingChanged += RelayOptionChanged; ((MyWindow)wnd).OnFree += delegate { RelayControl.FasterRelayLaunchEnabledConfig.SettingChanged -= RelayOptionChanged; }; RelayOptionChanged(null, null); num += 36f; ((MyWindow)wnd).AddCheckBox(10f, num, val, FasterResearchControl.EnabledConfig, "faster-research-enabled", 16); num += 36f; ((MyWindow)wnd).AddCheckBox(10f, num, val, BuildAnywhereOnWaterControl.EnabledConfig, "build-anywhere-on-water-enabled", 16); num += 36f; ((MyWindow)wnd).AddCheckBox(10f, num, val, VeinPlacementControl.EnabledConfig, "vein-placement-enabled", 16); num += 36f; ((MyWindow)wnd).AddCheckBox(10f, num, val, OverpoweredMechaFightersControl.EnabledConfig, "overpowered-mecha-fighters-enabled", 16); num = 10f; clearCurrentPlanetButton = ((MyWindow)wnd).AddButton(400f, num, 240f, val, "clear_current_planet", 16, "button-clear-current-planet-dark-fog", new UnityAction(OnClearCurrentPlanetClicked)); num += 36f; clearCurrentStarButton = ((MyWindow)wnd).AddButton(400f, num, 240f, val, "clear_current_star", 16, "button-clear-current-star-dark-fog", new UnityAction(OnClearCurrentStarClicked)); num += 36f; fillGalaxyHivesButton = ((MyWindow)wnd).AddButton(400f, num, 240f, val, "fill_hive", 16, "button-fill-galaxy-dark-fog-hives", new UnityAction(OnFillGalaxyHivesClicked)); num += 36f; constructLowLatitudeRuinsButton = ((MyWindow)wnd).AddButton(400f, num, 260f, val, "surface-ruins-construct-low-latitude", 16, "button-surface-ruins-construct-low-latitude", new UnityAction(OnConstructLowLatitudeRuinsClicked)); num += 36f; constructMidLatitudeRuinsButton = ((MyWindow)wnd).AddButton(400f, num, 260f, val, "surface-ruins-construct-mid-latitude", 16, "button-surface-ruins-construct-mid-latitude", new UnityAction(OnConstructMidLatitudeRuinsClicked)); num += 36f; constructHighLatitudeRuinsButton = ((MyWindow)wnd).AddButton(400f, num, 260f, val, "surface-ruins-construct-high-latitude", 16, "button-surface-ruins-construct-high-latitude", new UnityAction(OnConstructHighLatitudeRuinsClicked)); void RelayOptionChanged(object sender, EventArgs args) { smartRelayDispatchCheckBox.SetEnable(RelayControl.FasterRelayLaunchEnabledConfig.Value); } } private static void OnClearCurrentPlanetClicked() { RunWithButtonDisabled(clearCurrentPlanetButton, DarkFogControl.ClearCurrentPlanetDarkFog); } private static void OnClearCurrentStarClicked() { RunWithButtonDisabled(clearCurrentStarButton, DarkFogControl.ClearCurrentStarSpaceDarkFog); } private static void OnFillGalaxyHivesClicked() { RunWithButtonDisabled(fillGalaxyHivesButton, DarkFogControl.FillGalaxyWithDarkFogHives); } private static void OnConstructLowLatitudeRuinsClicked() { RunWithButtonDisabled(constructLowLatitudeRuinsButton, SurfaceRuinControl.ConstructLowLatitudeRuinsOnCurrentPlanet); } private static void OnConstructMidLatitudeRuinsClicked() { RunWithButtonDisabled(constructMidLatitudeRuinsButton, SurfaceRuinControl.ConstructMidLatitudeRuinsOnCurrentPlanet); } private static void OnConstructHighLatitudeRuinsClicked() { RunWithButtonDisabled(constructHighLatitudeRuinsButton, SurfaceRuinControl.ConstructHighLatitudeRuinsOnCurrentPlanet); } private static void OnBuildGeothermalOnIdleRuinsClicked() { RunWithButtonDisabled(buildGeothermalOnIdleRuinsButton, SurfaceRuinControl.BuildGeothermalOnIdleRuinsCurrentPlanet); } private static void RunWithButtonDisabled(UIButton button, Action action) { if ((Object)(object)button != (Object)null) { ((Behaviour)button).enabled = false; } try { action(); } finally { if ((Object)(object)button != (Object)null) { ((Behaviour)button).enabled = true; } } } } internal static class DarkFogControl { private struct EnemyModelRef { public int ModelIndex; public int ModelId; } internal static ManualLogSource Log; internal static void ClearCurrentPlanetDarkFog() { SaveCurrentGame(); if (GameMain.mainPlayer != null) { PlanetData localPlanet = GameMain.localPlanet; if (localPlanet != null) { ClearPlanetDarkFog(localPlanet); } } } private static void ClearPlanetDarkFog(PlanetData planet) { LogInfo("planet.name: " + planet.name); LogInfo("astroId: " + planet.astroId); PlanetFactory orCreateFactory = GameMain.data.GetOrCreateFactory(planet); if (orCreateFactory?.enemySystem?.bases != null) { ObjectPool<DFGBaseComponent> bases = orCreateFactory.enemySystem.bases; List<int> list = CollectGroundBaseIdsDescending(bases); if (list.Count <= 0) { ClearDarkFogAssaultTips(); return; } HashSet<int> baseIds = new HashSet<int>(list); List<EnemyModelRef> removedModels = new List<EnemyModelRef>(); ClearGroundUnits(orCreateFactory, baseIds, removedModels); ClearGroundBaseFormations(orCreateFactory, list); ClearGroundNonCoreBuildings(orCreateFactory, list, removedModels); ClearGroundBaseCores(orCreateFactory, list, removedModels); ReturnRelaysForGroundBases(planet, baseIds); UnlinkGroundBaseRuins(orCreateFactory, bases, list); ClearLocalDarkFogRenderResidue(planet, orCreateFactory, list, removedModels); RefreshGroundDefenseSearch(orCreateFactory); ClearDarkFogAssaultTips(); } } private static List<int> CollectGroundBaseIdsDescending(ObjectPool<DFGBaseComponent> bases) { List<int> list = new List<int>(); if (bases?.buffer == null) { return list; } for (int num = bases.cursor - 1; num > 0; num--) { DFGBaseComponent val = bases.buffer[num]; if (val != null && val.id == num) { list.Add(num); } } return list; } private static void ClearGroundUnits(PlanetFactory planetFactory, HashSet<int> baseIds, List<EnemyModelRef> removedModels) { foreach (int item in CollectGroundUnitEnemyIdsDescending(planetFactory, baseIds)) { KillGroundEnemyFinally(planetFactory, item, "unit", removedModels); } } private static void ClearGroundNonCoreBuildings(PlanetFactory planetFactory, List<int> baseIds, List<EnemyModelRef> removedModels) { for (int i = 0; i < 8; i++) { int num = 0; foreach (int baseId in baseIds) { foreach (int item in CollectGroundNonCoreBuildingEnemyIdsDescending(planetFactory, baseId)) { if (KillGroundEnemyFinally(planetFactory, item, "building", removedModels)) { num++; } } } ExecuteDeferredGroundEnemyChanges(planetFactory); if (num == 0) { break; } } } private static void ClearGroundBaseCores(PlanetFactory planetFactory, List<int> baseIds, List<EnemyModelRef> removedModels) { foreach (int baseId in baseIds) { int enemyId = GetGroundBase(planetFactory, baseId)?.enemyId ?? 0; if (IsGroundCoreEnemy(planetFactory, enemyId, baseId)) { KillGroundEnemyFinally(planetFactory, enemyId, "core", removedModels); } } } private static List<int> CollectGroundUnitEnemyIdsDescending(PlanetFactory planetFactory, HashSet<int> baseIds) { List<int> list = new List<int>(); HashSet<int> hashSet = new HashSet<int>(); DataPool<EnemyUnitComponent> val = planetFactory?.enemySystem?.units; if (planetFactory?.enemyPool == null || baseIds == null || baseIds.Count <= 0) { return list; } if (val?.buffer != null) { for (int num = val.cursor - 1; num > 0; num--) { ref EnemyUnitComponent reference = ref val.buffer[num]; if (reference.id == num && baseIds.Contains(reference.baseId) && IsGroundUnitEnemy(planetFactory, reference.enemyId, reference.baseId)) { list.Add(reference.enemyId); hashSet.Add(reference.enemyId); } } } for (int num2 = planetFactory.enemyCursor - 1; num2 > 0; num2--) { ref EnemyData reference2 = ref planetFactory.enemyPool[num2]; if (reference2.id == num2 && reference2.dynamic && !reference2.isSpace && baseIds.Contains(reference2.owner) && !hashSet.Contains(num2)) { list.Add(num2); } } return list; } private static List<int> CollectGroundNonCoreBuildingEnemyIdsDescending(PlanetFactory planetFactory, int baseId) { List<int> list = new List<int>(); HashSet<int> hashSet = new HashSet<int>(); Builder[] array = GetGroundBase(planetFactory, baseId)?.pbuilders; if (array != null) { for (int num = array.Length - 1; num > 1; num--) { int instId = array[num].instId; if (IsGroundNonCoreBuildingEnemy(planetFactory, instId, baseId)) { list.Add(instId); hashSet.Add(instId); } } } if (planetFactory?.enemyPool == null) { return list; } for (int num2 = planetFactory.enemyCursor - 1; num2 > 0; num2--) { ref EnemyData reference = ref planetFactory.enemyPool[num2]; if (reference.id == num2 && !reference.dynamic && !reference.isSpace && reference.owner == baseId && reference.dfGBaseId != baseId && !hashSet.Contains(num2)) { list.Add(num2); } } return list; } private static bool IsGroundUnitEnemy(PlanetFactory planetFactory, int enemyId, int baseId) { if (!IsLiveGroundEnemy(planetFactory, enemyId)) { return false; } ref EnemyData reference = ref planetFactory.enemyPool[enemyId]; if (reference.dynamic) { return reference.owner == baseId; } return false; } private static bool IsGroundNonCoreBuildingEnemy(PlanetFactory planetFactory, int enemyId, int baseId) { if (!IsLiveGroundEnemy(planetFactory, enemyId)) { return false; } ref EnemyData reference = ref planetFactory.enemyPool[enemyId]; if (!reference.dynamic && reference.owner == baseId) { return reference.dfGBaseId != baseId; } return false; } private static bool IsGroundCoreEnemy(PlanetFactory planetFactory, int enemyId, int baseId) { if (!IsLiveGroundEnemy(planetFactory, enemyId)) { return false; } ref EnemyData reference = ref planetFactory.enemyPool[enemyId]; if (!reference.dynamic) { return reference.dfGBaseId == baseId; } return false; } private static bool KillGroundEnemyFinally(PlanetFactory planetFactory, int enemyId, string kind, List<EnemyModelRef> removedModels) { if (!IsLiveGroundEnemy(planetFactory, enemyId)) { return false; } try { RememberEnemyModel(planetFactory, enemyId, removedModels); LogInfo("KillEnemyFinally " + kind + " -> enemyData.id: " + enemyId); planetFactory.KillEnemyFinally(enemyId, ref CombatStat.empty); return true; } catch (Exception ex) { LogInfo("error to kill ground " + kind + " " + enemyId + ": " + ex.Message); return false; } } private static bool IsLiveGroundEnemy(PlanetFactory planetFactory, int enemyId) { if (planetFactory?.enemyPool != null && enemyId > 0 && enemyId < planetFactory.enemyCursor && enemyId < planetFactory.enemyPool.Length && planetFactory.enemyPool[enemyId].id == enemyId) { return !planetFactory.enemyPool[enemyId].isSpace; } return false; } private static void RememberEnemyModel(PlanetFactory planetFactory, int enemyId, List<EnemyModelRef> removedModels) { if (removedModels != null && IsLiveGroundEnemy(planetFactory, enemyId)) { ref EnemyData reference = ref planetFactory.enemyPool[enemyId]; if (reference.modelId > 0) { removedModels.Add(new EnemyModelRef { ModelIndex = reference.modelIndex, ModelId = reference.modelId }); } } } private static void ClearGroundBaseFormations(PlanetFactory planetFactory, List<int> baseIds) { foreach (int baseId in baseIds) { DFGBaseComponent groundBase = GetGroundBase(planetFactory, baseId); if (groundBase == null || groundBase.forms == null) { continue; } for (int num = groundBase.forms.Length - 1; num >= 0; num--) { EnemyFormation val = groundBase.forms[num]; if (val != null && val.unitCount > 0) { try { LogInfo("clear DFGBaseComponent:" + groundBase.id + " -> form count: " + val.unitCount); val.Clear(); } catch (Exception ex) { LogInfo("error to clear form " + num + " for base " + baseId + ": " + ex.Message); } } } } } private static DFGBaseComponent GetGroundBase(PlanetFactory planetFactory, int baseId) { ObjectPool<DFGBaseComponent> val = planetFactory?.enemySystem?.bases; if (baseId <= 0 || val?.buffer == null || baseId >= val.cursor) { return null; } DFGBaseComponent val2 = val.buffer[baseId]; if (val2 == null || val2.id != baseId) { return null; } return val2; } private static void ExecuteDeferredGroundEnemyChanges(PlanetFactory planetFactory) { try { if (planetFactory != null) { EnemyDFGroundSystem enemySystem = planetFactory.enemySystem; if (enemySystem != null) { enemySystem.ExecuteDeferredEnemyChange(); } } } catch (Exception ex) { LogInfo("error to execute deferred ground enemy changes: " + ex.Message); } } private static void ReturnRelaysForGroundBases(PlanetData planet, HashSet<int> baseIds) { if (planet?.star != null && GameMain.spaceSector != null && baseIds != null && baseIds.Count > 0) { for (EnemyDFHiveSystem val = GameMain.spaceSector.dfHives[planet.star.index]; val != null; val = val.nextSibling) { ReturnRelaysForGroundBases(val, planet.astroId, baseIds); } } } private static void ReturnRelaysForGroundBases(EnemyDFHiveSystem hive, int planetAstroId, HashSet<int> baseIds) { if (hive?.relays?.buffer == null) { return; } for (int num = hive.relays.cursor - 1; num > 0; num--) { DFRelayComponent val = hive.relays.buffer[num]; if (val != null && val.id == num) { bool flag = val.targetAstroId == planetAstroId && baseIds.Contains(val.baseId); bool flag2 = val.searchAstroId == planetAstroId; if (flag || flag2) { try { if (flag2) { val.ResetSearchStates(); val.ResetTargetedMarker(); } if (flag && ReturnRelay(val)) { hive.relayNeutralizedCounter++; } } catch (Exception ex) { LogInfo("error to return relay " + val.id + ": " + ex.Message); } } } } } private static bool ReturnRelay(DFRelayComponent relay) { //IL_0060: 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_0090: Unknown result type (might be due to invalid IL or missing references) LogInfo("return relay -> relay.id: " + relay.id + ", enemyId: " + relay.enemyId); if (relay.stage == 2) { relay.LeaveBase(); return true; } if (relay.direction < 0) { relay.ResetSearchStates(); relay.ResetTargetedMarker(); return false; } relay.ClearBaseReferences(); relay.targetAstroId = 0; relay.targetLPos = Vector3.zero; relay.targetYaw = 0f; relay.baseState = 0; relay.baseId = 0; relay.baseTicks = 0; relay.baseEvolve = default(EvolveData); relay.baseRespawnCD = 0; relay.direction = -1; relay.param0 = 0f; relay.RemoveAllCarriers(); relay.ResetSearchStates(); relay.ResetTargetedMarker(); return true; } private static void UnlinkGroundBaseRuins(PlanetFactory planetFactory, ObjectPool<DFGBaseComponent> bases, List<int> baseIds) { foreach (int baseId in baseIds) { if (baseId <= 0 || bases?.buffer == null || baseId >= bases.cursor) { continue; } DFGBaseComponent val = bases.buffer[baseId]; if (val == null || val.id != baseId) { continue; } try { int enemyId = val.enemyId; int ruinId = val.ruinId; LogInfo("unlink DFGBaseComponent -> base.id: " + baseId + ", enemyId: " + enemyId + ", ruinId: " + ruinId); val.relayId = 0; val.relayEnemyId = 0; val.hiveAstroId = 0; if (IsLiveGroundEnemy(planetFactory, enemyId)) { planetFactory.RemoveEnemyWithComponents(enemyId); } else { RemoveGroundBaseComponentOnly(planetFactory, baseId); } } catch (Exception ex) { LogInfo("error to unlink DFGBaseComponent " + baseId + ": " + ex.Message); } } } private static void RemoveGroundBaseComponentOnly(PlanetFactory planetFactory, int baseId) { if (planetFactory?.enemySystem != null && baseId > 0) { if (planetFactory.platformSystem != null) { planetFactory.platformSystem.RemoveStateArea((uint)(0x1000000uL | (ulong)baseId)); } planetFactory.enemySystem.RemoveDFGBaseComponent(baseId); } } private static void ClearLocalDarkFogRenderResidue(PlanetData planet, PlanetFactory planetFactory, List<int> baseIds, List<EnemyModelRef> removedModels) { if (!((Object)(object)planet?.factoryModel == (Object)null) && planetFactory != null && planet == GameMain.localPlanet && planet.factoryLoaded) { RemoveRememberedEnemyModels(planetFactory, removedModels); ClearLocalGroundRenderer(planet.factoryModel, planetFactory, baseIds); ClearLocalFormationRenderers(planet.factoryModel); } } private static void RemoveRememberedEnemyModels(PlanetFactory planetFactory, List<EnemyModelRef> removedModels) { if (removedModels == null || removedModels.Count <= 0) { return; } GPUInstancingManager gpuiManager = GameMain.gpuiManager; if (((gpuiManager != null) ? gpuiManager.activeFactory : null) != planetFactory) { return; } HashSet<int> hashSet = new HashSet<int>(); foreach (EnemyModelRef removedModel in removedModels) { if (removedModel.ModelId > 0 && hashSet.Add(removedModel.ModelId)) { try { GameMain.gpuiManager.RemoveModel(removedModel.ModelIndex, removedModel.ModelId, true); } catch (Exception ex) { int modelId = removedModel.ModelId; LogInfo("error to remove remembered enemy model " + modelId + ": " + ex.Message); } } } } private static void ClearLocalGroundRenderer(FactoryModel factoryModel, PlanetFactory planetFactory, List<int> baseIds) { EnemyDFGroundRenderer dfGroundRenderer = factoryModel.dfGroundRenderer; if (dfGroundRenderer == null) { return; } try { dfGroundRenderer.enemySystem = planetFactory.enemySystem; if (dfGroundRenderer.builderArr != null && baseIds != null) { foreach (int baseId in baseIds) { int num = baseId * 80; int num2 = Math.Min(num + 80, dfGroundRenderer.builderArr.Length); for (int i = num; i < num2; i++) { dfGroundRenderer.builderArr[i].instId = 0u; } } } if (dfGroundRenderer.truckSegments != null) { Array.Clear(dfGroundRenderer.truckSegments, 0, dfGroundRenderer.truckSegments.Length); } if (dfGroundRenderer.truckBuilderIndices != null) { Array.Clear(dfGroundRenderer.truckBuilderIndices, 0, dfGroundRenderer.truckBuilderIndices.Length); } } catch (Exception ex) { LogInfo("error to clear local ground renderer residue: " + ex.Message); } } private static void ClearLocalFormationRenderers(FactoryModel factoryModel) { EnemyFormationRenderer[] dfFormRenderers = factoryModel.dfFormRenderers; if (dfFormRenderers == null) { return; } EnemyFormationRenderer[] array = dfFormRenderers; foreach (EnemyFormationRenderer val in array) { if (val != null) { val.unitCount = 0; val.stateCursor = 0; val.groupCursor = 0; } } } private static void RefreshGroundDefenseSearch(PlanetFactory planetFactory) { try { if (planetFactory != null) { DefenseSystem defenseSystem = planetFactory.defenseSystem; if (defenseSystem != null) { defenseSystem.RefreshTurretSearchPair(); } } } catch (Exception ex) { LogInfo("error to refresh turret search pair: " + ex.Message); } } private static void ClearDarkFogAssaultTips() { try { UIRoot instance = UIRoot.instance; if (instance == null) { return; } UIGame uiGame = instance.uiGame; if (uiGame != null) { UIDarkFogAssaultTip dfAssaultTip = uiGame.dfAssaultTip; if (dfAssaultTip != null) { dfAssaultTip.ClearAllSpots(); } } } catch (Exception) { LogInfo("error to clear dark fog assault tips"); } } internal static void ClearCurrentStarSpaceDarkFog() { SaveCurrentGame(); if (GameMain.mainPlayer != null) { StarData localStar = GameMain.localStar; if (localStar != null) { ClearStarSpaceDarkFog(localStar); } } } private static void ClearStarSpaceDarkFog(StarData star) { SpaceSector spaceSector = GameMain.spaceSector; List<int> list = new List<int>(); for (int num = spaceSector.enemyCursor - 1; num > 0; num--) { ref EnemyData reference = ref spaceSector.enemyPool[num]; if (reference.id == num && !((EnemyData)(ref reference)).isInvincible && reference.dfSCoreId <= 0 && reference.astroId == star.astroId) { LogInfo("active relays -> " + reference.id); list.Add(reference.id); } } for (EnemyDFHiveSystem val = spaceSector.dfHives[star.index]; val != null; val = val.nextSibling) { if (val.isAlive) { LogInfo("hiveAstroId " + val.hiveAstroId); LogInfo("rootEnemyId " + val.rootEnemyId); CollectKillableEnemyIds<EnemyUnitComponent>(spaceSector, list, val.units, (Func<EnemyUnitComponent, int>)((EnemyUnitComponent component) => component.enemyId)); CollectKillableEnemyIds<DFTinderComponent>(spaceSector, list, val.tinders, (Func<DFTinderComponent, int>)((DFTinderComponent component) => component.enemyId)); CollectIdleRelayEnemyIds(spaceSector, list, val); CollectKillableEnemyIds<DFSTurretComponent>(spaceSector, list, val.turrets, (Func<DFSTurretComponent, int>)((DFSTurretComponent component) => component.enemyId)); CollectKillableEnemyIds<DFSGammaComponent>(spaceSector, list, val.gammas, (Func<DFSGammaComponent, int>)((DFSGammaComponent component) => component.enemyId)); CollectKillableEnemyIds<DFSReplicatorComponent>(spaceSector, list, val.replicators, (Func<DFSReplicatorComponent, int>)((DFSReplicatorComponent component) => component.enemyId)); CollectKillableEnemyIds<DFSConnectorComponent>(spaceSector, list, val.connectors, (Func<DFSConnectorComponent, int>)((DFSConnectorComponent component) => component.enemyId)); CollectKillableEnemyIds<DFSNodeComponent>(spaceSector, list, val.nodes, (Func<DFSNodeComponent, int>)((DFSNodeComponent component) => component.enemyId)); CollectKillableEnemyIds<EnemyBuilderComponent>(spaceSector, list, val.builders, (Func<EnemyBuilderComponent, int>)((EnemyBuilderComponent component) => component.enemyId)); ClearHiveFormations(val); DrainHiveCoreBuilders(val); } } foreach (int item in list.Distinct()) { try { spaceSector.KillEnemyFinal(item, ref CombatStat.empty); } catch (Exception) { LogInfo("error to kill " + item); } } MakeHiveCoresInvincible(star); } private static void CollectKillableEnemyIds<T>(SpaceSector spaceSector, List<int> enemyIds, DataPool<T> pool, Func<T, int> getEnemyId) where T : struct, IPoolElement { for (int num = pool.cursor - 1; num > 0; num--) { int num2 = getEnemyId(pool.buffer[num]); if (CanKillSpaceEnemy(spaceSector, num2)) { enemyIds.Add(num2); } } } private static void CollectIdleRelayEnemyIds(SpaceSector spaceSector, List<int> enemyIds, EnemyDFHiveSystem hive) { for (int num = hive.idleRelayCount - 1; num > 0; num--) { DFRelayComponent val = hive.relays.buffer[hive.idleRelayIds[num]]; if (CanKillSpaceEnemy(spaceSector, val.enemyId)) { enemyIds.Add(val.enemyId); } } } private static bool CanKillSpaceEnemy(SpaceSector spaceSector, int enemyId) { if (enemyId <= 0) { return false; } ref EnemyData reference = ref spaceSector.enemyPool[enemyId]; if (!((EnemyData)(ref reference)).isInvincible) { return reference.dfSCoreId <= 0; } return false; } private static void ClearHiveFormations(EnemyDFHiveSystem hive) { EnemyFormation[] forms = hive.forms; for (int i = 0; i < forms.Length; i++) { if (forms[i].unitCount > 0) { LogInfo("clear form " + forms[i].unitCount); forms[i].Clear(); } } } private static void DrainHiveCoreBuilders(EnemyDFHiveSystem hive) { for (int num = hive.cores.cursor - 1; num > 0; num--) { ref EnemyBuilderComponent reference = ref hive.builders.buffer[hive.cores.buffer[num].builderId]; reference.matter = 0; reference.energy = 0; } } internal static void FillGalaxyWithDarkFogHives() { SaveCurrentGame(); if (GameMain.mainPlayer == null) { return; } GalaxyData galaxy = GameMain.galaxy; SpaceSector spaceSector = GameMain.spaceSector; for (int i = 0; i < galaxy.starCount; i++) { StarData val = galaxy.stars[i]; int num = Math.Min(val.maxHiveCount, 8); int num2 = CountHives(spaceSector.dfHives[val.index]); for (int j = 0; j < num - num2; j++) { EnemyDFHiveSystem val2 = spaceSector.TryCreateNewHive(val); if (val2 != null) { LogInfo(val.displayName + " Add 1 hive"); val2.SetForNewGame(); } } } } private static int CountHives(EnemyDFHiveSystem hive) { int num = 0; while (hive != null) { num++; hive = hive.nextSibling; } return num; } private static void MakeHiveCoresInvincible(StarData star) { SpaceSector spaceSector = GameMain.spaceSector; for (EnemyDFHiveSystem val = spaceSector.dfHives[star.index]; val != null; val = val.nextSibling) { for (int num = val.cores.cursor - 1; num > 0; num--) { ((EnemyData)(ref spaceSector.enemyPool[val.cores.buffer[num].enemyId])).isInvincible = true; } } } private static void SaveCurrentGame() { string arg = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); string arg2 = GameMain.data.gameDesc.galaxySeed.ToString("00000000"); GameSave.SaveCurrentGame($"[{arg2}] {arg}"); } private static void LogInfo(string message) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)message); } } } internal static class SurfaceRuinControl { private enum LatitudeBand { Low, Mid, High } private const short BasePitRuinModelIndex = 406; private const int Level30BasePitLifeTime = -31; private const float DuplicateRuinRadius = 50f; private const float SurfaceOffset = 0.2f; private const float LowLatitudeMax = 28.5f; private const float MidLatitudeMax = 46.5f; internal static ManualLogSource Log; private static readonly Vector3[] LowLatitudeRuinPositions = (Vector3[])(object)new Vector3[76] { new Vector3(-173.0104f, -47.818897f, 88.66112f), new Vector3(173.0104f, -47.818897f, 88.66112f), new Vector3(173.0104f, 47.818897f, 88.66112f), new Vector3(-173.0104f, 47.818897f, 88.66112f), new Vector3(-117.67461f, -137.77583f, 85.15015f), new Vector3(117.67461f, -137.77583f, 85.15015f), new Vector3(117.67461f, 137.77583f, 85.15015f), new Vector3(-117.67461f, 137.77583f, 85.15015f), new Vector3(-161.9652f, -100.1f, 61.865204f), new Vector3(161.9652f, -100.1f, 61.865204f), new Vector3(161.9652f, 100.1f, 61.865204f), new Vector3(-161.9652f, 100.1f, 61.865204f), new Vector3(191.2756f, 0f, 59.10741f), new Vector3(-191.2756f, 0f, 59.10741f), new Vector3(-32.524464f, -190.40152f, 52.625683f), new Vector3(32.524464f, -190.40152f, 52.625683f), new Vector3(32.524464f, 190.40152f, 52.625683f), new Vector3(-32.524464f, 190.40152f, 52.625683f), new Vector3(-88.66112f, -173.0104f, 47.818897f), new Vector3(88.66112f, -173.0104f, 47.818897f), new Vector3(88.66112f, 173.0104f, 47.818897f), new Vector3(-88.66112f, 173.0104f, 47.818897f), new Vector3(-190.40152f, -52.625683f, 32.524464f), new Vector3(190.40152f, -52.625683f, 32.524464f), new Vector3(190.40152f, 52.625683f, 32.524464f), new Vector3(-190.40152f, 52.625683f, 32.524464f), new Vector3(-136.48001f, -143.4567f, 29.553705f), new Vector3(136.48001f, -143.4567f, 29.553705f), new Vector3(136.48001f, 143.4567f, 29.553705f), new Vector3(-136.48001f, 143.4567f, 29.553705f), new Vector3(-170.3003f, -105.251366f, 0f), new Vector3(-105.251366f, -170.3003f, 0f), new Vector3(-59.10741f, -191.2756f, 0f), new Vector3(0f, -200.2f, 0f), new Vector3(59.10741f, -191.2756f, 0f), new Vector3(105.251366f, -170.3003f, 0f), new Vector3(170.3003f, -105.251366f, 0f), new Vector3(200.2f, 0f, 0f), new Vector3(170.3003f, 105.251366f, 0f), new Vector3(105.251366f, 170.3003f, 0f), new Vector3(59.10741f, 191.2756f, 0f), new Vector3(0f, 200.2f, 0f), new Vector3(-59.10741f, 191.2756f, 0f), new Vector3(-105.251366f, 170.3003f, 0f), new Vector3(-170.3003f, 105.251366f, 0f), new Vector3(-200.2f, 0f, 0f), new Vector3(-136.48001f, -143.4567f, -29.553705f), new Vector3(136.48001f, -143.4567f, -29.553705f), new Vector3(136.48001f, 143.4567f, -29.553705f), new Vector3(-136.48001f, 143.4567f, -29.553705f), new Vector3(-190.40152f, -52.625683f, -32.524464f), new Vector3(190.40152f, -52.625683f, -32.524464f), new Vector3(190.40152f, 52.625683f, -32.524464f), new Vector3(-190.40152f, 52.625683f, -32.524464f), new Vector3(-88.66112f, -173.0104f, -47.818897f), new Vector3(88.66112f, -173.0104f, -47.818897f), new Vector3(88.66112f, 173.0104f, -47.818897f), new Vector3(-88.66112f, 173.0104f, -47.818897f), new Vector3(-32.524464f, -190.40152f, -52.625683f), new Vector3(32.524464f, -190.40152f, -52.625683f), new Vector3(32.524464f, 190.40152f, -52.625683f), new Vector3(-32.524464f, 190.40152f, -52.625683f), new Vector3(191.2756f, 0f, -59.10741f), new Vector3(-191.2756f, 0f, -59.10741f), new Vector3(-161.9652f, -100.1f, -61.865204f), new Vector3(161.9652f, -100.1f, -61.865204f), new Vector3(161.9652f, 100.1f, -61.865204f), new Vector3(-161.9652f, 100.1f, -61.865204f), new Vector3(-117.67461f, -137.77583f, -85.15015f), new Vector3(117.67461f, -137.77583f, -85.15015f), new Vector3(117.67461f, 137.77583f, -85.15015f), new Vector3(-117.67461f, 137.77583f, -85.15015f), new Vector3(-173.0104f, -47.818897f, -88.66112f), new Vector3(173.0104f, -47.818897f, -88.66112f), new Vector3(173.0104f, 47.818897f, -88.66112f), new Vector3(-173.0104f, 47.818897f, -88.66112f) }; private static readonly Vector3[] MidLatitudeRuinPositions = (Vector3[])(object)new Vector3[48] { new Vector3(-29.553705f, -136.48001f, 143.4567f), new Vector3(29.553705f, -136.48001f, 143.4567f), new Vector3(29.553705f, 136.48001f, 143.4567f), new Vector3(-29.553705f, 136.48001f, 143.4567f), new Vector3(-85.15015f, -117.67461f, 137.77583f), new Vector3(85.15015f, -117.67461f, 137.77583f), new Vector3(85.15015f, 117.67461f, 137.77583f), new Vector3(-85.15015f, 117.67461f, 137.77583f), new Vector3(-143.4567f, -29.553705f, 136.48001f), new Vector3(143.4567f, -29.553705f, 136.48001f), new Vector3(143.4567f, 29.553705f, 136.48001f), new Vector3(-143.4567f, 29.553705f, 136.48001f), new Vector3(-137.77583f, -85.15015f, 117.67461f), new Vector3(137.77583f, -85.15015f, 117.67461f), new Vector3(137.77583f, 85.15015f, 117.67461f), new Vector3(-137.77583f, 85.15015f, 117.67461f), new Vector3(0f, -170.3003f, 105.251366f), new Vector3(170.3003f, 0f, 105.251366f), new Vector3(0f, 170.3003f, 105.251366f), new Vector3(-170.3003f, 0f, 105.251366f), new Vector3(-61.865204f, -161.9652f, 100.1f), new Vector3(61.865204f, -161.9652f, 100.1f), new Vector3(61.865204f, 161.9652f, 100.1f), new Vector3(-61.865204f, 161.9652f, 100.1f), new Vector3(-61.865204f, -161.9652f, -100.1f), new Vector3(61.865204f, -161.9652f, -100.1f), new Vector3(61.865204f, 161.9652f, -100.1f), new Vector3(-61.865204f, 161.9652f, -100.1f), new Vector3(0f, -170.3003f, -105.251366f), new Vector3(170.3003f, 0f, -105.251366f), new Vector3(0f, 170.3003f, -105.251366f), new Vector3(-170.3003f, 0f, -105.251366f), new Vector3(-137.77583f, -85.15015f, -117.67461f), new Vector3(137.77583f, -85.15015f, -117.67461f), new Vector3(137.77583f, 85.15015f, -117.67461f), new Vector3(-137.77583f, 85.15015f, -117.67461f), new Vector3(-143.4567f, -29.553705f, -136.48001f), new Vector3(143.4567f, -29.553705f, -136.48001f), new Vector3(143.4567f, 29.553705f, -136.48001f), new Vector3(-143.4567f, 29.553705f, -136.48001f), new Vector3(-85.15015f, -117.67461f, -137.77583f), new Vector3(85.15015f, -117.67461f, -137.77583f), new Vector3(85.15015f, 117.67461f, -137.77583f), new Vector3(-85.15015f, 117.67461f, -137.77583f), new Vector3(-29.553705f, -136.48001f, -143.4567f), new Vector3(29.553705f, -136.48001f, -143.4567f), new Vector3(29.553705f, 136.48001f, -143.4567f), new Vector3(-29.553705f, 136.48001f, -143.4567f) }; private static readonly Vector3[] HighLatitudeRuinPositions = (Vector3[])(object)new Vector3[38] { new Vector3(0f, 0f, 200.2f), new Vector3(0f, -59.10741f, 191.2756f), new Vector3(0f, 59.10741f, 191.2756f), new Vector3(-52.625683f, -32.524464f, 190.40152f), new Vector3(52.625683f, -32.524464f, 190.40152f), new Vector3(52.625683f, 32.524464f, 190.40152f), new Vector3(-52.625683f, 32.524464f, 190.40152f), new Vector3(-47.818897f, -88.66112f, 173.0104f), new Vector3(47.818897f, -88.66112f, 173.0104f), new Vector3(47.818897f, 88.66112f, 173.0104f), new Vector3(-47.818897f, 88.66112f, 173.0104f), new Vector3(0f, -105.251366f, 170.3003f), new Vector3(105.251366f, 0f, 170.3003f), new Vector3(0f, 105.251366f, 170.3003f), new Vector3(-105.251366f, 0f, 170.3003f), new Vector3(-100.1f, -61.865204f, 161.9652f), new Vector3(100.1f, -61.865204f, 161.9652f), new Vector3(100.1f, 61.865204f, 161.9652f), new Vector3(-100.1f, 61.865204f, 161.9652f), new Vector3(-100.1f, -61.865204f, -161.9652f), new Vector3(100.1f, -61.865204f, -161.9652f), new Vector3(100.1f, 61.865204f, -161.9652f), new Vector3(-100.1f, 61.865204f, -161.9652f), new Vector3(0f, -105.251366f, -170.3003f), new Vector3(105.251366f, 0f, -170.3003f), new Vector3(0f, 105.251366f, -170.3003f), new Vector3(-105.251366f, 0f, -170.3003f), new Vector3(-47.818897f, -88.66112f, -173.0104f), new Vector3(47.818897f, -88.66112f, -173.0104f), new Vector3(47.818897f, 88.66112f, -173.0104f), new Vector3(-47.818897f, 88.66112f, -173.0104f), new Vector3(-52.625683f, -32.524464f, -190.40152f), new Vector3(52.625683f, -32.524464f, -190.40152f), new Vector3(52.625683f, 32.524464f, -190.40152f), new Vector3(-52.625683f, 32.524464f, -190.40152f), new Vector3(0f, -59.10741f, -191.2756f), new Vector3(0f, 59.10741f, -191.2756f), new Vector3(0f, 0f, -200.2f) }; internal static void ConstructLowLatitudeRuinsOnCurrentPlanet() { ConstructRuinsOnCurrentPlanet(LatitudeBand.Low, "low-latitude"); } internal static void ConstructMidLatitudeRuinsOnCurrentPlanet() { ConstructRuinsOnCurrentPlanet(LatitudeBand.Mid, "mid-latitude"); } internal static void ConstructHighLatitudeRuinsOnCurrentPlanet() { ConstructRuinsOnCurrentPlanet(LatitudeBand.High, "high-latitude"); } private static void ConstructRuinsOnCurrentPlanet(LatitudeBand targetBand, string bandName) { //IL_0062: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) PlanetData localPlanet = GameMain.localPlanet; if (localPlanet == null) { Report("Surface Ruins: no current planet."); return; } PlanetFactory factory = localPlanet.factory; if (factory == null || factory.ruinPool == null) { Report("Surface Ruins: planet " + (localPlanet.displayName ?? localPlanet.name) + " has no loaded factory."); return; } int num = 0; int num2 = 0; Vector3[] allRuinPositions = GetAllRuinPositions(); for (int i = 0; i < allRuinPositions.Length; i++) { Vector3 val = allRuinPositions[i]; if (GetLatitudeBand(val) == targetBand) { Vector3 val2 = SnapToSurface(localPlanet, val); if (HasRuinWithin(factory, val2, 50f)) { num2++; continue; } RuinData val3 = default(RuinData); val3.modelIndex = 406; val3.lifeTime = -31; val3.pos = val2; val3.rot = Maths.SphericalRotation(val2, DeterministicYaw(i)); factory.AddRuinDataWithComponent(val3); num++; } } Report($"Surface Ruins: created {num}, skipped {num2}, total {CountRuinPositions(targetBand)} {bandName} ruins on {localPlanet.displayName ?? localPlanet.name}."); } private static Vector3[] GetAllRuinPositions() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) Vector3[] array = (Vector3[])(object)new Vector3[LowLatitudeRuinPositions.Length + MidLatitudeRuinPositions.Length + HighLatitudeRuinPositions.Length]; int num = 0; for (int i = 0; i < LowLatitudeRuinPositions.Length; i++) { array[num + i] = LowLatitudeRuinPositions[i]; } num += LowLatitudeRuinPositions.Length; for (int j = 0; j < MidLatitudeRuinPositions.Length; j++) { array[num + j] = MidLatitudeRuinPositions[j]; } num += MidLatitudeRuinPositions.Length; for (int k = 0; k < HighLatitudeRuinPositions.Length; k++) { array[num + k] = HighLatitudeRuinPositions[k]; } return array; } private static int CountRuinPositions(LatitudeBand targetBand) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) int num = 0; Vector3[] allRuinPositions = GetAllRuinPositions(); for (int i = 0; i < allRuinPositions.Length; i++) { if (GetLatitudeBand(allRuinPositions[i]) == targetBand) { num++; } } return num; } private static LatitudeBand GetLatitudeBand(Vector3 position) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Abs(Mathf.Asin(Mathf.Clamp(((Vector3)(ref position)).normalized.y, -1f, 1f)) * 57.29578f); if (num < 28.5f) { return LatitudeBand.Low; } if (num < 46.5f) { return LatitudeBand.Mid; } return LatitudeBand.High; } internal static void BuildGeothermalOnIdleRuinsCurrentPlanet() { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) PlanetData localPlanet = GameMain.localPlanet; if (localPlanet == null) { Report("Surface Ruins: no current planet."); return; } PlanetFactory factory = localPlanet.factory; if (factory == null || factory.ruinPool == null || factory.powerSystem == null) { Report("Surface Ruins: planet " + (localPlanet.displayName ?? localPlanet.name) + " has no loaded factory or power system."); return; } ItemProto val = FindGeothermalPowerItem(); if (val == null || val.prefabDesc == null || !val.prefabDesc.geothermal) { Report("Surface Ruins: geothermal power item not found."); return; } int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; RuinData[] ruinPool = factory.ruinPool; int ruinCursor = factory.ruinCursor; for (int i = 1; i < ruinCursor; i++) { if (ruinPool[i].id == i && ruinPool[i].modelIndex == 406) { if (HasGeothermalOnBaseRuin(factory, i)) { num2++; } else if (HasBaseOnRuin(factory, i)) { num3++; } else if (BuildGeothermalEntity(factory, val, i, ruinPool[i].pos) > 0) { num++; } else { num4++; } } } Report($"Surface Ruins: built geothermal {num}, occupied {num2}, bound bases {num3}, failed {num4} on {localPlanet.displayName ?? localPlanet.name}."); } private static ItemProto FindGeothermalPowerItem() { if (((ProtoSet<ItemProto>)(object)LDB.items)?.dataArray == null) { return null; } ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray; foreach (ItemProto val in dataArray) { if (val?.prefabDesc != null && val.CanBuild && val.IsEntity && val.prefabDesc.isPowerGen && val.prefabDesc.geothermal) { return val; } } return null; } private static bool HasGeothermalOnBaseRuin(PlanetFactory factory, int baseRuinId) { if (factory == null || factory.powerSystem == null || baseRuinId <= 0) { return false; } PowerGeneratorComponent[] genPool = factory.powerSystem.genPool; int genCursor = factory.powerSystem.genCursor; for (int i = 1; i < genCursor; i++) { ref PowerGeneratorComponent reference = ref genPool[i]; if (reference.id == i && reference.geothermal && reference.baseRuinId == baseRuinId) { return true; } } PrebuildData[] prebuildPool = factory.prebuildPool; int prebuildCursor = factory.prebuildCursor; for (int j = 1; j < prebuildCursor; j++) { ref PrebuildData reference2 = ref prebuildPool[j]; if (reference2.id == j && reference2.paramCount > 0 && reference2.parameters != null && reference2.parameters[0] == baseRuinId) { ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select((int)reference2.protoId); if (val?.prefabDesc != null && val.prefabDesc.geothermal) { return true; } } } return false; } private static bool HasBaseOnRuin(PlanetFactory factory, int baseRuinId) { if (factory?.enemySystem?.bases == null || baseRuinId <= 0) { return false; } ObjectPool<DFGBaseComponent> bases = factory.enemySystem.bases; for (int i = 1; i < bases.cursor; i++) { DFGBaseComponent val = bases.buffer[i]; if (val != null && val.id == i && val.ruinId == baseRuinId) { return true; } } return false; } private static int BuildGeothermalEntity(PlanetFactory factory, ItemProto geothermalItem, int baseRuinId, Vector3 ruinPos) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_0072: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //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) //IL_00f7: 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_0179: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) if (((factory != null) ? factory.planet : null) == null || geothermalItem?.prefabDesc == null || baseRuinId <= 0) { return 0; } Vector3 val = SnapGeothermalBuildPosition(factory.planet, ruinPos); Quaternion val2 = Maths.SphericalRotation(val, 0f); PrebuildData val3 = default(PrebuildData); val3.isDestroyed = false; val3.protoId = (short)((Proto)geothermalItem).ID; val3.modelIndex = (short)geothermalItem.ModelIndex; val3.pos = val; val3.pos2 = val; val3.rot = val2; val3.rot2 = val2; ((PrebuildData)(ref val3)).InitParametersArray(1); val3.parameters[0] = baseRuinId; int num = factory.AddPrebuildDataWithComponents(val3); if (num <= 0) { return 0; } EntityData val4 = default(EntityData); val4.protoId = val3.protoId; val4.modelIndex = val3.modelIndex; val4.pos = val3.pos; val4.rot = val3.rot; val4.alt = ((Vector3)(ref val4.pos)).magnitude; val4.tilt = val3.tilt; ((EntityData)(ref val4)).localized = factory.planet == GameMain.localPlanet && factory.planet.factoryLoaded; int num2 = factory.AddEntityDataWithComponents(val4, num); if (num2 <= 0) { factory.RemovePrebuildWithComponents(num); return 0; } Player mainPlayer = GameMain.mainPlayer; if (mainPlayer != null) { PlayerController controller = mainPlayer.controller; if (controller != null) { PlayerAction_Build actionBuild = controller.actionBuild; if (actionBuild != null) { actionBuild.NotifyBuilt(-num, num2); } } } factory.RemovePrebuildWithComponents(num); GameHistoryData history = GameMain.history; if (history != null) { history.MarkItemBuilt((int)val3.protoId, 1); } if (factory.entityPool[num2].beltId > 0) { factory.OnBeltBuilt(num2); } if (factory.entityPool[num2].inserterId > 0) { factory.OnInserterBuilt(num2); } if ((int)geothermalItem.prefabDesc.addonType != 0) { factory.OnAddonBuilt(num2); } factory.OnBuildEntity(num2, num); if (!PlanetFactory.batchBuild) { factory.OnSinglyBuildEntity(num2, num); } GameScenarioLogic gameScenario = GameMain.gameScenario; if (gameScenario != null) { gameScenario.NotifyOnBuild(factory.planet.id, (int)factory.entityPool[num2].protoId, num2); } return num2; } private static Vector3 SnapGeothermalBuildPosition(PlanetData planet, Vector3 ruinPos) { //IL_0018: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (planet.aux != null) { return planet.aux.Snap(ruinPos, true); } return ((Vector3)(ref ruinPos)).normalized * (planet.realRadius + 0.2f); } private static Vector3 SnapToSurface(PlanetData planet, Vector3 templatePos) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) float num = planet.realRadius + 0.2f; Vector3 val = ((Vector3)(ref templatePos)).normalized * num; if (planet.aux != null) { val = planet.aux.Snap(val, true); } return val; } private static bool HasRuinWithin(PlanetFactory factory, Vector3 pos, float radius) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) float num = radius * radius; RuinData[] ruinPool = factory.ruinPool; int ruinCursor = factory.ruinCursor; for (int i = 1; i < ruinCursor; i++) { if (ruinPool[i].id == i) { Vector3 val = ruinPool[i].pos - pos; if (((Vector3)(ref val)).sqrMagnitude < num) { return true; } } } return false; } private static float DeterministicYaw(int index) { return (float)index * 137.50777f % 360f; } private static void Report(string message) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)message); } UIRealtimeTip.Popup(message, false, 0); } } [HarmonyPatch] internal static class BuildAnywhereOnWaterControl { private const string PatchGuid = "me.liantian.plugin.HardFog.BuildAnywhereOnWater"; private static ManualLogSource Log; private static Harmony harmony; private static EventHandler settingChangedHandler; internal static ConfigEntry<bool> EnabledConfig { get; private set; } internal static void Init(ConfigEntry<bool> enabledConfig, ManualLogSource log) { if (EnabledConfig != null && settingChangedHandler != null) { EnabledConfig.SettingChanged -= settingChangedHandler; } Log = log; EnabledConfig = enabledConfig; settingChangedHandler = OnSettingChanged; EnabledConfig.SettingChanged += settingChangedHandler; SetActive(EnabledConfig.Value); } internal static void Uninit() { if (EnabledConfig != null && settingChangedHandler != null) { EnabledConfig.SettingChanged -= settingChangedHandler; } SetActive(active: false); settingChangedHandler = null; EnabledConfig = null; Log = null; } private static void OnSettingChanged(object sender, EventArgs args) { SetActive(EnabledConfig != null && EnabledConfig.Value); } private static void SetActive(bool active) { if (active) { if (harmony == null) { harmony = Harmony.CreateAndPatchAll(typeof(BuildAnywhereOnWaterControl), "me.liantian.plugin.HardFog.BuildAnywhereOnWater"); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"BuildAnywhereOnWater enabled"); } } } else if (harmony != null) { harmony.UnpatchSelf(); harmony = null; ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"BuildAnywhereOnWater disabled"); } } } [HarmonyPostfix] [HarmonyPatch(typeof(BuildTool_Click), "CheckBuildConditions")] private static void BuildToolClickCheckBuildConditionsPostfix(BuildTool_Click __instance, ref bool __result) { if (((__instance != null) ? ((BuildTool)__instance).buildPreviews : null) != null && ClearNeedGroundConditions(((BuildTool)__instance).buildPreviews)) { __result = IsManualBuildAllowed(((BuildTool)__instance).buildPreviews); RefreshManualCursor(__instance, __result); } } [HarmonyPostfix] [HarmonyPatch(typeof(BuildTool_BlueprintPaste), "CheckBuildConditions")] private static void BuildToolBlueprintPasteCheckBuildConditionsPostfix(BuildTool_BlueprintPaste __instance, ref bool __result) { if (__instance?.bpPool != null && __instance.bpCursor > 0 && ClearNeedGroundConditions(__instance.bpPool, __instance.bpCursor)) { bool removeConnectionErrors = ClearConnectionErrors(__instance.bpPool, __instance.bpCursor); RemoveClearedBlueprintErrors(__instance, removeConnectionErrors); __result = IsBlueprintBuildAllowed(__instance); if (__result && ((BuildTool)__instance).actionBuild?.model != null) { ((BuildTool)__instance).actionBuild.model.cursorState = 0; } } } private static bool ClearNeedGroundConditions(IList<BuildPreview> previews) { bool flag = false; for (int i = 0; i < previews.Count; i++) { flag |= ClearNeedGroundCondition(previews[i]); } return flag; } private static bool ClearNeedGroundConditions(BuildPreview[] previews, int count) { bool flag = false; int num = Math.Min(count, previews.Length); for (int i = 0; i < num; i++) { flag |= ClearNeedGroundCondition(previews[i]); } return flag; } private static bool ClearNeedGroundCondition(BuildPreview bp) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (bp == null) { return false; } if ((int)bp.condition == 23) { bp.condition = (EBuildCondition)0; return true; } return false; } private static bool ClearConnectionErrors(BuildPreview[] previews, int count) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) bool result = false; int num = Math.Min(count, previews.Length); for (int i = 0; i < num; i++) { BuildPreview val = previews[i]; if (val != null && (int)val.condition == 201 && AreConnectionsAllowed(val) && (int)val.condition == 201) { val.condition = (EBuildCondition)0; result = true; } } return result; } private static bool AreConnectionsAllowed(BuildPreview bp) { if (IsConnectedPreviewAllowed(bp.input)) { return IsConnectedPreviewAllowed(bp.output); } return false; } private static bool IsConnectedPreviewAllowed(BuildPreview bp) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (bp == null || (int)bp.condition == 51) { return true; } return IsBlueprintAllowedCondition(bp.condition); } private static bool IsManualBuildAllowed(IList<BuildPreview> previews) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 for (int i = 0; i < previews.Count; i++) { BuildPreview val = previews[i]; if (val != null && (int)val.condition != 0 && (int)val.condition != 28) { return false; } } return true; } private static bool IsBlueprintBuildAllowed(BuildTool_BlueprintPaste tool) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) int num = Math.Min(tool.bpCursor, tool.bpPool.Length); for (int i = 0; i < num; i++) { BuildPreview val = tool.bpPool[i]; if (val != null && val.bpgpuiModelId > 0 && !IsBlueprintAllowedCondition(val.condition)) { return false; } } return true; } private static bool IsBlueprintAllowedCondition(EBuildCondition condition) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 if ((int)condition != 0 && (int)condition != 28) { return (int)condition == 2; } return true; } private static void RemoveClearedBlueprintErrors(BuildTool_BlueprintPaste tool, bool removeConnectionErrors) { RemoveCondition(tool._tmp_error_types, (EBuildCondition)23); RemoveConditionErrorBuildings(tool, (EBuildCondition)23); if (removeConnectionErrors) { RemoveCondition(tool._tmp_error_types, (EBuildCondition)201); RemoveConditionErrorBuildings(tool, (EBuildCondition)201); } if (tool.rootGridErrors == null) { return; } List<uint> list = new List<uint>(); foreach (KeyValuePair<uint, HashSet<EBuildCondition>> rootGridError in tool.rootGridErrors) { if (rootGridError.Value == null) { list.Add(rootGridError.Key); continue; } rootGridError.Value.Remove((EBuildCondition)23); if (removeConnectionErrors) { rootGridError.Value.Remove((EBuildCondition)201); } if (rootGridError.Value.Count == 0) { list.Add(rootGridError.Key); } } for (int i = 0; i < list.Count; i++) { tool.rootGridErrors.Remove(list[i]); } } private static void RemoveCondition(List<EBuildCondition> conditions, EBuildCondition condition) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (conditions != null) { while (conditions.Remove(condition)) { } } } private static void RemoveConditionErrorBuildings(BuildTool_BlueprintPaste tool, EBuildCondition condition) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between I4 and Unknown if (tool._tmpErrorBuildings == null || tool._tmpErrorTipsCursor <= 0) { return; } int num = 0; int num2 = Math.Min(tool._tmpErrorTipsCursor, tool._tmpErrorBuildings.Length); for (int i = 0; i < num2; i++) { ulong num3 = tool._tmpErrorBuildings[i]; if ((int)(num3 >> 48) != (int)condition) { if (num != i) { tool._tmpErrorBuildings[num] = num3; } num++; } } for (int j = num; j < num2; j++) { tool._tmpErrorBuildings[j] = 0uL; } tool._tmpErrorTipsCursor = num; } private static void RefreshManualCursor(BuildTool_Click tool, bool allowed) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Invalid comparison between Unknown and I4 if (((BuildTool)tool).actionBuild?.model == null) { return; } if (allowed) { ((BuildTool)tool).actionBuild.model.cursorState = 0; ((BuildTool)tool).actionBuild.model.cursorText = BuildPreview.GetConditionText((EBuildCondition)0); return; } for (int i = 0; i < ((BuildTool)tool).buildPreviews.Count; i++) { BuildPreview val = ((BuildTool)tool).buildPreviews[i]; if (val != null && (int)val.condition != 0 && (int)val.condition != 28) { ((BuildTool)tool).actionBuild.model.cursorState = -1; ((BuildTool)tool).actionBuild.model.cursorText = val.conditionText; break; } } } } [HarmonyPatch] internal static class SuperThreatReducerControl { private const string PatchGuid = "me.liantian.plugin.HardFog.SuperThreatReducer"; private static ManualLogSource Log; private static Harmony harmony; private static EventHandler settingChangedHandler; internal static ConfigEntry<bool> EnabledConfigHive { get; private set; } internal static ConfigEntry<bool> EnabledConfigGround { get; private set; } private static bool IsAnyEnabled { get { if (EnabledConfigHive == null || !EnabledConfigHive.Value) { if (EnabledConfigGround != null) { return EnabledConfigGround.Value; } return false; } return true; } } internal static void Init(ConfigEntry<bool> enabledConfigHive, ConfigEntry<bool> enabledConfigGround, ManualLogSource log) { if (EnabledConfigHive != null && settingChangedHandler != null) { EnabledConfigHive.SettingChanged -= settingChangedHandler; EnabledConfigGround.SettingChanged -= settingChangedHandler; } Log = log; EnabledConfigHive = enabledConfigHive; EnabledConfigGround = enabledConfigGround; settingChangedHandler = OnSettingChanged; EnabledConfigHive.SettingChanged += settingChangedHandler; EnabledConfigGround.SettingChanged += settingChangedHandler; UpdateHarmonyState(); } internal static void Uninit() { if (EnabledConfigHive != null && settingChangedHandler != null) { EnabledConfigHive.SettingChanged -= settingChangedHandler; EnabledConfigGround.SettingChanged -= settingChangedHandler; } DestroyHarmony(); settingChangedHandler = null; EnabledConfigHive = null; EnabledConfigGround = null; Log = null; } private static void OnSettingChanged(object sender, EventArgs args) { UpdateHarmonyState(); } private static void UpdateHarmonyState() { if (IsAnyEnabled) { EnsureHarmony(); } else { DestroyHarmony(); } } private static void EnsureHarmony() { if (harmony == null) { harmony = Harmony.CreateAndPatchAll(typeof(SuperThreatReducerControl), "me.liantian.plugin.HardFog.SuperThreatReducer"); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"SuperThreatReducer enabled"); } } } private static void DestroyHarmony() { if (harmony != null) { harmony.UnpatchSelf(); harmony = null; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"SuperThreatReducer disabled"); } } } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyDFHiveSystem), "DecisionAI")] private static void EnemyDFHiveSystem_DecisionAI_Postfix(EnemyDFHiveSystem __instance) { if (EnabledConfigHive != null && EnabledConfigHive.Value && __instance != null && __instance.realized && __instance.isAlive) { __instance.evolve.threat = 0; __instance.evolve.threatshr = 0; } } [HarmonyPrefix] [HarmonyPatch(typeof(EnemyDFHiveSystem), "AssaultingWavesDetermineAI")] private static bool EnemyDFHiveSystem_AssaultingWavesDetermineAI_Prefix() { if (EnabledConfigHive == null || !EnabledConfigHive.Value) { return true; } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(DFGBaseComponent), "UpdateFactoryThreat")] private static bool DFGBaseComponent_UpdateFactoryThreat_Prefix() { if (EnabledConfigGround == null || !EnabledConfigGround.Value) { return true; } return false; } } [HarmonyPatch] internal static class RelayControl { private const string PatchGuid = "me.liantian.plugin.HardFog.RelayControl"; private const int VanillaRelayDemandInterval = 600; private const int FasterRelayDemandInterval = 120; private static ManualLogSource Log; private static Harmony harmony; private static EventHandler fasterRelayLaunchChangedHandler; internal static ConfigEntry<bool> FasterRelayLaunchEnabledConfig { get; private set; } internal static ConfigEntry<bool> SmartRelayDispatchEnabledConfig { get; private set; } internal static void Init(ConfigEntry<bool> fasterRelayLaunchEnabledConfig, ConfigEntry<bool> smartRelayDispatchEnabledConfig, ManualLogSource log) { if (FasterRelayLaunchEnabledConfig != null && fasterRelayLaunchChangedHandler != null) { FasterRelayLaunchEnabledConfig.SettingChanged -= fasterRelayLaunchChangedHandler; } Log = log; FasterRelayLaunchEnabledConfig = fasterRelayLaunchEnabledConfig; SmartRelayDispatchEnabledConfig = smartRelayDispatchEnabledConfig; fasterRelayLaunchChangedHandler = OnFasterRelayLaunchChanged; FasterRelayLaunchEnabledConfig.SettingChanged += fasterRelayLaunchChangedHandler; SetActive(FasterRelayLaunchEnabledConfig.Value); } internal static void Uninit() { if (FasterRelayLaunchEnabledConfig != null && fasterRelayLaunchChangedHandler != null) { FasterRelayLaunchEnabledConfig.SettingChanged -= fasterRelayLaunchChangedHandler; } SetActive(active: false); fasterRelayLaunchChangedHandler = null; FasterRelayLaunchEnabledConfig = null; SmartRelayDispatchEnabledConfig = null; Log = null; } private static void OnFasterRelayLaunchChanged(object sender, EventArgs args) { SetActive(FasterRelayLaunchEnabledConfig != null && FasterRelayLaunchEnabledConfig.Value); } private static void SetActive(bool active) { if (active) { if (harmony == null) { harmony = Harmony.CreateAndPatchAll(typeof(RelayControl), "me.liantian.plugin.HardFog.RelayControl"); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"RelayControl enabled"); } } } else if (harmony != null) { harmony.UnpatchSelf(); harmony = null; ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"RelayControl disabled"); } } } [HarmonyPrefix] [HarmonyPatch(typeof(EnemyDFHiveSystem), "DetermineRelayDemand")] private static bool EnemyDFHiveSystemDetermineRelayDemandPrefix(EnemyDFHiveSystem __instance) { DispatchOneIdleRelayIfAllowed(__instance); return false; } [HarmonyTranspiler] [HarmonyPatch(typeof(EnemyDFHiveSystem), "UpdateMatterStatisticsVirtual")] private static IEnumerable<CodeInstruction> EnemyDFHiveSystemUpdateMatterStatisticsVirtualTranspiler(IEnumerable<CodeInstruction> instructions) { return ReplaceRelayDemandInterval(instructions); } [HarmonyTranspiler] [HarmonyPatch(typeof(EnemyDFHiveSystem), "UpdateMatterStatisticsRealized")] private static IEnumerable<CodeInstruction> EnemyDFHiveSystemUpdateMatterStatisticsRealizedTranspiler(IEnumerable<CodeInstruction> instructions) { return ReplaceRelayDemandInterval(instructions); } [HarmonyPrefix] [HarmonyPatch(typeof(DFRelayComponent), "SearchTargetPlaceProcess")] private static bool DFRelayComponentSearchTargetPlaceProcessPrefix(DFRelayComponent __instance, ref bool __result) { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if (__instance == null) { return true; } if (IsMarkerOnlyEnabled()) { if (IsRelayMarkerStillValid(__instance)) { return true; } CancelDockDispatch(__instance); __result = false; return false; } if (__instance.dstMarkerAstroId > 0 || __instance.dstMarkerId > 0 || __instance.searchAstroId != 0) { return true; } EnemyDFHiveSystem hive = __instance.hive; StarData val = hive?.starData; if (val == null) { return true; } int num = CountNonGasPlanets(val); if (num <= 0) { return true; } int pick = RandomTable.Integer(ref hive.rtseed, num); PlanetData val2 = PickNonGasPlanet(val, pick); if (val2 == null) { return true; } __instance.searchAstroId = val2.astroId; __instance.searchBaseId = 0; __instance.searchChance = 5; __instance.searchLPos = Vector3.zero; __instance.searchEntityCursor = 0; __result = false; return false; } private static IEnumerable<CodeInstruction> ReplaceRelayDemandInterval(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = 0; for (int i = 0; i < list.Count; i++) { if (LoadsInt(list[i], 600)) { list[i].opcode = OpCodes.Ldc_I4; list[i].operand = 120; num++; } } if (num == 0) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"Failed to patch relay demand interval."); } } return list; } private static bool LoadsInt(CodeInstruction code, int value) { if (code.opcode == OpCodes.Ldc_I4 && code.operand is int num) { return num == value; } if (code.opcode == OpCodes.Ldc_I4_S && code.operand is sbyte b) { return b == value; } if (code.opcode == OpCodes.Ldc_I4_0) { return value == 0; } if (code.opcode == OpCodes.Ldc_I4_1) { return value == 1; } if (code.opcode == OpCodes.Ldc_I4_2) { return value == 2; } if (code.opcode == OpCodes.Ldc_I4_3) { return value == 3; } if (code.opcode == OpCodes.Ldc_I4_4) { return value == 4; } if (code.opcode == OpCodes.Ldc_I4_5) { return value == 5; } if (code.opcode == OpCodes.Ldc_I4_6) { return value == 6; } if (code.opcode == OpCodes.Ldc_I4_7) { return value == 7; } if (code.opcode == OpCodes.Ldc_I4_8) { return value == 8; } return false; } private static void DispatchOneIdleRelayIfAllowed(EnemyDFHiveSystem hive) { if (hive == null || hive.relays == null || hive.idleRelayCount <= 0 || HasOutgoingRelay(hive)) { return; } if (IsMarkerOnlyEnabled()) { DispatchOneIdleRelayToMarkerIfAllowed(hive); return; } for (int i = 0; i < hive.idleRelayCount; i++) { int num = hive.idleRelayIds[i]; if (num > 0) { DFRelayComponent val = hive.relays.buffer[num]; if (val != null && val.id == num && val.TryDispatchFromHive()) { break; } } } } private static void DispatchOneIdleRelayToMarkerIfAllowed(EnemyDFHiveSystem hive) { if (!TryPickAvailableRelayMarker(hive, out var factory, out var markerId)) { return; } for (int i = 0; i < hive.idleRelayCount; i++) { int num = hive.idleRelayIds[i]; if (num <= 0) { continue; } DFRelayComponent val = hive.relays.buffer[num]; if (val != null && val.id == num && val.TryDispatchFromHive()) { val.SetTargetedMarker(factory, markerId); if (!IsRelayMarkerStillValid(val)) { CancelDockDispatch(val); } break; } } } private static bool TryPickAvailableRelayMarker(EnemyDFHiveSystem hive, out PlanetFactory factory, out int markerId) { factory = null; markerId = 0; int num = CountAvailableRelayMarkers(hive); if (num <= 0) { return false; } int num2 = num; StarData starData = hive.starData; for (int i = 0; i < starData.planetCount; i++) { PlanetData planet = starData.planets[i]; PlanetFactory markerPlanetFactory = GetMarkerPlanetFactory(hive, planet); if (markerPlanetFactory == null) { continue; } ObjectPool<MarkerComponent> markers = markerPlanetFactory.digitalSystem.markers; for (int j = 1; j < markers.cursor; j++) { MarkerComponent val = markers[j]; if (IsAvailableRelayMarker(hive, markerPlanetFactory, val, j)) { float num3 = val.power / (float)num2; if (Random.value < num3) { factory = markerPlanetFactory; markerId = j; return true; } num2--; } } } return false; } private static int CountAvailableRelayMarkers(EnemyDFHiveSystem hive) { int num = 0; StarData starData = hive.starData; for (int i = 0; i < starData.planetCount; i++) { PlanetData planet = starData.planets[i]; PlanetFactory markerPlanetFactory = GetMarkerPlanetFactory(hive, planet); if (markerPlanetFactory == null) { continue; } ObjectPool<MarkerComponent> markers = markerPlanetFactory.digitalSystem.markers; for (int j = 1; j < markers.cursor; j++) { if (IsAvailableRelayMarker(hive, markerPlanetFactory, markers[j], j)) { num++; } } } return num; } private static PlanetFactory GetMarkerPlanetFactory(EnemyDFHiveSystem hive, PlanetData planet) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if (hive == null || planet == null || (int)planet.type == 5 || planet.star != hive.starData || planet.factory == null || planet.factory.entityCount == 0 || planet.factory.digitalSystem == null) { return null; } return planet.factory; } private static bool IsAvailableRelayMarker(EnemyDFHiveSystem hive, PlanetFactory factory, MarkerComponent marker, int markerId) { if (marker != null && marker.id == markerId && marker.attractsDFRelay) { return !IsMarkerAlreadyTargeted(hive, factory.planet.astroId, markerId); } return false; } private static bool IsMarkerAlreadyTargeted(EnemyDFHiveSystem hive, int astroId, int markerId) { for (EnemyDFHiveSystem val = hive.firstSibling; val != null; val = val.nextSibling) { DFRelayComponent[] buffer = val.relays.buffer; int cursor = val.relays.cursor; for (int i = 1; i < cursor; i++) { DFRelayComponent val2 = buffer[i]; if (val2 != null && val2.id == i && val2.direction > 0 && val2.dstMarkerAstroId == astroId && val2.dstMarkerId == markerId) { return true; } } } return false; } private static bool HasOutgoingRelay(EnemyDFHiveSystem hive) { DFRelayComponent[] buffer = hive.relays.buffer; int cursor = hive.relays.cursor; for (int i = 1; i < cursor; i++) { DFRelayComponent val = buffer[i]; if (val != null && val.id == i && val.direction > 0) { return true; } } return false; } private static bool IsRelayMarkerStillValid(DFRelayComponent relay) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Invalid comparison between Unknown and I4 //IL_0114: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) if (relay.dstMarkerAstroId <= 0 || relay.dstMarkerId <= 0 || relay.hive == null) { return false; } PlanetFactory val = relay.hive.sector.galaxy.astrosFactory[relay.dstMarkerAstroId]; if (val == null || (int)val.planet.type == 5 || val.planet.star != relay.hive.starData || val.digitalSystem == null || relay.dstMarkerId >= val.digitalSystem.markers.cursor) { return false; } MarkerComponent val2 = val.digitalSystem.markers[relay.dstMarkerId]; if (val2 == null || val2.id != relay.dstMarkerId || !val2.attractsDFRelay) { return false; } if (((Vector3)(ref relay.dstMarkerLPos)).sqrMagnitude < (val.planet.realRadius - 2f) * (val.planet.realRadius - 2f)) { return false; } if (val2.entityId <= 0 || val2.entityId >= val.entityPool.Length) { return false; } Vector3 val3 = val.entityPool[val2.entityId].pos - relay.dstMarkerLPos; return ((Vector3)(ref val3)).sqrMagnitude <= 0.25f; } private static void CancelDockDispatch(DFRelayComponent relay) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) relay.targetAstroId = 0; relay.targetLPos = Vector3.zero; relay.targetYaw = 0f; relay.baseState = 0; relay.baseId = 0; relay.baseTicks = 0; relay.baseEvolve = default(EvolveData); relay.baseRespawnCD = 0; relay.direction = 0; relay.param0 = 0f; relay.uSpeed = 0f; relay.ResetSearchStates(); relay.ResetTargetedMarker(); } private static bool IsMarkerOnlyEnabled() { if (FasterRelayLaunchEnabledConfig != null && FasterRelayLaunchEnabledConfig.Value && SmartRelayDispatchEnabledConfig != null) { return SmartRelayDispatchEnabledConfig.Value; } return false; } private static int CountNonGasPlanets(StarData starData) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 int num = 0; for (int i = 0; i < starData.planetCount; i++) { PlanetData val = starData.planets[i]; if (val != null && (int)val.type != 5) { num++; } } return num; } private static PlanetData PickNonGasPlanet(StarData starData, int pick) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 for (int i = 0; i < starData.planetCount; i++) { PlanetData val = starData.planets[i]; if (val != null && (int)val.type != 5) { if (pick == 0) { return val; } pick--; } } return null; } } [HarmonyPatch] internal static class FasterResearchControl { private const string PatchGuid = "me.liantian.plugin.HardFog.FasterResearch"; private const int Multiplier = 48; private static ManualLogSource Log; private static Harmony harmony; private static EventHandler settingChangedHandler; internal static ConfigEntry<bool> EnabledConfig { get; private set; } internal static void Init(ConfigEntry<bool> enabledConfig, ManualLogSource log) { if (EnabledConfig != null && settingChangedHandler != null) { EnabledConfig.SettingChanged -= settingChangedHandler; } Log = log; EnabledConfig = enabledConfig; settingChangedHandler = OnSettingChanged; EnabledConfig.SettingChanged += settingChangedHandler; SetActive(EnabledConfig.Value); } internal static void Uninit() { if (EnabledConfig != null && settingChangedHandler != null) { EnabledConfig.SettingChanged -= settingChangedHandler; } SetActive(active: false); settingChangedHandler = null; EnabledConfig = null; Log = null; } private static void OnSettingChanged(object sender, EventArgs args) { SetActive(EnabledConfig != null && EnabledConfig.Value); } private static void SetActive(bool active) { if (active) { if (harmony == null) { harmony = Harmony.CreateAndPatchAll(typeof(FasterResearchControl), "me.liantian.plugin.HardFog.FasterResearch"); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("FasterResearch enabled, multiplier = " + 48)); } } SyncCurrentTechHashNeeded(GameMain.history); } else if (harmony != null) { harmony.UnpatchSelf(); harmony = null; ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"FasterResearch disabled"); } SyncCurrentTechHashNeeded(GameMain.history); } } [HarmonyPostfix] [HarmonyPatch(typeof(TechProto), "GetHashNeeded")] private static void TechProtoGetHashNeededPostfix(ref long __result) { __result = DivideRoundUp(__result, 48); } [HarmonyPostfix] [HarmonyPatch(typeof(GameHistoryData), "SetForNewGame")] private static void GameHistoryDataSetForNewGamePostfix(GameHistoryData __instance) { SyncCurrentTechHashNeeded(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(GameHistoryData), "Import")] private static void GameHistoryDataImportPostfix(GameHistoryData __instance, bool isPreview) { if (!isPreview) { SyncCurrentTechHashNeeded(__instance); } } private static long DivideRoundUp(long value, int divisor) { if (value <= 0) { return value; } return (value + divisor - 1) / divisor; } private static void SyncCurrentTechHashNeeded(GameHistoryData history) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_0076: Unknown result type (might be due to invalid IL or missing references) if (history?.techStates == null) { return; } foreach (int item in new List<int>(history.techStates.Keys)) { TechState val = history.techStates[item]; if (val.unlocked) { continue; } TechProto val2 = ((ProtoSet<TechProto>)(object)LDB.techs).Select(item); if (val2 != null) { val.hashNeeded = val2.GetHashNeeded(val.curLevel); if (val.hashUploaded >= val.hashNeeded) { val.hashUploaded = val.hashNeeded - 1; } history.techStates[item] = val; } } } } [HarmonyPatch] internal static class VeinPlacementControl { private sealed class VeinGroupWork { public readonly short GroupIndex; public readonly EVeinType Type; public readonly List<int> VeinIds = new List<int>(); public VeinGroupWork(short groupIndex, EVeinType type) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) GroupIndex = groupIndex; Type = type; } } private const string PatchGuid = "me.liantian.plugin.HardFog.VeinPlacement"; private const int ModSeedSalt = 1448095793; private const float TargetLatitudeDegrees = 40f; private const float TargetLongitudeDegrees = 80f; private const float NormalGroupSpacing = 196f; private const float OilGroupSpacing = 100f; private const float InnerVeinMinDistanceSqr = 0.5f; private const float InnerVeinMaxRadiusSqr = 13f; private const int GroupPlacementAttempts = 24; private const int LongitudeExpansionPasses = 100; private const float LongitudeExpansionStepDegrees = 30f; private const int LocalShapePasses = 20; private const int LocalFallbackAttempts = 8192; private static ManualLogSource Log; private static Harmony harmony; private static EventHandler settingChangedHandler; private static readonly FieldRef<PlanetAlgorithm, PlanetData> PlanetRef = AccessTools.FieldRefAccess<PlanetAlgorithm, PlanetData>("planet"); internal static ConfigEntry<bool> EnabledConfig { get; private set; } internal static void Init(ConfigEntry<bool> enabledConfig, ManualLogSource log) { if (EnabledConfig != null && settingChangedHandler != null) { EnabledConfig.SettingChanged -= settingChangedHandler; } Log = log; EnabledConfig = enabledConfig; settingChangedHandler = OnSettingChanged; EnabledConfig.SettingChanged += settingChangedHandler; SetActive(EnabledConfig.Value); } internal static void Uninit() { if (EnabledConfig != null && settingChangedHandler != null) { EnabledConfig.SettingChanged -= settingChangedHandler; } SetActive(active: false); settingChangedHandler = null; EnabledConfig = null; Log = null; } private static void OnSettingChanged(object sender, EventArgs args) { SetActive(EnabledConfig != null && EnabledConfig.Value); } private static void SetActive(bool active) { if (active) { if (harmony == null) { harmony = Harmony.CreateAndPatchAll(typeof(VeinPlacementControl), "me.liantian.plugin.HardFog.VeinPlacement"); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"VeinPlacement enabled"); } } } else if (harmony != null) { harmony.UnpatchSelf(); harmony = null; ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"VeinPlacement disabled"); } } } private static void ApplyPlacement(PlanetAlgorithm algorithm) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) PlanetData planet = GetPlanet(algorithm); if (planet == null || (int)planet.type == 5 || planet.data == null || planet.data.veinPool == null || planet.data.veinCursor <= 1) { return; } List<VeinGroupWork> list = InterleaveGroupsByType(CollectGroups(planet)); if (list.Count == 0) { return; } DotNet35Random rng = CreateRandom(planet); Vector3 birthDirection = EnsureBirthPointDirection(planet); if (((Vector3)(ref birthDirection)).sqrMagnitude < 0.5f) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("Unable to read birth point on planet " + (planet.displayName ?? planet.name))); } return; } List<Vector3> list2 = PlaceGroupCenters(planet, list, birthDirection, rng); PlanetRawData data = planet.data; for (int i = 0; i < list.Count; i++) { Vector3 val = list2[i]; if (!(((Vector3)(ref val)).sqrMagnitude < 0.5f)) { RegenerateGroupVeins(planet, data, list[i], list2[i], rng); } } planet.SummarizeVeinGroups(); } private static PlanetData GetPlanet(PlanetAlgorithm algorithm) { if (algorithm == null) { return null; } try { return PlanetRef.Invoke(algorithm); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("Unable to read PlanetAlgorithm.planet: " + ex.Message)); } return null; } } private static DotNet35Random CreateRandom(PlanetData planet) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown return new DotNet35Random((((planet.seed * 397) ^ planet.id) * 397) ^ planet.algoId ^ 0x56503031); } private static List<VeinGroupWork> CollectGroups(PlanetData planet) { //IL_0042: 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) Dictionary<short, VeinGroupWork> dictionary = new Dictionary<short, VeinGroupWork>(); List<VeinGroupWork> list = new List<VeinGroupWork>(); VeinData[] veinPool = planet.data.veinPool; int veinCursor = planet.data.veinCursor; for (int i = 1; i < veinCursor; i++) { if (veinPool[i].id != i || (int)veinPool[i].type == 0) { continue; } short groupIndex = veinPool[i].groupIndex; if (groupIndex > 0) { if (!dictionary.TryGetValue(groupIndex, out var value)) { value = (dictionary[groupIndex] = new VeinGroupWork(groupIndex, veinPool[i].type)); list.Add(value); } value.VeinIds.Add(i); } } return list; } private static List<VeinGroupWork> InterleaveGroupsByType(List<VeinGroupWork> groups) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) Dictionary<EVeinType, List<VeinGroupWork>> dictionary = new Dictionary<EVeinType, List<VeinGroupWork>>(); List<List<VeinGroupWork>> list = new List<List<VeinGroupWork>>(); int num = 0; for (int i = 0; i < groups.Count; i++) { VeinGroupWork veinGroupWork = groups[i]; if (!dictionary.TryGetValue(veinGroupWork.Type, out var value)) { value = new List<VeinGroupWork>(); dictionary[veinGroupWork.Type] = value; list.Add(value); } value.Add(veinGroupWork); if (value.Count > num) { num = value.Count; } } List<VeinGroupWork> list2 = new List<VeinGroupWork>(groups.Count); for (int j = 0; j < num; j++) { for (int k = 0; k < list.Count; k++) { if (j < list[k].Count) { list2.Add(list[k][j]); } } } return list2; } private static void Shuffle<T>(IList<T> items, DotNet35Random rng) { for (int num = items.Count - 1; num > 0; num--) { int index = rng.Next(num + 1); T value = items[num]; items[num] = items[index]; items[index] = value; } } private static Vector3 EnsureBirthPointDirection(PlanetData planet) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (((Vector3)(ref planet.birthPoint)).sqrMagnitude < 1E-08f) { try { planet.GenBirthPoints(); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("Unable to generate birth point on planet " + (planet.displayName ?? planet.name) + ": " + ex.Message)); } } } if (((Vector3)(ref planet.birthPoint)).sqrMagnitude < 1E-08f) { return Vector3.zero; } return ((Vector3)(ref planet.birthPoint)).normalized; } private static List<Vector3> PlaceGroupCenters(PlanetData planet, List<VeinGroupWork> groups, Vector3 birthDirection, DotNet35Random rng) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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) List<Vector3> list = new List<Vector3>(groups.Count); List<Vector3> list2 = new List<Vector3>(groups.Count); if (groups.Count == 0) { return list; } float centerLongitude = LongitudeFromDirection(birthDirection); list.Add(birthDirection); list2.Add(birthDirection); Vector3 anchor = birthDirection; for (int i = 1; i < groups.Count; i++) { if (TryPlaceGroupCenter(planet, groups[i], anchor, centerLongitude, rng, list2, out var center)) { list.Add(center); list2.Add(center); anchor = center; continue; } list.Add(Vector3.zero); Vector3 originalGroupCenter = GetOriginalGroupCenter(planet, groups[i]); if (((Vector3)(ref originalGroupCenter)).sqrMagnitude > 0.5f) { list2.Add(originalGroupCenter); } } return list; } private static bool TryPlaceGroupCenter(PlanetData planet, VeinGroupWork group, Vector3 anchor, float centerLongitude, DotNet35Random rng, List<Vector3> placedCenters, out Vector3 center) { //IL_0015: 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_008f: Unknown result type (might be due to invalid IL or missing references) float minDistanceSqr = GetMinDistanceSqr(planet, group); float num = Mathf.Sqrt(minDistanceSqr); for (int i = 1; i <= 3; i++) { if (TryPlaceOnDistanceBand(planet, group, anchor, num * (float)i, num * (float)(i + 1), centerLongitude, 80f, rng, placedCenters, minDistanceSqr, out center)) { return true; } } if (TryPlaceRandomInWindow(planet, group, centerLongitude, 80f, rng, placedCenters, minDistanceSqr, out center)) { return true; } for (int j = 1; j <= 100; j++) { float longitudeHalfWidthDegrees = 80f + 30f * (float)j; if (TryPlaceRandomInWindow(planet, group, centerLongitude, longitudeHalfWidthDegrees, rng, placedCenters, minDistanceSqr, out center)) { return true; } } center = Vector3.zero; return false; } private static bool TryPlaceOnDistanceBand(PlanetData planet, VeinGroupWork group, Vector3 anchor, float minDistance, float maxDistance, float centerLongitude, float longitudeHalfWidthDegrees, DotNet35Random rng, List<Vector3> placedCenters, float minDistanceSqr, out Vector3 center) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < 24; i++) { float chordDistance = minDistance + (float)rng.NextDouble() * (maxDistance - minDistance); float angle = (float)(rng.NextDouble() * Math.PI * 2.0); Vector3 val = DirectionAtChordDistance(anchor, chordDistance, angle); if (IsValidCandidate(p