mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2025-12-09 01:33:33 +08:00
UXAssist and CheatEnabler new releases
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -86,6 +86,7 @@ public class CheatEnabler : BaseUnityPlugin
|
||||
PlayerFunctions.Init();
|
||||
PlayerPatch.Init();
|
||||
DysonSpherePatch.Init();
|
||||
DysonSphereFunctions.Init();
|
||||
CombatPatch.Init();
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
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
|
||||
+ Quick absorb
|
||||
+ Eject anyway
|
||||
+ Complete Dyson Sphere Shells instantly
|
||||
+ Mecha/Combat:
|
||||
+ Mecha and Drones/Fleets invicible
|
||||
+ Buildings invicible
|
||||
@@ -100,6 +101,7 @@
|
||||
+ 跳过吸收阶段
|
||||
+ 快速吸收
|
||||
+ 全球弹射
|
||||
+ 立即完成戴森壳建造
|
||||
+ 战斗:
|
||||
+ 机甲和战斗无人机无敌
|
||||
+ 建筑无敌
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -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
|
||||
@@ -158,11 +160,13 @@
|
||||
- 在控制面板物流塔列表中右键点击物品图标快速设置为筛选条件
|
||||
+ 新功能:`戴森球自动快速建造速度倍率`
|
||||
- 注意:这仅适用于沙盒模式下的`戴森球自动快速建造`功能
|
||||
+ 新功能:`基于mod管理器配置档案名的存档文件夹`
|
||||
- 存档文件会存储在`Save\<ProfileName>`文件夹中
|
||||
- 如果匹配默认配置档案名则使用原始存档位置
|
||||
+ `快速建造和拆除堆叠研究站`:现在也支持储物仓和储液罐
|
||||
+ `允许调整游戏窗口大小`:在应用游戏选项时保持窗口可调整大小
|
||||
+ `记住上次退出时的窗口位置和大小`:如果分辨率相关的配置项未改变,则在应用游戏选项时不调整窗口大小
|
||||
+ 自动调整面板大小适应内容,以更好地支持多语言和依赖于UX助手配置面板功能的mod
|
||||
+ 修复了在游戏完全加载前打开配置面板可能导致的崩溃问题
|
||||
* 1.1.4
|
||||
+ 修复了`移除部分不影响游戏逻辑的建造条件`
|
||||
* 1.1.3
|
||||
|
||||
@@ -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,14 +85,11 @@ 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)
|
||||
{
|
||||
|
||||
if (count > totalCount)
|
||||
{
|
||||
count = totalCount;
|
||||
@@ -118,6 +115,7 @@ public static class DysonSpherePatch
|
||||
dysonNode.sp += diff;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
// Make compatible with DSPOptimizations
|
||||
if (_totalNodeSpInfo != null)
|
||||
_totalNodeSpInfo.SetValue(dysonSphereLayer, (long)_totalNodeSpInfo.GetValue(dysonSphereLayer) + diff - 1);
|
||||
@@ -151,6 +149,7 @@ public static class DysonSpherePatch
|
||||
dysonFrame.spA += diff;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
// Make compatible with DSPOptimizations
|
||||
if (_totalFrameSpInfo != null)
|
||||
_totalFrameSpInfo.SetValue(dysonSphereLayer, (long)_totalFrameSpInfo.GetValue(dysonSphereLayer) + diff - 1);
|
||||
@@ -176,6 +175,7 @@ public static class DysonSpherePatch
|
||||
dysonFrame.spB += diff;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
// Make compatible with DSPOptimizations
|
||||
if (_totalFrameSpInfo != null)
|
||||
_totalFrameSpInfo.SetValue(dysonSphereLayer, (long)_totalFrameSpInfo.GetValue(dysonSphereLayer) + diff - 1);
|
||||
@@ -184,13 +184,16 @@ public static class DysonSpherePatch
|
||||
|
||||
frameIndex = (frameIndex + 1) % frameCount;
|
||||
}
|
||||
|
||||
dysonNode.frameTurn = frameIndex;
|
||||
}
|
||||
|
||||
if (dysonNode.spOrdered >= dysonNode._spReq)
|
||||
{
|
||||
__instance.RemoveAutoNode(dysonNode);
|
||||
__instance.PickAutoNode();
|
||||
}
|
||||
|
||||
productRegister = __instance.productRegister;
|
||||
if (productRegister != null)
|
||||
{
|
||||
@@ -211,8 +214,6 @@ public static class DysonSpherePatch
|
||||
for (var i = shellCount; i > 0 && count > 0; i--)
|
||||
{
|
||||
var dysonShell = dysonNode.shells[shellIndex];
|
||||
lock (dysonShell)
|
||||
{
|
||||
var nodeIndex = dysonShell.nodeIndexMap[dysonNode.id];
|
||||
var diff = (dysonShell.vertsqOffset[nodeIndex + 1] - dysonShell.vertsqOffset[nodeIndex]) * dysonShell.cpPerVertex - dysonShell.nodecps[nodeIndex];
|
||||
if (diff > count)
|
||||
@@ -227,9 +228,9 @@ public static class DysonSpherePatch
|
||||
_totalCpInfo.SetValue(dysonSphereLayer, (long)_totalCpInfo.GetValue(dysonSphereLayer) + diff);
|
||||
dysonShell.SetMaterialDynamicVars();
|
||||
}
|
||||
}
|
||||
shellIndex = (shellIndex + 1) % shellCount;
|
||||
}
|
||||
|
||||
dysonNode.shellTurn = shellIndex;
|
||||
|
||||
productRegister = __instance.productRegister;
|
||||
@@ -243,7 +244,6 @@ public static class DysonSpherePatch
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -329,6 +329,7 @@ public static class DysonSpherePatch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
+ 行星/工厂
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user