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
+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]);
}
}