mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2026-08-05 07:40:12 +08:00
Compare commits
7
Commits
7a8f4af31d
...
cc783937e6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc783937e6 | ||
|
|
f1cfc5619f | ||
|
|
ffd8b91930 | ||
|
|
79dea142de | ||
|
|
c3f3c2e96e | ||
|
|
63aaceda6f | ||
|
|
33921e7177 |
@@ -10,6 +10,8 @@
|
||||
# C# generated folders
|
||||
bin/
|
||||
obj/
|
||||
*.dll
|
||||
!/AssemblyFromGame/*.dll
|
||||
|
||||
# C++ build folders
|
||||
build/
|
||||
@@ -18,3 +20,6 @@ build/
|
||||
/*/package/*.zip
|
||||
/*/package/patchers/
|
||||
/*/package/plugins/
|
||||
|
||||
# Agent files
|
||||
/.omo/
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
- Update `AGENTS.md` after completing every task.
|
||||
- Do not record a changelog in `AGENTS.md`; modify the document content directly instead.
|
||||
- All documentation and code comments must be written in English.
|
||||
- When you need to inspect game method implementations, decompile the **original** game DLL rather than the publicized copy in `AssemblyFromGame/` (which was built with `--strip` and has all method bodies removed). Locate the original DLL using the same logic as `UpdateGameDlls.ps1`: read the Steam installation path from the Windows registry (`HKCU\Software\Valve\Steam`), parse `steamapps/libraryfolders.vdf` to find the library containing DSP (AppID `1366540`), then decompile `<game_root>/DSPGAME_Data/Managed/Assembly-CSharp.dll` directly.
|
||||
- When looking up in-game terminology, use the localization files under `<game_root>/Locale/` (located via the same Steam registry + `libraryfolders.vdf` method). The `Names` directory contains the dictionary keys; `1033` is the English translation directory; `2052` is the Simplified Chinese translation directory.
|
||||
|
||||
## Project Overview
|
||||
|
||||
@@ -49,7 +51,7 @@ DSP_Mods/
|
||||
|
||||
| Mod | GUID | Description |
|
||||
|-----|------|-------------|
|
||||
| **UXAssist** | `org.soardev.uxassist` | Core QoL mod and shared library. Window resize, profile-based saves, FPS control, factory/logistics/navigation/Dyson Sphere tweaks, UI improvements, config panel UI, and `Common/` + `UI/` widget library shared by other mods. |
|
||||
| **UXAssist** | `org.soardev.uxassist` | Core QoL mod and shared library. Window resize, profile-based saves, FPS control, factory/logistics/navigation/Dyson Sphere tweaks, UI improvements, config panel UI, and `Common/` + `UI/` widget library shared by other mods. The Logistics tab can also push auto-config values to all existing facilities of a type on the current planet (per-setting `Apply` and per-category `Apply All` buttons; logic in `LogisticsPatch.Apply*`/`ForEach*`, wired in `UIConfigWindow`). |
|
||||
| **CheatEnabler** | `org.soardev.cheatenabler` | Cheat pack (depends on UXAssist). Instant build, architect mode, infinite resources, power boosts, Dyson Sphere cheats, mecha invincibility, and more. |
|
||||
| **LogisticMiner** | — | Makes logistic stations automatically mine ores and water from the current planet. |
|
||||
| **HideTips** | — | Suppresses all tutorial popups, random tips, achievement/milestone cards, and skips the prologue cutscene. |
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
|
||||
## Changlog
|
||||
|
||||
* 2.4.4
|
||||
* 2.4.5
|
||||
* New button `Generate illegal dyson shells for all layers without nodes and shells`, which is used to extend dyson layers.
|
||||
* You must enable `IllegalDysonShellFunctionsEnabled` of `DysonSphere` section in config to see it.
|
||||
* 2.4.4
|
||||
* `Finish build immediately`: Fix a possible crash.
|
||||
* 2.4.3
|
||||
* `Duplicate shells from that with highest production`: Fix crash on using with frameless shells.
|
||||
@@ -189,9 +190,10 @@
|
||||
|
||||
## 更新日志
|
||||
|
||||
* 2.4.4
|
||||
* 2.4.5
|
||||
* 新按钮 `为所有没有节点和壳的层级生成仙术戴森壳`,用于扩展新戴森壳层面的时候。
|
||||
* 你必须在设置文件里开启`DysonSphere`分类的`IllegalDysonShellFunctionsEnabled`才能看到它。
|
||||
* 2.4.4
|
||||
* `立即完成建造`: 修复一个可能的崩溃问题。
|
||||
* 2.4.3
|
||||
* `从发电量最高的壳复制戴森壳`:修复在无框壳体时可能崩溃的问题。
|
||||
|
||||
@@ -53,8 +53,6 @@ public class CheatEnabler : BaseUnityPlugin
|
||||
"Boost geothermal power");
|
||||
FactoryPatch.WindTurbinesPowerGlobalCoverageEnabled = Config.Bind("Build", "PowerGlobalCoverage", false,
|
||||
"Global power coverage");
|
||||
FactoryPatch.GreaterPowerUsageInLogisticsEnabled = Config.Bind("Build", "GreaterPowerUsageInLogistics", false,
|
||||
"Increase maximum power usage in Logistic Stations and Advanced Mining Machines");
|
||||
FactoryPatch.ControlPanelRemoteLogisticsEnabled = Config.Bind("Build", "ControlPanelRemoteLogistics", false,
|
||||
"Retrieve/Place items from/to remote planets on logistics control panel");
|
||||
ResourcePatch.InfiniteResourceEnabled = Config.Bind("Planet", "AlwaysInfiniteResource", false,
|
||||
|
||||
@@ -30,7 +30,6 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
|
||||
public static ConfigEntry<bool> BoostFuelPowerEnabled;
|
||||
public static ConfigEntry<bool> BoostGeothermalPowerEnabled;
|
||||
public static ConfigEntry<bool> WindTurbinesPowerGlobalCoverageEnabled;
|
||||
public static ConfigEntry<bool> GreaterPowerUsageInLogisticsEnabled;
|
||||
public static ConfigEntry<bool> ControlPanelRemoteLogisticsEnabled;
|
||||
|
||||
private static PressKeyBind _noConditionKey;
|
||||
@@ -76,7 +75,6 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
|
||||
BoostFuelPowerEnabled.SettingChanged += (_, _) => BoostFuelPower.Enable(BoostFuelPowerEnabled.Value);
|
||||
BoostGeothermalPowerEnabled.SettingChanged += (_, _) => BoostGeothermalPower.Enable(BoostGeothermalPowerEnabled.Value);
|
||||
WindTurbinesPowerGlobalCoverageEnabled.SettingChanged += (_, _) => WindTurbinesPowerGlobalCoverage.Enable(WindTurbinesPowerGlobalCoverageEnabled.Value);
|
||||
GreaterPowerUsageInLogisticsEnabled.SettingChanged += (_, _) => GreaterPowerUsageInLogistics.Enable(GreaterPowerUsageInLogisticsEnabled.Value);
|
||||
ControlPanelRemoteLogisticsEnabled.SettingChanged += (_, _) => ControlPanelRemoteLogistics.Enable(ControlPanelRemoteLogisticsEnabled.Value);
|
||||
}
|
||||
|
||||
@@ -92,7 +90,6 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
|
||||
BoostSolarPower.Enable(BoostSolarPowerEnabled.Value);
|
||||
BoostFuelPower.Enable(BoostFuelPowerEnabled.Value);
|
||||
BoostGeothermalPower.Enable(BoostGeothermalPowerEnabled.Value);
|
||||
GreaterPowerUsageInLogistics.Enable(GreaterPowerUsageInLogisticsEnabled.Value);
|
||||
ControlPanelRemoteLogistics.Enable(ControlPanelRemoteLogisticsEnabled.Value);
|
||||
Enable(true);
|
||||
CargoTrafficPatch.Enable(true);
|
||||
@@ -116,7 +113,6 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
|
||||
BoostFuelPower.Enable(false);
|
||||
BoostGeothermalPower.Enable(false);
|
||||
WindTurbinesPowerGlobalCoverage.Enable(false);
|
||||
GreaterPowerUsageInLogistics.Enable(false);
|
||||
ControlPanelRemoteLogistics.Enable(false);
|
||||
}
|
||||
|
||||
@@ -1681,156 +1677,6 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
|
||||
}
|
||||
}
|
||||
|
||||
private class GreaterPowerUsageInLogistics : PatchImpl<GreaterPowerUsageInLogistics>
|
||||
{
|
||||
protected override void OnEnable()
|
||||
{
|
||||
var window = UIRoot.instance?.uiGame?.stationWindow;
|
||||
if (window == null) return;
|
||||
window._Close();
|
||||
window.maxMiningSpeedSlider.maxValue = 27f;
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
var window = UIRoot.instance?.uiGame?.stationWindow;
|
||||
if (window == null) return;
|
||||
window._Close();
|
||||
window.maxMiningSpeedSlider.maxValue = 20f;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UIStationWindow), nameof(UIStationWindow.OnStationIdChange))]
|
||||
private static IEnumerable<CodeInstruction> UIStationWindow_OnStationIdChange_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.Start().Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
Transpilers.EmitDelegate((UIStationWindow window) =>
|
||||
{
|
||||
window.maxMiningSpeedSlider.maxValue = 27f;
|
||||
})
|
||||
).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStationWindow), nameof(UIStationWindow.maxChargePowerSlider))),
|
||||
new CodeMatch(ci => ci.IsLdloc()),
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4 && ci.OperandIs(0xC350)),
|
||||
new CodeMatch(OpCodes.Conv_I8)
|
||||
);
|
||||
var pos = matcher.Pos + 1;
|
||||
matcher.Advance(5).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Conv_R4),
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertySetter(typeof(Slider), nameof(Slider.value)))
|
||||
);
|
||||
var pos2 = matcher.Pos + 2;
|
||||
matcher.Start().Advance(pos);
|
||||
var ldvar = matcher.InstructionAt(1).Clone();
|
||||
var locWorkEnergyPerTick = matcher.InstructionAt(-2).operand;
|
||||
matcher.RemoveInstructions(pos2 - pos).InsertAndAdvance(
|
||||
ldvar,
|
||||
new CodeInstruction(OpCodes.Ldloc_S, locWorkEnergyPerTick),
|
||||
Transpilers.EmitDelegate((UIStationWindow window, long maxWorkEnergy, long workEnergyPerTick) =>
|
||||
{
|
||||
var maxSliderValue = maxWorkEnergy / 50000L;
|
||||
window.maxChargePowerSlider.maxValue = maxSliderValue + 9;
|
||||
window.maxChargePowerSlider.minValue = maxWorkEnergy / 500000L;
|
||||
if (workEnergyPerTick <= maxWorkEnergy)
|
||||
window.maxChargePowerSlider.Set(workEnergyPerTick / 50000L, false);
|
||||
else
|
||||
window.maxChargePowerSlider.Set(maxSliderValue + (workEnergyPerTick - 1) / maxWorkEnergy + 1, false);
|
||||
})
|
||||
);
|
||||
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStationWindow), nameof(UIStationWindow.maxMiningSpeedSlider))),
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStationWindow), nameof(UIStationWindow.factorySystem))),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.minerPool))),
|
||||
new CodeMatch(ci => ci.IsLdloc()),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(StationComponent), nameof(StationComponent.minerId))),
|
||||
new CodeMatch(OpCodes.Ldelema, typeof(MinerComponent)),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(MinerComponent), nameof(MinerComponent.speed)))
|
||||
);
|
||||
pos = matcher.Pos + 9;
|
||||
matcher.Advance(5).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Conv_R4),
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertySetter(typeof(Slider), nameof(Slider.value)))
|
||||
);
|
||||
pos2 = matcher.Pos;
|
||||
matcher.Start().Advance(pos).RemoveInstructions(pos2 - pos).Insert(
|
||||
Transpilers.EmitDelegate((int speed) =>
|
||||
{
|
||||
if (speed <= 30000)
|
||||
return (speed - 10000) / 1000;
|
||||
return (speed - 30000) / 10000 + 20;
|
||||
})
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UIStationWindow), nameof(UIStationWindow.OnMaxMiningSpeedChange))]
|
||||
private static IEnumerable<CodeInstruction> UIStationWindow_OnMaxMiningSpeedChange_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4 && ci.OperandIs(10000)),
|
||||
new CodeMatch(OpCodes.Ldarg_1)
|
||||
);
|
||||
var pos = matcher.Pos;
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stloc_1)
|
||||
);
|
||||
var pos2 = matcher.Pos;
|
||||
matcher.Start().Advance(pos);
|
||||
var labels = matcher.Labels;
|
||||
matcher.RemoveInstructions(pos2 - pos);
|
||||
matcher.Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_1).WithLabels(labels),
|
||||
Transpilers.EmitDelegate((float value) =>
|
||||
{
|
||||
var intval = (int)(value + 0.5f);
|
||||
if (intval <= 20)
|
||||
return intval * 1000 + 10000;
|
||||
return (intval - 20) * 10000 + 30000;
|
||||
})
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UIStationWindow), nameof(UIStationWindow.OnMaxChargePowerSliderValueChange))]
|
||||
private static IEnumerable<CodeInstruction> UIStationWindow_OnMaxChargePowerSliderValueChange_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStationWindow), nameof(UIStationWindow.factory))),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PlanetFactory), nameof(PlanetFactory.powerSystem))),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerSystem), nameof(PowerSystem.consumerPool)))
|
||||
);
|
||||
var labels = matcher.Labels;
|
||||
matcher.Labels = null;
|
||||
matcher.Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0).WithLabels(labels),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
Transpilers.EmitDelegate((UIStationWindow window, float value) =>
|
||||
{
|
||||
float prevMax = window.workEnergyPrefab * 5L / 50000L;
|
||||
if (value <= prevMax)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return prevMax * (value - prevMax + 1);
|
||||
}),
|
||||
new CodeInstruction(OpCodes.Starg_S, 1)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private class ControlPanelRemoteLogistics : PatchImpl<ControlPanelRemoteLogistics>
|
||||
{
|
||||
[HarmonyTranspiler]
|
||||
|
||||
@@ -57,8 +57,6 @@ public static class UIConfigWindow
|
||||
I18N.Add("Boost fuel power 2", "(x20,000 for deuteron, x10,000 for antimatter)", "(氘核燃料棒x20,000,反物质燃料棒x10,000)");
|
||||
I18N.Add("Wind Turbines do global power coverage", "Wind Turbines do global power coverage", "风力涡轮机供电覆盖全球");
|
||||
I18N.Add("Boost geothermal power", "Boost geothermal power(x50,000)", "提升地热发电(x50,000)");
|
||||
I18N.Add("Increase maximum power usage in Logistic Stations and Advanced Mining Machines", "Increase maximum power usage in Logistic Stations and Advanced Mining Machines",
|
||||
"提升物流塔和大型采矿机的最大功耗");
|
||||
I18N.Add("Retrieve/Place items from/to remote planets on logistics control panel", "Retrieve/Place items from/to remote planets on logistics control panel", "在物流总控面板上可以从非本地行星取放物品");
|
||||
I18N.Add("Infinite Natural Resources", "Infinite natural resources", "自然资源采集不消耗");
|
||||
I18N.Add("Fast Mining", "Fast mining", "高速采集");
|
||||
@@ -205,8 +203,6 @@ public static class UIConfigWindow
|
||||
y += 6f;
|
||||
var tip2 = wnd.AddTipsButton2(x + cb5.Width + 5f, y, tab2, "Belt signal alt format", "Belt signal alt format tips", "belt-signal-alt-format-tips");
|
||||
x = 0f;
|
||||
y += 30f;
|
||||
wnd.AddCheckBox(x, y, tab2, FactoryPatch.GreaterPowerUsageInLogisticsEnabled, "Increase maximum power usage in Logistic Stations and Advanced Mining Machines");
|
||||
y += 36f;
|
||||
wnd.AddCheckBox(x, y, tab2, FactoryPatch.ControlPanelRemoteLogisticsEnabled, "Retrieve/Place items from/to remote planets on logistics control panel");
|
||||
{
|
||||
|
||||
@@ -45,7 +45,6 @@ public static class WinApi
|
||||
public const int GWLP_ID = -12;
|
||||
public const int GWL_STYLE = -16;
|
||||
public const int GWLP_USERDATA = -21;
|
||||
public const int GWLP_WNDPROC = -4;
|
||||
public const int DWLP_DLGPROC = 0x4;
|
||||
public const int DWLP_MSGRESULT = 0;
|
||||
public const int DWLP_USER = 0x8;
|
||||
@@ -99,10 +98,11 @@ public static class WinApi
|
||||
|
||||
#region Functions
|
||||
|
||||
public delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
|
||||
[DllImport("user32", CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);
|
||||
|
||||
[DllImport("kernel32", ExactSpelling = true)]
|
||||
public static extern int GetLastError();
|
||||
[DllImport("user32", ExactSpelling = true, SetLastError = true)]
|
||||
public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int lpdwProcessId);
|
||||
|
||||
[DllImport("user32", CharSet = CharSet.Unicode)]
|
||||
public static extern int GetWindowLong(IntPtr hwnd, int nIndex);
|
||||
@@ -110,12 +110,6 @@ public static class WinApi
|
||||
[DllImport("user32", CharSet = CharSet.Unicode)]
|
||||
public static extern int SetWindowLong(IntPtr hwnd, int nIndex, int dwNewLong);
|
||||
|
||||
[DllImport("user32", CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);
|
||||
|
||||
[DllImport("user32", ExactSpelling = true, SetLastError = true)]
|
||||
public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int lpdwProcessId);
|
||||
|
||||
[DllImport("user32", ExactSpelling = true)]
|
||||
public static extern bool GetWindowRect(IntPtr hwnd, out Rect lpRect);
|
||||
|
||||
@@ -125,33 +119,8 @@ public static class WinApi
|
||||
[DllImport("user32", CharSet = CharSet.Unicode)]
|
||||
public static extern bool SetWindowText(IntPtr hwnd, string lpString);
|
||||
|
||||
[DllImport("user32", ExactSpelling = true)]
|
||||
public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
|
||||
|
||||
[DllImport("user32", ExactSpelling = true)]
|
||||
public static extern IntPtr MonitorFromRect([In] ref Rect lpRect, uint dwFlags);
|
||||
|
||||
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
|
||||
public static extern IntPtr GetCurrentProcess();
|
||||
|
||||
[DllImport("kernel32", ExactSpelling = true)]
|
||||
public static extern int GetCurrentProcessId();
|
||||
|
||||
[DllImport("kernel32", ExactSpelling = true)]
|
||||
public static extern IntPtr GetConsoleWindow();
|
||||
|
||||
// GetPriorityClass and SetPriorityClass
|
||||
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
|
||||
public static extern int GetPriorityClass(IntPtr hProcess);
|
||||
|
||||
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
|
||||
public static extern bool SetPriorityClass(IntPtr hProcess, int dwPriorityClass);
|
||||
|
||||
[DllImport("user32", CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
|
||||
|
||||
[DllImport("user32", CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using BepInEx.Configuration;
|
||||
using UXAssist.Common;
|
||||
|
||||
@@ -13,7 +13,6 @@ public static class WindowFunctions
|
||||
private const string GameWindowClass = "UnityWndClass";
|
||||
private static string _gameWindowTitle = "Dyson Sphere Program";
|
||||
|
||||
private static IntPtr _oldWndProc = IntPtr.Zero;
|
||||
private static IntPtr _gameWindowHandle = IntPtr.Zero;
|
||||
|
||||
public static ConfigEntry<int> ProcessPriority;
|
||||
@@ -36,8 +35,15 @@ public static class WindowFunctions
|
||||
|
||||
public static void Start()
|
||||
{
|
||||
ProcessPriority.SettingChanged += (_, _) => WinApi.SetPriorityClass(WinApi.GetCurrentProcess(), ProrityFlags[ProcessPriority.Value]);
|
||||
WinApi.SetPriorityClass(WinApi.GetCurrentProcess(), ProrityFlags[ProcessPriority.Value]);
|
||||
ProcessPriority.SettingChanged += (_, _) => ApplyProcessPriority();
|
||||
ApplyProcessPriority();
|
||||
}
|
||||
|
||||
private static void ApplyProcessPriority()
|
||||
{
|
||||
// Use the managed BCL wrapper instead of a raw kernel32 SetPriorityClass P/Invoke.
|
||||
using var process = Process.GetCurrentProcess();
|
||||
process.PriorityClass = (ProcessPriorityClass)ProrityFlags[ProcessPriority.Value];
|
||||
}
|
||||
|
||||
private static string GetPriorityName(int priority)
|
||||
@@ -92,16 +98,20 @@ public static class WindowFunctions
|
||||
{
|
||||
if (_gameWindowHandle != IntPtr.Zero)
|
||||
return _gameWindowHandle;
|
||||
// Match the game window by its Unity window class plus our own process id. Matching the
|
||||
// class excludes the BepInEx console window (class "ConsoleWindowClass"), which
|
||||
// Process.MainWindowHandle would otherwise return when the console is enabled; the pid
|
||||
// check guards against other running Unity apps. Process.Id supplies the pid so no extra
|
||||
// kernel32 P/Invoke (GetCurrentProcessId/GetConsoleWindow) is needed.
|
||||
int currentProcessId;
|
||||
using (var process = Process.GetCurrentProcess())
|
||||
currentProcessId = process.Id;
|
||||
var wnd = IntPtr.Zero;
|
||||
var consoleWnd = WinApi.GetConsoleWindow();
|
||||
var currentProcessId = WinApi.GetCurrentProcessId();
|
||||
while (true)
|
||||
{
|
||||
wnd = WinApi.FindWindowEx(IntPtr.Zero, wnd, GameWindowClass, _gameWindowTitle);
|
||||
wnd = WinApi.FindWindowEx(IntPtr.Zero, wnd, GameWindowClass, null);
|
||||
if (wnd == IntPtr.Zero)
|
||||
return IntPtr.Zero;
|
||||
if (wnd == consoleWnd)
|
||||
continue;
|
||||
WinApi.GetWindowThreadProcessId(wnd, out var pid);
|
||||
if (pid == currentProcessId)
|
||||
break;
|
||||
|
||||
@@ -48,6 +48,7 @@ public static class LogisticsPatch
|
||||
|
||||
public static ConfigEntry<bool> LogisticsCapacityTweaksEnabled;
|
||||
public static ConfigEntry<bool> AllowOverflowInLogisticsEnabled;
|
||||
public static ConfigEntry<bool> GreaterPowerUsageInLogisticsEnabled;
|
||||
public static ConfigEntry<bool> LogisticsConstrolPanelImprovementEnabled;
|
||||
public static ConfigEntry<bool> RealtimeLogisticsInfoPanelEnabled;
|
||||
public static ConfigEntry<bool> RealtimeLogisticsInfoPanelBarsEnabled;
|
||||
@@ -59,6 +60,7 @@ public static class LogisticsPatch
|
||||
SetDefaultRemoteLogicToStorage.SettingChanged += (_, _) => AutoConfigLogisticsSetDefaultRemoteLogicToStorage.Enable(SetDefaultRemoteLogicToStorage.Value);
|
||||
LogisticsCapacityTweaksEnabled.SettingChanged += (_, _) => LogisticsCapacityTweaks.Enable(LogisticsCapacityTweaksEnabled.Value);
|
||||
AllowOverflowInLogisticsEnabled.SettingChanged += (_, _) => AllowOverflowInLogistics.Enable(AllowOverflowInLogisticsEnabled.Value);
|
||||
GreaterPowerUsageInLogisticsEnabled.SettingChanged += (_, _) => GreaterPowerUsageInLogistics.Enable(GreaterPowerUsageInLogisticsEnabled.Value);
|
||||
LogisticsConstrolPanelImprovementEnabled.SettingChanged += (_, _) => LogisticsConstrolPanelImprovement.Enable(LogisticsConstrolPanelImprovementEnabled.Value);
|
||||
RealtimeLogisticsInfoPanelEnabled.SettingChanged += (_, _) => RealtimeLogisticsInfoPanel.Enable(RealtimeLogisticsInfoPanelEnabled.Value);
|
||||
RealtimeLogisticsInfoPanelBarsEnabled.SettingChanged += (_, _) => RealtimeLogisticsInfoPanel.EnableBars(RealtimeLogisticsInfoPanelBarsEnabled.Value);
|
||||
@@ -70,6 +72,7 @@ public static class LogisticsPatch
|
||||
AutoConfigLogisticsSetDefaultRemoteLogicToStorage.Enable(SetDefaultRemoteLogicToStorage.Value);
|
||||
LogisticsCapacityTweaks.Enable(LogisticsCapacityTweaksEnabled.Value);
|
||||
AllowOverflowInLogistics.Enable(AllowOverflowInLogisticsEnabled.Value);
|
||||
GreaterPowerUsageInLogistics.Enable(GreaterPowerUsageInLogisticsEnabled.Value);
|
||||
LogisticsConstrolPanelImprovement.Enable(LogisticsConstrolPanelImprovementEnabled.Value);
|
||||
RealtimeLogisticsInfoPanel.Enable(RealtimeLogisticsInfoPanelEnabled.Value);
|
||||
RealtimeLogisticsInfoPanel.EnableBars(RealtimeLogisticsInfoPanelBarsEnabled.Value);
|
||||
@@ -89,6 +92,7 @@ public static class LogisticsPatch
|
||||
AutoConfigLogisticsSetDefaultRemoteLogicToStorage.Enable(false);
|
||||
LogisticsCapacityTweaks.Enable(false);
|
||||
AllowOverflowInLogistics.Enable(false);
|
||||
GreaterPowerUsageInLogistics.Enable(false);
|
||||
LogisticsConstrolPanelImprovement.Enable(false);
|
||||
RealtimeLogisticsInfoPanel.Enable(false);
|
||||
}
|
||||
@@ -109,6 +113,241 @@ public static class LogisticsPatch
|
||||
}
|
||||
}
|
||||
|
||||
#region Apply auto-config values to existing facilities on the current planet
|
||||
|
||||
private enum StationKind
|
||||
{
|
||||
Pls,
|
||||
Ils,
|
||||
VeinCollector
|
||||
}
|
||||
|
||||
// === Per-field setters (single source of truth, shared by auto-config-on-build and apply-to-planet) ===
|
||||
|
||||
private static void StationSetChargePower(PlanetFactory factory, StationComponent station) =>
|
||||
factory.powerSystem.consumerPool[station.pcId].workEnergyPerTick =
|
||||
(long)((station.isStellar ? 250000.0 * AutoConfigILSChargePower.Value : 50000.0 * AutoConfigPLSChargePower.Value) + 0.5);
|
||||
|
||||
private static void StationSetTripRangeDrones(PlanetFactory factory, StationComponent station) =>
|
||||
station.tripRangeDrones = Math.Cos((station.isStellar ? AutoConfigILSMaxTripDrone.Value : AutoConfigPLSMaxTripDrone.Value) / 180.0 * Math.PI);
|
||||
|
||||
private static void StationSetDeliveryDrones(PlanetFactory factory, StationComponent station)
|
||||
{
|
||||
var v = station.isStellar ? AutoConfigILSDroneMinDeliver.Value : AutoConfigPLSDroneMinDeliver.Value;
|
||||
station.deliveryDrones = v == 0 ? 1 : v * 10;
|
||||
}
|
||||
|
||||
private static void StationSetPilerCount(PlanetFactory factory, StationComponent station) =>
|
||||
station.pilerCount = station.isStellar ? AutoConfigILSMinPilerValue.Value : AutoConfigPLSMinPilerValue.Value;
|
||||
|
||||
private static void StationFillDrones(PlanetFactory factory, StationComponent station)
|
||||
{
|
||||
var target = station.isStellar ? AutoConfigILSDroneCount.Value : AutoConfigPLSDroneCount.Value;
|
||||
var toFill = Math.Max(0, target - station.idleDroneCount - station.workDroneCount);
|
||||
if (toFill > 0) station.idleDroneCount += GameMain.data.mainPlayer.package.TakeItem((int)KnownItemId.Drone, toFill, out _);
|
||||
}
|
||||
|
||||
private static void StationSetTripRangeShips(PlanetFactory factory, StationComponent station) =>
|
||||
station.tripRangeShips = AutoConfigILSMaxTripShip.Value switch
|
||||
{
|
||||
<= 20 => AutoConfigILSMaxTripShip.Value,
|
||||
<= 40 => AutoConfigILSMaxTripShip.Value * 2 - 20,
|
||||
_ => 10000,
|
||||
} * 2400000.0;
|
||||
|
||||
private static void StationSetWarpDistance(PlanetFactory factory, StationComponent station) =>
|
||||
station.warpEnableDist = AutoConfigILSWarperDistance.Value switch
|
||||
{
|
||||
<= 7 => AutoConfigILSWarperDistance.Value * 0.5 - 0.5,
|
||||
<= 16 => AutoConfigILSWarperDistance.Value - 4.0,
|
||||
<= 20 => AutoConfigILSWarperDistance.Value * 2 - 20.0,
|
||||
_ => 60.0,
|
||||
} * 40000.0;
|
||||
|
||||
private static void StationSetDeliveryShips(PlanetFactory factory, StationComponent station)
|
||||
{
|
||||
var v = AutoConfigILSShipMinDeliver.Value;
|
||||
station.deliveryShips = v == 0 ? 1 : v * 10;
|
||||
}
|
||||
|
||||
private static void StationFillShips(PlanetFactory factory, StationComponent station)
|
||||
{
|
||||
var toFill = Math.Max(0, AutoConfigILSShipCount.Value - station.idleShipCount - station.workShipCount);
|
||||
if (toFill > 0) station.idleShipCount += GameMain.data.mainPlayer.package.TakeItem((int)KnownItemId.Ship, toFill, out _);
|
||||
}
|
||||
|
||||
private static void StationSetIncludeOrbitCollector(PlanetFactory factory, StationComponent station) =>
|
||||
station.includeOrbitCollector = AutoConfigILSIncludeOrbitCollector.Value;
|
||||
|
||||
private static void StationSetWarperNecessary(PlanetFactory factory, StationComponent station) =>
|
||||
station.warperNecessary = AutoConfigILSWarperNecessary.Value;
|
||||
|
||||
/* station.minerId may not be set yet on freshly built collectors, so resolve the minerId from the EntityData. */
|
||||
private static bool VeinCollectorSetHarvestSpeed(PlanetFactory factory, StationComponent station)
|
||||
{
|
||||
ref var entity = ref factory.entityPool[station.entityId];
|
||||
if (entity.id != station.entityId || entity.minerId <= 0 || entity.minerId >= factory.factorySystem.minerCursor) return false;
|
||||
factory.factorySystem.minerPool[entity.minerId].speed = 10000 + AutoConfigVeinCollectorHarvestSpeed.Value * 1000;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void VeinCollectorSetPilerCount(PlanetFactory factory, StationComponent station) =>
|
||||
station.pilerCount = AutoConfigVeinCollectorMinPilerValue.Value;
|
||||
|
||||
private static void DispenserSetChargePower(PlanetFactory factory, DispenserComponent dispenser) =>
|
||||
factory.powerSystem.consumerPool[dispenser.pcId].workEnergyPerTick = (long)(5000.0 * AutoConfigDispenserChargePower.Value + 0.5);
|
||||
|
||||
private static void DispenserFillCouriers(PlanetFactory factory, DispenserComponent dispenser)
|
||||
{
|
||||
var toFill = Math.Max(0, AutoConfigDispenserCourierCount.Value - dispenser.idleCourierCount - dispenser.workCourierCount);
|
||||
if (toFill > 0) dispenser.idleCourierCount += GameMain.data.mainPlayer.package.TakeItem((int)KnownItemId.Bot, toFill, out _);
|
||||
}
|
||||
|
||||
private static void BattleBaseSetChargePower(PlanetFactory factory, BattleBaseComponent battleBase) =>
|
||||
factory.powerSystem.consumerPool[battleBase.pcId].workEnergyPerTick = (long)(5000.0 * AutoConfigBattleBaseChargePower.Value + 0.5);
|
||||
|
||||
// === Per-facility "apply all settings" (also used as auto-config-on-build entry point) ===
|
||||
|
||||
private static void DoConfigStation(PlanetFactory factory, StationComponent station)
|
||||
{
|
||||
if (station.isCollector) return;
|
||||
if (station.isVeinCollector)
|
||||
{
|
||||
if (VeinCollectorSetHarvestSpeed(factory, station))
|
||||
VeinCollectorSetPilerCount(factory, station);
|
||||
return;
|
||||
}
|
||||
if (!station.isStellar)
|
||||
{
|
||||
StationSetChargePower(factory, station);
|
||||
StationSetTripRangeDrones(factory, station);
|
||||
StationSetDeliveryDrones(factory, station);
|
||||
StationSetPilerCount(factory, station);
|
||||
StationFillDrones(factory, station);
|
||||
return;
|
||||
}
|
||||
StationSetChargePower(factory, station);
|
||||
StationSetTripRangeDrones(factory, station);
|
||||
StationSetTripRangeShips(factory, station);
|
||||
StationSetWarpDistance(factory, station);
|
||||
StationSetDeliveryDrones(factory, station);
|
||||
StationSetDeliveryShips(factory, station);
|
||||
StationSetPilerCount(factory, station);
|
||||
StationSetIncludeOrbitCollector(factory, station);
|
||||
StationSetWarperNecessary(factory, station);
|
||||
StationFillDrones(factory, station);
|
||||
StationFillShips(factory, station);
|
||||
}
|
||||
|
||||
// === Iterate over the current planet's facilities of a given kind ===
|
||||
|
||||
private static void ForEachStation(StationKind kind, Action<PlanetFactory, StationComponent> action)
|
||||
{
|
||||
var factory = GameMain.localPlanet?.factory;
|
||||
var transport = factory?.transport;
|
||||
var stationPool = transport?.stationPool;
|
||||
if (stationPool == null) return;
|
||||
for (var i = transport.stationCursor - 1; i > 0; i--)
|
||||
{
|
||||
var station = stationPool[i];
|
||||
if (station == null || station.id != i || station.isCollector) continue;
|
||||
var skip = kind switch
|
||||
{
|
||||
StationKind.VeinCollector => !station.isVeinCollector,
|
||||
StationKind.Ils => station.isVeinCollector || !station.isStellar,
|
||||
StationKind.Pls => station.isVeinCollector || station.isStellar,
|
||||
_ => true
|
||||
};
|
||||
if (skip) continue;
|
||||
action(factory, station);
|
||||
}
|
||||
RefreshOpenLogisticsWindows();
|
||||
}
|
||||
|
||||
private static void ForEachDispenser(Action<PlanetFactory, DispenserComponent> action)
|
||||
{
|
||||
var factory = GameMain.localPlanet?.factory;
|
||||
var transport = factory?.transport;
|
||||
var dispenserPool = transport?.dispenserPool;
|
||||
if (dispenserPool == null) return;
|
||||
for (var i = transport.dispenserCursor - 1; i > 0; i--)
|
||||
{
|
||||
var dispenser = dispenserPool[i];
|
||||
if (dispenser == null || dispenser.id != i) continue;
|
||||
action(factory, dispenser);
|
||||
}
|
||||
RefreshOpenLogisticsWindows();
|
||||
}
|
||||
|
||||
private static void ForEachBattleBase(Action<PlanetFactory, BattleBaseComponent> action)
|
||||
{
|
||||
var factory = GameMain.localPlanet?.factory;
|
||||
var battleBases = factory?.defenseSystem?.battleBases;
|
||||
if (battleBases?.buffer == null) return;
|
||||
for (var i = battleBases.cursor - 1; i > 0; i--)
|
||||
{
|
||||
var battleBase = battleBases.buffer[i];
|
||||
if (battleBase == null || battleBase.id != i) continue;
|
||||
action(factory, battleBase);
|
||||
}
|
||||
RefreshOpenLogisticsWindows();
|
||||
}
|
||||
|
||||
// Re-populate any open logistic facility detail window so applied values show immediately.
|
||||
private static void RefreshOpenLogisticsWindows()
|
||||
{
|
||||
var uiRoot = UIRoot.instance;
|
||||
if (!uiRoot) return;
|
||||
var uiGame = uiRoot.uiGame;
|
||||
if (!uiGame) return;
|
||||
var stationWindow = uiGame.stationWindow;
|
||||
if (stationWindow && stationWindow.active) stationWindow.OnStationIdChange();
|
||||
var dispenserWindow = uiGame.dispenserWindow;
|
||||
if (dispenserWindow && dispenserWindow.active) dispenserWindow.OnDispenserIdChange();
|
||||
var battleBaseWindow = uiGame.battleBaseWindow;
|
||||
if (battleBaseWindow && battleBaseWindow.active) battleBaseWindow.OnBattleBaseIdChange();
|
||||
}
|
||||
|
||||
// === Public entry points invoked by the config panel buttons ===
|
||||
|
||||
// Dispenser
|
||||
public static void ApplyDispenserChargePower() => ForEachDispenser(DispenserSetChargePower);
|
||||
public static void ApplyDispenserCourierCount() => ForEachDispenser(DispenserFillCouriers);
|
||||
public static void ApplyAllDispenser() => ForEachDispenser((f, d) => { DispenserSetChargePower(f, d); DispenserFillCouriers(f, d); });
|
||||
|
||||
// Battlefield Analysis Base
|
||||
public static void ApplyBattleBaseChargePower() => ForEachBattleBase(BattleBaseSetChargePower);
|
||||
public static void ApplyAllBattleBase() => ForEachBattleBase(BattleBaseSetChargePower);
|
||||
|
||||
// PLS
|
||||
public static void ApplyPLSChargePower() => ForEachStation(StationKind.Pls, StationSetChargePower);
|
||||
public static void ApplyPLSTripRangeDrones() => ForEachStation(StationKind.Pls, StationSetTripRangeDrones);
|
||||
public static void ApplyPLSDroneMinDeliver() => ForEachStation(StationKind.Pls, StationSetDeliveryDrones);
|
||||
public static void ApplyPLSMinPilerValue() => ForEachStation(StationKind.Pls, StationSetPilerCount);
|
||||
public static void ApplyPLSDroneCount() => ForEachStation(StationKind.Pls, StationFillDrones);
|
||||
public static void ApplyAllPLS() => ForEachStation(StationKind.Pls, DoConfigStation);
|
||||
|
||||
// ILS
|
||||
public static void ApplyILSChargePower() => ForEachStation(StationKind.Ils, StationSetChargePower);
|
||||
public static void ApplyILSTripRangeDrones() => ForEachStation(StationKind.Ils, StationSetTripRangeDrones);
|
||||
public static void ApplyILSTripRangeShips() => ForEachStation(StationKind.Ils, StationSetTripRangeShips);
|
||||
public static void ApplyILSWarpDistance() => ForEachStation(StationKind.Ils, StationSetWarpDistance);
|
||||
public static void ApplyILSDroneMinDeliver() => ForEachStation(StationKind.Ils, StationSetDeliveryDrones);
|
||||
public static void ApplyILSShipMinDeliver() => ForEachStation(StationKind.Ils, StationSetDeliveryShips);
|
||||
public static void ApplyILSMinPilerValue() => ForEachStation(StationKind.Ils, StationSetPilerCount);
|
||||
public static void ApplyILSDroneCount() => ForEachStation(StationKind.Ils, StationFillDrones);
|
||||
public static void ApplyILSShipCount() => ForEachStation(StationKind.Ils, StationFillShips);
|
||||
public static void ApplyILSIncludeOrbitCollector() => ForEachStation(StationKind.Ils, StationSetIncludeOrbitCollector);
|
||||
public static void ApplyILSWarperNecessary() => ForEachStation(StationKind.Ils, StationSetWarperNecessary);
|
||||
public static void ApplyAllILS() => ForEachStation(StationKind.Ils, DoConfigStation);
|
||||
|
||||
// Vein Collector (Advanced Mining Machine)
|
||||
public static void ApplyVeinCollectorHarvestSpeed() => ForEachStation(StationKind.VeinCollector, (f, s) => VeinCollectorSetHarvestSpeed(f, s));
|
||||
public static void ApplyVeinCollectorMinPilerValue() => ForEachStation(StationKind.VeinCollector, VeinCollectorSetPilerCount);
|
||||
public static void ApplyAllVeinCollector() => ForEachStation(StationKind.VeinCollector, DoConfigStation);
|
||||
|
||||
#endregion
|
||||
|
||||
private class AutoConfigLogistics : PatchImpl<AutoConfigLogistics>
|
||||
{
|
||||
protected override void OnEnable()
|
||||
@@ -180,66 +419,6 @@ public static class LogisticsPatch
|
||||
}
|
||||
}
|
||||
|
||||
private static void DoConfigStation(PlanetFactory factory, StationComponent station)
|
||||
{
|
||||
if (station.isCollector) return;
|
||||
if (station.isVeinCollector)
|
||||
{
|
||||
/* station.minerId is not set at this point, so we need to fetch the minerId from the EntityData */
|
||||
ref var entity = ref factory.entityPool[station.entityId];
|
||||
if (entity.id != station.entityId || entity.minerId <= 0 || entity.minerId >= factory.factorySystem.minerCursor) return;
|
||||
factory.factorySystem.minerPool[entity.minerId].speed = 10000 + AutoConfigVeinCollectorHarvestSpeed.Value * 1000;
|
||||
station.pilerCount = AutoConfigVeinCollectorMinPilerValue.Value;
|
||||
return;
|
||||
}
|
||||
int toFill;
|
||||
if (!station.isStellar)
|
||||
{
|
||||
factory.powerSystem.consumerPool[station.pcId].workEnergyPerTick = (long)(50000.0 * AutoConfigPLSChargePower.Value + 0.5);
|
||||
station.tripRangeDrones = Math.Cos(AutoConfigPLSMaxTripDrone.Value / 180.0 * Math.PI);
|
||||
station.deliveryDrones = AutoConfigPLSDroneMinDeliver.Value switch { 0 => 1, _ => AutoConfigPLSDroneMinDeliver.Value * 10 };
|
||||
station.pilerCount = AutoConfigPLSMinPilerValue.Value;
|
||||
toFill = Math.Max(0, AutoConfigPLSDroneCount.Value - station.idleDroneCount - station.workDroneCount);
|
||||
if (toFill > 0) station.idleDroneCount += GameMain.data.mainPlayer.package.TakeItem((int)KnownItemId.Drone, toFill, out _);
|
||||
return;
|
||||
}
|
||||
factory.powerSystem.consumerPool[station.pcId].workEnergyPerTick = (long)(250000.0 * AutoConfigILSChargePower.Value + 0.5);
|
||||
station.tripRangeDrones = Math.Cos(AutoConfigILSMaxTripDrone.Value / 180.0 * Math.PI);
|
||||
station.tripRangeShips = AutoConfigILSMaxTripShip.Value switch
|
||||
{
|
||||
<= 20 => AutoConfigILSMaxTripShip.Value,
|
||||
<= 40 => AutoConfigILSMaxTripShip.Value * 2 - 20,
|
||||
_ => 10000,
|
||||
} * 2400000.0;
|
||||
station.warpEnableDist = AutoConfigILSWarperDistance.Value switch
|
||||
{
|
||||
<= 7 => AutoConfigILSWarperDistance.Value * 0.5 - 0.5,
|
||||
<= 16 => AutoConfigILSWarperDistance.Value - 4.0,
|
||||
<= 20 => AutoConfigILSWarperDistance.Value * 2 - 20.0,
|
||||
_ => 60.0,
|
||||
} * 40000.0;
|
||||
station.deliveryDrones = AutoConfigILSDroneMinDeliver.Value switch { 0 => 1, _ => AutoConfigILSDroneMinDeliver.Value * 10 };
|
||||
station.deliveryShips = AutoConfigILSShipMinDeliver.Value switch { 0 => 1, _ => AutoConfigILSShipMinDeliver.Value * 10 };
|
||||
station.pilerCount = AutoConfigILSMinPilerValue.Value;
|
||||
station.includeOrbitCollector = AutoConfigILSIncludeOrbitCollector.Value;
|
||||
station.warperNecessary = AutoConfigILSWarperNecessary.Value;
|
||||
toFill = Math.Max(0, AutoConfigILSDroneCount.Value - station.idleDroneCount - station.workDroneCount);
|
||||
if (toFill > 0) station.idleDroneCount += GameMain.data.mainPlayer.package.TakeItem((int)KnownItemId.Drone, toFill, out _);
|
||||
toFill = Math.Max(0, AutoConfigILSShipCount.Value - station.idleShipCount - station.workShipCount);
|
||||
if (toFill > 0) station.idleShipCount += GameMain.data.mainPlayer.package.TakeItem((int)KnownItemId.Ship, toFill, out _);
|
||||
}
|
||||
|
||||
private static void DoConfigDispenser(PlanetFactory factory, DispenserComponent dispenser)
|
||||
{
|
||||
var toFill = Math.Max(0, AutoConfigDispenserCourierCount.Value - dispenser.idleCourierCount - dispenser.workCourierCount);
|
||||
if (toFill > 0) dispenser.idleCourierCount += GameMain.data.mainPlayer.package.TakeItem((int)KnownItemId.Bot, toFill, out _);
|
||||
}
|
||||
|
||||
private static void DoConfigBattleBase(PlanetFactory factory, BattleBaseComponent battleBase)
|
||||
{
|
||||
factory.powerSystem.consumerPool[battleBase.pcId].workEnergyPerTick = (long)(5000.0 * AutoConfigBattleBaseChargePower.Value + 0.5);
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(BuildTool_Addon), nameof(BuildTool_Addon.SetDefaultParams))]
|
||||
private static void BuildTool_Addon_SetDefaultParams_Postfix(BuildTool_Addon __instance, int bpIndex)
|
||||
@@ -262,7 +441,7 @@ public static class LogisticsPatch
|
||||
private static void DefenseSystem_NewBattleBaseComponent_Postfix(DefenseSystem __instance, int __result)
|
||||
{
|
||||
if (__result <= 0) return;
|
||||
DoConfigBattleBase(__instance.factory, __instance.battleBases[__result]);
|
||||
BattleBaseSetChargePower(__instance.factory, __instance.battleBases[__result]);
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
@@ -270,7 +449,7 @@ public static class LogisticsPatch
|
||||
private static void PlanetTransport_NewDispenserComponent_Postfix(PlanetTransport __instance, int __result)
|
||||
{
|
||||
if (__result <= 0) return;
|
||||
DoConfigDispenser(__instance.factory, __instance.dispenserPool[__result]);
|
||||
DispenserFillCouriers(__instance.factory, __instance.dispenserPool[__result]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,6 +784,156 @@ public static class LogisticsPatch
|
||||
}
|
||||
}
|
||||
|
||||
private class GreaterPowerUsageInLogistics : PatchImpl<GreaterPowerUsageInLogistics>
|
||||
{
|
||||
protected override void OnEnable()
|
||||
{
|
||||
var window = UIRoot.instance?.uiGame?.stationWindow;
|
||||
if (window == null) return;
|
||||
window._Close();
|
||||
window.maxMiningSpeedSlider.maxValue = 27f;
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
var window = UIRoot.instance?.uiGame?.stationWindow;
|
||||
if (window == null) return;
|
||||
window._Close();
|
||||
window.maxMiningSpeedSlider.maxValue = 20f;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UIStationWindow), nameof(UIStationWindow.OnStationIdChange))]
|
||||
private static IEnumerable<CodeInstruction> UIStationWindow_OnStationIdChange_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.Start().Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0),
|
||||
Transpilers.EmitDelegate((UIStationWindow window) =>
|
||||
{
|
||||
window.maxMiningSpeedSlider.maxValue = 27f;
|
||||
})
|
||||
).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStationWindow), nameof(UIStationWindow.maxChargePowerSlider))),
|
||||
new CodeMatch(ci => ci.IsLdloc()),
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4 && ci.OperandIs(0xC350)),
|
||||
new CodeMatch(OpCodes.Conv_I8)
|
||||
);
|
||||
var pos = matcher.Pos + 1;
|
||||
matcher.Advance(5).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Conv_R4),
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertySetter(typeof(Slider), nameof(Slider.value)))
|
||||
);
|
||||
var pos2 = matcher.Pos + 2;
|
||||
matcher.Start().Advance(pos);
|
||||
var ldvar = matcher.InstructionAt(1).Clone();
|
||||
var locWorkEnergyPerTick = matcher.InstructionAt(-2).operand;
|
||||
matcher.RemoveInstructions(pos2 - pos).InsertAndAdvance(
|
||||
ldvar,
|
||||
new CodeInstruction(OpCodes.Ldloc_S, locWorkEnergyPerTick),
|
||||
Transpilers.EmitDelegate((UIStationWindow window, long maxWorkEnergy, long workEnergyPerTick) =>
|
||||
{
|
||||
var maxSliderValue = maxWorkEnergy / 50000L;
|
||||
window.maxChargePowerSlider.maxValue = maxSliderValue + 9;
|
||||
window.maxChargePowerSlider.minValue = maxWorkEnergy / 500000L;
|
||||
if (workEnergyPerTick <= maxWorkEnergy)
|
||||
window.maxChargePowerSlider.Set(workEnergyPerTick / 50000L, false);
|
||||
else
|
||||
window.maxChargePowerSlider.Set(maxSliderValue + (workEnergyPerTick - 1) / maxWorkEnergy + 1, false);
|
||||
})
|
||||
);
|
||||
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStationWindow), nameof(UIStationWindow.maxMiningSpeedSlider))),
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStationWindow), nameof(UIStationWindow.factorySystem))),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(FactorySystem), nameof(FactorySystem.minerPool))),
|
||||
new CodeMatch(ci => ci.IsLdloc()),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(StationComponent), nameof(StationComponent.minerId))),
|
||||
new CodeMatch(OpCodes.Ldelema, typeof(MinerComponent)),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(MinerComponent), nameof(MinerComponent.speed)))
|
||||
);
|
||||
pos = matcher.Pos + 9;
|
||||
matcher.Advance(5).MatchForward(false,
|
||||
new CodeMatch(OpCodes.Conv_R4),
|
||||
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertySetter(typeof(Slider), nameof(Slider.value)))
|
||||
);
|
||||
pos2 = matcher.Pos;
|
||||
matcher.Start().Advance(pos).RemoveInstructions(pos2 - pos).Insert(
|
||||
Transpilers.EmitDelegate((int speed) =>
|
||||
{
|
||||
if (speed <= 30000)
|
||||
return (speed - 10000) / 1000;
|
||||
return (speed - 30000) / 10000 + 20;
|
||||
})
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UIStationWindow), nameof(UIStationWindow.OnMaxMiningSpeedChange))]
|
||||
private static IEnumerable<CodeInstruction> UIStationWindow_OnMaxMiningSpeedChange_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(ci => ci.opcode == OpCodes.Ldc_I4 && ci.OperandIs(10000)),
|
||||
new CodeMatch(OpCodes.Ldarg_1)
|
||||
);
|
||||
var pos = matcher.Pos;
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Stloc_1)
|
||||
);
|
||||
var pos2 = matcher.Pos;
|
||||
matcher.Start().Advance(pos);
|
||||
var labels = matcher.Labels;
|
||||
matcher.RemoveInstructions(pos2 - pos);
|
||||
matcher.Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_1).WithLabels(labels),
|
||||
Transpilers.EmitDelegate((float value) =>
|
||||
{
|
||||
var intval = (int)(value + 0.5f);
|
||||
if (intval <= 20)
|
||||
return intval * 1000 + 10000;
|
||||
return (intval - 20) * 10000 + 30000;
|
||||
})
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(UIStationWindow), nameof(UIStationWindow.OnMaxChargePowerSliderValueChange))]
|
||||
private static IEnumerable<CodeInstruction> UIStationWindow_OnMaxChargePowerSliderValueChange_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
matcher.MatchForward(false,
|
||||
new CodeMatch(OpCodes.Ldarg_0),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStationWindow), nameof(UIStationWindow.factory))),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PlanetFactory), nameof(PlanetFactory.powerSystem))),
|
||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PowerSystem), nameof(PowerSystem.consumerPool)))
|
||||
);
|
||||
var labels = matcher.Labels;
|
||||
matcher.Labels = null;
|
||||
matcher.Insert(
|
||||
new CodeInstruction(OpCodes.Ldarg_0).WithLabels(labels),
|
||||
new CodeInstruction(OpCodes.Ldarg_1),
|
||||
Transpilers.EmitDelegate((UIStationWindow window, float value) =>
|
||||
{
|
||||
float prevMax = window.workEnergyPrefab * 5L / 50000L;
|
||||
if (value <= prevMax)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return prevMax * (value - prevMax + 1);
|
||||
}),
|
||||
new CodeInstruction(OpCodes.Starg_S, 1)
|
||||
);
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
private class LogisticsConstrolPanelImprovement : PatchImpl<LogisticsConstrolPanelImprovement>
|
||||
{
|
||||
private static int ItemIdHintUnderMouse()
|
||||
|
||||
@@ -192,7 +192,7 @@ public class PersistPatch : PatchImpl<PersistPatch>
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
// Disable rendering when hideAllUI0 is true
|
||||
// Disable rendering when Player is hidden (Press F11 twice)
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic.LateUpdate))]
|
||||
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic.Draw))]
|
||||
@@ -203,9 +203,10 @@ public class PersistPatch : PatchImpl<PersistPatch>
|
||||
matcher.Start();
|
||||
matcher.CreateLabel(out var label);
|
||||
matcher.InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(UIRoot), nameof(UIRoot.instance))),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UIRoot), nameof(UIRoot.uiGame))),
|
||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UIGame), nameof(UIGame.hideAllUI0))),
|
||||
Transpilers.EmitDelegate(bool () =>
|
||||
{
|
||||
return GameMain.localPlanet == null && !GameMain.mainPlayer.controller.modelVisible;
|
||||
}),
|
||||
new CodeInstruction(OpCodes.Brfalse, label),
|
||||
new CodeInstruction(OpCodes.Ret)
|
||||
);
|
||||
@@ -213,55 +214,11 @@ public class PersistPatch : PatchImpl<PersistPatch>
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
static bool _preHideAllUI0 = false;
|
||||
static bool _localPlanetChanged = false;
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(UIGame), nameof(UIGame._OnLateUpdate))]
|
||||
private static void UIGame__OnLateUpdate_Prefix(UIGame __instance)
|
||||
{
|
||||
_preHideAllUI0 = __instance.hideAllUI0;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(UIGame), nameof(UIGame._OnLateUpdate))]
|
||||
private static void UIGame__OnLateUpdate_Postfix(UIGame __instance)
|
||||
{
|
||||
var hideAllUI0 = __instance.hideAllUI0;
|
||||
if (_localPlanetChanged)
|
||||
{
|
||||
_localPlanetChanged = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_preHideAllUI0 == hideAllUI0) return;
|
||||
}
|
||||
var show = GameMain.localPlanet != null || !hideAllUI0;
|
||||
GameMain.data?.mainPlayer?.effect.sailEffect.gameObject.SetActive(!hideAllUI0);
|
||||
var universeSimulator = GameMain.universeSimulator;
|
||||
if (universeSimulator == null) return;
|
||||
universeSimulator.gameObject.SetActive(show);
|
||||
var planetSimulators = universeSimulator.planetSimulators;
|
||||
if (planetSimulators == null) return;
|
||||
foreach (var planet in planetSimulators)
|
||||
{
|
||||
if (planet == null) continue;
|
||||
planet.gameObject.SetActive(show);
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(UniverseSimulator), nameof(UniverseSimulator.SetPlanetSimulator))]
|
||||
private static void UniverseSimulator_SetPlanetSimulator_Postfix(UniverseSimulator __instance, PlanetSimulator sim)
|
||||
{
|
||||
if (GameMain.localPlanet == null && UIRoot.instance.uiGame.hideAllUI0) sim.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(GameData), nameof(GameData.localPlanet), MethodType.Setter)]
|
||||
private static void GameData_localPlanet_Setter_Prefix(GameData __instance, PlanetData value)
|
||||
{
|
||||
var oldPlanet = __instance.localPlanet;
|
||||
if (oldPlanet == null && value != null || oldPlanet != null && value == null) _localPlanetChanged = true;
|
||||
if (GameMain.localPlanet == null && !GameMain.mainPlayer.controller.modelVisible) sim.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
#region Cluster Upload Result
|
||||
|
||||
@@ -104,6 +104,9 @@
|
||||
* Real-time logistic stations info panel
|
||||
* Auto-config logistic stations
|
||||
* Auto-config buildings include: Logistics Distributor, PLS, ILS, Advanced Mining Machine
|
||||
* Apply settings to all existing facilities on the current planet
|
||||
* Each setting on the Logistics tab has an `Apply` button that pushes that single value to all facilities of that type on the current planet.
|
||||
* Each category header (Logistics Distributor, Battlefield Analysis Base, PLS, ILS, Advanced Mining Machine) has an `Apply All` button that pushes every setting of that category to all facilities of that type on the current planet.
|
||||
* Player/Mecha
|
||||
* Unlimited interactive range
|
||||
* Enable player actions in globe view
|
||||
@@ -268,6 +271,9 @@
|
||||
* 注意:如果你启用了`Auxilaryfunction`中的`展示物流站信息`,此功能将被隐藏
|
||||
* 自动配置物流站
|
||||
* 自动配置的建筑包括:物流配送器、行星物流站、星际物流站、高级采矿机
|
||||
* 将设置应用到当前行星上所有已建成的物流设施
|
||||
* 物流标签页上每一项设置右侧都有一个`应用`按钮,按下后将该项数值应用到当前行星上所有该类型的物流设施。
|
||||
* 每个大分类标题(物流配送器、战场分析基站、行星物流站、星际物流站、大型采矿机)右侧都有一个`应用全部`按钮,按下后将该分类的所有设置数值应用到当前行星上所有该类型的物流设施。
|
||||
* 玩家/机甲
|
||||
* 无限交互距离
|
||||
* 移除建造数量和范围限制
|
||||
|
||||
@@ -79,6 +79,15 @@ public class MyFlatButton : MonoBehaviour
|
||||
return this;
|
||||
}
|
||||
|
||||
public MyFlatButton WithFontSize(int fontSize)
|
||||
{
|
||||
if (labelText != null)
|
||||
{
|
||||
labelText.fontSize = fontSize;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public MyFlatButton WithTip(string tip, float delay = 1f)
|
||||
{
|
||||
uiButton.tips.type = UIButton.ItemTipType.Other;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UXAssist.Common;
|
||||
using UXAssist.Functions;
|
||||
using UXAssist.ModsCompat;
|
||||
@@ -98,8 +99,14 @@ public static class UIConfigWindow
|
||||
I18N.Add("Count of Vessels filled", "Count of Vessels filled", "填充的运输船数量");
|
||||
I18N.Add("Collecting Speed", "Collecting Speed", "开采速度");
|
||||
I18N.Add("Min. Piler Value", "Outgoing integration count", "输出货物集装数量");
|
||||
I18N.Add("Apply config to planet", "Apply", "应用");
|
||||
I18N.Add("Apply all config to planet", "Apply All", "应用全部");
|
||||
I18N.Add("Apply config to planet tips", "Apply this value to all facilities of this type on the current planet", "将此项数值应用到当前行星上所有该类型物流设施");
|
||||
I18N.Add("Apply all config to planet tips", "Apply all settings of this category to all facilities of this type on the current planet", "将本分类的所有设置数值应用到当前行星上所有该类型物流设施");
|
||||
|
||||
I18N.Add("Allow overflow for Logistic Stations and Advanced Mining Machines", "Allow overflow for Logistic Stations and Advanced Mining Machines", "允许物流站和大型采矿机物品溢出");
|
||||
I18N.Add("Increase maximum power usage in Logistic Stations and Advanced Mining Machines", "Increase maximum power usage in Logistic Stations and Advanced Mining Machines",
|
||||
"提升物流塔和大型采矿机的最大功耗");
|
||||
I18N.Add("Enhance control for logistic storage capacities", "Enhance control for logistic storage capacities", "物流塔存储容量控制改进");
|
||||
I18N.Add("Enhance control for logistic storage capacities tips",
|
||||
"Logistic storage capacity limits are not scaled on upgrading 'Logistics Carrier Capacity', if they are not set to maximum capacity or already greater than upgraded maximum capacity.\nUse arrow keys to adjust logistic storage capacities:\n \u2190/\u2192: -/+10 \u2193\u2191: -/+100",
|
||||
@@ -529,6 +536,8 @@ public static class UIConfigWindow
|
||||
wnd.AddTipsButton2(x + checkBoxForMeasureTextWidth.Width + 5f, y + 6f, tab3, "Enhance control for logistic storage capacities", "Enhance control for logistic storage capacities tips", "enhanced-logistic-capacities-tips");
|
||||
y += 36f;
|
||||
wnd.AddCheckBox(x, y, tab3, LogisticsPatch.AllowOverflowInLogisticsEnabled, "Allow overflow for Logistic Stations and Advanced Mining Machines");
|
||||
y += 30f;
|
||||
wnd.AddCheckBox(x, y, tab2, LogisticsPatch.GreaterPowerUsageInLogisticsEnabled, "Increase maximum power usage in Logistic Stations and Advanced Mining Machines");
|
||||
y += 36f;
|
||||
checkBoxForMeasureTextWidth = wnd.AddCheckBox(x, y, tab3, LogisticsPatch.LogisticsConstrolPanelImprovementEnabled, "Logistics Control Panel Improvement");
|
||||
wnd.AddTipsButton2(x + checkBoxForMeasureTextWidth.Width + 5f, y + 6f, tab3, "Logistics Control Panel Improvement", "Logistics Control Panel Improvement tips", "lcp-improvement-tips");
|
||||
@@ -573,6 +582,7 @@ public static class UIConfigWindow
|
||||
y += 16f;
|
||||
var maxWidth = 0f;
|
||||
wnd.AddText2(10f, y, tab3, "Dispenser", 14, "text-dispenser");
|
||||
var dispenserCatY = y;
|
||||
y += 18f;
|
||||
var oy = y;
|
||||
x = 20f;
|
||||
@@ -583,11 +593,13 @@ public static class UIConfigWindow
|
||||
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
|
||||
y += 18f;
|
||||
wnd.AddText2(10f, y, tab3, "Battlefield Analysis Base", 14, "text-battlefield-analysis-base");
|
||||
var battleBaseCatY = y;
|
||||
y += 18f;
|
||||
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Max. Charging Power", 13, "text-battlefield-analysis-base-max-charging-power");
|
||||
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
|
||||
y += 18f;
|
||||
wnd.AddText2(10f, y, tab3, "PLS", 14, "text-pls");
|
||||
var plsCatY = y;
|
||||
y += 18f;
|
||||
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Max. Charging Power", 13, "text-pls-max-charging-power");
|
||||
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
|
||||
@@ -605,6 +617,7 @@ public static class UIConfigWindow
|
||||
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
|
||||
y += 18f;
|
||||
wnd.AddText2(10f, y, tab3, "ILS", 14, "text-ils");
|
||||
var ilsCatY = y;
|
||||
y += 18f;
|
||||
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Max. Charging Power", 13, "text-ils-max-charging-power");
|
||||
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
|
||||
@@ -614,11 +627,9 @@ public static class UIConfigWindow
|
||||
y += 18f;
|
||||
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Vessel transport range", 13, "text-ils-vessel-transport-range");
|
||||
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
|
||||
wnd.AddCheckBox(x + 360f, y + 6f, tab3, LogisticsPatch.AutoConfigILSIncludeOrbitCollector, "Include Orbital Collector", 13).WithSmallerBox();
|
||||
y += 18f;
|
||||
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Warp distance", 13, "text-ils-warp-distance");
|
||||
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
|
||||
wnd.AddCheckBox(x + 360f, y + 6f, tab3, LogisticsPatch.AutoConfigILSWarperNecessary, "Warpers required", 13).WithSmallerBox();
|
||||
y += 18f;
|
||||
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Min. Load of Drones", 13, "text-ils-min-load-of-drones");
|
||||
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
|
||||
@@ -636,6 +647,7 @@ public static class UIConfigWindow
|
||||
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
|
||||
y += 18f;
|
||||
wnd.AddText2(10f, y, tab3, "Advanced Mining Machine", 14, "text-amm");
|
||||
var ammCatY = y;
|
||||
y += 18f;
|
||||
textForMeasureTextWidth = wnd.AddText2(x, y, tab3, "Collecting Speed", 13, "text-amm-collecting-speed");
|
||||
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
|
||||
@@ -644,43 +656,95 @@ public static class UIConfigWindow
|
||||
maxWidth = Mathf.Max(maxWidth, textForMeasureTextWidth.preferredWidth);
|
||||
y = oy + 1;
|
||||
var nx = x + maxWidth + 5f + 10f;
|
||||
const float applyBtnWidth = 44f;
|
||||
const float applyBtnHeight = 15f;
|
||||
const int applyBtnFontSize = 11;
|
||||
const float applyAllBtnWidth = 58f;
|
||||
var applyBtnX = nx + 265f;
|
||||
// Right-align the wider "Apply All" buttons with the right edge of the per-option "Apply" buttons.
|
||||
var applyAllBtnX = applyBtnX + applyBtnWidth - applyAllBtnWidth;
|
||||
var checkBoxX = applyBtnX + applyBtnWidth + 12f;
|
||||
|
||||
// Buttons are vertically centered on their row (NormalizeRectWithTopLeft places y at the top edge).
|
||||
void AddApplyButtonAt(float bx, float rowY, string objName, UnityAction onClick) =>
|
||||
wnd.AddFlatButton(bx, rowY + 6f, tab3, "Apply config to planet", applyBtnFontSize, objName, onClick).WithSize(applyBtnWidth, applyBtnHeight)
|
||||
.WithFontSize(applyBtnFontSize).WithTip("Apply config to planet tips".Translate());
|
||||
|
||||
void AddApplyButton(float rowY, string objName, UnityAction onClick) => AddApplyButtonAt(applyBtnX, rowY, objName, onClick);
|
||||
|
||||
void AddCategoryApplyButton(float catY, string objName, UnityAction onClick) =>
|
||||
wnd.AddFlatButton(applyAllBtnX, catY + 7f, tab3, "Apply all config to planet", applyBtnFontSize, objName, onClick).WithSize(applyAllBtnWidth, applyBtnHeight)
|
||||
.WithFontSize(applyBtnFontSize).WithTip("Apply all config to planet tips".Translate());
|
||||
|
||||
AddCategoryApplyButton(dispenserCatY, "btn-apply-all-dispenser", LogisticsPatch.ApplyAllDispenser);
|
||||
AddCategoryApplyButton(battleBaseCatY, "btn-apply-all-battle-base", LogisticsPatch.ApplyAllBattleBase);
|
||||
AddCategoryApplyButton(plsCatY, "btn-apply-all-pls", LogisticsPatch.ApplyAllPLS);
|
||||
AddCategoryApplyButton(ilsCatY, "btn-apply-all-ils", LogisticsPatch.ApplyAllILS);
|
||||
AddCategoryApplyButton(ammCatY, "btn-apply-all-amm", LogisticsPatch.ApplyAllVeinCollector);
|
||||
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigDispenserChargePower, new AutoConfigDispenserChargePowerMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-dispenser-charge-power", LogisticsPatch.ApplyDispenserChargePower);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigDispenserCourierCount, new MyWindow.RangeValueMapper<int>(0, 10), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-dispenser-courier-count", LogisticsPatch.ApplyDispenserCourierCount);
|
||||
y += 36f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigBattleBaseChargePower, new AutoConfigBattleBaseChargePowerMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-battle-base-charge-power", LogisticsPatch.ApplyBattleBaseChargePower);
|
||||
y += 36f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigPLSChargePower, new AutoConfigPLSChargePowerMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-pls-charge-power", LogisticsPatch.ApplyPLSChargePower);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigPLSMaxTripDrone, new MyWindow.RangeValueMapper<int>(1, 180), "0°", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-pls-trip-range-drones", LogisticsPatch.ApplyPLSTripRangeDrones);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigPLSDroneMinDeliver, new AutoConfigCarrierMinDeliverMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-pls-drone-min-deliver", LogisticsPatch.ApplyPLSDroneMinDeliver);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigPLSMinPilerValue, new AutoConfigMinPilerValueMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-pls-min-piler-value", LogisticsPatch.ApplyPLSMinPilerValue);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigPLSDroneCount, new MyWindow.RangeValueMapper<int>(0, 50), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-pls-drone-count", LogisticsPatch.ApplyPLSDroneCount);
|
||||
y += 36f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigILSChargePower, new AutoConfigILSChargePowerMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-ils-charge-power", LogisticsPatch.ApplyILSChargePower);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigILSMaxTripDrone, new MyWindow.RangeValueMapper<int>(1, 180), "0°", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-ils-trip-range-drones", LogisticsPatch.ApplyILSTripRangeDrones);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigILSMaxTripShip, new AutoConfigILSMaxTripShipMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-ils-trip-range-ships", LogisticsPatch.ApplyILSTripRangeShips);
|
||||
var includeOrbitCollectorCheckBox = wnd.AddCheckBox(checkBoxX, y + 4f, tab3, LogisticsPatch.AutoConfigILSIncludeOrbitCollector, "Include Orbital Collector", 13).WithSmallerBox();
|
||||
var includeOrbitCollectorY = y;
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigILSWarperDistance, new AutoConfigILSWarperDistanceMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-ils-warp-distance", LogisticsPatch.ApplyILSWarpDistance);
|
||||
var warperNecessaryCheckBox = wnd.AddCheckBox(checkBoxX, y + 4f, tab3, LogisticsPatch.AutoConfigILSWarperNecessary, "Warpers required", 13).WithSmallerBox();
|
||||
// Align both checkbox "Apply" buttons in a common column after the widest checkbox label.
|
||||
var checkBoxApplyBtnX = checkBoxX + Mathf.Max(includeOrbitCollectorCheckBox.Width, warperNecessaryCheckBox.Width) + 10f;
|
||||
AddApplyButtonAt(checkBoxApplyBtnX, includeOrbitCollectorY, "btn-apply-ils-include-orbit-collector", LogisticsPatch.ApplyILSIncludeOrbitCollector);
|
||||
AddApplyButtonAt(checkBoxApplyBtnX, y, "btn-apply-ils-warper-necessary", LogisticsPatch.ApplyILSWarperNecessary);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigILSDroneMinDeliver, new AutoConfigCarrierMinDeliverMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-ils-drone-min-deliver", LogisticsPatch.ApplyILSDroneMinDeliver);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigILSShipMinDeliver, new AutoConfigCarrierMinDeliverMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-ils-ship-min-deliver", LogisticsPatch.ApplyILSShipMinDeliver);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigILSMinPilerValue, new AutoConfigMinPilerValueMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-ils-min-piler-value", LogisticsPatch.ApplyILSMinPilerValue);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigILSDroneCount, new MyWindow.RangeValueMapper<int>(0, 100), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-ils-drone-count", LogisticsPatch.ApplyILSDroneCount);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigILSShipCount, new MyWindow.RangeValueMapper<int>(0, 10), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-ils-ship-count", LogisticsPatch.ApplyILSShipCount);
|
||||
y += 36f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigVeinCollectorHarvestSpeed, new AutoConfigVeinCollectorHarvestSpeedMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-amm-harvest-speed", LogisticsPatch.ApplyVeinCollectorHarvestSpeed);
|
||||
y += 18f;
|
||||
wnd.AddSideSlider(nx, y, tab3, LogisticsPatch.AutoConfigVeinCollectorMinPilerValue, new AutoConfigMinPilerValueMapper(), "G", 150f, -100f).WithFontSize(13);
|
||||
AddApplyButton(y, "btn-apply-amm-min-piler-value", LogisticsPatch.ApplyVeinCollectorMinPilerValue);
|
||||
x = 0f;
|
||||
|
||||
var tab4 = wnd.AddTab(trans, "Player/Mecha");
|
||||
|
||||
@@ -198,6 +198,8 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
|
||||
"Logistics capacity related tweaks");
|
||||
LogisticsPatch.AllowOverflowInLogisticsEnabled = Config.Bind("Factory", "AllowOverflowInLogistics", false,
|
||||
"Allow overflow in logistic stations");
|
||||
LogisticsPatch.GreaterPowerUsageInLogisticsEnabled = Config.Bind("Build", "GreaterPowerUsageInLogistics", false,
|
||||
"Increase maximum power usage in Logistic Stations and Advanced Mining Machines");
|
||||
LogisticsPatch.LogisticsConstrolPanelImprovementEnabled = Config.Bind("Factory", "LogisticsConstrolPanelImprovement", false,
|
||||
"Logistics control panel improvement");
|
||||
LogisticsPatch.RealtimeLogisticsInfoPanelEnabled = Config.Bind("Factory", "RealtimeLogisticsInfoPanel", false,
|
||||
|
||||
Reference in New Issue
Block a user