mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2026-08-05 08:50:11 +08:00
Compare commits
6
Commits
93e60cd4f0
...
7a8f4af31d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a8f4af31d | ||
|
|
44efbdbb4f | ||
|
|
b7180afff2 | ||
|
|
e5cb52c3f4 | ||
|
|
ca4244384c | ||
|
|
19629eae97 |
Binary file not shown.
Binary file not shown.
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
## Changlog
|
## Changlog
|
||||||
|
|
||||||
|
* 2.4.4
|
||||||
|
* 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.
|
||||||
|
* `Finish build immediately`: Fix a possible crash.
|
||||||
* 2.4.3
|
* 2.4.3
|
||||||
* `Duplicate shells from that with highest production`: Fix crash on using with frameless shells.
|
* `Duplicate shells from that with highest production`: Fix crash on using with frameless shells.
|
||||||
* `Keep max production shells and remove others`: Fix wrong behaviour when left count > 1.
|
* `Keep max production shells and remove others`: Fix wrong behaviour when left count > 1.
|
||||||
@@ -185,6 +189,10 @@
|
|||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
|
* 2.4.4
|
||||||
|
* 新按钮 `为所有没有节点和壳的层级生成仙术戴森壳`,用于扩展新戴森壳层面的时候。
|
||||||
|
* 你必须在设置文件里开启`DysonSphere`分类的`IllegalDysonShellFunctionsEnabled`才能看到它。
|
||||||
|
* `立即完成建造`: 修复一个可能的崩溃问题。
|
||||||
* 2.4.3
|
* 2.4.3
|
||||||
* `从发电量最高的壳复制戴森壳`:修复在无框壳体时可能崩溃的问题。
|
* `从发电量最高的壳复制戴森壳`:修复在无框壳体时可能崩溃的问题。
|
||||||
* `保留发电量最高的戴森壳并移除其他戴森壳`:修复当剩余壳体数量大于1时的异常行为。
|
* `保留发电量最高的戴森壳并移除其他戴森壳`:修复当剩余壳体数量大于1时的异常行为。
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<BepInExPluginGuid>org.soardev.cheatenabler</BepInExPluginGuid>
|
<BepInExPluginGuid>org.soardev.cheatenabler</BepInExPluginGuid>
|
||||||
<Description>DSP MOD - CheatEnabler</Description>
|
<Description>DSP MOD - CheatEnabler</Description>
|
||||||
<Version>2.4.3</Version>
|
<Version>2.4.4</Version>
|
||||||
<PackageId>CheatEnabler</PackageId>
|
<PackageId>CheatEnabler</PackageId>
|
||||||
<RootNamespace>CheatEnabler</RootNamespace>
|
<RootNamespace>CheatEnabler</RootNamespace>
|
||||||
<PackHasChangelog>true</PackHasChangelog>
|
<PackHasChangelog>true</PackHasChangelog>
|
||||||
|
|||||||
@@ -1334,46 +1334,13 @@ public static class DysonSphereFunctions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CreateIllegalDysonShellWithMaxOutput()
|
private static bool CreateIllegalDysonShellWithMaxOutputForLayer(DysonSphereLayer layer)
|
||||||
{
|
{
|
||||||
StarData star = null;
|
|
||||||
var dysonEditor = UIRoot.instance?.uiGame?.dysonEditor;
|
|
||||||
if (dysonEditor != null && dysonEditor.gameObject.activeSelf)
|
|
||||||
{
|
|
||||||
star = dysonEditor.selection.viewStar;
|
|
||||||
}
|
|
||||||
if (star == null)
|
|
||||||
{
|
|
||||||
star = GameMain.data?.localStar;
|
|
||||||
if (star == null)
|
|
||||||
{
|
|
||||||
UIMessageBox.Show("CheatEnabler".Translate(), "You are not in any system.".Translate(), "确定".Translate(), UIMessageBox.ERROR, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UXAssist.Functions.DysonSphereFunctions.InitCurrentDysonLayer(star, 0);
|
|
||||||
var dysonSphere = GameMain.data?.dysonSpheres[star.index];
|
|
||||||
if (dysonSphere == null)
|
|
||||||
{
|
|
||||||
UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere data on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DysonShell.s_vmap ??= new Dictionary<int, Vector3>(16384);
|
DysonShell.s_vmap ??= new Dictionary<int, Vector3>(16384);
|
||||||
DysonShell.s_outvmap ??= new Dictionary<int, Vector3>(16384);
|
DysonShell.s_outvmap ??= new Dictionary<int, Vector3>(16384);
|
||||||
DysonShell.s_ivmap ??= new Dictionary<int, int>(16384);
|
DysonShell.s_ivmap ??= new Dictionary<int, int>(16384);
|
||||||
var shellsChanged = false;
|
var shellsChanged = false;
|
||||||
var mutex = new object();
|
var mutex = new object();
|
||||||
Dictionary<(int, int), int> availableFrames = [];
|
|
||||||
HashSet<int> unusedFrameIds = [];
|
|
||||||
var layer = dysonSphere.layersIdBased[1];
|
|
||||||
if (layer != null)
|
|
||||||
{
|
|
||||||
dysonSphere.RemoveLayer(1);
|
|
||||||
}
|
|
||||||
var maxOrbitRadius = Patches.DysonSpherePatch.UnlockMaxOrbitRadiusEnabled.Value ? Patches.DysonSpherePatch.UnlockMaxOrbitRadiusValue.Value : dysonSphere.maxOrbitRadius;
|
|
||||||
layer = dysonSphere.AddLayerOnId(1, maxOrbitRadius, Quaternion.Euler(0f, 0f, 0f), Mathf.Sqrt(dysonSphere.gravity / maxOrbitRadius) / maxOrbitRadius * 57.2957802f);
|
|
||||||
if (layer == null) return;
|
|
||||||
|
|
||||||
var supposedShells = new List<SupposedShell>(60 * 59 * 58);
|
var supposedShells = new List<SupposedShell>(60 * 59 * 58);
|
||||||
Vector3[] nodePos = new Vector3[60];
|
Vector3[] nodePos = new Vector3[60];
|
||||||
for (var i = 0; i < 60; i++)
|
for (var i = 0; i < 60; i++)
|
||||||
@@ -1397,7 +1364,7 @@ public static class DysonSphereFunctions
|
|||||||
var maxJ = -1;
|
var maxJ = -1;
|
||||||
var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount - 1 };
|
var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount - 1 };
|
||||||
|
|
||||||
var gridScale = (int)(Math.Pow(maxOrbitRadius / 4000.0, 0.75) + 0.5);
|
var gridScale = (int)(Math.Pow(layer.orbitRadius / 4000.0, 0.75) + 0.5);
|
||||||
gridScale = (gridScale < 1) ? 1 : gridScale;
|
gridScale = (gridScale < 1) ? 1 : gridScale;
|
||||||
var cpPerVertex = gridScale * gridScale * 2;
|
var cpPerVertex = gridScale * gridScale * 2;
|
||||||
var barrier = 0x7FFFFFFF / cpPerVertex;
|
var barrier = 0x7FFFFFFF / cpPerVertex;
|
||||||
@@ -1457,6 +1424,85 @@ public static class DysonSphereFunctions
|
|||||||
}
|
}
|
||||||
shellsChanged = true;
|
shellsChanged = true;
|
||||||
}
|
}
|
||||||
|
return shellsChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateIllegalDysonShellWithMaxOutput()
|
||||||
|
{
|
||||||
|
StarData star = null;
|
||||||
|
var dysonEditor = UIRoot.instance?.uiGame?.dysonEditor;
|
||||||
|
if (dysonEditor != null && dysonEditor.gameObject.activeSelf)
|
||||||
|
{
|
||||||
|
star = dysonEditor.selection.viewStar;
|
||||||
|
}
|
||||||
|
if (star == null)
|
||||||
|
{
|
||||||
|
star = GameMain.data?.localStar;
|
||||||
|
if (star == null)
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("CheatEnabler".Translate(), "You are not in any system.".Translate(), "确定".Translate(), UIMessageBox.ERROR, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UXAssist.Functions.DysonSphereFunctions.InitCurrentDysonLayer(star, 0);
|
||||||
|
var dysonSphere = GameMain.data?.dysonSpheres[star.index];
|
||||||
|
if (dysonSphere == null)
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere data on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var layer = dysonSphere.layersIdBased[1];
|
||||||
|
if (layer != null)
|
||||||
|
{
|
||||||
|
dysonSphere.RemoveLayer(1);
|
||||||
|
}
|
||||||
|
var maxOrbitRadius = Patches.DysonSpherePatch.UnlockMaxOrbitRadiusEnabled.Value ? Patches.DysonSpherePatch.UnlockMaxOrbitRadiusValue.Value : dysonSphere.maxOrbitRadius;
|
||||||
|
layer = dysonSphere.AddLayerOnId(1, maxOrbitRadius, Quaternion.Euler(0f, 0f, 0f), Mathf.Sqrt(dysonSphere.gravity / maxOrbitRadius) / maxOrbitRadius * 57.2957802f);
|
||||||
|
if (layer == null) return;
|
||||||
|
|
||||||
|
var shellsChanged = CreateIllegalDysonShellWithMaxOutputForLayer(layer);
|
||||||
|
|
||||||
|
dysonSphere.CheckAutoNodes();
|
||||||
|
if (dysonSphere.autoNodeCount <= 0) dysonSphere.PickAutoNode();
|
||||||
|
dysonSphere.modelRenderer.RebuildModels();
|
||||||
|
if (shellsChanged) GameMain.gameScenario?.NotifyOnPlanDysonShell();
|
||||||
|
dysonSphere.inEditorRenderMaskS = 0;
|
||||||
|
dysonSphere.inEditorRenderMaskL = 0;
|
||||||
|
dysonSphere.inGameRenderMaskS = 0;
|
||||||
|
dysonSphere.inGameRenderMaskL = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateIllegalDysonShellWithMaxOutput2()
|
||||||
|
{
|
||||||
|
StarData star = null;
|
||||||
|
var dysonEditor = UIRoot.instance?.uiGame?.dysonEditor;
|
||||||
|
if (dysonEditor != null && dysonEditor.gameObject.activeSelf)
|
||||||
|
{
|
||||||
|
star = dysonEditor.selection.viewStar;
|
||||||
|
}
|
||||||
|
if (star == null)
|
||||||
|
{
|
||||||
|
star = GameMain.data?.localStar;
|
||||||
|
if (star == null)
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("CheatEnabler".Translate(), "You are not in any system.".Translate(), "确定".Translate(), UIMessageBox.ERROR, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var dysonSphere = GameMain.data?.dysonSpheres[star.index];
|
||||||
|
if (dysonSphere == null)
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere data on \"{0}\".".Translate(), star.displayName), "确定".Translate(), UIMessageBox.ERROR, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var shellsChanged = false;
|
||||||
|
for (int i = dysonSphere.layersSorted.Length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var layer = dysonSphere.layersSorted[i];
|
||||||
|
if (layer == null) continue;
|
||||||
|
shellsChanged = CreateIllegalDysonShellWithMaxOutputForLayer(layer) || shellsChanged;
|
||||||
|
}
|
||||||
|
|
||||||
dysonSphere.CheckAutoNodes();
|
dysonSphere.CheckAutoNodes();
|
||||||
if (dysonSphere.autoNodeCount <= 0) dysonSphere.PickAutoNode();
|
if (dysonSphere.autoNodeCount <= 0) dysonSphere.PickAutoNode();
|
||||||
|
|||||||
@@ -446,7 +446,9 @@ public class FactoryPatch : PatchImpl<FactoryPatch>
|
|||||||
{
|
{
|
||||||
var time = __instance.timei;
|
var time = __instance.timei;
|
||||||
if (time % 6 != 0) return;
|
if (time % 6 != 0) return;
|
||||||
var factory = GameMain.localPlanet?.factory;
|
var planet = GameMain.localPlanet;
|
||||||
|
if (planet == null || !planet.factoryLoaded) return;
|
||||||
|
var factory = planet.factory;
|
||||||
if (factory == null || factory.prebuildCount <= 0) return;
|
if (factory == null || factory.prebuildCount <= 0) return;
|
||||||
var player = GameMain.mainPlayer;
|
var player = GameMain.mainPlayer;
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ public static class UIConfigWindow
|
|||||||
I18N.Add("Complete Dyson Sphere shells instantly", "Complete Dyson Sphere shells instantly", "立即完成戴森壳建造");
|
I18N.Add("Complete Dyson Sphere shells instantly", "Complete Dyson Sphere shells instantly", "立即完成戴森壳建造");
|
||||||
I18N.Add("Remove all frames on Dyson Sphere", "Remove all frames on Dyson Sphere", "移除戴森球上的所有框架");
|
I18N.Add("Remove all frames on Dyson Sphere", "Remove all frames on Dyson Sphere", "移除戴森球上的所有框架");
|
||||||
I18N.Add("Generate illegal dyson shell", "Generate an illegal dyson shell (!!1st shell layer will be replaced!!)", "生成单层仙术戴森壳(!!会先删除第一层戴森壳!!)");
|
I18N.Add("Generate illegal dyson shell", "Generate an illegal dyson shell (!!1st shell layer will be replaced!!)", "生成单层仙术戴森壳(!!会先删除第一层戴森壳!!)");
|
||||||
|
I18N.Add("Generate illegal dyson shell 2", "Generate illegal dyson shells for all layers without nodes and shells", "为所有没有节点和壳的层级生成仙术戴森壳");
|
||||||
I18N.Add("Keep max production shells and remove others", "Keep max production shells and remove others", "保留发电量最高的戴森壳并移除其他戴森壳");
|
I18N.Add("Keep max production shells and remove others", "Keep max production shells and remove others", "保留发电量最高的戴森壳并移除其他戴森壳");
|
||||||
I18N.Add("Duplicate shells from that with highest production", "Duplicate shells from that with highest production", "从发电量最高的壳复制戴森壳");
|
I18N.Add("Duplicate shells from that with highest production", "Duplicate shells from that with highest production", "从发电量最高的壳复制戴森壳");
|
||||||
I18N.Add("Generate illegal dyson shell quickly", "Generate illegal dyson shell quickly", "快速生成仙术戴森壳");
|
I18N.Add("Generate illegal dyson shell quickly", "Generate illegal dyson shell quickly", "快速生成仙术戴森壳");
|
||||||
@@ -316,12 +317,18 @@ public static class UIConfigWindow
|
|||||||
{
|
{
|
||||||
y += 72f;
|
y += 72f;
|
||||||
var originalY = y;
|
var originalY = y;
|
||||||
var btn1 = wnd.AddButton(x, y, 300f, tab4, "Generate illegal dyson shell", 16, "button-generate-illegal-dyson-shells", () =>
|
var btn0 = wnd.AddButton(x, y, 300f, tab4, "Generate illegal dyson shell", 16, "button-generate-illegal-dyson-shells", () =>
|
||||||
{
|
{
|
||||||
UIMessageBox.Show("Generate illegal dyson shell".Translate(), "WARNING: This operation can be very slow, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
|
UIMessageBox.Show("Generate illegal dyson shell".Translate(), "WARNING: This operation can be very slow, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
|
||||||
() => { DysonSphereFunctions.CreateIllegalDysonShellWithMaxOutput(); });
|
() => { DysonSphereFunctions.CreateIllegalDysonShellWithMaxOutput(); });
|
||||||
});
|
});
|
||||||
y += 36f;
|
y += 36f;
|
||||||
|
var btn1 = wnd.AddButton(x, y, 300f, tab4, "Generate illegal dyson shell 2", 16, "button-generate-illegal-dyson-shells", () =>
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("Generate illegal dyson shell 2".Translate(), "WARNING: This operation can be very slow, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
|
||||||
|
() => { DysonSphereFunctions.CreateIllegalDysonShellWithMaxOutput2(); });
|
||||||
|
});
|
||||||
|
y += 36f;
|
||||||
var btn2 = wnd.AddButton(x, y, 300f, tab4, "Keep max production shells and remove others", 16, "button-keep-max-production-shells", () =>
|
var btn2 = wnd.AddButton(x, y, 300f, tab4, "Keep max production shells and remove others", 16, "button-keep-max-production-shells", () =>
|
||||||
{
|
{
|
||||||
UIMessageBox.Show("Keep max production shells and remove others".Translate(), "WARNING: This operation is DANGEROUS, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
|
UIMessageBox.Show("Keep max production shells and remove others".Translate(), "WARNING: This operation is DANGEROUS, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
|
||||||
@@ -352,6 +359,7 @@ public static class UIConfigWindow
|
|||||||
void onIllegalDysonShellFunctionsChanged(object o, EventArgs e)
|
void onIllegalDysonShellFunctionsChanged(object o, EventArgs e)
|
||||||
{
|
{
|
||||||
var enabled = Functions.DysonSphereFunctions.IllegalDysonShellFunctionsEnabled.Value;
|
var enabled = Functions.DysonSphereFunctions.IllegalDysonShellFunctionsEnabled.Value;
|
||||||
|
btn0.gameObject.SetActive(enabled);
|
||||||
btn1.gameObject.SetActive(enabled);
|
btn1.gameObject.SetActive(enabled);
|
||||||
btn2.gameObject.SetActive(enabled);
|
btn2.gameObject.SetActive(enabled);
|
||||||
btn3.gameObject.SetActive(enabled);
|
btn3.gameObject.SetActive(enabled);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "CheatEnabler",
|
"name": "CheatEnabler",
|
||||||
"version_number": "2.4.3",
|
"version_number": "2.4.4",
|
||||||
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/CheatEnabler",
|
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/CheatEnabler",
|
||||||
"description": "Add various cheat functions while disabling abnormal determinants / 添加一些作弊功能,同时屏蔽异常检测",
|
"description": "Add various cheat functions while disabling abnormal determinants / 添加一些作弊功能,同时屏蔽异常检测",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
## Changlog
|
## Changlog
|
||||||
|
|
||||||
|
* 1.5.8
|
||||||
|
* `Initialize This Planet`: Fix a possible crash.
|
||||||
|
* `Remember window position and size on last exit`: Remove a window hook that are not useful anymore.
|
||||||
|
* `Real-time logistic stations info panel`: Fix display issue (finally!) when count of logistic towers > 128.
|
||||||
* 1.5.7
|
* 1.5.7
|
||||||
* Fix compatibility with game update 0.10.34.28505.
|
* Fix compatibility with game update 0.10.34.28505.
|
||||||
* 1.5.6
|
* 1.5.6
|
||||||
@@ -397,6 +401,10 @@
|
|||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
|
* 1.5.8
|
||||||
|
* `初始化本行星`:修复可能的崩溃。
|
||||||
|
* `记住上次退出时的窗口位置和大小`:移除不再有用的窗口钩子。
|
||||||
|
* `物流站实时信息面板`:修复物流塔数量 > 128 时的显示问题。
|
||||||
* 1.5.7
|
* 1.5.7
|
||||||
* 修复了与游戏更新0.10.34.28505的兼容性。
|
* 修复了与游戏更新0.10.34.28505的兼容性。
|
||||||
* 1.5.6
|
* 1.5.6
|
||||||
|
|||||||
@@ -75,12 +75,14 @@ public static class LogisticsPatch
|
|||||||
RealtimeLogisticsInfoPanel.EnableBars(RealtimeLogisticsInfoPanelBarsEnabled.Value);
|
RealtimeLogisticsInfoPanel.EnableBars(RealtimeLogisticsInfoPanelBarsEnabled.Value);
|
||||||
|
|
||||||
GameLogicProc.OnGameBegin += RealtimeLogisticsInfoPanel.OnGameBegin;
|
GameLogicProc.OnGameBegin += RealtimeLogisticsInfoPanel.OnGameBegin;
|
||||||
|
GameLogicProc.OnGameEnd += RealtimeLogisticsInfoPanel.OnGameEnd;
|
||||||
GameLogicProc.OnDataLoaded += RealtimeLogisticsInfoPanel.OnDataLoaded;
|
GameLogicProc.OnDataLoaded += RealtimeLogisticsInfoPanel.OnDataLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Uninit()
|
public static void Uninit()
|
||||||
{
|
{
|
||||||
GameLogicProc.OnDataLoaded -= RealtimeLogisticsInfoPanel.OnDataLoaded;
|
GameLogicProc.OnDataLoaded -= RealtimeLogisticsInfoPanel.OnDataLoaded;
|
||||||
|
GameLogicProc.OnGameEnd -= RealtimeLogisticsInfoPanel.OnGameEnd;
|
||||||
GameLogicProc.OnGameBegin -= RealtimeLogisticsInfoPanel.OnGameBegin;
|
GameLogicProc.OnGameBegin -= RealtimeLogisticsInfoPanel.OnGameBegin;
|
||||||
|
|
||||||
AutoConfigLogistics.Enable(false);
|
AutoConfigLogistics.Enable(false);
|
||||||
@@ -798,12 +800,13 @@ public static class LogisticsPatch
|
|||||||
|
|
||||||
public static void Enable(bool on)
|
public static void Enable(bool on)
|
||||||
{
|
{
|
||||||
|
// Toggle the defensive localPlanet setter hook regardless of whether the GUI
|
||||||
|
// root has been initialized yet (InitGUI may run later via OnDataLoaded).
|
||||||
|
LocalPlanetWatcher.Enable(on);
|
||||||
if (_stationTipsRoot == null) return;
|
if (_stationTipsRoot == null) return;
|
||||||
if (!on)
|
if (!on)
|
||||||
{
|
{
|
||||||
RecycleStationTips();
|
HideAndRecycleStationTips();
|
||||||
_lastPlanetId = 0;
|
|
||||||
_stationTipsRoot.SetActive(false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (DSPGame.IsMenuDemo || !GameMain.isRunning)
|
if (DSPGame.IsMenuDemo || !GameMain.isRunning)
|
||||||
@@ -827,9 +830,12 @@ public static class LogisticsPatch
|
|||||||
|
|
||||||
public static void OnGameBegin()
|
public static void OnGameBegin()
|
||||||
{
|
{
|
||||||
RecycleStationTips();
|
HideAndRecycleStationTips();
|
||||||
_lastPlanetId = 0;
|
}
|
||||||
_stationTipsRoot?.SetActive(false);
|
|
||||||
|
public static void OnGameEnd()
|
||||||
|
{
|
||||||
|
HideAndRecycleStationTips();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void OnDataLoaded()
|
public static void OnDataLoaded()
|
||||||
@@ -1065,22 +1071,32 @@ public static class LogisticsPatch
|
|||||||
StateSprite[2] = Util.LoadEmbeddedSprite("assets/icon/in.png");
|
StateSprite[2] = Util.LoadEmbeddedSprite("assets/icon/in.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ReleaseStationTip(StationTip stationTip)
|
||||||
|
{
|
||||||
|
if (!stationTip) return;
|
||||||
|
var go = stationTip.gameObject;
|
||||||
|
if (_stationTipsRecycleCount < StationTipsRecycle.Length)
|
||||||
|
{
|
||||||
|
stationTip.ResetStationTip();
|
||||||
|
go.SetActive(false);
|
||||||
|
StationTipsRecycle[_stationTipsRecycleCount++] = stationTip;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Recycle pool is full: destroy the cloned UI GameObject (not just the
|
||||||
|
// StationTip MonoBehaviour). Destroying only the component would leave the
|
||||||
|
// GameObject and all its UI children orphaned under _stationTipsRoot,
|
||||||
|
// causing "ghost" tips to remain visible whenever the root is reactivated.
|
||||||
|
go.SetActive(false);
|
||||||
|
Object.Destroy(go);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void RecycleStationTips()
|
private static void RecycleStationTips()
|
||||||
{
|
{
|
||||||
foreach (var stationTip in _stationTips)
|
foreach (var stationTip in _stationTips)
|
||||||
{
|
{
|
||||||
if (!stationTip) continue;
|
ReleaseStationTip(stationTip);
|
||||||
if (_stationTipsRecycleCount < 128)
|
|
||||||
{
|
|
||||||
stationTip.ResetStationTip();
|
|
||||||
stationTip.gameObject.SetActive(false);
|
|
||||||
StationTipsRecycle[_stationTipsRecycleCount] = stationTip;
|
|
||||||
_stationTipsRecycleCount++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Object.Destroy(stationTip);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_stationTips = new StationTip[16];
|
_stationTips = new StationTip[16];
|
||||||
}
|
}
|
||||||
@@ -1089,19 +1105,17 @@ public static class LogisticsPatch
|
|||||||
{
|
{
|
||||||
var stationTip = _stationTips[index];
|
var stationTip = _stationTips[index];
|
||||||
if (!stationTip) return;
|
if (!stationTip) return;
|
||||||
if (_stationTipsRecycleCount < 128)
|
ReleaseStationTip(stationTip);
|
||||||
{
|
|
||||||
stationTip.ResetStationTip();
|
|
||||||
stationTip.gameObject.SetActive(false);
|
|
||||||
StationTipsRecycle[_stationTipsRecycleCount++] = stationTip;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Object.Destroy(stationTip);
|
|
||||||
}
|
|
||||||
_stationTips[index] = null;
|
_stationTips[index] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void HideAndRecycleStationTips()
|
||||||
|
{
|
||||||
|
_stationTipsRoot?.SetActive(false);
|
||||||
|
RecycleStationTips();
|
||||||
|
_lastPlanetId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
private static StationTip AllocateStationTip()
|
private static StationTip AllocateStationTip()
|
||||||
{
|
{
|
||||||
if (_stationTipsRecycleCount > 0)
|
if (_stationTipsRecycleCount > 0)
|
||||||
@@ -1247,6 +1261,26 @@ public static class LogisticsPatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Defensive Harmony hook on GameData.localPlanet setter.
|
||||||
|
// It guarantees tips are hidden and recycled when the local planet id changes,
|
||||||
|
// even if UXAssist.Update() is skipped that frame (e.g. by VFInput.inputing
|
||||||
|
// while the player is typing while transitioning between planets, or by a brief
|
||||||
|
// !GameMain.isRunning state during loading). _lastPlanetId is reset to 0 here so
|
||||||
|
// the next StationInfoPanelsUpdate() re-validates factoryLoaded/transport/viewMode
|
||||||
|
// and re-allocates fresh tips for the new planet.
|
||||||
|
private class LocalPlanetWatcher : PatchImpl<LocalPlanetWatcher>
|
||||||
|
{
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(GameData), nameof(GameData.localPlanet), MethodType.Setter)]
|
||||||
|
private static void GameData_localPlanet_Setter_Prefix(GameData __instance, PlanetData value)
|
||||||
|
{
|
||||||
|
var oldId = __instance.localPlanet?.id ?? 0;
|
||||||
|
var newId = value?.id ?? 0;
|
||||||
|
if (oldId == newId) return;
|
||||||
|
HideAndRecycleStationTips();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class StationTip : MonoBehaviour
|
public class StationTip : MonoBehaviour
|
||||||
{
|
{
|
||||||
[FormerlySerializedAs("RectTransform")]
|
[FormerlySerializedAs("RectTransform")]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<BepInExPluginGuid>org.soardev.uxassist</BepInExPluginGuid>
|
<BepInExPluginGuid>org.soardev.uxassist</BepInExPluginGuid>
|
||||||
<Description>DSP MOD - UXAssist</Description>
|
<Description>DSP MOD - UXAssist</Description>
|
||||||
<Version>1.5.7</Version>
|
<Version>1.5.8</Version>
|
||||||
<PackageId>UXAssist</PackageId>
|
<PackageId>UXAssist</PackageId>
|
||||||
<RootNamespace>UXAssist</RootNamespace>
|
<RootNamespace>UXAssist</RootNamespace>
|
||||||
<PackHasChangelog>true</PackHasChangelog>
|
<PackHasChangelog>true</PackHasChangelog>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "UXAssist",
|
"name": "UXAssist",
|
||||||
"version_number": "1.5.7",
|
"version_number": "1.5.8",
|
||||||
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/UXAssist",
|
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/UXAssist",
|
||||||
"description": "Some functions and patches for better user experience / 一些提升用户体验的功能和补丁",
|
"description": "Some functions and patches for better user experience / 一些提升用户体验的功能和补丁",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|||||||
Reference in New Issue
Block a user