mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2025-12-09 03:33:29 +08:00
UXAssist v1.0.4
This commit is contained in:
@@ -73,4 +73,7 @@ public static class WinApi
|
||||
|
||||
[DllImport("user32", ExactSpelling = true)]
|
||||
public static extern bool SetWindowPos(IntPtr hwnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, int flags);
|
||||
|
||||
[DllImport("user32", ExactSpelling = true)]
|
||||
public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
|
||||
}
|
||||
@@ -15,6 +15,7 @@ public static class FactoryPatch
|
||||
public static ConfigEntry<bool> RemoveBuildRangeLimitEnabled;
|
||||
public static ConfigEntry<bool> LargerAreaForUpgradeAndDismantleEnabled;
|
||||
public static ConfigEntry<bool> LargerAreaForTerraformEnabled;
|
||||
public static ConfigEntry<bool> OffGridBuildingEnabled;
|
||||
|
||||
private static Harmony _factoryPatch;
|
||||
|
||||
@@ -26,12 +27,14 @@ public static class FactoryPatch
|
||||
RemoveBuildRangeLimitEnabled.SettingChanged += (_, _) => RemoveBuildRangeLimit.Enable(RemoveBuildRangeLimitEnabled.Value);
|
||||
LargerAreaForUpgradeAndDismantleEnabled.SettingChanged += (_, _) => LargerAreaForUpgradeAndDismantle.Enable(LargerAreaForUpgradeAndDismantleEnabled.Value);
|
||||
LargerAreaForTerraformEnabled.SettingChanged += (_, _) => LargerAreaForTerraform.Enable(LargerAreaForTerraformEnabled.Value);
|
||||
OffGridBuildingEnabled.SettingChanged += (_, _) => OffGridBuilding.Enable(OffGridBuildingEnabled.Value);
|
||||
UnlimitInteractive.Enable(UnlimitInteractiveEnabled.Value);
|
||||
RemoveSomeConditionBuild.Enable(RemoveSomeConditionEnabled.Value);
|
||||
NightLight.Enable(NightLightEnabled.Value);
|
||||
RemoveBuildRangeLimit.Enable(RemoveBuildRangeLimitEnabled.Value);
|
||||
LargerAreaForUpgradeAndDismantle.Enable(LargerAreaForUpgradeAndDismantleEnabled.Value);
|
||||
LargerAreaForTerraform.Enable(LargerAreaForTerraformEnabled.Value);
|
||||
OffGridBuilding.Enable(OffGridBuildingEnabled.Value);
|
||||
|
||||
_factoryPatch ??= Harmony.CreateAndPatchAll(typeof(FactoryPatch));
|
||||
}
|
||||
@@ -44,6 +47,7 @@ public static class FactoryPatch
|
||||
RemoveBuildRangeLimit.Enable(false);
|
||||
LargerAreaForUpgradeAndDismantle.Enable(false);
|
||||
LargerAreaForTerraform.Enable(false);
|
||||
OffGridBuilding.Enable(false);
|
||||
|
||||
_factoryPatch?.UnpatchSelf();
|
||||
_factoryPatch = null;
|
||||
@@ -519,4 +523,147 @@ public static class FactoryPatch
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
}
|
||||
|
||||
public class OffGridBuilding
|
||||
{
|
||||
private static Harmony _patch;
|
||||
private const float SteppedRotationDegrees = 15f;
|
||||
|
||||
public static void Enable(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(OffGridBuilding));
|
||||
return;
|
||||
}
|
||||
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
}
|
||||
|
||||
private static void MatchIgnoreGridAndCheckIfRotatable(CodeMatcher matcher, out Label? ifBlockEntryLabel, out Label? elseBlockEntryLabel)
|
||||
{
|
||||
Label? thisIfBlockEntryLabel = null;
|
||||
Label? thisElseBlockEntryLabel = null;
|
||||
|
||||
matcher.MatchForward(
|
||||
false
|
||||
, new CodeMatch(ci => ci.Calls(AccessTools.PropertyGetter(typeof(VFInput), nameof(VFInput._ignoreGrid))))
|
||||
, new CodeMatch(ci => ci.Branches(out thisElseBlockEntryLabel))
|
||||
, new CodeMatch(ci => ci.IsLdarg())
|
||||
, new CodeMatch(OpCodes.Ldfld)
|
||||
, new CodeMatch(OpCodes.Ldfld)
|
||||
, new CodeMatch(ci => ci.LoadsConstant(EMinerType.Vein))
|
||||
, new CodeMatch(ci => ci.Branches(out thisIfBlockEntryLabel))
|
||||
, new CodeMatch(ci => ci.IsLdarg())
|
||||
, new CodeMatch(OpCodes.Ldfld)
|
||||
, new CodeMatch(OpCodes.Ldfld)
|
||||
, new CodeMatch(ci => ci.Branches(out _))
|
||||
);
|
||||
|
||||
ifBlockEntryLabel = thisIfBlockEntryLabel;
|
||||
elseBlockEntryLabel = thisElseBlockEntryLabel;
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(BuildTool_Click), nameof(BuildTool_Click.UpdateRaycast))]
|
||||
[HarmonyPatch(typeof(BuildTool_Click), nameof(BuildTool_Click.DeterminePreviews))]
|
||||
public static IEnumerable<CodeInstruction> AllowOffGridConstruction(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
|
||||
MatchIgnoreGridAndCheckIfRotatable(matcher, out var entryLabel, out _);
|
||||
|
||||
if (matcher.IsInvalid)
|
||||
return instructions;
|
||||
|
||||
matcher.Advance(2);
|
||||
matcher.Insert(new CodeInstruction(OpCodes.Br, entryLabel.Value));
|
||||
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
[HarmonyTranspiler]
|
||||
[HarmonyPatch(typeof(BuildTool_Click), nameof(BuildTool_Click.DeterminePreviews))]
|
||||
public static IEnumerable<CodeInstruction> PreventDraggingWhenOffGrid(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
|
||||
Label? exitLabel = null;
|
||||
|
||||
matcher.MatchForward(
|
||||
false
|
||||
, new CodeMatch(ci => ci.Branches(out exitLabel))
|
||||
, new CodeMatch(OpCodes.Ldarg_0)
|
||||
, new CodeMatch(ci => ci.LoadsConstant(1))
|
||||
, new CodeMatch(ci => ci.StoresField(AccessTools.Field(typeof(BuildTool_Click), nameof(BuildTool_Click.isDragging))))
|
||||
);
|
||||
|
||||
if (matcher.IsInvalid)
|
||||
return instructions;
|
||||
|
||||
matcher.Advance(1);
|
||||
matcher.Insert(
|
||||
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(VFInput), nameof(VFInput._ignoreGrid)))
|
||||
, new CodeInstruction(OpCodes.Brtrue, exitLabel)
|
||||
);
|
||||
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
public static IEnumerable<CodeInstruction> PatchToPerformSteppedRotate(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||
{
|
||||
var matcher = new CodeMatcher(instructions, generator);
|
||||
|
||||
MatchIgnoreGridAndCheckIfRotatable(matcher, out var ifBlockEntryLabel, out var elseBlockEntryLabel);
|
||||
|
||||
if (matcher.IsInvalid)
|
||||
return instructions;
|
||||
|
||||
while (!matcher.Labels.Contains(elseBlockEntryLabel.Value))
|
||||
matcher.Advance(1);
|
||||
|
||||
Label? ifBlockExitLabel = null;
|
||||
|
||||
matcher.MatchBack(false, new CodeMatch(ci => ci.Branches(out ifBlockExitLabel)));
|
||||
|
||||
if (matcher.IsInvalid)
|
||||
return instructions;
|
||||
|
||||
while (!matcher.Labels.Contains(ifBlockEntryLabel.Value))
|
||||
matcher.Advance(-1);
|
||||
|
||||
var instructionToClone = matcher.Instruction.Clone();
|
||||
var overwriteWith = CodeInstruction.LoadField(typeof(VFInput), nameof(VFInput.control));
|
||||
|
||||
matcher.SetAndAdvance(overwriteWith.opcode, overwriteWith.operand);
|
||||
matcher.Insert(instructionToClone);
|
||||
matcher.CreateLabel(out var existingEntryLabel);
|
||||
matcher.InsertAndAdvance(
|
||||
new CodeInstruction(OpCodes.Brfalse, existingEntryLabel)
|
||||
, new CodeInstruction(OpCodes.Ldarg_0)
|
||||
, CodeInstruction.Call(typeof(OffGridBuilding), nameof(OffGridBuilding.RotateStepped))
|
||||
, new CodeInstruction(OpCodes.Br, ifBlockExitLabel)
|
||||
);
|
||||
|
||||
return matcher.InstructionEnumeration();
|
||||
}
|
||||
|
||||
public static void RotateStepped(BuildTool_Click instance)
|
||||
{
|
||||
if (VFInput._rotate.onDown)
|
||||
{
|
||||
instance.yaw += SteppedRotationDegrees;
|
||||
instance.yaw = Mathf.Repeat(instance.yaw, 360f);
|
||||
instance.yaw = Mathf.Round(instance.yaw / SteppedRotationDegrees) * SteppedRotationDegrees;
|
||||
}
|
||||
|
||||
if (VFInput._counterRotate.onDown)
|
||||
{
|
||||
instance.yaw -= SteppedRotationDegrees;
|
||||
instance.yaw = Mathf.Repeat(instance.yaw, 360f);
|
||||
instance.yaw = Mathf.Round(instance.yaw / SteppedRotationDegrees) * SteppedRotationDegrees;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,17 +60,31 @@ public static class GamePatch
|
||||
private static class LoadLastWindowRect
|
||||
{
|
||||
private static Harmony _patch;
|
||||
private static bool _loaded;
|
||||
public static void Enable(bool on)
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
_patch ??= Harmony.CreateAndPatchAll(typeof(LoadLastWindowRect));
|
||||
MoveWindowPosition();
|
||||
return;
|
||||
}
|
||||
_patch?.UnpatchSelf();
|
||||
_patch = null;
|
||||
}
|
||||
|
||||
private static void MoveWindowPosition()
|
||||
{
|
||||
if (Screen.fullScreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow || GameMain.isRunning) return;
|
||||
var wnd = WinApi.FindWindow(GameWindowClass, GameWindowTitle);
|
||||
if (wnd == IntPtr.Zero) return;
|
||||
var rect = LastWindowRect.Value;
|
||||
if (rect.z == 0f && rect.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);
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(Screen), nameof(Screen.SetResolution), typeof(int), typeof(int), typeof(FullScreenMode), typeof(int))]
|
||||
private static void Screen_SetResolution_Prefix(ref int width, ref int height, FullScreenMode fullscreenMode)
|
||||
@@ -86,14 +100,26 @@ public static class GamePatch
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(Screen), nameof(Screen.SetResolution), typeof(int), typeof(int), typeof(FullScreenMode), typeof(int))]
|
||||
private static void Screen_SetResolution_Postfix()
|
||||
private static void Screen_SetResolution_Postfix(FullScreenMode fullscreenMode)
|
||||
{
|
||||
MoveWindowPosition();
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(VFPreload), "InvokeOnLoadWorkEnded")]
|
||||
private static void VFPreload_InvokeOnLoadWorkEnded_Postfix()
|
||||
{
|
||||
if (_loaded || Screen.fullScreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow) return;
|
||||
_loaded = true;
|
||||
var wnd = WinApi.FindWindow(GameWindowClass, GameWindowTitle);
|
||||
if (wnd == IntPtr.Zero) return;
|
||||
var rect = LastWindowRect.Value;
|
||||
if (rect.z == 0f && rect.w == 0f) return;
|
||||
var x = Mathf.RoundToInt(rect.x);
|
||||
var y = Mathf.RoundToInt(rect.y);
|
||||
var w = Mathf.RoundToInt(rect.z);
|
||||
var h = Mathf.RoundToInt(rect.w);
|
||||
Screen.SetResolution(w, h, false);
|
||||
WinApi.SetWindowPos(wnd, IntPtr.Zero, x, y, 0, 0, 0x0235);
|
||||
if (EnableWindowResizeEnabled.Value)
|
||||
WinApi.SetWindowLong(wnd, (int)WindowLongFlags.GWL_STYLE,
|
||||
|
||||
@@ -4,11 +4,14 @@
|
||||
#### 一些提升用户体验的功能和补丁
|
||||
|
||||
## Changlog
|
||||
* 1.0.4
|
||||
+ Add new function: `Off-grid building and stepped rotation`
|
||||
+ Fix an issue that window position not restored and can not be resized when function is enabled but game is started with different mod profiles.
|
||||
* 1.0.3
|
||||
+ Add new function: `Quick build Orbital Collectors`.
|
||||
+ Add confirmation popup for `Re-intialize planet`, `Quick dismantle all buildings`, `Re-initialize Dyson Spheres` and `Quick dismantle Dyson Shells`.
|
||||
+ Fix error on `Remove build count and range limit` when building a large amount of belts.
|
||||
+ Fix an issue that windows position not saved correctly when quit game without using in-game menu.
|
||||
+ Fix an issue that window position not saved correctly when quit game without using in-game menu.
|
||||
* 1.0.2
|
||||
+ Redesign config tabs, for clearer layout.
|
||||
+ Add 2 new options:
|
||||
@@ -60,8 +63,12 @@
|
||||
* [Dyson Sphere Program](https://store.steampowered.com/app/1366540): The great game
|
||||
* [Multifunction_mod](https://github.com/blacksnipebiu/Multifunction_mod): Some cheat functions
|
||||
* [LSTM](https://github.com/hetima/DSP_LSTM) & [PlanetFinder](https://github.com/hetima/DSP_PlanetFinder): UI implementations
|
||||
* [OffGridConstruction](https://github.com/Velociraptor115-DSPModding/OffGridConstruction): Off-grid building & stepped rotation implementations
|
||||
|
||||
## 更新日志
|
||||
* 1.0.4
|
||||
+ 添加了新功能:`脱离网格建造和小角度旋转`
|
||||
+ 修复了当功能启用但游戏使用不同的mod配置文件启动时窗口位置无法正确恢复和不可拖动改变大小的问题
|
||||
* 1.0.3
|
||||
+ 添加了新功能:`快速建造轨道采集器`
|
||||
+ 为`初始化行星`,`快速拆除所有建筑`,`初始化戴森球`和`快速拆除戴森壳`添加了确认弹窗
|
||||
@@ -118,3 +125,4 @@
|
||||
* [戴森球计划](https://store.steampowered.com/app/1366540): 伟大的游戏
|
||||
* [BepInEx](https://bepinex.dev/): 基础模组框架
|
||||
* [LSTM](https://github.com/hetima/DSP_LSTM) & [PlanetFinder](https://github.com/hetima/DSP_PlanetFinder): UI实现
|
||||
* [OffGridConstruction](https://github.com/Velociraptor115-DSPModding/OffGridConstruction): 脱离网格建造以及小角度旋转的实现
|
||||
|
||||
@@ -24,6 +24,7 @@ public static class UIConfigWindow
|
||||
I18N.Add("Remove build range limit", "Remove build count and range limit", "移除建造数量和距离限制");
|
||||
I18N.Add("Larger area for upgrade and dismantle", "Larger area for upgrade and dismantle", "范围升级和拆除的最大区域扩大");
|
||||
I18N.Add("Larger area for terraform", "Larger area for terraform", "范围铺设地基的最大区域扩大");
|
||||
I18N.Add("Off-grid building and stepped rotation", "Off-grid building and stepped rotation (Hold Shift)", "脱离网格建造以及小角度旋转(按住Shift)");
|
||||
I18N.Add("Enable player actions in globe view", "Enable player actions in globe view", "在行星视图中允许玩家操作");
|
||||
I18N.Add("Enhanced count control for hand-make", "Enhanced count control for hand-make", "手动制造物品的数量控制改进");
|
||||
I18N.Add("Enhanced count control for hand-make tips", "Maximum count is increased to 1000.\nHold Ctrl/Shift/Alt to change the count rapidly.", "最大数量提升至1000\n按住Ctrl/Shift/Alt可快速改变数量");
|
||||
@@ -74,6 +75,8 @@ public static class UIConfigWindow
|
||||
y += 36f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.LargerAreaForTerraformEnabled, "Larger area for terraform");
|
||||
y += 36f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab2, FactoryPatch.OffGridBuildingEnabled, "Off-grid building and stepped rotation");
|
||||
y += 36f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab2, PlanetPatch.PlayerActionsInGlobeViewEnabled, "Enable player actions in globe view");
|
||||
y += 36f;
|
||||
MyCheckBox.CreateCheckBox(x, y, tab2, PlayerPatch.EnhancedMechaForgeCountControlEnabled, "Enhanced count control for hand-make");
|
||||
|
||||
@@ -45,6 +45,8 @@ public class UXAssist : BaseUnityPlugin
|
||||
"Increase maximum area size for upgrade and dismantle to 31x31 (from 11x11)");
|
||||
FactoryPatch.LargerAreaForTerraformEnabled = Config.Bind("Factory", "LargerAreaForTerraform", false,
|
||||
"Increase maximum area size for terraform to 30x30 (from 10x10)\nNote: this may impact game performance while using large area");
|
||||
FactoryPatch.OffGridBuildingEnabled = Config.Bind("Factory", "OffGridBuilding", false,
|
||||
"Enable off grid building and stepped rotation");
|
||||
PlanetFunctions.OrbitalCollectorMaxBuildCount = Config.Bind("Factory", "OCMaxBuildCount", 0, "Maximum Orbital Collectors to build once, set to 0 to build as many as possible");
|
||||
PlayerPatch.EnhancedMechaForgeCountControlEnabled = Config.Bind("Player", "EnhancedMechaForgeCountControl", false,
|
||||
"Enhanced count control for hand-make, increases maximum of count to 1000, and you can hold Ctrl/Shift/Alt to change the count rapidly");
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<BepInExPluginGuid>org.soardev.uxassist</BepInExPluginGuid>
|
||||
<Description>DSP MOD - UXAssist</Description>
|
||||
<Version>1.0.3</Version>
|
||||
<Version>1.0.4</Version>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<PackageId>UXAssist</PackageId>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "UXAssist",
|
||||
"version_number": "1.0.3",
|
||||
"version_number": "1.0.4",
|
||||
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/UXAssist",
|
||||
"description": "Some functions and patches for better user experience / 一些提升用户体验的功能和补丁",
|
||||
"dependencies": [
|
||||
|
||||
Reference in New Issue
Block a user