mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2025-12-09 15:33:31 +08:00
UXAssist and CheatEnabler new releases
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
## Changlog
|
## Changlog
|
||||||
|
|
||||||
|
* 2.3.24
|
||||||
|
+ `Complete Dyson Sphere Shells instantly`: Fix a bug that may cause negative power in some cases
|
||||||
|
* 2.3.23
|
||||||
|
+ New feature: `Complete Dyson Sphere Shells instantly`
|
||||||
|
+ Fix a crash when config panel is opened before game is fully loaded
|
||||||
* 2.3.22
|
* 2.3.22
|
||||||
+ Fix `Pump Anywhere`
|
+ Fix `Pump Anywhere`
|
||||||
* 2.3.21
|
* 2.3.21
|
||||||
@@ -122,6 +127,11 @@
|
|||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
|
* 2.3.24
|
||||||
|
+ `立即完成戴森壳建造`:修复了在某些情况下可能导致发电为负的问题
|
||||||
|
* 2.3.23
|
||||||
|
+ 新功能:`立即完成戴森壳建造`
|
||||||
|
+ 修复了在游戏完全加载前打开配置面板可能导致的崩溃问题
|
||||||
* 2.3.22
|
* 2.3.22
|
||||||
+ 修复了`平地抽水`
|
+ 修复了`平地抽水`
|
||||||
* 2.3.21
|
* 2.3.21
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ public class CheatEnabler : BaseUnityPlugin
|
|||||||
PlayerFunctions.Init();
|
PlayerFunctions.Init();
|
||||||
PlayerPatch.Init();
|
PlayerPatch.Init();
|
||||||
DysonSpherePatch.Init();
|
DysonSpherePatch.Init();
|
||||||
|
DysonSphereFunctions.Init();
|
||||||
CombatPatch.Init();
|
CombatPatch.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<TargetFramework>net472</TargetFramework>
|
<TargetFramework>net472</TargetFramework>
|
||||||
<BepInExPluginGuid>org.soardev.cheatenabler</BepInExPluginGuid>
|
<BepInExPluginGuid>org.soardev.cheatenabler</BepInExPluginGuid>
|
||||||
<Description>DSP MOD - CheatEnabler</Description>
|
<Description>DSP MOD - CheatEnabler</Description>
|
||||||
<Version>2.3.22</Version>
|
<Version>2.3.24</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<PackageId>CheatEnabler</PackageId>
|
<PackageId>CheatEnabler</PackageId>
|
||||||
|
|||||||
121
CheatEnabler/DysonSphereFunctions.cs
Normal file
121
CheatEnabler/DysonSphereFunctions.cs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
using HarmonyLib;
|
||||||
|
using UXAssist.Common;
|
||||||
|
|
||||||
|
namespace CheatEnabler;
|
||||||
|
|
||||||
|
public static class DysonSphereFunctions
|
||||||
|
{
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
I18N.Add("You are not in any system.", "You are not in any system.", "你不在任何星系中");
|
||||||
|
I18N.Add("There is no Dyson Sphere shell on \"{0}\".", "There is no Dyson Sphere shell on \"{0}\".", "“{0}”上没有可建造的戴森壳");
|
||||||
|
I18N.Add("This will complete all Dyson Sphere shells on \"{0}\" instantly. Are you sure?", "This will complete all Dyson Sphere shells on \"{0}\" instantly. Are you sure?", "这将立即完成“{0}”上的所有戴森壳。你确定吗?");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CompleteShellsInstantly()
|
||||||
|
{
|
||||||
|
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(), 3, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var dysonSphere = GameMain.data?.dysonSpheres[star.index];
|
||||||
|
if (dysonSphere == null || dysonSphere.layerCount == 0)
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere shell on \"{0}\".".Translate(), star.displayName), "确定".Translate(), 3, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIMessageBox.Show("CheatEnabler".Translate(), string.Format("This will complete all Dyson Sphere shells on \"{0}\" instantly. Are you sure?".Translate(), star.displayName), "取消".Translate(), "确定".Translate(), 2, null, () =>
|
||||||
|
{
|
||||||
|
var totalNodeSpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalNodeSP");
|
||||||
|
var totalFrameSpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalFrameSP");
|
||||||
|
var totalCpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalCP");
|
||||||
|
|
||||||
|
var rocketCount = 0;
|
||||||
|
var solarSailCount = 0;
|
||||||
|
foreach (var dysonSphereLayer in dysonSphere.layersIdBased)
|
||||||
|
{
|
||||||
|
if (dysonSphereLayer == null) continue;
|
||||||
|
long totalNodeSp = 0;
|
||||||
|
long totalFrameSp = 0;
|
||||||
|
long totalCp = 0;
|
||||||
|
for (var i = dysonSphereLayer.frameCursor - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var dysonFrame = dysonSphereLayer.framePool[i];
|
||||||
|
if (dysonFrame == null || dysonFrame.id != i) continue;
|
||||||
|
totalFrameSp += dysonFrame.spMax;
|
||||||
|
var spMax = dysonFrame.spMax / 2;
|
||||||
|
if (dysonFrame.spA < spMax)
|
||||||
|
{
|
||||||
|
rocketCount += spMax - dysonFrame.spA;
|
||||||
|
dysonFrame.spA = spMax;
|
||||||
|
dysonSphere.UpdateProgress(dysonFrame);
|
||||||
|
}
|
||||||
|
if (dysonFrame.spB < spMax)
|
||||||
|
{
|
||||||
|
rocketCount += spMax - dysonFrame.spB;
|
||||||
|
dysonFrame.spB = spMax;
|
||||||
|
dysonSphere.UpdateProgress(dysonFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = dysonSphereLayer.nodeCursor - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var dysonNode = dysonSphereLayer.nodePool[i];
|
||||||
|
if (dysonNode == null || dysonNode.id != i) continue;
|
||||||
|
dysonNode.spOrdered = 0;
|
||||||
|
dysonNode._spReq = 0;
|
||||||
|
totalNodeSp += dysonNode.spMax;
|
||||||
|
var diff = dysonNode.spMax - dysonNode.sp;
|
||||||
|
if (diff > 0)
|
||||||
|
{
|
||||||
|
rocketCount += diff;
|
||||||
|
dysonNode.sp = dysonNode.spMax;
|
||||||
|
dysonSphere.UpdateProgress(dysonNode);
|
||||||
|
}
|
||||||
|
dysonNode._cpReq = 0;
|
||||||
|
dysonNode.cpOrdered = 0;
|
||||||
|
foreach (var shell in dysonNode.shells)
|
||||||
|
{
|
||||||
|
var nodeIndex = shell.nodeIndexMap[dysonNode.id];
|
||||||
|
var cpMax = (shell.vertsqOffset[nodeIndex + 1] - shell.vertsqOffset[nodeIndex]) * shell.cpPerVertex;
|
||||||
|
totalCp += cpMax;
|
||||||
|
diff = cpMax - shell.nodecps[nodeIndex];
|
||||||
|
shell.nodecps[nodeIndex] = cpMax;
|
||||||
|
shell.nodecps[shell.nodecps.Length - 1] += diff;
|
||||||
|
solarSailCount += diff;
|
||||||
|
if (totalCpInfo != null)
|
||||||
|
{
|
||||||
|
shell.SetMaterialDynamicVars();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
totalNodeSpInfo?.SetValue(dysonSphereLayer, totalNodeSp);
|
||||||
|
totalFrameSpInfo?.SetValue(dysonSphereLayer, totalFrameSp);
|
||||||
|
totalCpInfo?.SetValue(dysonSphereLayer, totalCp);
|
||||||
|
}
|
||||||
|
dysonSphere.CheckAutoNodes();
|
||||||
|
|
||||||
|
var productRegister = dysonSphere.productRegister;
|
||||||
|
if (productRegister != null)
|
||||||
|
{
|
||||||
|
lock (productRegister)
|
||||||
|
{
|
||||||
|
if (rocketCount > 0) productRegister[11902] += rocketCount;
|
||||||
|
if (solarSailCount > 0) productRegister[11903] += solarSailCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
+ Skip absorption period
|
+ Skip absorption period
|
||||||
+ Quick absorb
|
+ Quick absorb
|
||||||
+ Eject anyway
|
+ Eject anyway
|
||||||
|
+ Complete Dyson Sphere Shells instantly
|
||||||
+ Mecha/Combat:
|
+ Mecha/Combat:
|
||||||
+ Mecha and Drones/Fleets invicible
|
+ Mecha and Drones/Fleets invicible
|
||||||
+ Buildings invicible
|
+ Buildings invicible
|
||||||
@@ -100,6 +101,7 @@
|
|||||||
+ 跳过吸收阶段
|
+ 跳过吸收阶段
|
||||||
+ 快速吸收
|
+ 快速吸收
|
||||||
+ 全球弹射
|
+ 全球弹射
|
||||||
|
+ 立即完成戴森壳建造
|
||||||
+ 战斗:
|
+ 战斗:
|
||||||
+ 机甲和战斗无人机无敌
|
+ 机甲和战斗无人机无敌
|
||||||
+ 建筑无敌
|
+ 建筑无敌
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ public static class UIConfigWindow
|
|||||||
I18N.Add("Eject anyway", "Eject anyway", "全球弹射");
|
I18N.Add("Eject anyway", "Eject anyway", "全球弹射");
|
||||||
I18N.Add("Overclock Ejectors", "Overclock Ejectors (10x)", "高速弹射器(10倍射速)");
|
I18N.Add("Overclock Ejectors", "Overclock Ejectors (10x)", "高速弹射器(10倍射速)");
|
||||||
I18N.Add("Overclock Silos", "Overclock Silos (10x)", "高速发射井(10倍射速)");
|
I18N.Add("Overclock Silos", "Overclock Silos (10x)", "高速发射井(10倍射速)");
|
||||||
|
I18N.Add("Complete Dyson Sphere shells instantly", "Complete Dyson Sphere shells instantly", "立即完成戴森壳建造");
|
||||||
I18N.Add("Terraform without enough soil piles", "Terraform without enough soil piles", "沙土不够时依然可以整改地形");
|
I18N.Add("Terraform without enough soil piles", "Terraform without enough soil piles", "沙土不够时依然可以整改地形");
|
||||||
I18N.Add("Instant teleport (like that in Sandbox mode)", "Instant teleport (like that in Sandbox mode)", "快速传送(和沙盒模式一样)");
|
I18N.Add("Instant teleport (like that in Sandbox mode)", "Instant teleport (like that in Sandbox mode)", "快速传送(和沙盒模式一样)");
|
||||||
I18N.Add("Mecha and Drones/Fleets invicible", "Mecha and Drones/Fleets invicible", "机甲和战斗无人机无敌");
|
I18N.Add("Mecha and Drones/Fleets invicible", "Mecha and Drones/Fleets invicible", "机甲和战斗无人机无敌");
|
||||||
@@ -204,6 +205,9 @@ public static class UIConfigWindow
|
|||||||
wnd.AddCheckBox(x, y, tab4, DysonSpherePatch.OverclockEjectorEnabled, "Overclock Ejectors");
|
wnd.AddCheckBox(x, y, tab4, DysonSpherePatch.OverclockEjectorEnabled, "Overclock Ejectors");
|
||||||
y += 36f;
|
y += 36f;
|
||||||
wnd.AddCheckBox(x, y, tab4, DysonSpherePatch.OverclockSiloEnabled, "Overclock Silos");
|
wnd.AddCheckBox(x, y, tab4, DysonSpherePatch.OverclockSiloEnabled, "Overclock Silos");
|
||||||
|
x = 300f;
|
||||||
|
y = 10f;
|
||||||
|
wnd.AddButton(x, y, 300f, tab4, "Complete Dyson Sphere shells instantly", 16, "button-complete-dyson-sphere-shells-instantly", DysonSphereFunctions.CompleteShellsInstantly);
|
||||||
|
|
||||||
var tab5 = wnd.AddTab(_windowTrans, "Mecha/Combat");
|
var tab5 = wnd.AddTab(_windowTrans, "Mecha/Combat");
|
||||||
x = 0f;
|
x = 0f;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "CheatEnabler",
|
"name": "CheatEnabler",
|
||||||
"version_number": "2.3.22",
|
"version_number": "2.3.24",
|
||||||
"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": [
|
||||||
|
|||||||
@@ -6,11 +6,13 @@
|
|||||||
- Quick-set item filter while right-clicking item icons in storage list on the panel
|
- Quick-set item filter while right-clicking item icons in storage list on the panel
|
||||||
+ New feature: `Dyson Sphere "Auto Fast Build" speed multiplier`
|
+ New feature: `Dyson Sphere "Auto Fast Build" speed multiplier`
|
||||||
- Note: this only applies to `Dyson Sphere "Auto Fast Build"` in sandbox mode
|
- Note: this only applies to `Dyson Sphere "Auto Fast Build"` in sandbox mode
|
||||||
|
+ New feature: `Mod manager profile based save folder`
|
||||||
|
- Save files are stored in `Save\<ProfileName>` folder.
|
||||||
|
- Will use original save location if matching default profile name.
|
||||||
+ `Quick build and dismantle stacking labs`: works for storages and tanks now
|
+ `Quick build and dismantle stacking labs`: works for storages and tanks now
|
||||||
+ `Enable game window resize`: Keep window resizable on applying game options.
|
+ `Enable game window resize`: Keep window resizable on applying game options.
|
||||||
+ `Remember window position and size on last exit`: Do not resize window on applying game options if resolution related config entries are not changed.
|
+ `Remember window position and size on last exit`: Do not resize window on applying game options if resolution related config entries are not changed.
|
||||||
+ Auto resize panel to fit content, for better support of multilanguages and mods dependent on UX Assist config panel functions.
|
+ Auto resize panel to fit content, for better support of multilanguages and mods dependent on UX Assist config panel functions.
|
||||||
+ Fix a crash when config panel is opened before game is fully loaded
|
|
||||||
* 1.1.4
|
* 1.1.4
|
||||||
+ Fix `Remove some build conditions`
|
+ Fix `Remove some build conditions`
|
||||||
* 1.1.3
|
* 1.1.3
|
||||||
@@ -157,12 +159,14 @@
|
|||||||
- 打开面板时自动将鼠标指向物品设为筛选条件
|
- 打开面板时自动将鼠标指向物品设为筛选条件
|
||||||
- 在控制面板物流塔列表中右键点击物品图标快速设置为筛选条件
|
- 在控制面板物流塔列表中右键点击物品图标快速设置为筛选条件
|
||||||
+ 新功能:`戴森球自动快速建造速度倍率`
|
+ 新功能:`戴森球自动快速建造速度倍率`
|
||||||
- 注意:这仅适用于沙盒模式下的`戴森球自动快速建造`功能
|
- 注意:这仅适用于沙盒模式下的`戴森球自动快速建造`功能
|
||||||
|
+ 新功能:`基于mod管理器配置档案名的存档文件夹`
|
||||||
|
- 存档文件会存储在`Save\<ProfileName>`文件夹中
|
||||||
|
- 如果匹配默认配置档案名则使用原始存档位置
|
||||||
+ `快速建造和拆除堆叠研究站`:现在也支持储物仓和储液罐
|
+ `快速建造和拆除堆叠研究站`:现在也支持储物仓和储液罐
|
||||||
+ `允许调整游戏窗口大小`:在应用游戏选项时保持窗口可调整大小
|
+ `允许调整游戏窗口大小`:在应用游戏选项时保持窗口可调整大小
|
||||||
+ `记住上次退出时的窗口位置和大小`:如果分辨率相关的配置项未改变,则在应用游戏选项时不调整窗口大小
|
+ `记住上次退出时的窗口位置和大小`:如果分辨率相关的配置项未改变,则在应用游戏选项时不调整窗口大小
|
||||||
+ 自动调整面板大小适应内容,以更好地支持多语言和依赖于UX助手配置面板功能的mod
|
+ 自动调整面板大小适应内容,以更好地支持多语言和依赖于UX助手配置面板功能的mod
|
||||||
+ 修复了在游戏完全加载前打开配置面板可能导致的崩溃问题
|
|
||||||
* 1.1.4
|
* 1.1.4
|
||||||
+ 修复了`移除部分不影响游戏逻辑的建造条件`
|
+ 修复了`移除部分不影响游戏逻辑的建造条件`
|
||||||
* 1.1.3
|
* 1.1.3
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public static class DysonSpherePatch
|
|||||||
_totalFrameSpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalFrameSP");
|
_totalFrameSpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalFrameSP");
|
||||||
_totalCpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalCP");
|
_totalCpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalCP");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Uninit()
|
public static void Uninit()
|
||||||
{
|
{
|
||||||
StopEjectOnNodeComplete.Enable(false);
|
StopEjectOnNodeComplete.Enable(false);
|
||||||
@@ -62,6 +62,7 @@ public static class DysonSpherePatch
|
|||||||
if (pool[id].nodeLayerId != index) continue;
|
if (pool[id].nodeLayerId != index) continue;
|
||||||
ds.RemoveDysonRocket(id);
|
ds.RemoveDysonRocket(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ds.RemoveLayer(index);
|
ds.RemoveLayer(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,10 +70,9 @@ public static class DysonSpherePatch
|
|||||||
[HarmonyPatch(typeof(DysonSwarm), nameof(DysonSwarm.AutoConstruct))]
|
[HarmonyPatch(typeof(DysonSwarm), nameof(DysonSwarm.AutoConstruct))]
|
||||||
private static bool DysonSwarm_AutoConstruct_Prefix(DysonSwarm __instance)
|
private static bool DysonSwarm_AutoConstruct_Prefix(DysonSwarm __instance)
|
||||||
{
|
{
|
||||||
return false;
|
return __instance.dysonSphere.autoNodeCount == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(DysonSphere), nameof(DysonSphere.AutoConstruct))]
|
[HarmonyPatch(typeof(DysonSphere), nameof(DysonSphere.AutoConstruct))]
|
||||||
private static bool DysonSphere_AutoConstruct_Prefix(DysonSphere __instance)
|
private static bool DysonSphere_AutoConstruct_Prefix(DysonSphere __instance)
|
||||||
@@ -85,160 +85,160 @@ public static class DysonSpherePatch
|
|||||||
{
|
{
|
||||||
var dysonNode = dysonSphereLayer.nodePool[j];
|
var dysonNode = dysonSphereLayer.nodePool[j];
|
||||||
if (dysonNode == null || dysonNode.id != j) continue;
|
if (dysonNode == null || dysonNode.id != j) continue;
|
||||||
lock (dysonNode)
|
var count = dysonNode._spReq - dysonNode.spOrdered;
|
||||||
|
int todoCount;
|
||||||
|
int[] productRegister;
|
||||||
|
if (count > 0)
|
||||||
{
|
{
|
||||||
var count = dysonNode._spReq - dysonNode.spOrdered;
|
if (count > totalCount)
|
||||||
int todoCount;
|
|
||||||
int[] productRegister;
|
|
||||||
if (count > 0)
|
|
||||||
{
|
{
|
||||||
|
count = totalCount;
|
||||||
if (count > totalCount)
|
}
|
||||||
{
|
|
||||||
count = totalCount;
|
todoCount = count;
|
||||||
}
|
if (dysonNode.sp < dysonNode.spMax)
|
||||||
|
{
|
||||||
todoCount = count;
|
int diff;
|
||||||
if (dysonNode.sp < dysonNode.spMax)
|
if (dysonNode.sp + count > dysonNode.spMax)
|
||||||
{
|
{
|
||||||
int diff;
|
diff = dysonNode.spMax - dysonNode.sp;
|
||||||
if (dysonNode.sp + count > dysonNode.spMax)
|
count -= diff;
|
||||||
{
|
dysonNode._spReq -= diff;
|
||||||
diff = dysonNode.spMax - dysonNode.sp;
|
|
||||||
count -= diff;
|
dysonNode.sp = dysonNode.spMax;
|
||||||
dysonNode._spReq -= diff;
|
}
|
||||||
|
else
|
||||||
dysonNode.sp = dysonNode.spMax;
|
{
|
||||||
}
|
diff = count;
|
||||||
else
|
dysonNode._spReq -= diff;
|
||||||
{
|
|
||||||
diff = count;
|
dysonNode.sp += diff;
|
||||||
dysonNode._spReq -= diff;
|
count = 0;
|
||||||
|
}
|
||||||
dysonNode.sp += diff;
|
|
||||||
count = 0;
|
// Make compatible with DSPOptimizations
|
||||||
}
|
if (_totalNodeSpInfo != null)
|
||||||
// Make compatible with DSPOptimizations
|
_totalNodeSpInfo.SetValue(dysonSphereLayer, (long)_totalNodeSpInfo.GetValue(dysonSphereLayer) + diff - 1);
|
||||||
if (_totalNodeSpInfo != null)
|
__instance.UpdateProgress(dysonNode);
|
||||||
_totalNodeSpInfo.SetValue(dysonSphereLayer, (long)_totalNodeSpInfo.GetValue(dysonSphereLayer) + diff - 1);
|
|
||||||
__instance.UpdateProgress(dysonNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count > 0)
|
|
||||||
{
|
|
||||||
var frameCount = dysonNode.frames.Count;
|
|
||||||
var frameIndex = dysonNode.frameTurn % frameCount;
|
|
||||||
for (var i = frameCount; i > 0 && count > 0; i--)
|
|
||||||
{
|
|
||||||
var dysonFrame = dysonNode.frames[frameIndex];
|
|
||||||
var spMax = dysonFrame.spMax >> 1;
|
|
||||||
if (dysonFrame.nodeA == dysonNode && dysonFrame.spA < spMax)
|
|
||||||
{
|
|
||||||
int diff;
|
|
||||||
if (dysonFrame.spA + count > spMax)
|
|
||||||
{
|
|
||||||
diff = spMax - dysonFrame.spA;
|
|
||||||
count -= diff;
|
|
||||||
dysonNode._spReq -= diff;
|
|
||||||
|
|
||||||
dysonFrame.spA = spMax;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
diff = count;
|
|
||||||
dysonNode._spReq -= diff;
|
|
||||||
|
|
||||||
dysonFrame.spA += diff;
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
// Make compatible with DSPOptimizations
|
|
||||||
if (_totalFrameSpInfo != null)
|
|
||||||
_totalFrameSpInfo.SetValue(dysonSphereLayer, (long)_totalFrameSpInfo.GetValue(dysonSphereLayer) + diff - 1);
|
|
||||||
__instance.UpdateProgress(dysonFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count > 0 && dysonFrame.nodeB == dysonNode && dysonFrame.spB < spMax)
|
|
||||||
{
|
|
||||||
int diff;
|
|
||||||
if (dysonFrame.spB + count > spMax)
|
|
||||||
{
|
|
||||||
diff = spMax - dysonFrame.spB;
|
|
||||||
count -= diff;
|
|
||||||
dysonNode._spReq -= diff;
|
|
||||||
|
|
||||||
dysonFrame.spB = spMax;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
diff = count;
|
|
||||||
dysonNode._spReq -= diff;
|
|
||||||
|
|
||||||
dysonFrame.spB += diff;
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
// Make compatible with DSPOptimizations
|
|
||||||
if (_totalFrameSpInfo != null)
|
|
||||||
_totalFrameSpInfo.SetValue(dysonSphereLayer, (long)_totalFrameSpInfo.GetValue(dysonSphereLayer) + diff - 1);
|
|
||||||
__instance.UpdateProgress(dysonFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
frameIndex = (frameIndex + 1) % frameCount;
|
|
||||||
}
|
|
||||||
dysonNode.frameTurn = frameIndex;
|
|
||||||
}
|
|
||||||
if (dysonNode.spOrdered >= dysonNode._spReq)
|
|
||||||
{
|
|
||||||
__instance.RemoveAutoNode(dysonNode);
|
|
||||||
__instance.PickAutoNode();
|
|
||||||
}
|
|
||||||
productRegister = __instance.productRegister;
|
|
||||||
if (productRegister != null)
|
|
||||||
{
|
|
||||||
lock (productRegister)
|
|
||||||
{
|
|
||||||
productRegister[11902] += todoCount - count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
count = dysonNode._cpReq - dysonNode.cpOrdered;
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
if (count > totalCount) count = totalCount;
|
var frameCount = dysonNode.frames.Count;
|
||||||
todoCount = count;
|
var frameIndex = dysonNode.frameTurn % frameCount;
|
||||||
var shellCount = dysonNode.shells.Count;
|
for (var i = frameCount; i > 0 && count > 0; i--)
|
||||||
var shellIndex = dysonNode.shellTurn % shellCount;
|
|
||||||
for (var i = shellCount; i > 0 && count > 0; i--)
|
|
||||||
{
|
{
|
||||||
var dysonShell = dysonNode.shells[shellIndex];
|
var dysonFrame = dysonNode.frames[frameIndex];
|
||||||
lock (dysonShell)
|
var spMax = dysonFrame.spMax >> 1;
|
||||||
|
if (dysonFrame.nodeA == dysonNode && dysonFrame.spA < spMax)
|
||||||
{
|
{
|
||||||
var nodeIndex = dysonShell.nodeIndexMap[dysonNode.id];
|
int diff;
|
||||||
var diff = (dysonShell.vertsqOffset[nodeIndex + 1] - dysonShell.vertsqOffset[nodeIndex]) * dysonShell.cpPerVertex - dysonShell.nodecps[nodeIndex];
|
if (dysonFrame.spA + count > spMax)
|
||||||
if (diff > count)
|
|
||||||
diff = count;
|
|
||||||
count -= diff;
|
|
||||||
dysonNode._cpReq -= diff;
|
|
||||||
dysonShell.nodecps[nodeIndex] += diff;
|
|
||||||
dysonShell.nodecps[dysonShell.nodecps.Length - 1] += diff;
|
|
||||||
// Make compatible with DSPOptimizations
|
|
||||||
if (_totalCpInfo != null)
|
|
||||||
{
|
{
|
||||||
_totalCpInfo.SetValue(dysonSphereLayer, (long)_totalCpInfo.GetValue(dysonSphereLayer) + diff);
|
diff = spMax - dysonFrame.spA;
|
||||||
dysonShell.SetMaterialDynamicVars();
|
count -= diff;
|
||||||
}
|
dysonNode._spReq -= diff;
|
||||||
}
|
|
||||||
shellIndex = (shellIndex + 1) % shellCount;
|
|
||||||
}
|
|
||||||
dysonNode.shellTurn = shellIndex;
|
|
||||||
|
|
||||||
productRegister = __instance.productRegister;
|
dysonFrame.spA = spMax;
|
||||||
if (productRegister != null)
|
}
|
||||||
{
|
else
|
||||||
lock (productRegister)
|
{
|
||||||
{
|
diff = count;
|
||||||
productRegister[11903] += todoCount - count;
|
dysonNode._spReq -= diff;
|
||||||
|
|
||||||
|
dysonFrame.spA += diff;
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make compatible with DSPOptimizations
|
||||||
|
if (_totalFrameSpInfo != null)
|
||||||
|
_totalFrameSpInfo.SetValue(dysonSphereLayer, (long)_totalFrameSpInfo.GetValue(dysonSphereLayer) + diff - 1);
|
||||||
|
__instance.UpdateProgress(dysonFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count > 0 && dysonFrame.nodeB == dysonNode && dysonFrame.spB < spMax)
|
||||||
|
{
|
||||||
|
int diff;
|
||||||
|
if (dysonFrame.spB + count > spMax)
|
||||||
|
{
|
||||||
|
diff = spMax - dysonFrame.spB;
|
||||||
|
count -= diff;
|
||||||
|
dysonNode._spReq -= diff;
|
||||||
|
|
||||||
|
dysonFrame.spB = spMax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff = count;
|
||||||
|
dysonNode._spReq -= diff;
|
||||||
|
|
||||||
|
dysonFrame.spB += diff;
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make compatible with DSPOptimizations
|
||||||
|
if (_totalFrameSpInfo != null)
|
||||||
|
_totalFrameSpInfo.SetValue(dysonSphereLayer, (long)_totalFrameSpInfo.GetValue(dysonSphereLayer) + diff - 1);
|
||||||
|
__instance.UpdateProgress(dysonFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
frameIndex = (frameIndex + 1) % frameCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
dysonNode.frameTurn = frameIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dysonNode.spOrdered >= dysonNode._spReq)
|
||||||
|
{
|
||||||
|
__instance.RemoveAutoNode(dysonNode);
|
||||||
|
__instance.PickAutoNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
productRegister = __instance.productRegister;
|
||||||
|
if (productRegister != null)
|
||||||
|
{
|
||||||
|
lock (productRegister)
|
||||||
|
{
|
||||||
|
productRegister[11902] += todoCount - count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count = dysonNode._cpReq - dysonNode.cpOrdered;
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
if (count > totalCount) count = totalCount;
|
||||||
|
todoCount = count;
|
||||||
|
var shellCount = dysonNode.shells.Count;
|
||||||
|
var shellIndex = dysonNode.shellTurn % shellCount;
|
||||||
|
for (var i = shellCount; i > 0 && count > 0; i--)
|
||||||
|
{
|
||||||
|
var dysonShell = dysonNode.shells[shellIndex];
|
||||||
|
var nodeIndex = dysonShell.nodeIndexMap[dysonNode.id];
|
||||||
|
var diff = (dysonShell.vertsqOffset[nodeIndex + 1] - dysonShell.vertsqOffset[nodeIndex]) * dysonShell.cpPerVertex - dysonShell.nodecps[nodeIndex];
|
||||||
|
if (diff > count)
|
||||||
|
diff = count;
|
||||||
|
count -= diff;
|
||||||
|
dysonNode._cpReq -= diff;
|
||||||
|
dysonShell.nodecps[nodeIndex] += diff;
|
||||||
|
dysonShell.nodecps[dysonShell.nodecps.Length - 1] += diff;
|
||||||
|
// Make compatible with DSPOptimizations
|
||||||
|
if (_totalCpInfo != null)
|
||||||
|
{
|
||||||
|
_totalCpInfo.SetValue(dysonSphereLayer, (long)_totalCpInfo.GetValue(dysonSphereLayer) + diff);
|
||||||
|
dysonShell.SetMaterialDynamicVars();
|
||||||
|
}
|
||||||
|
shellIndex = (shellIndex + 1) % shellCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
dysonNode.shellTurn = shellIndex;
|
||||||
|
|
||||||
|
productRegister = __instance.productRegister;
|
||||||
|
if (productRegister != null)
|
||||||
|
{
|
||||||
|
lock (productRegister)
|
||||||
|
{
|
||||||
|
productRegister[11903] += todoCount - count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -329,6 +329,7 @@ public static class DysonSpherePatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,7 +465,7 @@ public static class DysonSpherePatch
|
|||||||
);
|
);
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(UIEjectorWindow), nameof(UIEjectorWindow._OnUpdate))]
|
[HarmonyPatch(typeof(UIEjectorWindow), nameof(UIEjectorWindow._OnUpdate))]
|
||||||
static IEnumerable<CodeInstruction> UIEjectorWindow__OnUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
static IEnumerable<CodeInstruction> UIEjectorWindow__OnUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
@@ -498,7 +499,7 @@ public static class DysonSpherePatch
|
|||||||
private static class OnlyConstructNodes
|
private static class OnlyConstructNodes
|
||||||
{
|
{
|
||||||
private static Harmony _patch;
|
private static Harmony _patch;
|
||||||
|
|
||||||
public static void Enable(bool on)
|
public static void Enable(bool on)
|
||||||
{
|
{
|
||||||
if (on)
|
if (on)
|
||||||
@@ -543,4 +544,4 @@ public static class DysonSpherePatch
|
|||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
using BepInEx.Configuration;
|
using BepInEx.Configuration;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
@@ -13,11 +14,15 @@ public static class GamePatch
|
|||||||
private const string GameWindowClass = "UnityWndClass";
|
private const string GameWindowClass = "UnityWndClass";
|
||||||
private static string _gameWindowTitle = "Dyson Sphere Program";
|
private static string _gameWindowTitle = "Dyson Sphere Program";
|
||||||
|
|
||||||
|
public static string ProfileName { get; private set; }
|
||||||
|
|
||||||
public static ConfigEntry<bool> EnableWindowResizeEnabled;
|
public static ConfigEntry<bool> EnableWindowResizeEnabled;
|
||||||
public static ConfigEntry<bool> LoadLastWindowRectEnabled;
|
public static ConfigEntry<bool> LoadLastWindowRectEnabled;
|
||||||
// public static ConfigEntry<bool> AutoSaveOptEnabled;
|
// public static ConfigEntry<bool> AutoSaveOptEnabled;
|
||||||
public static ConfigEntry<bool> ConvertSavesFromPeaceEnabled;
|
public static ConfigEntry<bool> ConvertSavesFromPeaceEnabled;
|
||||||
public static ConfigEntry<Vector4> LastWindowRect;
|
public static ConfigEntry<Vector4> LastWindowRect;
|
||||||
|
public static ConfigEntry<bool> ProfileBasedSaveFolderEnabled;
|
||||||
|
public static ConfigEntry<string> DefaultProfileName;
|
||||||
private static Harmony _gamePatch;
|
private static Harmony _gamePatch;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
@@ -39,6 +44,7 @@ public static class GamePatch
|
|||||||
arg = arg.Substring(index + profileSuffix.Length);
|
arg = arg.Substring(index + profileSuffix.Length);
|
||||||
var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle);
|
var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle);
|
||||||
if (wnd == IntPtr.Zero) return;
|
if (wnd == IntPtr.Zero) return;
|
||||||
|
ProfileName = arg;
|
||||||
_gameWindowTitle = $"Dyson Sphere Program - {arg}";
|
_gameWindowTitle = $"Dyson Sphere Program - {arg}";
|
||||||
WinApi.SetWindowText(wnd, _gameWindowTitle);
|
WinApi.SetWindowText(wnd, _gameWindowTitle);
|
||||||
break;
|
break;
|
||||||
@@ -48,6 +54,14 @@ public static class GamePatch
|
|||||||
LoadLastWindowRectEnabled.SettingChanged += (_, _) => LoadLastWindowRect.Enable(LoadLastWindowRectEnabled.Value);
|
LoadLastWindowRectEnabled.SettingChanged += (_, _) => LoadLastWindowRect.Enable(LoadLastWindowRectEnabled.Value);
|
||||||
// AutoSaveOptEnabled.SettingChanged += (_, _) => AutoSaveOpt.Enable(AutoSaveOptEnabled.Value);
|
// AutoSaveOptEnabled.SettingChanged += (_, _) => AutoSaveOpt.Enable(AutoSaveOptEnabled.Value);
|
||||||
ConvertSavesFromPeaceEnabled.SettingChanged += (_, _) => ConvertSavesFromPeace.Enable(ConvertSavesFromPeaceEnabled.Value);
|
ConvertSavesFromPeaceEnabled.SettingChanged += (_, _) => ConvertSavesFromPeace.Enable(ConvertSavesFromPeaceEnabled.Value);
|
||||||
|
ProfileBasedSaveFolderEnabled.SettingChanged += (_, _) =>
|
||||||
|
{
|
||||||
|
RefreshSavePath();
|
||||||
|
};
|
||||||
|
DefaultProfileName.SettingChanged += (_, _) =>
|
||||||
|
{
|
||||||
|
RefreshSavePath();
|
||||||
|
};
|
||||||
EnableWindowResize.Enable(EnableWindowResizeEnabled.Value);
|
EnableWindowResize.Enable(EnableWindowResizeEnabled.Value);
|
||||||
LoadLastWindowRect.Enable(LoadLastWindowRectEnabled.Value);
|
LoadLastWindowRect.Enable(LoadLastWindowRectEnabled.Value);
|
||||||
// AutoSaveOpt.Enable(AutoSaveOptEnabled.Value);
|
// AutoSaveOpt.Enable(AutoSaveOptEnabled.Value);
|
||||||
@@ -65,6 +79,32 @@ public static class GamePatch
|
|||||||
_gamePatch = null;
|
_gamePatch = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void RefreshSavePath()
|
||||||
|
{
|
||||||
|
if (ProfileName == null) return;
|
||||||
|
|
||||||
|
if (UIRoot.instance.loadGameWindow.gameObject.activeSelf)
|
||||||
|
{
|
||||||
|
UIRoot.instance.loadGameWindow._Close();
|
||||||
|
}
|
||||||
|
if (UIRoot.instance.saveGameWindow.gameObject.activeSelf)
|
||||||
|
{
|
||||||
|
UIRoot.instance.saveGameWindow._Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
string gameSavePath;
|
||||||
|
if (ProfileBasedSaveFolderEnabled.Value && string.Compare(DefaultProfileName.Value, ProfileName, StringComparison.OrdinalIgnoreCase) != 0)
|
||||||
|
gameSavePath = $"{GameConfig.overrideDocumentFolder}{GameConfig.gameName}/Save/{ProfileName}/";
|
||||||
|
else
|
||||||
|
gameSavePath = $"{GameConfig.overrideDocumentFolder}{GameConfig.gameName}/Save/";
|
||||||
|
if (string.Compare(GameConfig.gameSavePath, gameSavePath, StringComparison.OrdinalIgnoreCase) == 0) return;
|
||||||
|
GameConfig.gameSavePath = gameSavePath;
|
||||||
|
if (!Directory.Exists(GameConfig.gameSavePath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(GameConfig.gameSavePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HarmonyPrefix, HarmonyPatch(typeof(GameMain), nameof(GameMain.HandleApplicationQuit))]
|
[HarmonyPrefix, HarmonyPatch(typeof(GameMain), nameof(GameMain.HandleApplicationQuit))]
|
||||||
private static void GameMain_HandleApplicationQuit_Prefix()
|
private static void GameMain_HandleApplicationQuit_Prefix()
|
||||||
{
|
{
|
||||||
@@ -180,7 +220,7 @@ public static class GamePatch
|
|||||||
var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle);
|
var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle);
|
||||||
if (wnd == IntPtr.Zero) return;
|
if (wnd == IntPtr.Zero) return;
|
||||||
var rect = LastWindowRect.Value;
|
var rect = LastWindowRect.Value;
|
||||||
if (rect.z == 0f && rect.w == 0f) return;
|
if (rect is { z: 0f, w: 0f }) return;
|
||||||
var x = Mathf.RoundToInt(rect.x);
|
var x = Mathf.RoundToInt(rect.x);
|
||||||
var y = Mathf.RoundToInt(rect.y);
|
var y = Mathf.RoundToInt(rect.y);
|
||||||
WinApi.SetWindowPos(wnd, IntPtr.Zero, x, y, 0, 0, 0x0235);
|
WinApi.SetWindowPos(wnd, IntPtr.Zero, x, y, 0, 0, 0x0235);
|
||||||
@@ -192,7 +232,7 @@ public static class GamePatch
|
|||||||
{
|
{
|
||||||
if (fullscreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow || GameMain.isRunning) return;
|
if (fullscreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow || GameMain.isRunning) return;
|
||||||
var rect = LastWindowRect.Value;
|
var rect = LastWindowRect.Value;
|
||||||
if (rect.z == 0f && rect.w == 0f) return;
|
if (rect is { z: 0f, w: 0f }) return;
|
||||||
var w = Mathf.RoundToInt(rect.z);
|
var w = Mathf.RoundToInt(rect.z);
|
||||||
var h = Mathf.RoundToInt(rect.w);
|
var h = Mathf.RoundToInt(rect.w);
|
||||||
width = w;
|
width = w;
|
||||||
@@ -213,7 +253,7 @@ public static class GamePatch
|
|||||||
var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle);
|
var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle);
|
||||||
if (wnd == IntPtr.Zero) return;
|
if (wnd == IntPtr.Zero) return;
|
||||||
var rect = LastWindowRect.Value;
|
var rect = LastWindowRect.Value;
|
||||||
if (rect.z == 0f && rect.w == 0f) return;
|
if (rect is { z: 0f, w: 0f }) return;
|
||||||
var x = Mathf.RoundToInt(rect.x);
|
var x = Mathf.RoundToInt(rect.x);
|
||||||
var y = Mathf.RoundToInt(rect.y);
|
var y = Mathf.RoundToInt(rect.y);
|
||||||
var w = Mathf.RoundToInt(rect.z);
|
var w = Mathf.RoundToInt(rect.z);
|
||||||
|
|||||||
@@ -21,6 +21,11 @@
|
|||||||
- Enable game window resize
|
- Enable game window resize
|
||||||
- Remember window position and size on last exit
|
- Remember window position and size on last exit
|
||||||
- Convert Peace-Mode saves to Combat-Mode on loading
|
- Convert Peace-Mode saves to Combat-Mode on loading
|
||||||
|
- Mod manager profile based save folder
|
||||||
|
- Save files are stored in `Save\<ProfileName>` folder.
|
||||||
|
- Will use original save location if matching default profile name.
|
||||||
|
- Increase maximum count of Metadata Instantiations to 20000 (from 2000)
|
||||||
|
- Increase capacity of player order queue to 128 (from 16)
|
||||||
+ Planet/Factory
|
+ Planet/Factory
|
||||||
- Sunlight at night
|
- Sunlight at night
|
||||||
- Remove some build conditions
|
- Remove some build conditions
|
||||||
@@ -117,6 +122,9 @@
|
|||||||
- 可调整游戏窗口大小(可最大化和拖动边框)
|
- 可调整游戏窗口大小(可最大化和拖动边框)
|
||||||
- 记住上次退出时的窗口位置和大小
|
- 记住上次退出时的窗口位置和大小
|
||||||
- 在加载和平模式存档时将其转换为战斗模式
|
- 在加载和平模式存档时将其转换为战斗模式
|
||||||
|
- 基于mod管理器配置档案名的存档文件夹
|
||||||
|
- 存档文件会存储在`Save\<ProfileName>`文件夹中
|
||||||
|
- 如果匹配默认配置档案名则使用原始存档位置
|
||||||
- 将元数据提取的最大数量增加到20000(原来为2000)
|
- 将元数据提取的最大数量增加到20000(原来为2000)
|
||||||
- 将玩家指令队列的容量增加到128(原来为16)
|
- 将玩家指令队列的容量增加到128(原来为16)
|
||||||
+ 行星/工厂
|
+ 行星/工厂
|
||||||
|
|||||||
@@ -14,9 +14,6 @@ namespace UXAssist.UI;
|
|||||||
|
|
||||||
public class MyWindow : ManualBehaviour
|
public class MyWindow : ManualBehaviour
|
||||||
{
|
{
|
||||||
private readonly Dictionary<InputField, Tuple<UnityAction<string>, UnityAction<string>>> _inputFields = new();
|
|
||||||
private readonly Dictionary<UIButton, UnityAction> _buttons = new();
|
|
||||||
protected bool EventRegistered { get; private set; }
|
|
||||||
private float _maxX;
|
private float _maxX;
|
||||||
protected float MaxY;
|
protected float MaxY;
|
||||||
protected const float TitleHeight = 48f;
|
protected const float TitleHeight = 48f;
|
||||||
@@ -141,15 +138,10 @@ public class MyWindow : ManualBehaviour
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.fontSize = fontSize;
|
t.fontSize = fontSize;
|
||||||
btn.button.onClick.RemoveAllListeners();
|
|
||||||
btn.tip = null;
|
btn.tip = null;
|
||||||
btn.tips = new UIButton.TipSettings();
|
btn.tips = new UIButton.TipSettings();
|
||||||
_buttons[btn] = onClick;
|
btn.button.onClick.RemoveAllListeners();
|
||||||
if (EventRegistered)
|
if (onClick != null) btn.button.onClick.AddListener(onClick);
|
||||||
{
|
|
||||||
if (onClick != null)
|
|
||||||
btn.button.onClick.AddListener(onClick);
|
|
||||||
}
|
|
||||||
|
|
||||||
_maxX = Math.Max(_maxX, x + rect.sizeDelta.x);
|
_maxX = Math.Max(_maxX, x + rect.sizeDelta.x);
|
||||||
MaxY = Math.Max(MaxY, y + rect.sizeDelta.y);
|
MaxY = Math.Max(MaxY, y + rect.sizeDelta.y);
|
||||||
@@ -184,11 +176,7 @@ public class MyWindow : ManualBehaviour
|
|||||||
}
|
}
|
||||||
|
|
||||||
btn.button.onClick.RemoveAllListeners();
|
btn.button.onClick.RemoveAllListeners();
|
||||||
_buttons[btn] = onClick;
|
if (onClick != null) btn.button.onClick.AddListener(onClick);
|
||||||
if (EventRegistered && onClick != null)
|
|
||||||
{
|
|
||||||
btn.button.onClick.AddListener(onClick);
|
|
||||||
}
|
|
||||||
|
|
||||||
_maxX = Math.Max(_maxX, x + rect.sizeDelta.x);
|
_maxX = Math.Max(_maxX, x + rect.sizeDelta.x);
|
||||||
MaxY = Math.Max(MaxY, y + rect.sizeDelta.y);
|
MaxY = Math.Max(MaxY, y + rect.sizeDelta.y);
|
||||||
@@ -305,67 +293,39 @@ public class MyWindow : ManualBehaviour
|
|||||||
inputField.GetComponent<Image>().color = new Color(1f, 1f, 1f, 0.05f);
|
inputField.GetComponent<Image>().color = new Color(1f, 1f, 1f, 0.05f);
|
||||||
var rect = Util.NormalizeRectWithTopLeft(inputField, x, y, parent);
|
var rect = Util.NormalizeRectWithTopLeft(inputField, x, y, parent);
|
||||||
rect.sizeDelta = new Vector2(210, rect.sizeDelta.y);
|
rect.sizeDelta = new Vector2(210, rect.sizeDelta.y);
|
||||||
inputField.textComponent.text = text;
|
inputField.text = text;
|
||||||
inputField.textComponent.fontSize = fontSize;
|
inputField.textComponent.fontSize = fontSize;
|
||||||
|
|
||||||
inputField.onValueChanged.RemoveAllListeners();
|
inputField.onValueChanged.RemoveAllListeners();
|
||||||
|
if (onChanged != null) inputField.onValueChanged.AddListener(onChanged);
|
||||||
inputField.onEndEdit.RemoveAllListeners();
|
inputField.onEndEdit.RemoveAllListeners();
|
||||||
_inputFields[inputField] = Tuple.Create(onChanged, onEditEnd);
|
if (onEditEnd != null) inputField.onEndEdit.AddListener(onEditEnd);
|
||||||
if (EventRegistered)
|
|
||||||
{
|
|
||||||
if (onChanged != null)
|
|
||||||
inputField.onValueChanged.AddListener(onChanged);
|
|
||||||
if (onEditEnd != null)
|
|
||||||
inputField.onEndEdit.AddListener(onEditEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
_maxX = Math.Max(_maxX, x + rect.sizeDelta.x);
|
_maxX = Math.Max(_maxX, x + rect.sizeDelta.x);
|
||||||
MaxY = Math.Max(MaxY, y + rect.sizeDelta.y);
|
MaxY = Math.Max(MaxY, y + rect.sizeDelta.y);
|
||||||
return inputField;
|
return inputField;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _OnRegEvent()
|
public InputField AddInputField(float x, float y, float width, RectTransform parent, ConfigEntry<string> config, int fontSize = 16, string objName = "input")
|
||||||
{
|
{
|
||||||
base._OnRegEvent();
|
var stationWindow = UIRoot.instance.uiGame.stationWindow;
|
||||||
if (EventRegistered) return;
|
//public InputField nameInput;
|
||||||
foreach (var t in _inputFields)
|
var inputField = Instantiate(stationWindow.nameInput);
|
||||||
{
|
inputField.gameObject.name = objName;
|
||||||
var inputField = t.Key;
|
Destroy(inputField.GetComponent<UIButton>());
|
||||||
if (t.Value.Item1 != null)
|
inputField.GetComponent<Image>().color = new Color(1f, 1f, 1f, 0.05f);
|
||||||
inputField.onValueChanged.AddListener(t.Value.Item1);
|
var rect = Util.NormalizeRectWithTopLeft(inputField, x, y, parent);
|
||||||
if (t.Value.Item2 != null)
|
rect.sizeDelta = new Vector2(width, rect.sizeDelta.y);
|
||||||
inputField.onEndEdit.AddListener(t.Value.Item2);
|
inputField.text = config.Value;
|
||||||
}
|
inputField.textComponent.fontSize = fontSize;
|
||||||
|
|
||||||
foreach (var t in _buttons)
|
inputField.onValueChanged.RemoveAllListeners();
|
||||||
{
|
inputField.onEndEdit.RemoveAllListeners();
|
||||||
var btn = t.Key;
|
inputField.onEndEdit.AddListener(value => config.Value = value);
|
||||||
if (t.Value != null)
|
|
||||||
btn.button.onClick.AddListener(t.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
EventRegistered = true;
|
_maxX = Math.Max(_maxX, x + rect.sizeDelta.x);
|
||||||
}
|
MaxY = Math.Max(MaxY, y + rect.sizeDelta.y);
|
||||||
|
return inputField;
|
||||||
public override void _OnUnregEvent()
|
|
||||||
{
|
|
||||||
base._OnUnregEvent();
|
|
||||||
if (!EventRegistered) return;
|
|
||||||
EventRegistered = false;
|
|
||||||
foreach (var t in _buttons)
|
|
||||||
{
|
|
||||||
var btn = t.Key;
|
|
||||||
if (t.Value != null)
|
|
||||||
btn.button.onClick.RemoveListener(t.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var t in _inputFields)
|
|
||||||
{
|
|
||||||
var inputField = t.Key;
|
|
||||||
if (t.Value.Item1 != null)
|
|
||||||
inputField.onValueChanged.RemoveListener(t.Value.Item1);
|
|
||||||
if (t.Value.Item2 != null)
|
|
||||||
inputField.onEndEdit.RemoveListener(t.Value.Item2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,10 +371,7 @@ public class MyWindowWithTabs : MyWindow
|
|||||||
btn.data = index;
|
btn.data = index;
|
||||||
|
|
||||||
_tabs.Add(Tuple.Create(tabRect, btn));
|
_tabs.Add(Tuple.Create(tabRect, btn));
|
||||||
if (EventRegistered)
|
btn.onClick += OnTabButtonClick;
|
||||||
{
|
|
||||||
btn.onClick += OnTabButtonClick;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaxY = Math.Max(MaxY, y + TabHeight);
|
MaxY = Math.Max(MaxY, y + TabHeight);
|
||||||
return tabRect;
|
return tabRect;
|
||||||
@@ -443,32 +400,6 @@ public class MyWindowWithTabs : MyWindow
|
|||||||
_tabY += 28f;
|
_tabY += 28f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _OnRegEvent()
|
|
||||||
{
|
|
||||||
if (!EventRegistered)
|
|
||||||
{
|
|
||||||
foreach (var t in _tabs)
|
|
||||||
{
|
|
||||||
t.Item2.onClick += OnTabButtonClick;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
base._OnRegEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _OnUnregEvent()
|
|
||||||
{
|
|
||||||
if (EventRegistered)
|
|
||||||
{
|
|
||||||
foreach (var t in _tabs)
|
|
||||||
{
|
|
||||||
t.Item2.onClick -= OnTabButtonClick;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
base._OnUnregEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void SetCurrentTab(int index) => OnTabButtonClick(index);
|
protected void SetCurrentTab(int index) => OnTabButtonClick(index);
|
||||||
|
|
||||||
private void OnTabButtonClick(int index)
|
private void OnTabButtonClick(int index)
|
||||||
@@ -524,7 +455,7 @@ public static class MyWindowManager
|
|||||||
{
|
{
|
||||||
var btn = child.GetComponentInChildren<Button>();
|
var btn = child.GetComponentInChildren<Button>();
|
||||||
//close-btn
|
//close-btn
|
||||||
if (btn != null)
|
if (btn)
|
||||||
{
|
{
|
||||||
btn.onClick.AddListener(win._Close);
|
btn.onClick.AddListener(win._Close);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ public static class UIConfigWindow
|
|||||||
I18N.Add("Better auto-save mechanism tips", "Auto saves are stored in 'Save\\AutoSaves' folder, filenames are combined with cluster address and date-time", "自动存档会以星区地址和日期时间组合为文件名存储在'Save\\AutoSaves'文件夹中");
|
I18N.Add("Better auto-save mechanism tips", "Auto saves are stored in 'Save\\AutoSaves' folder, filenames are combined with cluster address and date-time", "自动存档会以星区地址和日期时间组合为文件名存储在'Save\\AutoSaves'文件夹中");
|
||||||
*/
|
*/
|
||||||
I18N.Add("Convert old saves to Combat Mode on loading", "Convert old saves to Combat Mode on loading (Use settings in new game panel)", "读取旧档时转为战斗模式(使用新游戏面板的战斗难度设置)");
|
I18N.Add("Convert old saves to Combat Mode on loading", "Convert old saves to Combat Mode on loading (Use settings in new game panel)", "读取旧档时转为战斗模式(使用新游戏面板的战斗难度设置)");
|
||||||
|
I18N.Add("Profile-based save folder", "Mod manager profile based save folder", "基于mod管理器配置档案名的存档文件夹");
|
||||||
|
I18N.Add("Profile-based save folder tips", "Save files are stored in 'Save\\<ProfileName>' folder.\nWill use original save location if matching default profile name", "存档文件会存储在'Save\\<ProfileName>'文件夹中\n如果匹配默认配置档案名则使用原始存档位置");
|
||||||
|
I18N.Add("Default profile name", "Default profile name", "默认配置档案名");
|
||||||
I18N.Add("Unlimited interactive range", "Unlimited interactive range", "无限交互距离");
|
I18N.Add("Unlimited interactive range", "Unlimited interactive range", "无限交互距离");
|
||||||
I18N.Add("Night Light", "Sunlight at night", "夜间日光灯");
|
I18N.Add("Night Light", "Sunlight at night", "夜间日光灯");
|
||||||
I18N.Add("Remove some build conditions", "Remove some build conditions", "移除部分不影响游戏逻辑的建造条件");
|
I18N.Add("Remove some build conditions", "Remove some build conditions", "移除部分不影响游戏逻辑的建造条件");
|
||||||
@@ -97,6 +100,8 @@ public static class UIConfigWindow
|
|||||||
|
|
||||||
private static void CreateUI(MyConfigWindow wnd, RectTransform trans)
|
private static void CreateUI(MyConfigWindow wnd, RectTransform trans)
|
||||||
{
|
{
|
||||||
|
MyCheckBox checkBoxForMeasureTipsPos;
|
||||||
|
|
||||||
_windowTrans = trans;
|
_windowTrans = trans;
|
||||||
wnd.AddTabGroup(trans, "UXAssist", "tab-group-uxassist");
|
wnd.AddTabGroup(trans, "UXAssist", "tab-group-uxassist");
|
||||||
var tab1 = wnd.AddTab(trans, "General");
|
var tab1 = wnd.AddTab(trans, "General");
|
||||||
@@ -105,16 +110,30 @@ public static class UIConfigWindow
|
|||||||
wnd.AddCheckBox(x, y, tab1, GamePatch.EnableWindowResizeEnabled, "Enable game window resize");
|
wnd.AddCheckBox(x, y, tab1, GamePatch.EnableWindowResizeEnabled, "Enable game window resize");
|
||||||
y += 36f;
|
y += 36f;
|
||||||
wnd.AddCheckBox(x, y, tab1, GamePatch.LoadLastWindowRectEnabled, "Remeber window position and size on last exit");
|
wnd.AddCheckBox(x, y, tab1, GamePatch.LoadLastWindowRectEnabled, "Remeber window position and size on last exit");
|
||||||
y += 36f;
|
|
||||||
/*
|
/*
|
||||||
|
y += 30f;
|
||||||
wnd.AddCheckBox(x, y, tab1, GamePatch.AutoSaveOptEnabled, "Better auto-save mechanism");
|
wnd.AddCheckBox(x, y, tab1, GamePatch.AutoSaveOptEnabled, "Better auto-save mechanism");
|
||||||
x = 200f;
|
x = 200f;
|
||||||
y += 6f;
|
y += 6f;
|
||||||
wnd.AddTipsButton2(x, y, tab1, "Better auto-save mechanism", "Better auto-save mechanism tips", "auto-save-opt-tips");
|
wnd.AddTipsButton2(x, y, tab1, "Better auto-save mechanism", "Better auto-save mechanism tips", "auto-save-opt-tips");
|
||||||
x = 0f;
|
x = 0f;
|
||||||
y += 30f;
|
|
||||||
*/
|
*/
|
||||||
|
y += 36f;
|
||||||
wnd.AddCheckBox(x, y, tab1, GamePatch.ConvertSavesFromPeaceEnabled, "Convert old saves to Combat Mode on loading");
|
wnd.AddCheckBox(x, y, tab1, GamePatch.ConvertSavesFromPeaceEnabled, "Convert old saves to Combat Mode on loading");
|
||||||
|
if (GamePatch.ProfileName != null)
|
||||||
|
{
|
||||||
|
y += 36f;
|
||||||
|
checkBoxForMeasureTipsPos = wnd.AddCheckBox(x, y, tab1, GamePatch.ProfileBasedSaveFolderEnabled, "Profile-based save folder");
|
||||||
|
x += checkBoxForMeasureTipsPos.Width + 5f;
|
||||||
|
y += 6f;
|
||||||
|
wnd.AddTipsButton2(x, y, tab1, "Profile-based save folder", "Profile-based save folder tips", "btn-profile-based-save-folder-tips");
|
||||||
|
x = 0;
|
||||||
|
y += 24f;
|
||||||
|
wnd.AddText2(x, y, tab1, "Default profile name", 15, "text-default-profile-name");
|
||||||
|
y += 24f;
|
||||||
|
wnd.AddInputField(x, y, 200f, tab1, GamePatch.DefaultProfileName, 15, "input-profile-save-folder");
|
||||||
|
}
|
||||||
|
|
||||||
var tab2 = wnd.AddTab(trans, "Planet/Factory");
|
var tab2 = wnd.AddTab(trans, "Planet/Factory");
|
||||||
x = 0f;
|
x = 0f;
|
||||||
y = 10f;
|
y = 10f;
|
||||||
@@ -130,16 +149,16 @@ public static class UIConfigWindow
|
|||||||
y += 36f;
|
y += 36f;
|
||||||
wnd.AddCheckBox(x, y, tab2, FactoryPatch.OffGridBuildingEnabled, "Off-grid building and stepped rotation");
|
wnd.AddCheckBox(x, y, tab2, FactoryPatch.OffGridBuildingEnabled, "Off-grid building and stepped rotation");
|
||||||
y += 36f;
|
y += 36f;
|
||||||
var cb = wnd.AddCheckBox(x, y, tab2, FactoryPatch.TreatStackingAsSingleEnabled, "Treat stack items as single in monitor components");
|
checkBoxForMeasureTipsPos = wnd.AddCheckBox(x, y, tab2, FactoryPatch.TreatStackingAsSingleEnabled, "Treat stack items as single in monitor components");
|
||||||
x += cb.Width + 5f;
|
x += checkBoxForMeasureTipsPos.Width + 5f;
|
||||||
y += 6f;
|
y += 6f;
|
||||||
wnd.AddTipsButton2(x, y, tab2, "Enhance control for logistic storage limits", "Enhance control for logistic storage limits tips", "enhanced-logistic-limit-tips");
|
wnd.AddTipsButton2(x, y, tab2, "Enhance control for logistic storage limits", "Enhance control for logistic storage limits tips", "enhanced-logistic-limit-tips");
|
||||||
x = 0f;
|
x = 0f;
|
||||||
y += 30f;
|
y += 30f;
|
||||||
wnd.AddCheckBox(x, y, tab2, FactoryPatch.QuickBuildAndDismantleLabsEnabled, "Quick build and dismantle stacking labs");
|
wnd.AddCheckBox(x, y, tab2, FactoryPatch.QuickBuildAndDismantleLabsEnabled, "Quick build and dismantle stacking labs");
|
||||||
y += 36f;
|
y += 36f;
|
||||||
cb = wnd.AddCheckBox(x, y, tab2, FactoryPatch.ProtectVeinsFromExhaustionEnabled, "Protect veins from exhaustion");
|
checkBoxForMeasureTipsPos = wnd.AddCheckBox(x, y, tab2, FactoryPatch.ProtectVeinsFromExhaustionEnabled, "Protect veins from exhaustion");
|
||||||
x += cb.Width + 5f;
|
x += checkBoxForMeasureTipsPos.Width + 5f;
|
||||||
y += 6f;
|
y += 6f;
|
||||||
wnd.AddTipsButton2(x, y, tab2, "Protect veins from exhaustion", "Protect veins from exhaustion tips", "protect-veins-tips");
|
wnd.AddTipsButton2(x, y, tab2, "Protect veins from exhaustion", "Protect veins from exhaustion tips", "protect-veins-tips");
|
||||||
x = 0f;
|
x = 0f;
|
||||||
@@ -177,8 +196,8 @@ public static class UIConfigWindow
|
|||||||
y += 36f;
|
y += 36f;
|
||||||
wnd.AddCheckBox(x, y, tab2, LogisticsPatch.AllowOverflowInLogisticsEnabled, "Allow overflow for Logistic Stations and Advanced Mining Machines");
|
wnd.AddCheckBox(x, y, tab2, LogisticsPatch.AllowOverflowInLogisticsEnabled, "Allow overflow for Logistic Stations and Advanced Mining Machines");
|
||||||
y += 36f;
|
y += 36f;
|
||||||
cb = wnd.AddCheckBox(x, y, tab2, LogisticsPatch.LogisticsConstrolPanelImprovementEnabled, "Logistics Control Panel Improvement");
|
checkBoxForMeasureTipsPos = wnd.AddCheckBox(x, y, tab2, LogisticsPatch.LogisticsConstrolPanelImprovementEnabled, "Logistics Control Panel Improvement");
|
||||||
x += cb.Width + 5f;
|
x += checkBoxForMeasureTipsPos.Width + 5f;
|
||||||
y += 6f;
|
y += 6f;
|
||||||
wnd.AddTipsButton2(x, y, tab2, "Logistics Control Panel Improvement", "Logistics Control Panel Improvement tips", "lcp-improvement-tips");
|
wnd.AddTipsButton2(x, y, tab2, "Logistics Control Panel Improvement", "Logistics Control Panel Improvement tips", "lcp-improvement-tips");
|
||||||
// x -= 200f;
|
// x -= 200f;
|
||||||
@@ -192,8 +211,8 @@ public static class UIConfigWindow
|
|||||||
y += 36f;
|
y += 36f;
|
||||||
wnd.AddCheckBox(x, y, tab3, PlayerPatch.HideTipsForSandsChangesEnabled, "Hide tips for soil piles changes");
|
wnd.AddCheckBox(x, y, tab3, PlayerPatch.HideTipsForSandsChangesEnabled, "Hide tips for soil piles changes");
|
||||||
y += 36f;
|
y += 36f;
|
||||||
cb = wnd.AddCheckBox(x, y, tab3, PlayerPatch.EnhancedMechaForgeCountControlEnabled, "Enhanced count control for hand-make");
|
checkBoxForMeasureTipsPos = wnd.AddCheckBox(x, y, tab3, PlayerPatch.EnhancedMechaForgeCountControlEnabled, "Enhanced count control for hand-make");
|
||||||
x += cb.Width + 5f;
|
x += checkBoxForMeasureTipsPos.Width + 5f;
|
||||||
y += 6f;
|
y += 6f;
|
||||||
wnd.AddTipsButton2(x, y, tab3, "Enhanced count control for hand-make", "Enhanced count control for hand-make tips", "enhanced-count-control-tips");
|
wnd.AddTipsButton2(x, y, tab3, "Enhanced count control for hand-make", "Enhanced count control for hand-make tips", "enhanced-count-control-tips");
|
||||||
x = 0f;
|
x = 0f;
|
||||||
|
|||||||
@@ -67,6 +67,10 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
|
|||||||
"Load last window position and size when game starts");
|
"Load last window position and size when game starts");
|
||||||
GamePatch.LastWindowRect = Config.Bind("Game", "LastWindowRect", new Vector4(0f, 0f, 0f, 0f),
|
GamePatch.LastWindowRect = Config.Bind("Game", "LastWindowRect", new Vector4(0f, 0f, 0f, 0f),
|
||||||
"Last window position and size");
|
"Last window position and size");
|
||||||
|
GamePatch.ProfileBasedSaveFolderEnabled = Config.Bind("Game", "ProfileBasedSaveFolder", false,
|
||||||
|
"Profile-based save folder");
|
||||||
|
GamePatch.DefaultProfileName = Config.Bind("Game", "DefaultProfileName", "Default",
|
||||||
|
"Default profile name, used when profile-based save folder is enabled. Use original game save folder if matched");
|
||||||
/*
|
/*
|
||||||
GamePatch.AutoSaveOptEnabled = Config.Bind("Game", "AutoSaveOpt", false,
|
GamePatch.AutoSaveOptEnabled = Config.Bind("Game", "AutoSaveOpt", false,
|
||||||
"Better auto-save mechanism");
|
"Better auto-save mechanism");
|
||||||
|
|||||||
Reference in New Issue
Block a user