1
0
mirror of https://github.com/soarqin/DSP_Mods.git synced 2025-12-09 00:53:39 +08:00

UXAssist and CheatEnabler new releases

This commit is contained in:
2024-08-30 19:14:34 +08:00
parent 287cfbbed4
commit 92445a452a
14 changed files with 408 additions and 263 deletions

View File

@@ -1,5 +1,10 @@
## 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
+ Fix `Pump Anywhere`
* 2.3.21
@@ -122,6 +127,11 @@
## 更新日志
* 2.3.24
+ `立即完成戴森壳建造`:修复了在某些情况下可能导致发电为负的问题
* 2.3.23
+ 新功能:`立即完成戴森壳建造`
+ 修复了在游戏完全加载前打开配置面板可能导致的崩溃问题
* 2.3.22
+ 修复了`平地抽水`
* 2.3.21

View File

@@ -86,6 +86,7 @@ public class CheatEnabler : BaseUnityPlugin
PlayerFunctions.Init();
PlayerPatch.Init();
DysonSpherePatch.Init();
DysonSphereFunctions.Init();
CombatPatch.Init();
}

View File

@@ -5,7 +5,7 @@
<TargetFramework>net472</TargetFramework>
<BepInExPluginGuid>org.soardev.cheatenabler</BepInExPluginGuid>
<Description>DSP MOD - CheatEnabler</Description>
<Version>2.3.22</Version>
<Version>2.3.24</Version>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>latest</LangVersion>
<PackageId>CheatEnabler</PackageId>

View 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;
}
}
});
}
}

View File

@@ -43,6 +43,7 @@
+ Skip absorption period
+ Quick absorb
+ Eject anyway
+ Complete Dyson Sphere Shells instantly
+ Mecha/Combat:
+ Mecha and Drones/Fleets invicible
+ Buildings invicible
@@ -100,6 +101,7 @@
+ 跳过吸收阶段
+ 快速吸收
+ 全球弹射
+ 立即完成戴森壳建造
+ 战斗:
+ 机甲和战斗无人机无敌
+ 建筑无敌

View File

@@ -61,6 +61,7 @@ public static class UIConfigWindow
I18N.Add("Eject anyway", "Eject anyway", "全球弹射");
I18N.Add("Overclock Ejectors", "Overclock Ejectors (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("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", "机甲和战斗无人机无敌");
@@ -204,6 +205,9 @@ public static class UIConfigWindow
wnd.AddCheckBox(x, y, tab4, DysonSpherePatch.OverclockEjectorEnabled, "Overclock Ejectors");
y += 36f;
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");
x = 0f;

View File

@@ -1,6 +1,6 @@
{
"name": "CheatEnabler",
"version_number": "2.3.22",
"version_number": "2.3.24",
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/CheatEnabler",
"description": "Add various cheat functions while disabling abnormal determinants / 添加一些作弊功能,同时屏蔽异常检测",
"dependencies": [

View File

@@ -6,11 +6,13 @@
- Quick-set item filter while right-clicking item icons in storage list on the panel
+ New feature: `Dyson Sphere "Auto Fast Build" speed multiplier`
- 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
+ `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.
+ 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
+ Fix `Remove some build conditions`
* 1.1.3
@@ -157,12 +159,14 @@
- 打开面板时自动将鼠标指向物品设为筛选条件
- 在控制面板物流塔列表中右键点击物品图标快速设置为筛选条件
+ 新功能:`戴森球自动快速建造速度倍率`
- 注意:这仅适用于沙盒模式下的`戴森球自动快速建造`功能
- 注意:这仅适用于沙盒模式下的`戴森球自动快速建造`功能
+ 新功能:`基于mod管理器配置档案名的存档文件夹`
- 存档文件会存储在`Save\<ProfileName>`文件夹中
- 如果匹配默认配置档案名则使用原始存档位置
+ `快速建造和拆除堆叠研究站`:现在也支持储物仓和储液罐
+ `允许调整游戏窗口大小`:在应用游戏选项时保持窗口可调整大小
+ `记住上次退出时的窗口位置和大小`:如果分辨率相关的配置项未改变,则在应用游戏选项时不调整窗口大小
+ 自动调整面板大小适应内容以更好地支持多语言和依赖于UX助手配置面板功能的mod
+ 修复了在游戏完全加载前打开配置面板可能导致的崩溃问题
* 1.1.4
+ 修复了`移除部分不影响游戏逻辑的建造条件`
* 1.1.3

View File

@@ -28,7 +28,7 @@ public static class DysonSpherePatch
_totalFrameSpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalFrameSP");
_totalCpInfo = AccessTools.Field(typeof(DysonSphereLayer), "totalCP");
}
public static void Uninit()
{
StopEjectOnNodeComplete.Enable(false);
@@ -62,6 +62,7 @@ public static class DysonSpherePatch
if (pool[id].nodeLayerId != index) continue;
ds.RemoveDysonRocket(id);
}
ds.RemoveLayer(index);
}
@@ -69,10 +70,9 @@ public static class DysonSpherePatch
[HarmonyPatch(typeof(DysonSwarm), nameof(DysonSwarm.AutoConstruct))]
private static bool DysonSwarm_AutoConstruct_Prefix(DysonSwarm __instance)
{
return false;
return __instance.dysonSphere.autoNodeCount == 0;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(DysonSphere), nameof(DysonSphere.AutoConstruct))]
private static bool DysonSphere_AutoConstruct_Prefix(DysonSphere __instance)
@@ -85,160 +85,160 @@ public static class DysonSpherePatch
{
var dysonNode = dysonSphereLayer.nodePool[j];
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;
int todoCount;
int[] productRegister;
if (count > 0)
if (count > totalCount)
{
if (count > totalCount)
{
count = totalCount;
}
todoCount = count;
if (dysonNode.sp < dysonNode.spMax)
{
int diff;
if (dysonNode.sp + count > dysonNode.spMax)
{
diff = dysonNode.spMax - dysonNode.sp;
count -= diff;
dysonNode._spReq -= diff;
dysonNode.sp = dysonNode.spMax;
}
else
{
diff = count;
dysonNode._spReq -= diff;
dysonNode.sp += diff;
count = 0;
}
// Make compatible with DSPOptimizations
if (_totalNodeSpInfo != null)
_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 = totalCount;
}
todoCount = count;
if (dysonNode.sp < dysonNode.spMax)
{
int diff;
if (dysonNode.sp + count > dysonNode.spMax)
{
diff = dysonNode.spMax - dysonNode.sp;
count -= diff;
dysonNode._spReq -= diff;
dysonNode.sp = dysonNode.spMax;
}
else
{
diff = count;
dysonNode._spReq -= diff;
dysonNode.sp += diff;
count = 0;
}
// Make compatible with DSPOptimizations
if (_totalNodeSpInfo != null)
_totalNodeSpInfo.SetValue(dysonSphereLayer, (long)_totalNodeSpInfo.GetValue(dysonSphereLayer) + diff - 1);
__instance.UpdateProgress(dysonNode);
}
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 frameCount = dysonNode.frames.Count;
var frameIndex = dysonNode.frameTurn % frameCount;
for (var i = frameCount; i > 0 && count > 0; i--)
{
var dysonShell = dysonNode.shells[shellIndex];
lock (dysonShell)
var dysonFrame = dysonNode.frames[frameIndex];
var spMax = dysonFrame.spMax >> 1;
if (dysonFrame.nodeA == dysonNode && dysonFrame.spA < spMax)
{
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)
int diff;
if (dysonFrame.spA + count > spMax)
{
_totalCpInfo.SetValue(dysonSphereLayer, (long)_totalCpInfo.GetValue(dysonSphereLayer) + diff);
dysonShell.SetMaterialDynamicVars();
}
}
shellIndex = (shellIndex + 1) % shellCount;
}
dysonNode.shellTurn = shellIndex;
diff = spMax - dysonFrame.spA;
count -= diff;
dysonNode._spReq -= diff;
productRegister = __instance.productRegister;
if (productRegister != null)
{
lock (productRegister)
{
productRegister[11903] += todoCount - count;
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 > 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;
}
@@ -464,7 +465,7 @@ public static class DysonSpherePatch
);
return matcher.InstructionEnumeration();
}
[HarmonyTranspiler]
[HarmonyPatch(typeof(UIEjectorWindow), nameof(UIEjectorWindow._OnUpdate))]
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 Harmony _patch;
public static void Enable(bool on)
{
if (on)
@@ -543,4 +544,4 @@ public static class DysonSpherePatch
return matcher.InstructionEnumeration();
}
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Emit;
using BepInEx.Configuration;
using HarmonyLib;
@@ -13,11 +14,15 @@ public static class GamePatch
private const string GameWindowClass = "UnityWndClass";
private static string _gameWindowTitle = "Dyson Sphere Program";
public static string ProfileName { get; private set; }
public static ConfigEntry<bool> EnableWindowResizeEnabled;
public static ConfigEntry<bool> LoadLastWindowRectEnabled;
// public static ConfigEntry<bool> AutoSaveOptEnabled;
public static ConfigEntry<bool> ConvertSavesFromPeaceEnabled;
public static ConfigEntry<Vector4> LastWindowRect;
public static ConfigEntry<bool> ProfileBasedSaveFolderEnabled;
public static ConfigEntry<string> DefaultProfileName;
private static Harmony _gamePatch;
public static void Init()
@@ -39,6 +44,7 @@ public static class GamePatch
arg = arg.Substring(index + profileSuffix.Length);
var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle);
if (wnd == IntPtr.Zero) return;
ProfileName = arg;
_gameWindowTitle = $"Dyson Sphere Program - {arg}";
WinApi.SetWindowText(wnd, _gameWindowTitle);
break;
@@ -48,6 +54,14 @@ public static class GamePatch
LoadLastWindowRectEnabled.SettingChanged += (_, _) => LoadLastWindowRect.Enable(LoadLastWindowRectEnabled.Value);
// AutoSaveOptEnabled.SettingChanged += (_, _) => AutoSaveOpt.Enable(AutoSaveOptEnabled.Value);
ConvertSavesFromPeaceEnabled.SettingChanged += (_, _) => ConvertSavesFromPeace.Enable(ConvertSavesFromPeaceEnabled.Value);
ProfileBasedSaveFolderEnabled.SettingChanged += (_, _) =>
{
RefreshSavePath();
};
DefaultProfileName.SettingChanged += (_, _) =>
{
RefreshSavePath();
};
EnableWindowResize.Enable(EnableWindowResizeEnabled.Value);
LoadLastWindowRect.Enable(LoadLastWindowRectEnabled.Value);
// AutoSaveOpt.Enable(AutoSaveOptEnabled.Value);
@@ -65,6 +79,32 @@ public static class GamePatch
_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))]
private static void GameMain_HandleApplicationQuit_Prefix()
{
@@ -180,7 +220,7 @@ public static class GamePatch
var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle);
if (wnd == IntPtr.Zero) return;
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 y = Mathf.RoundToInt(rect.y);
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;
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 h = Mathf.RoundToInt(rect.w);
width = w;
@@ -213,7 +253,7 @@ public static class GamePatch
var wnd = WinApi.FindWindow(GameWindowClass, _gameWindowTitle);
if (wnd == IntPtr.Zero) return;
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 y = Mathf.RoundToInt(rect.y);
var w = Mathf.RoundToInt(rect.z);

View File

@@ -21,6 +21,11 @@
- Enable game window resize
- Remember window position and size on last exit
- 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
- Sunlight at night
- Remove some build conditions
@@ -117,6 +122,9 @@
- 可调整游戏窗口大小(可最大化和拖动边框)
- 记住上次退出时的窗口位置和大小
- 在加载和平模式存档时将其转换为战斗模式
- 基于mod管理器配置档案名的存档文件夹
- 存档文件会存储在`Save\<ProfileName>`文件夹中
- 如果匹配默认配置档案名则使用原始存档位置
- 将元数据提取的最大数量增加到20000(原来为2000)
- 将玩家指令队列的容量增加到128(原来为16)
+ 行星/工厂

View File

@@ -14,9 +14,6 @@ namespace UXAssist.UI;
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;
protected float MaxY;
protected const float TitleHeight = 48f;
@@ -141,15 +138,10 @@ public class MyWindow : ManualBehaviour
}
t.fontSize = fontSize;
btn.button.onClick.RemoveAllListeners();
btn.tip = null;
btn.tips = new UIButton.TipSettings();
_buttons[btn] = onClick;
if (EventRegistered)
{
if (onClick != null)
btn.button.onClick.AddListener(onClick);
}
btn.button.onClick.RemoveAllListeners();
if (onClick != null) btn.button.onClick.AddListener(onClick);
_maxX = Math.Max(_maxX, x + rect.sizeDelta.x);
MaxY = Math.Max(MaxY, y + rect.sizeDelta.y);
@@ -184,11 +176,7 @@ public class MyWindow : ManualBehaviour
}
btn.button.onClick.RemoveAllListeners();
_buttons[btn] = onClick;
if (EventRegistered && onClick != null)
{
btn.button.onClick.AddListener(onClick);
}
if (onClick != null) btn.button.onClick.AddListener(onClick);
_maxX = Math.Max(_maxX, x + rect.sizeDelta.x);
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);
var rect = Util.NormalizeRectWithTopLeft(inputField, x, y, parent);
rect.sizeDelta = new Vector2(210, rect.sizeDelta.y);
inputField.textComponent.text = text;
inputField.text = text;
inputField.textComponent.fontSize = fontSize;
inputField.onValueChanged.RemoveAllListeners();
if (onChanged != null) inputField.onValueChanged.AddListener(onChanged);
inputField.onEndEdit.RemoveAllListeners();
_inputFields[inputField] = Tuple.Create(onChanged, onEditEnd);
if (EventRegistered)
{
if (onChanged != null)
inputField.onValueChanged.AddListener(onChanged);
if (onEditEnd != null)
inputField.onEndEdit.AddListener(onEditEnd);
}
if (onEditEnd != null) inputField.onEndEdit.AddListener(onEditEnd);
_maxX = Math.Max(_maxX, x + rect.sizeDelta.x);
MaxY = Math.Max(MaxY, y + rect.sizeDelta.y);
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();
if (EventRegistered) return;
foreach (var t in _inputFields)
{
var inputField = t.Key;
if (t.Value.Item1 != null)
inputField.onValueChanged.AddListener(t.Value.Item1);
if (t.Value.Item2 != null)
inputField.onEndEdit.AddListener(t.Value.Item2);
}
var stationWindow = UIRoot.instance.uiGame.stationWindow;
//public InputField nameInput;
var inputField = Instantiate(stationWindow.nameInput);
inputField.gameObject.name = objName;
Destroy(inputField.GetComponent<UIButton>());
inputField.GetComponent<Image>().color = new Color(1f, 1f, 1f, 0.05f);
var rect = Util.NormalizeRectWithTopLeft(inputField, x, y, parent);
rect.sizeDelta = new Vector2(width, rect.sizeDelta.y);
inputField.text = config.Value;
inputField.textComponent.fontSize = fontSize;
foreach (var t in _buttons)
{
var btn = t.Key;
if (t.Value != null)
btn.button.onClick.AddListener(t.Value);
}
inputField.onValueChanged.RemoveAllListeners();
inputField.onEndEdit.RemoveAllListeners();
inputField.onEndEdit.AddListener(value => config.Value = value);
EventRegistered = true;
}
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);
}
_maxX = Math.Max(_maxX, x + rect.sizeDelta.x);
MaxY = Math.Max(MaxY, y + rect.sizeDelta.y);
return inputField;
}
}
@@ -411,10 +371,7 @@ public class MyWindowWithTabs : MyWindow
btn.data = index;
_tabs.Add(Tuple.Create(tabRect, btn));
if (EventRegistered)
{
btn.onClick += OnTabButtonClick;
}
btn.onClick += OnTabButtonClick;
MaxY = Math.Max(MaxY, y + TabHeight);
return tabRect;
@@ -443,32 +400,6 @@ public class MyWindowWithTabs : MyWindow
_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);
private void OnTabButtonClick(int index)
@@ -524,7 +455,7 @@ public static class MyWindowManager
{
var btn = child.GetComponentInChildren<Button>();
//close-btn
if (btn != null)
if (btn)
{
btn.onClick.AddListener(win._Close);
}

View File

@@ -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("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("Night Light", "Sunlight at night", "夜间日光灯");
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)
{
MyCheckBox checkBoxForMeasureTipsPos;
_windowTrans = trans;
wnd.AddTabGroup(trans, "UXAssist", "tab-group-uxassist");
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");
y += 36f;
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");
x = 200f;
y += 6f;
wnd.AddTipsButton2(x, y, tab1, "Better auto-save mechanism", "Better auto-save mechanism tips", "auto-save-opt-tips");
x = 0f;
y += 30f;
*/
y += 36f;
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");
x = 0f;
y = 10f;
@@ -130,16 +149,16 @@ public static class UIConfigWindow
y += 36f;
wnd.AddCheckBox(x, y, tab2, FactoryPatch.OffGridBuildingEnabled, "Off-grid building and stepped rotation");
y += 36f;
var cb = wnd.AddCheckBox(x, y, tab2, FactoryPatch.TreatStackingAsSingleEnabled, "Treat stack items as single in monitor components");
x += cb.Width + 5f;
checkBoxForMeasureTipsPos = wnd.AddCheckBox(x, y, tab2, FactoryPatch.TreatStackingAsSingleEnabled, "Treat stack items as single in monitor components");
x += checkBoxForMeasureTipsPos.Width + 5f;
y += 6f;
wnd.AddTipsButton2(x, y, tab2, "Enhance control for logistic storage limits", "Enhance control for logistic storage limits tips", "enhanced-logistic-limit-tips");
x = 0f;
y += 30f;
wnd.AddCheckBox(x, y, tab2, FactoryPatch.QuickBuildAndDismantleLabsEnabled, "Quick build and dismantle stacking labs");
y += 36f;
cb = wnd.AddCheckBox(x, y, tab2, FactoryPatch.ProtectVeinsFromExhaustionEnabled, "Protect veins from exhaustion");
x += cb.Width + 5f;
checkBoxForMeasureTipsPos = wnd.AddCheckBox(x, y, tab2, FactoryPatch.ProtectVeinsFromExhaustionEnabled, "Protect veins from exhaustion");
x += checkBoxForMeasureTipsPos.Width + 5f;
y += 6f;
wnd.AddTipsButton2(x, y, tab2, "Protect veins from exhaustion", "Protect veins from exhaustion tips", "protect-veins-tips");
x = 0f;
@@ -177,8 +196,8 @@ public static class UIConfigWindow
y += 36f;
wnd.AddCheckBox(x, y, tab2, LogisticsPatch.AllowOverflowInLogisticsEnabled, "Allow overflow for Logistic Stations and Advanced Mining Machines");
y += 36f;
cb = wnd.AddCheckBox(x, y, tab2, LogisticsPatch.LogisticsConstrolPanelImprovementEnabled, "Logistics Control Panel Improvement");
x += cb.Width + 5f;
checkBoxForMeasureTipsPos = wnd.AddCheckBox(x, y, tab2, LogisticsPatch.LogisticsConstrolPanelImprovementEnabled, "Logistics Control Panel Improvement");
x += checkBoxForMeasureTipsPos.Width + 5f;
y += 6f;
wnd.AddTipsButton2(x, y, tab2, "Logistics Control Panel Improvement", "Logistics Control Panel Improvement tips", "lcp-improvement-tips");
// x -= 200f;
@@ -192,8 +211,8 @@ public static class UIConfigWindow
y += 36f;
wnd.AddCheckBox(x, y, tab3, PlayerPatch.HideTipsForSandsChangesEnabled, "Hide tips for soil piles changes");
y += 36f;
cb = wnd.AddCheckBox(x, y, tab3, PlayerPatch.EnhancedMechaForgeCountControlEnabled, "Enhanced count control for hand-make");
x += cb.Width + 5f;
checkBoxForMeasureTipsPos = wnd.AddCheckBox(x, y, tab3, PlayerPatch.EnhancedMechaForgeCountControlEnabled, "Enhanced count control for hand-make");
x += checkBoxForMeasureTipsPos.Width + 5f;
y += 6f;
wnd.AddTipsButton2(x, y, tab3, "Enhanced count control for hand-make", "Enhanced count control for hand-make tips", "enhanced-count-control-tips");
x = 0f;

View File

@@ -67,6 +67,10 @@ public class UXAssist : BaseUnityPlugin, IModCanSave
"Load last window position and size when game starts");
GamePatch.LastWindowRect = Config.Bind("Game", "LastWindowRect", new Vector4(0f, 0f, 0f, 0f),
"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,
"Better auto-save mechanism");