1
0
mirror of https://github.com/soarqin/DSP_Mods.git synced 2026-06-21 06:51:11 +08:00

UXAssist: add buttons to apply logistics auto-config to current planet's facilities

This commit is contained in:
2026-06-16 03:37:55 +08:00
parent 79dea142de
commit ffd8b91930
5 changed files with 315 additions and 65 deletions
+1 -1
View File
@@ -51,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. |
+237 -62
View File
@@ -109,6 +109,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 +415,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 +437,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 +445,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]);
}
}
+6
View File
@@ -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`中的`展示物流站信息`,此功能将被隐藏
* 自动配置物流站
* 自动配置的建筑包括:物流配送器、行星物流站、星际物流站、高级采矿机
* 将设置应用到当前行星上所有已建成的物流设施
* 物流标签页上每一项设置右侧都有一个`应用`按钮,按下后将该项数值应用到当前行星上所有该类型的物流设施。
* 每个大分类标题(物流配送器、战场分析基站、行星物流站、星际物流站、大型采矿机)右侧都有一个`应用全部`按钮,按下后将该分类的所有设置数值应用到当前行星上所有该类型的物流设施。
* 玩家/机甲
* 无限交互距离
* 移除建造数量和范围限制
+9
View File
@@ -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;
+62 -2
View File
@@ -1,6 +1,7 @@
using System;
using System.Text;
using UnityEngine;
using UnityEngine.Events;
using UXAssist.Common;
using UXAssist.Functions;
using UXAssist.ModsCompat;
@@ -98,6 +99,10 @@ 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("Enhance control for logistic storage capacities", "Enhance control for logistic storage capacities", "物流塔存储容量控制改进");
@@ -573,6 +578,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 +589,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 +613,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 +623,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 +643,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 +652,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");