mirror of
https://github.com/soarqin/DSP_Mods.git
synced 2026-05-14 10:47:10 +08:00
Compare commits
188 Commits
78379165e8
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| b7180afff2 | |||
| e5cb52c3f4 | |||
| ca4244384c | |||
| 19629eae97 | |||
| 93e60cd4f0 | |||
| be86aebf7c | |||
| 69b028d706 | |||
| 93c39e2133 | |||
| a894c34987 | |||
| d7f8dc55d4 | |||
| 2e6950afb3 | |||
| a5b2bdedd4 | |||
| a346778db9 | |||
| 109c6afd90 | |||
| e2848b4f97 | |||
| f69a90d452 | |||
| e91271e137 | |||
|
|
524e2b62f0 | ||
|
|
2487a099c1 | ||
|
|
7e9f9ee1ce | ||
| f7fc9aaab0 | |||
| c823e72c67 | |||
| 669ce9f88c | |||
| a9ad961bd3 | |||
| d6b00b1b78 | |||
| ad99b49bad | |||
| 5e501ea649 | |||
| d98d87af48 | |||
| 6ab286bb0b | |||
| 6f33669163 | |||
| 91184ccc3a | |||
| 2e13206346 | |||
| 3e24461ef0 | |||
| 097a5c8e8a | |||
| 63fb13bf92 | |||
| e758209d99 | |||
| a5009496d5 | |||
| 29b30996e6 | |||
| 60d14c9401 | |||
| f0ee1aaea9 | |||
| 358fd4cf23 | |||
| 80aa2f9b70 | |||
| 5914f02d09 | |||
| d9d1e0108f | |||
| 2456280151 | |||
| 0d090ddfb0 | |||
| 39578559aa | |||
| 157c86112b | |||
| d0c20693e3 | |||
| 8ae88f4b41 | |||
| c1428f6aee | |||
| 260e419855 | |||
| 6e0484f035 | |||
| 6e4416389d | |||
| 71c0fe75db | |||
| aa775bd05f | |||
| 9787636d08 | |||
| 256faeee19 | |||
| 78e86aeafe | |||
| 3156f0ffb5 | |||
| 2377f92589 | |||
| 788ed4275e | |||
| ed8d7d61ff | |||
| 6eb9161af1 | |||
| 2201de2b1b | |||
| b537ff22be | |||
| 0049629fd1 | |||
| c339041824 | |||
| 0d7941387f | |||
| f237789fa0 | |||
| b2c04c1dff | |||
| 29ee32b11b | |||
| 3f7c384284 | |||
| 556493b2b6 | |||
| 269cc3b801 | |||
| cacbfd6d5f | |||
| 45445f82a1 | |||
| 1a242af84e | |||
| 1467a6010d | |||
| 6f5b779d58 | |||
| d8fa46d495 | |||
| af3b46be11 | |||
| 96f160926c | |||
| ee812bbc79 | |||
| 052c23d3b7 | |||
| be9de43492 | |||
| 2dbf017a5e | |||
| 3c7744047c | |||
| a9959a2f07 | |||
| 77f5803a24 | |||
| e9bbcf5e2c | |||
| a183485286 | |||
| 5a6cfb18c9 | |||
| 49226001be | |||
| 7c1e88f86d | |||
| 16429936a9 | |||
| d711dd25ef | |||
| e909b6d9d2 | |||
| 2a4008deac | |||
| 6b423225fe | |||
| 9d9a12c1af | |||
| 1d11ba90bd | |||
| a5dc7c5825 | |||
| 73ebcf1aa3 | |||
| dc092d7f6f | |||
| d9f87ca4e9 | |||
| a3c60c32ca | |||
| 96a9e8a570 | |||
| d6a8275938 | |||
| b995503f58 | |||
| a25f74443d | |||
| 5f37b8b6d6 | |||
| 4584895345 | |||
| 5b4633e54c | |||
| 31b1d90d5d | |||
| 8446fba0e4 | |||
| 688b50344c | |||
| 0dd1a11c14 | |||
| f8552d5c34 | |||
| c98c801f27 | |||
| 9bfa74edf2 | |||
| 9d586d68e0 | |||
| a446a17d02 | |||
| 7a7943b001 | |||
| a9dd130f76 | |||
| 0178c8cc2e | |||
| 4e2b4a8e22 | |||
| 4f292bd2d3 | |||
| 2949066712 | |||
| b093a62e36 | |||
| f58bd869fe | |||
| b7abb3a32a | |||
| b79cfbc994 | |||
| c91a873e8d | |||
| 4b632db315 | |||
| 2c4d1b8b0d | |||
| ba095d79f0 | |||
| a9286d2839 | |||
| 17aca89249 | |||
| 4a3bffd927 | |||
| cb3975ae1a | |||
| 4ba1512205 | |||
| c6f1a8bd80 | |||
| dc246170ac | |||
| 23aa8c1f13 | |||
| 944a4d7948 | |||
| f7e1a27be1 | |||
| b6c182168b | |||
| 7d98471dca | |||
| e460b55eb4 | |||
| 177d8b3caf | |||
| 75030c5b23 | |||
| 7bd8abe7e6 | |||
| b51cb326b7 | |||
| f2a849c1af | |||
| c7465133f7 | |||
| ac2cc258ee | |||
| 586ce9a427 | |||
| b060204d80 | |||
| 47cfb4d79a | |||
| fb3a74c7e7 | |||
| 0d5a07b1ac | |||
| 780ad3d3ec | |||
| 40e3206953 | |||
| 167f53e2df | |||
| f407928579 | |||
| 5545d7a2bf | |||
| 2124719de0 | |||
| 8550a354f1 | |||
| f6f28efd88 | |||
| d61b40216c | |||
| 6877b8e9ac | |||
| 950bde3464 | |||
| 8362fcf546 | |||
| b86825c645 | |||
| bb18912155 | |||
| 99b7943d76 | |||
| 5f53c50da0 | |||
| 68a18c113d | |||
| 40aa331294 | |||
| 150868fcea | |||
| fd2aa924ff | |||
| 1ae4aa3ecb | |||
| 996a57130c | |||
| 5c187fb32e | |||
| e765f0f42d | |||
| 65522c6f21 | |||
| 2a3fed7180 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -4,6 +4,9 @@
|
|||||||
# Rider project files
|
# Rider project files
|
||||||
/.idea/
|
/.idea/
|
||||||
|
|
||||||
|
# VS Code project files
|
||||||
|
/.vscode/
|
||||||
|
|
||||||
# C# generated folders
|
# C# generated folders
|
||||||
bin/
|
bin/
|
||||||
obj/
|
obj/
|
||||||
|
|||||||
7
.markdownlint.json
Normal file
7
.markdownlint.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"MD013": false,
|
||||||
|
"MD033": {
|
||||||
|
"allowed_elements": ["details", "summary"]
|
||||||
|
},
|
||||||
|
"MD041": false
|
||||||
|
}
|
||||||
146
AGENTS.md
Normal file
146
AGENTS.md
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
# Agent Guidelines
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
- Update `AGENTS.md` after completing every task.
|
||||||
|
- Do not record a changelog in `AGENTS.md`; modify the document content directly instead.
|
||||||
|
- All documentation and code comments must be written in English.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
This repository is a collection of **BepInEx mods** for the game **Dyson Sphere Program (DSP)**, a factory/automation game on Steam. Each subdirectory is an independent mod plugin loaded by the BepInEx framework at game startup. Mods use **HarmonyLib** to patch the game's compiled C# methods at runtime (prefix, postfix, and transpiler patches).
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
|
||||||
|
- **Language:** C# (`net472` / `netstandard2.1`, latest LangVersion)
|
||||||
|
- **Modding Framework:** BepInEx 5.x
|
||||||
|
- **Patching Library:** HarmonyLib (runtime IL patching via `[HarmonyPatch]` attributes)
|
||||||
|
- **Build System:** Visual Studio solution (`DSP_Mods.sln`), SDK-style `.csproj` per mod
|
||||||
|
- **Package Manager:** NuGet (standard feed + BepInEx dev feed)
|
||||||
|
- **Packaging:** `ZipMod` MSBuild target (explicit, not post-build) produces Thunderstore-ready `.zip` files via `powershell.exe Compress-Archive`
|
||||||
|
- **Game DLL references:** `AssemblyFromGame/Assembly-CSharp.dll` and `UnityEngine.UI.dll`
|
||||||
|
- **Notable dependencies:** DSPModSave, NebulaMultiplayer API, CommonAPI, NLua, obs-websocket-dotnet, Mono.Cecil
|
||||||
|
|
||||||
|
## Repository Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
DSP_Mods/
|
||||||
|
├── DSP_Mods.sln # Visual Studio solution
|
||||||
|
├── AssemblyFromGame/ # Game DLLs used as compile-time references
|
||||||
|
├── UXAssist/ # Core UX mod + shared library (largest mod)
|
||||||
|
├── CheatEnabler/ # Cheat functions mod (depends on UXAssist)
|
||||||
|
├── Dustbin/ # Storage/tank dustbin mod
|
||||||
|
├── DustbinPreloader/ # BepInEx preloader for Dustbin
|
||||||
|
├── HideTips/ # Hides tutorial/tip popups
|
||||||
|
├── LabOpt/ # Lab performance optimizations
|
||||||
|
├── LabOptPreloader/ # BepInEx preloader for LabOpt
|
||||||
|
├── LogisticMiner/ # Logistic stations auto-mine ores
|
||||||
|
├── LuaScriptEngine/ # Lua scripting support for the game
|
||||||
|
├── MechaDronesTweaks/ # Mecha drone speed/energy tweaks
|
||||||
|
├── OverclockEverything/ # Speed/power multipliers for all buildings
|
||||||
|
├── PoolOpt/ # Memory pool optimization on save loading
|
||||||
|
├── UniverseGenTweaks/ # Universe generator parameter tweaks
|
||||||
|
├── UserCloak/ # Hides/fakes Steam account info
|
||||||
|
├── UpdateGameDlls/ # MSBuild helper project; runs UpdateGameDlls.ps1 before any mod compiles
|
||||||
|
└── CompressSave/ # Stub only (moved to external repo)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Mods Summary
|
||||||
|
|
||||||
|
| Mod | GUID | Description |
|
||||||
|
|-----|------|-------------|
|
||||||
|
| **UXAssist** | `org.soardev.uxassist` | Core QoL mod and shared library. Window resize, profile-based saves, FPS control, factory/logistics/navigation/Dyson Sphere tweaks, UI improvements, config panel UI, and `Common/` + `UI/` widget library shared by other mods. |
|
||||||
|
| **CheatEnabler** | `org.soardev.cheatenabler` | Cheat pack (depends on UXAssist). Instant build, architect mode, infinite resources, power boosts, Dyson Sphere cheats, mecha invincibility, and more. |
|
||||||
|
| **LogisticMiner** | — | Makes logistic stations automatically mine ores and water from the current planet. |
|
||||||
|
| **HideTips** | — | Suppresses all tutorial popups, random tips, achievement/milestone cards, and skips the prologue cutscene. |
|
||||||
|
| **MechaDronesTweaks** | — | Configurable drone speed multiplier, skip stage-1 animation, reduce energy consumption. Successor to FastDrones. |
|
||||||
|
| **OverclockEverything** | — | Multiplies speed and power consumption of belts, sorters, assemblers, labs, miners, generators, ejectors, and silos. |
|
||||||
|
| **PoolOpt** | — | Shrinks all object pool arrays to actual used size on save load, then forces GC to reduce memory footprint. |
|
||||||
|
| **UniverseGenTweaks** | — | Adds Epic difficulty, expands max star count to 1024, allows rare veins and flat terrain on birth planet. |
|
||||||
|
| **UserCloak** | — | Prevents Steam leaderboard/achievement uploads; can fake or block Steam user identity. |
|
||||||
|
| **Dustbin** | — | Turns storage boxes and tanks into item-destroying dustbins. Supports Nebula multiplayer and DSPModSave. Requires DustbinPreloader. |
|
||||||
|
| **DustbinPreloader** | — | Mono.Cecil preloader that injects `bool IsDustbin` into `StorageComponent` and `TankComponent` before game load. |
|
||||||
|
| **LabOpt** | — | Optimizes stacked Matrix Lab updates via a `rootLabId` concept. Temporarily marked obsolete. Requires LabOptPreloader. |
|
||||||
|
| **LabOptPreloader** | — | Mono.Cecil preloader that injects `int rootLabId` into `LabComponent` before game load. |
|
||||||
|
| **LuaScriptEngine** | `org.soardev.luascriptengine` | Embeds NLua runtime; loads `.lua` files from `scripts/`; exposes game lifecycle hooks and OBS WebSocket integration. |
|
||||||
|
| **CompressSave** | — | Stub only; functionality moved to external repository `soarqin/DSP_Mods_TO`. |
|
||||||
|
|
||||||
|
## Build System
|
||||||
|
|
||||||
|
### Shared MSBuild Configuration
|
||||||
|
|
||||||
|
Common properties and references are factored into two root-level files that MSBuild automatically imports for every project:
|
||||||
|
|
||||||
|
- **`Directory.Build.props`** — shared `PropertyGroup` defaults (`TargetFramework`, `AllowUnsafeBlocks`, `LangVersion`, `RestoreAdditionalProjectSources`) and shared `ItemGroup`s (BepInEx packages, game DLL references, `Microsoft.NETFramework.ReferenceAssemblies`), and a global `ProjectReference` to the `UpdateGameDlls` helper project (ensuring game DLLs are refreshed before any mod project resolves assembly references).
|
||||||
|
- **`Directory.Build.targets`** — defines the `ZipMod` and `CopyToParentPackage` targets (see below).
|
||||||
|
- **`UpdateGameDlls.ps1`** — PowerShell script invoked by the `UpdateGameDlls` helper project; locates the DSP installation via Steam registry and `libraryfolders.vdf`, compares DLL timestamps, and re-publicizes stale DLLs using `assembly-publicizer`.
|
||||||
|
|
||||||
|
Individual `.csproj` files only declare what is unique to that project (GUID, version, extra packages, embedded resources).
|
||||||
|
|
||||||
|
### Automatic Game DLL Update
|
||||||
|
|
||||||
|
`AssemblyFromGame/` holds publicized copies of two game DLLs used as compile-time references. They are refreshed automatically before any mod project compiles by the `UpdateGameDlls` helper project.
|
||||||
|
|
||||||
|
The helper project (`UpdateGameDlls/UpdateGameDlls.csproj`) uses the `Microsoft.Build.NoTargets` SDK and is declared as a global `ProjectReference` in `Directory.Build.props` with `ReferenceOutputAssembly=false`, `SkipGetTargetFrameworkProperties=true`, and `Private=false`. This ensures that MSBuild's dependency graph guarantees the helper project completes before any mod project resolves assembly references, with no need for file locks or conditional triggers.
|
||||||
|
|
||||||
|
The `UpdateGameDlls.ps1` script:
|
||||||
|
1. Reads the Steam installation path from the Windows registry (`HKCU\Software\Valve\Steam`).
|
||||||
|
2. Parses `steamapps/libraryfolders.vdf` to find the library that contains DSP (AppID `1366540`).
|
||||||
|
3. Locates `<game_root>/DSPGAME_Data/Managed/`.
|
||||||
|
4. For each DLL (`Assembly-CSharp.dll`, `UnityEngine.UI.dll`): if the game copy is newer than the local copy, runs `assembly-publicizer … --strip --overwrite` to regenerate the local file and stamps it with the source timestamp.
|
||||||
|
|
||||||
|
To explicitly update game DLLs:
|
||||||
|
```
|
||||||
|
dotnet build UpdateGameDlls\UpdateGameDlls.csproj
|
||||||
|
```
|
||||||
|
|
||||||
|
**Prerequisite:** `assembly-publicizer` must be installed as a .NET global tool:
|
||||||
|
```
|
||||||
|
dotnet tool install -g BepInEx.AssemblyPublicizer.Cli
|
||||||
|
```
|
||||||
|
If the tool is missing or DSP is not found, the script prints a warning and continues without failing the build.
|
||||||
|
|
||||||
|
### Packaging
|
||||||
|
|
||||||
|
Packaging is a **separate, explicit build target** — it does not run on every normal build.
|
||||||
|
|
||||||
|
To produce a Thunderstore-ready zip:
|
||||||
|
```
|
||||||
|
dotnet build -t:ZipMod -c Release
|
||||||
|
```
|
||||||
|
|
||||||
|
The `ZipMod` target (defined in `Directory.Build.targets`) uses pure MSBuild tasks (`MakeDir`, `Copy`, `Delete`) plus `powershell.exe -NoProfile -Command` for `Compress-Archive`. Calling `powershell.exe` as an explicit executable path works correctly from any shell environment (cmd, PowerShell, bash/WSL).
|
||||||
|
|
||||||
|
> Note: the target is named `ZipMod` rather than `Pack` because `Pack` is a reserved target name in the .NET SDK (used for NuGet packaging) and would be silently intercepted.
|
||||||
|
|
||||||
|
**Per-project packaging properties** (set in the project's `PropertyGroup`):
|
||||||
|
|
||||||
|
| Property | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `PackHasChangelog` | `false` | Include `CHANGELOG.md` in the zip |
|
||||||
|
| `PackUsePluginsLayout` | `false` | Use `plugins/` + `patchers/` folder layout (Dustbin, LabOpt) |
|
||||||
|
| `PackPreloaderTargetDir` | *(empty)* | Preloader projects: destination folder for `CopyToParentPackage` |
|
||||||
|
|
||||||
|
**Preloader projects** (DustbinPreloader, LabOptPreloader) use `CopyToParentPackage` instead of `ZipMod`:
|
||||||
|
```
|
||||||
|
dotnet build -t:CopyToParentPackage -c Release
|
||||||
|
```
|
||||||
|
This copies the preloader DLL into the sibling main mod's `package/patchers/` directory, ready to be zipped by the main mod's `ZipMod` target.
|
||||||
|
|
||||||
|
### Version Management
|
||||||
|
|
||||||
|
Each mod's `<Version>` property in its `.csproj` file is the **single source of truth** for the version number. The `version_number` field in `package/manifest.json` is automatically synchronized from `<Version>` during the `ZipMod` target — no manual update of `manifest.json` is needed.
|
||||||
|
|
||||||
|
**Release workflow:**
|
||||||
|
1. Update `<Version>` in the mod's `.csproj` file (e.g., `<Version>1.2.3</Version>`)
|
||||||
|
2. Run `dotnet build -t:ZipMod -c Release` — `manifest.json` is updated automatically before packaging
|
||||||
|
|
||||||
|
The sync is implemented as an inline PowerShell `Exec` step inside the `ZipMod` target in `Directory.Build.targets`. It uses a regex replace that preserves the original UTF-8 BOM encoding and CRLF line endings of `manifest.json`. Preloader projects (which have no `manifest.json`) are safely skipped via a `Condition="Exists(...)"` guard.
|
||||||
|
|
||||||
|
## Key Architectural Patterns
|
||||||
|
|
||||||
|
- **Shared library:** `UXAssist` acts as a common library. `CheatEnabler` and `UniverseGenTweaks` reference `UXAssist.csproj` directly to reuse `Common/`, `UI/`, and config panel infrastructure.
|
||||||
|
- **Preloader pattern:** `DustbinPreloader` and `LabOptPreloader` use Mono.Cecil to inject new fields into game assemblies at BepInEx preload time, enabling their corresponding main mods to read/write those fields via normal C# without reflection.
|
||||||
|
- **Internationalization:** `UXAssist/Common/I18N.cs` provides bilingual (EN + ZH) string lookup used across UXAssist and CheatEnabler.
|
||||||
|
- **Transpiler patches:** Performance-critical mods (LabOpt, MechaDronesTweaks) use `[HarmonyTranspiler]` to rewrite IL instructions directly for maximum efficiency.
|
||||||
|
- **Save persistence:** Mods that need to persist data use the `IModCanSave` interface from DSPModSave.
|
||||||
BIN
AssemblyFromGame/Assembly-CSharp.dll
Normal file
BIN
AssemblyFromGame/Assembly-CSharp.dll
Normal file
Binary file not shown.
BIN
AssemblyFromGame/UnityEngine.UI.dll
Normal file
BIN
AssemblyFromGame/UnityEngine.UI.dll
Normal file
Binary file not shown.
@@ -1,295 +1,363 @@
|
|||||||
|
<details>
|
||||||
|
<summary>Read me in English</summary>
|
||||||
|
|
||||||
## Changlog
|
## Changlog
|
||||||
|
|
||||||
|
* 2.4.3
|
||||||
|
* `Duplicate shells from that with highest production`: Fix crash on using with frameless shells.
|
||||||
|
* `Keep max production shells and remove others`: Fix wrong behaviour when left count > 1.
|
||||||
|
* `Quick absorb`: Fix ant issue that it is not working while `Skip absorption period` is enabled.
|
||||||
|
* `Finish build immediately`: Fixed an issue where prebuilt buildings were not constructed immediately when the building quantity became sufficient.
|
||||||
|
* New option for `Belt signal item generation`: `Use proliferators for raws/intermediates and finished products`
|
||||||
|
* Following items use extra products: `Titanium Alloy`, `Prism`, `Frame Material`, `Proliferator Mk.II`, `Proliferator Mk.III`, `Magnetic Coil`, `Electric Motor`, `Electromagnetic Turbine`, `Super-magnetic Ring`, `Circuit Board`, `Thruster`, `Reinforced Thruster`, `Plasma Exciter`, `Particle Broadband`, `Graviton Lens`, `Quantum Chip`, `Annihilation Constraint Sphere`, `Deuteron Fuel Rod`, `Space Warper`, `Dyson Sphere Component`, `Small Carrier Rocket`, `Electromagnetic Matrix`, `Structure Matrix`, `Information Matrix`, `Gravity Matrix`, `Universe Matrix`
|
||||||
|
* Following items does not use proliferators: `Casimir Crystal`, `Energy Matrix`
|
||||||
|
* Other items use speed up production.
|
||||||
|
* Fix some other minor bugs found by LLM AI.
|
||||||
|
* 2.4.2
|
||||||
|
* Fix critical bugs:
|
||||||
|
* Dyson Power is not updated actively when `Skip bullet period` or `Skip absorption period` is enabled and no rocket is in fire.
|
||||||
|
* Dyson Power is not updated actively on clicking `Complete Dyson Sphere Shells instantly` or `Remove all frames on Dyson Sphere`.
|
||||||
|
* 2.4.1
|
||||||
|
* New feature: `Remove all frames on Dyson Sphere`
|
||||||
|
* Can save rockets with very little power generation impact.
|
||||||
|
* Will keep nodes and shells and does not affect solar sails' absorption.
|
||||||
|
* `Terraform without enough soil piles`: Working for blueprint paste and burying Dark Fog Core Driller now.
|
||||||
|
* `Belt signal item generation`: Fix mod compatibility by resolving recursive recipes.
|
||||||
|
* 2.4.0
|
||||||
|
* Support game version 0.10.33
|
||||||
|
* `Generate illegal dyson shell`: This function is open to all users now, enabling certain config entry is not needed any more.
|
||||||
|
* 2.3.32
|
||||||
|
* `Complete Dyson Sphere Shells instantly`: Fix a crash.
|
||||||
|
* 2.3.31
|
||||||
|
* New feature: `Unlock Dyson Sphere max orbit radius`
|
||||||
|
* `Remove metadata consumption record in current game`: Fix implementation
|
||||||
|
* Add 3 buttons for creating illegal Dyson Sphere Shells, you must enable `IllegalDysonShellFunctionsEnabled` of `DysonSphere` section in config to see them.
|
||||||
|
* `Generate an illegal dyson shell`
|
||||||
|
* `Keep max production shells and remove others`
|
||||||
|
* `Duplicate shells from that with highest production`
|
||||||
|
* 2.3.30
|
||||||
|
* Fix a warning issue while `No condition build` or `No collision` is enabled.
|
||||||
|
* Increase performance for `Finish build immediately` greatly on pasting large blueprints.
|
||||||
* 2.3.29
|
* 2.3.29
|
||||||
+ Fix compatibility with game update 0.10.32.25779
|
* Fix compatibility with game update 0.10.32.25779
|
||||||
* 2.3.28
|
* 2.3.28
|
||||||
+ New feature: `Instant hand-craft`.
|
* New feature: `Instant hand-craft`.
|
||||||
+ Fix some panels' display while `Infinite Natural Resources` is enabled.
|
* Fix some panels' display while `Infinite Natural Resources` is enabled.
|
||||||
* 2.3.27
|
* 2.3.27
|
||||||
+ `Skip bullet period` & `Eject anyway`: Fix compatibility with `Dyson Sphere Program v0.10.32.25496`.
|
* `Skip bullet period` & `Eject anyway`: Fix compatibility with `Dyson Sphere Program v0.10.32.25496`.
|
||||||
* 2.3.26
|
* 2.3.26
|
||||||
+ Refactor codes to adapt to UXAssist 1.2.0
|
* Refactor codes to adapt to UXAssist 1.2.0
|
||||||
- You should update UXAssist to 1.2.0 or later before using this version.
|
* You should update UXAssist to 1.2.0 or later before using this version.
|
||||||
+ `Complete Dyson Sphere Shells instantly`: Fix possible wrong production records.
|
* `Complete Dyson Sphere Shells instantly`: Fix possible wrong production records.
|
||||||
* 2.3.25
|
* 2.3.25
|
||||||
+ New feature: `Enable warp without space warpers`
|
* New feature: `Enable warp without space warpers`
|
||||||
+ New feature: `Wind Turbines do global power coverage`
|
* New feature: `Wind Turbines do global power coverage`
|
||||||
+ Fix an issue that `Complete Dyson Sphere Shells instantly` does not generate production records for solar sails.
|
* Fix an issue that `Complete Dyson Sphere Shells instantly` does not generate production records for solar sails.
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Older versions</summary>
|
|
||||||
|
|
||||||
* 2.3.24
|
* 2.3.24
|
||||||
+ `Complete Dyson Sphere Shells instantly`: Fix a bug that may cause negative power in some cases
|
* `Complete Dyson Sphere Shells instantly`: Fix a bug that may cause negative power in some cases
|
||||||
* 2.3.23
|
* 2.3.23
|
||||||
+ New feature: `Complete Dyson Sphere Shells instantly`
|
* New feature: `Complete Dyson Sphere Shells instantly`
|
||||||
+ Fix a crash when config panel is opened before game is fully loaded
|
* 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
|
||||||
+ `Retrieve/Place items from/to remote planets on logistics control panel`: Items are put back to player's inventory when a slot is removed from the logistics station on remote planet.
|
* `Retrieve/Place items from/to remote planets on logistics control panel`: Items are put back to player's inventory when a slot is removed from the logistics station on remote planet.
|
||||||
+ `Dev Shortcuts`: Camera Pose related shortcurts are working now.
|
* `Dev Shortcuts`: Camera Pose related shortcurts are working now.
|
||||||
* 2.3.20
|
* 2.3.20
|
||||||
+ New feature: `Retrieve/Place items from/to remote planets on logistics control panel`
|
* New feature: `Retrieve/Place items from/to remote planets on logistics control panel`
|
||||||
* 2.3.19
|
* 2.3.19
|
||||||
+ New features:
|
* New features:
|
||||||
+ `Remove all metadata consumption records`
|
* `Remove all metadata consumption records`
|
||||||
+ `Remove metadata consumption record in current game`
|
* `Remove metadata consumption record in current game`
|
||||||
+ `Clear metadata flag which bans achievements`
|
* `Clear metadata flag which bans achievements`
|
||||||
* 2.3.18
|
* 2.3.18
|
||||||
+ New features:
|
* New features:
|
||||||
+ `Teleport to outer space`, this will teleport you to the outer space which is 50 LYs far from the farthest star.
|
* `Teleport to outer space`, this will teleport you to the outer space which is 50 LYs far from the farthest star.
|
||||||
+ `Teleport to selected astronomical`
|
* `Teleport to selected astronomical`
|
||||||
+ Fix logic of `Unlock techs with key-modifiers`.
|
* Fix logic of `Unlock techs with key-modifiers`.
|
||||||
+ `No condition build` does not hide rotation info of belts now.
|
* `No condition build` does not hide rotation info of belts now.
|
||||||
* 2.3.17
|
* 2.3.17
|
||||||
+ Make compatible with game version 0.10.30.23292
|
* Make compatible with game version 0.10.30.23292
|
||||||
* 2.3.16
|
* 2.3.16
|
||||||
+ Add 2 options to `Belt signal item generation`:
|
* Add 2 options to `Belt signal item generation`:
|
||||||
- `Count generations as production in statistics`
|
* `Count generations as production in statistics`
|
||||||
- `Count removals as consumption in statistics`
|
* `Count removals as consumption in statistics`
|
||||||
+ New feature: `Increase maximum power usage in Logistic Stations and Advanced Mining Machines`
|
* New feature: `Increase maximum power usage in Logistic Stations and Advanced Mining Machines`
|
||||||
- Logistic Stations: Increased max charging power to 3GW(ILS) and 600MW(PLS) (10x of original)
|
* Logistic Stations: Increased max charging power to 3GW(ILS) and 600MW(PLS) (10x of original)
|
||||||
- Advanced Mining Machines: Increased max mining speed to 1000%
|
* Advanced Mining Machines: Increased max mining speed to 1000%
|
||||||
* 2.3.15
|
* 2.3.15
|
||||||
+ New features:
|
* New features:
|
||||||
- `Instant teleport (like that in Sandbox mode)`
|
* `Instant teleport (like that in Sandbox mode)`
|
||||||
- `Mecha and Drones/Fleets invicible`
|
* `Mecha and Drones/Fleets invicible`
|
||||||
- `Buildings invicible`
|
* `Buildings invicible`
|
||||||
* 2.3.14
|
* 2.3.14
|
||||||
+ Remove default shortcut key for `No condition build` and `No collision`, to avoid misoperation. You can still set them in system settings window manually if needed.
|
* Remove default shortcut key for `No condition build` and `No collision`, to avoid misoperation. You can still set them in system settings window manually if needed.
|
||||||
+ Fix translation issue.
|
* Fix translation issue.
|
||||||
* 2.3.13
|
* 2.3.13
|
||||||
+ Fix a bug that shortcuts are not working and have display issue on settings window.
|
* Fix a bug that shortcuts are not working and have display issue on settings window.
|
||||||
* 2.3.12
|
* 2.3.12
|
||||||
+ Add a shortcut to toggle `No collision`, you can modify the shortcut on system settings window.
|
* Add a shortcut to toggle `No collision`, you can modify the shortcut on system settings window.
|
||||||
+ Add realtime tips when toggling `No condition build` and `No collision` with shortcuts.
|
* Add realtime tips when toggling `No condition build` and `No collision` with shortcuts.
|
||||||
* 2.3.11
|
* 2.3.11
|
||||||
+ Add a shortcut to toggle `No condition build`, you can modify the shortcut on system settings window. This depends on [UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist) 1.0.15 or later.
|
* Add a shortcut to toggle `No condition build`, you can modify the shortcut on system settings window. This depends on [UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist) 1.0.15 or later.
|
||||||
* 2.3.10
|
* 2.3.10
|
||||||
+ Fix following functions not working in new game updates:
|
* Fix following functions not working in new game updates:
|
||||||
- `Pump Anywhere`
|
* `Pump Anywhere`
|
||||||
- `Terraform without enough soil piles`
|
* `Terraform without enough soil piles`
|
||||||
* 2.3.9
|
* 2.3.9
|
||||||
+ Support game version 0.10.28.21219
|
* Support game version 0.10.28.21219
|
||||||
* 2.3.8
|
* 2.3.8
|
||||||
+ Fix a crash on starting new games while `Finish build immediately` is enabled.
|
* Fix a crash on starting new games while `Finish build immediately` is enabled.
|
||||||
+ Fix UI button width.
|
* Fix UI button width.
|
||||||
* 2.3.7
|
* 2.3.7
|
||||||
+ Support game version 0.10.28.20759
|
* Support game version 0.10.28.20759
|
||||||
+ Fix belt signal that items' generation speed is not fit to number set sometimes.
|
* Fix belt signal that items' generation speed is not fit to number set sometimes.
|
||||||
* 2.3.6
|
* 2.3.6
|
||||||
+ Support for UXAssist's new function within `Finish build immediately`.
|
* Support for UXAssist's new function within `Finish build immediately`.
|
||||||
+ Add a warning message when `Build without condition` is enabled.
|
* Add a warning message when `Build without condition` is enabled.
|
||||||
+ Fix an issue in `Finish build immediately` that some buildings are not finished immediately.
|
* Fix an issue in `Finish build immediately` that some buildings are not finished immediately.
|
||||||
* 2.3.5
|
* 2.3.5
|
||||||
+ Fix another crash in `Skip bullet period`.
|
* Fix another crash in `Skip bullet period`.
|
||||||
* 2.3.4
|
* 2.3.4
|
||||||
+ Use new tab layout of UXAssist 1.0.2
|
* Use new tab layout of UXAssist 1.0.2
|
||||||
+ Minor bug fixes
|
* Minor bug fixes
|
||||||
* 2.3.3
|
* 2.3.3
|
||||||
+ Fix a crash in `Skip bullet period`.
|
* Fix a crash in `Skip bullet period`.
|
||||||
+ Unlock techs with Alt unlocks VeinUtil to 10000 instead of 7200 now, as bug fixed in UXAssist.
|
* Unlock techs with Alt unlocks VeinUtil to 10000 instead of 7200 now, as bug fixed in UXAssist.
|
||||||
* 2.3.2
|
* 2.3.2
|
||||||
+ Birth star options moved to [UniverseGenTweaks](https://dsp.thunderstore.io/package/soarqin/UniverseGenTweaks/)
|
* Birth star options moved to [UniverseGenTweaks](https://dsp.thunderstore.io/package/soarqin/UniverseGenTweaks/)
|
||||||
+ Optimize `Quick absorb`, consumes less CPU time and take turns firing to nodes.
|
* Optimize `Quick absorb`, consumes less CPU time and take turns firing to nodes.
|
||||||
+ `Fast Mining` ensures full output of oil extractors now.
|
* `Fast Mining` ensures full output of oil extractors now.
|
||||||
+ Fix issue that `Belt signal generator` not working after switched off then on again.
|
* Fix issue that `Belt signal generator` not working after switched off then on again.
|
||||||
+ Fix absorption issue by `Quick absorb` and `Skip bullet period` enabled at the same time.
|
* Fix absorption issue by `Quick absorb` and `Skip bullet period` enabled at the same time.
|
||||||
+ Crash fix for some options
|
* Crash fix for some options
|
||||||
* 2.3.1
|
* 2.3.1
|
||||||
+ Add UXAssist to dependencies in manifest.
|
* Add UXAssist to dependencies in manifest.
|
||||||
* 2.3.0
|
* 2.3.0
|
||||||
+ Move some functions to an individual mod: [UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist)
|
* Move some functions to an individual mod: [UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist)
|
||||||
+ Depends on [UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist) now, so that config panel is unified with UXAssist.
|
* Depends on [UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist) now, so that config panel is unified with UXAssist.
|
||||||
+ Remove `LCtrl+A` from Dev Shortcuts, to avoid misoperation.
|
* Remove `LCtrl+A` from Dev Shortcuts, to avoid misoperation.
|
||||||
+ Infinite bots/drones/vessels in `Architect mode` now.
|
* Infinite bots/drones/vessels in `Architect mode` now.
|
||||||
* 2.2.7
|
* 2.2.7
|
||||||
+ New function: `Construct only nodes but frames`
|
* New function: `Construct only nodes but frames`
|
||||||
+ Opening config panel does not close inventory panel now
|
* Opening config panel does not close inventory panel now
|
||||||
+ Remove `Input direction conflict` check while using `Remove some build conditions`
|
* Remove `Input direction conflict` check while using `Remove some build conditions`
|
||||||
+ Fix a bug that prevents `Belt signal alt format` from switching number formats for current belt signals
|
* Fix a bug that prevents `Belt signal alt format` from switching number formats for current belt signals
|
||||||
* 2.2.6
|
* 2.2.6
|
||||||
+ New function: `Stop ejectors when available nodes are all filled up`
|
* New function: `Stop ejectors when available nodes are all filled up`
|
||||||
+ Fix a bug that absorb solar sails on unfinised nodes
|
* Fix a bug that absorb solar sails on unfinised nodes
|
||||||
* 2.2.5
|
* 2.2.5
|
||||||
+ Skip all intermediate states and absorb solar sails instantly while enable `Quick absorb`, `Skip bullet period` and `Skip absorption period` at the same time.
|
* Skip all intermediate states and absorb solar sails instantly while enable `Quick absorb`, `Skip bullet period` and `Skip absorption period` at the same time.
|
||||||
+ Fix a problem that `Quick absorb` does not absorb all solar sails instantly when most nodes are full.
|
* Fix a problem that `Quick absorb` does not absorb all solar sails instantly when most nodes are full.
|
||||||
+ Fix crash while using with some mods
|
* Fix crash while using with some mods
|
||||||
* 2.2.4
|
* 2.2.4
|
||||||
+ New function: `Enable player actions in globe view`
|
* New function: `Enable player actions in globe view`
|
||||||
+ Fix UI bug
|
* Fix UI bug
|
||||||
* 2.2.3
|
* 2.2.3
|
||||||
+ New function: `Remove some build conditions`
|
* New function: `Remove some build conditions`
|
||||||
+ Fix compatibility with some mods
|
* Fix compatibility with some mods
|
||||||
* 2.2.2
|
* 2.2.2
|
||||||
+ New function: `Assign gamesave to currrnet account`
|
* New function: `Assign gamesave to currrnet account`
|
||||||
+ New subfunction: `Belt signal alt format`
|
* New subfunction: `Belt signal alt format`
|
||||||
+ Fix a crash on using `Initialize this Planet`
|
* Fix a crash on using `Initialize this Planet`
|
||||||
+ Fix belt build in `Finish build immediately`
|
* Fix belt build in `Finish build immediately`
|
||||||
* 2.2.1
|
* 2.2.1
|
||||||
+ Check condition for miners even when `Build without condition` is enabled.
|
* Check condition for miners even when `Build without condition` is enabled.
|
||||||
+ Fix a patch issue that may cause `Build without condition` not working.
|
* Fix a patch issue that may cause `Build without condition` not working.
|
||||||
* 2.2.0
|
* 2.2.0
|
||||||
+ Add some power related functions
|
* Add some power related functions
|
||||||
+ Add a subfunction to belt signal item generation, which simulates production process of raws and intermediates on statistics
|
* Add a subfunction to belt signal item generation, which simulates production process of raws and intermediates on statistics
|
||||||
+ Split some functions from Architect mode
|
* Split some functions from Architect mode
|
||||||
* 2.1.0
|
* 2.1.0
|
||||||
+ Belt signal item generation
|
* Belt signal item generation
|
||||||
+ Fix window display priority which may cause tips to be covered by main window
|
* Fix window display priority which may cause tips to be covered by main window
|
||||||
* 2.0.0
|
* 2.0.0
|
||||||
+ Refactorying codes
|
* Refactorying codes
|
||||||
+ UI implementation
|
* UI implementation
|
||||||
+ Add a lot of functions
|
* Add a lot of functions
|
||||||
* 1.0.0
|
* 1.0.0
|
||||||
+ Initial release
|
* Initial release
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>中文读我</summary>
|
||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
|
* 2.4.3
|
||||||
|
* `从发电量最高的壳复制戴森壳`:修复在无框壳体时可能崩溃的问题。
|
||||||
|
* `保留发电量最高的戴森壳并移除其他戴森壳`:修复当剩余壳体数量大于1时的异常行为。
|
||||||
|
* `快速吸收`:修复开启`跳过吸收阶段`时不生效的问题。
|
||||||
|
* `立即完成建造`:修复建筑数量补足时,之前预建造状态的建筑未能立即完成的问题。
|
||||||
|
* `传送带信号物品生成`新增选项:`原料/中间品和成品使用增产剂`
|
||||||
|
* 以下物品会使用额外产出:`钛合金`、`棱镜`、`框架材料`、`增产剂 Mk.II`、`增产剂 Mk.III`、`磁线圈`、`电动机`、`电磁涡轮`、`超级磁场环`、`电路板`、`推进器`、`加力推进器`、`电浆激发器`、`粒子宽带`、`引力透镜`、`量子芯片`、`湮灭约束球`、`氘燃料棒`、`空间翘曲器`、`戴森球组件`、`小型运载火箭`、`电磁矩阵`、`结构矩阵`、`信息矩阵`、`引力矩阵`、`宇宙矩阵`
|
||||||
|
* 以下物品不使用增产剂:`卡西米尔晶体`、`能量矩阵`
|
||||||
|
* 其他物品使用加速生产
|
||||||
|
* 修复一些由 LLM AI 发现的其他小问题。
|
||||||
|
* 2.4.2
|
||||||
|
* 修复了严重的系列BUG:
|
||||||
|
* 在启用`跳过子弹阶段`或`跳过吸收阶段`并且没有火箭发射时,戴森球的发电量未实时更新
|
||||||
|
* 点击`立即完成戴森壳建造`或`移除戴森球上的所有框架`时,戴森球的发电量未实时更新
|
||||||
|
* 2.4.1
|
||||||
|
* 新增功能:`移除戴森球上的所有框架`
|
||||||
|
* 可以节省火箭,且几乎不影响发电效率
|
||||||
|
* 会保留节点和壳面,不影响太阳帆的吸收
|
||||||
|
* `沙土不够时依然可以整改地形`:现在支持蓝图粘贴和掩埋黑雾核心钻机
|
||||||
|
* `传送带信号物品生成`:修复对递归配方的支持,兼容一些mod
|
||||||
|
* 2.4.0
|
||||||
|
* 支持游戏版本 0.10.33
|
||||||
|
* `生成仙术戴森壳`:此功能现在对所有用户开放,不再需要启用特定的配置项。
|
||||||
|
* 2.3.32
|
||||||
|
* `立即完成戴森壳建造`:修复了一个崩溃问题
|
||||||
|
* 2.3.31
|
||||||
|
* 新功能:`解锁戴森球最大轨道半径`
|
||||||
|
* `移除当前存档的元数据消耗记录`:修复实现
|
||||||
|
* 增加了3个用于制作仙术戴森壳的按钮,你必须在设置文件里开启`DysonSphere`分类的`IllegalDysonShellFunctionsEnabled`才能看到它们
|
||||||
|
* `生成单层仙术戴森壳`
|
||||||
|
* `保留发电量最高的戴森壳并移除其他戴森壳`
|
||||||
|
* `从发电量最高的壳复制戴森壳`
|
||||||
|
* 2.3.30
|
||||||
|
* 修复了启用`无条件建造`或`无碰撞`时的警告问题
|
||||||
|
* 粘贴大规模蓝图时大幅提升`立即完成建造`的性能表现
|
||||||
* 2.3.29
|
* 2.3.29
|
||||||
+ 修复了与游戏更新0.10.32.25779的兼容性
|
* 修复了与游戏更新0.10.32.25779的兼容性
|
||||||
* 2.3.28
|
* 2.3.28
|
||||||
+ 新功能:`快速手动制造`
|
* 新功能:`快速手动制造`
|
||||||
+ 修复了启用`自然资源采集不消耗`时部分面板的显示问题
|
* 修复了启用`自然资源采集不消耗`时部分面板的显示问题
|
||||||
* 2.3.27
|
* 2.3.27
|
||||||
+ `跳过子弹阶段`和`全球弹射`:修复了与`戴森球计划 v0.10.32.25496`的兼容性
|
* `跳过子弹阶段`和`全球弹射`:修复了与`戴森球计划 v0.10.32.25496`的兼容性
|
||||||
* 2.3.26
|
* 2.3.26
|
||||||
+ 重构代码以适应UXAssist 1.2.0
|
* 重构代码以适应UXAssist 1.2.0
|
||||||
- 在使用此版本之前,您应先更新UXAssist到1.2.0或更高版本。
|
* 在使用此版本之前,您应先更新UXAssist到1.2.0或更高版本。
|
||||||
+ `立即完成戴森壳建造`:修复了可能导致错误的生产记录的问题
|
* `立即完成戴森壳建造`:修复了可能导致错误的生产记录的问题
|
||||||
* 2.3.25
|
* 2.3.25
|
||||||
+ 新功能:`无需空间翘曲器即可曲速飞行`
|
* 新功能:`无需空间翘曲器即可曲速飞行`
|
||||||
+ 新功能:`风力涡轮机供电覆盖全球`
|
* 新功能:`风力涡轮机供电覆盖全球`
|
||||||
+ 修复了`立即完成戴森壳建造`未生成太阳帆生产记录的问题
|
* 修复了`立即完成戴森壳建造`未生成太阳帆生产记录的问题
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>更早的版本</summary>
|
|
||||||
|
|
||||||
* 2.3.24
|
* 2.3.24
|
||||||
+ `立即完成戴森壳建造`:修复了在某些情况下可能导致发电为负的问题
|
* `立即完成戴森壳建造`:修复了在某些情况下可能导致发电为负的问题
|
||||||
* 2.3.23
|
* 2.3.23
|
||||||
+ 新功能:`立即完成戴森壳建造`
|
* 新功能:`立即完成戴森壳建造`
|
||||||
+ 修复了在游戏完全加载前打开配置面板可能导致的崩溃问题
|
* 修复了在游戏完全加载前打开配置面板可能导致的崩溃问题
|
||||||
* 2.3.22
|
* 2.3.22
|
||||||
+ 修复了`平地抽水`
|
* 修复了`平地抽水`
|
||||||
* 2.3.21
|
* 2.3.21
|
||||||
+ `在物流总控面板上可以从非本地行星取放物品`:当从非本地星球的物流站移除槽位时,物品会放回玩家的背包
|
* `在物流总控面板上可以从非本地行星取放物品`:当从非本地星球的物流站移除槽位时,物品会放回玩家的背包
|
||||||
+ `开发模式快捷键`:摄像机位(Pose)相关的快捷键现在生效了
|
* `开发模式快捷键`:摄像机位(Pose)相关的快捷键现在生效了
|
||||||
* 2.3.20
|
* 2.3.20
|
||||||
+ 新功能:`在物流总控面板上可以从非本地行星取放物品`
|
* 新功能:`在物流总控面板上可以从非本地行星取放物品`
|
||||||
* 2.3.19
|
* 2.3.19
|
||||||
+ 新功能:
|
* 新功能:
|
||||||
+ `移除所有元数据消耗记录`
|
* `移除所有元数据消耗记录`
|
||||||
+ `移除当前存档的元数据消耗记录`
|
* `移除当前存档的元数据消耗记录`
|
||||||
+ `解除当前存档因使用元数据导致的成就限制`
|
* `解除当前存档因使用元数据导致的成就限制`
|
||||||
* 2.3.18
|
* 2.3.18
|
||||||
+ 新功能:
|
* 新功能:
|
||||||
+ `传送到外太空`,这会将你传送到距离最远星球50光年的外太空
|
* `传送到外太空`,这会将你传送到距离最远星球50光年的外太空
|
||||||
+ `传送到选中天体`
|
* `传送到选中天体`
|
||||||
+ 修复了`组合键解锁科技`的逻辑
|
* 修复了`组合键解锁科技`的逻辑
|
||||||
+ `无条件建造`现在不会隐藏传送带的旋转信息了
|
* `无条件建造`现在不会隐藏传送带的旋转信息了
|
||||||
* 2.3.17
|
* 2.3.17
|
||||||
+ 适配游戏版本0.10.30.23292
|
* 适配游戏版本0.10.30.23292
|
||||||
* 2.3.16
|
* 2.3.16
|
||||||
+ 为`传送带信号物品生成`添加了两个选项:
|
* 为`传送带信号物品生成`添加了两个选项:
|
||||||
- `统计信息里将生成计算为产物`
|
* `统计信息里将生成计算为产物`
|
||||||
- `统计信息里将移除计算为消耗`
|
* `统计信息里将移除计算为消耗`
|
||||||
+ 新功能:`提升物流塔和大型采矿机的最大功耗`
|
* 新功能:`提升物流塔和大型采矿机的最大功耗`
|
||||||
- 物流塔:将最大充电功率提高到3GW(星际物流塔)和600MW(行星物流塔)(原来的10倍)
|
* 物流塔:将最大充电功率提高到3GW(星际物流塔)和600MW(行星物流塔)(原来的10倍)
|
||||||
- 大型采矿机:将最大采矿速度提高到1000%
|
* 大型采矿机:将最大采矿速度提高到1000%
|
||||||
* 2.3.15
|
* 2.3.15
|
||||||
+ 新功能:
|
* 新功能:
|
||||||
- `快速传送(和沙盒模式一样)`
|
* `快速传送(和沙盒模式一样)`
|
||||||
- `机甲和战斗无人机无敌`
|
* `机甲和战斗无人机无敌`
|
||||||
- `建筑无敌`
|
* `建筑无敌`
|
||||||
* 2.3.14
|
* 2.3.14
|
||||||
+ 移除了`无条件建造`和`无碰撞`的默认快捷键,以避免误操作。如有需要请手动在系统选项窗口中设置。
|
* 移除了`无条件建造`和`无碰撞`的默认快捷键,以避免误操作。如有需要请手动在系统选项窗口中设置。
|
||||||
+ 修复了翻译问题。
|
* 修复了翻译问题。
|
||||||
* 2.3.13
|
* 2.3.13
|
||||||
+ 修复了快捷键无效和设置窗口上的按键显示问题
|
* 修复了快捷键无效和设置窗口上的按键显示问题
|
||||||
* 2.3.12
|
* 2.3.12
|
||||||
+ 添加了一个快捷键来切换`无碰撞`,你可以在系统设置面板中修改快捷键。
|
* 添加了一个快捷键来切换`无碰撞`,你可以在系统设置面板中修改快捷键。
|
||||||
+ 在使用快捷键切换`无条件建造`和`无碰撞`时添加了实时提示信息。
|
* 在使用快捷键切换`无条件建造`和`无碰撞`时添加了实时提示信息。
|
||||||
* 2.3.11
|
* 2.3.11
|
||||||
+ 添加了一个快捷键来切换`无条件建造`,你可以在系统设置面板中修改快捷键。这依赖于[UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist) 1.0.15或更高版本
|
* 添加了一个快捷键来切换`无条件建造`,你可以在系统设置面板中修改快捷键。这依赖于[UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist) 1.0.15或更高版本
|
||||||
* 2.3.10
|
* 2.3.10
|
||||||
+ 修复了以下功能在新游戏版本中不生效的问题:
|
* 修复了以下功能在新游戏版本中不生效的问题:
|
||||||
- `平地抽水`
|
* `平地抽水`
|
||||||
- `沙土不够时依然可以整改地形`
|
* `沙土不够时依然可以整改地形`
|
||||||
* 2.3.9
|
* 2.3.9
|
||||||
+ 支持游戏版本0.10.28.21219
|
* 支持游戏版本0.10.28.21219
|
||||||
* 2.3.8
|
* 2.3.8
|
||||||
+ 修复了启用`建造秒完成`时开新游戏可能导致崩溃的问题
|
* 修复了启用`建造秒完成`时开新游戏可能导致崩溃的问题
|
||||||
+ 修复了UI按钮宽度
|
* 修复了UI按钮宽度
|
||||||
* 2.3.7
|
* 2.3.7
|
||||||
+ 支持游戏版本0.10.28.20759
|
* 支持游戏版本0.10.28.20759
|
||||||
+ 修复了传送带信号有时候物品生成速度和设置不匹配的问题
|
* 修复了传送带信号有时候物品生成速度和设置不匹配的问题
|
||||||
* 2.3.6
|
* 2.3.6
|
||||||
+ 在`建造秒完成`中支持UXAssist的新功能
|
* 在`建造秒完成`中支持UXAssist的新功能
|
||||||
+ 在启用`无条件建造`时添加警告信息
|
* 在启用`无条件建造`时添加警告信息
|
||||||
+ 修复了`建造秒完成`可能导致部分建筑无法立即完成的问题
|
* 修复了`建造秒完成`可能导致部分建筑无法立即完成的问题
|
||||||
* 2.3.5
|
* 2.3.5
|
||||||
+ 修复了`跳过子弹阶段`可能导致崩溃的问题
|
* 修复了`跳过子弹阶段`可能导致崩溃的问题
|
||||||
* 2.3.4
|
* 2.3.4
|
||||||
+ 使用UXAssist 1.0.2的新页签布局
|
* 使用UXAssist 1.0.2的新页签布局
|
||||||
+ 修复了一些小bug
|
* 修复了一些小bug
|
||||||
* 2.3.3
|
* 2.3.3
|
||||||
+ 修复了`跳过子弹阶段`可能导致崩溃的问题
|
* 修复了`跳过子弹阶段`可能导致崩溃的问题
|
||||||
+ 使用Alt解锁科技时,现在`矿物利用`的科技解锁到10000级而不是7200级,因为UXAssist已修复对应bug
|
* 使用Alt解锁科技时,现在`矿物利用`的科技解锁到10000级而不是7200级,因为UXAssist已修复对应bug
|
||||||
* 2.3.2
|
* 2.3.2
|
||||||
+ 母星系的选项移动到了[UniverseGenTweaks](https://dsp.thunderstore.io/package/soarqin/UniverseGenTweaks/)
|
* 母星系的选项移动到了[UniverseGenTweaks](https://dsp.thunderstore.io/package/soarqin/UniverseGenTweaks/)
|
||||||
+ 优化了`快速吸收`,现在消耗更少的CPU,并且会轮流打向各节点
|
* 优化了`快速吸收`,现在消耗更少的CPU,并且会轮流打向各节点
|
||||||
+ `高速采集`现在可以保证油井的最大产出
|
* `高速采集`现在可以保证油井的最大产出
|
||||||
+ 修复了`传送带信号物品生成`在选项关闭后再次启用时不生效的问题
|
* 修复了`传送带信号物品生成`在选项关闭后再次启用时不生效的问题
|
||||||
+ 修复了`快速吸收`和`跳过子弹阶段`同时启用时可能导致吸收计算错误的问题
|
* 修复了`快速吸收`和`跳过子弹阶段`同时启用时可能导致吸收计算错误的问题
|
||||||
+ 修复了一些选项可能导致崩溃的问题
|
* 修复了一些选项可能导致崩溃的问题
|
||||||
* 2.3.1
|
* 2.3.1
|
||||||
+ 在manifest中添加UXAssist到依赖
|
* 在manifest中添加UXAssist到依赖
|
||||||
* 2.3.0
|
* 2.3.0
|
||||||
+ 将部分功能移动到单独的mod:[UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist)
|
* 将部分功能移动到单独的mod:[UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist)
|
||||||
+ 现在依赖[UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist),因此配置面板与UXAssist合并
|
* 现在依赖[UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist),因此配置面板与UXAssist合并
|
||||||
+ 从开发模式快捷键中移除`LCtrl+A`,以避免误操作
|
* 从开发模式快捷键中移除`LCtrl+A`,以避免误操作
|
||||||
+ 现在`建筑师模式`中配送机/物流机/物流船也无限了
|
* 现在`建筑师模式`中配送机/物流机/物流船也无限了
|
||||||
* 2.2.7
|
* 2.2.7
|
||||||
+ 新功能:`只建造节点不建造框架`
|
* 新功能:`只建造节点不建造框架`
|
||||||
+ 打开设置面板时不再关闭背包面板
|
* 打开设置面板时不再关闭背包面板
|
||||||
+ 在`移除部分不影响游戏逻辑的建造条件`启用时移除`输入方向冲突`的检查条件
|
* 在`移除部分不影响游戏逻辑的建造条件`启用时移除`输入方向冲突`的检查条件
|
||||||
+ 修复导致`传送带信号替换格式`不切换传送带信号数字格式的问题
|
* 修复导致`传送带信号替换格式`不切换传送带信号数字格式的问题
|
||||||
* 2.2.6
|
* 2.2.6
|
||||||
+ 新功能:`可用节点全部造完时停止弹射`
|
* 新功能:`可用节点全部造完时停止弹射`
|
||||||
+ 修复了在未完成的节点上吸收太阳帆的问题
|
* 修复了在未完成的节点上吸收太阳帆的问题
|
||||||
* 2.2.5
|
* 2.2.5
|
||||||
+ 在同时启用`快速吸收`、`跳过子弹阶段`和`跳过吸收阶段`时,所有弹射的太阳帆会跳过所有中间环节立即吸收
|
* 在同时启用`快速吸收`、`跳过子弹阶段`和`跳过吸收阶段`时,所有弹射的太阳帆会跳过所有中间环节立即吸收
|
||||||
+ 修复了`快速吸收`在大部分节点已满时无法立即吸收所有太阳帆的问题
|
* 修复了`快速吸收`在大部分节点已满时无法立即吸收所有太阳帆的问题
|
||||||
+ 修复了与一些mod的兼容性问题
|
* 修复了与一些mod的兼容性问题
|
||||||
* 2.2.4
|
* 2.2.4
|
||||||
+ 新功能:`在行星视图中允许玩家操作`
|
* 新功能:`在行星视图中允许玩家操作`
|
||||||
+ 修复了UI显示问题
|
* 修复了UI显示问题
|
||||||
* 2.2.3
|
* 2.2.3
|
||||||
+ 新功能:`移除部分不影响游戏逻辑的建造条件`
|
* 新功能:`移除部分不影响游戏逻辑的建造条件`
|
||||||
+ 修复了与一些mod的兼容性问题
|
* 修复了与一些mod的兼容性问题
|
||||||
* 2.2.2
|
* 2.2.2
|
||||||
+ 新功能:`将游戏存档绑定给当前账号`
|
* 新功能:`将游戏存档绑定给当前账号`
|
||||||
+ 新子功能:`传送带信号替换格式`
|
* 新子功能:`传送带信号替换格式`
|
||||||
+ 修复了`初始化本行星`可能导致崩溃的问题
|
* 修复了`初始化本行星`可能导致崩溃的问题
|
||||||
+ 修复了`建造秒完成`中传送带建造的问题
|
* 修复了`建造秒完成`中传送带建造的问题
|
||||||
* 2.2.1
|
* 2.2.1
|
||||||
+ 即使在启用`无条件建造`时依然检查矿机的建造条件
|
* 即使在启用`无条件建造`时依然检查矿机的建造条件
|
||||||
+ 修复一个可能导致`无条件建造`不生效的问题
|
* 修复一个可能导致`无条件建造`不生效的问题
|
||||||
* 2.2.0
|
* 2.2.0
|
||||||
+ 添加了一些发电相关功能
|
* 添加了一些发电相关功能
|
||||||
+ 为传送带信号物品生成添加了一个子功能,在统计面板模拟了原材料和中间产物的生产过程
|
* 为传送带信号物品生成添加了一个子功能,在统计面板模拟了原材料和中间产物的生产过程
|
||||||
+ 从建筑师模式中分离了一些功能
|
* 从建筑师模式中分离了一些功能
|
||||||
* 2.1.0
|
* 2.1.0
|
||||||
+ 传送带信号物品生成
|
* 传送带信号物品生成
|
||||||
+ 修复窗口显示优先级可能导致提示信息被主窗口遮挡的问题
|
* 修复窗口显示优先级可能导致提示信息被主窗口遮挡的问题
|
||||||
* 2.0.0
|
* 2.0.0
|
||||||
+ 重构代码
|
* 重构代码
|
||||||
+ UI实现
|
* UI实现
|
||||||
+ 添加了很多功能
|
* 添加了很多功能
|
||||||
* 1.0.0
|
* 1.0.0
|
||||||
+ 初始版本
|
* 初始版本
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ public class CheatEnabler : BaseUnityPlugin
|
|||||||
"Belt signal count removals as comsumption in statistics");
|
"Belt signal count removals as comsumption in statistics");
|
||||||
FactoryPatch.BeltSignalCountRecipeEnabled = Config.Bind("Build", "BeltSignalCountRecipe", false,
|
FactoryPatch.BeltSignalCountRecipeEnabled = Config.Bind("Build", "BeltSignalCountRecipe", false,
|
||||||
"Belt signal count all raws and intermediates in statistics");
|
"Belt signal count all raws and intermediates in statistics");
|
||||||
|
FactoryPatch.BeltSignalUseProliferatorEnabled = Config.Bind("Build", "BeltSignalUseProliferator", false,
|
||||||
|
"Belt signal count proliferators used for raws/intermediates and finished products");
|
||||||
FactoryPatch.RemovePowerSpaceLimitEnabled = Config.Bind("Build", "RemovePowerDistanceLimit", false,
|
FactoryPatch.RemovePowerSpaceLimitEnabled = Config.Bind("Build", "RemovePowerDistanceLimit", false,
|
||||||
"Remove distance limit for wind turbines and geothermals");
|
"Remove distance limit for wind turbines and geothermals");
|
||||||
FactoryPatch.BoostWindPowerEnabled = Config.Bind("Build", "BoostWindPower", false,
|
FactoryPatch.BoostWindPowerEnabled = Config.Bind("Build", "BoostWindPower", false,
|
||||||
@@ -71,6 +73,8 @@ public class CheatEnabler : BaseUnityPlugin
|
|||||||
"Enable warp without warper");
|
"Enable warp without warper");
|
||||||
DysonSpherePatch.SkipBulletEnabled = Config.Bind("DysonSphere", "SkipBullet", false,
|
DysonSpherePatch.SkipBulletEnabled = Config.Bind("DysonSphere", "SkipBullet", false,
|
||||||
"Skip bullet");
|
"Skip bullet");
|
||||||
|
DysonSpherePatch.FireAllBulletsEnabled = Config.Bind("DysonSphere", "FireAllBullets", false,
|
||||||
|
"Fire all bullets at once");
|
||||||
DysonSpherePatch.SkipAbsorbEnabled = Config.Bind("DysonSphere", "SkipAbsorb", false,
|
DysonSpherePatch.SkipAbsorbEnabled = Config.Bind("DysonSphere", "SkipAbsorb", false,
|
||||||
"Skip absorption");
|
"Skip absorption");
|
||||||
DysonSpherePatch.QuickAbsorbEnabled = Config.Bind("DysonSphere", "QuickAbsorb", false,
|
DysonSpherePatch.QuickAbsorbEnabled = Config.Bind("DysonSphere", "QuickAbsorb", false,
|
||||||
@@ -81,6 +85,14 @@ public class CheatEnabler : BaseUnityPlugin
|
|||||||
"Overclock ejector");
|
"Overclock ejector");
|
||||||
DysonSpherePatch.OverclockSiloEnabled = Config.Bind("DysonSphere", "OverclockSilo", false,
|
DysonSpherePatch.OverclockSiloEnabled = Config.Bind("DysonSphere", "OverclockSilo", false,
|
||||||
"Overclock silo");
|
"Overclock silo");
|
||||||
|
DysonSpherePatch.UnlockMaxOrbitRadiusEnabled = Config.Bind("DysonSphere", "UnlockMaxOrbitRadius", false,
|
||||||
|
"Unlock Dyson Sphere max orbit radius");
|
||||||
|
DysonSpherePatch.UnlockMaxOrbitRadiusValue = Config.Bind("DysonSphere", "MaxOrbitRadiusValue", 10_000_000f,
|
||||||
|
"Unlocked Dyson Sphere max orbit radius value");
|
||||||
|
Functions.DysonSphereFunctions.IllegalDysonShellFunctionsEnabled = Config.Bind("DysonSphere", "IllegalDysonShellFunctions", false,
|
||||||
|
"Enable illegal dyson shell functions");
|
||||||
|
Functions.DysonSphereFunctions.ShellsCountForFunctions = Config.Bind("DysonSphere", "ShellsCountForFunctions", 2048,
|
||||||
|
"Shells count for various functions");
|
||||||
CombatPatch.MechaInvincibleEnabled = Config.Bind("Battle", "MechaInvincible", false,
|
CombatPatch.MechaInvincibleEnabled = Config.Bind("Battle", "MechaInvincible", false,
|
||||||
"Mecha and Drones/Fleets invincible");
|
"Mecha and Drones/Fleets invincible");
|
||||||
CombatPatch.BuildingsInvincibleEnabled = Config.Bind("Battle", "BuildingsInvincible", false,
|
CombatPatch.BuildingsInvincibleEnabled = Config.Bind("Battle", "BuildingsInvincible", false,
|
||||||
@@ -106,6 +118,6 @@ public class CheatEnabler : BaseUnityPlugin
|
|||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
if (VFInput.inputing) return;
|
if (VFInput.inputing) return;
|
||||||
FactoryPatch.OnUpdate();
|
FactoryPatch.OnInputUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,45 +1,15 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<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.29</Version>
|
<Version>2.4.3</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<PackageId>CheatEnabler</PackageId>
|
<PackageId>CheatEnabler</PackageId>
|
||||||
<RootNamespace>CheatEnabler</RootNamespace>
|
<RootNamespace>CheatEnabler</RootNamespace>
|
||||||
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
|
<PackHasChangelog>true</PackHasChangelog>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
|
||||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
|
||||||
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="Assembly-CSharp">
|
|
||||||
<HintPath>..\AssemblyFromGame\Assembly-CSharp.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="UnityEngine.UI">
|
|
||||||
<HintPath>..\AssemblyFromGame\UnityEngine.UI.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\UXAssist\UXAssist.csproj" />
|
<ProjectReference Include="..\UXAssist\UXAssist.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<Exec Command="del /F /Q package\$(ProjectName)-$(Version).zip
powershell Compress-Archive -Force -DestinationPath 'package/$(ProjectName)-$(Version).zip' -Path '$(TargetPath)', package/icon.png, package/manifest.json, README.md, CHANGELOG.md" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
|||||||
using Random = UnityEngine.Random;
|
using Random = UnityEngine.Random;
|
||||||
|
|
||||||
namespace CheatEnabler.Functions;
|
namespace CheatEnabler.Functions;
|
||||||
|
|
||||||
public static class PlanetFunctions
|
public static class PlanetFunctions
|
||||||
{
|
{
|
||||||
public static void BuryAllVeins(bool bury)
|
public static void BuryAllVeins(bool bury)
|
||||||
@@ -16,9 +17,15 @@ public static class PlanetFunctions
|
|||||||
{
|
{
|
||||||
var pos = array[m].pos;
|
var pos = array[m].pos;
|
||||||
var colliderId = array[m].colliderId;
|
var colliderId = array[m].colliderId;
|
||||||
|
if (colliderId <= 0) continue;
|
||||||
|
var chunkIdx = colliderId >> 20;
|
||||||
|
var poolIdx = colliderId & 0xFFFFF;
|
||||||
|
if (chunkIdx >= physics.colChunks.Length) continue;
|
||||||
|
var chunk = physics.colChunks[chunkIdx];
|
||||||
|
if (chunk == null || poolIdx >= chunk.colliderPool.Length) continue;
|
||||||
var colliderData = physics.GetColliderData(colliderId);
|
var colliderData = physics.GetColliderData(colliderId);
|
||||||
var vector = colliderData.pos.normalized * (height + 0.4f);
|
var vector = colliderData.pos.normalized * (height + 0.4f);
|
||||||
physics.colChunks[colliderId >> 20].colliderPool[colliderId & 0xFFFFF].pos = vector;
|
chunk.colliderPool[poolIdx].pos = vector;
|
||||||
array[m].pos = pos.normalized * height;
|
array[m].pos = pos.normalized * height;
|
||||||
var quaternion = Maths.SphericalRotation(array[m].pos, Random.value * 360f);
|
var quaternion = Maths.SphericalRotation(array[m].pos, Random.value * 360f);
|
||||||
physics.SetPlanetPhysicsColliderDirty();
|
physics.SetPlanetPhysicsColliderDirty();
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public static class PlayerFunctions
|
|||||||
{
|
{
|
||||||
var maxSqrDistance = 0.0;
|
var maxSqrDistance = 0.0;
|
||||||
var starPosition = VectorLF3.zero;
|
var starPosition = VectorLF3.zero;
|
||||||
|
if (GameMain.galaxy == null) return;
|
||||||
foreach (var star in GameMain.galaxy.stars)
|
foreach (var star in GameMain.galaxy.stars)
|
||||||
{
|
{
|
||||||
var sqrDistance = star.position.sqrMagnitude;
|
var sqrDistance = star.position.sqrMagnitude;
|
||||||
@@ -106,7 +107,7 @@ public static class PlayerFunctions
|
|||||||
|
|
||||||
if (itemCnt.All(cnt => cnt == 0))
|
if (itemCnt.All(cnt => cnt == 0))
|
||||||
{
|
{
|
||||||
UIMessageBox.Show("Remove all metadata consumption records".Translate(), "NoMetadataConsumptionRecord".Translate(), "OK".Translate(), 0);
|
UIMessageBox.Show("Remove all metadata consumption records".Translate(), "NoMetadataConsumptionRecord".Translate(), "OK".Translate(), UIMessageBox.INFO);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var msg = "ClearAllMetadataConsumptionDetails".Translate();
|
var msg = "ClearAllMetadataConsumptionDetails".Translate();
|
||||||
@@ -117,7 +118,7 @@ public static class PlayerFunctions
|
|||||||
msg += $"\n {LDB.items.Select(i + 6001).propertyName} x{itemCnt[i]}";
|
msg += $"\n {LDB.items.Select(i + 6001).propertyName} x{itemCnt[i]}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIMessageBox.Show("Remove all metadata consumption records".Translate(), msg, "取消".Translate(), "确定".Translate(), 2, null, () =>
|
UIMessageBox.Show("Remove all metadata consumption records".Translate(), msg, "取消".Translate(), "确定".Translate(), UIMessageBox.QUESTION, null, () =>
|
||||||
{
|
{
|
||||||
foreach (var data in propertySystem.propertyDatas)
|
foreach (var data in propertySystem.propertyDatas)
|
||||||
{
|
{
|
||||||
@@ -143,17 +144,18 @@ public static class PlayerFunctions
|
|||||||
var clusterPropertyData = propertySystem.propertyDatas.FirstOrDefault(cpd => cpd.seedKey == seedKey);
|
var clusterPropertyData = propertySystem.propertyDatas.FirstOrDefault(cpd => cpd.seedKey == seedKey);
|
||||||
if (clusterPropertyData == null)
|
if (clusterPropertyData == null)
|
||||||
{
|
{
|
||||||
UIMessageBox.Show("Remove metadata consumption record in current game".Translate(), "NoMetadataConsumptionRecord".Translate(), "OK".Translate(), 0);
|
UIMessageBox.Show("Remove metadata consumption record in current game".Translate(), "NoMetadataConsumptionRecord".Translate(), "OK".Translate(), UIMessageBox.INFO);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
foreach (var cons in clusterPropertyData.totalConsumption.Where(cons => cons.id is >= 6001 and <= 6006))
|
var currentGamePropertyData = GameMain.data.history.propertyData;
|
||||||
|
foreach (var cons in currentGamePropertyData.totalConsumption.Where(cons => cons.id is >= 6001 and <= 6006))
|
||||||
{
|
{
|
||||||
itemCnt[cons.id - 6001] += cons.count;
|
itemCnt[cons.id - 6001] += cons.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemCnt.All(cnt => cnt == 0))
|
if (itemCnt.All(cnt => cnt == 0))
|
||||||
{
|
{
|
||||||
UIMessageBox.Show("Remove metadata consumption record in current game".Translate(), "NoMetadataConsumptionRecord".Translate(), "OK".Translate(), 0);
|
UIMessageBox.Show("Remove metadata consumption record in current game".Translate(), "NoMetadataConsumptionRecord".Translate(), "OK".Translate(), UIMessageBox.INFO);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var msg = "ClearCurrentMetadataConsumptionDetails".Translate();
|
var msg = "ClearCurrentMetadataConsumptionDetails".Translate();
|
||||||
@@ -164,13 +166,17 @@ public static class PlayerFunctions
|
|||||||
msg += $"\n {LDB.items.Select(i + 6001).propertyName} x{itemCnt[i]}";
|
msg += $"\n {LDB.items.Select(i + 6001).propertyName} x{itemCnt[i]}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIMessageBox.Show("Remove metadata consumption record in current game".Translate(), msg, "取消".Translate(), "确定".Translate(), 2, null, () =>
|
UIMessageBox.Show("Remove metadata consumption record in current game".Translate(), msg, "取消".Translate(), "确定".Translate(), UIMessageBox.QUESTION, null, () =>
|
||||||
{
|
{
|
||||||
for (var i = 0; i < clusterPropertyData.totalConsumption.Count; i++)
|
for (var i = 0; i < clusterPropertyData.totalConsumption.Count; i++)
|
||||||
{
|
{
|
||||||
if (clusterPropertyData.totalConsumption[i].count == 0) continue;
|
if (clusterPropertyData.totalConsumption[i].count == 0) continue;
|
||||||
var id = clusterPropertyData.totalConsumption[i].id;
|
var id = clusterPropertyData.totalConsumption[i].id;
|
||||||
clusterPropertyData.totalConsumption[i] = new IDCNT(id, 0);
|
if (id < 6001 || id > 6006) continue;
|
||||||
|
var currentGameCount = itemCnt[id - 6001];
|
||||||
|
if (currentGameCount == 0) continue;
|
||||||
|
var totalCount = clusterPropertyData.totalConsumption[i].count;
|
||||||
|
clusterPropertyData.totalConsumption[i] = new IDCNT(id, totalCount > currentGameCount ? totalCount - currentGameCount : 0);
|
||||||
}
|
}
|
||||||
PurgePropertySystem(propertySystem);
|
PurgePropertySystem(propertySystem);
|
||||||
propertySystem.SaveToFile();
|
propertySystem.SaveToFile();
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public static class CombatPatch
|
|||||||
MechaInvincible.Enable(false);
|
MechaInvincible.Enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MechaInvincible: PatchImpl<MechaInvincible>
|
private class MechaInvincible : PatchImpl<MechaInvincible>
|
||||||
{
|
{
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(Player), nameof(Player.invincible), MethodType.Getter)]
|
[HarmonyPatch(typeof(Player), nameof(Player.invincible), MethodType.Getter)]
|
||||||
@@ -65,7 +65,7 @@ public static class CombatPatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BuildingsInvincible: PatchImpl<BuildingsInvincible>
|
private class BuildingsInvincible : PatchImpl<BuildingsInvincible>
|
||||||
{
|
{
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(SkillSystem), nameof(SkillSystem.DamageGroundObjectByLocalCaster))]
|
[HarmonyPatch(typeof(SkillSystem), nameof(SkillSystem.DamageGroundObjectByLocalCaster))]
|
||||||
|
|||||||
@@ -4,17 +4,21 @@ using System.Reflection.Emit;
|
|||||||
using BepInEx.Configuration;
|
using BepInEx.Configuration;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using UXAssist.Common;
|
using UXAssist.Common;
|
||||||
|
using GameLogicProc = UXAssist.Common.GameLogic;
|
||||||
|
|
||||||
namespace CheatEnabler.Patches;
|
namespace CheatEnabler.Patches;
|
||||||
|
|
||||||
public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
public class DysonSpherePatch : PatchImpl<DysonSpherePatch>
|
||||||
{
|
{
|
||||||
public static ConfigEntry<bool> SkipBulletEnabled;
|
public static ConfigEntry<bool> SkipBulletEnabled;
|
||||||
|
public static ConfigEntry<bool> FireAllBulletsEnabled;
|
||||||
public static ConfigEntry<bool> SkipAbsorbEnabled;
|
public static ConfigEntry<bool> SkipAbsorbEnabled;
|
||||||
public static ConfigEntry<bool> QuickAbsorbEnabled;
|
public static ConfigEntry<bool> QuickAbsorbEnabled;
|
||||||
public static ConfigEntry<bool> EjectAnywayEnabled;
|
public static ConfigEntry<bool> EjectAnywayEnabled;
|
||||||
public static ConfigEntry<bool> OverclockEjectorEnabled;
|
public static ConfigEntry<bool> OverclockEjectorEnabled;
|
||||||
public static ConfigEntry<bool> OverclockSiloEnabled;
|
public static ConfigEntry<bool> OverclockSiloEnabled;
|
||||||
|
public static ConfigEntry<bool> UnlockMaxOrbitRadiusEnabled;
|
||||||
|
public static ConfigEntry<float> UnlockMaxOrbitRadiusValue;
|
||||||
private static bool _instantAbsorb;
|
private static bool _instantAbsorb;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
@@ -25,6 +29,9 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
EjectAnywayEnabled.SettingChanged += (_, _) => EjectAnywayPatch.Enable(EjectAnywayEnabled.Value);
|
EjectAnywayEnabled.SettingChanged += (_, _) => EjectAnywayPatch.Enable(EjectAnywayEnabled.Value);
|
||||||
OverclockEjectorEnabled.SettingChanged += (_, _) => OverclockEjector.Enable(OverclockEjectorEnabled.Value);
|
OverclockEjectorEnabled.SettingChanged += (_, _) => OverclockEjector.Enable(OverclockEjectorEnabled.Value);
|
||||||
OverclockSiloEnabled.SettingChanged += (_, _) => OverclockSilo.Enable(OverclockSiloEnabled.Value);
|
OverclockSiloEnabled.SettingChanged += (_, _) => OverclockSilo.Enable(OverclockSiloEnabled.Value);
|
||||||
|
UnlockMaxOrbitRadiusEnabled.SettingChanged += (_, _) => UnlockMaxOrbitRadius.Enable(UnlockMaxOrbitRadiusEnabled.Value);
|
||||||
|
|
||||||
|
FireAllBulletsEnabled.SettingChanged += (_, _) => SkipBulletPatch.SetFireAllBullets(FireAllBulletsEnabled.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Start()
|
public static void Start()
|
||||||
@@ -35,9 +42,11 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
EjectAnywayPatch.Enable(EjectAnywayEnabled.Value);
|
EjectAnywayPatch.Enable(EjectAnywayEnabled.Value);
|
||||||
OverclockEjector.Enable(OverclockEjectorEnabled.Value);
|
OverclockEjector.Enable(OverclockEjectorEnabled.Value);
|
||||||
OverclockSilo.Enable(OverclockSiloEnabled.Value);
|
OverclockSilo.Enable(OverclockSiloEnabled.Value);
|
||||||
|
UnlockMaxOrbitRadius.Enable(UnlockMaxOrbitRadiusEnabled.Value);
|
||||||
Enable(true);
|
Enable(true);
|
||||||
|
SkipBulletPatch.SetFireAllBullets(FireAllBulletsEnabled.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Uninit()
|
public static void Uninit()
|
||||||
{
|
{
|
||||||
Enable(false);
|
Enable(false);
|
||||||
@@ -47,8 +56,16 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
EjectAnywayPatch.Enable(false);
|
EjectAnywayPatch.Enable(false);
|
||||||
OverclockEjector.Enable(false);
|
OverclockEjector.Enable(false);
|
||||||
OverclockSilo.Enable(false);
|
OverclockSilo.Enable(false);
|
||||||
|
UnlockMaxOrbitRadius.Enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [HarmonyPostfix]
|
||||||
|
// [HarmonyPatch(typeof(DysonShell), nameof(DysonShell.ImportFromBlueprint))]
|
||||||
|
// private static void DysonShell_ImportFromBlueprint_Postfix(DysonShell __instance)
|
||||||
|
// {
|
||||||
|
// CheatEnabler.Logger.LogDebug($"[DysonShell.ImportFromBlueprint] vertCount={__instance.vertexCount}, cpPerVertex={__instance.cpPerVertex}, cpMax={__instance.cellPointMax}");
|
||||||
|
// }
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(DysonNode), nameof(DysonNode.OrderConstructCp))]
|
[HarmonyPatch(typeof(DysonNode), nameof(DysonNode.OrderConstructCp))]
|
||||||
private static IEnumerable<CodeInstruction> DysonNode_OrderConstructCp_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
private static IEnumerable<CodeInstruction> DysonNode_OrderConstructCp_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
@@ -83,12 +100,18 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SkipBulletPatch: PatchImpl<SkipBulletPatch>
|
private class SkipBulletPatch : PatchImpl<SkipBulletPatch>
|
||||||
{
|
{
|
||||||
private static long _sailLifeTime;
|
private static long _sailLifeTime;
|
||||||
private static DysonSailCache[][] _sailsCache;
|
private static DysonSailCache[][] _sailsCache;
|
||||||
private static int[] _sailsCacheLen, _sailsCacheCapacity;
|
private static int[] _sailsCacheLen, _sailsCacheCapacity;
|
||||||
|
private static bool _fireAllBullets;
|
||||||
|
|
||||||
|
public static void SetFireAllBullets(bool value)
|
||||||
|
{
|
||||||
|
_fireAllBullets = value;
|
||||||
|
}
|
||||||
|
|
||||||
private struct DysonSailCache
|
private struct DysonSailCache
|
||||||
{
|
{
|
||||||
public DysonSail Sail;
|
public DysonSail Sail;
|
||||||
@@ -111,12 +134,12 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
{
|
{
|
||||||
UpdateSailLifeTime();
|
UpdateSailLifeTime();
|
||||||
UpdateSailsCacheForThisGame();
|
UpdateSailsCacheForThisGame();
|
||||||
GameLogic.OnGameBegin += GameMain_Begin_Postfix;
|
GameLogicProc.OnGameBegin += OnGameBegin;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisable()
|
protected override void OnDisable()
|
||||||
{
|
{
|
||||||
GameLogic.OnGameBegin -= GameMain_Begin_Postfix;
|
GameLogicProc.OnGameBegin -= OnGameBegin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateSailLifeTime()
|
private static void UpdateSailLifeTime()
|
||||||
@@ -136,7 +159,7 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
Array.Clear(_sailsCacheLen, 0, starCount);
|
Array.Clear(_sailsCacheLen, 0, starCount);
|
||||||
Array.Clear(_sailsCacheCapacity, 0, starCount);
|
Array.Clear(_sailsCacheCapacity, 0, starCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetSailsCacheCapacity(int index, int capacity)
|
private static void SetSailsCacheCapacity(int index, int capacity)
|
||||||
{
|
{
|
||||||
var newCache = new DysonSailCache[capacity];
|
var newCache = new DysonSailCache[capacity];
|
||||||
@@ -149,7 +172,7 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
_sailsCacheCapacity[index] = capacity;
|
_sailsCacheCapacity[index] = capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GameMain_Begin_Postfix()
|
private static void OnGameBegin()
|
||||||
{
|
{
|
||||||
UpdateSailsCacheForThisGame();
|
UpdateSailsCacheForThisGame();
|
||||||
UpdateSailLifeTime();
|
UpdateSailLifeTime();
|
||||||
@@ -164,7 +187,7 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
UpdateSailLifeTime();
|
UpdateSailLifeTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(EjectorComponent), nameof(EjectorComponent.InternalUpdate))]
|
[HarmonyPatch(typeof(EjectorComponent), nameof(EjectorComponent.InternalUpdate))]
|
||||||
private static IEnumerable<CodeInstruction> EjectorComponent_InternalUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
private static IEnumerable<CodeInstruction> EjectorComponent_InternalUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
@@ -175,25 +198,28 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
).Advance(2);
|
).Advance(2);
|
||||||
var start = matcher.Pos;
|
var start = matcher.Pos;
|
||||||
matcher.MatchForward(false,
|
matcher.MatchForward(false,
|
||||||
new CodeMatch(OpCodes.Pop)
|
new CodeMatch(OpCodes.Ldc_I4_M1),
|
||||||
).Advance(1);
|
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.direction)))
|
||||||
|
).Advance(2);
|
||||||
var end = matcher.Pos;
|
var end = matcher.Pos;
|
||||||
matcher.Start().Advance(start).RemoveInstructions(end - start).Insert(
|
matcher.Start().Advance(start).RemoveInstructions(end - start).Insert(
|
||||||
new CodeInstruction(OpCodes.Ldarg_3),
|
|
||||||
new CodeInstruction(OpCodes.Ldarg_0),
|
new CodeInstruction(OpCodes.Ldarg_0),
|
||||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.orbitId))),
|
new CodeInstruction(OpCodes.Ldarg_3),
|
||||||
new CodeInstruction(OpCodes.Ldloc_S, 9),
|
new CodeInstruction(OpCodes.Ldloc_S, 9),
|
||||||
new CodeInstruction(OpCodes.Ldloc_S, 11),
|
new CodeInstruction(OpCodes.Ldloc_S, 11),
|
||||||
|
new CodeInstruction(OpCodes.Ldarg_S, 6),
|
||||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(SkipBulletPatch), nameof(SkipBulletPatch.AddDysonSail)))
|
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(SkipBulletPatch), nameof(SkipBulletPatch.AddDysonSail)))
|
||||||
);
|
);
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddDysonSail(DysonSwarm swarm, int orbitId, VectorLF3 uPos, VectorLF3 endVec)
|
private static void AddDysonSail(ref EjectorComponent ejector, DysonSwarm swarm, VectorLF3 uPos, VectorLF3 endVec, int[] consumeRegister)
|
||||||
{
|
{
|
||||||
var index = swarm.starData.index;
|
var index = swarm.starData.index;
|
||||||
|
var orbitId = ejector.orbitId;
|
||||||
var delta1 = endVec - swarm.starData.uPosition;
|
var delta1 = endVec - swarm.starData.uPosition;
|
||||||
var delta2 = VectorLF3.Cross(endVec - uPos, swarm.orbits[orbitId].up).normalized * Math.Sqrt(swarm.dysonSphere.gravity / swarm.orbits[orbitId].radius);
|
var delta2 = VectorLF3.Cross(endVec - uPos, swarm.orbits[orbitId].up).normalized * Math.Sqrt(swarm.dysonSphere.gravity / swarm.orbits[orbitId].radius);
|
||||||
|
var bulletCount = ejector.bulletCount;
|
||||||
lock (swarm)
|
lock (swarm)
|
||||||
{
|
{
|
||||||
var cache = _sailsCache[index];
|
var cache = _sailsCache[index];
|
||||||
@@ -203,6 +229,24 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
SetSailsCacheCapacity(index, 256);
|
SetSailsCacheCapacity(index, 256);
|
||||||
cache = _sailsCache[index];
|
cache = _sailsCache[index];
|
||||||
}
|
}
|
||||||
|
if (_fireAllBullets)
|
||||||
|
{
|
||||||
|
var capacity = _sailsCacheCapacity[index];
|
||||||
|
var leastCapacity = len + bulletCount;
|
||||||
|
if (leastCapacity > capacity)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
capacity *= 2;
|
||||||
|
} while (leastCapacity > capacity);
|
||||||
|
SetSailsCacheCapacity(index, capacity);
|
||||||
|
cache = _sailsCache[index];
|
||||||
|
}
|
||||||
|
_sailsCacheLen[index] = len + bulletCount;
|
||||||
|
var end = len + bulletCount;
|
||||||
|
for (var i = len; i < end; i++)
|
||||||
|
cache[i].FromData(delta1, delta2 + RandomTable.SphericNormal(ref swarm.randSeed, 0.5), orbitId);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var capacity = _sailsCacheCapacity[index];
|
var capacity = _sailsCacheCapacity[index];
|
||||||
@@ -211,14 +255,48 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
SetSailsCacheCapacity(index, capacity * 2);
|
SetSailsCacheCapacity(index, capacity * 2);
|
||||||
cache = _sailsCache[index];
|
cache = _sailsCache[index];
|
||||||
}
|
}
|
||||||
|
_sailsCacheLen[index] = len + 1;
|
||||||
|
cache[len].FromData(delta1, delta2 + RandomTable.SphericNormal(ref swarm.randSeed, 0.5), orbitId);
|
||||||
}
|
}
|
||||||
_sailsCacheLen[index] = len + 1;
|
|
||||||
cache[len].FromData(delta1, delta2 + RandomTable.SphericNormal(ref swarm.randSeed, 0.5), orbitId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_fireAllBullets)
|
||||||
|
{
|
||||||
|
if (!ejector.incUsed)
|
||||||
|
{
|
||||||
|
ejector.incUsed = ejector.bulletInc >= bulletCount;
|
||||||
|
}
|
||||||
|
ejector.bulletInc = 0;
|
||||||
|
ejector.bulletCount = 0;
|
||||||
|
lock (consumeRegister)
|
||||||
|
{
|
||||||
|
consumeRegister[ejector.bulletId] += bulletCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var inc = ejector.bulletInc / bulletCount;
|
||||||
|
if (!ejector.incUsed)
|
||||||
|
{
|
||||||
|
ejector.incUsed = inc > 0;
|
||||||
|
}
|
||||||
|
ejector.bulletInc -= inc;
|
||||||
|
ejector.bulletCount = bulletCount - 1;
|
||||||
|
if (ejector.bulletCount == 0)
|
||||||
|
{
|
||||||
|
ejector.bulletInc = 0;
|
||||||
|
}
|
||||||
|
lock (consumeRegister)
|
||||||
|
{
|
||||||
|
consumeRegister[ejector.bulletId]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ejector.time = ejector.coldSpend;
|
||||||
|
ejector.direction = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(DysonSwarm), "GameTick")]
|
[HarmonyPatch(typeof(DysonSwarm), nameof(DysonSwarm.GameTick))]
|
||||||
public static void DysonSwarm_GameTick_Prefix(DysonSwarm __instance, long time)
|
public static void DysonSwarm_GameTick_Prefix(DysonSwarm __instance, long time)
|
||||||
{
|
{
|
||||||
var index = __instance.starData.index;
|
var index = __instance.starData.index;
|
||||||
@@ -256,9 +334,10 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
if (node.ConstructCp() == null) break;
|
if (node.ConstructCp() == null) break;
|
||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
{
|
{
|
||||||
sphereProductRegister[11901] += len;
|
sphereProductRegister[ProductionStatistics.SOLAR_SAIL_ID] += len;
|
||||||
sphereConsumeRegister[11901] += len;
|
sphereConsumeRegister[ProductionStatistics.SOLAR_SAIL_ID] += len;
|
||||||
sphereProductRegister[11903] += len;
|
sphereProductRegister[ProductionStatistics.DYSON_CELL_ID] += len;
|
||||||
|
__instance.dysonSphere.needRecalculatePower = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
idx--;
|
idx--;
|
||||||
@@ -269,9 +348,10 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
var absorbCnt = len - 1 - idx;
|
var absorbCnt = len - 1 - idx;
|
||||||
if (absorbCnt > 0)
|
if (absorbCnt > 0)
|
||||||
{
|
{
|
||||||
sphereProductRegister[11901] += absorbCnt;
|
sphereProductRegister[ProductionStatistics.SOLAR_SAIL_ID] += absorbCnt;
|
||||||
sphereConsumeRegister[11901] += absorbCnt;
|
sphereConsumeRegister[ProductionStatistics.SOLAR_SAIL_ID] += absorbCnt;
|
||||||
sphereProductRegister[11903] += absorbCnt;
|
sphereProductRegister[ProductionStatistics.DYSON_CELL_ID] += absorbCnt;
|
||||||
|
__instance.dysonSphere.needRecalculatePower = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (; idx >= 0; idx--)
|
for (; idx >= 0; idx--)
|
||||||
@@ -280,17 +360,17 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SkipAbsorbPatch: PatchImpl<SkipAbsorbPatch>
|
private class SkipAbsorbPatch : PatchImpl<SkipAbsorbPatch>
|
||||||
{
|
{
|
||||||
protected override void OnEnable()
|
protected override void OnEnable()
|
||||||
{
|
{
|
||||||
_instantAbsorb = QuickAbsorbEnabled.Value;
|
_instantAbsorb = QuickAbsorbEnabled.Value && QuickAbsorbPatch.GetHarmony() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisable()
|
protected override void OnDisable()
|
||||||
{
|
{
|
||||||
_instantAbsorb = false;
|
_instantAbsorb = QuickAbsorbEnabled.Value && QuickAbsorbPatch.GetHarmony() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
@@ -302,47 +382,37 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
matcher.MatchForward(false,
|
matcher.MatchForward(false,
|
||||||
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(ExpiryOrder), nameof(ExpiryOrder.index)))
|
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(ExpiryOrder), nameof(ExpiryOrder.index)))
|
||||||
).Advance(1).RemoveInstructions(matcher.Length - matcher.Pos).Insert(
|
).Advance(1).RemoveInstructions(matcher.Length - matcher.Pos).Insert(
|
||||||
// if (node.ConstructCp() != null)
|
|
||||||
// {
|
|
||||||
// this.dysonSphere.productRegister[11903]++;
|
|
||||||
// }
|
|
||||||
new CodeInstruction(OpCodes.Ldarg_1),
|
|
||||||
new CodeInstruction(OpCodes.Callvirt, AccessTools.Method(typeof(DysonNode), nameof(DysonNode.ConstructCp))),
|
|
||||||
new CodeInstruction(OpCodes.Brfalse_S, label1),
|
|
||||||
new CodeInstruction(OpCodes.Ldarg_0),
|
new CodeInstruction(OpCodes.Ldarg_0),
|
||||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(DysonSwarm), nameof(DysonSwarm.dysonSphere))),
|
new CodeInstruction(OpCodes.Ldarg_1),
|
||||||
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(DysonSphere), nameof(DysonSphere.productRegister))),
|
|
||||||
new CodeInstruction(OpCodes.Ldc_I4, 11903),
|
|
||||||
new CodeInstruction(OpCodes.Ldelema, typeof(int)),
|
|
||||||
new CodeInstruction(OpCodes.Dup),
|
|
||||||
new CodeInstruction(OpCodes.Ldind_I4),
|
|
||||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
|
||||||
new CodeInstruction(OpCodes.Add),
|
|
||||||
new CodeInstruction(OpCodes.Stind_I4),
|
|
||||||
|
|
||||||
// this.RemoveSolarSail(index);
|
|
||||||
new CodeInstruction(OpCodes.Ldarg_0).WithLabels(label1),
|
|
||||||
new CodeInstruction(OpCodes.Ldloc_1),
|
new CodeInstruction(OpCodes.Ldloc_1),
|
||||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(DysonSwarm), nameof(DysonSwarm.RemoveSolarSail))),
|
Transpilers.EmitDelegate((DysonSwarm swarm, DysonNode node, int index) =>
|
||||||
|
{
|
||||||
// return false;
|
if (node.ConstructCp() != null)
|
||||||
|
{
|
||||||
|
swarm.dysonSphere.productRegister[ProductionStatistics.DYSON_CELL_ID]++;
|
||||||
|
swarm.dysonSphere.needRecalculatePower = true;
|
||||||
|
}
|
||||||
|
swarm.RemoveSolarSail(index);
|
||||||
|
}),
|
||||||
|
// return true;
|
||||||
|
// to avoid conflict with QuickAbsorbPatch
|
||||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||||
new CodeInstruction(OpCodes.Ret)
|
new CodeInstruction(OpCodes.Ret)
|
||||||
);
|
);
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class QuickAbsorbPatch: PatchImpl<QuickAbsorbPatch>
|
private class QuickAbsorbPatch : PatchImpl<QuickAbsorbPatch>
|
||||||
{
|
{
|
||||||
protected override void OnEnable()
|
protected override void OnEnable()
|
||||||
{
|
{
|
||||||
_instantAbsorb = SkipAbsorbEnabled.Value;
|
_instantAbsorb = SkipAbsorbEnabled.Value && SkipAbsorbPatch.GetHarmony() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisable()
|
protected override void OnDisable()
|
||||||
{
|
{
|
||||||
_instantAbsorb = false;
|
_instantAbsorb = SkipAbsorbEnabled.Value && SkipAbsorbPatch.GetHarmony() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
@@ -363,7 +433,7 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
/* Insert a RETURN before old absorption functions */
|
/* Insert a RETURN before old absorption functions */
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DoAbsorb(DysonSphereLayer layer, long gameTick)
|
private static void DoAbsorb(DysonSphereLayer layer, long gameTick)
|
||||||
{
|
{
|
||||||
var nodeCount = layer.nodeCursor - 1;
|
var nodeCount = layer.nodeCursor - 1;
|
||||||
@@ -383,8 +453,8 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class EjectAnywayPatch: PatchImpl<EjectAnywayPatch>
|
private class EjectAnywayPatch : PatchImpl<EjectAnywayPatch>
|
||||||
{
|
{
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(EjectorComponent), nameof(EjectorComponent.InternalUpdate))]
|
[HarmonyPatch(typeof(EjectorComponent), nameof(EjectorComponent.InternalUpdate))]
|
||||||
@@ -414,7 +484,7 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OverclockEjector: PatchImpl<OverclockEjector>
|
private class OverclockEjector : PatchImpl<OverclockEjector>
|
||||||
{
|
{
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(EjectorComponent), nameof(EjectorComponent.InternalUpdate))]
|
[HarmonyPatch(typeof(EjectorComponent), nameof(EjectorComponent.InternalUpdate))]
|
||||||
@@ -467,7 +537,7 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OverclockSilo: PatchImpl<OverclockSilo>
|
private class OverclockSilo : PatchImpl<OverclockSilo>
|
||||||
{
|
{
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(SiloComponent), nameof(SiloComponent.InternalUpdate))]
|
[HarmonyPatch(typeof(SiloComponent), nameof(SiloComponent.InternalUpdate))]
|
||||||
@@ -519,4 +589,53 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class UnlockMaxOrbitRadius : PatchImpl<UnlockMaxOrbitRadius>
|
||||||
|
{
|
||||||
|
protected override void OnEnable()
|
||||||
|
{
|
||||||
|
OnViewStarChange(null, null);
|
||||||
|
UnlockMaxOrbitRadiusValue.SettingChanged += OnViewStarChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDisable()
|
||||||
|
{
|
||||||
|
OnViewStarChange(null, null);
|
||||||
|
UnlockMaxOrbitRadiusValue.SettingChanged -= OnViewStarChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnViewStarChange(object o, EventArgs e)
|
||||||
|
{
|
||||||
|
var dysonEditor = UIRoot.instance?.uiGame?.dysonEditor;
|
||||||
|
if (dysonEditor == null || !dysonEditor.gameObject.activeSelf) return;
|
||||||
|
dysonEditor.selection?.onViewStarChange?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyTranspiler]
|
||||||
|
[HarmonyPatch(typeof(DysonSphere), nameof(DysonSphere.CheckLayerRadius))]
|
||||||
|
[HarmonyPatch(typeof(DysonSphere), nameof(DysonSphere.CheckSwarmRadius))]
|
||||||
|
[HarmonyPatch(typeof(DysonSphere), nameof(DysonSphere.QueryLayerRadius))]
|
||||||
|
[HarmonyPatch(typeof(DysonSphere), nameof(DysonSphere.QuerySwarmRadius))]
|
||||||
|
[HarmonyPatch(typeof(UIDEAddLayerDialogue), nameof(UIDEAddLayerDialogue.OnViewStarChange))]
|
||||||
|
[HarmonyPatch(typeof(UIDEAddSwarmDialogue), nameof(UIDEAddSwarmDialogue.OnViewStarChange))]
|
||||||
|
[HarmonyPatch(typeof(UIDysonEditor), nameof(UIDysonEditor.OnViewStarChange))]
|
||||||
|
[HarmonyPatch(typeof(UIDESwarmOrbitInfo), nameof(UIDESwarmOrbitInfo._OnInit))]
|
||||||
|
[HarmonyPatch(typeof(UIDysonOrbitPreview), nameof(UIDysonOrbitPreview.UpdateAscNodeGizmos))]
|
||||||
|
private static IEnumerable<CodeInstruction> MaxOrbitRadiusPatch_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
{
|
||||||
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(DysonSphere), nameof(DysonSphere.maxOrbitRadius)))
|
||||||
|
);
|
||||||
|
matcher.Repeat(m =>
|
||||||
|
{
|
||||||
|
m.Advance(1).InsertAndAdvance(
|
||||||
|
new CodeInstruction(OpCodes.Pop),
|
||||||
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(DysonSpherePatch), nameof(UnlockMaxOrbitRadiusValue))),
|
||||||
|
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(ConfigEntry<float>), nameof(ConfigEntry<float>.Value)))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return matcher.InstructionEnumeration();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -42,19 +42,21 @@ public static class GamePatch
|
|||||||
protected override void OnEnable()
|
protected override void OnEnable()
|
||||||
{
|
{
|
||||||
if (_savedDeterminators == null) return;
|
if (_savedDeterminators == null) return;
|
||||||
var abnormalLogic = GameMain.gameScenario.abnormalityLogic;
|
var abnormalLogic = GameMain.gameScenario?.abnormalityLogic;
|
||||||
|
if (abnormalLogic == null) return;
|
||||||
foreach (var p in _savedDeterminators)
|
foreach (var p in _savedDeterminators)
|
||||||
{
|
{
|
||||||
p.Value.OnUnregEvent();
|
p.Value.OnUnregEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
abnormalLogic.determinators = new Dictionary<int, AbnormalityDeterminator>();
|
abnormalLogic.determinators = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisable()
|
protected override void OnDisable()
|
||||||
{
|
{
|
||||||
if (_savedDeterminators == null) return;
|
if (_savedDeterminators == null) return;
|
||||||
var abnormalLogic = GameMain.gameScenario.abnormalityLogic;
|
var abnormalLogic = GameMain.gameScenario?.abnormalityLogic;
|
||||||
|
if (abnormalLogic?.determinators == null) return;
|
||||||
abnormalLogic.determinators = _savedDeterminators;
|
abnormalLogic.determinators = _savedDeterminators;
|
||||||
foreach (var p in _savedDeterminators)
|
foreach (var p in _savedDeterminators)
|
||||||
{
|
{
|
||||||
@@ -63,24 +65,24 @@ public static class GamePatch
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyBeforeGameSave")]
|
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.NotifyBeforeGameSave))]
|
||||||
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnAssemblerRecipePick")]
|
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.NotifyOnAssemblerRecipePick))]
|
||||||
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnGameBegin")]
|
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.NotifyOnGameBegin))]
|
||||||
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnMechaForgeTaskComplete")]
|
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.NotifyOnMechaForgeTaskComplete))]
|
||||||
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnUnlockTech")]
|
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.NotifyOnUnlockTech))]
|
||||||
[HarmonyPatch(typeof(AbnormalityLogic), "NotifyOnUseConsole")]
|
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.NotifyOnUseConsole))]
|
||||||
private static bool DisableAbnormalLogic()
|
private static bool DisableAbnormalLogic()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(AbnormalityLogic), "InitDeterminators")]
|
[HarmonyPatch(typeof(AbnormalityLogic), nameof(AbnormalityLogic.InitDeterminators))]
|
||||||
private static void DisableAbnormalDeterminators(AbnormalityLogic __instance)
|
private static void DisableAbnormalDeterminators(AbnormalityLogic __instance)
|
||||||
{
|
{
|
||||||
_savedDeterminators = __instance.determinators;
|
_savedDeterminators = __instance.determinators;
|
||||||
if (!AbnormalDisablerEnabled.Value) return;
|
if (!AbnormalDisablerEnabled.Value) return;
|
||||||
__instance.determinators = new Dictionary<int, AbnormalityDeterminator>();
|
__instance.determinators = [];
|
||||||
foreach (var p in _savedDeterminators)
|
foreach (var p in _savedDeterminators)
|
||||||
{
|
{
|
||||||
p.Value.OnUnregEvent();
|
p.Value.OnUnregEvent();
|
||||||
@@ -139,7 +141,7 @@ public static class GamePatch
|
|||||||
var pos = matcher.Pos;
|
var pos = matcher.Pos;
|
||||||
/* Remove Shift+F4 part of the method */
|
/* Remove Shift+F4 part of the method */
|
||||||
matcher.Start().RemoveInstructions(pos).MatchForward(false,
|
matcher.Start().RemoveInstructions(pos).MatchForward(false,
|
||||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(GameMain), "get_sandboxToolsEnabled")),
|
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(GameMain), nameof(GameMain.sandboxToolsEnabled))),
|
||||||
new CodeMatch(OpCodes.Ldc_I4_0),
|
new CodeMatch(OpCodes.Ldc_I4_0),
|
||||||
new CodeMatch(OpCodes.Ceq)
|
new CodeMatch(OpCodes.Ceq)
|
||||||
);
|
);
|
||||||
@@ -186,7 +188,7 @@ public static class GamePatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UnlockTech: PatchImpl<UnlockTech>
|
public class UnlockTech : PatchImpl<UnlockTech>
|
||||||
{
|
{
|
||||||
private static void UnlockTechRecursive(GameHistoryData history, [NotNull] TechProto techProto, int maxLevel = 10000)
|
private static void UnlockTechRecursive(GameHistoryData history, [NotNull] TechProto techProto, int maxLevel = 10000)
|
||||||
{
|
{
|
||||||
@@ -281,7 +283,7 @@ public static class GamePatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
history.VarifyTechQueue();
|
history.VerifyTechQueue();
|
||||||
if (history.currentTech != history.techQueue[0])
|
if (history.currentTech != history.techQueue[0])
|
||||||
{
|
{
|
||||||
history.currentTech = history.techQueue[0];
|
history.currentTech = history.techQueue[0];
|
||||||
@@ -296,7 +298,7 @@ public static class GamePatch
|
|||||||
matcher.MatchForward(false,
|
matcher.MatchForward(false,
|
||||||
new CodeMatch(OpCodes.Ldarg_0),
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UITechNode), nameof(UITechNode.tree))),
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UITechNode), nameof(UITechNode.tree))),
|
||||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(UITechTree), "get_selected"))
|
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(UITechTree), nameof(UITechTree.selected)))
|
||||||
);
|
);
|
||||||
var labels = matcher.Labels;
|
var labels = matcher.Labels;
|
||||||
matcher.Labels = null;
|
matcher.Labels = null;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using HarmonyLib;
|
|||||||
using UXAssist.Common;
|
using UXAssist.Common;
|
||||||
|
|
||||||
namespace CheatEnabler.Patches;
|
namespace CheatEnabler.Patches;
|
||||||
|
|
||||||
public static class PlanetPatch
|
public static class PlanetPatch
|
||||||
{
|
{
|
||||||
public static ConfigEntry<bool> WaterPumpAnywhereEnabled;
|
public static ConfigEntry<bool> WaterPumpAnywhereEnabled;
|
||||||
@@ -29,7 +30,7 @@ public static class PlanetPatch
|
|||||||
TerraformAnyway.Enable(false);
|
TerraformAnyway.Enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class WaterPumperPatch: PatchImpl<WaterPumperPatch>
|
private class WaterPumperPatch : PatchImpl<WaterPumperPatch>
|
||||||
{
|
{
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(BuildTool_BlueprintPaste), nameof(BuildTool_BlueprintPaste.CheckBuildConditions))]
|
[HarmonyPatch(typeof(BuildTool_BlueprintPaste), nameof(BuildTool_BlueprintPaste.CheckBuildConditions))]
|
||||||
@@ -51,8 +52,94 @@ public static class PlanetPatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TerraformAnyway: PatchImpl<TerraformAnyway>
|
private class TerraformAnyway : PatchImpl<TerraformAnyway>
|
||||||
{
|
{
|
||||||
|
[HarmonyTranspiler]
|
||||||
|
[HarmonyPatch(typeof(BuildTool_BlueprintPaste), nameof(BuildTool_BlueprintPaste.DetermineReforms))]
|
||||||
|
private static IEnumerable<CodeInstruction> BuildTool_BlueprintPaste_DetermineReforms_Patch(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
{
|
||||||
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(BuildTool), nameof(BuildTool.player))),
|
||||||
|
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Player), nameof(Player.sandCount))),
|
||||||
|
new CodeMatch(ci => ci.IsStloc())
|
||||||
|
).Advance(4).MatchForward(false,
|
||||||
|
new CodeMatch(ci => ci.IsLdloc()),
|
||||||
|
new CodeMatch(ci => ci.IsLdloc()),
|
||||||
|
new CodeMatch(OpCodes.Conv_I8),
|
||||||
|
new CodeMatch(ci => ci.opcode == OpCodes.Bge || ci.opcode == OpCodes.Bge_S)
|
||||||
|
);
|
||||||
|
var labels = matcher.Labels;
|
||||||
|
matcher.Labels = null;
|
||||||
|
matcher.RemoveInstructions(3);
|
||||||
|
matcher.Labels.AddRange(labels);
|
||||||
|
matcher.Opcode = OpCodes.Br;
|
||||||
|
return matcher.InstructionEnumeration();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyTranspiler]
|
||||||
|
[HarmonyPatch(typeof(BuildTool_Reform), nameof(BuildTool_Reform.RemoveBasePit))]
|
||||||
|
private static IEnumerable<CodeInstruction> BuildTool_Reform_RemoveBasePit_Patch(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
{
|
||||||
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(BuildTool_Reform), nameof(BuildTool_Reform.circlePointCount))),
|
||||||
|
new CodeMatch(ci => ci.opcode == OpCodes.Blt || ci.opcode == OpCodes.Blt_S)
|
||||||
|
).RemoveInstructions(2).InsertAndAdvance(
|
||||||
|
new CodeInstruction(OpCodes.Ldc_I4_0)
|
||||||
|
).MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Call, AccessTools.PropertyGetter(typeof(BuildTool), nameof(BuildTool.player))),
|
||||||
|
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Player), nameof(Player.sandCount))),
|
||||||
|
new CodeMatch(ci => ci.IsLdloc()),
|
||||||
|
new CodeMatch(OpCodes.Conv_I8),
|
||||||
|
new CodeMatch(OpCodes.Sub)
|
||||||
|
).Advance(6).InsertAndAdvance(
|
||||||
|
new CodeInstruction(OpCodes.Ldc_I8, 0L),
|
||||||
|
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Math), nameof(Math.Max), [typeof(long), typeof(long)]))
|
||||||
|
);
|
||||||
|
return matcher.InstructionEnumeration();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyTranspiler]
|
||||||
|
[HarmonyPatch(typeof(UIRemoveBasePitButton), nameof(UIRemoveBasePitButton.OnRemoveButtonClick))]
|
||||||
|
[HarmonyPatch(typeof(UIRemoveBasePitButton), nameof(UIRemoveBasePitButton._OnUpdate))]
|
||||||
|
private static IEnumerable<CodeInstruction> UIRemoveBasePitButton_OnRemoveButtonClick_Patch(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
{
|
||||||
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIRemoveBasePitButton), nameof(UIRemoveBasePitButton.pointCount))),
|
||||||
|
new CodeMatch(OpCodes.Sub),
|
||||||
|
new CodeMatch(OpCodes.Ldc_I4_0),
|
||||||
|
new CodeMatch(OpCodes.Clt)
|
||||||
|
);
|
||||||
|
if (matcher.IsValid)
|
||||||
|
{
|
||||||
|
matcher.RemoveInstructions(2).InsertAndAdvance(
|
||||||
|
new CodeInstruction(OpCodes.Ldc_I4_0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matcher.Start();
|
||||||
|
}
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIRemoveBasePitButton), nameof(UIRemoveBasePitButton.player))),
|
||||||
|
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Player), nameof(Player.sandCount))),
|
||||||
|
new CodeMatch(ci => ci.IsLdloc()),
|
||||||
|
new CodeMatch(OpCodes.Conv_I8),
|
||||||
|
new CodeMatch(OpCodes.Sub)
|
||||||
|
).Advance(6).InsertAndAdvance(
|
||||||
|
new CodeInstruction(OpCodes.Ldc_I8, 0L),
|
||||||
|
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Math), nameof(Math.Max), [typeof(long), typeof(long)]))
|
||||||
|
);
|
||||||
|
return matcher.InstructionEnumeration();
|
||||||
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(BuildTool_Reform), nameof(BuildTool_Reform.ReformAction))]
|
[HarmonyPatch(typeof(BuildTool_Reform), nameof(BuildTool_Reform.ReformAction))]
|
||||||
private static IEnumerable<CodeInstruction> BuildTool_Reform_ReformAction_Patch(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
private static IEnumerable<CodeInstruction> BuildTool_Reform_ReformAction_Patch(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
@@ -65,13 +152,13 @@ public static class PlanetPatch
|
|||||||
).RemoveInstructions(2).InsertAndAdvance(
|
).RemoveInstructions(2).InsertAndAdvance(
|
||||||
new CodeInstruction(OpCodes.Ldc_I4_0)
|
new CodeInstruction(OpCodes.Ldc_I4_0)
|
||||||
).MatchForward(false,
|
).MatchForward(false,
|
||||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Method(typeof(Player), "get_sandCount"))
|
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Player), nameof(Player.sandCount)))
|
||||||
).Advance(1).MatchForward(false,
|
).Advance(1).MatchForward(false,
|
||||||
new CodeMatch(OpCodes.Conv_I8),
|
new CodeMatch(OpCodes.Conv_I8),
|
||||||
new CodeMatch(OpCodes.Sub)
|
new CodeMatch(OpCodes.Sub)
|
||||||
).Advance(2).InsertAndAdvance(
|
).Advance(2).InsertAndAdvance(
|
||||||
new CodeInstruction(OpCodes.Ldc_I8, 0L),
|
new CodeInstruction(OpCodes.Ldc_I8, 0L),
|
||||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Math), "Max", [typeof(long), typeof(long)]))
|
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Math), nameof(Math.Max), [typeof(long), typeof(long)]))
|
||||||
);
|
);
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public static class PlayerPatch
|
|||||||
WarpWithoutSpaceWarpers.Enable(false);
|
WarpWithoutSpaceWarpers.Enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InstantHandCraft: PatchImpl<InstantHandCraft>
|
private class InstantHandCraft : PatchImpl<InstantHandCraft>
|
||||||
{
|
{
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(ForgeTask), MethodType.Constructor, typeof(int), typeof(int))]
|
[HarmonyPatch(typeof(ForgeTask), MethodType.Constructor, typeof(int), typeof(int))]
|
||||||
@@ -43,7 +43,7 @@ public static class PlayerPatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InstantTeleport: PatchImpl<InstantTeleport>
|
private class InstantTeleport : PatchImpl<InstantTeleport>
|
||||||
{
|
{
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(UIGlobemap), nameof(UIGlobemap._OnUpdate))]
|
[HarmonyPatch(typeof(UIGlobemap), nameof(UIGlobemap._OnUpdate))]
|
||||||
@@ -66,7 +66,7 @@ public static class PlayerPatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class WarpWithoutSpaceWarpers: PatchImpl<WarpWithoutSpaceWarpers>
|
private class WarpWithoutSpaceWarpers : PatchImpl<WarpWithoutSpaceWarpers>
|
||||||
{
|
{
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(Mecha), nameof(Mecha.HasWarper))]
|
[HarmonyPatch(typeof(Mecha), nameof(Mecha.HasWarper))]
|
||||||
@@ -75,7 +75,7 @@ public static class PlayerPatch
|
|||||||
__result = true;
|
__result = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(Mecha), nameof(Mecha.UseWarper))]
|
[HarmonyPatch(typeof(Mecha), nameof(Mecha.UseWarper))]
|
||||||
private static void Mecha_UseWarper_Postfix(ref bool __result)
|
private static void Mecha_UseWarper_Postfix(ref bool __result)
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ public static class ResourcePatch
|
|||||||
FastMining.Enable(false);
|
FastMining.Enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InfiniteResource: PatchImpl<InfiniteResource>
|
private class InfiniteResource : PatchImpl<InfiniteResource>
|
||||||
{
|
{
|
||||||
|
static private readonly float InfiniteResourceRate = 0f;
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTick), typeof(long), typeof(bool))]
|
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTick), typeof(long), typeof(bool))]
|
||||||
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTick), typeof(long), typeof(bool), typeof(int), typeof(int), typeof(int))]
|
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic._miner_parallel))]
|
||||||
[HarmonyPatch(typeof(ItemProto), nameof(ItemProto.GetPropValue))]
|
|
||||||
[HarmonyPatch(typeof(PlanetTransport), nameof(PlanetTransport.GameTick))]
|
[HarmonyPatch(typeof(PlanetTransport), nameof(PlanetTransport.GameTick))]
|
||||||
[HarmonyPatch(typeof(UIChartAstroResource), nameof(UIChartAstroResource.CalculateMaxAmount))]
|
[HarmonyPatch(typeof(UIChartAstroResource), nameof(UIChartAstroResource.CalculateMaxAmount))]
|
||||||
[HarmonyPatch(typeof(UIChartVeinGroup), nameof(UIChartVeinGroup.CalculateMaxAmount))]
|
[HarmonyPatch(typeof(UIChartVeinGroup), nameof(UIChartVeinGroup.CalculateMaxAmount))]
|
||||||
@@ -42,48 +42,81 @@ public static class ResourcePatch
|
|||||||
[HarmonyPatch(typeof(UIControlPanelVeinCollectorPanel), nameof(UIControlPanelVeinCollectorPanel._OnUpdate))]
|
[HarmonyPatch(typeof(UIControlPanelVeinCollectorPanel), nameof(UIControlPanelVeinCollectorPanel._OnUpdate))]
|
||||||
[HarmonyPatch(typeof(UIMinerWindow), nameof(UIMinerWindow._OnUpdate))]
|
[HarmonyPatch(typeof(UIMinerWindow), nameof(UIMinerWindow._OnUpdate))]
|
||||||
[HarmonyPatch(typeof(UIMiningUpgradeLabel), nameof(UIMiningUpgradeLabel.Update))]
|
[HarmonyPatch(typeof(UIMiningUpgradeLabel), nameof(UIMiningUpgradeLabel.Update))]
|
||||||
|
[HarmonyPatch(typeof(UIVeinCollectorPanel), nameof(UIVeinCollectorPanel._OnUpdate))]
|
||||||
|
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
{
|
||||||
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(ci => (ci.opcode == OpCodes.Ldfld || ci.opcode == OpCodes.Ldflda) && ci.OperandIs(AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.miningCostRate))))
|
||||||
|
).Repeat(codeMatcher =>
|
||||||
|
{
|
||||||
|
if (codeMatcher.Instruction.opcode == OpCodes.Ldfld)
|
||||||
|
{
|
||||||
|
codeMatcher.RemoveInstruction().InsertAndAdvance(
|
||||||
|
new CodeInstruction(OpCodes.Pop),
|
||||||
|
new CodeInstruction(OpCodes.Ldc_R4, InfiniteResourceRate)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codeMatcher.RemoveInstruction().InsertAndAdvance(
|
||||||
|
new CodeInstruction(OpCodes.Pop),
|
||||||
|
new CodeInstruction(OpCodes.Ldsflda, AccessTools.Field(typeof(InfiniteResource), nameof(InfiniteResourceRate)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return matcher.InstructionEnumeration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FastMining : PatchImpl<FastMining>
|
||||||
|
{
|
||||||
|
static private readonly float FastMiningSpeed = 2400f;
|
||||||
|
|
||||||
|
[HarmonyTranspiler]
|
||||||
|
[HarmonyPatch(typeof(AstroResourceStatPlan), nameof(AstroResourceStatPlan.AddPlanetResources))]
|
||||||
|
[HarmonyPatch(typeof(BuildingGizmo), nameof(BuildingGizmo.Update))]
|
||||||
|
[HarmonyPatch(typeof(FactorySystem), nameof(FactorySystem.GameTick), typeof(long), typeof(bool))]
|
||||||
|
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic._miner_parallel))]
|
||||||
|
[HarmonyPatch(typeof(ItemProto), nameof(ItemProto.GetPropValue))]
|
||||||
|
[HarmonyPatch(typeof(PlanetTransport), nameof(PlanetTransport.GameTick))]
|
||||||
|
[HarmonyPatch(typeof(ProductionExtraInfoCalculator), nameof(ProductionExtraInfoCalculator.CalculateFactory))]
|
||||||
|
[HarmonyPatch(typeof(UIChartAstroResource), nameof(UIChartAstroResource.CalculateMaxAmount))]
|
||||||
|
[HarmonyPatch(typeof(UIChartVeinGroup), nameof(UIChartVeinGroup.CalculateMaxAmount))]
|
||||||
|
[HarmonyPatch(typeof(UIControlPanelStationStorage), nameof(UIControlPanelStationStorage.RefreshValues))]
|
||||||
|
[HarmonyPatch(typeof(UIControlPanelVeinCollectorPanel), nameof(UIControlPanelVeinCollectorPanel._OnUpdate))]
|
||||||
|
[HarmonyPatch(typeof(UIMinerWindow), nameof(UIMinerWindow._OnUpdate))]
|
||||||
|
[HarmonyPatch(typeof(UIMiningUpgradeLabel), nameof(UIMiningUpgradeLabel.Update))]
|
||||||
|
[HarmonyPatch(typeof(UIPlanetDetail), nameof(UIPlanetDetail.OnPlanetDataSet))]
|
||||||
|
[HarmonyPatch(typeof(UIPlanetDetail), nameof(UIPlanetDetail.RefreshDynamicProperties))]
|
||||||
|
[HarmonyPatch(typeof(UIReferenceSpeedTip), nameof(UIReferenceSpeedTip.AddEntryDataWithFactory))]
|
||||||
|
[HarmonyPatch(typeof(UIStarDetail), nameof(UIStarDetail.OnStarDataSet))]
|
||||||
|
[HarmonyPatch(typeof(UIStarDetail), nameof(UIStarDetail.RefreshDynamicProperties))]
|
||||||
[HarmonyPatch(typeof(UIStationStorage), nameof(UIStationStorage.RefreshValues))]
|
[HarmonyPatch(typeof(UIStationStorage), nameof(UIStationStorage.RefreshValues))]
|
||||||
[HarmonyPatch(typeof(UIVeinCollectorPanel), nameof(UIVeinCollectorPanel._OnUpdate))]
|
[HarmonyPatch(typeof(UIVeinCollectorPanel), nameof(UIVeinCollectorPanel._OnUpdate))]
|
||||||
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
{
|
{
|
||||||
var matcher = new CodeMatcher(instructions, generator);
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
matcher.MatchForward(false,
|
matcher.MatchForward(false,
|
||||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.miningCostRate)))
|
new CodeMatch(ci => (ci.opcode == OpCodes.Ldfld || ci.opcode == OpCodes.Ldflda) && ci.OperandIs(AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.miningSpeedScale))))
|
||||||
).Repeat(codeMatcher =>
|
).Repeat(codeMatcher =>
|
||||||
codeMatcher.RemoveInstruction().InsertAndAdvance(
|
{
|
||||||
new CodeInstruction(OpCodes.Pop),
|
if (codeMatcher.Instruction.opcode == OpCodes.Ldfld)
|
||||||
new CodeInstruction(OpCodes.Ldc_R4, 0f)
|
{
|
||||||
)
|
codeMatcher.RemoveInstruction().InsertAndAdvance(
|
||||||
);
|
new CodeInstruction(OpCodes.Pop),
|
||||||
return matcher.InstructionEnumeration();
|
new CodeInstruction(OpCodes.Ldc_R4, FastMiningSpeed)
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
private class FastMining: PatchImpl<FastMining>
|
{
|
||||||
{
|
codeMatcher.RemoveInstruction().InsertAndAdvance(
|
||||||
[HarmonyTranspiler]
|
new CodeInstruction(OpCodes.Pop),
|
||||||
[HarmonyPatch(typeof(FactorySystem), "GameTick", typeof(long), typeof(bool))]
|
new CodeInstruction(OpCodes.Ldsflda, AccessTools.Field(typeof(FastMining), nameof(FastMiningSpeed)))
|
||||||
[HarmonyPatch(typeof(FactorySystem), "GameTick", typeof(long), typeof(bool), typeof(int), typeof(int), typeof(int))]
|
);
|
||||||
[HarmonyPatch(typeof(ItemProto), "GetPropValue")]
|
}
|
||||||
[HarmonyPatch(typeof(PlanetTransport), "GameTick")]
|
}
|
||||||
[HarmonyPatch(typeof(UIMinerWindow), "_OnUpdate")]
|
|
||||||
[HarmonyPatch(typeof(UIMiningUpgradeLabel), "Update")]
|
|
||||||
[HarmonyPatch(typeof(UIPlanetDetail), "OnPlanetDataSet")]
|
|
||||||
[HarmonyPatch(typeof(UIPlanetDetail), "RefreshDynamicProperties")]
|
|
||||||
[HarmonyPatch(typeof(UIStarDetail), "OnStarDataSet")]
|
|
||||||
[HarmonyPatch(typeof(UIStarDetail), "RefreshDynamicProperties")]
|
|
||||||
[HarmonyPatch(typeof(UIStationStorage), "RefreshValues")]
|
|
||||||
[HarmonyPatch(typeof(UIVeinCollectorPanel), "_OnUpdate")]
|
|
||||||
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
||||||
{
|
|
||||||
var matcher = new CodeMatcher(instructions, generator);
|
|
||||||
matcher.MatchForward(false,
|
|
||||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.miningSpeedScale)))
|
|
||||||
).Repeat(codeMatcher =>
|
|
||||||
codeMatcher.RemoveInstruction().InsertAndAdvance(
|
|
||||||
new CodeInstruction(OpCodes.Pop),
|
|
||||||
new CodeInstruction(OpCodes.Ldc_R4, 2400f)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,125 +1,151 @@
|
|||||||
# CheatEnabler
|
# CheatEnabler
|
||||||
|
|
||||||
#### Add various cheat functions while disabling abnormal determinants
|
<details>
|
||||||
#### 添加一些作弊功能,同时屏蔽异常检测
|
<summary>Read me in English</summary>
|
||||||
|
|
||||||
|
***Add various cheat functions while disabling abnormal determinants***
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
* Config panel is unified with UXAssist.
|
* Config panel is unified with UXAssist.
|
||||||
* There are also buttons on title screen and planet minimap area to call up the config panel.
|
* There are also buttons on title screen and planet minimap area to call up the config panel.
|
||||||
* Features:
|
* Features:
|
||||||
+ General:
|
* General:
|
||||||
+ Enable Dev Shortcuts (check config panel for usage)
|
* Enable Dev Shortcuts (check config panel for usage)
|
||||||
+ Disable Abnormal Checks
|
* Disable Abnormal Checks
|
||||||
+ Unlock techs with key-modifiers (Ctrl/Alt/Shift)
|
* Unlock techs with key-modifiers (Ctrl/Alt/Shift)
|
||||||
+ Remove all metadata consumption records
|
* Remove all metadata consumption records
|
||||||
+ Remove metadata consumption record in current game
|
* Remove metadata consumption record in current game
|
||||||
+ Clear metadata flag which bans achievements
|
* Clear metadata flag which bans achievements
|
||||||
+ Assign gamesave to currrnet account
|
* Assign gamesave to currrnet account
|
||||||
+ Factory:
|
* Factory:
|
||||||
+ Finish build immediately
|
* Finish build immediately
|
||||||
+ Architect mode (Infinite buildings)
|
* Architect mode (Infinite buildings)
|
||||||
+ Build without condition
|
* Build without condition
|
||||||
+ No collision
|
* No collision
|
||||||
+ Belt signal item generation
|
* Belt signal item generation
|
||||||
- Count generations as production in statistics
|
* Count generations as production in statistics
|
||||||
- Count removals as consumption in statistics
|
* Count removals as consumption in statistics
|
||||||
- Count all raws and intermediates in statistics
|
* Count all raws and intermediates in statistics
|
||||||
- Belt signal alt format
|
* Belt signal alt format
|
||||||
+ Increase maximum power usage in Logistic Stations and Advanced Mining Machines
|
* Increase maximum power usage in Logistic Stations and Advanced Mining Machines
|
||||||
- Logistic Stations: Increased max charging power to 3GW(ILS) and 600MW(PLS) (10x of original)
|
* Logistic Stations: Increased max charging power to 3GW(ILS) and 600MW(PLS) (10x of original)
|
||||||
- Advanced Mining Machines: Increased max mining speed to 1000%
|
* Advanced Mining Machines: Increased max mining speed to 1000%
|
||||||
+ Retrieve/Place items from/to remote planets on logistics control panel
|
* Retrieve/Place items from/to remote planets on logistics control panel
|
||||||
+ Remove space limit between wind turbines and solar panels
|
* Remove space limit between wind turbines and solar panels
|
||||||
+ Wind Turbines do global power coverage
|
* Wind Turbines do global power coverage
|
||||||
+ Boost power generations for kinds of power generators
|
* Boost power generations for kinds of power generators
|
||||||
+ Planet:
|
* Planet:
|
||||||
+ Instant hand-craft
|
* Instant hand-craft
|
||||||
+ Infinite Natural Resources
|
* Infinite Natural Resources
|
||||||
+ Fast Mining
|
* Fast Mining
|
||||||
+ Pump Anywhere
|
* Pump Anywhere
|
||||||
+ Terraform without enought soil piles
|
* Terraform without enought soil piles
|
||||||
+ Instant teleport (like that in Sandbox mode)
|
* Instant teleport (like that in Sandbox mode)
|
||||||
+ Dyson Sphere:
|
* Dyson Sphere:
|
||||||
+ Skip bullet period
|
* Skip bullet period
|
||||||
+ Skip absorption period
|
* Skip absorption period
|
||||||
+ Quick absorb
|
* Quick absorb
|
||||||
+ Eject anyway
|
* Eject anyway
|
||||||
+ Complete Dyson Sphere Shells instantly
|
* Unlock Dyson Sphere max orbit radius
|
||||||
+ Mecha/Combat:
|
* Complete Dyson Sphere Shells instantly
|
||||||
+ Mecha and Drones/Fleets invicible
|
* Remove all frames on Dyson Sphere
|
||||||
+ Buildings invicible
|
* Buttons for creating illegal Dyson Sphere Shells, you must enable `IllegalDysonShellFunctionsEnabled` of `DysonSphere` section in config to see the last 2 buttons.
|
||||||
+ Enable warp without space warpers
|
* Generate an illegal dyson shell
|
||||||
+ Teleport to outer space
|
* Keep max production shells and remove others
|
||||||
+ Teleport to selected astronomical
|
* Duplicate shells from that with highest production
|
||||||
|
* Mecha/Combat:
|
||||||
|
* Mecha and Drones/Fleets invicible
|
||||||
|
* Buildings invicible
|
||||||
|
* Enable warp without space warpers
|
||||||
|
* Teleport to outer space
|
||||||
|
* Teleport to selected astronomical
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
* Please upgrade `BepInEx` 5.4.21 or later if using with [BlueprintTweaks](https://dsp.thunderstore.io/package/kremnev8/BlueprintTweaks/) to avoid possible conflicts.
|
* Please upgrade `BepInEx` 5.4.21 or later if using with [BlueprintTweaks](https://dsp.thunderstore.io/package/kremnev8/BlueprintTweaks/) to avoid possible conflicts.
|
||||||
+ You can download `BepInEx` [here](https://github.com/bepinex/bepinex/releases/latest)(choose x64 edition).
|
* You can download [BepInEx here](https://github.com/bepinex/bepinex/releases/latest)(choose x64 edition).
|
||||||
+ If using with r2modman, you can upgrade `BepInEx` by clicking `Settings` -> `Browse profile folder`, then extract downloaded zip to the folder and overwrite existing files.
|
* If using with r2modman, you can upgrade `BepInEx` by clicking `Settings` -> `Browse profile folder`, then extract downloaded zip to the folder and overwrite existing files.
|
||||||
|
|
||||||
## CREDITS
|
## CREDITS
|
||||||
|
|
||||||
* [Dyson Sphere Program](https://store.steampowered.com/app/1366540): The great game
|
* [Dyson Sphere Program](https://store.steampowered.com/app/1366540): The great game
|
||||||
* [BepInEx](https://bepinex.dev/): Base modding framework
|
* [BepInEx](https://bepinex.dev/): Base modding framework
|
||||||
* [Multifunction_mod](https://github.com/blacksnipebiu/Multifunction_mod): Some cheat functions
|
* [Multifunction_mod](https://github.com/blacksnipebiu/Multifunction_mod): Some cheat functions
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>中文读我</summary>
|
||||||
|
|
||||||
|
***添加一些作弊功能,同时屏蔽异常检测***
|
||||||
|
|
||||||
## 使用说明
|
## 使用说明
|
||||||
|
|
||||||
* 配置面板复用UXAssist
|
* 配置面板复用UXAssist
|
||||||
* 标题界面和行星小地图旁也有按钮呼出主面板
|
* 标题界面和行星小地图旁也有按钮呼出主面板
|
||||||
* 功能:
|
* 功能:
|
||||||
+ 常规:
|
* 常规:
|
||||||
+ 启用开发模式快捷键(使用说明见设置面板)
|
* 启用开发模式快捷键(使用说明见设置面板)
|
||||||
+ 屏蔽异常检测
|
* 屏蔽异常检测
|
||||||
+ 使用组合键解锁科技(Ctrl/Alt/Shift)
|
* 使用组合键解锁科技(Ctrl/Alt/Shift)
|
||||||
+ 移除所有元数据消耗记录
|
* 移除所有元数据消耗记录
|
||||||
+ 移除当前存档的元数据消耗记录
|
* 移除当前存档的元数据消耗记录
|
||||||
+ 解除当前存档因使用元数据导致的成就限制
|
* 解除当前存档因使用元数据导致的成就限制
|
||||||
+ 将游戏存档绑定给当前账号
|
* 将游戏存档绑定给当前账号
|
||||||
+ 工厂:
|
* 工厂:
|
||||||
+ 建造秒完成
|
* 建造秒完成
|
||||||
+ 建筑师模式(无限建筑)
|
* 建筑师模式(无限建筑)
|
||||||
+ 无条件建造
|
* 无条件建造
|
||||||
+ 无碰撞
|
* 无碰撞
|
||||||
+ 传送带信号物品生成
|
* 传送带信号物品生成
|
||||||
- 统计信息里将生成计算为产物
|
* 统计信息里将生成计算为产物
|
||||||
- 统计信息里将移除计算为消耗
|
* 统计信息里将移除计算为消耗
|
||||||
- 统计面板中计算所有原材料和中间产物
|
* 统计面板中计算所有原材料和中间产物
|
||||||
- 传送带信号替换格式
|
* 传送带信号替换格式
|
||||||
+ 提升物流塔和大型采矿机的最大功耗
|
* 提升物流塔和大型采矿机的最大功耗
|
||||||
- 物流塔:将最大充电功率提高到3GW(星际物流塔)和600MW(行星物流塔)(原来的10倍)
|
* 物流塔:将最大充电功率提高到3GW(星际物流塔)和600MW(行星物流塔)(原来的10倍)
|
||||||
- 大型采矿机:将最大采矿速度提高到1000%
|
* 大型采矿机:将最大采矿速度提高到1000%
|
||||||
+ 在物流总控面板上可以从非本地行星取放物品
|
* 在物流总控面板上可以从非本地行星取放物品
|
||||||
+ 风力发电机和太阳能板无间距限制
|
* 风力发电机和太阳能板无间距限制
|
||||||
+ 风力涡轮机供电覆盖全球
|
* 风力涡轮机供电覆盖全球
|
||||||
+ 提升各种发电设备发电量
|
* 提升各种发电设备发电量
|
||||||
+ 行星:
|
* 行星:
|
||||||
+ 快速手动制造
|
* 快速手动制造
|
||||||
+ 自然资源采集不消耗
|
* 自然资源采集不消耗
|
||||||
+ 高速采集
|
* 高速采集
|
||||||
+ 平地抽水
|
* 平地抽水
|
||||||
+ 沙土不够时依然可以整改地形
|
* 沙土不够时依然可以整改地形
|
||||||
+ 快速传送(和沙盒模式一样)
|
* 快速传送(和沙盒模式一样)
|
||||||
+ 戴森球:
|
* 戴森球:
|
||||||
+ 跳过子弹阶段
|
* 跳过子弹阶段
|
||||||
+ 跳过吸收阶段
|
* 跳过吸收阶段
|
||||||
+ 快速吸收
|
* 快速吸收
|
||||||
+ 全球弹射
|
* 全球弹射
|
||||||
+ 立即完成戴森壳建造
|
* 解锁戴森球最大轨道半径
|
||||||
+ 机甲/战斗:
|
* 立即完成戴森壳建造
|
||||||
+ 机甲和战斗无人机无敌
|
* 移除戴森球上的所有框架
|
||||||
+ 建筑无敌
|
* 用于制作仙术戴森壳的按钮,你必须在设置文件里开启`DysonSphere`分类的`IllegalDysonShellFunctionsEnabled`才能看到后面两个按钮
|
||||||
+ 无需空间翘曲器即可曲速飞行
|
* 生成单层仙术戴森壳
|
||||||
+ 传送到外太空
|
* 保留发电量最高的戴森壳并移除其他戴森壳
|
||||||
+ 传送到选定的天体
|
* 从发电量最高的壳复制戴森壳
|
||||||
|
* 机甲/战斗:
|
||||||
|
* 机甲和战斗无人机无敌
|
||||||
|
* 建筑无敌
|
||||||
|
* 无需空间翘曲器即可曲速飞行
|
||||||
|
* 传送到外太空
|
||||||
|
* 传送到选定的天体
|
||||||
|
|
||||||
## 注意事项
|
## 注意事项
|
||||||
|
|
||||||
* 如果和[BlueprintTweaks](https://dsp.thunderstore.io/package/kremnev8/BlueprintTweaks/)一起使用,请升级`BepInEx`到5.4.21或更高版本,以避免可能的冲突
|
* 如果和[BlueprintTweaks](https://dsp.thunderstore.io/package/kremnev8/BlueprintTweaks/)一起使用,请升级`BepInEx`到5.4.21或更高版本,以避免可能的冲突
|
||||||
+ 你可以在[这里](https://github.com/bepinex/bepinex/releases/latest)(选择x64版本)下载`BepInEx`
|
* 你可以在[这里](https://github.com/bepinex/bepinex/releases/latest)(选择x64版本)下载`BepInEx`
|
||||||
+ 如果使用r2modman,你可以点击`Settings` -> `Browse profile folder`,然后将下载的zip解压到该文件夹并覆盖现有文件
|
* 如果使用r2modman,你可以点击`Settings` -> `Browse profile folder`,然后将下载的zip解压到该文件夹并覆盖现有文件
|
||||||
|
|
||||||
## 鸣谢
|
## 鸣谢
|
||||||
|
|
||||||
* [戴森球计划](https://store.steampowered.com/app/1366540): 伟大的游戏
|
* [戴森球计划](https://store.steampowered.com/app/1366540): 伟大的游戏
|
||||||
* [BepInEx](https://bepinex.dev/): 基础模组框架
|
* [BepInEx](https://bepinex.dev/): 基础模组框架
|
||||||
* [Multifunction_mod](https://github.com/blacksnipebiu/Multifunction_mod): 一些作弊功能
|
* [Multifunction_mod](https://github.com/blacksnipebiu/Multifunction_mod): 一些作弊功能
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using CheatEnabler.Patches;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UXAssist.UI;
|
using UXAssist.UI;
|
||||||
using UXAssist.Common;
|
using UXAssist.Common;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace CheatEnabler;
|
namespace CheatEnabler;
|
||||||
|
|
||||||
@@ -38,13 +39,17 @@ public static class UIConfigWindow
|
|||||||
I18N.Add("Build without condition", "Build without condition check", "无条件建造");
|
I18N.Add("Build without condition", "Build without condition check", "无条件建造");
|
||||||
I18N.Add("No collision", "No collision", "无碰撞");
|
I18N.Add("No collision", "No collision", "无碰撞");
|
||||||
I18N.Add("Belt signal generator", "Belt signal generator", "传送带信号物品生成");
|
I18N.Add("Belt signal generator", "Belt signal generator", "传送带信号物品生成");
|
||||||
|
I18N.Add("Count proliferators used for raws/intermediates and finished products", "Use proliferators for raws/intermediates and finished products", "原料、中间产物以及成品使用增产剂");
|
||||||
|
I18N.Add("Count proliferators used for raws/intermediates and finished products tips",
|
||||||
|
"Following items use extra products: Titanium Alloy, Prism, Frame Material, Proliferator Mk.II, Proliferator Mk.III, Magnetic Coil, Electric Motor, Electromagnetic Turbine, Super-magnetic Ring, Circuit Board, Thruster, Reinforced Thruster, Plasma Exciter, Particle Broadband, Graviton Lens, Quantum Chip, Annihilation Constraint Sphere, Deuteron Fuel Rod, Space Warper, Dyson Sphere Component, Small Carrier Rocket, Electromagnetic Matrix, Structure Matrix, Information Matrix, Gravity Matrix, Universe Matrix\nFollowing items does not use proliferators: Casimir Crystal, Energy Matrix\nOther items use speed up production.",
|
||||||
|
"以下物品使用额外产出: 钛合金, 棱镜, 框架材料, 增产剂 Mk.II, 增产剂 Mk.III, 磁线圈, 电动机, 电磁涡轮, 超级磁场环, 电路板, 推进器, 加力推进器, 电浆激发器, 粒子宽带, 引力透镜, 量子芯片, 湮灭约束球, 氘核燃料棒, 空间翘曲器, 戴森球组件, 小型运载火箭, 电磁矩阵, 结构矩阵, 信息矩阵, 引力矩阵, 宇宙矩阵\n以下物品不使用增产剂: 卡西米尔晶体, 能量矩阵\n其他物品使用加速生产");
|
||||||
I18N.Add("Belt signal alt format", "Belt signal alt format", "传送带信号替换格式");
|
I18N.Add("Belt signal alt format", "Belt signal alt format", "传送带信号替换格式");
|
||||||
I18N.Add("Belt signal alt format tips",
|
I18N.Add("Belt signal alt format tips",
|
||||||
"Belt signal number format alternative format:\n AAAABC by default\n BCAAAA as alternative\nAAAA=generation speed in minutes, B=proliferate points, C=stack count",
|
"Belt signal number format alternative format:\n AAAABC by default\n BCAAAA as alternative\nAAAA=generation speed in minutes, B=proliferate points, C=stack count",
|
||||||
"传送带信号物品生成数量格式:\n 默认为AAAABC\n 勾选替换为BCAAAA\nAAAA=生成速度,B=增产点数,C=堆叠数量");
|
"传送带信号物品生成数量格式:\n 默认为AAAABC\n 勾选替换为BCAAAA\nAAAA=生成速度,B=增产点数,C=堆叠数量");
|
||||||
I18N.Add("Count generations as production in statistics", "Count generations as production in statistics", "统计信息里将生成计算为产物");
|
I18N.Add("Count generations as production in statistics", "Count generations as production in statistics", "统计信息里将生成计算为产物");
|
||||||
I18N.Add("Count removals as consumption in statistics", "Count removals as consumption in statistics", "统计信息里将移除计算为消耗");
|
I18N.Add("Count removals as consumption in statistics", "Count removals as consumption in statistics", "统计信息里将移除计算为消耗");
|
||||||
I18N.Add("Count all raws and intermediates in statistics","Count all raw materials in statistics", "统计信息里计算所有原料和中间产物");
|
I18N.Add("Count all raws and intermediates in statistics", "Count all raw materials in statistics", "统计信息里计算所有原料和中间产物");
|
||||||
I18N.Add("Remove power space limit", "Remove space limit for winds and geothermals", "移除风力发电和地热发电的间距限制");
|
I18N.Add("Remove power space limit", "Remove space limit for winds and geothermals", "移除风力发电和地热发电的间距限制");
|
||||||
I18N.Add("Boost wind power", "Boost wind power(x100,000)", "提升风力发电(x100,000)");
|
I18N.Add("Boost wind power", "Boost wind power(x100,000)", "提升风力发电(x100,000)");
|
||||||
I18N.Add("Boost solar power", "Boost solar power(x100,000)", "提升太阳能发电(x100,000)");
|
I18N.Add("Boost solar power", "Boost solar power(x100,000)", "提升太阳能发电(x100,000)");
|
||||||
@@ -52,18 +57,30 @@ public static class UIConfigWindow
|
|||||||
I18N.Add("Boost fuel power 2", "(x20,000 for deuteron, x10,000 for antimatter)", "(氘核燃料棒x20,000,反物质燃料棒x10,000)");
|
I18N.Add("Boost fuel power 2", "(x20,000 for deuteron, x10,000 for antimatter)", "(氘核燃料棒x20,000,反物质燃料棒x10,000)");
|
||||||
I18N.Add("Wind Turbines do global power coverage", "Wind Turbines do global power coverage", "风力涡轮机供电覆盖全球");
|
I18N.Add("Wind Turbines do global power coverage", "Wind Turbines do global power coverage", "风力涡轮机供电覆盖全球");
|
||||||
I18N.Add("Boost geothermal power", "Boost geothermal power(x50,000)", "提升地热发电(x50,000)");
|
I18N.Add("Boost geothermal power", "Boost geothermal power(x50,000)", "提升地热发电(x50,000)");
|
||||||
I18N.Add("Increase maximum power usage in Logistic Stations and Advanced Mining Machines", "Increase maximum power usage in Logistic Stations and Advanced Mining Machines", "提升物流塔和大型采矿机的最大功耗");
|
I18N.Add("Increase maximum power usage in Logistic Stations and Advanced Mining Machines", "Increase maximum power usage in Logistic Stations and Advanced Mining Machines",
|
||||||
|
"提升物流塔和大型采矿机的最大功耗");
|
||||||
I18N.Add("Retrieve/Place items from/to remote planets on logistics control panel", "Retrieve/Place items from/to remote planets on logistics control panel", "在物流总控面板上可以从非本地行星取放物品");
|
I18N.Add("Retrieve/Place items from/to remote planets on logistics control panel", "Retrieve/Place items from/to remote planets on logistics control panel", "在物流总控面板上可以从非本地行星取放物品");
|
||||||
I18N.Add("Infinite Natural Resources", "Infinite natural resources", "自然资源采集不消耗");
|
I18N.Add("Infinite Natural Resources", "Infinite natural resources", "自然资源采集不消耗");
|
||||||
I18N.Add("Fast Mining", "Fast mining", "高速采集");
|
I18N.Add("Fast Mining", "Fast mining", "高速采集");
|
||||||
I18N.Add("Pump Anywhere", "Pump anywhere", "平地抽水");
|
I18N.Add("Pump Anywhere", "Pump anywhere", "平地抽水");
|
||||||
I18N.Add("Skip bullet period", "Skip bullet period", "跳过子弹阶段");
|
I18N.Add("Skip bullet period", "Skip bullet period", "跳过子弹阶段");
|
||||||
|
I18N.Add("Fire all bullets at once", "Fire all bullets at once", "一次弹射所有太阳帆");
|
||||||
I18N.Add("Skip absorption period", "Skip absorption period", "跳过吸收阶段");
|
I18N.Add("Skip absorption period", "Skip absorption period", "跳过吸收阶段");
|
||||||
I18N.Add("Quick absorb", "Quick absorb", "快速吸收");
|
I18N.Add("Quick absorb", "Quick absorb", "快速吸收");
|
||||||
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("Unlock Dyson Sphere max orbit radius", "Unlock Dyson Sphere max orbit radius", "解锁戴森球最大轨道半径");
|
||||||
I18N.Add("Complete Dyson Sphere shells instantly", "Complete Dyson Sphere shells instantly", "立即完成戴森壳建造");
|
I18N.Add("Complete Dyson Sphere shells instantly", "Complete Dyson Sphere shells instantly", "立即完成戴森壳建造");
|
||||||
|
I18N.Add("Remove all frames on Dyson Sphere", "Remove all frames on Dyson Sphere", "移除戴森球上的所有框架");
|
||||||
|
I18N.Add("Generate illegal dyson shell", "Generate an illegal dyson shell (!!1st shell layer will be replaced!!)", "生成单层仙术戴森壳(!!会先删除第一层戴森壳!!)");
|
||||||
|
I18N.Add("Generate illegal dyson shell 2", "Generate illegal dyson shells for all layers without nodes and shells", "为所有没有节点和壳的层级生成仙术戴森壳");
|
||||||
|
I18N.Add("Keep max production shells and remove others", "Keep max production shells and remove others", "保留发电量最高的戴森壳并移除其他戴森壳");
|
||||||
|
I18N.Add("Duplicate shells from that with highest production", "Duplicate shells from that with highest production", "从发电量最高的壳复制戴森壳");
|
||||||
|
I18N.Add("Generate illegal dyson shell quickly", "Generate illegal dyson shell quickly", "快速生成仙术戴森壳");
|
||||||
|
I18N.Add("Shells count", "Shells count", "壳面数量");
|
||||||
|
I18N.Add("WARNING: This operation can be very slow, continue?", "WARNING: This operation can be very slow, continue?", "警告:此操作可能非常慢,继续吗?");
|
||||||
|
I18N.Add("WARNING: This operation is DANGEROUS, continue?", "WARNING: This operation is DANGEROUS, continue?", "警告:此操作非常危险,继续吗?");
|
||||||
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 hand-craft", "Instant hand-craft", "快速手动制造");
|
I18N.Add("Instant hand-craft", "Instant hand-craft", "快速手动制造");
|
||||||
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)", "快速传送(和沙盒模式一样)");
|
||||||
@@ -77,6 +94,57 @@ public static class UIConfigWindow
|
|||||||
MyConfigWindow.OnUpdateUI += UpdateUI;
|
MyConfigWindow.OnUpdateUI += UpdateUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MaxOrbitRadiusValueMapper : MyWindow.RangeValueMapper<float>
|
||||||
|
{
|
||||||
|
public MaxOrbitRadiusValueMapper() : base(1, 20)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int ValueToIndex(float value)
|
||||||
|
{
|
||||||
|
int result = Mathf.FloorToInt(value / 500_000f);
|
||||||
|
if (result < 1) result = 1;
|
||||||
|
if (result > 20) result = 20;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override float IndexToValue(int index)
|
||||||
|
{
|
||||||
|
return index * 500_000f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShellsCountMapper : MyWindow.RangeValueMapper<int>
|
||||||
|
{
|
||||||
|
public ShellsCountMapper() : base(1, 139)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int ValueToIndex(int value)
|
||||||
|
{
|
||||||
|
return value switch
|
||||||
|
{
|
||||||
|
< 4 => value,
|
||||||
|
< 64 => value / 4 + 3,
|
||||||
|
< 256 => value / 16 + 15,
|
||||||
|
< 4096 => value / 64 + 27,
|
||||||
|
_ => value / 256 + 75,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int IndexToValue(int index)
|
||||||
|
{
|
||||||
|
return index switch
|
||||||
|
{
|
||||||
|
< 4 => index,
|
||||||
|
< 19 => (index - 3) * 4,
|
||||||
|
< 31 => (index - 15) * 16,
|
||||||
|
< 91 => (index - 27) * 64,
|
||||||
|
_ => (index - 75) * 256,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void CreateUI(MyConfigWindow wnd, RectTransform trans)
|
private static void CreateUI(MyConfigWindow wnd, RectTransform trans)
|
||||||
{
|
{
|
||||||
_windowTrans = trans;
|
_windowTrans = trans;
|
||||||
@@ -129,21 +197,34 @@ public static class UIConfigWindow
|
|||||||
y += 26f;
|
y += 26f;
|
||||||
var cb3 = wnd.AddCheckBox(x, y, tab2, FactoryPatch.BeltSignalCountRecipeEnabled, "Count all raws and intermediates in statistics", 13);
|
var cb3 = wnd.AddCheckBox(x, y, tab2, FactoryPatch.BeltSignalCountRecipeEnabled, "Count all raws and intermediates in statistics", 13);
|
||||||
y += 26f;
|
y += 26f;
|
||||||
var cb4 = wnd.AddCheckBox(x, y, tab2, FactoryPatch.BeltSignalNumberAltFormat, "Belt signal alt format", 13);
|
var cb4 = wnd.AddCheckBox(x, y, tab2, FactoryPatch.BeltSignalUseProliferatorEnabled, "Count proliferators used for raws/intermediates and finished products", 13);
|
||||||
x += cb4.Width + 5f;
|
|
||||||
y += 6f;
|
y += 6f;
|
||||||
var tip1 = wnd.AddTipsButton2(x, y, tab2, "Belt signal alt format", "Belt signal alt format tips", "belt-signal-alt-format-tips");
|
var tip1 = wnd.AddTipsButton2(x + cb4.Width + 5f, y, tab2, "Count proliferators used for raws/intermediates and finished products", "Count proliferators used for raws/intermediates and finished products tips", "count-proliferators-used-for-raws-intermediates-and-finished-products-tips");
|
||||||
|
y += 20f;
|
||||||
|
var cb5 = wnd.AddCheckBox(x, y, tab2, FactoryPatch.BeltSignalNumberAltFormat, "Belt signal alt format", 13);
|
||||||
|
y += 6f;
|
||||||
|
var tip2 = wnd.AddTipsButton2(x + cb5.Width + 5f, y, tab2, "Belt signal alt format", "Belt signal alt format tips", "belt-signal-alt-format-tips");
|
||||||
x = 0f;
|
x = 0f;
|
||||||
y += 30f;
|
y += 30f;
|
||||||
wnd.AddCheckBox(x, y, tab2, FactoryPatch.GreaterPowerUsageInLogisticsEnabled, "Increase maximum power usage in Logistic Stations and Advanced Mining Machines");
|
wnd.AddCheckBox(x, y, tab2, FactoryPatch.GreaterPowerUsageInLogisticsEnabled, "Increase maximum power usage in Logistic Stations and Advanced Mining Machines");
|
||||||
y += 36f;
|
y += 36f;
|
||||||
wnd.AddCheckBox(x, y, tab2, FactoryPatch.ControlPanelRemoteLogisticsEnabled, "Retrieve/Place items from/to remote planets on logistics control panel");
|
wnd.AddCheckBox(x, y, tab2, FactoryPatch.ControlPanelRemoteLogisticsEnabled, "Retrieve/Place items from/to remote planets on logistics control panel");
|
||||||
|
|
||||||
FactoryPatch.BeltSignalGeneratorEnabled.SettingChanged += (_, _) =>
|
|
||||||
{
|
{
|
||||||
OnBeltSignalChanged();
|
FactoryPatch.BeltSignalGeneratorEnabled.SettingChanged += OnBeltSignalChanged;
|
||||||
};
|
wnd.OnFree += () => { FactoryPatch.BeltSignalGeneratorEnabled.SettingChanged -= OnBeltSignalChanged; };
|
||||||
OnBeltSignalChanged();
|
OnBeltSignalChanged(null, null);
|
||||||
|
void OnBeltSignalChanged(object o, EventArgs e)
|
||||||
|
{
|
||||||
|
var on = FactoryPatch.BeltSignalGeneratorEnabled.Value;
|
||||||
|
cb1.gameObject.SetActive(on);
|
||||||
|
cb2.gameObject.SetActive(on);
|
||||||
|
cb3.gameObject.SetActive(on);
|
||||||
|
cb4.gameObject.SetActive(on);
|
||||||
|
cb5.gameObject.SetActive(on);
|
||||||
|
tip1.gameObject.SetActive(on);
|
||||||
|
tip2.gameObject.SetActive(on);
|
||||||
|
}
|
||||||
|
}
|
||||||
x = 350f;
|
x = 350f;
|
||||||
y = 10f;
|
y = 10f;
|
||||||
wnd.AddCheckBox(x, y, tab2, FactoryPatch.RemovePowerSpaceLimitEnabled, "Remove power space limit");
|
wnd.AddCheckBox(x, y, tab2, FactoryPatch.RemovePowerSpaceLimitEnabled, "Remove power space limit");
|
||||||
@@ -202,6 +283,8 @@ public static class UIConfigWindow
|
|||||||
x = 0f;
|
x = 0f;
|
||||||
y = 10f;
|
y = 10f;
|
||||||
wnd.AddCheckBox(x, y, tab4, DysonSpherePatch.SkipBulletEnabled, "Skip bullet period");
|
wnd.AddCheckBox(x, y, tab4, DysonSpherePatch.SkipBulletEnabled, "Skip bullet period");
|
||||||
|
y += 26f;
|
||||||
|
wnd.AddCheckBox(x + 26f, y, tab4, DysonSpherePatch.FireAllBulletsEnabled, "Fire all bullets at once", 13);
|
||||||
y += 36f;
|
y += 36f;
|
||||||
wnd.AddCheckBox(x, y, tab4, DysonSpherePatch.SkipAbsorbEnabled, "Skip absorption period");
|
wnd.AddCheckBox(x, y, tab4, DysonSpherePatch.SkipAbsorbEnabled, "Skip absorption period");
|
||||||
y += 36f;
|
y += 36f;
|
||||||
@@ -212,9 +295,81 @@ 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");
|
||||||
|
y += 36f;
|
||||||
|
wnd.AddCheckBox(x, y, tab4, DysonSpherePatch.UnlockMaxOrbitRadiusEnabled, "Unlock Dyson Sphere max orbit radius");
|
||||||
|
y += 30f;
|
||||||
|
{
|
||||||
|
var slider = wnd.AddSlider(x + 20, y, tab4, DysonSpherePatch.UnlockMaxOrbitRadiusValue, new MaxOrbitRadiusValueMapper(), "##,#m").WithSmallerHandle(-40f);
|
||||||
|
DysonSpherePatch.UnlockMaxOrbitRadiusEnabled.SettingChanged += UnlockMaxOrbitRadiusChanged;
|
||||||
|
wnd.OnFree += () => { DysonSpherePatch.UnlockMaxOrbitRadiusEnabled.SettingChanged -= UnlockMaxOrbitRadiusChanged; };
|
||||||
|
UnlockMaxOrbitRadiusChanged(null, null);
|
||||||
|
|
||||||
|
void UnlockMaxOrbitRadiusChanged(object o, EventArgs e)
|
||||||
|
{
|
||||||
|
slider.slider.enabled = DysonSpherePatch.UnlockMaxOrbitRadiusEnabled.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
x = 300f;
|
x = 300f;
|
||||||
y = 10f;
|
y = 10f;
|
||||||
wnd.AddButton(x, y, 300f, tab4, "Complete Dyson Sphere shells instantly", 16, "button-complete-dyson-sphere-shells-instantly", DysonSphereFunctions.CompleteShellsInstantly);
|
wnd.AddButton(x, y, 300f, tab4, "Complete Dyson Sphere shells instantly", 16, "button-complete-dyson-sphere-shells-instantly", DysonSphereFunctions.CompleteShellsInstantly);
|
||||||
|
y += 36f;
|
||||||
|
wnd.AddButton(x, y, 300f, tab4, "Remove all frames on Dyson Sphere", 16, "button-remove-all-frames-on-dyson-sphere", DysonSphereFunctions.RemoveAllFrames);
|
||||||
|
{
|
||||||
|
y += 72f;
|
||||||
|
var originalY = y;
|
||||||
|
var btn0 = wnd.AddButton(x, y, 300f, tab4, "Generate illegal dyson shell", 16, "button-generate-illegal-dyson-shells", () =>
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("Generate illegal dyson shell".Translate(), "WARNING: This operation can be very slow, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
|
||||||
|
() => { DysonSphereFunctions.CreateIllegalDysonShellWithMaxOutput(); });
|
||||||
|
});
|
||||||
|
y += 36f;
|
||||||
|
var btn1 = wnd.AddButton(x, y, 300f, tab4, "Generate illegal dyson shell 2", 16, "button-generate-illegal-dyson-shells", () =>
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("Generate illegal dyson shell 2".Translate(), "WARNING: This operation can be very slow, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
|
||||||
|
() => { DysonSphereFunctions.CreateIllegalDysonShellWithMaxOutput2(); });
|
||||||
|
});
|
||||||
|
y += 36f;
|
||||||
|
var btn2 = wnd.AddButton(x, y, 300f, tab4, "Keep max production shells and remove others", 16, "button-keep-max-production-shells", () =>
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("Keep max production shells and remove others".Translate(), "WARNING: This operation is DANGEROUS, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
|
||||||
|
() => { DysonSphereFunctions.KeepMaxProductionShells(); });
|
||||||
|
});
|
||||||
|
y += 36f;
|
||||||
|
var btn3 = wnd.AddButton(x, y, 300f, tab4, "Duplicate shells from that with highest production", 16, "button-duplicate-shells-from-the-highest-production", () =>
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("Duplicate shells from that with highest production".Translate(), "WARNING: This operation can be very slow, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
|
||||||
|
() => { DysonSphereFunctions.DuplicateShellsWithHighestProduction(); });
|
||||||
|
});
|
||||||
|
y += 30f;
|
||||||
|
var slider1 = wnd.AddSlider(x + 20f, y, tab4, DysonSphereFunctions.ShellsCountForFunctions, new ShellsCountMapper());
|
||||||
|
|
||||||
|
y = originalY;
|
||||||
|
var btn4 = wnd.AddButton(x, y, 300f, tab4, "Generate illegal dyson shell quickly", 16, "button-generate-illegal-dyson-shells-quickly", () =>
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("Generate illegal dyson shell quickly".Translate(), "WARNING: This operation can be very slow, continue?".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.WARNING, null,
|
||||||
|
() => { DysonSphereFunctions.CreateIllegalDysonShellQuickly(DysonSphereFunctions.ShellsCountForFunctions.Value); });
|
||||||
|
});
|
||||||
|
y += 30f;
|
||||||
|
var txt2 = wnd.AddText2(x, y, tab4, "Shells count", 15, "text-shells-count");
|
||||||
|
var slider2 = wnd.AddSlider(x + txt2.preferredWidth + 5f, y + 6f, tab4, DysonSphereFunctions.ShellsCountForFunctions, new ShellsCountMapper());
|
||||||
|
|
||||||
|
Functions.DysonSphereFunctions.IllegalDysonShellFunctionsEnabled.SettingChanged += onIllegalDysonShellFunctionsChanged;
|
||||||
|
wnd.OnFree += () => { Functions.DysonSphereFunctions.IllegalDysonShellFunctionsEnabled.SettingChanged -= onIllegalDysonShellFunctionsChanged; };
|
||||||
|
onIllegalDysonShellFunctionsChanged(null, null);
|
||||||
|
void onIllegalDysonShellFunctionsChanged(object o, EventArgs e)
|
||||||
|
{
|
||||||
|
var enabled = Functions.DysonSphereFunctions.IllegalDysonShellFunctionsEnabled.Value;
|
||||||
|
btn0.gameObject.SetActive(enabled);
|
||||||
|
btn1.gameObject.SetActive(enabled);
|
||||||
|
btn2.gameObject.SetActive(enabled);
|
||||||
|
btn3.gameObject.SetActive(enabled);
|
||||||
|
slider1.gameObject.SetActive(enabled);
|
||||||
|
|
||||||
|
btn4.gameObject.SetActive(!enabled);
|
||||||
|
txt2.gameObject.SetActive(!enabled);
|
||||||
|
slider2.gameObject.SetActive(!enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var tab5 = wnd.AddTab(_windowTrans, "Mecha/Combat");
|
var tab5 = wnd.AddTab(_windowTrans, "Mecha/Combat");
|
||||||
x = 0f;
|
x = 0f;
|
||||||
@@ -229,17 +384,6 @@ public static class UIConfigWindow
|
|||||||
wnd.AddButton(x, y, 200f, tab5, "Teleport to outer space", 16, "button-teleport-to-outer-space", PlayerFunctions.TeleportToOuterSpace);
|
wnd.AddButton(x, y, 200f, tab5, "Teleport to outer space", 16, "button-teleport-to-outer-space", PlayerFunctions.TeleportToOuterSpace);
|
||||||
y += 36f;
|
y += 36f;
|
||||||
wnd.AddButton(x, y, 200f, tab5, "Teleport to selected astronomical", 16, "button-teleport-to-selected-astronomical", PlayerFunctions.TeleportToSelectedAstronomical);
|
wnd.AddButton(x, y, 200f, tab5, "Teleport to selected astronomical", 16, "button-teleport-to-selected-astronomical", PlayerFunctions.TeleportToSelectedAstronomical);
|
||||||
return;
|
|
||||||
|
|
||||||
void OnBeltSignalChanged()
|
|
||||||
{
|
|
||||||
var on = FactoryPatch.BeltSignalGeneratorEnabled.Value;
|
|
||||||
cb1.gameObject.SetActive(on);
|
|
||||||
cb2.gameObject.SetActive(on);
|
|
||||||
cb3.gameObject.SetActive(on);
|
|
||||||
cb4.gameObject.SetActive(on);
|
|
||||||
tip1.gameObject.SetActive(on);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateUI()
|
private static void UpdateUI()
|
||||||
@@ -249,6 +393,7 @@ public static class UIConfigWindow
|
|||||||
|
|
||||||
private static void UpdateButtons()
|
private static void UpdateButtons()
|
||||||
{
|
{
|
||||||
|
if (_resignGameBtn == null || _clearBanBtn == null) return;
|
||||||
var data = GameMain.data;
|
var data = GameMain.data;
|
||||||
if (data == null) return;
|
if (data == null) return;
|
||||||
var resignEnabled = data.account != AccountData.me;
|
var resignEnabled = data.account != AccountData.me;
|
||||||
@@ -256,6 +401,7 @@ public static class UIConfigWindow
|
|||||||
{
|
{
|
||||||
_resignGameBtn.gameObject.SetActive(resignEnabled);
|
_resignGameBtn.gameObject.SetActive(resignEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
var history = data.history;
|
var history = data.history;
|
||||||
if (history == null) return;
|
if (history == null) return;
|
||||||
var banEnabled = history.hasUsedPropertyBanAchievement;
|
var banEnabled = history.hasUsedPropertyBanAchievement;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "CheatEnabler",
|
"name": "CheatEnabler",
|
||||||
"version_number": "2.3.29",
|
"version_number": "2.4.3",
|
||||||
"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": [
|
||||||
"xiaoye97-BepInEx-5.4.17",
|
"xiaoye97-BepInEx-5.4.17",
|
||||||
"soarqin-UXAssist-1.2.0"
|
"soarqin-UXAssist-1.4.0"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
# CompressSave
|
# CompressSave
|
||||||
|
|
||||||
#### Moved [here](https://github.com/soarqin/DSP_Mods_TO/tree/master/CompressSave)
|
Moved [to another repo](https://github.com/soarqin/DSP_Mods_TO/tree/master/CompressSave)
|
||||||
|
|||||||
220
DSP_Mods.sln
220
DSP_Mods.sln
@@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UXAssist", "UXAssist\UXAssist.csproj", "{9C048229-6A50-4642-BC5E-02CD39D3869A}"
|
||||||
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CheatEnabler", "CheatEnabler\CheatEnabler.csproj", "{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CheatEnabler", "CheatEnabler\CheatEnabler.csproj", "{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogisticMiner", "LogisticMiner\LogisticMiner.csproj", "{7149D717-C913-4153-9425-38CB9D087F83}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LogisticMiner", "LogisticMiner\LogisticMiner.csproj", "{7149D717-C913-4153-9425-38CB9D087F83}"
|
||||||
@@ -11,90 +13,190 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dustbin", "Dustbin\Dustbin.
|
|||||||
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC} = {B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC} = {B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OCBatchBuild", "OCBatchBuild\OCBatchBuild.csproj", "{E8FB30A0-29BF-4CF0-8E08-9784962A8656}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniverseGenTweaks", "UniverseGenTweaks\UniverseGenTweaks.csproj", "{9534694E-14F0-4498-852D-BBB3FCA986CD}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniverseGenTweaks", "UniverseGenTweaks\UniverseGenTweaks.csproj", "{9534694E-14F0-4498-852D-BBB3FCA986CD}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OverclockEverything", "OverclockEverything\OverclockEverything.csproj", "{0168941C-EEA6-49CF-9A67-E829FE06CF9B}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OverclockEverything", "OverclockEverything\OverclockEverything.csproj", "{0168941C-EEA6-49CF-9A67-E829FE06CF9B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MechaDronesTweaks", "MechaDronesTweaks\MechaDronesTweaks.csproj", "{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MechaDronesTweaks", "MechaDronesTweaks\MechaDronesTweaks.csproj", "{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LabOpt", "LabOpt\LabOpt.csproj", "{DD76B77C-68D8-4A4C-B98E-CBEECEDC49FB}"
|
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
|
||||||
{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F} = {F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}
|
|
||||||
EndProjectSection
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LabOptPreloader", "LabOptPreloader\LabOptPreloader.csproj", "{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DustbinPreloader", "DustbinPreloader\DustbinPreloader.csproj", "{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DustbinPreloader", "DustbinPreloader\DustbinPreloader.csproj", "{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoolOpt", "PoolOpt\PoolOpt.csproj", "{8BE61246-2C9D-4088-AA33-5AFF22C5046E}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoolOpt", "PoolOpt\PoolOpt.csproj", "{8BE61246-2C9D-4088-AA33-5AFF22C5046E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UXAssist", "UXAssist\UXAssist.csproj", "{9C048229-6A50-4642-BC5E-02CD39D3869A}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserCloak", "UserCloak\UserCloak.csproj", "{096D2E4B-D1CE-424D-9954-C36A23E9E279}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserCloak", "UserCloak\UserCloak.csproj", "{096D2E4B-D1CE-424D-9954-C36A23E9E279}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuaScriptEngine", "LuaScriptEngine\LuaScriptEngine.csproj", "{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateGameDlls", "UpdateGameDlls\UpdateGameDlls.csproj", "{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7149D717-C913-4153-9425-38CB9D087F83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{7149D717-C913-4153-9425-38CB9D087F83}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{7149D717-C913-4153-9425-38CB9D087F83}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7149D717-C913-4153-9425-38CB9D087F83}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{931F0230-5941-4E49-AB19-66921AF14096}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{931F0230-5941-4E49-AB19-66921AF14096}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{931F0230-5941-4E49-AB19-66921AF14096}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{931F0230-5941-4E49-AB19-66921AF14096}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{E8FB30A0-29BF-4CF0-8E08-9784962A8656}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{E8FB30A0-29BF-4CF0-8E08-9784962A8656}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{E8FB30A0-29BF-4CF0-8E08-9784962A8656}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{E8FB30A0-29BF-4CF0-8E08-9784962A8656}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{DD76B77C-68D8-4A4C-B98E-CBEECEDC49FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{DD76B77C-68D8-4A4C-B98E-CBEECEDC49FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{DD76B77C-68D8-4A4C-B98E-CBEECEDC49FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{DD76B77C-68D8-4A4C-B98E-CBEECEDC49FB}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{F2D5EBE8-7D9D-4572-9A3E-4DD1114FD99F}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Release|Any CPU.Build.0 = Release|Any CPU
|
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{9C048229-6A50-4642-BC5E-02CD39D3869A}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{F9F16B62-D1D3-466B-BE22-E64B9EA957C2}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{7149D717-C913-4153-9425-38CB9D087F83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7149D717-C913-4153-9425-38CB9D087F83}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7149D717-C913-4153-9425-38CB9D087F83}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{7149D717-C913-4153-9425-38CB9D087F83}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{7149D717-C913-4153-9425-38CB9D087F83}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{7149D717-C913-4153-9425-38CB9D087F83}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{7149D717-C913-4153-9425-38CB9D087F83}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7149D717-C913-4153-9425-38CB9D087F83}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7149D717-C913-4153-9425-38CB9D087F83}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{7149D717-C913-4153-9425-38CB9D087F83}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{7149D717-C913-4153-9425-38CB9D087F83}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{7149D717-C913-4153-9425-38CB9D087F83}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{4EABD71D-477F-448B-801B-48F8745A3FA7}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{931F0230-5941-4E49-AB19-66921AF14096}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{931F0230-5941-4E49-AB19-66921AF14096}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{931F0230-5941-4E49-AB19-66921AF14096}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{931F0230-5941-4E49-AB19-66921AF14096}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{931F0230-5941-4E49-AB19-66921AF14096}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{931F0230-5941-4E49-AB19-66921AF14096}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{931F0230-5941-4E49-AB19-66921AF14096}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{931F0230-5941-4E49-AB19-66921AF14096}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{931F0230-5941-4E49-AB19-66921AF14096}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{931F0230-5941-4E49-AB19-66921AF14096}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{931F0230-5941-4E49-AB19-66921AF14096}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{931F0230-5941-4E49-AB19-66921AF14096}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{9534694E-14F0-4498-852D-BBB3FCA986CD}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{0168941C-EEA6-49CF-9A67-E829FE06CF9B}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{15B8BC2E-93E0-4454-8F8F-BF1FA8DC90F4}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{B8EB3D8D-5613-42F0-9040-EAA11A38C6AC}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{8BE61246-2C9D-4088-AA33-5AFF22C5046E}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Release|Any CPU.Build.0 = Release|Any CPU
|
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{096D2E4B-D1CE-424D-9954-C36A23E9E279}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{E9375F0E-26DC-4CEC-80DC-9C48F23340BC}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{6E73B301-7C7A-4EF4-B0FA-4C6B40F96653}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
45
Directory.Build.props
Normal file
45
Directory.Build.props
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project>
|
||||||
|
<!-- Common properties shared by all DSP mod projects -->
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net472</TargetFramework>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
|
||||||
|
<!-- Set to true in projects that include a CHANGELOG.md in the package -->
|
||||||
|
<PackHasChangelog>false</PackHasChangelog>
|
||||||
|
<!-- Set to true in projects that use the plugins/patchers layout (Dustbin, LabOpt) -->
|
||||||
|
<PackUsePluginsLayout>false</PackUsePluginsLayout>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- Common NuGet packages for all mods -->
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
||||||
|
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
||||||
|
<PackageReference Include="UnityEngine.Modules" Version="2022.3.62" IncludeAssets="compile" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Game DLL references (local copies in AssemblyFromGame/) -->
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Assembly-CSharp">
|
||||||
|
<HintPath>$(MSBuildThisFileDirectory)AssemblyFromGame\Assembly-CSharp.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="UnityEngine.UI">
|
||||||
|
<HintPath>$(MSBuildThisFileDirectory)AssemblyFromGame\UnityEngine.UI.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- .NET Framework reference assemblies (only needed when targeting net*) -->
|
||||||
|
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
||||||
|
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- All projects depend on UpdateGameDlls helper to ensure game DLLs are
|
||||||
|
refreshed before any project resolves assembly references. -->
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="$(MSBuildThisFileDirectory)UpdateGameDlls\UpdateGameDlls.csproj"
|
||||||
|
ReferenceOutputAssembly="false"
|
||||||
|
SkipGetTargetFrameworkProperties="true"
|
||||||
|
Private="false" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
94
Directory.Build.targets
Normal file
94
Directory.Build.targets
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
ZipMod target: assembles a Thunderstore-ready zip under package/.
|
||||||
|
Run explicitly with: dotnet build -t:ZipMod -c Release
|
||||||
|
It does NOT run automatically on every build.
|
||||||
|
|
||||||
|
"Pack" is reserved by the .NET SDK for NuGet packaging, so this target
|
||||||
|
uses the name "ZipMod" to avoid conflict.
|
||||||
|
|
||||||
|
Per-project customisation properties (set in the project's PropertyGroup):
|
||||||
|
PackHasChangelog – set to 'true' to include CHANGELOG.md in the zip
|
||||||
|
PackUsePluginsLayout – set to 'true' for the plugins/patchers folder layout
|
||||||
|
(used by Dustbin and LabOpt)
|
||||||
|
|
||||||
|
Simple layout zips:
|
||||||
|
<AssemblyName>.dll icon.png manifest.json README.md [CHANGELOG.md]
|
||||||
|
plugins/patchers layout zips:
|
||||||
|
plugins/ patchers/ icon.png manifest.json README.md [CHANGELOG.md]
|
||||||
|
-->
|
||||||
|
<Target Name="ZipMod" DependsOnTargets="Build" Condition="'$(PackPreloaderTargetDir)' == ''">
|
||||||
|
<PropertyGroup>
|
||||||
|
<_PackageDir>$(MSBuildProjectDirectory)\package</_PackageDir>
|
||||||
|
<_StagingDir>$(MSBuildProjectDirectory)\obj\pack-staging</_StagingDir>
|
||||||
|
<_ZipPath>$(_PackageDir)\$(ProjectName)-$(Version).zip</_ZipPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- Sync manifest.json version_number from .csproj $(Version) before packaging -->
|
||||||
|
<Exec Condition="Exists('$(_PackageDir)\manifest.json')"
|
||||||
|
Command="powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "$f='$(_PackageDir)\manifest.json'; $c=[IO.File]::ReadAllText($f); $c=$c -replace '(\u0022version_number\u0022\s*:\s*\u0022)[^\u0022]*(\u0022)','${1}$(Version)${2}'; [IO.File]::WriteAllText($f,$c,[Text.UTF8Encoding]::new($true))"" />
|
||||||
|
|
||||||
|
<!-- ── plugins/patchers layout: copy DLL into package/plugins/ first ── -->
|
||||||
|
<MakeDir Directories="$(_PackageDir)\plugins"
|
||||||
|
Condition="'$(PackUsePluginsLayout)' == 'true'" />
|
||||||
|
<Copy SourceFiles="$(TargetPath)" DestinationFolder="$(_PackageDir)\plugins"
|
||||||
|
Condition="'$(PackUsePluginsLayout)' == 'true'" />
|
||||||
|
|
||||||
|
<!-- Collect loose root files (common to both layouts) -->
|
||||||
|
<ItemGroup>
|
||||||
|
<_PackRootFiles Include="$(_PackageDir)\icon.png" />
|
||||||
|
<_PackRootFiles Include="$(_PackageDir)\manifest.json" />
|
||||||
|
<_PackRootFiles Include="$(MSBuildProjectDirectory)\README.md" />
|
||||||
|
<_PackRootFiles Include="$(MSBuildProjectDirectory)\CHANGELOG.md"
|
||||||
|
Condition="'$(PackHasChangelog)' == 'true'" />
|
||||||
|
<!-- Simple layout: also include the DLL itself at the root -->
|
||||||
|
<_PackRootFiles Include="$(TargetPath)"
|
||||||
|
Condition="'$(PackUsePluginsLayout)' != 'true'" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Prepare staging directory -->
|
||||||
|
<RemoveDir Directories="$(_StagingDir)" />
|
||||||
|
<MakeDir Directories="$(_StagingDir)" />
|
||||||
|
|
||||||
|
<!-- Copy loose root files into staging root -->
|
||||||
|
<Copy SourceFiles="@(_PackRootFiles)" DestinationFolder="$(_StagingDir)" />
|
||||||
|
|
||||||
|
<!-- plugins/patchers layout: copy sub-folders into staging (preserve structure) -->
|
||||||
|
<ItemGroup Condition="'$(PackUsePluginsLayout)' == 'true'">
|
||||||
|
<_PluginFiles Include="$(_PackageDir)\plugins\**\*" />
|
||||||
|
<_PatcherFiles Include="$(_PackageDir)\patchers\**\*" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Copy SourceFiles="@(_PluginFiles)"
|
||||||
|
DestinationFiles="@(_PluginFiles->'$(_StagingDir)\plugins\%(RecursiveDir)%(Filename)%(Extension)')"
|
||||||
|
Condition="'$(PackUsePluginsLayout)' == 'true'" />
|
||||||
|
<Copy SourceFiles="@(_PatcherFiles)"
|
||||||
|
DestinationFiles="@(_PatcherFiles->'$(_StagingDir)\patchers\%(RecursiveDir)%(Filename)%(Extension)')"
|
||||||
|
Condition="'$(PackUsePluginsLayout)' == 'true'" />
|
||||||
|
|
||||||
|
<!-- Delete previous zip if present -->
|
||||||
|
<Delete Files="$(_ZipPath)" Condition="Exists('$(_ZipPath)')" />
|
||||||
|
|
||||||
|
<!-- Create zip using MSBuild ZipDirectory task – no shell, no quoting issues -->
|
||||||
|
<ZipDirectory SourceDirectory="$(_StagingDir)" DestinationFile="$(_ZipPath)" />
|
||||||
|
|
||||||
|
<!-- Clean up staging directory -->
|
||||||
|
<RemoveDir Directories="$(_StagingDir)" />
|
||||||
|
|
||||||
|
<Message Text="ZipMod: created $(_ZipPath)" Importance="high" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<!-- ── Preloader helper target ────────────────────────────────────────────
|
||||||
|
Preloader projects (DustbinPreloader, LabOptPreloader) call this to
|
||||||
|
copy their output DLL into the sibling main mod's patchers/ folder.
|
||||||
|
Set PackPreloaderTargetDir in the preloader's csproj, e.g.:
|
||||||
|
<PackPreloaderTargetDir>..\Dustbin\package\patchers</PackPreloaderTargetDir>
|
||||||
|
──────────────────────────────────────────────────────────────────────── -->
|
||||||
|
<Target Name="CopyToParentPackage" DependsOnTargets="Build"
|
||||||
|
Condition="'$(PackPreloaderTargetDir)' != ''">
|
||||||
|
<MakeDir Directories="$(PackPreloaderTargetDir)" />
|
||||||
|
<Copy SourceFiles="$(TargetPath)" DestinationFolder="$(PackPreloaderTargetDir)" />
|
||||||
|
<Message Text="CopyToParentPackage: copied $(TargetFileName) to $(PackPreloaderTargetDir)" Importance="high" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
@@ -52,7 +52,7 @@ public static class BeltSignal
|
|||||||
tex.LoadImage(fileData);
|
tex.LoadImage(fileData);
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Sprite LoadEmbeddedSprite(string path, Assembly assembly = null)
|
private static Sprite LoadEmbeddedSprite(string path, Assembly assembly = null)
|
||||||
{
|
{
|
||||||
var tex = LoadEmbeddedTexture(path, assembly);
|
var tex = LoadEmbeddedTexture(path, assembly);
|
||||||
@@ -77,7 +77,7 @@ public static class BeltSignal
|
|||||||
SID = ""
|
SID = ""
|
||||||
};
|
};
|
||||||
p.name = p.Name.Translate();
|
p.name = p.Name.Translate();
|
||||||
signals.dataArray = signals.dataArray.AddItem(p).ToArray();
|
signals.dataArray = [.. signals.dataArray.AddItem(p)];
|
||||||
signals.dataIndices[p.ID] = index;
|
signals.dataIndices[p.ID] = index;
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
@@ -225,11 +225,11 @@ public static class BeltSignal
|
|||||||
int itemId;
|
int itemId;
|
||||||
if ((itemId = cargoPath.TryPickItem(belt.segIndex + belt.segPivotOffset - 5, 12, out var stack, out _)) <= 0) continue;
|
if ((itemId = cargoPath.TryPickItem(belt.segIndex + belt.segPivotOffset - 5, 12, out var stack, out _)) <= 0) continue;
|
||||||
consumeRegister[itemId] += stack;
|
consumeRegister[itemId] += stack;
|
||||||
Dustbin.CalcGetSands(itemId, stack);
|
Dustbin.CalcGetSands(itemId, stack, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,67 +1,79 @@
|
|||||||
|
<details>
|
||||||
|
<summary>Read me in English</summary>
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
* 1.4.0
|
* 1.4.0
|
||||||
* Refactorying Tank input logic codes, for better performance, and resolve a bug [#53](https://github.com/soarqin/DSP_Mods/issues/53)
|
* Refactorying Tank input logic codes, for better performance, and resolve a bug [#53](https://github.com/soarqin/DSP_Mods/issues/53)
|
||||||
+ Remove use of AssetBundle, move the belt signal icon into `Assembly Resources`, for better flexibility.
|
* Remove use of AssetBundle, move the belt signal icon into `Assembly Resources`, for better flexibility.
|
||||||
|
|
||||||
* 1.3.3
|
* 1.3.3
|
||||||
+ Support for NebulaMultiplayerModApi 2.0.0
|
* Support for NebulaMultiplayerModApi 2.0.0
|
||||||
|
|
||||||
* 1.3.2
|
* 1.3.2
|
||||||
+ Fix a display issue that the dustbin checkbox is overlapped with the filter button in storage UI.
|
* Fix a display issue that the dustbin checkbox is overlapped with the filter button in storage UI.
|
||||||
|
|
||||||
* 1.3.1
|
* 1.3.1
|
||||||
+ Support for game version 0.10.28.20759
|
* Support for game version 0.10.28.20759
|
||||||
|
|
||||||
* 1.3.0
|
* 1.3.0
|
||||||
+ Add a belt signal(you can find it in first tab of signal selection panel) as dustbin, which is the simplest way to destroy items.
|
* Add a belt signal(you can find it in first tab of signal selection panel) as dustbin, which is the simplest way to destroy items.
|
||||||
+ Reworked dustbin support for Tanks, to improve performance and resolve known bugs.
|
* Reworked dustbin support for Tanks, to improve performance and resolve known bugs.
|
||||||
- Be note that the whole tank logic is optimized which may get a slight better performance even if you don't use them as dustbin.
|
* Be note that the whole tank logic is optimized which may get a slight better performance even if you don't use them as dustbin.
|
||||||
+ Config entry for soil piless gain from destroyed items are changed to a more flexible format.
|
* Config entry for soil piless gain from destroyed items are changed to a more flexible format.
|
||||||
+ [Nebula Mupltiplayer Mod](https://dsp.thunderstore.io/package/nebula/NebulaMultiplayerMod/) and bug fixes from [ModFixerOne](https://dsp.thunderstore.io/package/starfi5h/ModFixerOne/) by [starfi5h](https://github.com/starfi5h/).
|
* [Nebula Mupltiplayer Mod](https://dsp.thunderstore.io/package/nebula/NebulaMultiplayerMod/) and bug fixes from [ModFixerOne](https://dsp.thunderstore.io/package/starfi5h/ModFixerOne/) by [starfi5h](https://github.com/starfi5h/).
|
||||||
|
|
||||||
* 1.2.1
|
* 1.2.1
|
||||||
+ Fix dynamic array bug in codes, which causes various bugs and errors.
|
* Fix dynamic array bug in codes, which causes various bugs and errors.
|
||||||
|
|
||||||
* 1.2.0
|
* 1.2.0
|
||||||
+ Use [DSPModSave](https://dsp.thunderstore.io/package/CommonAPI/DSPModSave/) to save dustbin specified data now, which fixes [#1](https://github.com/soarqin/DSP_Mods/issues/1).
|
* Use [DSPModSave](https://dsp.thunderstore.io/package/CommonAPI/DSPModSave/) to save dustbin specified data now, which fixes [#1](https://github.com/soarqin/DSP_Mods/issues/1).
|
||||||
+ Fix issue for storages on multiple planets.
|
* Fix issue for storages on multiple planets.
|
||||||
+ Fix issue for multi-level tanks.
|
* Fix issue for multi-level tanks.
|
||||||
+ Add a note in README for known bug on tank.
|
* Add a note in README for known bug on tank.
|
||||||
|
|
||||||
* 1.1.0
|
* 1.1.0
|
||||||
+ Rewrite whole plugin, make a checkbox on UI so that you can turn storages into dustbin by just ticking it.
|
* Rewrite whole plugin, make a checkbox on UI so that you can turn storages into dustbin by just ticking it.
|
||||||
+ Can turn tank into dustbin now.
|
* Can turn tank into dustbin now.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>中文读我</summary>
|
||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
* 1.4.0
|
* 1.4.0
|
||||||
+ 重构储液罐的输入逻辑代码,以提高性能并解决bug [#53](https://github.com/soarqin/DSP_Mods/issues/53)
|
* 重构储液罐的输入逻辑代码,以提高性能并解决bug [#53](https://github.com/soarqin/DSP_Mods/issues/53)
|
||||||
+ 移除了AssetBundle的使用,将传送带信号图标移入`Assembly资源`,以获得更好的灵活性
|
* 移除了AssetBundle的使用,将传送带信号图标移入`Assembly资源`,以获得更好的灵活性
|
||||||
|
|
||||||
* 1.3.3
|
* 1.3.3
|
||||||
+ 支持NebulaMultiplayerModApi 2.0.0
|
* 支持NebulaMultiplayerModApi 2.0.0
|
||||||
|
|
||||||
* 1.3.2
|
* 1.3.2
|
||||||
+ 修正了储物仓UI中的垃圾桶勾选框与筛选按钮重叠的显示问题
|
* 修正了储物仓UI中的垃圾桶勾选框与筛选按钮重叠的显示问题
|
||||||
|
|
||||||
* 1.3.1
|
* 1.3.1
|
||||||
+ 支持游戏版本 0.10.28.20759
|
* 支持游戏版本 0.10.28.20759
|
||||||
|
|
||||||
* 1.3.0
|
* 1.3.0
|
||||||
+ 添加了一个传送带信号(可以在信号选择面板的第一个页签中找到)作为垃圾桶,这是目前销毁物品最简单的方法
|
* 添加了一个传送带信号(可以在信号选择面板的第一个页签中找到)作为垃圾桶,这是目前销毁物品最简单的方法
|
||||||
+ 重写了储液罐的垃圾桶实现,以提高性能并解决已知的bug
|
* 重写了储液罐的垃圾桶实现,以提高性能并解决已知的bug
|
||||||
- 注意:整个储液罐逻辑都被优化了,即使你不把他们作为垃圾桶使用,也可能会获得轻微的性能提升
|
* 注意:整个储液罐逻辑都被优化了,即使你不把他们作为垃圾桶使用,也可能会获得轻微的性能提升
|
||||||
+ 从销毁的物品中获得沙子的配置已变为更灵活的设置项格式
|
* 从销毁的物品中获得沙子的配置已变为更灵活的设置项格式
|
||||||
+ [Nebula Mupltiplayer Mod](https://dsp.thunderstore.io/package/nebula/NebulaMultiplayerMod/)支持和Bug修正来自[starfi5h](https://github.com/starfi5h/)的[ModFixerOne](https://dsp.thunderstore.io/package/starfi5h/ModFixerOne/)
|
* [Nebula Mupltiplayer Mod](https://dsp.thunderstore.io/package/nebula/NebulaMultiplayerMod/)支持和Bug修正来自[starfi5h](https://github.com/starfi5h/)的[ModFixerOne](https://dsp.thunderstore.io/package/starfi5h/ModFixerOne/)
|
||||||
|
|
||||||
* 1.2.1
|
* 1.2.1
|
||||||
+ 修正了代码中的动态数组Bug,该Bug可能导致各种问题
|
* 修正了代码中的动态数组Bug,该Bug可能导致各种问题
|
||||||
|
|
||||||
* 1.2.0
|
* 1.2.0
|
||||||
+ 现在使用[DSPModSave](https://dsp.thunderstore.io/package/CommonAPI/DSPModSave/)来保存垃圾桶的数据,修正了[#1](https://github.com/soarqin/DSP_Mods/issues/1)
|
* 现在使用[DSPModSave](https://dsp.thunderstore.io/package/CommonAPI/DSPModSave/)来保存垃圾桶的数据,修正了[#1](https://github.com/soarqin/DSP_Mods/issues/1)
|
||||||
+ 修正了多星球上的储物仓问题
|
* 修正了多星球上的储物仓问题
|
||||||
+ 修正了多层储液罐的问题
|
* 修正了多层储液罐的问题
|
||||||
+ 在README中添加了一个已知储液罐Bug的说明
|
* 在README中添加了一个已知储液罐Bug的说明
|
||||||
|
|
||||||
* 1.1.0
|
* 1.1.0
|
||||||
+ 重写了整个插件,现在可以在仓储类建筑的UI上勾选来将其转变为垃圾桶
|
* 重写了整个插件,现在可以在仓储类建筑的UI上勾选来将其转变为垃圾桶
|
||||||
+ 现在可以将储液罐转变为垃圾桶
|
* 现在可以将储液罐转变为垃圾桶
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class Dustbin : BaseUnityPlugin, IModCanSave, IMultiplayerMod
|
|||||||
NebulaModAPI.RegisterPackets(Assembly.GetExecutingAssembly());
|
NebulaModAPI.RegisterPackets(Assembly.GetExecutingAssembly());
|
||||||
NebulaModAPI.OnPlanetLoadFinished += RequestPlanetDustbinData;
|
NebulaModAPI.OnPlanetLoadFinished += RequestPlanetDustbinData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
TankPatch.Enable(false);
|
TankPatch.Enable(false);
|
||||||
@@ -58,7 +58,7 @@ public class Dustbin : BaseUnityPlugin, IModCanSave, IMultiplayerMod
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static int CalcGetSands(int itemId, int count)
|
public static int CalcGetSands(int itemId, int count, int inc)
|
||||||
{
|
{
|
||||||
var sandsPerItem = itemId <= 12000 ? Dustbin.SandsFactors[itemId] : 0;
|
var sandsPerItem = itemId <= 12000 ? Dustbin.SandsFactors[itemId] : 0;
|
||||||
if (sandsPerItem <= 0) return count;
|
if (sandsPerItem <= 0) return count;
|
||||||
@@ -68,7 +68,7 @@ public class Dustbin : BaseUnityPlugin, IModCanSave, IMultiplayerMod
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IModCanSave
|
#region IModCanSave
|
||||||
private const ushort ModSaveVersion = 1;
|
private const ushort ModSaveVersion = 1;
|
||||||
|
|
||||||
public void Export(BinaryWriter w)
|
public void Export(BinaryWriter w)
|
||||||
|
|||||||
@@ -1,41 +1,21 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net472</TargetFramework>
|
|
||||||
<BepInExPluginGuid>org.soardev.dustbin</BepInExPluginGuid>
|
<BepInExPluginGuid>org.soardev.dustbin</BepInExPluginGuid>
|
||||||
<Description>DSP MOD - Dustbin</Description>
|
<Description>DSP MOD - Dustbin</Description>
|
||||||
<Version>1.4.0</Version>
|
<Version>1.4.0</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<PackageId>Dustbin</PackageId>
|
<PackageId>Dustbin</PackageId>
|
||||||
<RootNamespace>Dustbin</RootNamespace>
|
<RootNamespace>Dustbin</RootNamespace>
|
||||||
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
|
<PackHasChangelog>true</PackHasChangelog>
|
||||||
|
<PackUsePluginsLayout>true</PackUsePluginsLayout>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
|
||||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.Modding.DSPModSave" Version="1.*" />
|
<PackageReference Include="DysonSphereProgram.Modding.DSPModSave" Version="1.*" />
|
||||||
<PackageReference Include="DysonSphereProgram.Modding.NebulaMultiplayerModApi" Version="2.0.0" />
|
<PackageReference Include="DysonSphereProgram.Modding.NebulaMultiplayerModApi" Version="2.0.0" />
|
||||||
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="assets/icon/signal-410.png" />
|
<EmbeddedResource Include="assets/icon/signal-410.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="Assembly-CSharp">
|
|
||||||
<HintPath>GameAssembly\Assembly-CSharp.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<Exec Command="del /F /Q package\$(ProjectName)-$(Version).zip
IF NOT EXIST package\plugins (mkdir package\plugins)
copy /y $(TargetPath) package\plugins\
cd package
powershell Compress-Archive -Force -DestinationPath '$(ProjectName)-$(Version).zip' -Path patchers, plugins, icon.png, manifest.json, ../README.md, ../CHANGELOG.md" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -61,19 +61,19 @@ namespace Dustbin.NebulaSupport
|
|||||||
NebulaModAPI.MultiplayerSession.Network.SendPacket(new SyncPlanetData(Dustbin.ExportData(factory)));
|
NebulaModAPI.MultiplayerSession.Network.SendPacket(new SyncPlanetData(Dustbin.ExportData(factory)));
|
||||||
return;
|
return;
|
||||||
case < 0:
|
case < 0:
|
||||||
{
|
{
|
||||||
var tankPool = factory.factoryStorage.tankPool;
|
var tankPool = factory.factoryStorage.tankPool;
|
||||||
tankPool[-storageId].IsDustbin = packet.Enable;
|
tankPool[-storageId].IsDustbin = packet.Enable;
|
||||||
TankPatch.Reset();
|
TankPatch.Reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case > 0:
|
case > 0:
|
||||||
{
|
{
|
||||||
var storagePool = factory.factoryStorage.storagePool;
|
var storagePool = factory.factoryStorage.storagePool;
|
||||||
storagePool[storageId].IsDustbin = packet.Enable;
|
storagePool[storageId].IsDustbin = packet.Enable;
|
||||||
StoragePatch.Reset();
|
StoragePatch.Reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,29 @@
|
|||||||
# Dustbin
|
# Dustbin
|
||||||
|
|
||||||
#### Can turn Storages and Tanks into Dustbin(Destroy incoming items)
|
<details>
|
||||||
#### 储物仓和储液罐可以转变为垃圾桶(销毁送进的物品)
|
<summary>Read me in English</summary>
|
||||||
|
|
||||||
|
***Can turn Storages and Tanks into Dustbin(Destroy incoming items)***
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
* A checkbox is added to Storages and Tanks UI, which turns them into dustbins.
|
* A checkbox is added to Storages and Tanks UI, which turns them into dustbins.
|
||||||
* Items sent into dustbins are removed immediately.
|
* Items sent into dustbins are removed immediately.
|
||||||
* Can get soil piless from destroyed items, configurable through a json encoded config entry.
|
* Can get soil piless from destroyed items, configurable through a json encoded config entry.
|
||||||
+ You can get item ID list [here](https://dsp-wiki.com/Modding:Items_IDs).
|
* You can get item ID list from [dsp-wiki](https://dsp-wiki.com/Modding:Items_IDs).
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>中文读我</summary>
|
||||||
|
|
||||||
|
***储物仓和储液罐可以转变为垃圾桶(销毁送进的物品)***
|
||||||
|
|
||||||
## 使用说明
|
## 使用说明
|
||||||
|
|
||||||
* 在储物仓和储液罐上增加一个垃圾桶的勾选框。
|
* 在储物仓和储液罐上增加一个垃圾桶的勾选框。
|
||||||
* 送进垃圾桶的物品会立即被移除。
|
* 送进垃圾桶的物品会立即被移除。
|
||||||
* 可以从移除的物品中获得沙子,可以通过json编码的设置项进行配置。
|
* 可以从移除的物品中获得沙子,可以通过json编码的设置项进行配置。
|
||||||
+ 可以在[这里](https://dsp-wiki.com/Modding:Items_IDs)获得物品ID列表。
|
* 可以在[这里](https://dsp-wiki.com/Modding:Items_IDs)获得物品ID列表。
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public static class StoragePatch
|
|||||||
private static UI.MyCheckBox _storageDustbinCheckBox;
|
private static UI.MyCheckBox _storageDustbinCheckBox;
|
||||||
private static int _lastStorageId;
|
private static int _lastStorageId;
|
||||||
private static Harmony _patch;
|
private static Harmony _patch;
|
||||||
|
|
||||||
public static void Enable(bool on)
|
public static void Enable(bool on)
|
||||||
{
|
{
|
||||||
if (on)
|
if (on)
|
||||||
@@ -138,7 +138,7 @@ public static class StoragePatch
|
|||||||
_storageDustbinCheckBox.rectTrans.anchoredPosition3D = new Vector3(190, 57 - rectTrans.sizeDelta.y, 0);
|
_storageDustbinCheckBox.rectTrans.anchoredPosition3D = new Vector3(190, 57 - rectTrans.sizeDelta.y, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Adopt fix from starfi5h's NebulaCompatiblilityAssist */
|
/* Adopt fix from starfi5h's NebulaCompatiblilityAssist */
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(UIStorageGrid), nameof(UIStorageGrid.OnStorageSizeChanged))]
|
[HarmonyPatch(typeof(UIStorageGrid), nameof(UIStorageGrid.OnStorageSizeChanged))]
|
||||||
@@ -148,25 +148,65 @@ public static class StoragePatch
|
|||||||
_lastStorageId = 0; // Refresh UI to reposition button on client side
|
_lastStorageId = 0; // Refresh UI to reposition button on client side
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(StorageComponent), nameof(StorageComponent.AddItem), [typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool)],
|
[HarmonyPatch(typeof(StorageComponent), nameof(StorageComponent.AddItem), [typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool)],
|
||||||
[ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Out, ArgumentType.Normal])]
|
[ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Out, ArgumentType.Normal])]
|
||||||
private static IEnumerable<CodeInstruction> StorageComponent_AddItem_HarmonyTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
private static IEnumerable<CodeInstruction> StorageComponent_AddItem_HarmonyTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
{
|
{
|
||||||
var matcher = new CodeMatcher(instructions, generator);
|
var codes = new List<CodeInstruction>(instructions);
|
||||||
var label1 = generator.DefineLabel();
|
var matcher = new CodeMatcher(codes, generator);
|
||||||
matcher.Start().MatchForward(false,
|
|
||||||
new CodeMatch(OpCodes.Stind_I4)
|
// 找到方法开始处
|
||||||
).Advance(1).InsertAndAdvance(
|
// Find the beginning of the method
|
||||||
|
matcher.Start();
|
||||||
|
|
||||||
|
// 定义标签用于跳转
|
||||||
|
// Define label for jump
|
||||||
|
var skipDustbinLogic = generator.DefineLabel();
|
||||||
|
|
||||||
|
// 在方法开始处插入安全检查
|
||||||
|
// Insert safety checks at the beginning of the method
|
||||||
|
matcher.InsertAndAdvance(
|
||||||
|
// 安全检查:确保StorageComponent实例不为null
|
||||||
|
// Safety check: Ensure StorageComponent instance is not null
|
||||||
|
new CodeInstruction(OpCodes.Ldarg_0),
|
||||||
|
new CodeInstruction(OpCodes.Brfalse, skipDustbinLogic),
|
||||||
|
|
||||||
|
// 检查是否是垃圾桶
|
||||||
|
// Check if it's a dustbin
|
||||||
new CodeInstruction(OpCodes.Ldarg_0),
|
new CodeInstruction(OpCodes.Ldarg_0),
|
||||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(StorageComponent), nameof(StorageComponent.IsDustbin))),
|
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(StorageComponent), nameof(StorageComponent.IsDustbin))),
|
||||||
new CodeInstruction(OpCodes.Brfalse, label1),
|
new CodeInstruction(OpCodes.Brfalse, skipDustbinLogic),
|
||||||
|
|
||||||
|
// 检查count是否大于0
|
||||||
|
// Check if count is greater than 0
|
||||||
|
new CodeInstruction(OpCodes.Ldarg_2),
|
||||||
|
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||||
|
new CodeInstruction(OpCodes.Ble, skipDustbinLogic),
|
||||||
|
|
||||||
|
// 调用CalcGetSands处理物品销毁和沙子生成
|
||||||
|
// Call CalcGetSands to handle item destruction and sand generation
|
||||||
new CodeInstruction(OpCodes.Ldarg_1),
|
new CodeInstruction(OpCodes.Ldarg_1),
|
||||||
new CodeInstruction(OpCodes.Ldarg_2),
|
new CodeInstruction(OpCodes.Ldarg_2),
|
||||||
|
new CodeInstruction(OpCodes.Ldarg_3),
|
||||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Dustbin), nameof(Dustbin.CalcGetSands))),
|
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Dustbin), nameof(Dustbin.CalcGetSands))),
|
||||||
new CodeInstruction(OpCodes.Ret)
|
|
||||||
|
// 设置remainInc为0(第5个参数,索引4)
|
||||||
|
// Set remainInc to 0 (5th parameter, index 4)
|
||||||
|
new CodeInstruction(OpCodes.Ldarg, 4),
|
||||||
|
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||||
|
new CodeInstruction(OpCodes.Stind_I4),
|
||||||
|
|
||||||
|
// 返回count表示成功销毁
|
||||||
|
// Return count to indicate successful destruction
|
||||||
|
new CodeInstruction(OpCodes.Ret),
|
||||||
|
|
||||||
|
// 跳过垃圾桶逻辑的标签
|
||||||
|
// Label to skip dustbin logic
|
||||||
|
new CodeInstruction(OpCodes.Nop).WithLabels(skipDustbinLogic)
|
||||||
);
|
);
|
||||||
matcher.Labels.Add(label1);
|
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public static class TankPatch
|
|||||||
private static UI.MyCheckBox _tankDustbinCheckBox;
|
private static UI.MyCheckBox _tankDustbinCheckBox;
|
||||||
private static int _lastTankId;
|
private static int _lastTankId;
|
||||||
private static Harmony _patch;
|
private static Harmony _patch;
|
||||||
|
|
||||||
public static void Enable(bool on)
|
public static void Enable(bool on)
|
||||||
{
|
{
|
||||||
if (on)
|
if (on)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace DustbinPreloader;
|
|||||||
|
|
||||||
public static class Preloader
|
public static class Preloader
|
||||||
{
|
{
|
||||||
private static readonly ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("Dustbin Preloader");
|
private static readonly ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("Dustbin Preloader");
|
||||||
public static IEnumerable<string> TargetDLLs { get; } = new[] { "Assembly-CSharp.dll" };
|
public static IEnumerable<string> TargetDLLs { get; } = new[] { "Assembly-CSharp.dll" };
|
||||||
|
|
||||||
public static void Patch(AssemblyDefinition assembly)
|
public static void Patch(AssemblyDefinition assembly)
|
||||||
|
|||||||
@@ -1,28 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net472</TargetFramework>
|
|
||||||
<AssemblyName>DustbinPreloader</AssemblyName>
|
<AssemblyName>DustbinPreloader</AssemblyName>
|
||||||
<Description>DSP MOD - Prealoder for Dustbin</Description>
|
<Description>DSP MOD - Preloader for Dustbin</Description>
|
||||||
<Version>1.3.1</Version>
|
<Version>1.3.1</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<PackPreloaderTargetDir>..\Dustbin\package\patchers</PackPreloaderTargetDir>
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
|
||||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
|
||||||
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<Exec Command="IF NOT EXIST ..\Dustbin\package\patchers (mkdir ..\Dustbin\package\patchers)
copy /y $(TargetPath) ..\Dustbin\package\patchers\" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
39
HideTips/CHANGELOG.md
Normal file
39
HideTips/CHANGELOG.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<details>
|
||||||
|
<summary>Read me in English</summary>
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
* 1.0.4
|
||||||
|
* Remove `Disable title screen demo scene loading`, as it is buggy in recent updates.
|
||||||
|
* Fix a bug that when tutorials are not added to the guides panel when they are hidden by this MOD.
|
||||||
|
* 1.0.3
|
||||||
|
* Add config entries to disable research completion tips/popup windows
|
||||||
|
* Add a note to README for mod compatibility on `Disable title screen demo scene loading`.
|
||||||
|
* 1.0.2
|
||||||
|
* Add a config entry to disable title screen demo scene loading
|
||||||
|
* 1.0.1
|
||||||
|
* Hide 3 more random tutorial tips popup from bottom-right panel
|
||||||
|
* 1.0.0
|
||||||
|
* Initial release
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>中文读我</summary>
|
||||||
|
|
||||||
|
## 更新日志
|
||||||
|
|
||||||
|
* 1.0.4
|
||||||
|
* 移除`关闭标题画面的演示场景加载`设置,因为在最近的更新中有较多bug。
|
||||||
|
* 修复了一个bug,当教程指引被这个MOD隐藏时,它们不会被添加到教程面板。
|
||||||
|
* 1.0.3
|
||||||
|
* 增加设置项以关闭研究完成的提示/弹窗
|
||||||
|
* 在README中增加了一个关于`关闭标题画面的演示场景加载`设置的兼容性说明
|
||||||
|
* 1.0.2
|
||||||
|
* 增加设置项以关闭标题画面的演示场景加载
|
||||||
|
* 1.0.1
|
||||||
|
* 可屏蔽右下面板的3种随机提醒
|
||||||
|
* 1.0.0
|
||||||
|
* 初始版本
|
||||||
|
|
||||||
|
</details>
|
||||||
@@ -152,7 +152,7 @@ public class HideTips : BaseUnityPlugin
|
|||||||
class HideMenuDemo
|
class HideMenuDemo
|
||||||
{
|
{
|
||||||
[HarmonyPriority(Priority.First), HarmonyPrefix]
|
[HarmonyPriority(Priority.First), HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(DSPGame), "StartDemoGame", typeof(int))]
|
[HarmonyPatch(typeof(DSPGame), nameof(DSPGame.StartDemoGame), typeof(int))]
|
||||||
private static bool DSPGame_StartDemoGame_Prefix()
|
private static bool DSPGame_StartDemoGame_Prefix()
|
||||||
{
|
{
|
||||||
if (DSPGame.Game != null)
|
if (DSPGame.Game != null)
|
||||||
@@ -188,7 +188,7 @@ class HideMenuDemo
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPriority(Priority.First), HarmonyPrefix]
|
[HarmonyPriority(Priority.First), HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(VFPreload), "IsMenuDemoLoaded")]
|
[HarmonyPatch(typeof(VFPreload), nameof(VFPreload.IsMenuDemoLoaded))]
|
||||||
private static bool VFPreload_IsMenuDemoLoaded_Prefix(ref bool __result)
|
private static bool VFPreload_IsMenuDemoLoaded_Prefix(ref bool __result)
|
||||||
{
|
{
|
||||||
__result = true;
|
__result = true;
|
||||||
@@ -196,18 +196,18 @@ class HideMenuDemo
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPriority(Priority.First), HarmonyPrefix]
|
[HarmonyPriority(Priority.First), HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(DSPGame), "LateUpdate")]
|
[HarmonyPatch(typeof(DSPGame), nameof(DSPGame.LateUpdate))]
|
||||||
[HarmonyPatch(typeof(GameMain), "LateUpdate")]
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.LateUpdate))]
|
||||||
[HarmonyPatch(typeof(GameMain), "FixedUpdate")]
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.FixedUpdate))]
|
||||||
[HarmonyPatch(typeof(GameMain), "Update")]
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Update))]
|
||||||
[HarmonyPatch(typeof(GameCamera), "LateUpdate")]
|
[HarmonyPatch(typeof(GameCamera), nameof(GameCamera.LateUpdate))]
|
||||||
private static bool DSPGame_LateUpdate_Prefix()
|
private static bool DSPGame_LateUpdate_Prefix()
|
||||||
{
|
{
|
||||||
return !DSPGame.IsMenuDemo;
|
return !DSPGame.IsMenuDemo;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPriority(Priority.First), HarmonyPrefix]
|
[HarmonyPriority(Priority.First), HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(GameMain), "Begin")]
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Begin))]
|
||||||
private static bool GameMain_Begin_Prefix()
|
private static bool GameMain_Begin_Prefix()
|
||||||
{
|
{
|
||||||
if (!DSPGame.IsMenuDemo) return true;
|
if (!DSPGame.IsMenuDemo) return true;
|
||||||
|
|||||||
@@ -1,29 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net472</TargetFramework>
|
|
||||||
<AssemblyName>HideTips</AssemblyName>
|
<AssemblyName>HideTips</AssemblyName>
|
||||||
<BepInExPluginGuid>org.soardev.hidetips</BepInExPluginGuid>
|
<BepInExPluginGuid>org.soardev.hidetips</BepInExPluginGuid>
|
||||||
<Description>DSP MOD - HideTips</Description>
|
<Description>DSP MOD - HideTips</Description>
|
||||||
<Version>1.0.4</Version>
|
<Version>1.0.4</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<PackHasChangelog>true</PackHasChangelog>
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
|
||||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
|
||||||
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<Exec Command="del /F /Q package\$(ProjectName)-$(Version).zip
powershell Compress-Archive -Force -DestinationPath 'package/$(ProjectName)-$(Version).zip' -Path '$(TargetPath)', package/icon.png, package/manifest.json, README.md" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,42 +1,23 @@
|
|||||||
# HideTips
|
# HideTips
|
||||||
|
|
||||||
#### Hide/Disable various tutorial tips/messages
|
<details>
|
||||||
#### 隐藏/屏蔽各种引导提示/消息
|
<summary>Read me in English</summary>
|
||||||
|
|
||||||
## Changelog
|
***Hide/Disable various tutorial tips/messages***
|
||||||
* 1.0.4
|
|
||||||
+ Remove `Disable title screen demo scene loading`, as it is buggy in recent updates.
|
|
||||||
+ Fix a bug that when tutorials are not added to the guides panel when they are hidden by this MOD.
|
|
||||||
* 1.0.3
|
|
||||||
+ Add config entries to disable research completion tips/popup windows
|
|
||||||
+ Add a note to README for mod compatibility on `Disable title screen demo scene loading`.
|
|
||||||
* 1.0.2
|
|
||||||
+ Add a config entry to disable title screen demo scene loading
|
|
||||||
* 1.0.1
|
|
||||||
+ Hide 3 more random tutorial tips popup from bottom-right panel
|
|
||||||
* 1.0.0
|
|
||||||
+ Initial release
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
* Tips/messages that can be hidden: random-reminder, tutorial, achievement/milestone card, research completion tips/popup windows.
|
* Tips/messages that can be hidden: random-reminder, tutorial, achievement/milestone card, research completion tips/popup windows.
|
||||||
* Skip prologue for new game.
|
* Skip prologue for new game.
|
||||||
* Each type of tips/messages is configurable individually.
|
* Each type of tips/messages is configurable individually.
|
||||||
|
|
||||||
## 更新日志
|
***隐藏/屏蔽各种引导提示/消息***
|
||||||
* 1.0.4
|
|
||||||
+ 移除`关闭标题画面的演示场景加载`设置,因为在最近的更新中有较多bug。
|
</details>
|
||||||
+ 修复了一个bug,当教程指引被这个MOD隐藏时,它们不会被添加到教程面板。
|
|
||||||
* 1.0.3
|
<details>
|
||||||
+ 增加设置项以关闭研究完成的提示/弹窗
|
<summary>中文读我</summary>
|
||||||
+ 在README中增加了一个关于`关闭标题画面的演示场景加载`设置的兼容性说明
|
|
||||||
* 1.0.2
|
|
||||||
+ 增加设置项以关闭标题画面的演示场景加载
|
|
||||||
* 1.0.1
|
|
||||||
+ 可屏蔽右下面板的3种随机提醒
|
|
||||||
* 1.0.0
|
|
||||||
+ 初始版本
|
|
||||||
|
|
||||||
## 使用说明
|
|
||||||
* 可以屏蔽的消息:随机提醒,教程,成就/里程碑卡片,研究完成的提示/弹窗。
|
* 可以屏蔽的消息:随机提醒,教程,成就/里程碑卡片,研究完成的提示/弹窗。
|
||||||
* 跳过新游戏引导动画。
|
* 跳过新游戏引导动画。
|
||||||
* 各种屏蔽功能都可以在配置文件里开关。
|
* 各种屏蔽功能都可以在配置文件里开关。
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|||||||
@@ -410,30 +410,30 @@ public static class LabOptPatchFunctions
|
|||||||
public static void SetFunctionInternal(ref LabComponent lab, bool researchMode, int recpId, int techId, SignData[] signPool, LabComponent[] labPool)
|
public static void SetFunctionInternal(ref LabComponent lab, bool researchMode, int recpId, int techId, SignData[] signPool, LabComponent[] labPool)
|
||||||
{
|
{
|
||||||
// LabOptPatch.Logger.LogDebug($"SetFunctionInternal: id={lab.id} root={(int)RootLabIdField.GetValue(lab)} research={researchMode} recp={recpId} tech={techId}");
|
// LabOptPatch.Logger.LogDebug($"SetFunctionInternal: id={lab.id} root={(int)RootLabIdField.GetValue(lab)} research={researchMode} recp={recpId} tech={techId}");
|
||||||
lab.replicating = false;
|
lab.replicating = false;
|
||||||
lab.time = 0;
|
lab.time = 0;
|
||||||
lab.hashBytes = 0;
|
lab.hashBytes = 0;
|
||||||
lab.extraHashBytes = 0;
|
lab.extraHashBytes = 0;
|
||||||
lab.extraTime = 0;
|
lab.extraTime = 0;
|
||||||
lab.extraSpeed = 0;
|
lab.extraSpeed = 0;
|
||||||
lab.extraPowerRatio = 0;
|
lab.extraPowerRatio = 0;
|
||||||
lab.productive = false;
|
lab.productive = false;
|
||||||
if (researchMode)
|
if (researchMode)
|
||||||
{
|
{
|
||||||
lab.forceAccMode = false;
|
lab.forceAccMode = false;
|
||||||
lab.researchMode = true;
|
lab.researchMode = true;
|
||||||
lab.recipeId = 0;
|
lab.recipeId = 0;
|
||||||
lab.techId = 0;
|
lab.techId = 0;
|
||||||
lab.timeSpend = 0;
|
lab.timeSpend = 0;
|
||||||
lab.extraTimeSpend = 0;
|
lab.extraTimeSpend = 0;
|
||||||
lab.requires = null;
|
lab.requires = null;
|
||||||
lab.requireCounts = null;
|
lab.requireCounts = null;
|
||||||
lab.served = null;
|
lab.served = null;
|
||||||
lab.incServed = null;
|
lab.incServed = null;
|
||||||
lab.products = null;
|
lab.products = null;
|
||||||
lab.productCounts = null;
|
lab.productCounts = null;
|
||||||
lab.produced = null;
|
lab.produced = null;
|
||||||
lab.productive = true;
|
lab.productive = true;
|
||||||
var rootLabId = lab.pcId;
|
var rootLabId = lab.pcId;
|
||||||
if (rootLabId > 0)
|
if (rootLabId > 0)
|
||||||
{
|
{
|
||||||
@@ -480,29 +480,29 @@ public static class LabOptPatchFunctions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
signPool[lab.entityId].iconId0 = (uint)lab.techId;
|
signPool[lab.entityId].iconId0 = (uint)lab.techId;
|
||||||
signPool[lab.entityId].iconType = lab.techId == 0 ? 0U : 3U;
|
signPool[lab.entityId].iconType = lab.techId == 0 ? 0U : 3U;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lab.researchMode = false;
|
lab.researchMode = false;
|
||||||
lab.recipeId = 0;
|
lab.recipeId = 0;
|
||||||
lab.techId = 0;
|
lab.techId = 0;
|
||||||
lab.matrixPoints = null;
|
lab.matrixPoints = null;
|
||||||
lab.matrixServed = null;
|
lab.matrixServed = null;
|
||||||
lab.matrixIncServed = null;
|
lab.matrixIncServed = null;
|
||||||
RecipeProto recipeProto = null;
|
RecipeProto recipeProto = null;
|
||||||
if (recpId > 0)
|
if (recpId > 0)
|
||||||
{
|
{
|
||||||
recipeProto = LDB.recipes.Select(recpId);
|
recipeProto = LDB.recipes.Select(recpId);
|
||||||
}
|
}
|
||||||
if (recipeProto != null && recipeProto.Type == ERecipeType.Research)
|
if (recipeProto != null && recipeProto.Type == ERecipeType.Research)
|
||||||
{
|
{
|
||||||
lab.recipeId = recipeProto.ID;
|
lab.recipeId = recipeProto.ID;
|
||||||
lab.speed = 10000;
|
lab.speed = 10000;
|
||||||
lab.speedOverride = lab.speed;
|
lab.speedOverride = lab.speed;
|
||||||
lab.timeSpend = recipeProto.TimeSpend * 10000;
|
lab.timeSpend = recipeProto.TimeSpend * 10000;
|
||||||
lab.extraTimeSpend = recipeProto.TimeSpend * 100000;
|
lab.extraTimeSpend = recipeProto.TimeSpend * 100000;
|
||||||
lab.productive = recipeProto.productive;
|
lab.productive = recipeProto.productive;
|
||||||
lab.forceAccMode &= lab.productive;
|
lab.forceAccMode &= lab.productive;
|
||||||
var rootLabId = lab.pcId;
|
var rootLabId = lab.pcId;
|
||||||
if (rootLabId > 0)
|
if (rootLabId > 0)
|
||||||
{
|
{
|
||||||
@@ -544,26 +544,26 @@ public static class LabOptPatchFunctions
|
|||||||
Array.Clear(lab.produced, 0, lab.produced.Length);
|
Array.Clear(lab.produced, 0, lab.produced.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lab.forceAccMode = false;
|
lab.forceAccMode = false;
|
||||||
lab.recipeId = 0;
|
lab.recipeId = 0;
|
||||||
lab.speed = 0;
|
lab.speed = 0;
|
||||||
lab.speedOverride = 0;
|
lab.speedOverride = 0;
|
||||||
lab.timeSpend = 0;
|
lab.timeSpend = 0;
|
||||||
lab.extraTimeSpend = 0;
|
lab.extraTimeSpend = 0;
|
||||||
lab.requires = null;
|
lab.requires = null;
|
||||||
lab.requireCounts = null;
|
lab.requireCounts = null;
|
||||||
lab.served = null;
|
lab.served = null;
|
||||||
lab.incServed = null;
|
lab.incServed = null;
|
||||||
lab.needs = null;
|
lab.needs = null;
|
||||||
lab.products = null;
|
lab.products = null;
|
||||||
lab.productCounts = null;
|
lab.productCounts = null;
|
||||||
lab.produced = null;
|
lab.produced = null;
|
||||||
}
|
}
|
||||||
signPool[lab.entityId].iconId0 = (uint)lab.recipeId;
|
signPool[lab.entityId].iconId0 = (uint)lab.recipeId;
|
||||||
signPool[lab.entityId].iconType = lab.recipeId == 0 ? 0U : 2U;
|
signPool[lab.entityId].iconType = lab.recipeId == 0 ? 0U : 2U;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int InsertIntoLab(PlanetFactory factory, int labId, int itemId, byte itemCount, byte itemInc, ref byte remainInc, int[] needs)
|
public static int InsertIntoLab(PlanetFactory factory, int labId, int itemId, byte itemCount, byte itemInc, ref byte remainInc, int[] needs)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public class LabOptPatch : BaseUnityPlugin
|
|||||||
{
|
{
|
||||||
Harmony.CreateAndPatchAll(typeof(LabOptPatch));
|
Harmony.CreateAndPatchAll(typeof(LabOptPatch));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Patch LabComponent.Export() to save zero value if rootLabId > 0.
|
// Patch LabComponent.Export() to save zero value if rootLabId > 0.
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(LabComponent), nameof(LabComponent.Export))]
|
[HarmonyPatch(typeof(LabComponent), nameof(LabComponent.Export))]
|
||||||
@@ -274,7 +274,7 @@ public class LabOptPatch : BaseUnityPlugin
|
|||||||
);
|
);
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change locks on PlanetFactory.InsertInto(), by calling LabOptPatchFunctions.InsertIntoLab()
|
// Change locks on PlanetFactory.InsertInto(), by calling LabOptPatchFunctions.InsertIntoLab()
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.InsertInto))]
|
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.InsertInto))]
|
||||||
@@ -332,7 +332,7 @@ public class LabOptPatch : BaseUnityPlugin
|
|||||||
{
|
{
|
||||||
LabOptPatchFunctions.SetRootId(ref __instance, 0);
|
LabOptPatchFunctions.SetRootId(ref __instance, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.SetRootId))]
|
[HarmonyPatch(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.SetRootId))]
|
||||||
[HarmonyPatch(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.SetRootLabIdForStacking))]
|
[HarmonyPatch(typeof(LabOptPatchFunctions), nameof(LabOptPatchFunctions.SetRootLabIdForStacking))]
|
||||||
|
|||||||
@@ -1,29 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net472</TargetFramework>
|
|
||||||
<AssemblyName>LabOpt</AssemblyName>
|
<AssemblyName>LabOpt</AssemblyName>
|
||||||
<BepInExPluginGuid>org.soardev.labopt</BepInExPluginGuid>
|
<BepInExPluginGuid>org.soardev.labopt</BepInExPluginGuid>
|
||||||
<Description>DSP MOD - LabOpt</Description>
|
<Description>DSP MOD - LabOpt</Description>
|
||||||
<Version>0.3.6</Version>
|
<Version>0.3.6</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<PackUsePluginsLayout>true</PackUsePluginsLayout>
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
|
||||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
|
||||||
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<Exec Command="del /F /Q package\$(ProjectName)-$(Version).zip
IF NOT EXIST package\plugins (mkdir package\plugins)
copy /y $(TargetPath) package\plugins\
cd package
powershell Compress-Archive -Force -DestinationPath '$(ProjectName)-$(Version).zip' -Path patchers, plugins, icon.png, manifest.json, ../README.md" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace LabOptPreloader;
|
|||||||
|
|
||||||
public static class Preloader
|
public static class Preloader
|
||||||
{
|
{
|
||||||
private static readonly ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("LabOpt Preloader");
|
private static readonly ManualLogSource Logger = BepInEx.Logging.Logger.CreateLogSource("LabOpt Preloader");
|
||||||
public static IEnumerable<string> TargetDLLs { get; } = new[] { "Assembly-CSharp.dll" };
|
public static IEnumerable<string> TargetDLLs { get; } = new[] { "Assembly-CSharp.dll" };
|
||||||
|
|
||||||
public static void Patch(AssemblyDefinition assembly)
|
public static void Patch(AssemblyDefinition assembly)
|
||||||
|
|||||||
@@ -1,28 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net472</TargetFramework>
|
|
||||||
<AssemblyName>LabOptPreloader</AssemblyName>
|
<AssemblyName>LabOptPreloader</AssemblyName>
|
||||||
<Description>DSP MOD - Prealoder for LabOpt</Description>
|
<Description>DSP MOD - Preloader for LabOpt</Description>
|
||||||
<Version>0.2.1</Version>
|
<Version>0.2.1</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<PackPreloaderTargetDir>..\LabOpt\package\patchers</PackPreloaderTargetDir>
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
|
||||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
|
||||||
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<Exec Command="IF NOT EXIST ..\LabOpt\package\patchers (mkdir ..\LabOpt\package\patchers)
copy /y $(TargetPath) ..\LabOpt\package\patchers\" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
|
|
||||||
private static long _oreEnergyConsume = 2000000;
|
private static long _oreEnergyConsume = 2000000;
|
||||||
private static long _oilEnergyConsume = 3600000;
|
private static long _oilEnergyConsume = 3600000;
|
||||||
private static long _waterEnergyConsume = 20000000;
|
private static long _waterEnergyConsume = 2000000;
|
||||||
private static int _waterSpeed = 100;
|
private static int _waterSpeed = 10;
|
||||||
private static int _miningScale;
|
private static int _miningScale;
|
||||||
private static int _fuelIlsSlot = 3;
|
private static int _fuelIlsSlot = 3;
|
||||||
private static int _fuelPlsSlot = 2;
|
private static int _fuelPlsSlot = 3;
|
||||||
|
|
||||||
private static float _frame;
|
private static float _frame;
|
||||||
private static float _miningCostRateByTech;
|
private static float _miningCostRateByTech;
|
||||||
@@ -31,8 +31,8 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
private static uint _miningCostBarrierOil;
|
private static uint _miningCostBarrierOil;
|
||||||
|
|
||||||
private static uint _seed = (uint)Random.Range(int.MinValue, int.MaxValue);
|
private static uint _seed = (uint)Random.Range(int.MinValue, int.MaxValue);
|
||||||
private static readonly Dictionary<int, VeinCacheData> PlanetVeinCacheData = new();
|
private static readonly Dictionary<int, VeinCacheData> PlanetVeinCacheData = [];
|
||||||
private static readonly Dictionary<int, (long, bool)> Fuels = new();
|
private static readonly Dictionary<int, (long, bool)> Fuels = [];
|
||||||
|
|
||||||
private bool _cfgEnabled = true;
|
private bool _cfgEnabled = true;
|
||||||
|
|
||||||
@@ -52,11 +52,11 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
.Value;
|
.Value;
|
||||||
_fuelIlsSlot = Config.Bind("General", "ILSFuelSlot", _fuelIlsSlot + 1,
|
_fuelIlsSlot = Config.Bind("General", "ILSFuelSlot", _fuelIlsSlot + 1,
|
||||||
new ConfigDescription("Fuel slot for ILS, set to 0 to disable",
|
new ConfigDescription("Fuel slot for ILS, set to 0 to disable",
|
||||||
new AcceptableValueRange<int>(0, 5), Array.Empty<object>()))
|
new AcceptableValueRange<int>(0, 5), []))
|
||||||
.Value - 1;
|
.Value - 1;
|
||||||
_fuelPlsSlot = Config.Bind("General", "PLSFuelSlot", _fuelPlsSlot + 1,
|
_fuelPlsSlot = Config.Bind("General", "PLSFuelSlot", _fuelPlsSlot + 1,
|
||||||
new ConfigDescription("Fuel slot for PLS, set to 0 to disable",
|
new ConfigDescription("Fuel slot for PLS, set to 0 to disable",
|
||||||
new AcceptableValueRange<int>(0, 4), Array.Empty<object>()))
|
new AcceptableValueRange<int>(0, 4), []))
|
||||||
.Value - 1;
|
.Value - 1;
|
||||||
if (!_cfgEnabled) return;
|
if (!_cfgEnabled) return;
|
||||||
|
|
||||||
@@ -98,8 +98,8 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(DSPGame), "StartGame", typeof(GameDesc))]
|
[HarmonyPatch(typeof(DSPGame), nameof(DSPGame.StartGame), typeof(GameDesc))]
|
||||||
[HarmonyPatch(typeof(DSPGame), "StartGame", typeof(string))]
|
[HarmonyPatch(typeof(DSPGame), nameof(DSPGame.StartGame), typeof(string))]
|
||||||
private static void OnGameStart()
|
private static void OnGameStart()
|
||||||
{
|
{
|
||||||
Logger.LogInfo("Game Start");
|
Logger.LogInfo("Game Start");
|
||||||
@@ -119,7 +119,7 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(GameMain), "Start")]
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Start))]
|
||||||
private static void OnGameLoaded()
|
private static void OnGameLoaded()
|
||||||
{
|
{
|
||||||
_frame = 0f;
|
_frame = 0f;
|
||||||
@@ -130,7 +130,7 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(GameHistoryData), "UnlockTechFunction")]
|
[HarmonyPatch(typeof(GameHistoryData), nameof(GameHistoryData.UnlockTechFunction))]
|
||||||
private static void OnUnlockTech(int func)
|
private static void OnUnlockTech(int func)
|
||||||
{
|
{
|
||||||
switch (func)
|
switch (func)
|
||||||
@@ -145,7 +145,7 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(GameData), "GameTick")]
|
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic.OnFactoryFrameBegin))]
|
||||||
private static void FrameTick()
|
private static void FrameTick()
|
||||||
{
|
{
|
||||||
var main = GameMain.instance;
|
var main = GameMain.instance;
|
||||||
@@ -165,7 +165,7 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(GameHistoryData), "UnlockRecipe")]
|
[HarmonyPatch(typeof(GameHistoryData), nameof(GameHistoryData.UnlockRecipe))]
|
||||||
private static void OnUnlockRecipe(int recipeId)
|
private static void OnUnlockRecipe(int recipeId)
|
||||||
{
|
{
|
||||||
if (recipeId == 119)
|
if (recipeId == 119)
|
||||||
@@ -175,9 +175,9 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(PlanetFactory), "Init")]
|
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.Init))]
|
||||||
[HarmonyPatch(typeof(PlanetFactory), "RecalculateVeinGroup")]
|
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.RecalculateVeinGroup))]
|
||||||
[HarmonyPatch(typeof(PlanetFactory), "RecalculateAllVeinGroups")]
|
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.RecalculateAllVeinGroups))]
|
||||||
private static void NeedRecalcVeins(PlanetFactory __instance)
|
private static void NeedRecalcVeins(PlanetFactory __instance)
|
||||||
{
|
{
|
||||||
RecalcVeins(__instance);
|
RecalcVeins(__instance);
|
||||||
@@ -204,13 +204,12 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(FactorySystem), "CheckBeforeGameTick")]
|
[HarmonyPatch(typeof(PlanetFactory), nameof(PlanetFactory.BeforeGameTick))]
|
||||||
private static void FactorySystemLogisticMiner(FactorySystem __instance)
|
private static void FactorySystemLogisticMiner(PlanetFactory __instance)
|
||||||
{
|
{
|
||||||
if (_miningSpeedScaleLong <= 0)
|
if (_miningSpeedScaleLong <= 0)
|
||||||
return;
|
return;
|
||||||
var factory = __instance.factory;
|
var planetId = __instance.planetId;
|
||||||
var planetId = factory.planetId;
|
|
||||||
lock (PlanetVeinCacheData)
|
lock (PlanetVeinCacheData)
|
||||||
{
|
{
|
||||||
if (PlanetVeinCacheData.TryGetValue(planetId, out var vcd))
|
if (PlanetVeinCacheData.TryGetValue(planetId, out var vcd))
|
||||||
@@ -227,11 +226,11 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var planetTransport = __instance.planet.factory.transport;
|
var planetTransport = __instance.transport;
|
||||||
var factoryProductionStat =
|
var factoryProductionStat =
|
||||||
GameMain.statistics.production.factoryStatPool[__instance.factory.index];
|
GameMain.statistics.production.factoryStatPool[__instance.index];
|
||||||
var productRegister = factoryProductionStat?.productRegister;
|
var productRegister = factoryProductionStat?.productRegister;
|
||||||
PerformanceMonitor.BeginSample(ECpuWorkEntry.Miner);
|
DeepProfiler.BeginSample(DPEntry.Miner);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
for (var j = 1; j < planetTransport.stationCursor; j++)
|
for (var j = 1; j < planetTransport.stationCursor; j++)
|
||||||
@@ -271,7 +270,7 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
|
|
||||||
if (isVein)
|
if (isVein)
|
||||||
{
|
{
|
||||||
(amount, energyConsume) = vcd.Mine(factory, stationStore.itemId, miningScale,
|
(amount, energyConsume) = vcd.Mine(__instance, stationStore.itemId, miningScale,
|
||||||
_miningSpeedScaleLong,
|
_miningSpeedScaleLong,
|
||||||
stationComponent.energy);
|
stationComponent.energy);
|
||||||
if (amount < 0)
|
if (amount < 0)
|
||||||
@@ -334,7 +333,7 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
vcd.FrameNext += _miningFrames;
|
vcd.FrameNext += _miningFrames;
|
||||||
} while (vcd.FrameNext <= _frame);
|
} while (vcd.FrameNext <= _frame);
|
||||||
|
|
||||||
PerformanceMonitor.EndSample(ECpuWorkEntry.Miner);
|
DeepProfiler.EndSample(DPEntry.Miner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,7 +342,7 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
public float FrameNext;
|
public float FrameNext;
|
||||||
|
|
||||||
/* stores list of indices to veinData, with an extra INT which indicates cout of veinGroups at last */
|
/* stores list of indices to veinData, with an extra INT which indicates cout of veinGroups at last */
|
||||||
private Dictionary<int, List<int>> _veins = new();
|
private Dictionary<int, List<int>> _veins = [];
|
||||||
private int _mineIndex = -1;
|
private int _mineIndex = -1;
|
||||||
|
|
||||||
public bool HasVein(int productId)
|
public bool HasVein(int productId)
|
||||||
@@ -353,9 +352,9 @@ public class LogisticMiner : BaseUnityPlugin
|
|||||||
|
|
||||||
public void GenVeins(PlanetFactory factory)
|
public void GenVeins(PlanetFactory factory)
|
||||||
{
|
{
|
||||||
_veins = new Dictionary<int, List<int>>();
|
_veins = [];
|
||||||
var veinPool = factory.veinPool;
|
var veinPool = factory.veinPool;
|
||||||
var vg = new Dictionary<int, HashSet<int>>();
|
Dictionary<int, HashSet<int>> vg = [];
|
||||||
for (var i = 0; i < veinPool.Length; i++)
|
for (var i = 0; i < veinPool.Length; i++)
|
||||||
{
|
{
|
||||||
if (veinPool[i].amount <= 0 || veinPool[i].type == EVeinType.None) continue;
|
if (veinPool[i].amount <= 0 || veinPool[i].type == EVeinType.None) continue;
|
||||||
|
|||||||
@@ -1,25 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net472</TargetFramework>
|
|
||||||
<AssemblyName>LogisticMiner</AssemblyName>
|
<AssemblyName>LogisticMiner</AssemblyName>
|
||||||
<BepInExPluginGuid>org.soardev.logisticminer</BepInExPluginGuid>
|
<BepInExPluginGuid>org.soardev.logisticminer</BepInExPluginGuid>
|
||||||
<Description>DSP MOD - LogisticMiner</Description>
|
<Description>DSP MOD - LogisticMiner</Description>
|
||||||
<Version>0.1.0</Version>
|
<Version>0.2.0</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
|
||||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
|
||||||
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
reaches Advanced Mining Machine, otherwise 100.
|
reaches Advanced Mining Machine, otherwise 100.
|
||||||
* 100/s for water by default.
|
* 100/s for water by default.
|
||||||
* Energy costs: 1MW/vein-group & 10MW/water-slot & 1.8MW/oil-seep(configurable)
|
* Energy costs: 1MW/vein-group & 10MW/water-slot & 1.8MW/oil-seep(configurable)
|
||||||
* Fuels burning slot. Default: 4th for ILS, 3rd for PLS. Set to 0 to disable it.
|
* Fuels burning slot. Default: 4th for ILS, 4th for PLS. Set to 0 to disable it.
|
||||||
|
|
||||||
## 使用说明
|
## 使用说明
|
||||||
|
|
||||||
@@ -47,4 +47,4 @@
|
|||||||
倍率可以设置为0(默认),此时倍率会随科技解锁而变化,默认是100%,解锁高级采矿机后变为300%。
|
倍率可以设置为0(默认),此时倍率会随科技解锁而变化,默认是100%,解锁高级采矿机后变为300%。
|
||||||
* 水的采集速度默认为100/s。
|
* 水的采集速度默认为100/s。
|
||||||
* 能耗:每矿物组 1MW,单格水 10MW,每油井 1.8MW。
|
* 能耗:每矿物组 1MW,单格水 10MW,每油井 1.8MW。
|
||||||
* 燃料格位置。默认:星际物流塔第4格,行星内物流塔第3格。设为0则关闭燃料补充能量功能。
|
* 燃料格位置。默认:星际物流塔第4格,行星内物流塔第4格。设为0则关闭燃料补充能量功能。
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "LogisticMiner",
|
"name": "LogisticMiner",
|
||||||
"version_number": "0.1.0",
|
"version_number": "0.2.0",
|
||||||
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/LogisticMiner",
|
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/LogisticMiner",
|
||||||
"description": "Logistic Storages can mine all ores/water on current planet / 物流塔可以采集当前星球的全部矿产(以及水)",
|
"description": "Logistic Storages can mine all ores/water on current planet / 物流塔可以采集当前星球的全部矿产(以及水)",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|||||||
7
LuaScriptEngine/CHANGELOG.md
Normal file
7
LuaScriptEngine/CHANGELOG.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
## Changlog
|
||||||
|
* 1.0.0
|
||||||
|
+ Initial release
|
||||||
|
|
||||||
|
## 更新日志
|
||||||
|
* 1.0.0
|
||||||
|
+ 初始版本
|
||||||
84
LuaScriptEngine/LuaScriptEngine.cs
Normal file
84
LuaScriptEngine/LuaScriptEngine.cs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using BepInEx;
|
||||||
|
using BepInEx.Logging;
|
||||||
|
using HarmonyLib;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using NLua;
|
||||||
|
|
||||||
|
namespace LuaScriptEngine;
|
||||||
|
|
||||||
|
[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)]
|
||||||
|
public class LuaScriptEngine : BaseUnityPlugin
|
||||||
|
{
|
||||||
|
public new static readonly ManualLogSource Logger =
|
||||||
|
BepInEx.Logging.Logger.CreateLogSource(PluginInfo.PLUGIN_NAME);
|
||||||
|
|
||||||
|
private Harmony _harmony;
|
||||||
|
|
||||||
|
private static readonly LuaState State = new();
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
_harmony = Harmony.CreateAndPatchAll(typeof(Patches));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
_harmony?.UnpatchSelf();
|
||||||
|
State.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Patches
|
||||||
|
{
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(VFPreload), nameof(VFPreload.InvokeOnLoadWorkEnded))]
|
||||||
|
private static void VFPreload_InvokeOnLoadWorkEnded_Postfix()
|
||||||
|
{
|
||||||
|
State.PostDataLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.FixedUpdate))]
|
||||||
|
private static void GameMain_FixedUpdate_Prefix()
|
||||||
|
{
|
||||||
|
State.PreUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.FixedUpdate))]
|
||||||
|
private static void GameMain_FixedUpdate_Postfix()
|
||||||
|
{
|
||||||
|
State.PostUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Begin))]
|
||||||
|
private static void GameMain_Begin_Prefix()
|
||||||
|
{
|
||||||
|
State.PreGameBegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Begin))]
|
||||||
|
private static void GameMain_Begin_Postfix()
|
||||||
|
{
|
||||||
|
State.PostGameBegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.End))]
|
||||||
|
private static void GameMain_End_Prefix()
|
||||||
|
{
|
||||||
|
State.PreGameEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.End))]
|
||||||
|
private static void GameMain_End_Postfix()
|
||||||
|
{
|
||||||
|
State.PostGameEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
LuaScriptEngine/LuaScriptEngine.csproj
Normal file
17
LuaScriptEngine/LuaScriptEngine.csproj
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- Override the default net472 from Directory.Build.props -->
|
||||||
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
|
<AssemblyName>LuaScriptEngine</AssemblyName>
|
||||||
|
<BepInExPluginGuid>org.soardev.luascriptengine</BepInExPluginGuid>
|
||||||
|
<Description>DSP MOD - LuaScriptEngine</Description>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="NLua" Version="1.*" />
|
||||||
|
<PackageReference Include="obs-websocket-dotnet" Version="5.*" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
404
LuaScriptEngine/LuaState.cs
Normal file
404
LuaScriptEngine/LuaState.cs
Normal file
@@ -0,0 +1,404 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using NLua;
|
||||||
|
using OBSWebsocketDotNet;
|
||||||
|
|
||||||
|
namespace LuaScriptEngine;
|
||||||
|
|
||||||
|
public class LuaState : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Lua state = new();
|
||||||
|
private readonly List<LuaFunction> PostDataLoadedFuncs = [];
|
||||||
|
private readonly List<LuaFunction> PreUpdateFuncs = [];
|
||||||
|
private readonly List<LuaFunction> PostUpdateFuncs = [];
|
||||||
|
private readonly List<LuaFunction> PreGameBeginFuncs = [];
|
||||||
|
private readonly List<LuaFunction> PostGameBeginFuncs = [];
|
||||||
|
private readonly List<LuaFunction> PreGameEndFuncs = [];
|
||||||
|
private readonly List<LuaFunction> PostGameEndFuncs = [];
|
||||||
|
private readonly HashSet<Timer> Timers = [];
|
||||||
|
private readonly List<Timer> TimersToRemove = [];
|
||||||
|
private readonly OBSWebsocket _obs = new();
|
||||||
|
private readonly Dictionary<string, string> _scheduledText = [];
|
||||||
|
|
||||||
|
private long _lastSeedKey = 0L;
|
||||||
|
private string _lastClusterString = "";
|
||||||
|
|
||||||
|
public LuaState()
|
||||||
|
{
|
||||||
|
var assemblyPath = System.IO.Path.Combine(
|
||||||
|
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)!,
|
||||||
|
"scripts"
|
||||||
|
);
|
||||||
|
|
||||||
|
state.State.Encoding = Encoding.UTF8;
|
||||||
|
state.LoadCLRPackage();
|
||||||
|
state.DoString("import('Assembly-CSharp')");
|
||||||
|
state.DoString($"package.path = '{assemblyPath.Replace('\\', '/')}/?.lua'");
|
||||||
|
RegisterFunctions();
|
||||||
|
|
||||||
|
foreach (var file in System.IO.Directory.GetFiles(assemblyPath, "*.lua"))
|
||||||
|
{
|
||||||
|
LuaScriptEngine.Logger.LogInfo($"Loading Lua script: {file}");
|
||||||
|
state.DoFile(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
state.Dispose();
|
||||||
|
if (_obs.IsConnected)
|
||||||
|
{
|
||||||
|
_obs.Disconnect();
|
||||||
|
}
|
||||||
|
_scheduledText.Clear();
|
||||||
|
Timers.Clear();
|
||||||
|
PreUpdateFuncs.Clear();
|
||||||
|
PostUpdateFuncs.Clear();
|
||||||
|
PreGameBeginFuncs.Clear();
|
||||||
|
PostGameBeginFuncs.Clear();
|
||||||
|
PreGameEndFuncs.Clear();
|
||||||
|
PostGameEndFuncs.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RegisterFunctions()
|
||||||
|
{
|
||||||
|
#region Callback Functions
|
||||||
|
state["register_callback"] = (string tp, LuaFunction action) =>
|
||||||
|
{
|
||||||
|
switch (tp)
|
||||||
|
{
|
||||||
|
case "data_loaded":
|
||||||
|
PostDataLoadedFuncs.Add(action);
|
||||||
|
break;
|
||||||
|
case "pre_update":
|
||||||
|
PreUpdateFuncs.Add(action);
|
||||||
|
break;
|
||||||
|
case "post_update":
|
||||||
|
PostUpdateFuncs.Add(action);
|
||||||
|
break;
|
||||||
|
case "pre_game_begin":
|
||||||
|
PreGameBeginFuncs.Add(action);
|
||||||
|
break;
|
||||||
|
case "post_game_begin":
|
||||||
|
PostGameBeginFuncs.Add(action);
|
||||||
|
break;
|
||||||
|
case "pre_game_end":
|
||||||
|
PreGameEndFuncs.Add(action);
|
||||||
|
break;
|
||||||
|
case "post_game_end":
|
||||||
|
PostGameEndFuncs.Add(action);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
state["add_timer"] = Timer (LuaFunction func, long firstInterval, long repeatInterval) =>
|
||||||
|
{
|
||||||
|
var timer = new Timer(func, firstInterval, repeatInterval);
|
||||||
|
Timers.Add(timer);
|
||||||
|
return timer;
|
||||||
|
};
|
||||||
|
|
||||||
|
state["remove_timer"] = void (Timer timer) => { Timers.Remove(timer); };
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region OBS Functions
|
||||||
|
state["obs_connect"] = void (string server, string password) =>
|
||||||
|
{
|
||||||
|
if (_obs.IsConnected)
|
||||||
|
{
|
||||||
|
LuaScriptEngine.Logger.LogInfo("Already connected to OBS");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_obs.Connected += (_, _) =>
|
||||||
|
{
|
||||||
|
LuaScriptEngine.Logger.LogInfo($"Connected to OBS at {server}");
|
||||||
|
foreach (var (sourceName, text) in _scheduledText)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_obs.SetInputSettings(sourceName,
|
||||||
|
new JObject
|
||||||
|
{
|
||||||
|
{ "text", text }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LuaScriptEngine.Logger.LogError($"Error setting {sourceName}'s text to `{text}`: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_scheduledText.Clear();
|
||||||
|
};
|
||||||
|
_obs.Disconnected += (_, _) =>
|
||||||
|
{
|
||||||
|
_obs.ConnectAsync(server, password);
|
||||||
|
};
|
||||||
|
_obs.ConnectAsync(server, password);
|
||||||
|
};
|
||||||
|
|
||||||
|
state["obs_disconnect"] = void () =>
|
||||||
|
{
|
||||||
|
_obs.Disconnect();
|
||||||
|
};
|
||||||
|
|
||||||
|
state["obs_set_source_text"] = void (string sourceName, string text) =>
|
||||||
|
{
|
||||||
|
if (_obs.IsConnected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_obs.SetInputSettings(sourceName, new JObject
|
||||||
|
{
|
||||||
|
{ "text", text }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LuaScriptEngine.Logger.LogError($"Error setting source text: {e}");
|
||||||
|
_obs.Disconnect();
|
||||||
|
_scheduledText[sourceName] = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_scheduledText[sourceName] = text;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Common Data Retrieval Functions
|
||||||
|
state["get_current_cluster"] = string () =>
|
||||||
|
{
|
||||||
|
var data = GameMain.data;
|
||||||
|
if (data == null) return "";
|
||||||
|
var seedKey = data.GetClusterSeedKey();
|
||||||
|
if (seedKey == _lastSeedKey) return _lastClusterString;
|
||||||
|
_lastSeedKey = seedKey;
|
||||||
|
_lastClusterString = data.gameDesc.clusterString;
|
||||||
|
return _lastClusterString;
|
||||||
|
};
|
||||||
|
|
||||||
|
var getCurrentResearch = () =>
|
||||||
|
{
|
||||||
|
var history = GameMain.history;
|
||||||
|
if (history == null) return (0, 0, 0L, 0L);
|
||||||
|
var current = history.currentTech;
|
||||||
|
if (current == 0) return (0, 0, 0L, 0L);
|
||||||
|
var techStates = history.techStates;
|
||||||
|
if (!techStates.TryGetValue(current, out var value)) return (0, 0, 0L, 0L);
|
||||||
|
return (current, value.curLevel, value.hashUploaded, value.hashNeeded);
|
||||||
|
};
|
||||||
|
state["get_current_research"] = getCurrentResearch;
|
||||||
|
state["get_current_research_str"] = string (string format) =>
|
||||||
|
{
|
||||||
|
var (current, level, hashUploaded, hashNeeded) = getCurrentResearch();
|
||||||
|
if (current == 0) return "";
|
||||||
|
return string.Format(format, LDB.techs.Select(current).name, level, JournalUtility.TranslateKMGValue(hashUploaded), JournalUtility.TranslateKMGValue(hashNeeded));
|
||||||
|
};
|
||||||
|
|
||||||
|
var getTechLevel = (NLua.LuaTable techIds) =>
|
||||||
|
{
|
||||||
|
var techStates = GameMain.history?.techStates;
|
||||||
|
if (techStates == null) return 0;
|
||||||
|
int level = 0;
|
||||||
|
foreach (var techId in techIds.Values.Cast<long>())
|
||||||
|
{
|
||||||
|
if (!techStates.TryGetValue((int)techId, out var value))
|
||||||
|
{
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
var newLevel = value.unlocked ? value.curLevel : value.curLevel - 1;
|
||||||
|
if (newLevel > level)
|
||||||
|
{
|
||||||
|
level = newLevel;
|
||||||
|
}
|
||||||
|
if (!value.unlocked)
|
||||||
|
{
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return level;
|
||||||
|
};
|
||||||
|
state["get_tech_level"] = getTechLevel;
|
||||||
|
state["get_tech_level_str"] = string (string format, NLua.LuaTable techIds) =>
|
||||||
|
{
|
||||||
|
var level = getTechLevel(techIds);
|
||||||
|
if (level <= 0) return "";
|
||||||
|
return string.Format(format, level);
|
||||||
|
};
|
||||||
|
|
||||||
|
var getFactoryStat = (int itemId) =>
|
||||||
|
{
|
||||||
|
var gameData = GameMain.data;
|
||||||
|
if (gameData == null) return (0, 0);
|
||||||
|
var statPool = GameMain.statistics?.production.factoryStatPool;
|
||||||
|
if (statPool == null) return (0, 0);
|
||||||
|
long productTotal = 0L, consumeTotal = 0L;
|
||||||
|
for (var i = gameData.factoryCount - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var stat = statPool[i];
|
||||||
|
if (stat == null) continue;
|
||||||
|
var index = stat.productIndices[itemId];
|
||||||
|
var ppool = stat.productPool[index];
|
||||||
|
if (ppool == null) continue;
|
||||||
|
var cursor = ppool.cursor[4];
|
||||||
|
if (cursor > 0)
|
||||||
|
{
|
||||||
|
productTotal += ppool.count[cursor - 1];
|
||||||
|
}
|
||||||
|
cursor = ppool.cursor[4 + 6];
|
||||||
|
if (cursor > 0)
|
||||||
|
{
|
||||||
|
consumeTotal += ppool.count[cursor - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (productTotal, consumeTotal);
|
||||||
|
};
|
||||||
|
state["get_factory_stat"] = getFactoryStat;
|
||||||
|
state["get_factory_stat_str"] = string (string format, int itemId) =>
|
||||||
|
{
|
||||||
|
var (productTotal, consumeTotal) = getFactoryStat(itemId);
|
||||||
|
return string.Format(format, JournalUtility.TranslateKMGValue(productTotal), JournalUtility.TranslateKMGValue(consumeTotal));
|
||||||
|
};
|
||||||
|
|
||||||
|
var getDysonSphereTotalGen = () =>
|
||||||
|
{
|
||||||
|
var data = GameMain.data;
|
||||||
|
if (data == null) return 0;
|
||||||
|
return data.GetDysonSphereTotalGen();
|
||||||
|
};
|
||||||
|
state["get_dyson_sphere_power_gen"] = getDysonSphereTotalGen;
|
||||||
|
state["get_dyson_sphere_power_gen_str"] = string (string format) =>
|
||||||
|
{
|
||||||
|
var totalGen = getDysonSphereTotalGen();
|
||||||
|
if (totalGen <= 0) return "";
|
||||||
|
return string.Format(format, JournalUtility.TranslateKMGValue(totalGen * 60L));
|
||||||
|
};
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostDataLoaded()
|
||||||
|
{
|
||||||
|
LoopCall(PostDataLoadedFuncs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PreUpdate()
|
||||||
|
{
|
||||||
|
if (Timers.Count > 0)
|
||||||
|
{
|
||||||
|
var gameTick = GameMain.gameTick;
|
||||||
|
foreach (var timer in Timers)
|
||||||
|
{
|
||||||
|
if (timer == null || !timer.Check(gameTick)) continue;
|
||||||
|
TimersToRemove.Add(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TimersToRemove.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var timer in TimersToRemove)
|
||||||
|
{
|
||||||
|
Timers.Remove(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimersToRemove.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LoopCall(PreUpdateFuncs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostUpdate()
|
||||||
|
{
|
||||||
|
LoopCall(PostUpdateFuncs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PreGameBegin()
|
||||||
|
{
|
||||||
|
var tick = GameMain.gameTick;
|
||||||
|
foreach (var timer in Timers)
|
||||||
|
{
|
||||||
|
if (timer.Reset(tick))
|
||||||
|
{
|
||||||
|
TimersToRemove.Add(timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TimersToRemove.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var timer in TimersToRemove)
|
||||||
|
{
|
||||||
|
Timers.Remove(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimersToRemove.Clear();
|
||||||
|
}
|
||||||
|
LoopCall(PreGameBeginFuncs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostGameBegin()
|
||||||
|
{
|
||||||
|
LoopCall(PostGameBeginFuncs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PreGameEnd()
|
||||||
|
{
|
||||||
|
LoopCall(PreGameEndFuncs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PostGameEnd()
|
||||||
|
{
|
||||||
|
LoopCall(PostGameEndFuncs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoopCall(List<LuaFunction> funcs)
|
||||||
|
{
|
||||||
|
foreach (var func in funcs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
func.Call();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LuaScriptEngine.Logger.LogError($"Error in Lua script: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Timer(LuaFunction func, long startInterval, long repeatInterval = 0L)
|
||||||
|
{
|
||||||
|
public bool Check(long gameTick)
|
||||||
|
{
|
||||||
|
if (gameTick < _nextTick) return false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_func.Call();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LuaScriptEngine.Logger.LogError($"Error in Lua script: {e}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_repeatInterval <= 0L) return true;
|
||||||
|
_nextTick += _repeatInterval;
|
||||||
|
if (_nextTick < gameTick)
|
||||||
|
_nextTick = gameTick + 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Reset(long gameTick)
|
||||||
|
{
|
||||||
|
if (_repeatInterval <= 0L) return true;
|
||||||
|
_nextTick = gameTick + _repeatInterval;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly LuaFunction _func = func;
|
||||||
|
private readonly long _repeatInterval = repeatInterval;
|
||||||
|
private long _nextTick = GameMain.gameTick + startInterval;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
LuaScriptEngine/README.md
Normal file
8
LuaScriptEngine/README.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# LuaScriptEngine
|
||||||
|
|
||||||
|
#### Write mod functions in lua scripts
|
||||||
|
#### 用lua脚本编写mod功能
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
BIN
LuaScriptEngine/package/icon.png
Normal file
BIN
LuaScriptEngine/package/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
9
LuaScriptEngine/package/manifest.json
Normal file
9
LuaScriptEngine/package/manifest.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "LuaScriptEngine",
|
||||||
|
"version_number": "1.0.0",
|
||||||
|
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/LuaScriptEngine",
|
||||||
|
"description": "Write mod functions in lua scripts / 用lua脚本编写mod功能",
|
||||||
|
"dependencies": [
|
||||||
|
"xiaoye97-BepInEx-5.4.17"
|
||||||
|
]
|
||||||
|
}
|
||||||
45
MechaDronesTweaks/CHANGELOG.md
Normal file
45
MechaDronesTweaks/CHANGELOG.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<details>
|
||||||
|
<summary>Read me in English</summary>
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
* 1.1.4
|
||||||
|
* Fixed support for game version 0.10.29
|
||||||
|
|
||||||
|
* 1.1.3
|
||||||
|
* Support for game version 0.10.28.20759+
|
||||||
|
* Fixed a minor bug that `RemoveSpeedLimitForStage1` not working while `UseFixedSpeed` set to false and `SpeedMultiplier` set to 1
|
||||||
|
|
||||||
|
* 1.1.2
|
||||||
|
* `RemoveBuildRangeLimit`, `LargerAreaForUpgradeAndDismantle` and `LargerAreaForTerraform` are moved to [UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist)
|
||||||
|
|
||||||
|
* 1.1.1
|
||||||
|
* Fixed crash in `LargeAreaForTerraform` functions.
|
||||||
|
|
||||||
|
* 1.1.0
|
||||||
|
* Added `RemoveBuildRangeLimit`, `LargerAreaForUpgradeAndDismantle` and `LargerAreaForTerraform` options (Check Usage for details).
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>中文读我</summary>
|
||||||
|
|
||||||
|
## 更新日志
|
||||||
|
|
||||||
|
* 1.1.4
|
||||||
|
* 修复了对游戏版本0.10.29的支持
|
||||||
|
|
||||||
|
* 1.1.3
|
||||||
|
* 支持游戏版本0.10.28.20759+
|
||||||
|
* 修复了当`UseFixedSpeed`设置为false且`SpeedMultiplier`设置为1时`RemoveSpeedLimitForStage1`无效的问题
|
||||||
|
|
||||||
|
* 1.1.2
|
||||||
|
* `RemoveBuildRangeLimit`, `LargerAreaForUpgradeAndDismantle` 和 `LargerAreaForTerraform` 移动到了 MOD [UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist) 中
|
||||||
|
|
||||||
|
* 1.1.1
|
||||||
|
* 修复了 `LargeAreaForTerraform` 功能可能导致崩溃的问题。
|
||||||
|
|
||||||
|
* 1.1.0
|
||||||
|
* 添加了 `RemoveBuildRangeLimit`, `LargerAreaForUpgradeAndDismantle` 和 `LargerAreaForTerraform` 选项 (详情见使用说明)。
|
||||||
|
|
||||||
|
</details>
|
||||||
@@ -1,29 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net472</TargetFramework>
|
|
||||||
<AssemblyName>MechaDronesTweaks</AssemblyName>
|
<AssemblyName>MechaDronesTweaks</AssemblyName>
|
||||||
<BepInExPluginGuid>org.soardev.mechadronestweaks</BepInExPluginGuid>
|
<BepInExPluginGuid>org.soardev.mechadronestweaks</BepInExPluginGuid>
|
||||||
<Description>DSP MOD - MechaDronesTweaks</Description>
|
<Description>DSP MOD - MechaDronesTweaks</Description>
|
||||||
<Version>1.1.4</Version>
|
<Version>1.1.4</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<PackHasChangelog>true</PackHasChangelog>
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
|
||||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
|
||||||
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<Exec Command="del /F /Q package\$(ProjectName)-$(Version).zip
powershell Compress-Archive -Force -DestinationPath 'package/$(ProjectName)-$(Version).zip' -Path '$(TargetPath)', package/icon.png, package/manifest.json, README.md" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
# MechaDronesTweaks
|
# MechaDronesTweaks
|
||||||
|
|
||||||
#### Some tweaks for mecha drones(Successor to FastDrones MOD)
|
<details>
|
||||||
#### 机甲建设机调整(FastDrones MOD的后继者)
|
<summary>Read me in English</summary>
|
||||||
|
|
||||||
|
***Some tweaks for mecha drones(Successor to FastDrones MOD)***
|
||||||
|
|
||||||
## Updates
|
## Updates
|
||||||
|
|
||||||
* 1.1.4
|
* 1.1.4
|
||||||
+ Fixed support for game version 0.10.29
|
* Fixed support for game version 0.10.29
|
||||||
|
|
||||||
* 1.1.3
|
* 1.1.3
|
||||||
+ Support for game version 0.10.28.20759+
|
* Support for game version 0.10.28.20759+
|
||||||
+ Fixed a minor bug that `RemoveSpeedLimitForStage1` not working while `UseFixedSpeed` set to false and `SpeedMultiplier` set to 1
|
* Fixed a minor bug that `RemoveSpeedLimitForStage1` not working while `UseFixedSpeed` set to false and `SpeedMultiplier` set to 1
|
||||||
|
|
||||||
* 1.1.2
|
* 1.1.2
|
||||||
+ `RemoveBuildRangeLimit`, `LargerAreaForUpgradeAndDismantle` and `LargerAreaForTerraform` are moved to [UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist)
|
* `RemoveBuildRangeLimit`, `LargerAreaForUpgradeAndDismantle` and `LargerAreaForTerraform` are moved to [UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist)
|
||||||
|
|
||||||
* 1.1.1
|
* 1.1.1
|
||||||
+ Fixed crash in `LargeAreaForTerraform` functions.
|
* Fixed crash in `LargeAreaForTerraform` functions.
|
||||||
|
|
||||||
* 1.1.0
|
* 1.1.0
|
||||||
+ Added `RemoveBuildRangeLimit`, `LargerAreaForUpgradeAndDismantle` and `LargerAreaForTerraform` options (Check Usage for details).
|
* Added `RemoveBuildRangeLimit`, `LargerAreaForUpgradeAndDismantle` and `LargerAreaForTerraform` options (Check Usage for details).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
* Inspired by [FastDrones](https://dsp.thunderstore.io/package/dkoppstein/FastDrones/), but patching IL codes, consuming less CPU to reduce lags on massive builds especially blueprints' put.
|
* Inspired by [FastDrones](https://dsp.thunderstore.io/package/dkoppstein/FastDrones/), but patching IL codes, consuming less CPU to reduce lags on massive builds especially blueprints' put.
|
||||||
* Does not affect current game-saves, which means:
|
* Does not affect current game-saves, which means:
|
||||||
* All values are patched in memory but written to game-saves so that you can play with normal mecha drone parameters while disabling this MOD.
|
* All values are patched in memory but written to game-saves so that you can play with normal mecha drone parameters while disabling this MOD.
|
||||||
@@ -37,24 +41,15 @@
|
|||||||
* `EnergyMultiplier` [Default Value: 0.1]: Energy consumption multiplier for mecha drones.
|
* `EnergyMultiplier` [Default Value: 0.1]: Energy consumption multiplier for mecha drones.
|
||||||
* Note: This MOD will disable `FastDrones` if the MOD is installed, to avoid conflict in functions.
|
* Note: This MOD will disable `FastDrones` if the MOD is installed, to avoid conflict in functions.
|
||||||
|
|
||||||
## 更新日志
|
</details>
|
||||||
* 1.1.4
|
|
||||||
+ 修复了对游戏版本0.10.29的支持
|
|
||||||
|
|
||||||
* 1.1.3
|
<details>
|
||||||
+ 支持游戏版本0.10.28.20759+
|
<summary>中文读我</summary>
|
||||||
+ 修复了当`UseFixedSpeed`设置为false且`SpeedMultiplier`设置为1时`RemoveSpeedLimitForStage1`无效的问题
|
|
||||||
|
|
||||||
* 1.1.2
|
***机甲建设机调整(FastDrones MOD的后继者)***
|
||||||
+ `RemoveBuildRangeLimit`, `LargerAreaForUpgradeAndDismantle` 和 `LargerAreaForTerraform` 移动到了 MOD [UXAssist](https://dsp.thunderstore.io/package/soarqin/UXAssist) 中
|
|
||||||
|
|
||||||
* 1.1.1
|
|
||||||
+ 修复了 `LargeAreaForTerraform` 功能可能导致崩溃的问题。
|
|
||||||
|
|
||||||
* 1.1.0
|
|
||||||
+ 添加了 `RemoveBuildRangeLimit`, `LargerAreaForUpgradeAndDismantle` 和 `LargerAreaForTerraform` 选项 (详情见使用说明)。
|
|
||||||
|
|
||||||
## 使用说明
|
## 使用说明
|
||||||
|
|
||||||
* 功能参考 [FastDrones](https://dsp.thunderstore.io/package/dkoppstein/FastDrones/),但主要对IL代码进行Patch因此消耗更少的CPU,尤其在大规模建造比如放置蓝图的时候可以大大减少卡顿。
|
* 功能参考 [FastDrones](https://dsp.thunderstore.io/package/dkoppstein/FastDrones/),但主要对IL代码进行Patch因此消耗更少的CPU,尤其在大规模建造比如放置蓝图的时候可以大大减少卡顿。
|
||||||
* 不影响当前游戏存档:
|
* 不影响当前游戏存档:
|
||||||
* 所有修改参数都在内存中Patch不会写入存档,禁用此MOD后可恢复正常建设机参数。
|
* 所有修改参数都在内存中Patch不会写入存档,禁用此MOD后可恢复正常建设机参数。
|
||||||
@@ -70,3 +65,5 @@
|
|||||||
* `SpeedMultiplier` [默认值: 4]: 速度倍数。
|
* `SpeedMultiplier` [默认值: 4]: 速度倍数。
|
||||||
* `EnergyMultiplier` [默认值: 0.1]: 能量消耗倍数。
|
* `EnergyMultiplier` [默认值: 0.1]: 能量消耗倍数。
|
||||||
* 说明: 如果安装了`FastDrones`本MOD会将其禁用避免功能冲突。
|
* 说明: 如果安装了`FastDrones`本MOD会将其禁用避免功能冲突。
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net472</TargetFramework>
|
|
||||||
<AssemblyName>OCBatchBuild</AssemblyName>
|
|
||||||
<BepInExPluginGuid>org.soardev.ocbatchbuild</BepInExPluginGuid>
|
|
||||||
<Description>DSP MOD - OCBatchBuild</Description>
|
|
||||||
<Version>1.2.0</Version>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
|
||||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
|
||||||
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<Exec Command="del /F /Q package\$(ProjectName)-$(Version).zip
powershell Compress-Archive -Force -DestinationPath 'package/$(ProjectName)-$(Version).zip' -Path '$(TargetPath)', package/icon.png, package/manifest.json, README.md" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using BepInEx;
|
|
||||||
using HarmonyLib;
|
|
||||||
|
|
||||||
namespace OCBatchBuild;
|
|
||||||
|
|
||||||
[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)]
|
|
||||||
public class OrbitalCollectorBatchBuild : BaseUnityPlugin
|
|
||||||
{
|
|
||||||
private new static readonly BepInEx.Logging.ManualLogSource Logger =
|
|
||||||
BepInEx.Logging.Logger.CreateLogSource(PluginInfo.PLUGIN_NAME);
|
|
||||||
|
|
||||||
private bool _cfgEnabled = true;
|
|
||||||
private static int _maxBuildCount;
|
|
||||||
private static bool _instantBuild;
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
_cfgEnabled = Config.Bind("General", "Enabled", _cfgEnabled, "enable/disable this plugin").Value;
|
|
||||||
_maxBuildCount = Config.Bind("General", "MaxBuildCount", _maxBuildCount, "Maximum Orbital Collectors to build once, set to 0 to build as many as possible").Value;
|
|
||||||
_instantBuild = Config.Bind("General", "InstantBuild", _instantBuild, "Enable to make Orbital Collectors built instantly. This is thought to be game logic breaking.").Value;
|
|
||||||
Harmony.CreateAndPatchAll(typeof(OrbitalCollectorBatchBuild));
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPostfix]
|
|
||||||
[HarmonyPatch(typeof(BuildTool_Click), "CreatePrebuilds")]
|
|
||||||
private static void CreatePrebuilds(BuildTool_Click __instance)
|
|
||||||
{
|
|
||||||
/* Check Gas Planet */
|
|
||||||
if (__instance.planet.type != EPlanetType.Gas) return;
|
|
||||||
if (__instance.buildPreviews.Count == 0) return;
|
|
||||||
|
|
||||||
var buildPreview = __instance.buildPreviews[0];
|
|
||||||
/* Check if is collector station */
|
|
||||||
if (!buildPreview.desc.isCollectStation) return;
|
|
||||||
|
|
||||||
var factory = __instance.factory;
|
|
||||||
var stationPool = factory.transport.stationPool;
|
|
||||||
var entityPool = factory.entityPool;
|
|
||||||
var stationCursor = factory.transport.stationCursor;
|
|
||||||
var pos = buildPreview.lpos;
|
|
||||||
var pos2 = buildPreview.lpos2;
|
|
||||||
var itemId = buildPreview.item.ID;
|
|
||||||
var countToBuild = _maxBuildCount - 1;
|
|
||||||
if (countToBuild == 0) return;
|
|
||||||
var prebuilds = new List<int> {-buildPreview.objId};
|
|
||||||
var player = __instance.player;
|
|
||||||
var firstPos = pos;
|
|
||||||
var cellCount = PlanetGrid.DetermineLongitudeSegmentCount(0, factory.planet.aux.mainGrid.segment) * 5;
|
|
||||||
var cellRad = Math.PI / cellCount;
|
|
||||||
var distRadCount = 0;
|
|
||||||
for (var i = 1; i <= cellCount; i++)
|
|
||||||
{
|
|
||||||
pos = Maths.RotateLF(0.0, 1.0, 0.0, cellRad, pos);
|
|
||||||
if ((firstPos - pos).sqrMagnitude < 14297f) continue;
|
|
||||||
distRadCount = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (distRadCount == 0) return;
|
|
||||||
pos = firstPos;
|
|
||||||
/* rotate for a minimal distance for next OC on sphere */
|
|
||||||
pos = Maths.RotateLF(0.0, 1.0, 0.0, cellRad * distRadCount, pos);
|
|
||||||
pos2 = Maths.RotateLF(0.0, 1.0, 0.0, cellRad * distRadCount, pos2);
|
|
||||||
for (var i = distRadCount; i < cellCount && countToBuild != 0;)
|
|
||||||
{
|
|
||||||
/* Check for collision */
|
|
||||||
var collide = false;
|
|
||||||
for (var j = 1; j < stationCursor; j++)
|
|
||||||
{
|
|
||||||
if (stationPool[j] == null || stationPool[j].id != j) continue;
|
|
||||||
if ((entityPool[stationPool[j].entityId].pos - pos).sqrMagnitude >= 14297f) continue;
|
|
||||||
collide = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (collide)
|
|
||||||
{
|
|
||||||
/* rotate for a small cell on sphere */
|
|
||||||
pos = Maths.RotateLF(0.0, 1.0, 0.0, cellRad, pos);
|
|
||||||
pos2 = Maths.RotateLF(0.0, 1.0, 0.0, cellRad, pos2);
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player.inhandItemId == itemId && player.inhandItemCount > 0)
|
|
||||||
{
|
|
||||||
player.UseHandItems(1, out var _);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var count = 1;
|
|
||||||
player.package.TakeTailItems(ref itemId, ref count, out var _);
|
|
||||||
if (count == 0) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var rot = Maths.SphericalRotation(pos, 0f);
|
|
||||||
var rot2 = Maths.SphericalRotation(pos2, 0f);
|
|
||||||
var prebuild = default(PrebuildData);
|
|
||||||
prebuild.protoId = (short)buildPreview.item.ID;
|
|
||||||
prebuild.modelIndex = (short)buildPreview.desc.modelIndex;
|
|
||||||
prebuild.pos = pos;
|
|
||||||
prebuild.pos2 = pos2;
|
|
||||||
prebuild.rot = rot;
|
|
||||||
prebuild.rot2 = rot2;
|
|
||||||
prebuild.pickOffset = (short)buildPreview.inputOffset;
|
|
||||||
prebuild.insertOffset = (short)buildPreview.outputOffset;
|
|
||||||
prebuild.recipeId = buildPreview.recipeId;
|
|
||||||
prebuild.filterId = buildPreview.filterId;
|
|
||||||
prebuild.InitParametersArray(buildPreview.paramCount);
|
|
||||||
for (var j = 0; j < buildPreview.paramCount; j++)
|
|
||||||
{
|
|
||||||
prebuild.parameters[j] = buildPreview.parameters[j];
|
|
||||||
}
|
|
||||||
prebuilds.Add(factory.AddPrebuildDataWithComponents(prebuild));
|
|
||||||
countToBuild--;
|
|
||||||
/* rotate for minimal distance for next OC on sphere */
|
|
||||||
pos = Maths.RotateLF(0.0, 1.0, 0.0, cellRad * distRadCount, pos);
|
|
||||||
pos2 = Maths.RotateLF(0.0, 1.0, 0.0, cellRad * distRadCount, pos2);
|
|
||||||
i += distRadCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_instantBuild) return;
|
|
||||||
foreach (var id in prebuilds)
|
|
||||||
{
|
|
||||||
factory.BuildFinally(player, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# OrbitalCollectorBatchBuild
|
|
||||||
|
|
||||||
#### Batch build Orbital Collectors
|
|
||||||
#### 轨道采集器快速批量建造
|
|
||||||
|
|
||||||
## Updates
|
|
||||||
### 1.2.0
|
|
||||||
* Support for mods that change default radius of Gas Planets, e.g. `GalacticScale`.
|
|
||||||
* Remove maximum build count limit in config.
|
|
||||||
|
|
||||||
### 1.1.0
|
|
||||||
* Add `InstantBuild` to config
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
* Build any orbital collector on a Gas Giant to trigger building all placable orbital collectors.
|
|
||||||
* Can set maximum orbital collectors to build once in config.
|
|
||||||
* Note: Collectors are placed as prebuilt status, you still need to fly around the Gas Giant to complete building. This is designed not to break much game logic.
|
|
||||||
You can set `InstantBuild` to `true` in config to make them built instantly.
|
|
||||||
|
|
||||||
## 使用说明
|
|
||||||
* 在气态星球上建造任何一个轨道采集器触发所有可建造采集器的放置。
|
|
||||||
* 可以在设置文件中配置一次批量建造的最大轨道采集器数量。
|
|
||||||
* 提示:轨道采集器会处于待建造状态,你仍然需要绕行气态行星一圈以完成建造。这个机制是为了尽可能减少对原有游戏逻辑的破坏。
|
|
||||||
在配置文件里设置`InstantBuild`为`true`可以使采集器的建造立即完成。
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 53 KiB |
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "OrbitalCollectorBatchBuild",
|
|
||||||
"version_number": "1.2.0",
|
|
||||||
"website_url": "https://github.com/soarqin/DSP_Mods/tree/master/OCBatchBuild",
|
|
||||||
"description": "Batch build Orbital Collectors / 轨道采集器快速批量建造",
|
|
||||||
"dependencies": [
|
|
||||||
"xiaoye97-BepInEx-5.4.17"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -186,7 +186,7 @@ public class Patch : BaseUnityPlugin, IModCanSave
|
|||||||
sorter.stt = sorter.stt * om / nm;
|
sorter.stt = sorter.stt * om / nm;
|
||||||
if (sorter.time > sorter.stt)
|
if (sorter.time > sorter.stt)
|
||||||
{
|
{
|
||||||
sorter.time = sorter.stt - sorter.speed;
|
sorter.time = sorter.stt - InserterComponent.speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (powerSystem == null) continue;
|
if (powerSystem == null) continue;
|
||||||
|
|||||||
@@ -1,31 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net472</TargetFramework>
|
|
||||||
<BepInExPluginGuid>org.soardev.overclockeverything</BepInExPluginGuid>
|
<BepInExPluginGuid>org.soardev.overclockeverything</BepInExPluginGuid>
|
||||||
<Description>DSP MOD - OverclockEverything</Description>
|
<Description>DSP MOD - OverclockEverything</Description>
|
||||||
<Version>1.0.0</Version>
|
<Version>1.0.0</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<PackageId>OverclockEverything</PackageId>
|
<PackageId>OverclockEverything</PackageId>
|
||||||
<RootNamespace>OverclockEverything</RootNamespace>
|
<RootNamespace>OverclockEverything</RootNamespace>
|
||||||
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
|
||||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.Modding.DSPModSave" Version="1.*" />
|
<PackageReference Include="DysonSphereProgram.Modding.DSPModSave" Version="1.*" />
|
||||||
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<Exec Command="del /F /Q package\$(ProjectName)-$(Version).zip
powershell Compress-Archive -Force -DestinationPath 'package/$(ProjectName)-$(Version).zip' -Path '$(TargetPath)', package/icon.png, package/manifest.json, README.md" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
# OverclockEverything
|
# OverclockEverything
|
||||||
|
|
||||||
#### Boost nearly all structures
|
***Boost nearly all structures***
|
||||||
#### 加速几乎所有建筑功能
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
* Boost power generation, assembling speed, belt and sorter speed.
|
* Boost power generation, assembling speed, belt and sorter speed.
|
||||||
|
|
||||||
## 使用说明
|
***加速几乎所有建筑功能***
|
||||||
|
|
||||||
* 加快发电,制造,传送带和分拣器速度。
|
* 加快发电,制造,传送带和分拣器速度。
|
||||||
|
|||||||
@@ -1,29 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net472</TargetFramework>
|
|
||||||
<AssemblyName>PoolOpt</AssemblyName>
|
<AssemblyName>PoolOpt</AssemblyName>
|
||||||
<BepInExPluginGuid>org.soardev.poolopt</BepInExPluginGuid>
|
<BepInExPluginGuid>org.soardev.poolopt</BepInExPluginGuid>
|
||||||
<Description>DSP MOD - PoolOpt</Description>
|
<Description>DSP MOD - PoolOpt</Description>
|
||||||
<Version>0.9.3</Version>
|
<Version>0.9.3</Version>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
<RestoreAdditionalProjectSources>https://nuget.bepinex.dev/v3/index.json</RestoreAdditionalProjectSources>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BepInEx.Core" Version="5.*" />
|
|
||||||
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
|
|
||||||
<PackageReference Include="DysonSphereProgram.GameLibs" Version="*-r.*" />
|
|
||||||
<PackageReference Include="UnityEngine.Modules" Version="2018.4.12" IncludeAssets="compile" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
|
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<Exec Command="del /F /Q package\$(ProjectName)-$(Version).zip
powershell Compress-Archive -Force -DestinationPath 'package/$(ProjectName)-$(Version).zip' -Path '$(TargetPath)', package/icon.png, package/manifest.json, README.md" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
87
README.md
87
README.md
@@ -1,67 +1,66 @@
|
|||||||
## DSP Mods by Soar Qin
|
# DSP Mods by Soar Qin
|
||||||
|
|
||||||
# [CheatEnabler](CheatEnabler)
|
## [CheatEnabler](CheatEnabler)
|
||||||
|
|
||||||
Add various cheat functions while disabling abnormal determinants
|
Add various cheat functions while disabling abnormal determinants
|
||||||
添加一些作弊功能,同时屏蔽异常检测
|
添加一些作弊功能,同时屏蔽异常检测
|
||||||
|
|
||||||
# [CompressSave](CompressSave)
|
## [CompressSave](CompressSave)
|
||||||
|
|
||||||
Moved [here](https://github.com/soarqin/DSP_Mods_TO/tree/master/CompressSave)
|
Moved [to another repo](https://github.com/soarqin/DSP_Mods_TO/tree/master/CompressSave)
|
||||||
|
|
||||||
# [LogisticMiner](LogisticMiner)
|
## [Dustbin](Dustbin)
|
||||||
|
|
||||||
Logistic Storages can mine all ores/water on current planet
|
Can turn Storages and Tanks into Dustbin(Destroy incoming items)
|
||||||
物流塔可以采集当前星球的全部矿产(以及水)
|
|
||||||
|
|
||||||
# [HideTips](HideTips)
|
|
||||||
|
|
||||||
Hide/Disable various tutorial tips/messages
|
|
||||||
隐藏/屏蔽各种引导提示/消息
|
|
||||||
|
|
||||||
# [Dustbin](Dustbin)
|
|
||||||
|
|
||||||
Can turn Storages and Tanks into Dustbin(Destroy incoming items)
|
|
||||||
储物仓和储液罐可以转变为垃圾桶(销毁送进的物品)
|
储物仓和储液罐可以转变为垃圾桶(销毁送进的物品)
|
||||||
|
|
||||||
# [OverclockEverything](OverclockEverything)
|
## [HideTips](HideTips)
|
||||||
|
|
||||||
Boost nearly all structures
|
Hide/Disable various tutorial tips/messages
|
||||||
加速几乎所有建筑功能
|
隐藏/屏蔽各种引导提示/消息
|
||||||
|
|
||||||
# [OrbitalCollectorBatchBuild](OCBatchBuild)
|
## [LabOpt](LabOpt)
|
||||||
|
|
||||||
Batch build Orbital Collectors
|
Performance optimizations for Matrix Labs
|
||||||
轨道采集器快速批量建造
|
|
||||||
|
|
||||||
# [UniverseGenTweaks](UniverseGenTweaks)
|
|
||||||
|
|
||||||
Universe Generator Tweak
|
|
||||||
宇宙生成参数调节
|
|
||||||
|
|
||||||
# [MechaDronesTweaks](MechaDronesTweaks)
|
|
||||||
|
|
||||||
Some tweaks for mecha drones and build functions(Successor to FastDrones MOD)
|
|
||||||
机甲建设机和建设功能调整(FastDrones MOD的后继者)
|
|
||||||
|
|
||||||
# [LabOpt](LabOpt)
|
|
||||||
|
|
||||||
Performance optimizations for Matrix Labs
|
|
||||||
Marked as obsoleted temporarily, needs more investigation about LabComponent's mechanism
|
Marked as obsoleted temporarily, needs more investigation about LabComponent's mechanism
|
||||||
优化研究站性能
|
优化研究站性能
|
||||||
暂时标识为过期,需要更多关于LabComponent机制的研究
|
暂时标识为过期,需要更多关于LabComponent机制的研究
|
||||||
|
|
||||||
# [PoolOpt](PoolOpt)
|
## [LogisticMiner](LogisticMiner)
|
||||||
|
|
||||||
Optimize memory pools on loading gamesaves
|
Logistic Storages can mine all ores/water on current planet
|
||||||
|
物流塔可以采集当前星球的全部矿产(以及水)
|
||||||
|
|
||||||
|
## [LuaScriptEngine](LuaScriptEngine)
|
||||||
|
Write mod functions in lua scripts
|
||||||
|
用lua脚本编写mod功能
|
||||||
|
|
||||||
|
## [MechaDronesTweaks](MechaDronesTweaks)
|
||||||
|
|
||||||
|
Some tweaks for mecha drones and build functions(Successor to FastDrones MOD)
|
||||||
|
机甲建设机和建设功能调整(FastDrones MOD的后继者)
|
||||||
|
|
||||||
|
## [OverclockEverything](OverclockEverything)
|
||||||
|
|
||||||
|
Boost nearly all structures
|
||||||
|
加速几乎所有建筑功能
|
||||||
|
|
||||||
|
## [PoolOpt](PoolOpt)
|
||||||
|
|
||||||
|
Optimize memory pools on loading gamesaves
|
||||||
加载游戏存档时优化内存池的使用
|
加载游戏存档时优化内存池的使用
|
||||||
|
|
||||||
# [UserCloak](UserCloak)
|
## [UniverseGenTweaks](UniverseGenTweaks)
|
||||||
|
|
||||||
Cloak(Fake) user account info
|
Universe Generator Tweak
|
||||||
|
宇宙生成参数调节
|
||||||
|
|
||||||
|
## [UserCloak](UserCloak)
|
||||||
|
|
||||||
|
Cloak(Fake) user account info
|
||||||
隐匿(伪装)用户账号信息
|
隐匿(伪装)用户账号信息
|
||||||
|
|
||||||
# [UXAssist](UXAssist)
|
## [UXAssist](UXAssist)
|
||||||
|
|
||||||
Some functions and patches for better user experience
|
Some functions and patches for better user experience
|
||||||
一些提升用户体验的功能和补丁
|
一些提升用户体验的功能和补丁
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,32 +1,49 @@
|
|||||||
using System;
|
using System;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace UXAssist.Common;
|
namespace UXAssist.Common;
|
||||||
|
|
||||||
public class GameLogic: PatchImpl<GameLogic>
|
public class GameLogic : PatchImpl<GameLogic>
|
||||||
{
|
{
|
||||||
public static Action OnDataLoaded;
|
public static Action OnDataLoaded;
|
||||||
public static Action OnGameBegin;
|
public static Action OnGameBegin;
|
||||||
public static Action OnGameEnd;
|
public static Action OnGameEnd;
|
||||||
|
|
||||||
|
private static void InvokeSafe(Action action)
|
||||||
|
{
|
||||||
|
if (action == null) return;
|
||||||
|
foreach (var handler in action.GetInvocationList())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((Action)handler)();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
[HarmonyPostfix]
|
||||||
[HarmonyPatch(typeof(VFPreload), nameof(VFPreload.InvokeOnLoadWorkEnded))]
|
[HarmonyPatch(typeof(VFPreload), nameof(VFPreload.InvokeOnLoadWorkEnded))]
|
||||||
public static void VFPreload_InvokeOnLoadWorkEnded_Postfix()
|
public static void VFPreload_InvokeOnLoadWorkEnded_Postfix()
|
||||||
{
|
{
|
||||||
OnDataLoaded?.Invoke();
|
InvokeSafe(OnDataLoaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix, HarmonyPriority(Priority.First)]
|
[HarmonyPostfix, HarmonyPriority(Priority.First)]
|
||||||
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Begin))]
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.Begin))]
|
||||||
public static void GameMain_Begin_Postfix()
|
public static void GameMain_Begin_Postfix()
|
||||||
{
|
{
|
||||||
OnGameBegin?.Invoke();
|
InvokeSafe(OnGameBegin);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix, HarmonyPriority(Priority.Last)]
|
[HarmonyPostfix, HarmonyPriority(Priority.Last)]
|
||||||
[HarmonyPatch(typeof(GameMain), nameof(GameMain.End))]
|
[HarmonyPatch(typeof(GameMain), nameof(GameMain.End))]
|
||||||
public static void GameMain_End_Postfix()
|
public static void GameMain_End_Postfix()
|
||||||
{
|
{
|
||||||
OnGameEnd?.Invoke();
|
InvokeSafe(OnGameEnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,14 +122,14 @@ public static class I18N
|
|||||||
_initialized = true;
|
_initialized = true;
|
||||||
Apply();
|
Apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(Localization), nameof(Localization.LoadLanguage))]
|
[HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(Localization), nameof(Localization.LoadLanguage))]
|
||||||
private static void Localization_LoadLanguage_Postfix(int index)
|
private static void Localization_LoadLanguage_Postfix(int index)
|
||||||
{
|
{
|
||||||
if (!_initialized) return;
|
if (!_initialized) return;
|
||||||
ApplyLanguage(index);
|
ApplyLanguage(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(Localization), nameof(Localization.NotifyLanguageChange))]
|
[HarmonyPostfix, HarmonyPriority(Priority.Last), HarmonyPatch(typeof(Localization), nameof(Localization.NotifyLanguageChange))]
|
||||||
private static void Localization_NotifyLanguageChange_Postfix()
|
private static void Localization_NotifyLanguageChange_Postfix()
|
||||||
{
|
{
|
||||||
|
|||||||
9
UXAssist/Common/KnownItemId.cs
Normal file
9
UXAssist/Common/KnownItemId.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace UXAssist.Common;
|
||||||
|
|
||||||
|
public enum KnownItemId : int
|
||||||
|
{
|
||||||
|
Drone = 5001,
|
||||||
|
Ship = 5002,
|
||||||
|
Bot = 5003,
|
||||||
|
Warper = 1210,
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ public static class Util
|
|||||||
{
|
{
|
||||||
public static Type[] GetTypesFiltered(Assembly assembly, Func<Type, bool> predicate)
|
public static Type[] GetTypesFiltered(Assembly assembly, Func<Type, bool> predicate)
|
||||||
{
|
{
|
||||||
return assembly.GetTypes().Where(predicate).ToArray();
|
return [.. assembly.GetTypes().Where(predicate)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type[] GetTypesInNamespace(Assembly assembly, string nameSpace) => GetTypesFiltered(assembly, t => string.Equals(t.Namespace, nameSpace, StringComparison.Ordinal));
|
public static Type[] GetTypesInNamespace(Assembly assembly, string nameSpace) => GetTypesFiltered(assembly, t => string.Equals(t.Namespace, nameSpace, StringComparison.Ordinal));
|
||||||
@@ -36,13 +36,13 @@ public static class Util
|
|||||||
tex.LoadImage(fileData);
|
tex.LoadImage(fileData);
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Sprite LoadSprite(string path)
|
public static Sprite LoadSprite(string path)
|
||||||
{
|
{
|
||||||
var tex = LoadTexture(path);
|
var tex = LoadTexture(path);
|
||||||
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
|
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Texture2D LoadEmbeddedTexture(string path, Assembly assembly = null)
|
public static Texture2D LoadEmbeddedTexture(string path, Assembly assembly = null)
|
||||||
{
|
{
|
||||||
var fileData = LoadEmbeddedResource(path, assembly);
|
var fileData = LoadEmbeddedResource(path, assembly);
|
||||||
@@ -50,12 +50,12 @@ public static class Util
|
|||||||
tex.LoadImage(fileData);
|
tex.LoadImage(fileData);
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Sprite LoadEmbeddedSprite(string path, Assembly assembly = null)
|
public static Sprite LoadEmbeddedSprite(string path, Assembly assembly = null)
|
||||||
{
|
{
|
||||||
var tex = LoadEmbeddedTexture(path, assembly);
|
var tex = LoadEmbeddedTexture(path, assembly);
|
||||||
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
|
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string PluginFolder(Assembly assembly = null) => Path.GetDirectoryName((assembly == null ? Assembly.GetCallingAssembly() : assembly).Location);
|
public static string PluginFolder(Assembly assembly = null) => Path.GetDirectoryName((assembly == null ? Assembly.GetCallingAssembly() : assembly).Location);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,13 +127,10 @@ public static class WinApi
|
|||||||
|
|
||||||
[DllImport("user32", ExactSpelling = true)]
|
[DllImport("user32", ExactSpelling = true)]
|
||||||
public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
|
public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint);
|
||||||
|
|
||||||
[DllImport("user32", ExactSpelling = true)]
|
[DllImport("user32", ExactSpelling = true)]
|
||||||
public static extern IntPtr MonitorFromRect([In] ref Rect lpRect, uint dwFlags);
|
public static extern IntPtr MonitorFromRect([In] ref Rect lpRect, uint dwFlags);
|
||||||
|
|
||||||
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
|
|
||||||
public static extern bool GetProcessAffinityMask(IntPtr hProcess, out ulong lpProcessAffinityMask, out ulong lpSystemAffinityMask);
|
|
||||||
|
|
||||||
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
|
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
|
||||||
public static extern IntPtr GetCurrentProcess();
|
public static extern IntPtr GetCurrentProcess();
|
||||||
|
|
||||||
@@ -143,9 +140,6 @@ public static class WinApi
|
|||||||
[DllImport("kernel32", ExactSpelling = true)]
|
[DllImport("kernel32", ExactSpelling = true)]
|
||||||
public static extern IntPtr GetConsoleWindow();
|
public static extern IntPtr GetConsoleWindow();
|
||||||
|
|
||||||
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
|
|
||||||
public static extern bool SetProcessAffinityMask(IntPtr hProcess, ulong dwProcessAffinityMask);
|
|
||||||
|
|
||||||
// GetPriorityClass and SetPriorityClass
|
// GetPriorityClass and SetPriorityClass
|
||||||
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
|
[DllImport("kernel32", ExactSpelling = true, SetLastError = true)]
|
||||||
public static extern int GetPriorityClass(IntPtr hProcess);
|
public static extern int GetPriorityClass(IntPtr hProcess);
|
||||||
@@ -160,126 +154,4 @@ public static class WinApi
|
|||||||
public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
|
public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region GetLogicalProcessorInformationEx
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
private enum LOGICAL_PROCESSOR_RELATIONSHIP
|
|
||||||
{
|
|
||||||
RelationProcessorCore,
|
|
||||||
RelationNumaNode,
|
|
||||||
RelationCache,
|
|
||||||
RelationProcessorPackage,
|
|
||||||
RelationGroup,
|
|
||||||
RelationAll = 0xffff
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
|
||||||
private struct GROUP_AFFINITY
|
|
||||||
{
|
|
||||||
public nuint Mask;
|
|
||||||
public ushort Group;
|
|
||||||
public ushort Reserved0;
|
|
||||||
public ushort Reserved1;
|
|
||||||
public ushort Reserved3;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
|
||||||
private struct PROCESSOR_RELATIONSHIP
|
|
||||||
{
|
|
||||||
public byte Flags;
|
|
||||||
public byte EfficiencyClass;
|
|
||||||
public ushort Reserved0;
|
|
||||||
public uint Reserved1;
|
|
||||||
public uint Reserved2;
|
|
||||||
public uint Reserved3;
|
|
||||||
public uint Reserved4;
|
|
||||||
public ushort Reserved5;
|
|
||||||
public ushort GroupCount;
|
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
|
|
||||||
public GROUP_AFFINITY[] GroupMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
private struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
|
|
||||||
{
|
|
||||||
public LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
|
|
||||||
public uint Size;
|
|
||||||
public PROCESSOR_RELATIONSHIP Processor;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("kernel32", SetLastError = true)]
|
|
||||||
private static extern bool GetLogicalProcessorInformationEx(
|
|
||||||
LOGICAL_PROCESSOR_RELATIONSHIP relationshipType,
|
|
||||||
IntPtr buffer,
|
|
||||||
ref uint returnLength
|
|
||||||
);
|
|
||||||
|
|
||||||
public struct LogicalProcessorDetails
|
|
||||||
{
|
|
||||||
public int CoreCount;
|
|
||||||
public int ThreadCount;
|
|
||||||
public int PerformanceCoreCount;
|
|
||||||
public int EfficiencyCoreCount;
|
|
||||||
public ulong PerformanceCoreMask;
|
|
||||||
public ulong EfficiencyCoreMask;
|
|
||||||
public bool HybridArchitecture => PerformanceCoreCount > 0 && EfficiencyCoreCount > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LogicalProcessorDetails GetLogicalProcessorDetails()
|
|
||||||
{
|
|
||||||
uint returnLength = 0;
|
|
||||||
GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore, IntPtr.Zero, ref returnLength);
|
|
||||||
var result = new LogicalProcessorDetails();
|
|
||||||
if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER) return result;
|
|
||||||
var ptr = Marshal.AllocHGlobal((int)returnLength);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore, ptr, ref returnLength))
|
|
||||||
return result;
|
|
||||||
uint offset = 0;
|
|
||||||
var item = ptr;
|
|
||||||
while (offset < returnLength)
|
|
||||||
{
|
|
||||||
var buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)Marshal.PtrToStructure(item, typeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX));
|
|
||||||
offset += buffer.Size;
|
|
||||||
item += (int)buffer.Size;
|
|
||||||
if (buffer.Relationship != LOGICAL_PROCESSOR_RELATIONSHIP.RelationProcessorCore) continue;
|
|
||||||
result.CoreCount++;
|
|
||||||
var mask = buffer.Processor.GroupMask[0].Mask;
|
|
||||||
var tcount = CountBitsSet(mask);
|
|
||||||
result.ThreadCount += tcount;
|
|
||||||
if (buffer.Processor.EfficiencyClass > 0)
|
|
||||||
{
|
|
||||||
result.PerformanceCoreCount++;
|
|
||||||
result.PerformanceCoreMask |= mask;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.EfficiencyCoreCount++;
|
|
||||||
result.EfficiencyCoreMask |= mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal.FreeHGlobal(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
int CountBitsSet(ulong mask)
|
|
||||||
{
|
|
||||||
var count = 0;
|
|
||||||
while (mask != 0)
|
|
||||||
{
|
|
||||||
mask &= mask - 1;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Linq;
|
namespace UXAssist.Functions;
|
||||||
|
|
||||||
namespace UXAssist.Functions;
|
|
||||||
|
|
||||||
public static class DysonSphereFunctions
|
public static class DysonSphereFunctions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace UXAssist.Functions;
|
namespace UXAssist.Functions;
|
||||||
|
|
||||||
@@ -12,7 +13,8 @@ public static class FactoryFunctions
|
|||||||
// Clear entity connection
|
// Clear entity connection
|
||||||
var factory = cargoTraffic.factory;
|
var factory = cargoTraffic.factory;
|
||||||
factory.ReadObjectConn(belt.entityId, 0, out var isOutput, out var otherObjId, out var otherSlot);
|
factory.ReadObjectConn(belt.entityId, 0, out var isOutput, out var otherObjId, out var otherSlot);
|
||||||
if (isOutput && factory.entityPool[otherObjId].beltId == belt.outputId) {
|
if (isOutput && factory.entityPool[otherObjId].beltId == belt.outputId)
|
||||||
|
{
|
||||||
factory.ClearObjectConnDirect(belt.entityId, 0);
|
factory.ClearObjectConnDirect(belt.entityId, 0);
|
||||||
factory.ClearObjectConnDirect(otherObjId, otherSlot);
|
factory.ClearObjectConnDirect(otherObjId, otherSlot);
|
||||||
}
|
}
|
||||||
@@ -22,6 +24,13 @@ public static class FactoryFunctions
|
|||||||
cargoTraffic.AlterBeltConnections(beltId, 0, i0, i1, i2);
|
cargoTraffic.AlterBeltConnections(beltId, 0, i0, i1, i2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool ObjectIsBeltOrInserter(PlanetFactory factory, int objId)
|
||||||
|
{
|
||||||
|
if (objId == 0) return false;
|
||||||
|
ItemProto proto = LDB.items.Select(objId > 0 ? factory.entityPool[objId].protoId : factory.prebuildPool[-objId].protoId);
|
||||||
|
return proto != null && (proto.prefabDesc.isBelt || proto.prefabDesc.isInserter);
|
||||||
|
}
|
||||||
|
|
||||||
public static void DismantleBlueprintSelectedBuildings()
|
public static void DismantleBlueprintSelectedBuildings()
|
||||||
{
|
{
|
||||||
var player = GameMain.mainPlayer;
|
var player = GameMain.mainPlayer;
|
||||||
@@ -33,21 +42,22 @@ public static class FactoryFunctions
|
|||||||
List<int> buildPreviewsToRemove = [];
|
List<int> buildPreviewsToRemove = [];
|
||||||
foreach (var buildPreview in blueprintCopyTool.bpPool)
|
foreach (var buildPreview in blueprintCopyTool.bpPool)
|
||||||
{
|
{
|
||||||
if (buildPreview?.item == null || buildPreview.objId <= 0) continue;
|
if (buildPreview?.item == null) continue;
|
||||||
|
var objId = buildPreview.objId;
|
||||||
|
if (objId == 0) continue;
|
||||||
int index;
|
int index;
|
||||||
if ((index = buildPreviewsToRemove.BinarySearch(buildPreview.objId)) < 0)
|
if ((index = buildPreviewsToRemove.BinarySearch(objId)) < 0)
|
||||||
buildPreviewsToRemove.Insert(~index, buildPreview.objId);
|
buildPreviewsToRemove.Insert(~index, objId);
|
||||||
var isBelt = buildPreview.desc.isBelt;
|
var isBelt = buildPreview.desc.isBelt;
|
||||||
var isInserter = buildPreview.desc.isInserter;
|
var isInserter = buildPreview.desc.isInserter;
|
||||||
if (isInserter) continue;
|
if (isInserter) continue;
|
||||||
var objId = buildPreview.objId;
|
|
||||||
if (isBelt)
|
if (isBelt)
|
||||||
{
|
{
|
||||||
var needCheck = false;
|
var needCheck = false;
|
||||||
for (var j = 0; j < 2; j++)
|
for (var j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
factory.ReadObjectConn(objId, j, out _, out var connObjId, out _);
|
factory.ReadObjectConn(objId, j, out _, out var connObjId, out _);
|
||||||
if (connObjId == 0 || factory.ObjectIsBelt(connObjId) || blueprintCopyTool.ObjectIsInserter(connObjId)) continue;
|
if (connObjId == 0 || ObjectIsBeltOrInserter(factory, connObjId)) continue;
|
||||||
needCheck = true;
|
needCheck = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -56,7 +66,7 @@ public static class FactoryFunctions
|
|||||||
for (var k = 0; k < 16; k++)
|
for (var k = 0; k < 16; k++)
|
||||||
{
|
{
|
||||||
factory.ReadObjectConn(objId, k, out _, out var connObjId, out _);
|
factory.ReadObjectConn(objId, k, out _, out var connObjId, out _);
|
||||||
if (connObjId != 0 && (index = buildPreviewsToRemove.BinarySearch(connObjId)) < 0 && (factory.ObjectIsBelt(connObjId) || blueprintCopyTool.ObjectIsInserter(connObjId)))
|
if (connObjId != 0 && (index = buildPreviewsToRemove.BinarySearch(connObjId)) < 0 && ObjectIsBeltOrInserter(factory, connObjId))
|
||||||
buildPreviewsToRemove.Insert(~index, connObjId);
|
buildPreviewsToRemove.Insert(~index, connObjId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,8 +77,8 @@ public static class FactoryFunctions
|
|||||||
for (var j = 0; j < 2; j++)
|
for (var j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
factory.ReadObjectConn(connObjId, j, out _, out var connObjId2, out _);
|
factory.ReadObjectConn(connObjId, j, out _, out var connObjId2, out _);
|
||||||
if (connObjId2 == 0 || (index = buildPreviewsToRemove.BinarySearch(connObjId2)) >= 0 || factory.ObjectIsBelt(connObjId2) || blueprintCopyTool.ObjectIsInserter(connObjId2)) continue;
|
if (connObjId2 == 0 || (index = buildPreviewsToRemove.BinarySearch(connObjId2)) >= 0 || ObjectIsBeltOrInserter(factory, connObjId2)) continue;
|
||||||
buildPreviewsToRemove.Insert(~index, connObjId2);
|
buildPreviewsToRemove.Insert(~index, connObjId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,19 +88,173 @@ public static class FactoryFunctions
|
|||||||
for (var j = 0; j < 16; j++)
|
for (var j = 0; j < 16; j++)
|
||||||
{
|
{
|
||||||
factory.ReadObjectConn(objId, j, out _, out var connObjId, out _);
|
factory.ReadObjectConn(objId, j, out _, out var connObjId, out _);
|
||||||
if (connObjId != 0 && (index = buildPreviewsToRemove.BinarySearch(connObjId)) < 0 && (factory.ObjectIsBelt(connObjId) || blueprintCopyTool.ObjectIsInserter(connObjId)))
|
if (connObjId != 0 && (index = buildPreviewsToRemove.BinarySearch(connObjId)) < 0 && ObjectIsBeltOrInserter(factory, connObjId))
|
||||||
buildPreviewsToRemove.Insert(~index, connObjId);
|
buildPreviewsToRemove.Insert(~index, connObjId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var entityPool = factory.entityPool;
|
||||||
|
var stationPool = factory.transport.stationPool;
|
||||||
foreach (var objId in buildPreviewsToRemove)
|
foreach (var objId in buildPreviewsToRemove)
|
||||||
{
|
{
|
||||||
|
if (objId > 0)
|
||||||
|
{
|
||||||
|
int stationId = entityPool[objId].stationId;
|
||||||
|
if (stationId > 0)
|
||||||
|
{
|
||||||
|
StationComponent sc = stationPool[stationId];
|
||||||
|
if (sc is null || sc.id != stationId) continue;
|
||||||
|
for (int i = 0; i < sc.storage.Length; i++)
|
||||||
|
{
|
||||||
|
int added = player.TryAddItemToPackage(sc.storage[i].itemId, sc.storage[i].count, sc.storage[i].inc, true, objId);
|
||||||
|
if (added > 0) UIItemup.Up(sc.storage[i].itemId, added);
|
||||||
|
}
|
||||||
|
sc.storage = new StationStore[sc.storage.Length];
|
||||||
|
sc.needs = new int[sc.needs.Length];
|
||||||
|
}
|
||||||
|
}
|
||||||
build.DoDismantleObject(objId);
|
build.DoDismantleObject(objId);
|
||||||
}
|
}
|
||||||
buildPreviewsToRemove = null;
|
|
||||||
blueprintCopyTool.ClearSelection();
|
blueprintCopyTool.ClearSelection();
|
||||||
blueprintCopyTool.ClearPreSelection();
|
blueprintCopyTool.ClearPreSelection();
|
||||||
blueprintCopyTool.ResetBlueprint();
|
blueprintCopyTool.ResetBlueprint();
|
||||||
blueprintCopyTool.ResetBuildPreviews();
|
blueprintCopyTool.ResetBuildPreviews();
|
||||||
blueprintCopyTool.RefreshBlueprintData();
|
blueprintCopyTool.RefreshBlueprintData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SelectAllBuildingsInBlueprintCopy()
|
||||||
|
{
|
||||||
|
var localFactory = GameMain.localPlanet?.factory;
|
||||||
|
if (localFactory == null) return;
|
||||||
|
var blueprintCopyTool = GameMain.mainPlayer?.controller?.actionBuild?.blueprintCopyTool;
|
||||||
|
if (blueprintCopyTool == null || !blueprintCopyTool.active) return;
|
||||||
|
var entityPool = localFactory.entityPool;
|
||||||
|
foreach (var entity in entityPool)
|
||||||
|
{
|
||||||
|
if (entity.id == 0) continue;
|
||||||
|
blueprintCopyTool.preSelectObjIds.Add(entity.id);
|
||||||
|
blueprintCopyTool.selectedObjIds.Add(entity.id);
|
||||||
|
}
|
||||||
|
var prebuildPool = localFactory.prebuildPool;
|
||||||
|
foreach (var prebuild in prebuildPool)
|
||||||
|
{
|
||||||
|
if (prebuild.id == 0) continue;
|
||||||
|
blueprintCopyTool.preSelectObjIds.Add(-prebuild.id);
|
||||||
|
blueprintCopyTool.selectedObjIds.Add(-prebuild.id);
|
||||||
|
}
|
||||||
|
blueprintCopyTool.RefreshBlueprintData();
|
||||||
|
blueprintCopyTool.DeterminePreviews();
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct BPBuildingData
|
||||||
|
{
|
||||||
|
public BlueprintBuilding building;
|
||||||
|
public int itemType;
|
||||||
|
public double offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct BPBeltData
|
||||||
|
{
|
||||||
|
public BlueprintBuilding building;
|
||||||
|
public double offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HashSet<int> _itemIsBelt = null;
|
||||||
|
private static Dictionary<int, int> _upgradeTypes = null;
|
||||||
|
|
||||||
|
public static void SortBlueprintData(BlueprintData blueprintData)
|
||||||
|
{
|
||||||
|
// Initialize itemIsBelt and upgradeTypes
|
||||||
|
if (_itemIsBelt == null)
|
||||||
|
{
|
||||||
|
_itemIsBelt = [];
|
||||||
|
_upgradeTypes = [];
|
||||||
|
foreach (var proto in LDB.items.dataArray)
|
||||||
|
{
|
||||||
|
if (proto.prefabDesc?.isBelt ?? false)
|
||||||
|
{
|
||||||
|
_itemIsBelt.Add(proto.ID);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (proto.Upgrades != null && proto.Upgrades.Length > 0)
|
||||||
|
{
|
||||||
|
var minUpgrade = proto.Upgrades.Min(u => u);
|
||||||
|
if (minUpgrade != 0 && minUpgrade != proto.ID)
|
||||||
|
{
|
||||||
|
_upgradeTypes.Add(proto.ID, minUpgrade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separate belt and non-belt buildings
|
||||||
|
List<BPBuildingData> bpBuildings = [];
|
||||||
|
Dictionary<BlueprintBuilding, BPBeltData> bpBelts = [];
|
||||||
|
foreach (var building in blueprintData.buildings)
|
||||||
|
{
|
||||||
|
var offset = building.areaIndex * 1073741824.0 + building.localOffset_y * 262144.0 + building.localOffset_x * 1024.0 + building.localOffset_z;
|
||||||
|
if (_itemIsBelt.Contains(building.itemId))
|
||||||
|
{
|
||||||
|
bpBelts.Add(building, new BPBeltData { building = building, offset = offset });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var itemType = _upgradeTypes.TryGetValue(building.itemId, out var upgradeType) ? upgradeType : building.itemId;
|
||||||
|
bpBuildings.Add(new BPBuildingData { building = building, itemType = itemType, offset = offset });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HashSet<BlueprintBuilding> beltsWithInput = [.. bpBelts.Select(pair => pair.Value.building.outputObj)];
|
||||||
|
var beltHeads = bpBelts.Where(pair => !beltsWithInput.Contains(pair.Value.building)).ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||||
|
// Sort belt buildings
|
||||||
|
List<BlueprintBuilding> sortedBpBelts = [];
|
||||||
|
// Deal with non-cycle belt paths
|
||||||
|
foreach (var pair in beltHeads.OrderByDescending(pair => pair.Value.offset))
|
||||||
|
{
|
||||||
|
var building = pair.Key;
|
||||||
|
while (building != null)
|
||||||
|
{
|
||||||
|
if (!bpBelts.Remove(building)) break;
|
||||||
|
sortedBpBelts.Add(building);
|
||||||
|
building = building.outputObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Deal with cycle belt paths
|
||||||
|
foreach (var pair in bpBelts.OrderByDescending(pair => pair.Value.offset))
|
||||||
|
{
|
||||||
|
var building = pair.Key;
|
||||||
|
while (building != null)
|
||||||
|
{
|
||||||
|
if (!bpBelts.Remove(building)) break;
|
||||||
|
sortedBpBelts.Add(building);
|
||||||
|
building = building.outputObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort non-belt buildings
|
||||||
|
bpBuildings.Sort((a, b) =>
|
||||||
|
{
|
||||||
|
var sign = b.itemType.CompareTo(a.itemType);
|
||||||
|
if (sign != 0) return sign;
|
||||||
|
|
||||||
|
sign = b.building.modelIndex.CompareTo(a.building.modelIndex);
|
||||||
|
if (sign != 0) return sign;
|
||||||
|
|
||||||
|
sign = b.building.recipeId.CompareTo(a.building.recipeId);
|
||||||
|
if (sign != 0) return sign;
|
||||||
|
|
||||||
|
sign = a.building.areaIndex.CompareTo(b.building.areaIndex);
|
||||||
|
if (sign != 0) return sign;
|
||||||
|
|
||||||
|
return b.offset.CompareTo(a.offset);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Concatenate sorted belts and non-belt buildings
|
||||||
|
sortedBpBelts.Reverse();
|
||||||
|
blueprintData.buildings = [.. bpBuildings.Select(b => b.building), .. sortedBpBelts];
|
||||||
|
var buildings = blueprintData.buildings;
|
||||||
|
|
||||||
|
for (var i = buildings.Length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
buildings[i].index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Collections.Generic;
|
||||||
using BepInEx.Configuration;
|
using BepInEx.Configuration;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@@ -9,7 +9,12 @@ namespace UXAssist.Functions;
|
|||||||
public static class PlanetFunctions
|
public static class PlanetFunctions
|
||||||
{
|
{
|
||||||
public static ConfigEntry<int> OrbitalCollectorMaxBuildCount;
|
public static ConfigEntry<int> OrbitalCollectorMaxBuildCount;
|
||||||
|
public static ConfigEntry<bool> ReturnBuildingsOnInitializeEnabled;
|
||||||
|
public static ConfigEntry<bool> ReturnLogisticStorageItemsOnInitializeEnabled;
|
||||||
|
public static ConfigEntry<bool> ReturnBeltAFactoryItemsOnInitializeEnabled;
|
||||||
|
|
||||||
private const int OrbitalCollectorItemId = 2105;
|
private const int OrbitalCollectorItemId = 2105;
|
||||||
|
|
||||||
public static void DismantleAll(bool toBag)
|
public static void DismantleAll(bool toBag)
|
||||||
{
|
{
|
||||||
var player = GameMain.mainPlayer;
|
var player = GameMain.mainPlayer;
|
||||||
@@ -19,28 +24,40 @@ public static class PlanetFunctions
|
|||||||
if (factory == null) return;
|
if (factory == null) return;
|
||||||
foreach (var etd in factory.entityPool)
|
foreach (var etd in factory.entityPool)
|
||||||
{
|
{
|
||||||
|
if (etd.id == 0) continue;
|
||||||
var stationId = etd.stationId;
|
var stationId = etd.stationId;
|
||||||
if (stationId > 0)
|
if (stationId > 0)
|
||||||
{
|
{
|
||||||
var sc = GameMain.localPlanet.factory.transport.stationPool[stationId];
|
var sc = GameMain.localPlanet.factory.transport.stationPool[stationId];
|
||||||
|
if (sc is null || sc.id != stationId) continue;
|
||||||
if (toBag)
|
if (toBag)
|
||||||
{
|
{
|
||||||
for (var i = sc.storage.Length - 1; i >= 0; i--)
|
for (var i = sc.storage.Length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var package = player.TryAddItemToPackage(sc.storage[i].itemId, sc.storage[i].count, 0, true, etd.id);
|
var added = player.TryAddItemToPackage(sc.storage[i].itemId, sc.storage[i].count, sc.storage[i].inc, true, etd.id);
|
||||||
UIItemup.Up(sc.storage[i].itemId, package);
|
if (added > 0) UIItemup.Up(sc.storage[i].itemId, added);
|
||||||
|
sc.storage[i].count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (var i = sc.storage.Length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
sc.storage[i].count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sc.storage = new StationStore[sc.storage.Length];
|
|
||||||
sc.needs = new int[sc.needs.Length];
|
|
||||||
}
|
}
|
||||||
if (toBag)
|
if (toBag)
|
||||||
{
|
{
|
||||||
player.controller.actionBuild.DoDismantleObject(etd.id);
|
int protoId = 0;
|
||||||
|
factory.DismantleFinally(player, etd.id, ref protoId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
factory.RemoveEntityWithComponents(etd.id, false);
|
var objId = etd.id;
|
||||||
|
factory.BeforeDismantleObject(objId);
|
||||||
|
factory.RemoveEntityWithComponents(objId, false);
|
||||||
|
factory.OnDismantleObject(objId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,68 +76,485 @@ public static class PlanetFunctions
|
|||||||
uiGame.ShutAllFullScreens();
|
uiGame.ShutAllFullScreens();
|
||||||
}
|
}
|
||||||
player.controller.actionBuild.Close();
|
player.controller.actionBuild.Close();
|
||||||
|
|
||||||
var groundCombatModule = player.mecha.groundCombatModule;
|
var groundCombatModule = player.mecha.groundCombatModule;
|
||||||
for (var i = 0; i < groundCombatModule.moduleFleets.Length; i++)
|
for (var i = groundCombatModule.moduleFleets.Length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var entry = groundCombatModule.moduleFleets[i];
|
var entry = groundCombatModule.moduleFleets[i];
|
||||||
if (entry.fleetId <= 0 || !entry.fleetEnabled) continue;
|
if (entry.fleetId <= 0 || !entry.fleetEnabled) continue;
|
||||||
entry.fleetEnabled = false;
|
entry.fleetEnabled = false;
|
||||||
groundCombatModule.RemoveFleetDirectly(i);
|
groundCombatModule.RemoveFleetDirectly(i);
|
||||||
}
|
}
|
||||||
//planet.data = new PlanetRawData(planet.precision);
|
var constructionSystem = factory.constructionSystem;
|
||||||
//planet.data.CalcVerts();
|
var constructionModule = player.mecha.constructionModule;
|
||||||
for (var id = factory.entityCursor - 1; id > 0; id--)
|
for (var i = constructionSystem.drones.cursor - 1; i > 0; i--)
|
||||||
{
|
{
|
||||||
ref var ed = ref factory.entityPool[id];
|
ref var drone = ref constructionSystem.drones.buffer[i];
|
||||||
if (ed.id != id) continue;
|
if (drone.id <= 0) continue;
|
||||||
if (ed.colliderId != 0)
|
var owner = drone.owner;
|
||||||
|
constructionSystem.ResetDroneTargets(ref drone);
|
||||||
|
if (owner == 0)
|
||||||
{
|
{
|
||||||
planet.physics.RemoveLinkedColliderData(ed.colliderId);
|
factory.RemoveCraftWithComponents(drone.craftId);
|
||||||
planet.physics.NotifyObjectRemove(EObjectType.Entity, ed.id);
|
constructionModule.droneIdleCount++;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (ed.modelId != 0)
|
|
||||||
{
|
{
|
||||||
GameMain.gpuiManager.RemoveModel(ed.modelIndex, ed.modelId);
|
drone.movement = factory.gameData.history.constructionDroneMovement;
|
||||||
|
factory.craftPool[drone.craftId].pos = constructionSystem.constructionModules[owner].baseEjectPos;
|
||||||
|
constructionSystem.constructionModules[owner].droneIdleCount++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (ed.mmblockId != 0)
|
if (constructionSystem.constructStats?.buffer != null)
|
||||||
|
{
|
||||||
|
for (var i = constructionSystem.constructStats.cursor - 1; i > 0; i--)
|
||||||
{
|
{
|
||||||
factory.blockContainer.RemoveMiniBlock(ed.mmblockId);
|
ref var constructStat = ref constructionSystem.constructStats.buffer[i];
|
||||||
|
if (constructStat.id <= 0) continue;
|
||||||
|
constructionSystem.RemoveConstructStat(constructStat.id);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
constructionModule.autoReconstructTargetTotalCount = 0;
|
||||||
|
constructionModule.buildTargetTotalCount = 0;
|
||||||
|
constructionModule.repairTargetTotalCount = 0;
|
||||||
|
constructionModule.autoReconstructTargets = null;
|
||||||
|
constructionModule.buildTargets = null;
|
||||||
|
constructionModule.repairTargets = null;
|
||||||
|
constructionModule.tmpTargets = null;
|
||||||
|
constructionModule.tmpTargetsHash = null;
|
||||||
|
constructionModule.checkItemCursor = 0;
|
||||||
|
|
||||||
if (ed.audioId == 0) continue;
|
var gameData = GameMain.data;
|
||||||
planet.audio?.RemoveAudioData(ed.audioId);
|
|
||||||
|
var returnBuildings = ReturnBuildingsOnInitializeEnabled.Value;
|
||||||
|
var returnLogisticStorageItems = ReturnLogisticStorageItemsOnInitializeEnabled.Value;
|
||||||
|
var returnBeltAFactoryItems = ReturnBeltAFactoryItemsOnInitializeEnabled.Value;
|
||||||
|
var returnedItems = new Dictionary<int, (long count, int inc)>();
|
||||||
|
|
||||||
|
static void AddReturnedItem(int itemId, int count, int inc, Dictionary<int, (long count, int inc)> returnedItems)
|
||||||
|
{
|
||||||
|
if (returnedItems.TryGetValue(itemId, out var value))
|
||||||
|
{
|
||||||
|
returnedItems[itemId] = (value.count + count, value.inc + inc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
returnedItems[itemId] = (count, inc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (planet.factory.enemyPool != null)
|
if (returnBuildings || returnBeltAFactoryItems)
|
||||||
{
|
{
|
||||||
for (var i = planet.factory.enemyCursor - 1; i > 0; i--)
|
var factoryStorage = factory.factoryStorage;
|
||||||
|
var factorySystem = factory.factorySystem;
|
||||||
|
var planetTransport = factory.transport;
|
||||||
|
var defenseSystem = factory.defenseSystem;
|
||||||
|
var powerSystem = factory.powerSystem;
|
||||||
|
var cargoTraffic = factory.cargoTraffic;
|
||||||
|
for (var i = factory.entityCursor - 1; i > 0; i--)
|
||||||
{
|
{
|
||||||
ref var enemyData = ref planet.factory.enemyPool[i];
|
ref var ed = ref factory.entityPool[i];
|
||||||
if (enemyData.id != i) continue;
|
if (ed.id != i) continue;
|
||||||
var combatStatId = enemyData.combatStatId;
|
if (ed.protoId <= 0) continue;
|
||||||
planet.factory.skillSystem.OnRemovingSkillTarget(combatStatId, planet.factory.skillSystem.combatStats.buffer[combatStatId].originAstroId, ETargetType.CombatStat);
|
if (returnBuildings) AddReturnedItem(ed.protoId, 1, 0, returnedItems);
|
||||||
planet.factory.skillSystem.combatStats.Remove(combatStatId);
|
if (!returnBeltAFactoryItems) continue;
|
||||||
planet.factory.KillEnemyFinally(player, i, ref CombatStat.empty);
|
#region Storage Items
|
||||||
|
var storageId = ed.storageId;
|
||||||
|
if (storageId > 0)
|
||||||
|
{
|
||||||
|
var storage = factoryStorage.storagePool[storageId];
|
||||||
|
if (storage != null)
|
||||||
|
{
|
||||||
|
for (var j = storage.size - 1; j >= 0; j--)
|
||||||
|
{
|
||||||
|
var count = storage.grids[j].count;
|
||||||
|
if (count <= 0) continue;
|
||||||
|
AddReturnedItem(storage.grids[j].itemId, count, storage.grids[j].inc, returnedItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Tank Items
|
||||||
|
var tankId = ed.tankId;
|
||||||
|
if (tankId > 0)
|
||||||
|
{
|
||||||
|
ref var tank = ref factoryStorage.tankPool[tankId];
|
||||||
|
var fluidId = tank.fluidId;
|
||||||
|
var fluidCount = tank.fluidCount;
|
||||||
|
if (fluidId > 0 && fluidCount > 0) AddReturnedItem(fluidId, fluidCount, tank.fluidInc, returnedItems);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Miner Items
|
||||||
|
var minerId = ed.minerId;
|
||||||
|
if (minerId > 0)
|
||||||
|
{
|
||||||
|
ref var miner = ref factorySystem.minerPool[minerId];
|
||||||
|
var productId = miner.productId;
|
||||||
|
var productCount = miner.productCount;
|
||||||
|
if (productId > 0 && productCount > 0) AddReturnedItem(productId, productCount, 0, returnedItems);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Inserter Items
|
||||||
|
var inserterId = ed.inserterId;
|
||||||
|
if (inserterId > 0)
|
||||||
|
{
|
||||||
|
ref var inserter = ref factorySystem.inserterPool[inserterId];
|
||||||
|
var itemId = inserter.itemId;
|
||||||
|
var itemCount = inserter.itemCount;
|
||||||
|
if (itemId > 0 && itemCount > 0) AddReturnedItem(itemId, itemCount, inserter.itemInc, returnedItems);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Assembler Items
|
||||||
|
var assemblerId = ed.assemblerId;
|
||||||
|
if (assemblerId > 0)
|
||||||
|
{
|
||||||
|
ref var assembler = ref factorySystem.assemblerPool[assemblerId];
|
||||||
|
if (assembler.recipeId > 0)
|
||||||
|
{
|
||||||
|
var products = assembler.recipeExecuteData.products;
|
||||||
|
var requires = assembler.recipeExecuteData.requires;
|
||||||
|
var requireCounts = assembler.recipeExecuteData.requireCounts;
|
||||||
|
for (var j = products.Length - 1; j >= 0; j--)
|
||||||
|
{
|
||||||
|
var product = products[j];
|
||||||
|
var produced = assembler.produced[j];
|
||||||
|
if (produced > 0) AddReturnedItem(product, produced, 0, returnedItems);
|
||||||
|
}
|
||||||
|
for (var j = requires.Length - 1; j >= 0; j--)
|
||||||
|
{
|
||||||
|
var require = requires[j];
|
||||||
|
var served = assembler.served[j];
|
||||||
|
var incServed = assembler.incServed[j];
|
||||||
|
if (incServed > served * 10) incServed = served * 10;
|
||||||
|
if (assembler.replicating) served += requireCounts[j];
|
||||||
|
if (served > 0) AddReturnedItem(require, served, incServed, returnedItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Fractionator Items
|
||||||
|
var fractionatorId = ed.fractionatorId;
|
||||||
|
if (fractionatorId > 0)
|
||||||
|
{
|
||||||
|
ref var fractionator = ref factorySystem.fractionatorPool[fractionatorId];
|
||||||
|
var fluidId = fractionator.fluidId;
|
||||||
|
var fluidInputCount = fractionator.fluidInputCount;
|
||||||
|
if (fluidInputCount > 0) AddReturnedItem(fluidId, fluidInputCount, fractionator.fluidInputInc, returnedItems);
|
||||||
|
var fluidOutputCount = fractionator.fluidOutputCount;
|
||||||
|
if (fluidOutputCount > 0) AddReturnedItem(fluidId, fluidOutputCount, fractionator.fluidOutputInc, returnedItems);
|
||||||
|
var productOutputCount = fractionator.productOutputCount;
|
||||||
|
if (productOutputCount > 0) AddReturnedItem(fractionator.productId, productOutputCount, 0, returnedItems);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Ejector Items
|
||||||
|
var ejectorId = ed.ejectorId;
|
||||||
|
if (ejectorId > 0)
|
||||||
|
{
|
||||||
|
ref var ejector = ref factorySystem.ejectorPool[ejectorId];
|
||||||
|
var bulletCount = ejector.bulletCount;
|
||||||
|
if (bulletCount > 0) AddReturnedItem(ejector.bulletId, bulletCount, ejector.bulletInc, returnedItems);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Silo Items
|
||||||
|
var siloId = ed.siloId;
|
||||||
|
if (siloId > 0)
|
||||||
|
{
|
||||||
|
ref var silo = ref factorySystem.siloPool[siloId];
|
||||||
|
var itemCount = silo.bulletCount;
|
||||||
|
if (itemCount > 0) AddReturnedItem(silo.bulletId, itemCount, silo.bulletInc, returnedItems);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Lab Items
|
||||||
|
var labId = ed.labId;
|
||||||
|
if (labId > 0)
|
||||||
|
{
|
||||||
|
ref var lab = ref factorySystem.labPool[labId];
|
||||||
|
if (lab.recipeId > 0)
|
||||||
|
{
|
||||||
|
var products = lab.recipeExecuteData.products;
|
||||||
|
var requires = lab.recipeExecuteData.requires;
|
||||||
|
var requireCounts = lab.recipeExecuteData.requireCounts;
|
||||||
|
for (var j = products.Length - 1; j >= 0; j--)
|
||||||
|
{
|
||||||
|
var produced = lab.produced[j];
|
||||||
|
if (produced > 0) AddReturnedItem(products[j], produced, 0, returnedItems);
|
||||||
|
}
|
||||||
|
for (var j = requires.Length - 1; j >= 0; j--)
|
||||||
|
{
|
||||||
|
var served = lab.served[j];
|
||||||
|
var incServed = lab.incServed[j];
|
||||||
|
if (incServed > served * 10) incServed = served * 10;
|
||||||
|
if (lab.replicating) served += requireCounts[j];
|
||||||
|
if (served > 0) AddReturnedItem(requires[j], served, incServed, returnedItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lab.researchMode && lab.matrixServed != null)
|
||||||
|
{
|
||||||
|
for (var j = lab.matrixServed.Length - 1; j >= 0; j--)
|
||||||
|
{
|
||||||
|
var served = lab.matrixServed[j] / 3600;
|
||||||
|
if (served > 0) AddReturnedItem(LabComponent.matrixIds[j], served, lab.matrixIncServed[j] / 3600, returnedItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Dispenser Items
|
||||||
|
var dispenserId = ed.dispenserId;
|
||||||
|
if (dispenserId > 0)
|
||||||
|
{
|
||||||
|
var dispenser = planetTransport.dispenserPool[dispenserId];
|
||||||
|
var holdupPackage = dispenser.holdupPackage;
|
||||||
|
for (var j = holdupPackage.Length - 1; j >= 0; j--)
|
||||||
|
{
|
||||||
|
var count = holdupPackage[j].count;
|
||||||
|
if (count > 0) AddReturnedItem(holdupPackage[j].itemId, count, holdupPackage[j].inc, returnedItems);
|
||||||
|
}
|
||||||
|
var courierCount = dispenser.idleCourierCount + dispenser.workCourierCount;
|
||||||
|
if (courierCount > 0) AddReturnedItem((int)Common.KnownItemId.Bot, courierCount, 0, returnedItems);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Turret Items
|
||||||
|
var turretId = ed.turretId;
|
||||||
|
if (turretId > 0)
|
||||||
|
{
|
||||||
|
ref var turret = ref defenseSystem.turrets.buffer[turretId];
|
||||||
|
var itemCount = turret.itemCount;
|
||||||
|
if (itemCount > 0) AddReturnedItem(turret.itemId, itemCount, turret.itemInc, returnedItems);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Battle Base Items
|
||||||
|
var battleBaseId = ed.battleBaseId;
|
||||||
|
if (battleBaseId > 0)
|
||||||
|
{
|
||||||
|
ref var battleBase = ref defenseSystem.battleBases.buffer[battleBaseId];
|
||||||
|
var combatModule = battleBase.combatModule;
|
||||||
|
if (combatModule != null && combatModule.moduleFleets[0].fleetId <= 0)
|
||||||
|
{
|
||||||
|
var fighters = combatModule.moduleFleets[0].fighters;
|
||||||
|
for (var j = fighters.Length - 1; j >= 0; j--)
|
||||||
|
{
|
||||||
|
var fighterItemId = fighters[j].itemId;
|
||||||
|
var fighterCount = fighters[j].count;
|
||||||
|
if (fighterItemId > 0 && fighterCount > 0) AddReturnedItem(fighterItemId, fighterCount, 0, returnedItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Power Generator Items
|
||||||
|
var powerGeneratorId = ed.powerGenId;
|
||||||
|
if (powerGeneratorId > 0)
|
||||||
|
{
|
||||||
|
ref var powerGen = ref powerSystem.genPool[powerGeneratorId];
|
||||||
|
if (powerGen.fuelId > 0 && powerGen.fuelCount > 0) AddReturnedItem(powerGen.fuelId, powerGen.fuelCount, powerGen.fuelInc, returnedItems);
|
||||||
|
if (powerGen.gamma)
|
||||||
|
{
|
||||||
|
var productId = powerGen.productId;
|
||||||
|
var productCount = (int)powerGen.productCount;
|
||||||
|
if (productId != 0 && productCount > 0) AddReturnedItem(productId, productCount, 0, returnedItems);
|
||||||
|
int catalystId = powerGen.catalystId;
|
||||||
|
var catalystPointDiv = powerGen.catalystPoint / 3600;
|
||||||
|
if (catalystId != 0 && catalystPointDiv > 0) AddReturnedItem(catalystId, catalystPointDiv, powerGen.catalystIncPoint / 3600, returnedItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Power Exchanger Items
|
||||||
|
var powerExchangerId = ed.powerExcId;
|
||||||
|
if (powerExchangerId > 0)
|
||||||
|
{
|
||||||
|
ref var powerExchanger = ref powerSystem.excPool[powerExchangerId];
|
||||||
|
var emptyCount = (int)powerExchanger.emptyCount;
|
||||||
|
if (emptyCount > 0) AddReturnedItem(powerExchanger.emptyId, emptyCount, powerExchanger.emptyInc, returnedItems);
|
||||||
|
var fullCount = (int)powerExchanger.fullCount;
|
||||||
|
if (fullCount > 0) AddReturnedItem(powerExchanger.fullId, fullCount, powerExchanger.fullInc, returnedItems);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Spraycoater Items
|
||||||
|
var spraycoaterId = ed.spraycoaterId;
|
||||||
|
if (spraycoaterId > 0)
|
||||||
|
{
|
||||||
|
ref var spraycoater = ref cargoTraffic.spraycoaterPool[spraycoaterId];
|
||||||
|
if (spraycoater.incItemId != 0 && spraycoater.incCount != 0)
|
||||||
|
{
|
||||||
|
var itemProto = LDB.items.Select(spraycoater.incItemId);
|
||||||
|
var count = spraycoater.incCount / itemProto.HpMax;
|
||||||
|
if (count != 0) AddReturnedItem(spraycoater.incItemId, count, 0, returnedItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Piler Items
|
||||||
|
var pilerId = ed.pilerId;
|
||||||
|
if (pilerId > 0)
|
||||||
|
{
|
||||||
|
ref var piler = ref cargoTraffic.pilerPool[pilerId];
|
||||||
|
var cacheCargoStack = (int)piler.cacheCargoStack1;
|
||||||
|
if (cacheCargoStack > 0) AddReturnedItem(piler.cacheItemId1, cacheCargoStack, piler.cacheCargoInc1, returnedItems);
|
||||||
|
var cacheCargoStack2 = (int)piler.cacheCargoStack2;
|
||||||
|
if (cacheCargoStack2 > 0) AddReturnedItem(piler.cacheItemId2, cacheCargoStack2, piler.cacheCargoInc2, returnedItems);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
if (returnBeltAFactoryItems)
|
||||||
|
{
|
||||||
|
#region Belt Items
|
||||||
|
for (var i = cargoTraffic.pathCursor - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
var cargoPath = cargoTraffic.pathPool[i];
|
||||||
|
if (cargoPath == null) continue;
|
||||||
|
var end = cargoPath.bufferLength - 5;
|
||||||
|
var buffer = cargoPath.buffer;
|
||||||
|
for (var j = 0; j <= end;)
|
||||||
|
{
|
||||||
|
if (buffer[j] >= 246)
|
||||||
|
{
|
||||||
|
var delta = 250 - buffer[j];
|
||||||
|
if (delta > 0) j += delta;
|
||||||
|
var bufferIndex = buffer[j + 1] - 1 + (buffer[j + 2] - 1) * 100 + (buffer[j + 3] - 1) * 10000 + (buffer[j + 4] - 1) * 1000000;
|
||||||
|
ref var cargo = ref cargoPath.cargoContainer.cargoPool[bufferIndex];
|
||||||
|
var stack = cargo.stack;
|
||||||
|
if (stack > 0) AddReturnedItem(cargo.item, stack, cargo.inc, returnedItems);
|
||||||
|
j += 10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
j += 5;
|
||||||
|
if (j > end && j < end + 5)
|
||||||
|
{
|
||||||
|
j = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
planet.factory.enemySystem.Free();
|
|
||||||
UIRoot.instance.uiGame.dfAssaultTip.ClearAllSpots();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var stationPool = factory.transport?.stationPool;
|
var stationPool = factory.transport?.stationPool;
|
||||||
if (stationPool != null)
|
if (stationPool != null)
|
||||||
{
|
{
|
||||||
foreach (var sc in stationPool)
|
var galacticTransport = gameData.galacticTransport;
|
||||||
|
for (var i = factory.transport.stationCursor - 1; i > 0; i--)
|
||||||
{
|
{
|
||||||
if (sc is not { id: > 0 }) continue;
|
var sc = stationPool[i];
|
||||||
sc.storage = new StationStore[sc.storage.Length];
|
if (sc == null || sc.id != i) continue;
|
||||||
sc.needs = new int[sc.needs.Length];
|
if (returnLogisticStorageItems)
|
||||||
int protoId = factory.entityPool[sc.entityId].protoId;
|
{
|
||||||
factory.DismantleFinally(player, sc.entityId, ref protoId);
|
for (var j = sc.storage.Length - 1; j >= 0; j--)
|
||||||
|
{
|
||||||
|
var count = sc.storage[j].count;
|
||||||
|
if (count > 0) AddReturnedItem(sc.storage[j].itemId, count, sc.storage[j].inc, returnedItems);
|
||||||
|
}
|
||||||
|
var droneCount = sc.idleDroneCount + sc.workDroneCount;
|
||||||
|
if (droneCount > 0) AddReturnedItem((int)Common.KnownItemId.Drone, droneCount, 0, returnedItems);
|
||||||
|
var shipCount = sc.idleShipCount + sc.workShipCount;
|
||||||
|
if (shipCount > 0) AddReturnedItem((int)Common.KnownItemId.Ship, shipCount, 0, returnedItems);
|
||||||
|
var warperCount = sc.warperCount;
|
||||||
|
if (warperCount > 0) AddReturnedItem((int)Common.KnownItemId.Warper, warperCount, 0, returnedItems);
|
||||||
|
}
|
||||||
|
var gid = sc.gid;
|
||||||
|
if (galacticTransport.stationPool[gid] != null)
|
||||||
|
{
|
||||||
|
galacticTransport.stationPool[gid] = null;
|
||||||
|
int cursor = galacticTransport.stationRecycleCursor;
|
||||||
|
galacticTransport.stationRecycleCursor = cursor + 1;
|
||||||
|
galacticTransport.stationRecycle[cursor] = gid;
|
||||||
|
}
|
||||||
|
galacticTransport.RemoveStation2StationRoute(gid);
|
||||||
|
galacticTransport.RefreshTraffic(gid);
|
||||||
|
sc.Reset();
|
||||||
|
}
|
||||||
|
if (galacticTransport.OnStellarStationRemoved != null)
|
||||||
|
{
|
||||||
|
galacticTransport.OnStellarStationRemoved();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var physics = planet.physics;
|
||||||
|
var gpuiManager = GameMain.gpuiManager;
|
||||||
|
var blockContainer = factory.blockContainer;
|
||||||
|
var audio = planet.audio;
|
||||||
|
for (var id = factory.entityCursor - 1; id > 0; id--)
|
||||||
|
{
|
||||||
|
ref var ed = ref factory.entityPool[id];
|
||||||
|
if (ed.id != id) continue;
|
||||||
|
|
||||||
|
factory.BeforeDismantleObject(id);
|
||||||
|
|
||||||
|
if (ed.colliderId != 0)
|
||||||
|
{
|
||||||
|
physics.RemoveLinkedColliderData(ed.colliderId);
|
||||||
|
physics.NotifyObjectRemove(EObjectType.Entity, ed.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ed.modelId != 0)
|
||||||
|
{
|
||||||
|
gpuiManager.RemoveModel(ed.modelIndex, ed.modelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ed.mmblockId != 0)
|
||||||
|
{
|
||||||
|
blockContainer.RemoveMiniBlock(ed.mmblockId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ed.audioId != 0)
|
||||||
|
{
|
||||||
|
audio.RemoveAudioData(ed.audioId);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory.OnDismantleObject(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var id = factory.prebuildCursor - 1; id > 0; id--)
|
||||||
|
{
|
||||||
|
ref var pb = ref factory.prebuildPool[id];
|
||||||
|
if (pb.id != id) continue;
|
||||||
|
if (pb.colliderId != 0)
|
||||||
|
{
|
||||||
|
physics.RemoveLinkedColliderData(pb.colliderId);
|
||||||
|
}
|
||||||
|
if (pb.modelId != 0)
|
||||||
|
{
|
||||||
|
gpuiManager.RemovePrebuildModel(pb.modelIndex, pb.modelId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hives = GameMain.spaceSector?.dfHives;
|
||||||
|
if (hives != null)
|
||||||
|
{
|
||||||
|
var hive = hives[planet.star.index];
|
||||||
|
var relays = hive?.relays?.buffer;
|
||||||
|
if (relays != null)
|
||||||
|
{
|
||||||
|
var astroId = planet.astroId;
|
||||||
|
for (var i = relays.Length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var relay = relays[i];
|
||||||
|
if (relay == null || relay.id != i) continue;
|
||||||
|
if (relay.targetAstroId != astroId && relay.searchAstroId != astroId) continue;
|
||||||
|
relay.targetAstroId = 0;
|
||||||
|
relay.searchAstroId = 0;
|
||||||
|
if (relay.baseId > 0)
|
||||||
|
hive.relayNeutralizedCounter++;
|
||||||
|
relay.LeaveBase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (factory.enemyPool != null)
|
||||||
|
{
|
||||||
|
for (var i = factory.enemyCursor - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
ref var enemyData = ref factory.enemyPool[i];
|
||||||
|
if (enemyData.id != i) continue;
|
||||||
|
var combatStatId = enemyData.combatStatId;
|
||||||
|
factory.skillSystem.OnRemovingSkillTarget(combatStatId, factory.skillSystem.combatStats.buffer[combatStatId].originAstroId, ETargetType.CombatStat);
|
||||||
|
factory.skillSystem.combatStats.Remove(combatStatId);
|
||||||
|
factory.KillEnemyFinally(i, ref CombatStat.empty);
|
||||||
|
}
|
||||||
|
factory.enemySystem.Free();
|
||||||
|
UIRoot.instance.uiGame.dfAssaultTip.ClearAllSpots();
|
||||||
|
}
|
||||||
|
|
||||||
|
var planetId = planet.id;
|
||||||
var gameScenario = GameMain.gameScenario;
|
var gameScenario = GameMain.gameScenario;
|
||||||
if (gameScenario != null)
|
if (gameScenario != null)
|
||||||
{
|
{
|
||||||
@@ -131,8 +565,8 @@ public static class PlanetFunctions
|
|||||||
{
|
{
|
||||||
if (pgc.id <= 0) continue;
|
if (pgc.id <= 0) continue;
|
||||||
int protoId = factory.entityPool[pgc.entityId].protoId;
|
int protoId = factory.entityPool[pgc.entityId].protoId;
|
||||||
gameScenario.achievementLogic.NotifyBeforeDismantleEntity(planet.id, protoId, pgc.entityId);
|
gameScenario.achievementLogic.NotifyBeforeDismantleEntity(planetId, protoId, pgc.entityId);
|
||||||
gameScenario.NotifyOnDismantleEntity(planet.id, protoId, pgc.entityId);
|
gameScenario.NotifyOnDismantleEntity(planetId, protoId, pgc.entityId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,12 +578,25 @@ public static class PlanetFunctions
|
|||||||
|
|
||||||
planet.UnloadFactory();
|
planet.UnloadFactory();
|
||||||
var index = factory.index;
|
var index = factory.index;
|
||||||
var warningSystem = GameMain.data.warningSystem;
|
var warningSystem = gameData.warningSystem;
|
||||||
var warningPool = warningSystem.warningPool;
|
var warningPool = warningSystem.warningPool;
|
||||||
for (var i = warningSystem.warningCursor - 1; i > 0; i--)
|
for (var i = warningSystem.warningCursor - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (warningPool[i].id == i && warningPool[i].factoryId == index)
|
ref var warning = ref warningPool[i];
|
||||||
warningSystem.RemoveWarningData(warningPool[i].id);
|
if (warning.id != i) continue;
|
||||||
|
switch (warning.factoryId)
|
||||||
|
{
|
||||||
|
case -4:
|
||||||
|
if (warning.astroId == planetId)
|
||||||
|
warningSystem.RemoveWarningData(i);
|
||||||
|
break;
|
||||||
|
case >= 0:
|
||||||
|
if (warning.factoryId == index)
|
||||||
|
warningSystem.RemoveWarningData(i);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var isCombatMode = factory.gameData.gameDesc.isCombatMode;
|
var isCombatMode = factory.gameData.gameDesc.isCombatMode;
|
||||||
factory.entityCursor = 1;
|
factory.entityCursor = 1;
|
||||||
@@ -176,6 +623,19 @@ public static class PlanetFunctions
|
|||||||
factory.factoryStorage = new FactoryStorage(planet);
|
factory.factoryStorage = new FactoryStorage(planet);
|
||||||
factory.powerSystem = new PowerSystem(planet);
|
factory.powerSystem = new PowerSystem(planet);
|
||||||
factory.constructionSystem = new ConstructionSystem(planet);
|
factory.constructionSystem = new ConstructionSystem(planet);
|
||||||
|
if (factory.veinPool != null)
|
||||||
|
{
|
||||||
|
for (var i = factory.veinPool.Length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
ref var vein = ref factory.veinPool[i];
|
||||||
|
if (vein.id != i) continue;
|
||||||
|
vein.minerCount = 0;
|
||||||
|
vein.minerId0 = 0;
|
||||||
|
vein.minerId1 = 0;
|
||||||
|
vein.minerId2 = 0;
|
||||||
|
vein.minerId3 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
factory.InitVeinHashAddress();
|
factory.InitVeinHashAddress();
|
||||||
factory.RecalculateAllVeinGroups();
|
factory.RecalculateAllVeinGroups();
|
||||||
factory.InitVegeHashAddress();
|
factory.InitVegeHashAddress();
|
||||||
@@ -188,8 +648,9 @@ public static class PlanetFunctions
|
|||||||
factory.combatGroundSystem = new CombatGroundSystem(planet);
|
factory.combatGroundSystem = new CombatGroundSystem(planet);
|
||||||
factory.defenseSystem = new DefenseSystem(planet);
|
factory.defenseSystem = new DefenseSystem(planet);
|
||||||
factory.planetATField = new PlanetATField(planet);
|
factory.planetATField = new PlanetATField(planet);
|
||||||
factory.transport = new PlanetTransport(GameMain.data, planet);
|
factory.transport = new PlanetTransport(gameData, planet);
|
||||||
factory.transport.Init();
|
factory.transport.Init();
|
||||||
|
factory.RefreshHashSystems();
|
||||||
var mem = new MemoryStream();
|
var mem = new MemoryStream();
|
||||||
var writer = new BinaryWriter(mem);
|
var writer = new BinaryWriter(mem);
|
||||||
factory.platformSystem.Export(writer);
|
factory.platformSystem.Export(writer);
|
||||||
@@ -206,7 +667,13 @@ public static class PlanetFunctions
|
|||||||
while (!planet.factoryLoaded)
|
while (!planet.factoryLoaded)
|
||||||
{
|
{
|
||||||
PlanetModelingManager.Update();
|
PlanetModelingManager.Update();
|
||||||
Thread.Sleep(0);
|
System.Threading.Thread.Sleep(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var kvp in returnedItems)
|
||||||
|
{
|
||||||
|
var added = player.TryAddItemToPackage(kvp.Key, (int)kvp.Value.count, kvp.Value.inc, true);
|
||||||
|
if (added > 0) UIItemup.Up(kvp.Key, added);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +692,7 @@ public static class PlanetFunctions
|
|||||||
var entityPool = factory.entityPool;
|
var entityPool = factory.entityPool;
|
||||||
var pos = new Vector3(0f, 0f, planet.realRadius * 1.025f + 0.2f);
|
var pos = new Vector3(0f, 0f, planet.realRadius * 1.025f + 0.2f);
|
||||||
var found = false;
|
var found = false;
|
||||||
for (var i = 1; i < stationCursor; i++)
|
for (var i = stationCursor - 1; i > 0; i--)
|
||||||
{
|
{
|
||||||
if (stationPool[i] == null || stationPool[i].id != i) continue;
|
if (stationPool[i] == null || stationPool[i].id != i) continue;
|
||||||
ref var entity = ref entityPool[stationPool[i].entityId];
|
ref var entity = ref entityPool[stationPool[i].entityId];
|
||||||
@@ -237,7 +704,7 @@ public static class PlanetFunctions
|
|||||||
var prebuildPool = factory.prebuildPool;
|
var prebuildPool = factory.prebuildPool;
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
for (var i = 1; i < prebuildCursor; i++)
|
for (var i = prebuildCursor - 1; i > 0; i--)
|
||||||
{
|
{
|
||||||
if (prebuildPool[i].id != i) continue;
|
if (prebuildPool[i].id != i) continue;
|
||||||
pos = prebuildPool[i].pos;
|
pos = prebuildPool[i].pos;
|
||||||
@@ -260,7 +727,7 @@ public static class PlanetFunctions
|
|||||||
{
|
{
|
||||||
/* Check for collision */
|
/* Check for collision */
|
||||||
var collide = false;
|
var collide = false;
|
||||||
for (var j = 1; j < stationCursor; j++)
|
for (var j = stationCursor - 1; j > 0; j--)
|
||||||
{
|
{
|
||||||
if (stationPool[j] == null || stationPool[j].id != j) continue;
|
if (stationPool[j] == null || stationPool[j].id != j) continue;
|
||||||
if ((entityPool[stationPool[j].entityId].pos - pos).sqrMagnitude >= 14297f) continue;
|
if ((entityPool[stationPool[j].entityId].pos - pos).sqrMagnitude >= 14297f) continue;
|
||||||
|
|||||||
293
UXAssist/Functions/TechFunctions.cs
Normal file
293
UXAssist/Functions/TechFunctions.cs
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
namespace UXAssist.Functions;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Common;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public static class TechFunctions
|
||||||
|
{
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
I18N.Add("Do you want to use metadata to buyout the following tech?", "Do you want to use metadata to buyout the following tech?", "要使用元数据买断以下科技吗?");
|
||||||
|
I18N.Add("The following is the required metadata for buyout:", "The following is the required metadata for buyout:", "以下是买断所需元数据:");
|
||||||
|
I18N.Add("Batch buyout tech", "Batch buyout tech", "批量买断科技");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CheckTechUnlockProperties(GameHistoryData history, TechProto techProto, SortedList<int, int> properties, List<Tuple<TechProto, int, int>> techList, int maxLevel = 10000, bool withPrerequisites = true, HashSet<int> seenTechs = null)
|
||||||
|
{
|
||||||
|
var techID = techProto.ID;
|
||||||
|
if (seenTechs!.Contains(techID)) return;
|
||||||
|
var techStates = history.techStates;
|
||||||
|
if (techStates == null || !techStates.TryGetValue(techID, out var value)) return;
|
||||||
|
if (value.unlocked) return;
|
||||||
|
|
||||||
|
var maxLvl = Math.Min(maxLevel < 0 ? value.curLevel - maxLevel - 1 : maxLevel, value.maxLevel);
|
||||||
|
if (withPrerequisites)
|
||||||
|
{
|
||||||
|
foreach (var preid in techProto.PreTechs)
|
||||||
|
{
|
||||||
|
var preProto = LDB.techs.Select(preid);
|
||||||
|
if (preProto != null)
|
||||||
|
CheckTechUnlockProperties(history, preProto, properties, techList, techProto.PreTechsMax ? 10000 : preProto.Level, true, seenTechs);
|
||||||
|
}
|
||||||
|
foreach (var preid in techProto.PreTechsImplicit)
|
||||||
|
{
|
||||||
|
var preProto = LDB.techs.Select(preid);
|
||||||
|
if (preProto != null)
|
||||||
|
CheckTechUnlockProperties(history, preProto, properties, techList, techProto.PreTechsMax ? 10000 : preProto.Level, true, seenTechs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.curLevel < techProto.Level) value.curLevel = techProto.Level;
|
||||||
|
techList.Add(new Tuple<TechProto, int, int>(techProto, value.curLevel, techProto.Level));
|
||||||
|
seenTechs!.Add(techID);
|
||||||
|
while (value.curLevel <= maxLvl)
|
||||||
|
{
|
||||||
|
if (techProto.PropertyOverrideItemArray != null)
|
||||||
|
{
|
||||||
|
var propertyOverrideItemArray = techProto.PropertyOverrideItemArray;
|
||||||
|
for (var i = 0; i < propertyOverrideItemArray.Length; i++)
|
||||||
|
{
|
||||||
|
var id = propertyOverrideItemArray[i].id;
|
||||||
|
var count = (float)propertyOverrideItemArray[i].count;
|
||||||
|
var ratio = Mathf.Clamp01((float)((double)value.hashUploaded / value.hashNeeded));
|
||||||
|
var consume = Mathf.CeilToInt(count * (1f - ratio));
|
||||||
|
if (properties.TryGetValue(id, out var existingCount))
|
||||||
|
properties[id] = existingCount + consume;
|
||||||
|
else
|
||||||
|
properties.Add(id, consume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (var i = 0; i < techProto.itemArray.Length; i++)
|
||||||
|
{
|
||||||
|
var id = techProto.itemArray[i].ID;
|
||||||
|
var consume = (int)(techProto.ItemPoints[i] * (value.hashNeeded - value.hashUploaded) / 3600L);
|
||||||
|
if (properties.TryGetValue(id, out var existingCount))
|
||||||
|
properties[id] = existingCount + consume;
|
||||||
|
else
|
||||||
|
properties.Add(id, consume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value.curLevel++;
|
||||||
|
value.hashUploaded = 0;
|
||||||
|
value.hashNeeded = techProto.GetHashNeeded(value.curLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int UnlockTechImpl(GameHistoryData history, TechProto techProto, int maxLevel = 10000, bool withPrerequisites = true)
|
||||||
|
{
|
||||||
|
var techStates = history.techStates;
|
||||||
|
var techID = techProto.ID;
|
||||||
|
if (techStates == null || !techStates.TryGetValue(techID, out var value))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.unlocked)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxLvl = Math.Min(maxLevel < 0 ? value.curLevel - maxLevel - 1 : maxLevel, value.maxLevel);
|
||||||
|
|
||||||
|
if (withPrerequisites)
|
||||||
|
{
|
||||||
|
foreach (var preid in techProto.PreTechs)
|
||||||
|
{
|
||||||
|
var preProto = LDB.techs.Select(preid);
|
||||||
|
if (preProto != null)
|
||||||
|
UnlockTechImpl(history, preProto, techProto.PreTechsMax ? 10000 : preProto.Level, true);
|
||||||
|
}
|
||||||
|
foreach (var preid in techProto.PreTechsImplicit)
|
||||||
|
{
|
||||||
|
var preProto = LDB.techs.Select(preid);
|
||||||
|
if (preProto != null)
|
||||||
|
UnlockTechImpl(history, preProto, techProto.PreTechsMax ? 10000 : preProto.Level, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.curLevel < techProto.Level) value.curLevel = techProto.Level;
|
||||||
|
while (value.curLevel <= maxLvl)
|
||||||
|
{
|
||||||
|
if (value.curLevel == 0)
|
||||||
|
{
|
||||||
|
foreach (var recipe in techProto.UnlockRecipes)
|
||||||
|
{
|
||||||
|
history.UnlockRecipe(recipe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var j = 0; j < techProto.UnlockFunctions.Length; j++)
|
||||||
|
{
|
||||||
|
history.UnlockTechFunction(techProto.UnlockFunctions[j], techProto.UnlockValues[j], value.curLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var k = 0; k < techProto.AddItems.Length; k++)
|
||||||
|
{
|
||||||
|
history.GainTechAwards(techProto.AddItems[k], techProto.AddItemCounts[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
value.curLevel++;
|
||||||
|
}
|
||||||
|
|
||||||
|
value.unlocked = maxLvl >= value.maxLevel;
|
||||||
|
value.curLevel = value.unlocked ? maxLvl : maxLvl + 1;
|
||||||
|
value.hashNeeded = techProto.GetHashNeeded(value.curLevel);
|
||||||
|
value.hashUploaded = value.unlocked ? value.hashNeeded : 0;
|
||||||
|
techStates[techID] = value;
|
||||||
|
return maxLvl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool UnlockTechImmediately(TechProto techProto, int maxLevel = 10000, bool withPrerequisites = true)
|
||||||
|
{
|
||||||
|
if (techProto == null) return false;
|
||||||
|
var history = GameMain.history;
|
||||||
|
var ulvl = UnlockTechImpl(history, techProto, maxLevel, withPrerequisites);
|
||||||
|
if (ulvl < 0) return false;
|
||||||
|
history.RegFeatureKey(1000100);
|
||||||
|
history.NotifyTechUnlock(techProto.ID, ulvl);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UnlockAllProtoWithMetadataAndPrompt()
|
||||||
|
{
|
||||||
|
var history = GameMain.history;
|
||||||
|
List<TechProto> techProtos = [];
|
||||||
|
foreach (var techProto in LDB.techs.dataArray)
|
||||||
|
{
|
||||||
|
if (techProto.Published && !techProto.IsObsolete && !techProto.IsHiddenTech && !history.TechUnlocked(techProto.ID) && (techProto.MaxLevel <= techProto.Level || techProto.MaxLevel <= 16) && (techProto.ID is (< 3301 or > 3309) and (< 3601 or > 3609) and (< 3901 or > 3909)) && techProto.ID != 1508)
|
||||||
|
{
|
||||||
|
techProtos.Add(techProto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnlockProtoWithMetadataAndPrompt([.. techProtos], 16, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UnlockProtoWithMetadataAndPrompt(TechProto[] techProtos, int toLevel, bool withPrerequisites = true)
|
||||||
|
{
|
||||||
|
var techList = new List<Tuple<TechProto, int, int>>();
|
||||||
|
var properties = new SortedList<int, int>();
|
||||||
|
var history = GameMain.history;
|
||||||
|
var seenTechs = new HashSet<int>();
|
||||||
|
foreach (var techProto in techProtos)
|
||||||
|
{
|
||||||
|
CheckTechUnlockProperties(history, techProto, properties, techList, toLevel, withPrerequisites, seenTechs);
|
||||||
|
}
|
||||||
|
var propertySystem = DSPGame.propertySystem;
|
||||||
|
var clusterSeedKey = history.gameData.GetClusterSeedKey();
|
||||||
|
var enough = true;
|
||||||
|
foreach (var consumption in properties)
|
||||||
|
{
|
||||||
|
if (propertySystem.GetItemAvaliableProperty(clusterSeedKey, consumption.Key) >= consumption.Value) continue;
|
||||||
|
enough = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!enough)
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("元数据".Translate(), "元数据不足".Translate(), "确定".Translate(), UIMessageBox.ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!history.hasUsedPropertyBanAchievement)
|
||||||
|
{
|
||||||
|
UIMessageBox.Show("初次使用元数据标题".Translate(), "初次使用元数据描述".Translate(), "取消".Translate(), "确定".Translate(), UIMessageBox.QUESTION, null, DoUnlockCalculatedTechs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoUnlockCalculatedTechs();
|
||||||
|
return;
|
||||||
|
|
||||||
|
void DoUnlockCalculatedTechs()
|
||||||
|
{
|
||||||
|
if (techList.Count <= 1)
|
||||||
|
{
|
||||||
|
UnlockWithPropertiesImmediately();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var msg = "Do you want to use metadata to buyout the following tech?".Translate();
|
||||||
|
|
||||||
|
if (techList.Count <= 10)
|
||||||
|
{
|
||||||
|
foreach (var tuple in techList)
|
||||||
|
{
|
||||||
|
AddToMsg(ref msg, tuple);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (var i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
AddToMsg(ref msg, techList[i]);
|
||||||
|
}
|
||||||
|
msg += "\n ...";
|
||||||
|
for (var i = techList.Count - 5; i < techList.Count; i++)
|
||||||
|
{
|
||||||
|
AddToMsg(ref msg, techList[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg += "\n\n";
|
||||||
|
msg += "The following is the required metadata for buyout:".Translate();
|
||||||
|
foreach (var consumption in properties)
|
||||||
|
{
|
||||||
|
if (consumption.Value <= 0) continue;
|
||||||
|
msg += $"\n {LDB.items.Select(consumption.Key).propertyName}x{consumption.Value}";
|
||||||
|
}
|
||||||
|
UIMessageBox.Show("Batch buyout tech".Translate(), msg, "取消".Translate(), "确定".Translate(), UIMessageBox.QUESTION, null, UnlockWithPropertiesImmediately);
|
||||||
|
return;
|
||||||
|
|
||||||
|
void AddToMsg(ref string str, Tuple<TechProto, int, int> tuple)
|
||||||
|
{
|
||||||
|
if (tuple.Item2 == tuple.Item3)
|
||||||
|
{
|
||||||
|
if (tuple.Item2 <= 0)
|
||||||
|
str += $"\n {tuple.Item1.name}";
|
||||||
|
else
|
||||||
|
str += $"\n {tuple.Item1.name}{"杠等级".Translate()}{tuple.Item2}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
str += $"\n {tuple.Item1.name}{"杠等级".Translate()}{tuple.Item2}->{tuple.Item3}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnlockWithPropertiesImmediately()
|
||||||
|
{
|
||||||
|
var mainPlayer = GameMain.mainPlayer;
|
||||||
|
foreach (var consumption in properties)
|
||||||
|
{
|
||||||
|
if (consumption.Value <= 0) continue;
|
||||||
|
propertySystem.AddItemConsumption(clusterSeedKey, consumption.Key, consumption.Value);
|
||||||
|
history.AddPropertyItemConsumption(consumption.Key, consumption.Value, true);
|
||||||
|
mainPlayer.mecha.AddProductionStat(consumption.Key, consumption.Value, mainPlayer.nearestFactory);
|
||||||
|
mainPlayer.mecha.AddConsumptionStat(consumption.Key, consumption.Value, mainPlayer.nearestFactory);
|
||||||
|
}
|
||||||
|
foreach (var techProto in techProtos)
|
||||||
|
{
|
||||||
|
UnlockTechImmediately(techProto, toLevel, withPrerequisites);
|
||||||
|
}
|
||||||
|
history.VerifyTechQueue();
|
||||||
|
if (history.currentTech != history.techQueue[0])
|
||||||
|
{
|
||||||
|
history.currentTech = history.techQueue[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemoveCargoStackingTechs()
|
||||||
|
{
|
||||||
|
var history = GameMain.data?.history;
|
||||||
|
if (history == null) return;
|
||||||
|
history.inserterStackCountObsolete = 1;
|
||||||
|
for (var id = 3301; id <= 3305; id++)
|
||||||
|
{
|
||||||
|
history.techStates.TryGetValue(id, out var state);
|
||||||
|
if (!state.unlocked) continue;
|
||||||
|
state.unlocked = false;
|
||||||
|
state.hashUploaded = 0;
|
||||||
|
history.techStates[id] = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1104
UXAssist/Functions/UIFunctions.cs
Normal file
1104
UXAssist/Functions/UIFunctions.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using BepInEx.Configuration;
|
using BepInEx.Configuration;
|
||||||
using UnityEngine;
|
|
||||||
using UXAssist.Common;
|
using UXAssist.Common;
|
||||||
using UXAssist.Patches;
|
|
||||||
|
|
||||||
namespace UXAssist.Functions;
|
namespace UXAssist.Functions;
|
||||||
|
|
||||||
@@ -18,11 +16,7 @@ public static class WindowFunctions
|
|||||||
private static IntPtr _oldWndProc = IntPtr.Zero;
|
private static IntPtr _oldWndProc = IntPtr.Zero;
|
||||||
private static IntPtr _gameWindowHandle = IntPtr.Zero;
|
private static IntPtr _gameWindowHandle = IntPtr.Zero;
|
||||||
|
|
||||||
private static bool _gameLoaded;
|
|
||||||
public static WinApi.LogicalProcessorDetails ProcessorDetails { get; private set; }
|
|
||||||
|
|
||||||
public static ConfigEntry<int> ProcessPriority;
|
public static ConfigEntry<int> ProcessPriority;
|
||||||
public static ConfigEntry<int> ProcessAffinity;
|
|
||||||
|
|
||||||
private static readonly int[] ProrityFlags =
|
private static readonly int[] ProrityFlags =
|
||||||
[
|
[
|
||||||
@@ -37,125 +31,13 @@ public static class WindowFunctions
|
|||||||
{
|
{
|
||||||
if (_initialized) return;
|
if (_initialized) return;
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
I18N.Add("Cores: {0}\nThreads: {1}", "Cores: {0}\nThreads: {1}", "核心数: {0}\n线程数: {1}");
|
|
||||||
I18N.Add("\nP-Cores: {0}\nE-Cores: {1}", "\nP-Cores: {0}\nE-Cores: {1}", "\n性能核心: {0}\n能效核心: {1}");
|
|
||||||
I18N.Add("\nPriority: {0}", "\nProcess priority: {0}", "\n进程优先级: {0}");
|
|
||||||
I18N.Add("\nEnabled CPUs: ", "\nEnabled CPUs: ", "\n使用的CPU: ");
|
|
||||||
I18N.Add("Unknown", "Unknown", "未知");
|
|
||||||
ProcessorDetails = WinApi.GetLogicalProcessorDetails();
|
|
||||||
SetWindowTitle();
|
SetWindowTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Start()
|
public static void Start()
|
||||||
{
|
{
|
||||||
GameLogic.OnDataLoaded += OnDataLoaded;
|
|
||||||
var wndProc = new WinApi.WndProc(GameWndProc);
|
|
||||||
var gameWnd = FindGameWindow();
|
|
||||||
if (gameWnd != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
_oldWndProc = WinApi.SetWindowLongPtr(gameWnd, WinApi.GWLP_WNDPROC, Marshal.GetFunctionPointerForDelegate(wndProc));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GamePatch.LoadLastWindowRectEnabled.Value)
|
|
||||||
GamePatch.LoadLastWindowRect.MoveWindowPosition(true);
|
|
||||||
|
|
||||||
ProcessPriority.SettingChanged += (_, _) => WinApi.SetPriorityClass(WinApi.GetCurrentProcess(), ProrityFlags[ProcessPriority.Value]);
|
ProcessPriority.SettingChanged += (_, _) => WinApi.SetPriorityClass(WinApi.GetCurrentProcess(), ProrityFlags[ProcessPriority.Value]);
|
||||||
WinApi.SetPriorityClass(WinApi.GetCurrentProcess(), ProrityFlags[ProcessPriority.Value]);
|
WinApi.SetPriorityClass(WinApi.GetCurrentProcess(), ProrityFlags[ProcessPriority.Value]);
|
||||||
ProcessAffinity.SettingChanged += (_, _) => UpdateAffinity();
|
|
||||||
UpdateAffinity();
|
|
||||||
return;
|
|
||||||
|
|
||||||
void UpdateAffinity()
|
|
||||||
{
|
|
||||||
var process = WinApi.GetCurrentProcess();
|
|
||||||
if (!WinApi.GetProcessAffinityMask(process, out _, out var systemMask))
|
|
||||||
{
|
|
||||||
systemMask = ulong.MaxValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ProcessAffinity.Value)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
WinApi.SetProcessAffinityMask(process, systemMask);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
WinApi.SetProcessAffinityMask(process, systemMask & ((1UL << (ProcessorDetails.ThreadCount / 2)) - 1UL));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
WinApi.SetProcessAffinityMask(process, systemMask & (ProcessorDetails.ThreadCount > 16 ? 0xFFUL : 1UL));
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
WinApi.SetProcessAffinityMask(process, systemMask & ProcessorDetails.PerformanceCoreMask);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
WinApi.SetProcessAffinityMask(process, systemMask & ProcessorDetails.EfficiencyCoreMask);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Uninit()
|
|
||||||
{
|
|
||||||
GameLogic.OnDataLoaded -= OnDataLoaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void OnDataLoaded()
|
|
||||||
{
|
|
||||||
_gameLoaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IntPtr GameWndProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam)
|
|
||||||
{
|
|
||||||
switch (uMsg)
|
|
||||||
{
|
|
||||||
case WinApi.WM_ACTIVATE:
|
|
||||||
WinApi.SetPriorityClass(WinApi.GetCurrentProcess(), ProrityFlags[ProcessPriority.Value]);
|
|
||||||
break;
|
|
||||||
case WinApi.WM_DESTROY:
|
|
||||||
if (_oldWndProc != IntPtr.Zero && _gameWindowHandle != IntPtr.Zero)
|
|
||||||
{
|
|
||||||
WinApi.SetWindowLongPtr(_gameWindowHandle, WinApi.GWLP_WNDPROC, _oldWndProc);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case WinApi.WM_SYSCOMMAND:
|
|
||||||
switch ((long)wParam & 0xFFF0L)
|
|
||||||
{
|
|
||||||
case WinApi.SC_MOVE:
|
|
||||||
if (GamePatch.LoadLastWindowRectEnabled.Value && !_gameLoaded) return (IntPtr)1L;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case WinApi.WM_MOVING:
|
|
||||||
if (!GamePatch.LoadLastWindowRectEnabled.Value || _gameLoaded) break;
|
|
||||||
var rect = GamePatch.LastWindowRect.Value;
|
|
||||||
if (rect is { z: 0f, w: 0f }) break;
|
|
||||||
var x = Mathf.RoundToInt(rect.x);
|
|
||||||
var y = Mathf.RoundToInt(rect.y);
|
|
||||||
var rect2 = Marshal.PtrToStructure<WinApi.Rect>(lParam);
|
|
||||||
rect2.Left = x;
|
|
||||||
rect2.Top = y;
|
|
||||||
Marshal.StructureToPtr(rect2, lParam, false);
|
|
||||||
break;
|
|
||||||
case WinApi.WM_SIZING:
|
|
||||||
if (!GamePatch.LoadLastWindowRectEnabled.Value || _gameLoaded) break;
|
|
||||||
rect = GamePatch.LastWindowRect.Value;
|
|
||||||
if (rect is { z: 0f, w: 0f }) break;
|
|
||||||
x = Mathf.RoundToInt(rect.x);
|
|
||||||
y = Mathf.RoundToInt(rect.y);
|
|
||||||
var w = Mathf.RoundToInt(rect.z);
|
|
||||||
var h = Mathf.RoundToInt(rect.w);
|
|
||||||
rect2 = Marshal.PtrToStructure<WinApi.Rect>(lParam);
|
|
||||||
rect2.Left = x;
|
|
||||||
rect2.Top = y;
|
|
||||||
rect2.Right = x + w;
|
|
||||||
rect2.Bottom = y + h;
|
|
||||||
Marshal.StructureToPtr(rect2, lParam, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return WinApi.CallWindowProc(_oldWndProc, hWnd, uMsg, wParam, lParam);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetPriorityName(int priority)
|
private static string GetPriorityName(int priority)
|
||||||
@@ -171,72 +53,36 @@ public static class WindowFunctions
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ShowCPUInfo()
|
|
||||||
{
|
|
||||||
var details = ProcessorDetails;
|
|
||||||
var msg = string.Format("Cores: {0}\nThreads: {1}".Translate(), details.CoreCount, details.ThreadCount);
|
|
||||||
var hybrid = details.HybridArchitecture;
|
|
||||||
if (hybrid)
|
|
||||||
{
|
|
||||||
msg += string.Format("\nP-Cores: {0}\nE-Cores: {1}".Translate(), details.PerformanceCoreCount, details.EfficiencyCoreCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
var handle = WinApi.GetCurrentProcess();
|
|
||||||
var prio = GetPriorityName(WinApi.GetPriorityClass(handle));
|
|
||||||
msg += string.Format("\nPriority: {0}".Translate(), prio);
|
|
||||||
|
|
||||||
var aff = 0UL;
|
|
||||||
if (WinApi.GetProcessAffinityMask(handle, out var processMask, out var systemMask))
|
|
||||||
aff = processMask & systemMask;
|
|
||||||
|
|
||||||
msg += "\nEnabled CPUs: ".Translate();
|
|
||||||
var first = true;
|
|
||||||
for (var i = 0; aff != 0UL; i++)
|
|
||||||
{
|
|
||||||
if ((aff & 1UL) != 0)
|
|
||||||
{
|
|
||||||
if (first)
|
|
||||||
first = false;
|
|
||||||
else
|
|
||||||
msg += ",";
|
|
||||||
msg += i;
|
|
||||||
if (hybrid)
|
|
||||||
{
|
|
||||||
if ((details.PerformanceCoreMask & (1UL << i)) != 0)
|
|
||||||
msg += "(P)";
|
|
||||||
else if ((details.EfficiencyCoreMask & (1UL << i)) != 0)
|
|
||||||
msg += "(E)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aff >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
UIMessageBox.Show("CPU Info".Translate(), msg, "确定".Translate(), -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetWindowTitle()
|
public static void SetWindowTitle()
|
||||||
{
|
{
|
||||||
// Get profile name from command line arguments, and set window title accordingly
|
// Get profile name from command line arguments, and set window title accordingly
|
||||||
var args = Environment.GetCommandLineArgs();
|
var args = Environment.GetCommandLineArgs();
|
||||||
for (var i = 0; i < args.Length - 1; i++)
|
for (var i = args.Length - 2; i >= 0; i--)
|
||||||
{
|
{
|
||||||
// Doorstop 3.x and 4.x use different arguments to pass the target assembly path
|
if (args[i] == "--gale-profile")
|
||||||
if (args[i] != "--doorstop-target" && args[i] != "--doorstop-target-assembly") continue;
|
{
|
||||||
var arg = args[i + 1];
|
// We use gale profile name directly
|
||||||
const string doorstopPathSuffix = @"\BepInEx\core\BepInEx.Preloader.dll";
|
ProfileName = args[i + 1];
|
||||||
if (!arg.EndsWith(doorstopPathSuffix, StringComparison.OrdinalIgnoreCase))
|
}
|
||||||
break;
|
else
|
||||||
arg = arg.Substring(0, arg.Length - doorstopPathSuffix.Length);
|
{
|
||||||
const string profileSuffix = @"\profiles\";
|
// Doorstop 3.x and 4.x use different arguments to pass the target assembly path
|
||||||
var index = arg.LastIndexOf(profileSuffix, StringComparison.OrdinalIgnoreCase);
|
if (args[i] != "--doorstop-target" && args[i] != "--doorstop-target-assembly") continue;
|
||||||
if (index < 0)
|
var arg = args[i + 1];
|
||||||
break;
|
const string doorstopPathSuffix = @"\BepInEx\core\BepInEx.Preloader.dll";
|
||||||
arg = arg.Substring(index + profileSuffix.Length);
|
if (!arg.EndsWith(doorstopPathSuffix, StringComparison.OrdinalIgnoreCase))
|
||||||
|
break;
|
||||||
|
arg = arg.Substring(0, arg.Length - doorstopPathSuffix.Length);
|
||||||
|
const string profileSuffix = @"\profiles\";
|
||||||
|
var index = arg.LastIndexOf(profileSuffix, StringComparison.OrdinalIgnoreCase);
|
||||||
|
if (index < 0)
|
||||||
|
break;
|
||||||
|
arg = arg.Substring(index + profileSuffix.Length);
|
||||||
|
ProfileName = arg;
|
||||||
|
}
|
||||||
var wnd = FindGameWindow();
|
var wnd = FindGameWindow();
|
||||||
if (wnd == IntPtr.Zero) return;
|
if (wnd == IntPtr.Zero) return;
|
||||||
ProfileName = arg;
|
_gameWindowTitle = $"Dyson Sphere Program - {ProfileName}";
|
||||||
_gameWindowTitle = $"Dyson Sphere Program - {arg}";
|
|
||||||
WinApi.SetWindowText(wnd, _gameWindowTitle);
|
WinApi.SetWindowText(wnd, _gameWindowTitle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
156
UXAssist/ModsCompat/BlueprintTweaks.cs
Normal file
156
UXAssist/ModsCompat/BlueprintTweaks.cs
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
using HarmonyLib;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
using UnityEngine;
|
||||||
|
using UXAssist.Functions;
|
||||||
|
|
||||||
|
namespace UXAssist.ModsCompat;
|
||||||
|
|
||||||
|
class BlueprintTweaks
|
||||||
|
{
|
||||||
|
public const string BlueprintTweaksGuid = "org.kremnev8.plugin.BlueprintTweaks";
|
||||||
|
private static FieldInfo selectObjIdsField;
|
||||||
|
private static Type classTypeBlueprintTweaksPlugin;
|
||||||
|
private static Type classTypeUIBuildingGridPatch2;
|
||||||
|
|
||||||
|
public static bool Run(Harmony harmony)
|
||||||
|
{
|
||||||
|
if (!BepInEx.Bootstrap.Chainloader.PluginInfos.TryGetValue(BlueprintTweaksGuid, out var pluginInfo)) return false;
|
||||||
|
var assembly = pluginInfo.Instance.GetType().Assembly;
|
||||||
|
var classTypeDragRemoveBuildTool = assembly.GetType("BlueprintTweaks.DragRemoveBuildTool");
|
||||||
|
if (classTypeDragRemoveBuildTool == null) return false;
|
||||||
|
if (AccessTools.Method(classTypeDragRemoveBuildTool, "DetermineMorePreviews") != null) return true;
|
||||||
|
classTypeBlueprintTweaksPlugin = assembly.GetType("BlueprintTweaks.BlueprintTweaksPlugin");
|
||||||
|
classTypeUIBuildingGridPatch2 = assembly.GetType("BlueprintTweaks.UIBuildingGridPatch2");
|
||||||
|
var UIBuildingGrid_Update = AccessTools.Method(typeof(UIBuildingGrid), nameof(UIBuildingGrid.Update));
|
||||||
|
harmony.Patch(AccessTools.Method(classTypeUIBuildingGridPatch2, "UpdateGrid"), null, null, new HarmonyMethod(AccessTools.Method(typeof(BlueprintTweaks), nameof(PatchUpdateGrid))));
|
||||||
|
selectObjIdsField = AccessTools.Field(classTypeDragRemoveBuildTool, "selectObjIds");
|
||||||
|
harmony.Patch(AccessTools.Method(classTypeDragRemoveBuildTool, "DeterminePreviews"),
|
||||||
|
new HarmonyMethod(AccessTools.Method(typeof(BlueprintTweaks), nameof(PatchDeterminePreviews))));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly int zMin = Shader.PropertyToID("_ZMin");
|
||||||
|
private static readonly int reformMode = Shader.PropertyToID("_ReformMode");
|
||||||
|
|
||||||
|
private static IEnumerable<CodeInstruction> PatchUpdateGrid(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
{
|
||||||
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldsfld, AccessTools.Field(classTypeBlueprintTweaksPlugin, "tool")),
|
||||||
|
new CodeMatch(OpCodes.Ldfld),
|
||||||
|
new CodeMatch(ci => ci.opcode == OpCodes.Brfalse || ci.opcode == OpCodes.Brfalse_S)
|
||||||
|
);
|
||||||
|
var label1 = generator.DefineLabel();
|
||||||
|
matcher.Advance(2).Operand = label1;
|
||||||
|
matcher.Advance(1);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIBuildingGrid), nameof(UIBuildingGrid.blueprintMaterial))),
|
||||||
|
new CodeMatch(OpCodes.Ldsfld, AccessTools.Field(classTypeUIBuildingGridPatch2, "tintColor")),
|
||||||
|
new CodeMatch(OpCodes.Call),
|
||||||
|
new CodeMatch(OpCodes.Callvirt)
|
||||||
|
).RemoveInstructions(5);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIBuildingGrid), nameof(UIBuildingGrid.blueprintMaterial))),
|
||||||
|
new CodeMatch(OpCodes.Ldsfld, AccessTools.Field(classTypeUIBuildingGridPatch2, "cursorGratBox")),
|
||||||
|
new CodeMatch(OpCodes.Ldsfld),
|
||||||
|
new CodeMatch(OpCodes.Ldfld),
|
||||||
|
new CodeMatch(OpCodes.Call),
|
||||||
|
new CodeMatch(OpCodes.Callvirt)
|
||||||
|
).Advance(1).Operand = AccessTools.Field(typeof(UIBuildingGrid), nameof(UIBuildingGrid.material));
|
||||||
|
matcher.Advance(6);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIBuildingGrid), nameof(UIBuildingGrid.blueprintMaterial))),
|
||||||
|
new CodeMatch(OpCodes.Ldsfld, AccessTools.Field(classTypeUIBuildingGridPatch2, "selectColor")),
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldfld),
|
||||||
|
new CodeMatch(OpCodes.Call),
|
||||||
|
new CodeMatch(OpCodes.Callvirt)
|
||||||
|
).Advance(1).Operand = AccessTools.Field(typeof(UIBuildingGrid), nameof(UIBuildingGrid.material));
|
||||||
|
matcher.Advance(1).Operand = AccessTools.Field(classTypeUIBuildingGridPatch2, "tintColor");
|
||||||
|
matcher.Advance(5);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIBuildingGrid), nameof(UIBuildingGrid.blueprintMaterial))),
|
||||||
|
new CodeMatch(OpCodes.Ldsfld, AccessTools.Field(classTypeUIBuildingGridPatch2, "showDivideLine")),
|
||||||
|
new CodeMatch(OpCodes.Ldc_R4, 0f),
|
||||||
|
new CodeMatch(OpCodes.Callvirt)
|
||||||
|
).RemoveInstructions(5);
|
||||||
|
matcher.InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0),
|
||||||
|
Transpilers.EmitDelegate((UIBuildingGrid grid) =>
|
||||||
|
{
|
||||||
|
grid.material.SetFloat(reformMode, 0f);
|
||||||
|
grid.material.SetFloat(zMin, -0.5f);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIBuildingGrid), nameof(UIBuildingGrid.blueprintGridRnd))),
|
||||||
|
new CodeMatch(OpCodes.Ldc_I4_1),
|
||||||
|
new CodeMatch(OpCodes.Callvirt),
|
||||||
|
new CodeMatch(ci => ci.opcode == OpCodes.Br || ci.opcode == OpCodes.Br_S)
|
||||||
|
).RemoveInstructions(4).Set(OpCodes.Ret, null).Labels.Add(label1);
|
||||||
|
return matcher.InstructionEnumeration();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void PatchDeterminePreviews(object __instance)
|
||||||
|
{
|
||||||
|
var selectObjIds = (HashSet<int>)selectObjIdsField.GetValue(__instance);
|
||||||
|
var buildTool = (BuildTool)__instance;
|
||||||
|
var factory = buildTool.factory;
|
||||||
|
HashSet<int> extraObjIds = [];
|
||||||
|
foreach (var objId in selectObjIds)
|
||||||
|
{
|
||||||
|
var desc = buildTool.GetPrefabDesc(objId);
|
||||||
|
var isBelt = desc.isBelt;
|
||||||
|
var isInserter = desc.isInserter;
|
||||||
|
if (isInserter) continue;
|
||||||
|
if (isBelt)
|
||||||
|
{
|
||||||
|
var needCheck = false;
|
||||||
|
for (var j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
factory.ReadObjectConn(objId, j, out _, out var connObjId, out _);
|
||||||
|
if (connObjId == 0 || FactoryFunctions.ObjectIsBeltOrInserter(factory, connObjId)) continue;
|
||||||
|
needCheck = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (needCheck)
|
||||||
|
{
|
||||||
|
for (var k = 0; k < 16; k++)
|
||||||
|
{
|
||||||
|
factory.ReadObjectConn(objId, k, out _, out var connObjId, out _);
|
||||||
|
if (connObjId != 0 && !selectObjIds.Contains(connObjId) && !extraObjIds.Contains(connObjId) && FactoryFunctions.ObjectIsBeltOrInserter(factory, connObjId))
|
||||||
|
extraObjIds.Add(connObjId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var m = 0; m < 4; m++)
|
||||||
|
{
|
||||||
|
factory.ReadObjectConn(objId, m, out _, out var connObjId, out _);
|
||||||
|
if (connObjId == 0 || !factory.ObjectIsBelt(connObjId) || selectObjIds.Contains(connObjId) || extraObjIds.Contains(connObjId)) continue;
|
||||||
|
for (var j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
factory.ReadObjectConn(connObjId, j, out _, out var connObjId2, out _);
|
||||||
|
if (connObjId2 == 0 || selectObjIds.Contains(connObjId2) || extraObjIds.Contains(connObjId2) || FactoryFunctions.ObjectIsBeltOrInserter(factory, connObjId2)) continue;
|
||||||
|
extraObjIds.Add(connObjId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (desc.addonType == EAddonType.Belt) continue;
|
||||||
|
for (var j = 0; j < 16; j++)
|
||||||
|
{
|
||||||
|
factory.ReadObjectConn(objId, j, out _, out var connObjId, out _);
|
||||||
|
if (connObjId != 0 && !selectObjIds.Contains(connObjId) && !extraObjIds.Contains(connObjId) && FactoryFunctions.ObjectIsBeltOrInserter(factory, connObjId))
|
||||||
|
extraObjIds.Add(connObjId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectObjIds.UnionWith(extraObjIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
UXAssist/ModsCompat/CommonAPIWrapper.cs
Normal file
20
UXAssist/ModsCompat/CommonAPIWrapper.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using BepInEx.Bootstrap;
|
||||||
|
using CommonAPI;
|
||||||
|
using HarmonyLib;
|
||||||
|
|
||||||
|
namespace UXAssist.ModsCompat;
|
||||||
|
|
||||||
|
public static class CommonAPIWrapper
|
||||||
|
{
|
||||||
|
public static void Run(Harmony harmony)
|
||||||
|
{
|
||||||
|
if (!Chainloader.PluginInfos.TryGetValue(CommonAPIPlugin.GUID, out var commonAPIPlugin) ||
|
||||||
|
commonAPIPlugin.Metadata.Version > new System.Version(1, 6, 7, 0)) return;
|
||||||
|
harmony.Patch(AccessTools.Method(typeof(GameOption), nameof(GameOption.InitKeys)), new HarmonyMethod(AccessTools.Method(typeof(CommonAPIWrapper), nameof(PatchInitKeys)), Priority.First));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool PatchInitKeys(GameOption __instance)
|
||||||
|
{
|
||||||
|
return __instance.overrideKeys == null;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
UXAssist/ModsCompat/PlanetVeinUtilization.cs
Normal file
23
UXAssist/ModsCompat/PlanetVeinUtilization.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using HarmonyLib;
|
||||||
|
|
||||||
|
namespace UXAssist.ModsCompat;
|
||||||
|
|
||||||
|
class PlanetVeinUtilization
|
||||||
|
{
|
||||||
|
public const string PlanetVeinUtilizationGuid = "testpostpleaseignore.dsp.planet_vein_utilization";
|
||||||
|
|
||||||
|
public static bool Run(Harmony harmony)
|
||||||
|
{
|
||||||
|
if (!BepInEx.Bootstrap.Chainloader.PluginInfos.TryGetValue(PlanetVeinUtilizationGuid, out var pluginInfo)) return false;
|
||||||
|
var assembly = pluginInfo.Instance.GetType().Assembly;
|
||||||
|
var classType = assembly.GetType("PlanetVeinUtilization.PlanetVeinUtilization");
|
||||||
|
harmony.Patch(AccessTools.Method(classType, "Awake"),
|
||||||
|
new HarmonyMethod(typeof(PlanetVeinUtilization).GetMethod("PatchPlanetVeinUtilizationAwake")));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool PatchPlanetVeinUtilizationAwake()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,10 +5,11 @@ using BepInEx.Configuration;
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UXAssist.Common;
|
using UXAssist.Common;
|
||||||
|
using GameLogicProc = UXAssist.Common.GameLogic;
|
||||||
|
|
||||||
namespace UXAssist.Patches;
|
namespace UXAssist.Patches;
|
||||||
|
|
||||||
public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
public class DysonSpherePatch : PatchImpl<DysonSpherePatch>
|
||||||
{
|
{
|
||||||
public static ConfigEntry<bool> StopEjectOnNodeCompleteEnabled;
|
public static ConfigEntry<bool> StopEjectOnNodeCompleteEnabled;
|
||||||
public static ConfigEntry<bool> OnlyConstructNodesEnabled;
|
public static ConfigEntry<bool> OnlyConstructNodesEnabled;
|
||||||
@@ -173,7 +174,7 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
{
|
{
|
||||||
lock (productRegister)
|
lock (productRegister)
|
||||||
{
|
{
|
||||||
productRegister[11902] += todoCount - count;
|
productRegister[ProductionStatistics.DYSON_STRUCTURE_ID] += todoCount - count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,8 +214,8 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
{
|
{
|
||||||
lock (productRegister)
|
lock (productRegister)
|
||||||
{
|
{
|
||||||
productRegister[11901] += solarSailCount;
|
productRegister[ProductionStatistics.SOLAR_SAIL_ID] += solarSailCount;
|
||||||
productRegister[11903] += solarSailCount;
|
productRegister[ProductionStatistics.DYSON_CELL_ID] += solarSailCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var consumeRegister = __instance.consumeRegister;
|
var consumeRegister = __instance.consumeRegister;
|
||||||
@@ -222,7 +223,7 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
{
|
{
|
||||||
lock (consumeRegister)
|
lock (consumeRegister)
|
||||||
{
|
{
|
||||||
consumeRegister[11901] += solarSailCount;
|
consumeRegister[ProductionStatistics.SOLAR_SAIL_ID] += solarSailCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,7 +261,7 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class StopEjectOnNodeComplete: PatchImpl<StopEjectOnNodeComplete>
|
private class StopEjectOnNodeComplete : PatchImpl<StopEjectOnNodeComplete>
|
||||||
{
|
{
|
||||||
private static HashSet<int>[] _nodeForAbsorb;
|
private static HashSet<int>[] _nodeForAbsorb;
|
||||||
private static bool _initialized;
|
private static bool _initialized;
|
||||||
@@ -268,14 +269,14 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
protected override void OnEnable()
|
protected override void OnEnable()
|
||||||
{
|
{
|
||||||
InitNodeForAbsorb();
|
InitNodeForAbsorb();
|
||||||
GameLogic.OnGameBegin += GameMain_Begin_Postfix;
|
GameLogicProc.OnGameBegin += OnGameBegin;
|
||||||
GameLogic.OnGameEnd += GameMain_End_Postfix;
|
GameLogicProc.OnGameEnd += OnGameEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisable()
|
protected override void OnDisable()
|
||||||
{
|
{
|
||||||
GameLogic.OnGameEnd -= GameMain_End_Postfix;
|
GameLogicProc.OnGameEnd -= OnGameEnd;
|
||||||
GameLogic.OnGameBegin -= GameMain_Begin_Postfix;
|
GameLogicProc.OnGameBegin -= OnGameBegin;
|
||||||
_initialized = false;
|
_initialized = false;
|
||||||
_nodeForAbsorb = null;
|
_nodeForAbsorb = null;
|
||||||
}
|
}
|
||||||
@@ -346,12 +347,12 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
return comp is { Count: > 0 };
|
return comp is { Count: > 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GameMain_Begin_Postfix()
|
private static void OnGameBegin()
|
||||||
{
|
{
|
||||||
InitNodeForAbsorb();
|
InitNodeForAbsorb();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GameMain_End_Postfix()
|
private static void OnGameEnd()
|
||||||
{
|
{
|
||||||
_initialized = false;
|
_initialized = false;
|
||||||
_nodeForAbsorb = null;
|
_nodeForAbsorb = null;
|
||||||
@@ -413,7 +414,7 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
);
|
);
|
||||||
if (jmpTarget == null) return matcher.InstructionEnumeration();
|
if (jmpTarget == null) return matcher.InstructionEnumeration();
|
||||||
var labels = matcher.Labels;
|
var labels = matcher.Labels;
|
||||||
matcher.Labels = null;
|
matcher.Labels = [];
|
||||||
matcher.Insert(
|
matcher.Insert(
|
||||||
new CodeInstruction(OpCodes.Ldarg_0).WithLabels(labels),
|
new CodeInstruction(OpCodes.Ldarg_0).WithLabels(labels),
|
||||||
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.runtimeOrbitId))),
|
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(EjectorComponent), nameof(EjectorComponent.runtimeOrbitId))),
|
||||||
@@ -491,13 +492,13 @@ public class DysonSpherePatch: PatchImpl<DysonSpherePatch>
|
|||||||
}
|
}
|
||||||
|
|
||||||
[PatchSetCallbackFlag(PatchCallbackFlag.CallOnDisableAfterUnpatch)]
|
[PatchSetCallbackFlag(PatchCallbackFlag.CallOnDisableAfterUnpatch)]
|
||||||
private class OnlyConstructNodes: PatchImpl<OnlyConstructNodes>
|
private class OnlyConstructNodes : PatchImpl<OnlyConstructNodes>
|
||||||
{
|
{
|
||||||
protected override void OnEnable()
|
protected override void OnEnable()
|
||||||
{
|
{
|
||||||
RecheckDysonSphereAutoNodes();
|
RecheckDysonSphereAutoNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisable()
|
protected override void OnDisable()
|
||||||
{
|
{
|
||||||
RecheckDysonSphereAutoNodes();
|
RecheckDysonSphereAutoNodes();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using BepInEx;
|
||||||
using BepInEx.Configuration;
|
using BepInEx.Configuration;
|
||||||
using CommonAPI.Systems;
|
using CommonAPI.Systems;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
@@ -17,8 +19,6 @@ public class GamePatch : PatchImpl<GamePatch>
|
|||||||
public static ConfigEntry<bool> EnableWindowResizeEnabled;
|
public static ConfigEntry<bool> EnableWindowResizeEnabled;
|
||||||
public static ConfigEntry<bool> LoadLastWindowRectEnabled;
|
public static ConfigEntry<bool> LoadLastWindowRectEnabled;
|
||||||
|
|
||||||
public static ConfigEntry<int> MouseCursorScaleUpMultiplier;
|
|
||||||
|
|
||||||
// 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;
|
||||||
@@ -58,31 +58,32 @@ public class GamePatch : PatchImpl<GamePatch>
|
|||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
_speedDownKey = KeyBindings.RegisterKeyBinding(new BuiltinKey
|
_speedDownKey = KeyBindings.RegisterKeyBinding(new BuiltinKey
|
||||||
{
|
{
|
||||||
key = new CombineKey((int)KeyCode.Minus, CombineKey.CTRL_COMB, ECombineKeyAction.OnceClick, false),
|
key = new CombineKey((int)KeyCode.Minus, CombineKey.CTRL_COMB, ECombineKeyAction.OnceClick, false),
|
||||||
conflictGroup = KeyBindConflict.MOVEMENT | KeyBindConflict.FLYING | KeyBindConflict.SAILING | KeyBindConflict.BUILD_MODE_1 | KeyBindConflict.KEYBOARD_KEYBIND,
|
conflictGroup = KeyBindConflict.MOVEMENT | KeyBindConflict.FLYING | KeyBindConflict.SAILING | KeyBindConflict.BUILD_MODE_1 | KeyBindConflict.KEYBOARD_KEYBIND,
|
||||||
name = "UPSSpeedDown",
|
name = "UPSSpeedDown",
|
||||||
canOverride = true
|
canOverride = true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
I18N.Add("KEYUPSSpeedDown", "[UXA] Decrease logical frame rate", "[UXA] 降低逻辑帧率");
|
I18N.Add("KEYUPSSpeedDown", "[UXA] Decrease logical frame rate", "[UXA] 降低逻辑帧率");
|
||||||
_speedUpKey = KeyBindings.RegisterKeyBinding(new BuiltinKey
|
_speedUpKey = KeyBindings.RegisterKeyBinding(new BuiltinKey
|
||||||
{
|
{
|
||||||
key = new CombineKey((int)KeyCode.Equals, CombineKey.CTRL_COMB, ECombineKeyAction.OnceClick, false),
|
key = new CombineKey((int)KeyCode.Equals, CombineKey.CTRL_COMB, ECombineKeyAction.OnceClick, false),
|
||||||
conflictGroup = KeyBindConflict.MOVEMENT | KeyBindConflict.UI | KeyBindConflict.FLYING | KeyBindConflict.SAILING | KeyBindConflict.BUILD_MODE_1 | KeyBindConflict.KEYBOARD_KEYBIND,
|
conflictGroup = KeyBindConflict.MOVEMENT | KeyBindConflict.UI | KeyBindConflict.FLYING | KeyBindConflict.SAILING | KeyBindConflict.BUILD_MODE_1 | KeyBindConflict.KEYBOARD_KEYBIND,
|
||||||
name = "UPSSpeedUp",
|
name = "UPSSpeedUp",
|
||||||
canOverride = true
|
canOverride = true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
I18N.Add("KEYUPSSpeedUp", "[UXA] Increase logical frame rate", "[UXA] 提升逻辑帧率");
|
I18N.Add("KEYUPSSpeedUp", "[UXA] Increase logical frame rate", "[UXA] 提升逻辑帧率");
|
||||||
I18N.Add("Logical frame rate: {0}x", "[UXA] Logical frame rate: {0}x", "[UXA] 逻辑帧速率: {0}x");
|
I18N.Add("Logical frame rate: {0}x", "[UXA] Logical frame rate: {0}x", "[UXA] 逻辑帧速率: {0}x");
|
||||||
|
|
||||||
EnableWindowResizeEnabled.SettingChanged += (_, _) => EnableWindowResize.Enable(EnableWindowResizeEnabled.Value);
|
EnableWindowResizeEnabled.SettingChanged += (_, _) => EnableWindowResize.Enable(EnableWindowResizeEnabled.Value);
|
||||||
LoadLastWindowRectEnabled.SettingChanged += (_, _) => LoadLastWindowRect.Enable(LoadLastWindowRectEnabled.Value);
|
LoadLastWindowRectEnabled.SettingChanged += (_, _) =>
|
||||||
MouseCursorScaleUpMultiplier.SettingChanged += (_, _) =>
|
|
||||||
{
|
{
|
||||||
MouseCursorScaleUp.NeedReloadCursors = true;
|
if (LoadLastWindowRectEnabled.Value)
|
||||||
MouseCursorScaleUp.Enable(MouseCursorScaleUpMultiplier.Value > 1);
|
{
|
||||||
|
FixLastWindowRect();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// AutoSaveOptEnabled.SettingChanged += (_, _) => AutoSaveOpt.Enable(AutoSaveOptEnabled.Value);
|
// AutoSaveOptEnabled.SettingChanged += (_, _) => AutoSaveOpt.Enable(AutoSaveOptEnabled.Value);
|
||||||
ConvertSavesFromPeaceEnabled.SettingChanged += (_, _) => ConvertSavesFromPeace.Enable(ConvertSavesFromPeaceEnabled.Value);
|
ConvertSavesFromPeaceEnabled.SettingChanged += (_, _) => ConvertSavesFromPeace.Enable(ConvertSavesFromPeaceEnabled.Value);
|
||||||
@@ -105,28 +106,32 @@ public class GamePatch : PatchImpl<GamePatch>
|
|||||||
|
|
||||||
public static void Start()
|
public static void Start()
|
||||||
{
|
{
|
||||||
RefreshSavePath();
|
if (LoadLastWindowRectEnabled.Value)
|
||||||
|
{
|
||||||
|
FixLastWindowRect();
|
||||||
|
var wnd = WindowFunctions.FindGameWindow();
|
||||||
|
if (wnd != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
ThreadingHelper.Instance.StartCoroutine(SetWindowPositionCoroutine(wnd, (int)LastWindowRect.Value.x, (int)LastWindowRect.Value.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
EnableWindowResize.Enable(EnableWindowResizeEnabled.Value);
|
EnableWindowResize.Enable(EnableWindowResizeEnabled.Value);
|
||||||
LoadLastWindowRect.Enable(LoadLastWindowRectEnabled.Value);
|
|
||||||
MouseCursorScaleUp.NeedReloadCursors = false;
|
|
||||||
MouseCursorScaleUp.Enable(MouseCursorScaleUpMultiplier.Value > 1);
|
|
||||||
// AutoSaveOpt.Enable(AutoSaveOptEnabled.Value);
|
// AutoSaveOpt.Enable(AutoSaveOptEnabled.Value);
|
||||||
ConvertSavesFromPeace.Enable(ConvertSavesFromPeaceEnabled.Value);
|
ConvertSavesFromPeace.Enable(ConvertSavesFromPeaceEnabled.Value);
|
||||||
Enable(true);
|
Enable(true);
|
||||||
|
|
||||||
|
RefreshSavePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Uninit()
|
public static void Uninit()
|
||||||
{
|
{
|
||||||
Enable(false);
|
Enable(false);
|
||||||
LoadLastWindowRect.Enable(false);
|
|
||||||
EnableWindowResize.Enable(false);
|
EnableWindowResize.Enable(false);
|
||||||
MouseCursorScaleUp.NeedReloadCursors = false;
|
|
||||||
MouseCursorScaleUp.Enable(false);
|
|
||||||
// AutoSaveOpt.Enable(false);
|
// AutoSaveOpt.Enable(false);
|
||||||
ConvertSavesFromPeace.Enable(false);
|
ConvertSavesFromPeace.Enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void OnUpdate()
|
public static void OnInputUpdate()
|
||||||
{
|
{
|
||||||
if (!_enableGameUpsFactor) return;
|
if (!_enableGameUpsFactor) return;
|
||||||
if (_speedDownKey.keyValue)
|
if (_speedDownKey.keyValue)
|
||||||
@@ -142,48 +147,129 @@ public class GamePatch : PatchImpl<GamePatch>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPriority(Priority.First)]
|
||||||
|
[HarmonyPatch(typeof(GameConfig), nameof(GameConfig.gameSaveFolder), MethodType.Getter)]
|
||||||
|
public static void GameConfig_gameSaveFolder_Postfix(ref string __result)
|
||||||
|
{
|
||||||
|
if (!ProfileBasedSaveFolderEnabled.Value || string.IsNullOrEmpty(WindowFunctions.ProfileName)) return;
|
||||||
|
__result = $"{__result}{WindowFunctions.ProfileName}/";
|
||||||
|
}
|
||||||
|
|
||||||
private static void RefreshSavePath()
|
private static void RefreshSavePath()
|
||||||
{
|
{
|
||||||
var profileName = WindowFunctions.ProfileName;
|
var gameSaveFolder = GameConfig.gameSaveFolder;
|
||||||
if (profileName == null)
|
if (!Directory.Exists(gameSaveFolder))
|
||||||
{
|
Directory.CreateDirectory(gameSaveFolder);
|
||||||
// We should initialize WindowFunctions before using WindowFunctions.ProfileName
|
if (UIRoot.instance?.loadGameWindow?.active == true) UIRoot.instance.loadGameWindow.RefreshList();
|
||||||
WindowFunctions.Init();
|
if (UIRoot.instance?.saveGameWindow?.active == true) UIRoot.instance.saveGameWindow.RefreshList();
|
||||||
profileName = WindowFunctions.ProfileName;
|
|
||||||
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.gameDocumentFolder}Save/{profileName}/";
|
|
||||||
else
|
|
||||||
gameSavePath = $"{GameConfig.gameDocumentFolder}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()
|
||||||
{
|
{
|
||||||
|
if (!LoadLastWindowRectEnabled.Value) return;
|
||||||
var wnd = WindowFunctions.FindGameWindow();
|
var wnd = WindowFunctions.FindGameWindow();
|
||||||
if (wnd == IntPtr.Zero) return;
|
if (wnd == IntPtr.Zero) return;
|
||||||
WinApi.GetWindowRect(wnd, out var rect);
|
WinApi.GetWindowRect(wnd, out var rect);
|
||||||
LastWindowRect.Value = new Vector4(rect.Left, rect.Top, Screen.width, Screen.height);
|
LastWindowRect.Value = new Vector4(rect.Left, rect.Top, Screen.width, Screen.height);
|
||||||
}
|
}
|
||||||
|
private static void FixLastWindowRect()
|
||||||
|
{
|
||||||
|
if (Screen.fullScreenMode is not (FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow))
|
||||||
|
{
|
||||||
|
var rect = LastWindowRect.Value;
|
||||||
|
var x = Mathf.RoundToInt(rect.x);
|
||||||
|
var y = Mathf.RoundToInt(rect.y);
|
||||||
|
var w = Mathf.RoundToInt(rect.z);
|
||||||
|
var h = Mathf.RoundToInt(rect.w);
|
||||||
|
var needFix = false;
|
||||||
|
if (w < 100)
|
||||||
|
{
|
||||||
|
w = 1280;
|
||||||
|
needFix = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h < 100)
|
||||||
|
{
|
||||||
|
h = 720;
|
||||||
|
needFix = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rc = new WinApi.Rect { Left = x, Top = y, Right = x + w, Bottom = y + h };
|
||||||
|
if (WinApi.MonitorFromRect(ref rc, 0) == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
w = 1280;
|
||||||
|
h = 720;
|
||||||
|
needFix = true;
|
||||||
|
}
|
||||||
|
if (needFix)
|
||||||
|
{
|
||||||
|
LastWindowRect.Value = new Vector4(x, y, w, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerator SetWindowPositionCoroutine(IntPtr wnd, int x, int y)
|
||||||
|
{
|
||||||
|
yield return new WaitForEndOfFrame();
|
||||||
|
yield return new WaitForEndOfFrame();
|
||||||
|
WinApi.SetWindowPos(wnd, IntPtr.Zero, x, y, 0, 0, 0x0235);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(Screen), nameof(Screen.SetResolution), typeof(int), typeof(int), typeof(FullScreenMode), typeof(RefreshRate))]
|
||||||
|
private static void Screen_SetResolution_Prefix(ref int width, ref int height, FullScreenMode fullscreenMode, ref Vector2Int __state)
|
||||||
|
{
|
||||||
|
if (fullscreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow) return;
|
||||||
|
if (GameMain.isRunning)
|
||||||
|
{
|
||||||
|
var wnd = WindowFunctions.FindGameWindow();
|
||||||
|
if (wnd == IntPtr.Zero) return;
|
||||||
|
WinApi.GetWindowRect(wnd, out var rc);
|
||||||
|
__state = new Vector2Int(rc.Left, rc.Top);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!LoadLastWindowRectEnabled.Value) return;
|
||||||
|
int x = 0, y = 0, w = 0, h = 0;
|
||||||
|
var rect = LastWindowRect.Value;
|
||||||
|
if (rect is not { z: 0f, w: 0f })
|
||||||
|
{
|
||||||
|
x = Mathf.RoundToInt(rect.x);
|
||||||
|
y = Mathf.RoundToInt(rect.y);
|
||||||
|
w = Mathf.RoundToInt(rect.z);
|
||||||
|
h = Mathf.RoundToInt(rect.w);
|
||||||
|
}
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(Screen), nameof(Screen.SetResolution), typeof(int), typeof(int), typeof(FullScreenMode), typeof(RefreshRate))]
|
||||||
|
private static void Screen_SetResolution_Postfix(FullScreenMode fullscreenMode, Vector2Int __state)
|
||||||
|
{
|
||||||
|
if (fullscreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow) return;
|
||||||
|
var gameRunning = GameMain.isRunning;
|
||||||
|
if (!LoadLastWindowRectEnabled.Value && !gameRunning) return;
|
||||||
|
var wnd = WindowFunctions.FindGameWindow();
|
||||||
|
if (wnd == IntPtr.Zero) return;
|
||||||
|
int x, y;
|
||||||
|
if (gameRunning)
|
||||||
|
{
|
||||||
|
x = __state.x;
|
||||||
|
y = __state.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var rect = LastWindowRect.Value;
|
||||||
|
if (rect is { z: 0f, w: 0f }) return;
|
||||||
|
x = Mathf.RoundToInt(rect.x);
|
||||||
|
y = Mathf.RoundToInt(rect.y);
|
||||||
|
}
|
||||||
|
ThreadingHelper.Instance.StartCoroutine(SetWindowPositionCoroutine(wnd, x, y));
|
||||||
|
}
|
||||||
|
|
||||||
private class EnableWindowResize : PatchImpl<EnableWindowResize>
|
private class EnableWindowResize : PatchImpl<EnableWindowResize>
|
||||||
{
|
{
|
||||||
@@ -229,145 +315,6 @@ public class GamePatch : PatchImpl<GamePatch>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LoadLastWindowRect : PatchImpl<LoadLastWindowRect>
|
|
||||||
{
|
|
||||||
private static bool _loaded;
|
|
||||||
|
|
||||||
protected override void OnEnable()
|
|
||||||
{
|
|
||||||
GameLogic.OnDataLoaded += VFPreload_InvokeOnLoadWorkEnded_Postfix;
|
|
||||||
if (Screen.fullScreenMode is not (FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow))
|
|
||||||
{
|
|
||||||
var rect = LastWindowRect.Value;
|
|
||||||
var x = Mathf.RoundToInt(rect.x);
|
|
||||||
var y = Mathf.RoundToInt(rect.y);
|
|
||||||
var w = Mathf.RoundToInt(rect.z);
|
|
||||||
var h = Mathf.RoundToInt(rect.w);
|
|
||||||
var needFix = false;
|
|
||||||
if (w < 100)
|
|
||||||
{
|
|
||||||
w = 1280;
|
|
||||||
needFix = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h < 100)
|
|
||||||
{
|
|
||||||
h = 720;
|
|
||||||
needFix = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var rc = new WinApi.Rect {Left = x, Top = y, Right = x + w, Bottom = y + h};
|
|
||||||
if (WinApi.MonitorFromRect(ref rc, 0) == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y = 0;
|
|
||||||
w = 1280;
|
|
||||||
h = 720;
|
|
||||||
needFix = true;
|
|
||||||
}
|
|
||||||
if (needFix)
|
|
||||||
{
|
|
||||||
LastWindowRect.Value = new Vector4(x, y, w, h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MoveWindowPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDisable()
|
|
||||||
{
|
|
||||||
GameLogic.OnDataLoaded -= VFPreload_InvokeOnLoadWorkEnded_Postfix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void MoveWindowPosition(bool setResolution = false)
|
|
||||||
{
|
|
||||||
if (Screen.fullScreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow || GameMain.isRunning) return;
|
|
||||||
var wnd = WindowFunctions.FindGameWindow();
|
|
||||||
if (wnd == IntPtr.Zero) return;
|
|
||||||
var rect = LastWindowRect.Value;
|
|
||||||
if (rect is { z: 0f, w: 0f }) return;
|
|
||||||
var x = Mathf.RoundToInt(rect.x);
|
|
||||||
var y = Mathf.RoundToInt(rect.y);
|
|
||||||
if (setResolution)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
[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)
|
|
||||||
{
|
|
||||||
if (fullscreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow || GameMain.isRunning) return;
|
|
||||||
var rect = LastWindowRect.Value;
|
|
||||||
if (rect is { z: 0f, w: 0f }) return;
|
|
||||||
var w = Mathf.RoundToInt(rect.z);
|
|
||||||
var h = Mathf.RoundToInt(rect.w);
|
|
||||||
width = w;
|
|
||||||
height = h;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPostfix]
|
|
||||||
[HarmonyPatch(typeof(Screen), nameof(Screen.SetResolution), typeof(int), typeof(int), typeof(FullScreenMode), typeof(int))]
|
|
||||||
private static void Screen_SetResolution_Postfix(FullScreenMode fullscreenMode)
|
|
||||||
{
|
|
||||||
MoveWindowPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void VFPreload_InvokeOnLoadWorkEnded_Postfix()
|
|
||||||
{
|
|
||||||
if (_loaded || Screen.fullScreenMode is FullScreenMode.ExclusiveFullScreen or FullScreenMode.FullScreenWindow or FullScreenMode.MaximizedWindow) return;
|
|
||||||
_loaded = true;
|
|
||||||
var wnd = WindowFunctions.FindGameWindow();
|
|
||||||
if (wnd == IntPtr.Zero) return;
|
|
||||||
var rect = LastWindowRect.Value;
|
|
||||||
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);
|
|
||||||
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, WinApi.GWL_STYLE,
|
|
||||||
WinApi.GetWindowLong(wnd, WinApi.GWL_STYLE) | WinApi.WS_THICKFRAME | WinApi.WS_MAXIMIZEBOX);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static GameOption _gameOption;
|
|
||||||
|
|
||||||
[HarmonyPostfix]
|
|
||||||
[HarmonyPatch(typeof(UIOptionWindow), nameof(UIOptionWindow._OnOpen))]
|
|
||||||
private static void UIOptionWindow__OnOpen_Postfix()
|
|
||||||
{
|
|
||||||
_gameOption = DSPGame.globalOption;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
|
||||||
[HarmonyPatch(typeof(GameOption), nameof(GameOption.Apply))]
|
|
||||||
private static IEnumerable<CodeInstruction> UIOptionWindow_ApplyOptions_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
||||||
{
|
|
||||||
var matcher = new CodeMatcher(instructions, generator);
|
|
||||||
var label1 = generator.DefineLabel();
|
|
||||||
matcher.MatchForward(false,
|
|
||||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(Screen), nameof(Screen.SetResolution), [typeof(int), typeof(int), typeof(bool), typeof(int)]))
|
|
||||||
).Advance(1).Labels.Add(label1);
|
|
||||||
matcher.Start().Insert(
|
|
||||||
Transpilers.EmitDelegate(() =>
|
|
||||||
_gameOption.fullscreen == DSPGame.globalOption.fullscreen &&
|
|
||||||
_gameOption.resolution.width == DSPGame.globalOption.resolution.width &&
|
|
||||||
_gameOption.resolution.height == DSPGame.globalOption.resolution.height &&
|
|
||||||
_gameOption.resolution.refreshRate == DSPGame.globalOption.resolution.refreshRate
|
|
||||||
),
|
|
||||||
new CodeInstruction(OpCodes.Brtrue, label1)
|
|
||||||
);
|
|
||||||
return matcher.InstructionEnumeration();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
private class AutoSaveOpt: PatchImpl<AutoSaveOpt>
|
private class AutoSaveOpt: PatchImpl<AutoSaveOpt>
|
||||||
{
|
{
|
||||||
@@ -517,6 +464,16 @@ public class GamePatch : PatchImpl<GamePatch>
|
|||||||
_needConvert = true;
|
_needConvert = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(GameHistoryData), nameof(GameHistoryData.Import))]
|
||||||
|
private static void GameHistoryData_Import_Postfix(GameHistoryData __instance)
|
||||||
|
{
|
||||||
|
if (_needConvert)
|
||||||
|
{
|
||||||
|
__instance.combatSettings = UIRoot.instance.galaxySelect.uiCombat.combatSettings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(GameData), nameof(GameData.Import))]
|
[HarmonyPatch(typeof(GameData), nameof(GameData.Import))]
|
||||||
private static IEnumerable<CodeInstruction> GameData_Import_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
private static IEnumerable<CodeInstruction> GameData_Import_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
@@ -547,7 +504,6 @@ public class GamePatch : PatchImpl<GamePatch>
|
|||||||
[HarmonyPatch(typeof(GameOption), nameof(GameOption.LoadGlobal))]
|
[HarmonyPatch(typeof(GameOption), nameof(GameOption.LoadGlobal))]
|
||||||
private static bool GameOption_LoadGlobal_Prefix(ref GameOption __instance)
|
private static bool GameOption_LoadGlobal_Prefix(ref GameOption __instance)
|
||||||
{
|
{
|
||||||
UXAssist.Logger.LogDebug("Loading global option");
|
|
||||||
var profileName = WindowFunctions.ProfileName;
|
var profileName = WindowFunctions.ProfileName;
|
||||||
if (profileName == null)
|
if (profileName == null)
|
||||||
{
|
{
|
||||||
@@ -565,8 +521,9 @@ public class GamePatch : PatchImpl<GamePatch>
|
|||||||
__instance.ImportXML(optionPath);
|
__instance.ImportXML(optionPath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
Debug.LogException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var gameXMLOptionPath = GameConfig.gameXMLOptionPath;
|
var gameXMLOptionPath = GameConfig.gameXMLOptionPath;
|
||||||
@@ -614,131 +571,4 @@ public class GamePatch : PatchImpl<GamePatch>
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[PatchSetCallbackFlag(PatchCallbackFlag.CallOnDisableAfterUnpatch)]
|
|
||||||
private class MouseCursorScaleUp : PatchImpl<MouseCursorScaleUp>
|
|
||||||
{
|
|
||||||
public static bool NeedReloadCursors;
|
|
||||||
|
|
||||||
protected override void OnEnable()
|
|
||||||
{
|
|
||||||
if (!NeedReloadCursors) return;
|
|
||||||
if (!UICursor.loaded) return;
|
|
||||||
UICursor.loaded = false;
|
|
||||||
UICursor.LoadCursors();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDisable()
|
|
||||||
{
|
|
||||||
if (!NeedReloadCursors) return;
|
|
||||||
if (!UICursor.loaded) return;
|
|
||||||
UICursor.loaded = false;
|
|
||||||
UICursor.LoadCursors();
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
|
||||||
[HarmonyPatch(typeof(UICursor), nameof(UICursor.LoadCursors))]
|
|
||||||
private static IEnumerable<CodeInstruction> UICursor_LoadCursors_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
||||||
{
|
|
||||||
var matcher = new CodeMatcher(instructions, generator);
|
|
||||||
/*
|
|
||||||
matcher.MatchForward(false,
|
|
||||||
new CodeMatch(OpCodes.Ldc_I4_S),
|
|
||||||
new CodeMatch(OpCodes.Newarr)
|
|
||||||
);
|
|
||||||
var startPos = matcher.Pos;
|
|
||||||
matcher.Advance(2).MatchForward(false,
|
|
||||||
new CodeMatch(OpCodes.Stsfld, AccessTools.Field(typeof(UICursor), nameof(UICursor.cursorTexs)))
|
|
||||||
);
|
|
||||||
var endPos = matcher.Pos + 1;
|
|
||||||
matcher.Start().Advance(startPos).RemoveInstructions(endPos - startPos);
|
|
||||||
matcher.InsertAndAdvance(
|
|
||||||
Transpilers.EmitDelegate(() =>
|
|
||||||
{
|
|
||||||
var pluginfolder = Util.PluginFolder;
|
|
||||||
UICursor.cursorTexs =
|
|
||||||
[
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-transfer.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-target-in.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-target-out.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-target-a.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-target-b.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-ban.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-delete.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-reform.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-dyson-node-create.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-painter.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-eyedropper.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-eraser.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-upgrade.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-downgrade.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-blank.png"),
|
|
||||||
Util.LoadTexture($"{pluginfolder}/assets/cursor/cursor-remove.png")
|
|
||||||
];
|
|
||||||
})
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
matcher.MatchForward(false,
|
|
||||||
new CodeMatch(OpCodes.Stsfld, AccessTools.Field(typeof(UICursor), nameof(UICursor.cursorHots))),
|
|
||||||
new CodeMatch(OpCodes.Ldc_I4_1),
|
|
||||||
new CodeMatch(OpCodes.Stsfld, AccessTools.Field(typeof(UICursor), nameof(UICursor.loaded)))
|
|
||||||
).Advance(1).InsertAndAdvance(
|
|
||||||
Transpilers.EmitDelegate(() =>
|
|
||||||
{
|
|
||||||
var multiplier = MouseCursorScaleUpMultiplier.Value;
|
|
||||||
for (var i = 0; i < UICursor.cursorTexs.Length; i++)
|
|
||||||
{
|
|
||||||
var cursor = UICursor.cursorTexs[i];
|
|
||||||
if (cursor == null) continue;
|
|
||||||
var newWidth = 32 * multiplier;
|
|
||||||
var newHeight = 32 * multiplier;
|
|
||||||
if (cursor.width == newWidth && cursor.height == newHeight) continue;
|
|
||||||
UICursor.cursorTexs[i] = ResizeTexture2D(cursor, newWidth, newHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (multiplier <= 1) return;
|
|
||||||
for (var i = UICursor.cursorHots.Length - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
UICursor.cursorHots[i] = new Vector2(UICursor.cursorHots[i].x * multiplier, UICursor.cursorHots[i].y * multiplier);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
).MatchForward(false,
|
|
||||||
new CodeMatch(OpCodes.Ldc_I4_0),
|
|
||||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(Cursor), nameof(Cursor.SetCursor), [typeof(Texture2D), typeof(Vector2), typeof(CursorMode)]))
|
|
||||||
).SetInstruction(new CodeInstruction(OpCodes.Ldc_I4_1));
|
|
||||||
return matcher.InstructionEnumeration();
|
|
||||||
|
|
||||||
Texture2D ResizeTexture2D(Texture2D texture2D, int targetWidth, int targetHeight)
|
|
||||||
{
|
|
||||||
var oldActive = RenderTexture.active;
|
|
||||||
var rt = new RenderTexture(targetWidth, targetHeight, 32)
|
|
||||||
{
|
|
||||||
antiAliasing = 8
|
|
||||||
};
|
|
||||||
RenderTexture.active = rt;
|
|
||||||
Graphics.Blit(texture2D, rt);
|
|
||||||
rt.ResolveAntiAliasedSurface();
|
|
||||||
var result = new Texture2D(targetWidth, targetHeight, texture2D.format, false);
|
|
||||||
result.ReadPixels(new Rect(0, 0, targetWidth, targetHeight), 0, 0);
|
|
||||||
result.filterMode = FilterMode.Trilinear;
|
|
||||||
result.Apply();
|
|
||||||
RenderTexture.active = oldActive;
|
|
||||||
rt.Release();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
|
||||||
[HarmonyPatch(typeof(UICursor), nameof(UICursor.cursorIndexApply), MethodType.Setter)]
|
|
||||||
private static IEnumerable<CodeInstruction> UICursor_set_cursorIndexApply_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
||||||
{
|
|
||||||
var matcher = new CodeMatcher(instructions, generator);
|
|
||||||
matcher.Start().MatchForward(false,
|
|
||||||
new CodeMatch(OpCodes.Ldc_I4_0),
|
|
||||||
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(Cursor), nameof(Cursor.SetCursor), [typeof(Texture2D), typeof(Vector2), typeof(CursorMode)]))
|
|
||||||
).SetInstruction(new CodeInstruction(OpCodes.Ldc_I4_1));
|
|
||||||
return matcher.InstructionEnumeration();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,9 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
using System.IO;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Networking;
|
||||||
using UXAssist.Common;
|
using UXAssist.Common;
|
||||||
|
|
||||||
namespace UXAssist.Patches;
|
namespace UXAssist.Patches;
|
||||||
@@ -39,29 +40,6 @@ public class PersistPatch : PatchImpl<PersistPatch>
|
|||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Patch to fix the issue that warning popup on VeinUtil upgraded to level 8000+
|
|
||||||
[HarmonyTranspiler]
|
|
||||||
[HarmonyPatch(typeof(ABN_VeinsUtil), nameof(ABN_VeinsUtil.CheckValue))]
|
|
||||||
private static IEnumerable<CodeInstruction> ABN_VeinsUtil_CheckValue_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
||||||
{
|
|
||||||
var matcher = new CodeMatcher(instructions, generator);
|
|
||||||
matcher.MatchForward(false,
|
|
||||||
new CodeMatch(OpCodes.Ldelem_R8),
|
|
||||||
new CodeMatch(OpCodes.Conv_R4),
|
|
||||||
new CodeMatch(OpCodes.Add),
|
|
||||||
new CodeMatch(OpCodes.Stloc_1)
|
|
||||||
);
|
|
||||||
// loc1 = Mathf.Round(n * 1000f) / 1000f;
|
|
||||||
matcher.Advance(3).Insert(
|
|
||||||
new CodeInstruction(OpCodes.Ldc_R4, 1000f),
|
|
||||||
new CodeInstruction(OpCodes.Mul),
|
|
||||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Mathf), nameof(Mathf.Round))),
|
|
||||||
new CodeInstruction(OpCodes.Ldc_R4, 1000f),
|
|
||||||
new CodeInstruction(OpCodes.Div)
|
|
||||||
);
|
|
||||||
return matcher.InstructionEnumeration();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bring popup tip window to top layer
|
// Bring popup tip window to top layer
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(UIButton), nameof(UIButton.LateUpdate))]
|
[HarmonyPatch(typeof(UIButton), nameof(UIButton.LateUpdate))]
|
||||||
@@ -75,7 +53,7 @@ public class PersistPatch : PatchImpl<PersistPatch>
|
|||||||
);
|
);
|
||||||
var ldLocOpr = matcher.Operand;
|
var ldLocOpr = matcher.Operand;
|
||||||
var labels = matcher.Labels;
|
var labels = matcher.Labels;
|
||||||
matcher.Labels = null;
|
matcher.Labels = [];
|
||||||
matcher.Insert(
|
matcher.Insert(
|
||||||
new CodeInstruction(OpCodes.Ldloc_S, ldLocOpr).WithLabels(labels),
|
new CodeInstruction(OpCodes.Ldloc_S, ldLocOpr).WithLabels(labels),
|
||||||
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Component), nameof(Component.transform))),
|
new CodeInstruction(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Component), nameof(Component.transform))),
|
||||||
@@ -86,36 +64,30 @@ public class PersistPatch : PatchImpl<PersistPatch>
|
|||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort blueprint structures by item id, model index, recipe id, area index, and position before saving
|
// Sort blueprint data when pasting
|
||||||
[HarmonyPostfix]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(BlueprintUtils), nameof(BlueprintUtils.GenerateBlueprintData))]
|
[HarmonyPatch(typeof(BuildTool_BlueprintCopy), nameof(BuildTool_BlueprintCopy.UseToPasteNow))]
|
||||||
private static void BlueprintUtils_GenerateBlueprintData_Postfix(BlueprintData _blueprintData)
|
private static IEnumerable<CodeInstruction> BuildTool_BlueprintCopy_UseToPasteNow_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
{
|
{
|
||||||
var buildings = _blueprintData.buildings;
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
Array.Sort(buildings, (a, b) =>
|
matcher.MatchForward(false,
|
||||||
{
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
var tmpItemId = a.itemId - b.itemId;
|
new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(BuildTool_BlueprintCopy), nameof(BuildTool_BlueprintCopy.RefreshBlueprintData)))
|
||||||
if (tmpItemId != 0) return tmpItemId;
|
).Advance(2).Insert(
|
||||||
|
new CodeInstruction(OpCodes.Ldarg_0),
|
||||||
|
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(BuildTool_BlueprintCopy), nameof(BuildTool_BlueprintCopy.blueprint))),
|
||||||
|
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(Functions.FactoryFunctions), nameof(Functions.FactoryFunctions.SortBlueprintData)))
|
||||||
|
);
|
||||||
|
return matcher.InstructionEnumeration();
|
||||||
|
}
|
||||||
|
|
||||||
var tmpModelIndex = a.modelIndex - b.modelIndex;
|
// Sort blueprint data when saving
|
||||||
if (tmpModelIndex != 0) return tmpModelIndex;
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(BlueprintData), nameof(BlueprintData.SaveBlueprintData))]
|
||||||
var tmpRecipeId = a.recipeId - b.recipeId;
|
private static void BlueprintData_SaveBlueprintData_Prefix(BlueprintData __instance)
|
||||||
if (tmpRecipeId != 0) return tmpRecipeId;
|
{
|
||||||
|
if (!__instance.isValid) return;
|
||||||
var tmpAreaIndex = a.areaIndex - b.areaIndex;
|
Functions.FactoryFunctions.SortBlueprintData(__instance);
|
||||||
if (tmpAreaIndex != 0) return tmpAreaIndex;
|
|
||||||
|
|
||||||
var sign = Math.Sign(b.localOffset_y - a.localOffset_y);
|
|
||||||
if (sign != 0) return sign;
|
|
||||||
|
|
||||||
sign = Math.Sign(b.localOffset_x - a.localOffset_x);
|
|
||||||
return sign != 0 ? sign : Math.Sign(b.localOffset_z - a.localOffset_z);
|
|
||||||
});
|
|
||||||
for (var i = buildings.Length - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
buildings[i].index = i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increase maximum value of property realizing, 2000 -> 20000
|
// Increase maximum value of property realizing, 2000 -> 20000
|
||||||
@@ -199,4 +171,194 @@ public class PersistPatch : PatchImpl<PersistPatch>
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix crash in NeutronStarHandler.OnEnable()
|
||||||
|
[HarmonyTranspiler]
|
||||||
|
[HarmonyPatch(typeof(NeutronStarHandler), nameof(NeutronStarHandler.OnEnable))]
|
||||||
|
private static IEnumerable<CodeInstruction> NeutronStarHandler_OnEnable_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
{
|
||||||
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(NeutronStarHandler), nameof(NeutronStarHandler.streamRenderer))),
|
||||||
|
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Renderer), nameof(Renderer.sharedMaterial)))
|
||||||
|
).RemoveInstructions(3).InsertAndAdvance(
|
||||||
|
Transpilers.EmitDelegate(() =>
|
||||||
|
{
|
||||||
|
return Configs.builtin.neutronStarPrefab.streamRenderer.sharedMaterial;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return matcher.InstructionEnumeration();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable rendering when hideAllUI0 is true
|
||||||
|
[HarmonyTranspiler]
|
||||||
|
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic.LateUpdate))]
|
||||||
|
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic.Draw))]
|
||||||
|
[HarmonyPatch(typeof(GameLogic), nameof(GameLogic.DrawPost))]
|
||||||
|
private static IEnumerable<CodeInstruction> GameLogic_LateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
{
|
||||||
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
|
matcher.Start();
|
||||||
|
matcher.CreateLabel(out var label);
|
||||||
|
matcher.InsertAndAdvance(
|
||||||
|
new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(UIRoot), nameof(UIRoot.instance))),
|
||||||
|
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UIRoot), nameof(UIRoot.uiGame))),
|
||||||
|
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UIGame), nameof(UIGame.hideAllUI0))),
|
||||||
|
new CodeInstruction(OpCodes.Brfalse, label),
|
||||||
|
new CodeInstruction(OpCodes.Ret)
|
||||||
|
);
|
||||||
|
|
||||||
|
return matcher.InstructionEnumeration();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _preHideAllUI0 = false;
|
||||||
|
static bool _localPlanetChanged = false;
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(UIGame), nameof(UIGame._OnLateUpdate))]
|
||||||
|
private static void UIGame__OnLateUpdate_Prefix(UIGame __instance)
|
||||||
|
{
|
||||||
|
_preHideAllUI0 = __instance.hideAllUI0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(UIGame), nameof(UIGame._OnLateUpdate))]
|
||||||
|
private static void UIGame__OnLateUpdate_Postfix(UIGame __instance)
|
||||||
|
{
|
||||||
|
var hideAllUI0 = __instance.hideAllUI0;
|
||||||
|
if (_localPlanetChanged)
|
||||||
|
{
|
||||||
|
_localPlanetChanged = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_preHideAllUI0 == hideAllUI0) return;
|
||||||
|
}
|
||||||
|
var show = GameMain.localPlanet != null || !hideAllUI0;
|
||||||
|
GameMain.data?.mainPlayer?.effect.sailEffect.gameObject.SetActive(!hideAllUI0);
|
||||||
|
var universeSimulator = GameMain.universeSimulator;
|
||||||
|
if (universeSimulator == null) return;
|
||||||
|
universeSimulator.gameObject.SetActive(show);
|
||||||
|
var planetSimulators = universeSimulator.planetSimulators;
|
||||||
|
if (planetSimulators == null) return;
|
||||||
|
foreach (var planet in planetSimulators)
|
||||||
|
{
|
||||||
|
if (planet == null) continue;
|
||||||
|
planet.gameObject.SetActive(show);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(UniverseSimulator), nameof(UniverseSimulator.SetPlanetSimulator))]
|
||||||
|
private static void UniverseSimulator_SetPlanetSimulator_Postfix(UniverseSimulator __instance, PlanetSimulator sim)
|
||||||
|
{
|
||||||
|
if (GameMain.localPlanet == null && UIRoot.instance.uiGame.hideAllUI0) sim.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(GameData), nameof(GameData.localPlanet), MethodType.Setter)]
|
||||||
|
private static void GameData_localPlanet_Setter_Prefix(GameData __instance, PlanetData value)
|
||||||
|
{
|
||||||
|
var oldPlanet = __instance.localPlanet;
|
||||||
|
if (oldPlanet == null && value != null || oldPlanet != null && value == null) _localPlanetChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Cluster Upload Result
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(MilkyWayWebClient), nameof(MilkyWayWebClient.OnUploadLoginErrored))]
|
||||||
|
private static void MilkyWayWebClient_OnUploadLoginErrored_Postfix(MilkyWayWebClient __instance, DSPWeb.HTTP_ERROR_TYPE errorType, string errorInfo, int errorCode)
|
||||||
|
{
|
||||||
|
switch (errorType)
|
||||||
|
{
|
||||||
|
case DSPWeb.HTTP_ERROR_TYPE.NETWORK_ERROR:
|
||||||
|
Functions.UIFunctions.AddClusterUploadResult(-10001, 0f);
|
||||||
|
break;
|
||||||
|
case DSPWeb.HTTP_ERROR_TYPE.HTTP_ERROR:
|
||||||
|
Functions.UIFunctions.AddClusterUploadResult(-10010 - errorCode, 0f);
|
||||||
|
break;
|
||||||
|
case DSPWeb.HTTP_ERROR_TYPE.USER_ABORT:
|
||||||
|
Functions.UIFunctions.AddClusterUploadResult(-10003, 0f);
|
||||||
|
break;
|
||||||
|
case DSPWeb.HTTP_ERROR_TYPE.UNEXPECTED_ERROR:
|
||||||
|
Functions.UIFunctions.AddClusterUploadResult(-10004, 0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(MilkyWayWebClient), nameof(MilkyWayWebClient.OnUploadErrored))]
|
||||||
|
private static void MilkyWayWebClient_OnUploadErrored_Postfix(MilkyWayWebClient __instance, DSPWeb.HTTP_ERROR_TYPE errorType, string errorInfo, int errorCode)
|
||||||
|
{
|
||||||
|
switch (errorType)
|
||||||
|
{
|
||||||
|
case DSPWeb.HTTP_ERROR_TYPE.NETWORK_ERROR:
|
||||||
|
Functions.UIFunctions.AddClusterUploadResult(-101, 0f);
|
||||||
|
break;
|
||||||
|
case DSPWeb.HTTP_ERROR_TYPE.HTTP_ERROR:
|
||||||
|
Functions.UIFunctions.AddClusterUploadResult(-110 - errorCode, 0f);
|
||||||
|
break;
|
||||||
|
case DSPWeb.HTTP_ERROR_TYPE.USER_ABORT:
|
||||||
|
Functions.UIFunctions.AddClusterUploadResult(-103, 0f);
|
||||||
|
break;
|
||||||
|
case DSPWeb.HTTP_ERROR_TYPE.UNEXPECTED_ERROR:
|
||||||
|
Functions.UIFunctions.AddClusterUploadResult(-104, 0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(MilkyWayWebClient), nameof(MilkyWayWebClient.OnUploadSucceed))]
|
||||||
|
private static void MilkyWayWebClient_OnUploadSucceed_Postfix(MilkyWayWebClient __instance, DownloadHandler handler)
|
||||||
|
{
|
||||||
|
if (!int.TryParse(handler.text, out var rcode))
|
||||||
|
rcode = -1;
|
||||||
|
Functions.UIFunctions.AddClusterUploadResult(rcode, __instance.uploadRequest == null ? 0f : (float)__instance.uploadRequest.reqTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyTranspiler]
|
||||||
|
[HarmonyPatch(typeof(MilkyWayCache), nameof(MilkyWayCache.LoadTopTenPlayerData))]
|
||||||
|
private static IEnumerable<CodeInstruction> MilkyWayCache_LoadTopTenPlayerData_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
{
|
||||||
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
|
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_1),
|
||||||
|
new CodeMatch(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(BinaryReader), nameof(BinaryReader.ReadInt32))),
|
||||||
|
new CodeMatch(ci => ci.IsStloc())
|
||||||
|
).Advance(2).InsertAndAdvance(
|
||||||
|
new CodeInstruction(OpCodes.Dup),
|
||||||
|
Transpilers.EmitDelegate(Functions.UIFunctions.SetTopPlayerCount)
|
||||||
|
);
|
||||||
|
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldloca_S),
|
||||||
|
new CodeMatch(OpCodes.Ldarg_1),
|
||||||
|
new CodeMatch(OpCodes.Callvirt),
|
||||||
|
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(ClusterPlayerData), nameof(ClusterPlayerData.isAnon)))
|
||||||
|
);
|
||||||
|
var objloc = matcher.Operand;
|
||||||
|
matcher.Advance(4);
|
||||||
|
var iinstr = matcher.Instruction.Clone();
|
||||||
|
matcher.InsertAndAdvance(
|
||||||
|
iinstr,
|
||||||
|
new CodeInstruction(OpCodes.Ldloca_S, objloc),
|
||||||
|
Transpilers.EmitDelegate((int index, ref ClusterPlayerData playerData) =>
|
||||||
|
{
|
||||||
|
Functions.UIFunctions.SetTopPlayerData(index, ref playerData);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return matcher.InstructionEnumeration();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(MilkyWayCache), nameof(MilkyWayCache.LoadTopTenPlayerData))]
|
||||||
|
private static void MilkyWayCache_LoadTopTenPlayerData_Postfix(MilkyWayCache __instance)
|
||||||
|
{
|
||||||
|
Functions.UIFunctions.UpdateMilkyWayTopTenPlayers();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using HarmonyLib;
|
|||||||
using UXAssist.Common;
|
using UXAssist.Common;
|
||||||
|
|
||||||
namespace UXAssist.Patches;
|
namespace UXAssist.Patches;
|
||||||
|
|
||||||
public static class PlanetPatch
|
public static class PlanetPatch
|
||||||
{
|
{
|
||||||
public static ConfigEntry<bool> PlayerActionsInGlobeViewEnabled;
|
public static ConfigEntry<bool> PlayerActionsInGlobeViewEnabled;
|
||||||
@@ -24,7 +25,7 @@ public static class PlanetPatch
|
|||||||
PlayerActionsInGlobeView.Enable(false);
|
PlayerActionsInGlobeView.Enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PlayerActionsInGlobeView: PatchImpl<PlayerActionsInGlobeView>
|
public class PlayerActionsInGlobeView : PatchImpl<PlayerActionsInGlobeView>
|
||||||
{
|
{
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(VFInput), nameof(VFInput.UpdateGameStates))]
|
[HarmonyPatch(typeof(VFInput), nameof(VFInput.UpdateGameStates))]
|
||||||
@@ -48,7 +49,7 @@ public static class PlanetPatch
|
|||||||
});
|
});
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(PlayerController), nameof(PlayerController.GetInput))]
|
[HarmonyPatch(typeof(PlayerController), nameof(PlayerController.GetInput))]
|
||||||
private static IEnumerable<CodeInstruction> PlayerController_GetInput_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
private static IEnumerable<CodeInstruction> PlayerController_GetInput_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using UXAssist.Common;
|
|||||||
|
|
||||||
namespace UXAssist.Patches;
|
namespace UXAssist.Patches;
|
||||||
|
|
||||||
public static class PlayerPatch
|
public class PlayerPatch : PatchImpl<PlayerPatch>
|
||||||
{
|
{
|
||||||
public static ConfigEntry<bool> EnhancedMechaForgeCountControlEnabled;
|
public static ConfigEntry<bool> EnhancedMechaForgeCountControlEnabled;
|
||||||
public static ConfigEntry<bool> HideTipsForSandsChangesEnabled;
|
public static ConfigEntry<bool> HideTipsForSandsChangesEnabled;
|
||||||
@@ -58,6 +58,8 @@ public static class PlayerPatch
|
|||||||
HideTipsForSandsChangesEnabled.SettingChanged += (_, _) => HideTipsForSandsChanges.Enable(HideTipsForSandsChangesEnabled.Value);
|
HideTipsForSandsChangesEnabled.SettingChanged += (_, _) => HideTipsForSandsChanges.Enable(HideTipsForSandsChangesEnabled.Value);
|
||||||
ShortcutKeysForStarsNameEnabled.SettingChanged += (_, _) => ShortcutKeysForStarsName.Enable(ShortcutKeysForStarsNameEnabled.Value);
|
ShortcutKeysForStarsNameEnabled.SettingChanged += (_, _) => ShortcutKeysForStarsName.Enable(ShortcutKeysForStarsNameEnabled.Value);
|
||||||
AutoNavigationEnabled.SettingChanged += (_, _) => AutoNavigation.Enable(AutoNavigationEnabled.Value);
|
AutoNavigationEnabled.SettingChanged += (_, _) => AutoNavigation.Enable(AutoNavigationEnabled.Value);
|
||||||
|
AutoNavigationEnabled.SettingChanged += (_, _) => Functions.UIFunctions.UpdateToggleAutoCruiseCheckButtonVisiblility();
|
||||||
|
AutoCruiseEnabled.SettingChanged += (_, _) => Functions.UIFunctions.UpdateToggleAutoCruiseCheckButtonVisiblility();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Start()
|
public static void Start()
|
||||||
@@ -66,14 +68,12 @@ public static class PlayerPatch
|
|||||||
HideTipsForSandsChanges.Enable(HideTipsForSandsChangesEnabled.Value);
|
HideTipsForSandsChanges.Enable(HideTipsForSandsChangesEnabled.Value);
|
||||||
ShortcutKeysForStarsName.Enable(ShortcutKeysForStarsNameEnabled.Value);
|
ShortcutKeysForStarsName.Enable(ShortcutKeysForStarsNameEnabled.Value);
|
||||||
AutoNavigation.Enable(AutoNavigationEnabled.Value);
|
AutoNavigation.Enable(AutoNavigationEnabled.Value);
|
||||||
|
Enable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void OnUpdate()
|
public static void OnInputUpdate()
|
||||||
{
|
{
|
||||||
if (_toggleAllStarsNameKey.keyValue)
|
ShortcutKeysForStarsName.OnInputUpdate();
|
||||||
{
|
|
||||||
ShortcutKeysForStarsName.ToggleAllStarsName();
|
|
||||||
}
|
|
||||||
if (_autoDriveKey.keyValue)
|
if (_autoDriveKey.keyValue)
|
||||||
{
|
{
|
||||||
AutoNavigation.ToggleAutoCruise();
|
AutoNavigation.ToggleAutoCruise();
|
||||||
@@ -82,13 +82,57 @@ public static class PlayerPatch
|
|||||||
|
|
||||||
public static void Uninit()
|
public static void Uninit()
|
||||||
{
|
{
|
||||||
|
Enable(false);
|
||||||
EnhancedMechaForgeCountControl.Enable(false);
|
EnhancedMechaForgeCountControl.Enable(false);
|
||||||
HideTipsForSandsChanges.Enable(false);
|
HideTipsForSandsChanges.Enable(false);
|
||||||
ShortcutKeysForStarsName.Enable(false);
|
ShortcutKeysForStarsName.Enable(false);
|
||||||
AutoNavigation.Enable(false);
|
AutoNavigation.Enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class EnhancedMechaForgeCountControl: PatchImpl<EnhancedMechaForgeCountControl>
|
|
||||||
|
[HarmonyTranspiler]
|
||||||
|
[HarmonyPatch(typeof(UIStarmapStar), nameof(UIStarmapStar._OnLateUpdate))]
|
||||||
|
private static IEnumerable<CodeInstruction> UIStarmapStar__OnLateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
{
|
||||||
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
|
Label? jumpPos = null;
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(UIStarmapStar), nameof(UIStarmapStar.projectedCoord))),
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0)
|
||||||
|
).Advance(2).MatchForward(false,
|
||||||
|
new CodeMatch(ci => ci.IsStloc()),
|
||||||
|
new CodeMatch(ci => ci.IsLdloc()),
|
||||||
|
new CodeMatch(ci => ci.Branches(out jumpPos))
|
||||||
|
).Advance(3);
|
||||||
|
var labels = matcher.Labels;
|
||||||
|
matcher.Labels = [];
|
||||||
|
matcher.CreateLabel(out var jumpPos2);
|
||||||
|
matcher.InsertAndAdvance(
|
||||||
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ShortcutKeysForStarsName), nameof(ShortcutKeysForStarsName.ShowAllStarsNameStatus))).WithLabels(labels),
|
||||||
|
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||||
|
new CodeInstruction(OpCodes.Ceq),
|
||||||
|
new CodeInstruction(OpCodes.Brtrue, jumpPos.Value),
|
||||||
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PlayerPatch.ShortcutKeysForStarsName), nameof(ShortcutKeysForStarsName.ForceShowAllStarsName))),
|
||||||
|
new CodeInstruction(OpCodes.Brtrue, jumpPos.Value),
|
||||||
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(Functions.UIFunctions), nameof(Functions.UIFunctions.ShowStarName))),
|
||||||
|
new CodeInstruction(OpCodes.Ldarg_0),
|
||||||
|
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(UIStarmapStar), nameof(UIStarmapStar.star))),
|
||||||
|
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(StarData), nameof(StarData.index))),
|
||||||
|
new CodeInstruction(OpCodes.Ldelem_I1),
|
||||||
|
new CodeInstruction(OpCodes.Brtrue, jumpPos.Value),
|
||||||
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ShortcutKeysForStarsName), nameof(ShortcutKeysForStarsName.ShowAllStarsNameStatus))),
|
||||||
|
new CodeInstruction(OpCodes.Ldc_I4_2),
|
||||||
|
new CodeInstruction(OpCodes.Ceq),
|
||||||
|
new CodeInstruction(OpCodes.Brfalse, jumpPos2),
|
||||||
|
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||||
|
new CodeInstruction(OpCodes.Stloc_1),
|
||||||
|
new CodeInstruction(OpCodes.Br, jumpPos.Value)
|
||||||
|
);
|
||||||
|
return matcher.InstructionEnumeration();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class EnhancedMechaForgeCountControl : PatchImpl<EnhancedMechaForgeCountControl>
|
||||||
{
|
{
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(UIReplicatorWindow), nameof(UIReplicatorWindow.OnOkButtonClick))]
|
[HarmonyPatch(typeof(UIReplicatorWindow), nameof(UIReplicatorWindow.OnOkButtonClick))]
|
||||||
@@ -139,7 +183,7 @@ public static class PlayerPatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class HideTipsForSandsChanges: PatchImpl<HideTipsForSandsChanges>
|
private class HideTipsForSandsChanges : PatchImpl<HideTipsForSandsChanges>
|
||||||
{
|
{
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(Player), nameof(Player.SetSandCount))]
|
[HarmonyPatch(typeof(Player), nameof(Player.SetSandCount))]
|
||||||
@@ -153,162 +197,158 @@ public static class PlayerPatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ShortcutKeysForStarsName: PatchImpl<ShortcutKeysForStarsName>
|
public class ShortcutKeysForStarsName : PatchImpl<ShortcutKeysForStarsName>
|
||||||
{
|
{
|
||||||
private static int _showAllStarsNameStatus;
|
public static int ShowAllStarsNameStatus;
|
||||||
|
public static bool ForceShowAllStarsName;
|
||||||
|
public static bool ForceShowAllStarsNameExternal;
|
||||||
|
|
||||||
public static void ToggleAllStarsName()
|
public static void ToggleAllStarsName()
|
||||||
{
|
{
|
||||||
_showAllStarsNameStatus = (_showAllStarsNameStatus + 1) % 3;
|
ShowAllStarsNameStatus = (ShowAllStarsNameStatus + 1) % 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPostfix]
|
public static void OnInputUpdate()
|
||||||
[HarmonyPatch(typeof(UIStarmap), nameof(UIStarmap._OnClose))]
|
|
||||||
private static void UIStarmap__OnClose_Postfix()
|
|
||||||
{
|
{
|
||||||
_showAllStarsNameStatus = 0;
|
if (!UIRoot.instance.uiGame.starmap.active) return;
|
||||||
|
var enabled = ShortcutKeysForStarsNameEnabled.Value;
|
||||||
|
if (!enabled)
|
||||||
|
{
|
||||||
|
ForceShowAllStarsName = ForceShowAllStarsNameExternal;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_toggleAllStarsNameKey.keyValue)
|
||||||
|
{
|
||||||
|
ToggleAllStarsName();
|
||||||
|
}
|
||||||
|
ForceShowAllStarsName = ForceShowAllStarsNameExternal || _showAllStarsNameKey.IsKeyPressing();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(UIStarmapStar), nameof(UIStarmapStar._OnLateUpdate))]
|
[HarmonyPatch(typeof(UIStarmap), nameof(UIStarmap._OnOpen))]
|
||||||
private static IEnumerable<CodeInstruction> UIStarmapStar__OnLateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
private static void UIStarmap__OnOpen_Prefix()
|
||||||
{
|
{
|
||||||
var matcher = new CodeMatcher(instructions, generator);
|
ShowAllStarsNameStatus = 0;
|
||||||
Label? jumpPos = null;
|
|
||||||
matcher.MatchForward(false,
|
|
||||||
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(UIStarmapStar), nameof(UIStarmapStar.projectedCoord))),
|
|
||||||
new CodeMatch(ci => ci.IsLdloc()),
|
|
||||||
new CodeMatch(ci => ci.Branches(out jumpPos))
|
|
||||||
);
|
|
||||||
matcher.Advance(3);
|
|
||||||
var labels = matcher.Labels;
|
|
||||||
matcher.Labels = [];
|
|
||||||
matcher.CreateLabel(out var jumpPos2);
|
|
||||||
matcher.InsertAndAdvance(
|
|
||||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ShortcutKeysForStarsName), nameof(_showAllStarsNameStatus))).WithLabels(labels),
|
|
||||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
|
||||||
new CodeInstruction(OpCodes.Ceq),
|
|
||||||
new CodeInstruction(OpCodes.Brtrue, jumpPos.Value),
|
|
||||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PlayerPatch), nameof(_showAllStarsNameKey))),
|
|
||||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(KeyBindings), nameof(KeyBindings.IsKeyPressing))),
|
|
||||||
new CodeInstruction(OpCodes.Brtrue, jumpPos.Value),
|
|
||||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ShortcutKeysForStarsName), nameof(_showAllStarsNameStatus))),
|
|
||||||
new CodeInstruction(OpCodes.Ldc_I4_2),
|
|
||||||
new CodeInstruction(OpCodes.Ceq),
|
|
||||||
new CodeInstruction(OpCodes.Brfalse, jumpPos2),
|
|
||||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
|
||||||
new CodeInstruction(OpCodes.Stloc_1),
|
|
||||||
new CodeInstruction(OpCodes.Br, jumpPos.Value)
|
|
||||||
);
|
|
||||||
return matcher.InstructionEnumeration();
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
[HarmonyTranspiler]
|
|
||||||
[HarmonyPatch(typeof(UIStarmapPlanet), nameof(UIStarmapPlanet._OnLateUpdate))]
|
|
||||||
private static IEnumerable<CodeInstruction> UIStarmapPlanet__OnLateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
|
||||||
{
|
|
||||||
var matcher = new CodeMatcher(instructions, generator);
|
|
||||||
matcher.MatchForward(false,
|
|
||||||
new CodeMatch(OpCodes.Ldarg_0),
|
|
||||||
new CodeMatch(OpCodes.Ldloc_3),
|
|
||||||
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(UIStarmapPlanet), nameof(UIStarmapPlanet.projected)))
|
|
||||||
);
|
|
||||||
matcher.Advance(3);
|
|
||||||
matcher.CreateLabel(out var jumpPos1);
|
|
||||||
matcher.InsertAndAdvance(
|
|
||||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ShortcutKeysForStarsName), nameof(_showAllStarsNameStatus))),
|
|
||||||
new CodeInstruction(OpCodes.Ldc_I4_2),
|
|
||||||
new CodeInstruction(OpCodes.Ceq),
|
|
||||||
new CodeInstruction(OpCodes.Brfalse, jumpPos1),
|
|
||||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
|
||||||
new CodeInstruction(OpCodes.Stloc_3)
|
|
||||||
);
|
|
||||||
matcher.MatchForward(false,
|
|
||||||
new CodeMatch(OpCodes.Ldarg_0),
|
|
||||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStarmapPlanet), nameof(UIStarmapPlanet.gameHistory))),
|
|
||||||
new CodeMatch(OpCodes.Ldarg_0),
|
|
||||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStarmapPlanet), nameof(UIStarmapPlanet.planet))),
|
|
||||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PlanetData), nameof(PlanetData.id))),
|
|
||||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.GetPlanetPin))),
|
|
||||||
new CodeMatch(OpCodes.Ldc_I4_1),
|
|
||||||
new CodeMatch(ci => ci.Branches(out _)),
|
|
||||||
new CodeMatch(OpCodes.Ldc_I4_1),
|
|
||||||
new CodeMatch(ci => ci.IsStloc()),
|
|
||||||
new CodeMatch(ci => ci.Branches(out _))
|
|
||||||
);
|
|
||||||
matcher.CreateLabelAt(matcher.Pos + 8, out var jumpPos);
|
|
||||||
var labels = matcher.Labels;
|
|
||||||
matcher.Labels = null;
|
|
||||||
matcher.InsertAndAdvance(
|
|
||||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ShortcutKeysForStarsName), nameof(_showAllStarsNameStatus))).WithLabels(labels),
|
|
||||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
|
||||||
new CodeInstruction(OpCodes.Ceq),
|
|
||||||
new CodeInstruction(OpCodes.Brtrue, jumpPos),
|
|
||||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PlayerPatch), nameof(_showAllStarsNameKey))),
|
|
||||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(KeyBindings), nameof(KeyBindings.IsKeyPressing))),
|
|
||||||
new CodeInstruction(OpCodes.Brtrue, jumpPos)
|
|
||||||
);
|
|
||||||
return matcher.InstructionEnumeration();
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
[HarmonyTranspiler]
|
||||||
|
[HarmonyPatch(typeof(UIStarmapPlanet), nameof(UIStarmapPlanet._OnLateUpdate))]
|
||||||
|
private static IEnumerable<CodeInstruction> UIStarmapPlanet__OnLateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
|
{
|
||||||
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldloc_3),
|
||||||
|
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(UIStarmapPlanet), nameof(UIStarmapPlanet.projected)))
|
||||||
|
);
|
||||||
|
matcher.Advance(3);
|
||||||
|
matcher.CreateLabel(out var jumpPos1);
|
||||||
|
matcher.InsertAndAdvance(
|
||||||
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ShortcutKeysForStarsName), nameof(_showAllStarsNameStatus))),
|
||||||
|
new CodeInstruction(OpCodes.Ldc_I4_2),
|
||||||
|
new CodeInstruction(OpCodes.Ceq),
|
||||||
|
new CodeInstruction(OpCodes.Brfalse, jumpPos1),
|
||||||
|
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||||
|
new CodeInstruction(OpCodes.Stloc_3)
|
||||||
|
);
|
||||||
|
matcher.MatchForward(false,
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStarmapPlanet), nameof(UIStarmapPlanet.gameHistory))),
|
||||||
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStarmapPlanet), nameof(UIStarmapPlanet.planet))),
|
||||||
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PlanetData), nameof(PlanetData.id))),
|
||||||
|
new CodeMatch(OpCodes.Callvirt, AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.GetPlanetPin))),
|
||||||
|
new CodeMatch(OpCodes.Ldc_I4_1),
|
||||||
|
new CodeMatch(ci => ci.Branches(out _)),
|
||||||
|
new CodeMatch(OpCodes.Ldc_I4_1),
|
||||||
|
new CodeMatch(ci => ci.IsStloc()),
|
||||||
|
new CodeMatch(ci => ci.Branches(out _))
|
||||||
|
);
|
||||||
|
matcher.CreateLabelAt(matcher.Pos + 8, out var jumpPos);
|
||||||
|
var labels = matcher.Labels;
|
||||||
|
matcher.Labels = [];
|
||||||
|
matcher.InsertAndAdvance(
|
||||||
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ShortcutKeysForStarsName), nameof(_showAllStarsNameStatus))).WithLabels(labels),
|
||||||
|
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||||
|
new CodeInstruction(OpCodes.Ceq),
|
||||||
|
new CodeInstruction(OpCodes.Brtrue, jumpPos),
|
||||||
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PlayerPatch), nameof(_showAllStarsNameKey))),
|
||||||
|
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(KeyBindings), nameof(KeyBindings.IsKeyPressing))),
|
||||||
|
new CodeInstruction(OpCodes.Brtrue, jumpPos)
|
||||||
|
);
|
||||||
|
return matcher.InstructionEnumeration();
|
||||||
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(UIStarmapDFHive), nameof(UIStarmapDFHive._OnLateUpdate))]
|
[HarmonyPatch(typeof(UIStarmapDFHive), nameof(UIStarmapDFHive._OnLateUpdate))]
|
||||||
private static IEnumerable<CodeInstruction> UIStarmapDFHive__OnLateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
private static IEnumerable<CodeInstruction> UIStarmapDFHive__OnLateUpdate_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
{
|
{
|
||||||
var matcher = new CodeMatcher(instructions, generator);
|
var matcher = new CodeMatcher(instructions, generator);
|
||||||
matcher.MatchForward(false,
|
matcher.MatchForward(false,
|
||||||
new CodeMatch(OpCodes.Ldarg_0),
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
new CodeMatch(ci => ci.IsLdloc()),
|
new CodeMatch(ci => ci.IsLdloc()),
|
||||||
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(UIStarmapDFHive), nameof(UIStarmapDFHive.projected)))
|
new CodeMatch(OpCodes.Stfld, AccessTools.Field(typeof(UIStarmapDFHive), nameof(UIStarmapDFHive.projected)))
|
||||||
);
|
);
|
||||||
matcher.Advance(3);
|
matcher.Advance(3);
|
||||||
matcher.CreateLabel(out var jumpPos1);
|
matcher.CreateLabel(out var jumpPos1);
|
||||||
matcher.InsertAndAdvance(
|
matcher.InsertAndAdvance(
|
||||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ShortcutKeysForStarsName), nameof(_showAllStarsNameStatus))),
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ShortcutKeysForStarsName), nameof(_showAllStarsNameStatus))),
|
||||||
new CodeInstruction(OpCodes.Ldc_I4_2),
|
new CodeInstruction(OpCodes.Ldc_I4_2),
|
||||||
new CodeInstruction(OpCodes.Ceq),
|
new CodeInstruction(OpCodes.Ceq),
|
||||||
new CodeInstruction(OpCodes.Brfalse, jumpPos1),
|
new CodeInstruction(OpCodes.Brfalse, jumpPos1),
|
||||||
new CodeInstruction(OpCodes.Ldc_I4_0),
|
new CodeInstruction(OpCodes.Ldc_I4_0),
|
||||||
new CodeInstruction(OpCodes.Stloc_S, 4)
|
new CodeInstruction(OpCodes.Stloc_S, 4)
|
||||||
);
|
);
|
||||||
matcher.MatchForward(false,
|
matcher.MatchForward(false,
|
||||||
new CodeMatch(OpCodes.Ldarg_0),
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStarmapDFHive), nameof(UIStarmapDFHive.gameHistory))),
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStarmapDFHive), nameof(UIStarmapDFHive.gameHistory))),
|
||||||
new CodeMatch(OpCodes.Ldarg_0),
|
new CodeMatch(OpCodes.Ldarg_0),
|
||||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStarmapDFHive), nameof(UIStarmapDFHive.hive))),
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(UIStarmapDFHive), nameof(UIStarmapDFHive.hive))),
|
||||||
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(EnemyDFHiveSystem), nameof(EnemyDFHiveSystem.hiveStarId))),
|
new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(EnemyDFHiveSystem), nameof(EnemyDFHiveSystem.hiveStarId))),
|
||||||
new CodeMatch(OpCodes.Ldc_I4, 1000000),
|
new CodeMatch(OpCodes.Ldc_I4, 1000000),
|
||||||
new CodeMatch(OpCodes.Sub),
|
new CodeMatch(OpCodes.Sub),
|
||||||
new CodeMatch(OpCodes.Callvirt, AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.GetHivePin))),
|
new CodeMatch(OpCodes.Callvirt, AccessTools.Field(typeof(GameHistoryData), nameof(GameHistoryData.GetHivePin))),
|
||||||
new CodeMatch(OpCodes.Ldc_I4_1),
|
new CodeMatch(OpCodes.Ldc_I4_1),
|
||||||
new CodeMatch(ci => ci.Branches(out _)),
|
new CodeMatch(ci => ci.Branches(out _)),
|
||||||
new CodeMatch(OpCodes.Ldc_I4_1),
|
new CodeMatch(OpCodes.Ldc_I4_1),
|
||||||
new CodeMatch(ci => ci.IsStloc()),
|
new CodeMatch(ci => ci.IsStloc()),
|
||||||
new CodeMatch(ci => ci.Branches(out _))
|
new CodeMatch(ci => ci.Branches(out _))
|
||||||
);
|
);
|
||||||
matcher.CreateLabelAt(matcher.Pos + 10, out var jumpPos);
|
matcher.CreateLabelAt(matcher.Pos + 10, out var jumpPos);
|
||||||
var labels = matcher.Labels;
|
var labels = matcher.Labels;
|
||||||
matcher.Labels = null;
|
matcher.Labels = [];
|
||||||
matcher.InsertAndAdvance(
|
matcher.InsertAndAdvance(
|
||||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ShortcutKeysForStarsName), nameof(_showAllStarsNameStatus))).WithLabels(labels),
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(ShortcutKeysForStarsName), nameof(_showAllStarsNameStatus))).WithLabels(labels),
|
||||||
new CodeInstruction(OpCodes.Ldc_I4_1),
|
new CodeInstruction(OpCodes.Ldc_I4_1),
|
||||||
new CodeInstruction(OpCodes.Ceq),
|
new CodeInstruction(OpCodes.Ceq),
|
||||||
new CodeInstruction(OpCodes.Brtrue, jumpPos),
|
new CodeInstruction(OpCodes.Brtrue, jumpPos),
|
||||||
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PlayerPatch), nameof(_showAllStarsNameKey))),
|
new CodeInstruction(OpCodes.Ldsfld, AccessTools.Field(typeof(PlayerPatch), nameof(_showAllStarsNameKey))),
|
||||||
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(KeyBindings), nameof(KeyBindings.IsKeyPressing))),
|
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(KeyBindings), nameof(KeyBindings.IsKeyPressing))),
|
||||||
new CodeInstruction(OpCodes.Brtrue, jumpPos)
|
new CodeInstruction(OpCodes.Brtrue, jumpPos)
|
||||||
);
|
);
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AutoNavigation: PatchImpl<AutoNavigation>
|
public class AutoNavigation : PatchImpl<AutoNavigation>
|
||||||
{
|
{
|
||||||
private static bool _canUseWarper;
|
private static bool _canUseWarper;
|
||||||
private static int _indicatorAstroId;
|
private static int _indicatorAstroId;
|
||||||
private static bool _speedUp;
|
private static bool _speedUp;
|
||||||
private static Vector3 _direction;
|
private static Vector3 _direction;
|
||||||
|
private static EMovementState _movementState = EMovementState.Walk;
|
||||||
|
|
||||||
|
public static int IndicatorAstroId => _indicatorAstroId;
|
||||||
|
|
||||||
|
protected override void OnEnable()
|
||||||
|
{
|
||||||
|
_canUseWarper = false;
|
||||||
|
_indicatorAstroId = 0;
|
||||||
|
_speedUp = false;
|
||||||
|
_direction = Vector3.zero;
|
||||||
|
_movementState = EMovementState.Walk;
|
||||||
|
}
|
||||||
|
|
||||||
public static void ToggleAutoCruise()
|
public static void ToggleAutoCruise()
|
||||||
{
|
{
|
||||||
@@ -319,6 +359,16 @@ public static class PlayerPatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool UpdateMovementState(PlayerController controller)
|
||||||
|
{
|
||||||
|
var movementStateChanged = controller.movementStateInFrame != _movementState;
|
||||||
|
if (movementStateChanged)
|
||||||
|
{
|
||||||
|
_movementState = controller.movementStateInFrame;
|
||||||
|
}
|
||||||
|
return movementStateChanged;
|
||||||
|
}
|
||||||
|
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(PlayerController), nameof(PlayerController.GameTick))]
|
[HarmonyPatch(typeof(PlayerController), nameof(PlayerController.GameTick))]
|
||||||
private static IEnumerable<CodeInstruction> PlayerController_GameTick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
private static IEnumerable<CodeInstruction> PlayerController_GameTick_Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
|
||||||
@@ -333,45 +383,55 @@ public static class PlayerPatch
|
|||||||
/* Update target astro if changed */
|
/* Update target astro if changed */
|
||||||
_speedUp = false;
|
_speedUp = false;
|
||||||
var player = controller.player;
|
var player = controller.player;
|
||||||
|
if (player.mecha.thrusterLevel < 2) return;
|
||||||
var navi = player.navigation;
|
var navi = player.navigation;
|
||||||
if (navi.indicatorAstroId != _indicatorAstroId)
|
var astroChanged = navi.indicatorAstroId != _indicatorAstroId;
|
||||||
|
if (astroChanged)
|
||||||
{
|
{
|
||||||
_indicatorAstroId = navi.indicatorAstroId;
|
_indicatorAstroId = navi.indicatorAstroId;
|
||||||
if (_indicatorAstroId == 0) return;
|
Functions.UIFunctions.UpdateToggleAutoCruiseCheckButtonVisiblility();
|
||||||
}
|
}
|
||||||
else if (_indicatorAstroId == 0) return;
|
if (_indicatorAstroId == 0) return;
|
||||||
switch (controller.movementStateInFrame)
|
switch (controller.movementStateInFrame)
|
||||||
{
|
{
|
||||||
case EMovementState.Walk:
|
case EMovementState.Walk:
|
||||||
case EMovementState.Drift:
|
case EMovementState.Drift:
|
||||||
if (!AutoCruiseEnabled.Value) return;
|
if (!AutoCruiseEnabled.Value) return;
|
||||||
if (GameMain.localStar?.astroId == _indicatorAstroId) return;
|
if (GameMain.localStar?.astroId == _indicatorAstroId) return;
|
||||||
|
UpdateMovementState(controller);
|
||||||
/* Press jump key to fly */
|
/* Press jump key to fly */
|
||||||
controller.input0.z = 1f;
|
controller.input0.z = 1f;
|
||||||
break;
|
break;
|
||||||
case EMovementState.Fly:
|
case EMovementState.Fly:
|
||||||
if (!AutoCruiseEnabled.Value) return;
|
if (!AutoCruiseEnabled.Value) return;
|
||||||
if (GameMain.localStar?.astroId == _indicatorAstroId) return;
|
if (GameMain.localStar?.astroId == _indicatorAstroId) return;
|
||||||
|
UpdateMovementState(controller);
|
||||||
/* Keep pressing jump and pullup key to sail */
|
/* Keep pressing jump and pullup key to sail */
|
||||||
controller.input0.y = 1f;
|
controller.input0.y = -1f;
|
||||||
controller.input1.y = 1f;
|
controller.input1.y = 1f;
|
||||||
break;
|
break;
|
||||||
case EMovementState.Sail:
|
case EMovementState.Sail:
|
||||||
if (VFInput._pullUp.pressing || VFInput._pushDown.pressing || VFInput._moveLeft.pressing || VFInput._moveRight.pressing ||
|
if (VFInput._pullUp.pressing || VFInput._pushDown.pressing || VFInput._moveLeft.pressing || VFInput._moveRight.pressing ||
|
||||||
(!player.warping && UIRoot.instance.uiGame.disableLockCursor && (VFInput._moveForward.pressing || VFInput._moveBackward.pressing)))
|
(!player.warping && UIRoot.instance.uiGame.disableLockCursor && (VFInput._moveForward.pressing || VFInput._moveBackward.pressing)))
|
||||||
return;
|
return;
|
||||||
|
var movementStateChanged = UpdateMovementState(controller);
|
||||||
var playerPos = player.uPosition;
|
var playerPos = player.uPosition;
|
||||||
var isHive = _indicatorAstroId > 1000000;
|
var isHive = _indicatorAstroId > 1000000;
|
||||||
ref var astro = ref isHive ? ref GameMain.spaceSector.astros[_indicatorAstroId - 1000000] : ref GameMain.galaxy.astrosData[_indicatorAstroId];
|
ref var astro = ref isHive ? ref GameMain.spaceSector.astros[_indicatorAstroId - 1000000] : ref GameMain.galaxy.astrosData[_indicatorAstroId];
|
||||||
var astroVec = astro.uPos - playerPos;
|
var astroVec = astro.uPos - playerPos;
|
||||||
var distance = astroVec.magnitude;
|
var distance = astroVec.magnitude;
|
||||||
|
astroVec = astroVec.normalized;
|
||||||
|
if (astroChanged || movementStateChanged)
|
||||||
|
{
|
||||||
|
controller.actionSail.sailPoser.targetURotWanted = Quaternion.LookRotation(astroVec);
|
||||||
|
}
|
||||||
if (distance < astro.type switch
|
if (distance < astro.type switch
|
||||||
{
|
{
|
||||||
EAstroType.Planet => 800.0 + astro.uRadius,
|
EAstroType.Planet => 800.0 + astro.uRadius,
|
||||||
EAstroType.Star => 4000.0 + astro.uRadius,
|
EAstroType.Star => 4000.0 + astro.uRadius,
|
||||||
EAstroType.EnemyHive => 400.0,
|
EAstroType.EnemyHive => 800.0,
|
||||||
_ => 2000.0 + astro.uRadius
|
_ => 2000.0 + astro.uRadius
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
if (isHive)
|
if (isHive)
|
||||||
{
|
{
|
||||||
@@ -382,11 +442,11 @@ public static class PlayerPatch
|
|||||||
var autoCruise = AutoCruiseEnabled.Value;
|
var autoCruise = AutoCruiseEnabled.Value;
|
||||||
if (GameMain.instance.timei % 6 == 0 || _direction == Vector3.zero)
|
if (GameMain.instance.timei % 6 == 0 || _direction == Vector3.zero)
|
||||||
{
|
{
|
||||||
_direction = astroVec.normalized;
|
_direction = astroVec;
|
||||||
|
|
||||||
/* Check nearest astroes, try to bypass them */
|
/* Check nearest astroes, try to bypass them */
|
||||||
var localStar = GameMain.localStar;
|
var localStar = GameMain.localStar;
|
||||||
_canUseWarper = autoCruise && !player.warping && player.mecha.warpStorage.GetItemCount(1210) > 0;
|
_canUseWarper = autoCruise && player.mecha.thrusterLevel >= 3 && !player.warping && player.mecha.HasWarper();
|
||||||
if (localStar != null)
|
if (localStar != null)
|
||||||
{
|
{
|
||||||
var nearestRange = (playerPos - localStar.uPosition).sqrMagnitude;
|
var nearestRange = (playerPos - localStar.uPosition).sqrMagnitude;
|
||||||
@@ -410,9 +470,9 @@ public static class PlayerPatch
|
|||||||
if (hiveSys.realized && hiveSys.hiveAstroId > 1000000)
|
if (hiveSys.realized && hiveSys.hiveAstroId > 1000000)
|
||||||
{
|
{
|
||||||
ref var hiveAstro = ref GameMain.spaceSector.astros[hiveSys.hiveAstroId - 1000000];
|
ref var hiveAstro = ref GameMain.spaceSector.astros[hiveSys.hiveAstroId - 1000000];
|
||||||
/* Divide by 4, so that the real range is 2 times of the calculated range,
|
/* Divide by 36, so that the real range is 6 times of the calculated range,
|
||||||
which means the minimal range allowed is 4000 */
|
which means the minimal range allowed is 12000 */
|
||||||
var range = (playerPos - hiveAstro.uPos).sqrMagnitude / 4.0;
|
var range = (playerPos - hiveAstro.uPos).sqrMagnitude / 36.0;
|
||||||
if (range < nearestRange)
|
if (range < nearestRange)
|
||||||
{
|
{
|
||||||
nearestRange = range;
|
nearestRange = range;
|
||||||
@@ -446,25 +506,30 @@ public static class PlayerPatch
|
|||||||
var speed = uVel.magnitude;
|
var speed = uVel.magnitude;
|
||||||
if (player.warping)
|
if (player.warping)
|
||||||
{
|
{
|
||||||
_speedUp = false;
|
|
||||||
if (autoCruise)
|
if (autoCruise)
|
||||||
{
|
{
|
||||||
/* Speed down if too close */
|
|
||||||
var actionSail = controller.actionSail;
|
var actionSail = controller.actionSail;
|
||||||
|
_speedUp = actionSail.currentWarpSpeed < actionSail.maxWarpSpeed;
|
||||||
|
/* Speed down if too close */
|
||||||
if (distance < GalaxyData.LY * 1.5)
|
if (distance < GalaxyData.LY * 1.5)
|
||||||
{
|
{
|
||||||
if (distance < actionSail.currentWarpSpeed * distance switch
|
if (distance < actionSail.currentWarpSpeed * distance switch
|
||||||
{
|
{
|
||||||
> GalaxyData.LY * 0.6 => 0.33,
|
> GalaxyData.LY * 0.6 => 0.33,
|
||||||
> GalaxyData.LY * 0.3 => 0.5,
|
> GalaxyData.LY * 0.3 => 0.5,
|
||||||
> GalaxyData.LY * 0.1 => 0.66,
|
> GalaxyData.LY * 0.1 => 0.66,
|
||||||
_ => 1.0
|
_ => 1.0
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
controller.input0.y = -1f;
|
controller.input0.y = -1f;
|
||||||
|
_speedUp = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_speedUp = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -474,6 +539,7 @@ public static class PlayerPatch
|
|||||||
{
|
{
|
||||||
player.warpCommand = true;
|
player.warpCommand = true;
|
||||||
VFAudio.Create("warp-begin", player.transform, Vector3.zero, true);
|
VFAudio.Create("warp-begin", player.transform, Vector3.zero, true);
|
||||||
|
controller.actionSail.sailPoser.targetURotWanted = Quaternion.LookRotation(astroVec);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -522,10 +588,7 @@ public static class PlayerPatch
|
|||||||
[HarmonyPatch(typeof(UISailPanel), nameof(UISailPanel._OnOpen))]
|
[HarmonyPatch(typeof(UISailPanel), nameof(UISailPanel._OnOpen))]
|
||||||
public static void OnOpen_Prefix()
|
public static void OnOpen_Prefix()
|
||||||
{
|
{
|
||||||
if (_aimingEnabled)
|
UIRoot.instance.uiGame.disableLockCursor = true;
|
||||||
{
|
|
||||||
UIRoot.instance.uiGame.disableLockCursor = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +1,82 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
using System.Linq;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
using BepInEx.Configuration;
|
using BepInEx.Configuration;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
using UXAssist.Common;
|
using UXAssist.Common;
|
||||||
|
using GameLogicProc = UXAssist.Common.GameLogic;
|
||||||
|
|
||||||
namespace UXAssist.Patches;
|
namespace UXAssist.Patches;
|
||||||
|
|
||||||
public static class TechPatch
|
public static class TechPatch
|
||||||
{
|
{
|
||||||
public static ConfigEntry<bool> SorterCargoStackingEnabled;
|
public static ConfigEntry<bool> SorterCargoStackingEnabled;
|
||||||
|
public static ConfigEntry<bool> DisableBattleRelatedTechsInPeaceModeEnabled;
|
||||||
public static ConfigEntry<bool> BatchBuyoutTechEnabled;
|
public static ConfigEntry<bool> BatchBuyoutTechEnabled;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
I18N.Add("分拣器运货量", "Sorter Mk.III cargo stacking : ", "极速分拣器每次可运送 ");
|
I18N.Add("分拣器运货量", "Sorter Mk.III cargo stacking : ", "极速分拣器每次可运送 ");
|
||||||
SorterCargoStackingEnabled.SettingChanged += (_, _) => SorterCargoStacking.Enable(SorterCargoStackingEnabled.Value);
|
SorterCargoStackingEnabled.SettingChanged += (_, _) => SorterCargoStacking.Enable(SorterCargoStackingEnabled.Value);
|
||||||
|
DisableBattleRelatedTechsInPeaceModeEnabled.SettingChanged += (_, _) => DisableBattleRelatedTechsInPeaceMode.Enable(DisableBattleRelatedTechsInPeaceModeEnabled.Value);
|
||||||
BatchBuyoutTechEnabled.SettingChanged += (_, _) => BatchBuyoutTech.Enable(BatchBuyoutTechEnabled.Value);
|
BatchBuyoutTechEnabled.SettingChanged += (_, _) => BatchBuyoutTech.Enable(BatchBuyoutTechEnabled.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Start()
|
public static void Start()
|
||||||
{
|
{
|
||||||
SorterCargoStacking.Enable(SorterCargoStackingEnabled.Value);
|
SorterCargoStacking.Enable(SorterCargoStackingEnabled.Value);
|
||||||
|
DisableBattleRelatedTechsInPeaceMode.Enable(DisableBattleRelatedTechsInPeaceModeEnabled.Value);
|
||||||
BatchBuyoutTech.Enable(BatchBuyoutTechEnabled.Value);
|
BatchBuyoutTech.Enable(BatchBuyoutTechEnabled.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Uninit()
|
public static void Uninit()
|
||||||
{
|
{
|
||||||
BatchBuyoutTech.Enable(false);
|
BatchBuyoutTech.Enable(false);
|
||||||
|
DisableBattleRelatedTechsInPeaceMode.Enable(false);
|
||||||
SorterCargoStacking.Enable(false);
|
SorterCargoStacking.Enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SorterCargoStacking: PatchImpl<SorterCargoStacking>
|
private class SorterCargoStacking
|
||||||
{
|
{
|
||||||
private static bool _protoPatched;
|
private static bool _protoPatched;
|
||||||
|
|
||||||
protected override void OnEnable()
|
public static void Enable(bool enable)
|
||||||
{
|
{
|
||||||
TryPatchProto(true);
|
if (enable)
|
||||||
GameLogic.OnDataLoaded += VFPreload_InvokeOnLoadWorkEnded_Postfix;
|
{
|
||||||
}
|
TryPatchProto(true);
|
||||||
|
GameLogicProc.OnDataLoaded += VFPreload_InvokeOnLoadWorkEnded_Postfix;
|
||||||
protected override void OnDisable()
|
}
|
||||||
{
|
else
|
||||||
GameLogic.OnDataLoaded -= VFPreload_InvokeOnLoadWorkEnded_Postfix;
|
{
|
||||||
TryPatchProto(false);
|
GameLogicProc.OnDataLoaded -= VFPreload_InvokeOnLoadWorkEnded_Postfix;
|
||||||
|
TryPatchProto(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TryPatchProto(bool on)
|
private static void TryPatchProto(bool on)
|
||||||
{
|
{
|
||||||
|
if (DSPGame.IsMenuDemo) return;
|
||||||
var techs = LDB.techs;
|
var techs = LDB.techs;
|
||||||
if (techs == null || techs.dataArray == null || techs.dataArray.Length == 0) return;
|
if (techs == null || techs?.dataArray == null || techs.dataArray.Length == 0) return;
|
||||||
if (on)
|
if (on)
|
||||||
{
|
{
|
||||||
var delim = -26.0f;
|
var delim = -26.0f;
|
||||||
|
var x = 9.0f;
|
||||||
|
var y = -27.0f;
|
||||||
var tp3301 = techs.Select(3301);
|
var tp3301 = techs.Select(3301);
|
||||||
if (tp3301 != null && tp3301.IsObsolete)
|
if (tp3301 != null && tp3301.IsObsolete)
|
||||||
{
|
{
|
||||||
_protoPatched = false;
|
_protoPatched = false;
|
||||||
delim = tp3301.Position.y + 1.0f;
|
var tp3311 = techs.Select(3311);
|
||||||
|
if (tp3311 != null)
|
||||||
|
{
|
||||||
|
x = tp3311.Position.x;
|
||||||
|
y = tp3311.Position.y;
|
||||||
|
delim = y + 1.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (_protoPatched) return;
|
if (_protoPatched) return;
|
||||||
|
|
||||||
@@ -70,9 +87,20 @@ public static class TechPatch
|
|||||||
case >= 3301 and <= 3305:
|
case >= 3301 and <= 3305:
|
||||||
tp.UnlockValues[0] = tp.ID - 3300 + 1;
|
tp.UnlockValues[0] = tp.ID - 3300 + 1;
|
||||||
tp.IsObsolete = false;
|
tp.IsObsolete = false;
|
||||||
|
tp.Position = new Vector2(x + 4.0f * (tp.ID - 3301), y);
|
||||||
|
if (tp.ID == 3305)
|
||||||
|
{
|
||||||
|
tp.postTechArray = [];
|
||||||
|
if (UIRoot.instance.uiGame.techTree.nodes.TryGetValue(tp.ID, out var node))
|
||||||
|
{
|
||||||
|
node.outputLine.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
case 3306:
|
case 3306:
|
||||||
tp.PreTechs = [];
|
tp.PreTechs = [];
|
||||||
|
tp.preTechArray = [];
|
||||||
|
tp.Position = new Vector2(x + 4.0f * (tp.ID - 3301), y);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +134,10 @@ public static class TechPatch
|
|||||||
|
|
||||||
_protoPatched = false;
|
_protoPatched = false;
|
||||||
}
|
}
|
||||||
|
LDB.techs.Signature = ProtoSignature_0_10_30_3100.CalculateSignature(LDB.techs);
|
||||||
|
var techTree = UIRoot.instance?.uiGame?.techTree;
|
||||||
|
if (techTree != null && techTree.isActiveAndEnabled)
|
||||||
|
techTree.OnPageChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void VFPreload_InvokeOnLoadWorkEnded_Postfix()
|
private static void VFPreload_InvokeOnLoadWorkEnded_Postfix()
|
||||||
@@ -114,162 +146,177 @@ public static class TechPatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BatchBuyoutTech: PatchImpl<BatchBuyoutTech>
|
private static class DisableBattleRelatedTechsInPeaceMode
|
||||||
{
|
{
|
||||||
private static void GenerateTechList(GameHistoryData history, int techId, List<int> techIdList)
|
private static bool _protoPatched;
|
||||||
|
private static HashSet<int> _techsToDisableSet;
|
||||||
|
private static Dictionary<int, TechProto[]> _originTechPosts = [];
|
||||||
|
|
||||||
|
public static void Enable(bool enable)
|
||||||
{
|
{
|
||||||
var techProto = LDB.techs.Select(techId);
|
if (_techsToDisableSet == null)
|
||||||
if (techProto == null || !techProto.Published) return;
|
|
||||||
var flag = true;
|
|
||||||
for (var i = 0; i < 2; i++)
|
|
||||||
{
|
{
|
||||||
var array = techProto.PreTechs;
|
(int, int)[] techListToDisable =
|
||||||
if (i == 1)
|
[
|
||||||
{
|
// Explosive Unit, Crystal Explosive Unit
|
||||||
array = techProto.PreTechsImplicit;
|
// 爆破单元,晶石爆破单元
|
||||||
}
|
(1803, 1804),
|
||||||
for (var j = 0; j < array.Length; j++)
|
// Implosion Cannon
|
||||||
{
|
// 聚爆加农炮
|
||||||
if (!history.techStates.ContainsKey(array[j]) || history.techStates[array[j]].unlocked) continue;
|
(1807, 1807),
|
||||||
if (history.techStates[array[j]].maxLevel > history.techStates[array[j]].curLevel)
|
// Signal Tower, Planetary Defense System, Jammer Tower, Plasma Turret, Titanium Ammo Box, Superalloy Ammo Box, High-Explosive Shell Set, Supersonic Missile Set, Crystal Shell Set, Gravity Missile Set, Antimatter Capsule, Precision Drone, Prototype, Attack Drone, Corvette, Destroyer, Suppressing Capsule, EM Capsule Mk.III
|
||||||
{
|
// 信号塔, 行星防御系统, 干扰塔, 磁化电浆炮, 钛化弹箱, 超合金弹箱, 高爆炮弹组, 超音速导弹组, 晶石炮弹组, 引力导弹组, 反物质胶囊, 地面战斗机-A型, 地面战斗机-E型, 地面战斗机-F型, 太空战斗机-A型, 太空战斗机-F型, 电磁胶囊II, 电磁胶囊III
|
||||||
flag = false;
|
(1809, 1825),
|
||||||
}
|
// Auto Reconstruction Marking
|
||||||
GenerateTechList(history, array[j], techIdList);
|
// 自动标记重建
|
||||||
}
|
(2951, 2956),
|
||||||
|
// Energy Shield
|
||||||
|
// 能量护盾
|
||||||
|
(2801, 2807),
|
||||||
|
// Kinetic Weapon Damage
|
||||||
|
// 动能武器伤害
|
||||||
|
(5001, 5006),
|
||||||
|
// Energy Weapon Damage
|
||||||
|
// 能量武器伤害
|
||||||
|
(5101, 5106),
|
||||||
|
// Explosive Weapon Damage
|
||||||
|
// 爆炸武器伤害
|
||||||
|
(5201, 5206),
|
||||||
|
// Combat Drone Damage
|
||||||
|
// 战斗无人机伤害
|
||||||
|
(5301, 5305),
|
||||||
|
// Combat Drone Attack Speed
|
||||||
|
// 战斗无人机攻击速度
|
||||||
|
(5401, 5405),
|
||||||
|
// Combat Drone Engine
|
||||||
|
// 战斗无人机引擎
|
||||||
|
(5601, 5605),
|
||||||
|
// Combat Drone Durability
|
||||||
|
// 战斗无人机耐久
|
||||||
|
(5701, 5705),
|
||||||
|
// Ground Squadron Expansion
|
||||||
|
// 地面编队扩容
|
||||||
|
(5801, 5807),
|
||||||
|
// Space Fleet Expansion
|
||||||
|
// 太空编队扩容
|
||||||
|
(5901, 5907),
|
||||||
|
// Enhanced Structure
|
||||||
|
// 结构强化
|
||||||
|
(6001, 6006),
|
||||||
|
// Planetary Shield
|
||||||
|
// 行星护盾
|
||||||
|
(6101, 6106),
|
||||||
|
];
|
||||||
|
_techsToDisableSet = [.. techListToDisable.SelectMany(t => Enumerable.Range(t.Item1, t.Item2 - t.Item1 + 1))];
|
||||||
}
|
}
|
||||||
if (history.techStates.ContainsKey(techId) && !history.techStates[techId].unlocked && flag)
|
if (enable)
|
||||||
{
|
{
|
||||||
techIdList.Add(techId);
|
if (DSPGame.GameDesc != null)
|
||||||
|
TryPatchProto(DSPGame.GameDesc.isPeaceMode);
|
||||||
|
GameLogicProc.OnGameBegin += OnGameBegin;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameLogicProc.OnGameBegin -= OnGameBegin;
|
||||||
|
TryPatchProto(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void OnGameBegin()
|
||||||
private static void CheckTechUnlockProperties(GameHistoryData history, TechProto techProto, int[] properties, List<Tuple<TechProto, int, int>> techList, int maxLevel = 10000)
|
|
||||||
{
|
{
|
||||||
var techStates = history.techStates;
|
TryPatchProto(DSPGame.GameDesc.isPeaceMode);
|
||||||
var techID = techProto.ID;
|
|
||||||
if (techStates == null || !techStates.TryGetValue(techID, out var value)) return;
|
|
||||||
if (value.unlocked) return;
|
|
||||||
|
|
||||||
var maxLvl = Math.Min(maxLevel < 0 ? value.curLevel - maxLevel - 1 : maxLevel, value.maxLevel);
|
|
||||||
|
|
||||||
foreach (var preid in techProto.PreTechs)
|
|
||||||
{
|
|
||||||
var preProto = LDB.techs.Select(preid);
|
|
||||||
if (preProto != null)
|
|
||||||
CheckTechUnlockProperties(history, preProto, properties, techList, techProto.PreTechsMax ? 10000 : preProto.Level);
|
|
||||||
}
|
|
||||||
foreach (var preid in techProto.PreTechsImplicit)
|
|
||||||
{
|
|
||||||
var preProto = LDB.techs.Select(preid);
|
|
||||||
if (preProto != null)
|
|
||||||
CheckTechUnlockProperties(history, preProto, properties, techList, techProto.PreTechsMax ? 10000 : preProto.Level);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.curLevel < techProto.Level) value.curLevel = techProto.Level;
|
|
||||||
techList.Add(new Tuple<TechProto, int, int>(techProto, value.curLevel, techProto.Level));
|
|
||||||
while (value.curLevel <= maxLvl)
|
|
||||||
{
|
|
||||||
if (techProto.PropertyOverrideItemArray != null)
|
|
||||||
{
|
|
||||||
var propertyOverrideItemArray = techProto.PropertyOverrideItemArray;
|
|
||||||
for (var i = 0; i < propertyOverrideItemArray.Length; i++)
|
|
||||||
{
|
|
||||||
var id = propertyOverrideItemArray[i].id;
|
|
||||||
var count = (float)propertyOverrideItemArray[i].count;
|
|
||||||
var ratio = Mathf.Clamp01((float)((double)value.hashUploaded / value.hashNeeded));
|
|
||||||
var consume = Mathf.CeilToInt(count * (1f - ratio));
|
|
||||||
properties[id - 6001] += consume;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (var j = 0; j < techProto.itemArray.Length; j++)
|
|
||||||
{
|
|
||||||
var id = techProto.itemArray[j].ID;
|
|
||||||
var consume = (int)(techProto.ItemPoints[j] * (value.hashNeeded - value.hashUploaded) / 3600L);
|
|
||||||
properties[id - 6001] += consume;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value.curLevel++;
|
|
||||||
value.hashUploaded = 0;
|
|
||||||
value.hashNeeded = techProto.GetHashNeeded(value.curLevel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int UnlockTechRecursiveImpl(GameHistoryData history, TechProto techProto, int maxLevel = 10000)
|
private static void TryPatchProto(bool on)
|
||||||
{
|
{
|
||||||
var techStates = history.techStates;
|
if (DSPGame.IsMenuDemo || on == _protoPatched) return;
|
||||||
var techID = techProto.ID;
|
var techs = LDB.techs;
|
||||||
if (techStates == null || !techStates.TryGetValue(techID, out var value))
|
if (techs?.dataArray == null || techs.dataArray.Length == 0) return;
|
||||||
|
if (on)
|
||||||
{
|
{
|
||||||
return -1;
|
foreach (var tp in techs.dataArray)
|
||||||
}
|
|
||||||
|
|
||||||
if (value.unlocked)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
var maxLvl = Math.Min(maxLevel < 0 ? value.curLevel - maxLevel - 1 : maxLevel, value.maxLevel);
|
|
||||||
|
|
||||||
foreach (var preid in techProto.PreTechs)
|
|
||||||
{
|
|
||||||
var preProto = LDB.techs.Select(preid);
|
|
||||||
if (preProto != null)
|
|
||||||
UnlockTechRecursiveImpl(history, preProto, techProto.PreTechsMax ? 10000 : preProto.Level);
|
|
||||||
}
|
|
||||||
foreach (var preid in techProto.PreTechsImplicit)
|
|
||||||
{
|
|
||||||
var preProto = LDB.techs.Select(preid);
|
|
||||||
if (preProto != null)
|
|
||||||
UnlockTechRecursiveImpl(history, preProto, techProto.PreTechsMax ? 10000 : preProto.Level);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.curLevel < techProto.Level) value.curLevel = techProto.Level;
|
|
||||||
while (value.curLevel <= maxLvl)
|
|
||||||
{
|
|
||||||
if (value.curLevel == 0)
|
|
||||||
{
|
{
|
||||||
foreach (var recipe in techProto.UnlockRecipes)
|
if (_techsToDisableSet.Contains(tp.ID))
|
||||||
{
|
{
|
||||||
history.UnlockRecipe(recipe);
|
tp.IsObsolete = true;
|
||||||
|
}
|
||||||
|
var postTechs = tp.postTechArray;
|
||||||
|
for (var i = postTechs.Length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (_techsToDisableSet.Contains(postTechs[i].ID))
|
||||||
|
{
|
||||||
|
_originTechPosts[tp.ID] = postTechs;
|
||||||
|
tp.postTechArray = [.. postTechs.Where(p => !_techsToDisableSet.Contains(p.ID))];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_protoPatched = true;
|
||||||
for (var j = 0; j < techProto.UnlockFunctions.Length; j++)
|
|
||||||
{
|
|
||||||
history.UnlockTechFunction(techProto.UnlockFunctions[j], techProto.UnlockValues[j], value.curLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var k = 0; k < techProto.AddItems.Length; k++)
|
|
||||||
{
|
|
||||||
history.GainTechAwards(techProto.AddItems[k], techProto.AddItemCounts[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
value.curLevel++;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
value.unlocked = maxLvl >= value.maxLevel;
|
{
|
||||||
value.curLevel = value.unlocked ? maxLvl : maxLvl + 1;
|
foreach (var tp in techs.dataArray)
|
||||||
value.hashNeeded = techProto.GetHashNeeded(value.curLevel);
|
{
|
||||||
value.hashUploaded = value.unlocked ? value.hashNeeded : 0;
|
if (_techsToDisableSet.Contains(tp.ID))
|
||||||
techStates[techID] = value;
|
{
|
||||||
return maxLvl;
|
tp.IsObsolete = false;
|
||||||
}
|
}
|
||||||
|
if (_originTechPosts.TryGetValue(tp.ID, out var postTechs))
|
||||||
private static bool UnlockTechRecursive(TechProto techProto, int maxLevel = 10000)
|
{
|
||||||
{
|
tp.postTechArray = postTechs;
|
||||||
if (techProto == null) return false;
|
}
|
||||||
|
}
|
||||||
|
_originTechPosts.Clear();
|
||||||
|
_protoPatched = false;
|
||||||
|
}
|
||||||
|
LDB.techs.Signature = ProtoSignature_0_10_30_3100.CalculateSignature(LDB.techs);
|
||||||
|
var nodes = UIRoot.instance.uiGame.techTree.nodes;
|
||||||
var history = GameMain.history;
|
var history = GameMain.history;
|
||||||
var ulvl = UnlockTechRecursiveImpl(history, techProto, maxLevel);
|
foreach (var item in nodes)
|
||||||
if (ulvl < 0) return false;
|
{
|
||||||
history.RegFeatureKey(1000100);
|
var node = item.Value;
|
||||||
history.NotifyTechUnlock(techProto.ID, ulvl);
|
foreach (var arrow in node.arrows)
|
||||||
return true;
|
{
|
||||||
|
arrow.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
var postTechArray = node.techProto.postTechArray;
|
||||||
|
var active = postTechArray.Length > 0;
|
||||||
|
node.connGroup.gameObject.SetActive(active);
|
||||||
|
node.connImages = active ? node.connGroup.GetComponentsInChildren<Image>(true) : [];
|
||||||
|
if (!active) continue;
|
||||||
|
bool onlyOneOutput = postTechArray.Length == 1;
|
||||||
|
for (var i = 0; i < postTechArray.Length; i++)
|
||||||
|
{
|
||||||
|
var postTech = postTechArray[i];
|
||||||
|
if (!nodes.ContainsKey(postTech.ID)) continue;
|
||||||
|
bool itemUnlocked = true;
|
||||||
|
for (var n = 0; n < postTech.PreItem.Length; n++)
|
||||||
|
{
|
||||||
|
if (history.ItemUnlocked(postTech.PreItem[n])) continue;
|
||||||
|
itemUnlocked = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bool techUnlocked = history.TechUnlocked(postTech.ID);
|
||||||
|
node.arrows[i].gameObject.SetActive(itemUnlocked || techUnlocked);
|
||||||
|
if (onlyOneOutput && !itemUnlocked && !techUnlocked)
|
||||||
|
{
|
||||||
|
node.outputArrow.enabled = false;
|
||||||
|
node.outputLine.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node.outputLine.gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var techTree = UIRoot.instance?.uiGame?.techTree;
|
||||||
|
if (techTree != null && techTree.isActiveAndEnabled)
|
||||||
|
techTree.OnPageChanged();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BatchBuyoutTech : PatchImpl<BatchBuyoutTech>
|
||||||
|
{
|
||||||
[HarmonyTranspiler]
|
[HarmonyTranspiler]
|
||||||
[HarmonyPatch(typeof(UITechNode), nameof(UITechNode.UpdateInfoDynamic))]
|
[HarmonyPatch(typeof(UITechNode), nameof(UITechNode.UpdateInfoDynamic))]
|
||||||
private static IEnumerable<CodeInstruction> UITechNode_UpdateInfoDynamic_Transpiler(IEnumerable<CodeInstruction> instructions)
|
private static IEnumerable<CodeInstruction> UITechNode_UpdateInfoDynamic_Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||||
@@ -285,7 +332,7 @@ public static class TechPatch
|
|||||||
);
|
);
|
||||||
return matcher.InstructionEnumeration();
|
return matcher.InstructionEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
[HarmonyPatch(typeof(UITechNode), nameof(UITechNode.OnBuyoutButtonClick))]
|
[HarmonyPatch(typeof(UITechNode), nameof(UITechNode.OnBuyoutButtonClick))]
|
||||||
private static bool UITechNode_OnBuyoutButtonClick_Prefix(UITechNode __instance)
|
private static bool UITechNode_OnBuyoutButtonClick_Prefix(UITechNode __instance)
|
||||||
@@ -296,109 +343,8 @@ public static class TechPatch
|
|||||||
}
|
}
|
||||||
var techProto = __instance.techProto;
|
var techProto = __instance.techProto;
|
||||||
if (techProto == null) return false;
|
if (techProto == null) return false;
|
||||||
var properties = new int[6];
|
Functions.TechFunctions.UnlockProtoWithMetadataAndPrompt([techProto], -1, true);
|
||||||
List<Tuple<TechProto, int, int>> techList = new();
|
|
||||||
var history = GameMain.history;
|
|
||||||
var maxLevel = -1;
|
|
||||||
CheckTechUnlockProperties(history, techProto, properties, techList, maxLevel);
|
|
||||||
var propertySystem = DSPGame.propertySystem;
|
|
||||||
var clusterSeedKey = history.gameData.GetClusterSeedKey();
|
|
||||||
var enough = true;
|
|
||||||
for (var i = 0; i < 6; i++)
|
|
||||||
{
|
|
||||||
if (propertySystem.GetItemAvaliableProperty(clusterSeedKey, 6001 + i) >= properties[i]) continue;
|
|
||||||
enough = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!enough)
|
|
||||||
{
|
|
||||||
UIRealtimeTip.Popup("元数据不足".Translate());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!history.hasUsedPropertyBanAchievement)
|
|
||||||
{
|
|
||||||
UIMessageBox.Show("初次使用元数据标题".Translate(), "初次使用元数据描述".Translate(), "取消".Translate(), "确定".Translate(), 2, null, DoUnlockFunc);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoUnlockFunc();
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
void DoUnlockFunc()
|
|
||||||
{
|
|
||||||
if (techList.Count <= 1)
|
|
||||||
{
|
|
||||||
DoUnlockFuncInternal();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var msg = "要使用元数据买断以下科技吗?";
|
|
||||||
|
|
||||||
if (techList.Count <= 10)
|
|
||||||
{
|
|
||||||
foreach (var tuple in techList)
|
|
||||||
{
|
|
||||||
AddToMsg(ref msg, tuple);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (var i = 0; i < 5; i++)
|
|
||||||
{
|
|
||||||
AddToMsg(ref msg, techList[i]);
|
|
||||||
}
|
|
||||||
msg += " ...\n";
|
|
||||||
for (var i = techList.Count - 5; i < techList.Count; i++)
|
|
||||||
{
|
|
||||||
AddToMsg(ref msg, techList[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msg += "\n\n";
|
|
||||||
msg += "以下是买断所需元数据:";
|
|
||||||
for (var i = 0; i < 6; i++)
|
|
||||||
{
|
|
||||||
var itemCount = properties[i];
|
|
||||||
if (itemCount <= 0) continue;
|
|
||||||
msg += $"\n {LDB.items.Select(6001 + i).propertyName}x{itemCount}";
|
|
||||||
}
|
|
||||||
UIMessageBox.Show("批量买断科技", msg, "取消".Translate(), "确定".Translate(), 2, null, DoUnlockFuncInternal);
|
|
||||||
return;
|
|
||||||
|
|
||||||
void AddToMsg(ref string str, Tuple<TechProto, int, int> tuple)
|
|
||||||
{
|
|
||||||
if (tuple.Item2 == tuple.Item3)
|
|
||||||
{
|
|
||||||
if (tuple.Item2 <= 0)
|
|
||||||
str += $"\n {tuple.Item1.name}";
|
|
||||||
else
|
|
||||||
str += $"\n {tuple.Item1.name}{"杠等级".Translate()}{tuple.Item2}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
str += $"\n {tuple.Item1.name}{"杠等级".Translate()}{tuple.Item2}->{tuple.Item3}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DoUnlockFuncInternal()
|
|
||||||
{
|
|
||||||
var mainPlayer = GameMain.mainPlayer;
|
|
||||||
for (var i = 0; i < 6; i++)
|
|
||||||
{
|
|
||||||
var itemCount = properties[i];
|
|
||||||
if (itemCount <= 0) continue;
|
|
||||||
var itemId = 6001 + i;
|
|
||||||
propertySystem.AddItemConsumption(clusterSeedKey, itemId, itemCount);
|
|
||||||
history.AddPropertyItemConsumption(itemId, itemCount, true);
|
|
||||||
mainPlayer.mecha.AddProductionStat(itemId, itemCount, mainPlayer.nearestFactory);
|
|
||||||
mainPlayer.mecha.AddConsumptionStat(itemId, itemCount, mainPlayer.nearestFactory);
|
|
||||||
}
|
|
||||||
UnlockTechRecursive(__instance.techProto, maxLevel);
|
|
||||||
history.VarifyTechQueue();
|
|
||||||
if (history.currentTech != history.techQueue[0])
|
|
||||||
{
|
|
||||||
history.currentTech = history.techQueue[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
396
UXAssist/Patches/UIPatch.cs
Normal file
396
UXAssist/Patches/UIPatch.cs
Normal file
@@ -0,0 +1,396 @@
|
|||||||
|
namespace UXAssist.Patches;
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using HarmonyLib;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using BepInEx.Configuration;
|
||||||
|
using Common;
|
||||||
|
using GameLogicProc = Common.GameLogic;
|
||||||
|
|
||||||
|
[PatchGuid(PluginInfo.PLUGIN_GUID)]
|
||||||
|
public class UIPatch : PatchImpl<UIPatch>
|
||||||
|
{
|
||||||
|
public static ConfigEntry<bool> PlanetVeinUtilizationEnabled;
|
||||||
|
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
PlanetVeinUtilizationEnabled.SettingChanged += (_, _) => PlanetVeinUtilization.Enable(PlanetVeinUtilizationEnabled.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Start()
|
||||||
|
{
|
||||||
|
GameLogicProc.OnGameBegin += PlanetVeinUtilization.OnGameBegin;
|
||||||
|
Enable(true);
|
||||||
|
Functions.UIFunctions.InitMenuButtons();
|
||||||
|
Functions.UIFunctions.InitMilkyWayTopTenPlayers();
|
||||||
|
PlanetVeinUtilization.Enable(PlanetVeinUtilizationEnabled.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Uninit()
|
||||||
|
{
|
||||||
|
PlanetVeinUtilization.Enable(false);
|
||||||
|
Enable(false);
|
||||||
|
GameLogicProc.OnGameBegin -= PlanetVeinUtilization.OnGameBegin;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PlanetVeinUtilization : PatchImpl<PlanetVeinUtilization>
|
||||||
|
{
|
||||||
|
private static VeinTypeInfo[] planetVeinCount = null;
|
||||||
|
private static VeinTypeInfo[] starVeinCount = null;
|
||||||
|
private static readonly Dictionary<int, bool> tmpGroups = [];
|
||||||
|
|
||||||
|
public static void OnGameBegin()
|
||||||
|
{
|
||||||
|
if (planetVeinCount != null)
|
||||||
|
{
|
||||||
|
foreach (VeinTypeInfo vti in planetVeinCount)
|
||||||
|
{
|
||||||
|
if (vti.textCtrl != null)
|
||||||
|
{
|
||||||
|
Object.Destroy(vti.textCtrl.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
planetVeinCount = null;
|
||||||
|
}
|
||||||
|
if (starVeinCount != null)
|
||||||
|
{
|
||||||
|
foreach (VeinTypeInfo vti in starVeinCount)
|
||||||
|
{
|
||||||
|
if (vti.textCtrl != null)
|
||||||
|
{
|
||||||
|
Object.Destroy(vti.textCtrl.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
starVeinCount = null;
|
||||||
|
}
|
||||||
|
var maxVeinId = LDB.veins.dataArray.Max(vein => vein.ID);
|
||||||
|
planetVeinCount = new VeinTypeInfo[maxVeinId + 1];
|
||||||
|
starVeinCount = new VeinTypeInfo[maxVeinId + 1];
|
||||||
|
InitializeVeinCountArray(planetVeinCount);
|
||||||
|
InitializeVeinCountArray(starVeinCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnEnable()
|
||||||
|
{
|
||||||
|
if (planetVeinCount != null)
|
||||||
|
{
|
||||||
|
foreach (VeinTypeInfo vti in planetVeinCount)
|
||||||
|
{
|
||||||
|
vti.Reset();
|
||||||
|
vti.textCtrl?.gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
UIPlanetDetail_RefreshDynamicProperties_Postfix(UIRoot.instance.uiGame.planetDetail);
|
||||||
|
}
|
||||||
|
if (starVeinCount != null)
|
||||||
|
{
|
||||||
|
foreach (VeinTypeInfo vti in starVeinCount)
|
||||||
|
{
|
||||||
|
vti.Reset();
|
||||||
|
vti.textCtrl?.gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
UIStarDetail_RefreshDynamicProperties_Postfix(UIRoot.instance.uiGame.starDetail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Vector2 GetAdjustedSizeDelta(Vector2 origSizeDelta)
|
||||||
|
{
|
||||||
|
return new Vector2(origSizeDelta.x + 40f, origSizeDelta.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDisable()
|
||||||
|
{
|
||||||
|
if (planetVeinCount != null)
|
||||||
|
{
|
||||||
|
foreach (VeinTypeInfo vti in planetVeinCount)
|
||||||
|
{
|
||||||
|
vti.Reset();
|
||||||
|
vti.textCtrl?.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (starVeinCount != null)
|
||||||
|
{
|
||||||
|
foreach (VeinTypeInfo vti in starVeinCount)
|
||||||
|
{
|
||||||
|
vti.Reset();
|
||||||
|
vti.textCtrl?.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Helper functions
|
||||||
|
private static void ProcessVeinData(VeinTypeInfo[] veinCount, VeinData[] veinPool)
|
||||||
|
{
|
||||||
|
if (veinPool == null) return;
|
||||||
|
lock (veinPool)
|
||||||
|
{
|
||||||
|
foreach (VeinData veinData in veinPool)
|
||||||
|
{
|
||||||
|
if (veinData.groupIndex == 0 || veinData.amount == 0) continue;
|
||||||
|
if (tmpGroups.TryGetValue(veinData.groupIndex, out bool hasMiner))
|
||||||
|
{
|
||||||
|
if (hasMiner) continue;
|
||||||
|
hasMiner = veinData.minerCount > 0;
|
||||||
|
if (!hasMiner) continue;
|
||||||
|
tmpGroups[veinData.groupIndex] = true;
|
||||||
|
VeinTypeInfo vti = veinCount[(int)veinData.type];
|
||||||
|
vti.numVeinGroupsWithCollector++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hasMiner = veinData.minerCount > 0;
|
||||||
|
tmpGroups.Add(veinData.groupIndex, hasMiner);
|
||||||
|
VeinTypeInfo vti = veinCount[(int)veinData.type];
|
||||||
|
vti.numVeinGroups++;
|
||||||
|
if (hasMiner)
|
||||||
|
{
|
||||||
|
vti.numVeinGroupsWithCollector++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmpGroups.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FormatResource(int refId, UIResAmountEntry uiresAmountEntry, VeinTypeInfo vt)
|
||||||
|
{
|
||||||
|
if (vt.textCtrl == null)
|
||||||
|
{
|
||||||
|
var parent = uiresAmountEntry.labelText.transform.parent;
|
||||||
|
vt.textCtrl = Object.Instantiate(uiresAmountEntry.valueText, parent);
|
||||||
|
vt.textCtrl.font = uiresAmountEntry.labelText.font;
|
||||||
|
RectTransform trans = vt.textCtrl.rectTransform;
|
||||||
|
var pos = uiresAmountEntry.rectTrans.localPosition;
|
||||||
|
pos.x = pos.x + uiresAmountEntry.iconImage.rectTransform.localPosition.x - 25f;
|
||||||
|
trans.localPosition = pos;
|
||||||
|
Vector2 size = trans.sizeDelta;
|
||||||
|
size.x = 40f;
|
||||||
|
trans.sizeDelta = size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RectTransform trans = vt.textCtrl.rectTransform;
|
||||||
|
Vector3 pos = trans.localPosition;
|
||||||
|
pos.y = uiresAmountEntry.rectTrans.localPosition.y;
|
||||||
|
trans.localPosition = pos;
|
||||||
|
}
|
||||||
|
vt.textCtrl.text = $"{vt.numVeinGroupsWithCollector}/{vt.numVeinGroups}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void InitializeVeinCountArray(VeinTypeInfo[] veinCountArray)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < veinCountArray.Length; i++)
|
||||||
|
{
|
||||||
|
veinCountArray[i] = new VeinTypeInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UIPlanetDetail patches
|
||||||
|
[HarmonyPrefix, HarmonyPatch(typeof(UIPlanetDetail), nameof(UIPlanetDetail.OnPlanetDataSet))]
|
||||||
|
public static void UIPlanetDetail_OnPlanetDataSet_Prefix(UIPlanetDetail __instance)
|
||||||
|
{
|
||||||
|
foreach (VeinTypeInfo vti in planetVeinCount)
|
||||||
|
{
|
||||||
|
vti.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix, HarmonyPatch(typeof(UIPlanetDetail), nameof(UIPlanetDetail.RefreshDynamicProperties))]
|
||||||
|
public static void UIPlanetDetail_RefreshDynamicProperties_Postfix(UIPlanetDetail __instance)
|
||||||
|
{
|
||||||
|
PlanetData planet = __instance.planet;
|
||||||
|
if (planet == null || planet.runtimeVeinGroups == null || __instance.tabIndex != 0) { return; }
|
||||||
|
|
||||||
|
int observeLevelCheck = __instance.planet == GameMain.localPlanet ? 1 : 2;
|
||||||
|
if (GameMain.history.universeObserveLevel < observeLevelCheck) { return; }
|
||||||
|
|
||||||
|
foreach (VeinTypeInfo vti in planetVeinCount)
|
||||||
|
{
|
||||||
|
vti.numVeinGroups = 0;
|
||||||
|
vti.numVeinGroupsWithCollector = 0;
|
||||||
|
}
|
||||||
|
// count up the total number of vein groups per resource type, as well as the total number of groups that have a miner attached
|
||||||
|
PlanetFactory factory = planet.factory;
|
||||||
|
if (factory != null)
|
||||||
|
{
|
||||||
|
ProcessVeinData(planetVeinCount, factory.veinPool);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VeinGroup[] veinGroups = planet.runtimeVeinGroups;
|
||||||
|
lock (planet.veinGroupsLock)
|
||||||
|
{
|
||||||
|
for (int i = 1; i < veinGroups.Length; i++)
|
||||||
|
{
|
||||||
|
planetVeinCount[(int)veinGroups[i].type].numVeinGroups++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update each resource to show the following vein group info:
|
||||||
|
// Iron: <number of vein groups with miners> / <total number of vein groups>
|
||||||
|
foreach (UIResAmountEntry uiresAmountEntry in __instance.entries)
|
||||||
|
{
|
||||||
|
int refId = uiresAmountEntry.refId;
|
||||||
|
if (refId > 0 && refId < (int)EVeinType.Max)
|
||||||
|
{
|
||||||
|
var vt = planetVeinCount[refId];
|
||||||
|
if (vt.numVeinGroups > 0)
|
||||||
|
{
|
||||||
|
FormatResource(refId, uiresAmountEntry, vt);
|
||||||
|
}
|
||||||
|
else if (vt.textCtrl != null)
|
||||||
|
{
|
||||||
|
vt.textCtrl.text = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UIStarDetail patches
|
||||||
|
[HarmonyPrefix, HarmonyPatch(typeof(UIStarDetail), nameof(UIStarDetail.OnStarDataSet))]
|
||||||
|
public static void UIStaretail_OnStarDataSet_Prefix(UIStarDetail __instance)
|
||||||
|
{
|
||||||
|
foreach (VeinTypeInfo vti in starVeinCount)
|
||||||
|
{
|
||||||
|
vti.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix, HarmonyPatch(typeof(UIStarDetail), nameof(UIStarDetail.RefreshDynamicProperties))]
|
||||||
|
public static void UIStarDetail_RefreshDynamicProperties_Postfix(UIStarDetail __instance)
|
||||||
|
{
|
||||||
|
if (__instance.star == null || __instance.tabIndex != 0) { return; }
|
||||||
|
if (GameMain.history.universeObserveLevel < 2) { return; }
|
||||||
|
|
||||||
|
foreach (VeinTypeInfo vti in starVeinCount)
|
||||||
|
{
|
||||||
|
vti.numVeinGroups = 0;
|
||||||
|
vti.numVeinGroupsWithCollector = 0;
|
||||||
|
}
|
||||||
|
foreach (PlanetData planet in __instance.star.planets)
|
||||||
|
{
|
||||||
|
PlanetFactory factory = planet.factory;
|
||||||
|
if (factory != null)
|
||||||
|
{
|
||||||
|
ProcessVeinData(starVeinCount, factory.veinPool);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
VeinGroup[] veinGroups = planet.veinGroups;
|
||||||
|
if (veinGroups == null) continue;
|
||||||
|
lock (planet.veinGroupsLock)
|
||||||
|
{
|
||||||
|
for (int i = 1; i < veinGroups.Length; i++)
|
||||||
|
{
|
||||||
|
starVeinCount[(int)veinGroups[i].type].numVeinGroups++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// update each resource to show the following vein group info:
|
||||||
|
// Iron: <number of vein groups with miners> / <total number of vein groups>
|
||||||
|
foreach (UIResAmountEntry uiresAmountEntry in __instance.entries)
|
||||||
|
{
|
||||||
|
int refId = uiresAmountEntry.refId;
|
||||||
|
if (refId > 0 && refId < (int)EVeinType.Max)
|
||||||
|
{
|
||||||
|
var vt = starVeinCount[refId];
|
||||||
|
if (vt.numVeinGroups > 0)
|
||||||
|
{
|
||||||
|
FormatResource(refId, uiresAmountEntry, vt);
|
||||||
|
}
|
||||||
|
else if (vt.textCtrl != null)
|
||||||
|
{
|
||||||
|
vt.textCtrl.text = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public class VeinTypeInfo
|
||||||
|
{
|
||||||
|
public int numVeinGroups;
|
||||||
|
public int numVeinGroupsWithCollector;
|
||||||
|
public Text textCtrl;
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
numVeinGroups = 0;
|
||||||
|
numVeinGroupsWithCollector = 0;
|
||||||
|
if (textCtrl != null)
|
||||||
|
{
|
||||||
|
textCtrl.text = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add config button to main menu
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(UIRoot), nameof(UIRoot._OnOpen))]
|
||||||
|
public static void UIRoot__OnOpen_Postfix()
|
||||||
|
{
|
||||||
|
Functions.UIFunctions.InitMenuButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(PlanetData), nameof(PlanetData.NotifyScanEnded))]
|
||||||
|
private static void PlanetData_NotifyScanEnded_Postfix(PlanetData __instance)
|
||||||
|
{
|
||||||
|
if (PlanetModelingManager.scnPlanetReqList.Count > 0) return;
|
||||||
|
BepInEx.ThreadingHelper.Instance.StartSyncInvoke(Functions.UIFunctions.OnPlanetScanEnded);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(UIPlanetGlobe), nameof(UIPlanetGlobe.DistributeButtons))]
|
||||||
|
private static void UIPlanetGlobe_DistributeButtons_Postfix(UIPlanetGlobe __instance)
|
||||||
|
{
|
||||||
|
Functions.UIFunctions.UpdateGlobeButtonPosition(__instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(UIStarmapStar), nameof(UIStarmapStar.OnStarDisplayNameChange))]
|
||||||
|
private static bool UIStarmapStar_OnStarDisplayNameChange_Prefix()
|
||||||
|
{
|
||||||
|
return Functions.UIFunctions.CornerComboBoxIndex == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPostfix]
|
||||||
|
[HarmonyPatch(typeof(UIStarmapStar), nameof(UIStarmapStar._OnClose))]
|
||||||
|
private static void UIStarmapStar__OnClose_Postfix(UIStarmapStar __instance)
|
||||||
|
{
|
||||||
|
Functions.UIFunctions.StarmapFilterToggler?.SetCheckedWithEvent(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(UIMechaLab), nameof(UIMechaLab.DetermineVisible))]
|
||||||
|
private static bool UIMechaLab_DetermineVisible_Prefix(UIMechaLab __instance, ref bool __result)
|
||||||
|
{
|
||||||
|
if (!UIRoot.instance.uiGame.starmap.active || !Functions.UIFunctions.StarmapFilterToggler.Checked)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
__instance._Close();
|
||||||
|
__result = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(typeof(UIGoalPanel), nameof(UIGoalPanel.DetermineVisiable))]
|
||||||
|
private static bool UIGoalPanel_DetermineVisiable_Prefix(UIGoalPanel __instance)
|
||||||
|
{
|
||||||
|
if (!UIRoot.instance.uiGame.starmap.active || !Functions.UIFunctions.StarmapFilterToggler.Checked)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
__instance.isUseOverwrittenState = true;
|
||||||
|
if (__instance.stateOverwritten == EUIGoalPanelState.None)
|
||||||
|
{
|
||||||
|
__instance.stateOverwritten = EUIGoalPanelState.Collapse;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,138 +1,153 @@
|
|||||||
# UXAssist
|
# UXAssist
|
||||||
|
|
||||||
#### Some functions and patches for better user experience
|
<details>
|
||||||
|
<summary>Read me in English</summary>
|
||||||
|
|
||||||
#### 一些提升用户体验的功能和补丁
|
***Some functions and patches for better user experience***
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
* Press `` Alt+`(BackQuote) `` to call up the config panel. You can change the shortcut on the panel.
|
* Press `` Alt+`(BackQuote) `` to call up the config panel. You can change the shortcut on the panel.
|
||||||
* There are also buttons on title screen and planet minimap area to call up the config panel.
|
* There are also buttons on title screen and planet minimap area to call up the config panel.
|
||||||
* Patches:
|
* Patches:
|
||||||
+ Strict hotkey dectection for build menu, thus building hotkeys(0~9, F1~F10, X, U) are not triggered while holding Ctrl/Alt/Shift.
|
* Strict hotkey dectection for build menu, thus building hotkeys(0~9, F1~F10, X, U) are not triggered while holding Ctrl/Alt/Shift.
|
||||||
+ Fix a bug that warning popup on `Veins Utilization` upgraded to level 8000+
|
* Fix a bug that warning popup on `Veins Utilization` upgraded to level 8000+
|
||||||
+ Sort blueprint structures before saving, to reduce generated blueprint data size a little
|
* Sort blueprint structures before saving, to reduce generated blueprint data size a little
|
||||||
+ Increase maximum count of Metadata Instantiations to 20000 (from 2000)
|
* Increase maximum count of Metadata Instantiations to 20000 (from 2000)
|
||||||
+ Increase capacity of player order queue to 128 (from 16)
|
* Increase capacity of player order queue to 128 (from 16)
|
||||||
+ Enable `Hide UI` function(`F11` by default) while on Star Map view
|
* Enable `Hide UI` function(`F11` by default) while on Star Map view
|
||||||
+ Append mod profile name to game window title, if using mod managers (`Thunderstore Mod Manager` or `r2modman`).
|
* Append mod profile name to game window title, if using mod managers (`Thunderstore Mod Manager` or `r2modman`).
|
||||||
* Features:
|
* Features:
|
||||||
+ General
|
* General
|
||||||
- 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
|
||||||
- Scale up mouse cursor
|
* Mod manager profile based save folder
|
||||||
- Note: This will enable software cursor mode, which may cause mouse movement lag on heavy load.
|
* Save files are stored in `Save\<ProfileName>` folder.
|
||||||
- Mod manager profile based save folder
|
* Will use original save location if matching default profile name.
|
||||||
- Save files are stored in `Save\<ProfileName>` folder.
|
* Mod manager profile based option
|
||||||
- Will use original save location if matching default profile name.
|
* Option file is stored as `Options\<ProfileName>.xml`.
|
||||||
- Mod manager profile based option
|
* Logical Frame Rate
|
||||||
- Option file is stored as `Options\<ProfileName>.xml`.
|
* This will change game running speed, down to 0.1x slower and up to 10x faster.
|
||||||
- Logical Frame Rate
|
* A pair of shortcut keys (`-` and `+`) to change the logical frame rate by -0.5x and +0.5x.
|
||||||
- This will change game running speed, down to 0.1x slower and up to 10x faster.
|
* Note:
|
||||||
- A pair of shortcut keys (`-` and `+`) to change the logical frame rate by -0.5x and +0.5x.
|
* High logical frame rate is not guaranteed to be stable, especially when factories are under heavy load.
|
||||||
- Note:
|
* This will not affect some game animations.
|
||||||
- High logical frame rate is not guaranteed to be stable, especially when factories are under heavy load.
|
* When set game speed in mod `Auxilaryfunction`, this feature will be disabled.
|
||||||
- This will not affect some game animations.
|
* When mod `BulletTime` is installed, this feature will be hidden, but patch `BulletTime`'s speed control, to make its maximum speed 10x.
|
||||||
- When set game speed in mod `Auxilaryfunction`, this feature will be disabled.
|
* Set process priority
|
||||||
- When mod `BulletTime` is installed, this feature will be hidden, but patch `BulletTime`'s speed control, to make its maximum speed 10x.
|
* Increase maximum count of Metadata Instantiations to 20000 (from 2000)
|
||||||
- Set process priority
|
* Increase capacity of player order queue to 128 (from 16)
|
||||||
- Set enabled CPU threads
|
* Factory
|
||||||
- Increase maximum count of Metadata Instantiations to 20000 (from 2000)
|
* Sunlight at night
|
||||||
- Increase capacity of player order queue to 128 (from 16)
|
* Remove some build conditions
|
||||||
+ Planet/Factory
|
* Remove build count and range limit
|
||||||
- Sunlight at night
|
* Larger area for upgrade and dismantle(30x30 at max)
|
||||||
- Remove some build conditions
|
* Larger area for terraform(30x30 at max)
|
||||||
- Remove build count and range limit
|
* Off-grid building and stepped rotation
|
||||||
- Larger area for upgrade and dismantle(30x30 at max)
|
* Cut conveyor belt
|
||||||
- Larger area for terraform(30x30 at max)
|
* Press shortcut key to cut conveyor belt under cursor.
|
||||||
- Off-grid building and stepped rotation
|
* The default shortcut key is Alt+X, you can set it in system options panel.
|
||||||
- Cut conveyor belt
|
* Treat stack items as single in monitor components
|
||||||
- Press shortcut key to cut conveyor belt under cursor.
|
* Quick build and dismantle stacking labs/storages/tanks
|
||||||
- The default shortcut key is Alt+X, you can set it in system options panel.
|
* Fast fill in to and take out from tanks
|
||||||
- Treat stack items as single in monitor components
|
* You can set multiplier for tanks' operation speed
|
||||||
- Enhanced control for logistic storage limits
|
* This affects manually fill in to and/or take out from tanks, as well as transfer from upper to lower level.
|
||||||
- Logistic storage limits are not scaled on upgrading `Logistics Carrier Capacity`, if they are not set to maximum capacity.
|
* Protect veins from exhaustion
|
||||||
- You can use arrow keys to adjust logistic storage limits gracefully.
|
* By default, the vein amount is protected at 100, and oil speed is protected at 1.0/s, you can set them yourself in config file.
|
||||||
- Quick build and dismantle stacking labs/storages/tanks
|
* When reach the protection value, veins/oils steeps will not be mined/extracted any longer.
|
||||||
- Fast fill in to and take out from tanks
|
* Close this function to resume mining and pumping, usually when you have enough level on `Veins Utilization`
|
||||||
- You can set multiplier for tanks' operation speed
|
* Do not render factory entities (except belts and sorters)
|
||||||
- This affects manually fill in to and/or take out from tanks, as well as transfer from upper to lower level.
|
* This also makes players click though factory entities but belts and sorters
|
||||||
- Protect veins from exhaustion
|
* Drag building power poles in maximum connection range
|
||||||
- By default, the vein amount is protected at 100, and oil speed is protected at 1.0/s, you can set them yourself in config file.
|
* Auto-construct
|
||||||
- When reach the protection value, veins/oils steeps will not be mined/extracted any longer.
|
* Fly to buildings to be contructed automatically
|
||||||
- Close this function to resume mining and pumping, usually when you have enough level on `Veins Utilization`
|
* Dismantle blueprint selected buildings
|
||||||
- Do not render factory entities (except belts and sorters)
|
* Press shortcut key in blueprint copy mode to dismantle selected buildings.
|
||||||
- This also makes players click though factory entities but belts and sorters
|
* The default shortcut key is Ctrl+X, you can set it in system options panel.
|
||||||
- Drag building power poles in maximum connection range
|
* Initialize This Planet (without reseting veins)
|
||||||
- Allow overflow for Logistic Stations and Advanced Mining Machines
|
* 3 Options to return certain items
|
||||||
- Allow overflow when trying to insert in-hand items
|
* Quick dismantle all buildings (without drops)
|
||||||
- Allow `Enhanced control for logistic storage limits` to exceed tech capacity limits
|
* Quick build Orbital Collectors
|
||||||
- Remove logistic strorage limit check on loading game
|
* Belt signals for buy out dark fog items automatically
|
||||||
- Logistics Control Panel Improvement
|
* 6 belt signals are added to the signal panel, which can be used to buy out dark fog items automatically.
|
||||||
- Auto apply filter with item under mouse cursor while opening the panel
|
* Generated items are stacked in 4 items.
|
||||||
- Quick-set item filter while right-clicking item icons in storage list on the panel
|
* Exchange ratio is following the original game design, aka:
|
||||||
- Real-time logistic stations info panel
|
* 1 Metaverse = 20 Dark Fog Matrices
|
||||||
- Dismantle blueprint selected buildings
|
* 1 Metaverse = 60 Engery Shards
|
||||||
- Press shortcut key in blueprint copy mode to dismantle selected buildings.
|
* 1 Metaverse = 30 Silicon-based Neurons
|
||||||
- The default shortcut key is Ctrl+X, you can set it in system options panel.
|
* 1 Metaverse = 30 Negentropy Singularities
|
||||||
- Re-intialize planet (without reseting veins)
|
* 1 Metaverse = 30 Matter Recombinators
|
||||||
- Quick dismantle all buildings (without drops)
|
* 1 Metaverse = 10 Core Elements
|
||||||
- Quick build Orbital Collectors
|
* Tweak building buffer
|
||||||
- Belt signals for buy out dark fog items automatically
|
* Factory recipe buffer formula: take the larger value between `Assembler buffer time multiplier(in seconds) * items needed per second` and `Assembler buffer minimum multiplier * items needed per recipe`
|
||||||
- 6 belt signals are added to the signal panel, which can be used to buy out dark fog items automatically.
|
* `Assembler buffer time multiplier(in seconds)`: Range 2-10, default is 4 (same as game)
|
||||||
- Generated items are stacked in 4 items.
|
* `Assembler buffer minimum multiplier`: Range 2-10, default is 2 (same as game)
|
||||||
- Exchange ratio is following the original game design, aka:
|
* Matrix Lab assembly mode formula: Default buffer is `Buffer count for assembling in labs`, when using Self-evolution Lab, if recipe's original production time is not greater than 9 seconds, add `Extra buffer count for Self-evolution Labs` * (`Lab speed` - 1)
|
||||||
- 1 Metaverse = 20 Dark Fog Matrices
|
* `Buffer count for assembling in labs`: Range 2-20, default is 6 (same as game)
|
||||||
- 1 Metaverse = 60 Engery Shards
|
* `Extra buffer count for Self-evolution Labs`: Range 1-10, default is 3 (same as game)
|
||||||
- 1 Metaverse = 30 Silicon-based Neurons
|
* `Buffer count for researching in labs`: Range 2-20, default is 10 (same as game)
|
||||||
- 1 Metaverse = 30 Negentropy Singularities
|
* `Ray Receiver Graviton Lens buffer count`: Range 1-20, default is 1 (game default is 20)
|
||||||
- 1 Metaverse = 30 Matter Recombinators
|
* `Ejector Solar Sails buffer count`: Range 5-400 (step by 5), default is 20 (same as game)
|
||||||
- 1 Metaverse = 10 Core Elements
|
* `Silo Rockets buffer count`: Range 1-20, default is 20 (same as game)
|
||||||
- Tweak building buffer
|
* Logistics
|
||||||
- Factory recipe buffer formula: take the larger value between `Assembler buffer time multiplier(in seconds) * items needed per second` and `Assembler buffer minimum multiplier * items needed per recipe`
|
* Enhanced control for logistic storage capacities
|
||||||
- `Assembler buffer time multiplier(in seconds)`: Range 2-10, default is 4 (same as game)
|
* Logistic storage capacities are not scaled on upgrading `Logistics Carrier Capacity`, if they are not set to maximum capacity or already greater than maximum capacity.
|
||||||
- `Assembler buffer minimum multiplier`: Range 2-10, default is 2 (same as game)
|
* You can use arrow keys to adjust logistic storage capacities gracefully.
|
||||||
- Matrix Lab assembly mode formula: Default buffer is `Buffer count for assembling in labs`, when using Self-evolution Lab, if recipe's original production time is not greater than 9 seconds, add `Extra buffer count for Self-evolution Labs` * (`Lab speed` - 1)
|
* Logistics Control Panel Improvement
|
||||||
- `Buffer count for assembling in labs`: Range 2-20, default is 6 (same as game)
|
* Auto apply filter with item under mouse cursor while opening the panel
|
||||||
- `Extra buffer count for Self-evolution Labs`: Range 1-10, default is 3 (same as game)
|
* Quick-set item filter while right-clicking item icons in storage list on the panel
|
||||||
- `Buffer count for researching in labs`: Range 2-20, default is 10 (same as game)
|
* Allow overflow for Logistic Stations and Advanced Mining Machines
|
||||||
- `Ray Receiver Graviton Lens buffer count`: Range 1-20, default is 1 (game default is 20)
|
* Allow overflow when trying to insert in-hand items
|
||||||
+ Player/Mecha
|
* Allow `Enhanced control for logistic storage capacities` to exceed tech capacity limits
|
||||||
- Unlimited interactive range
|
* Remove logistic strorage capacity limit check on loading game
|
||||||
- Enable player actions in globe view
|
* Real-time logistic stations info panel
|
||||||
- Hide tips for soil piles changes
|
* Auto-config logistic stations
|
||||||
- Enhanced count control for hand-make
|
* Auto-config buildings include: Logistics Distributor, PLS, ILS, Advanced Mining Machine
|
||||||
- Shortcut keys for showing stars' name
|
* Player/Mecha
|
||||||
- Add a shortcut key to always show all star names in starmap when holding, default is `Alt`
|
* Unlimited interactive range
|
||||||
- Add a shortcut key to toggle between three star name display states in starmap: `Original state`, `Show all names`, `Hide all names`, default is `Tab`, will restore to original state when closing starmap
|
* Enable player actions in globe view
|
||||||
- Auto navigation on sailings
|
* Hide tips for soil piles changes
|
||||||
- It keeps Icarus on course to the target planet
|
* Enhanced count control for hand-make
|
||||||
- It will try to bypass any obstacles(planets, stars or dark-fog hives) on the way
|
* Auto navigation on sailings
|
||||||
- Furthermore, you can set a shortcut key in the system options window, which is used to toggle `Auto-cruise` that enables flying to targeted planets fully automatically.
|
* It keeps Icarus on course to the target planet
|
||||||
- Auto-cruise will start when you select a planet as target
|
* It will try to bypass any obstacles(planets, stars or dark-fog hives) on the way
|
||||||
- It will use warper to fly to the target planet if the planet is too far away, the range can be configured.
|
* Furthermore, you can set a shortcut key in the system options window, which is used to toggle `Auto-cruise` that enables flying to targeted planets fully automatically.
|
||||||
- It will speed down when approaching the target planet, to avoid overshooting
|
* Auto-cruise will start when you select a planet as target
|
||||||
+ Dyson Sphere
|
* It will use warper to fly to the target planet if the planet is too far away, the range can be configured.
|
||||||
- Stop ejectors when available nodes are all filled up
|
* It will speed down when approaching the target planet, to avoid overshooting
|
||||||
- Construct only structure points but frames
|
* Dyson Sphere
|
||||||
- Re-initialize Dyson Spheres
|
* Stop ejectors when available nodes are all filled up
|
||||||
- Quick dismantle Dyson Shells
|
* Construct only structure points but frames
|
||||||
- Dyson Sphere "Auto Fast Build" speed multiplier
|
* Re-initialize Dyson Spheres
|
||||||
- Note: this only applies to `Dyson Sphere "Auto Fast Build"` in sandbox mode
|
* Quick dismantle Dyson Shells
|
||||||
+ Tech
|
* Dyson Sphere "Auto Fast Build" speed multiplier
|
||||||
- Restore upgrades of `Sorter Cargo Stacking` on panel
|
* Note: this only applies to `Dyson Sphere "Auto Fast Build"` in sandbox mode
|
||||||
- Set `Sorter Cargo Stacking` to unresearched state
|
* Tech
|
||||||
- Buy out techs with their prerequisites
|
* Restore upgrades of `Sorter Cargo Stacking` on panel
|
||||||
- This enables batch buying out techs with their prerequisites. Buy-out button is shown for all locked techs/upgrads.
|
* Set `Sorter Cargo Stacking` to unresearched state
|
||||||
+ Combat
|
* Buy out techs with their prerequisites
|
||||||
- Open Dark Fog Communicator anywhere
|
* This enables batch buying out techs with their prerequisites. Buy-out button is shown for all locked techs/upgrads.
|
||||||
|
* Combat
|
||||||
|
* Open Dark Fog Communicator anywhere
|
||||||
|
* UI
|
||||||
|
* Embedded [Planet Vein Untilization](https://thunderstore.io/c/dyson-sphere-program/p/testpushpleaseignore/Planet_Vein_Utilization/) due to its lack of maintainance, with minor bug fixes.
|
||||||
|
* Shortcut keys for showing stars' name
|
||||||
|
* Add a shortcut key to always show all star names in starmap when holding, default is `Alt`
|
||||||
|
* Add a shortcut key to toggle between three star name display states in starmap: `Original state`, `Show all names`, `Hide all names`, default is `Tab`, will restore to original state when closing starmap
|
||||||
|
* Starmap view:
|
||||||
|
* Add a star name filter, you can filter displayed star names by ores or planet types now.
|
||||||
|
* Add a dropdown box to show all stars' distance and/or planet count.
|
||||||
|
* Show top players in milkyway
|
||||||
|
* The button is available on top-left corner of Milkyway View
|
||||||
|
* Show recent milkyway upload results
|
||||||
|
* The button is on UXAssist `General` tab.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
* Please upgrade `BepInEx` 5.4.21 or later if using with [BlueprintTweaks](https://dsp.thunderstore.io/package/kremnev8/BlueprintTweaks/) to avoid possible conflicts.
|
* Please upgrade `BepInEx` 5.4.21 or later if using with [BlueprintTweaks](https://dsp.thunderstore.io/package/kremnev8/BlueprintTweaks/) to avoid possible conflicts.
|
||||||
+ You can download `BepInEx` [here](https://github.com/bepinex/bepinex/releases/latest)(choose x64 edition).
|
* You can download [BepInEx here](https://github.com/bepinex/bepinex/releases/latest)(choose x64 edition).
|
||||||
+ If using with r2modman, you can upgrade `BepInEx` by clicking `Settings` -> `Browse profile folder`, then extract downloaded zip to the folder and overwrite existing files.
|
* If using with r2modman, you can upgrade `BepInEx` by clicking `Settings` -> `Browse profile folder`, then extract downloaded zip to the folder and overwrite existing files.
|
||||||
|
|
||||||
## CREDITS
|
## CREDITS
|
||||||
|
|
||||||
@@ -141,137 +156,163 @@
|
|||||||
* [LSTM](https://github.com/hetima/DSP_LSTM) & [PlanetFinder](https://github.com/hetima/DSP_PlanetFinder): UI implementations
|
* [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
|
* [OffGridConstruction](https://github.com/Velociraptor115-DSPModding/OffGridConstruction): Off-grid building & stepped rotation implementations
|
||||||
* [CruiseAssist](https://dsp.thunderstore.io/package/tanu/CruiseAssist/) and its extension [AutoPilot](https://dsp.thunderstore.io/package/tanu/AutoPilot/): `Auto navigation on sailings` and `Auto-cruise` implementations
|
* [CruiseAssist](https://dsp.thunderstore.io/package/tanu/CruiseAssist/) and its extension [AutoPilot](https://dsp.thunderstore.io/package/tanu/AutoPilot/): `Auto navigation on sailings` and `Auto-cruise` implementations
|
||||||
|
* [Planet Vein Untilization](https://thunderstore.io/c/dyson-sphere-program/p/testpushpleaseignore/Planet_Vein_Utilization/)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>中文读我</summary>
|
||||||
|
|
||||||
|
***一些提升用户体验的功能和补丁***
|
||||||
|
|
||||||
|
## Bug反馈
|
||||||
|
|
||||||
|
* QQ群:372754090
|
||||||
|
|
||||||
## 使用说明
|
## 使用说明
|
||||||
|
|
||||||
* 按 `` Alt+`(反引号) `` 键呼出主面板,可以在面板上修改快捷键。
|
* 按 `` Alt+`(反引号) `` 键呼出主面板,可以在面板上修改快捷键。
|
||||||
* 标题界面和行星小地图旁也有按钮呼出主面板。
|
* 标题界面和行星小地图旁也有按钮呼出主面板。
|
||||||
* 补丁:
|
* 补丁:
|
||||||
+ 更严格的建造菜单热键检测,因此在按住Ctrl/Alt/Shift时不再会触发建造热键(0~9, F1~F10, X, U)
|
* 更严格的建造菜单热键检测,因此在按住Ctrl/Alt/Shift时不再会触发建造热键(0~9, F1~F10, X, U)
|
||||||
+ 修复了`矿物利用`升级到8000级以上时弹出警告的bug
|
* 修复了`矿物利用`升级到8000级以上时弹出警告的bug
|
||||||
+ 保存蓝图前对建筑进行排序,以减少生成的蓝图数据大小
|
* 保存蓝图前对建筑进行排序,以减少生成的蓝图数据大小
|
||||||
+ 将元数据提取的最大数量增加到20000(原来为2000)
|
* 将元数据提取的最大数量增加到20000(原来为2000)
|
||||||
+ 将玩家指令队列的容量增加到128(原来为16)
|
* 将玩家指令队列的容量增加到128(原来为16)
|
||||||
+ 在星图视图中启用`隐藏UI`功能(默认按键为`F11`)
|
* 在星图视图中启用`隐藏UI`功能(默认按键为`F11`)
|
||||||
+ 如果使用mod管理器(`Thunderstore Mod Manager`或`r2modman`)启动游戏,在游戏窗口标题中追加mod配置档案名
|
* 如果使用mod管理器(`Thunderstore Mod Manager`或`r2modman`)启动游戏,在游戏窗口标题中追加mod配置档案名
|
||||||
* 功能:
|
* 功能:
|
||||||
+ 通用
|
* 通用
|
||||||
- 可调整游戏窗口大小(可最大化和拖动边框)
|
* 可调整游戏窗口大小(可最大化和拖动边框)
|
||||||
- 记住上次退出时的窗口位置和大小
|
* 记住上次退出时的窗口位置和大小
|
||||||
- 在加载和平模式存档时将其转换为战斗模式
|
* 在加载和平模式存档时将其转换为战斗模式
|
||||||
- 放大鼠标指针
|
* 基于mod管理器配置档案名的存档文件夹
|
||||||
- 注意:这将启用软件指针模式,可能会在CPU负载较重时导致鼠标移动延迟
|
* 存档文件会存储在`Save\<ProfileName>`文件夹中
|
||||||
- 基于mod管理器配置档案名的存档文件夹
|
* 如果匹配默认配置档案名则使用原始存档位置
|
||||||
- 存档文件会存储在`Save\<ProfileName>`文件夹中
|
* 基于mod管理器配置档案名的选项文件
|
||||||
- 如果匹配默认配置档案名则使用原始存档位置
|
* 选项文件存储为`Options\<ProfileName>.xml`
|
||||||
- 基于mod管理器配置档案名的选项文件
|
* 逻辑帧倍率
|
||||||
- 选项文件存储为`Options\<ProfileName>.xml`
|
* 这将改变游戏运行速度,最慢0.1倍,最快10倍
|
||||||
- 逻辑帧倍率
|
* 设置了一对快捷键(`-`和`+`),可以-/+0.5倍改变逻辑帧倍率
|
||||||
- 这将改变游戏运行速度,最慢0.1倍,最快10倍
|
* 注意:
|
||||||
- 设置了一对快捷键(`-`和`+`),可以-/+0.5倍改变逻辑帧倍率
|
* 高逻辑帧倍率不能保证稳定性,特别是在工厂负载较重时
|
||||||
- 注意:
|
* 这不会影响一些游戏动画
|
||||||
- 高逻辑帧倍率不能保证稳定性,特别是在工厂负载较重时
|
* 当在`Auxilaryfunction`mod中设置游戏速度时,此功能将被禁用
|
||||||
- 这不会影响一些游戏动画
|
* 当安装了`BulletTime`mod时,此功能将被隐藏,但会对`BulletTime`的速度控制打补丁,使其最大速度变为10倍
|
||||||
- 当在`Auxilaryfunction`mod中设置游戏速度时,此功能将被禁用
|
* 设置进程优先级
|
||||||
- 当安装了`BulletTime`mod时,此功能将被隐藏,但会对`BulletTime`的速度控制打补丁,使其最大速度变为10倍
|
* 将元数据提取的最大数量增加到20000(原来为2000)
|
||||||
- 设置进程优先级
|
* 将玩家指令队列的容量增加到128(原来为16)
|
||||||
- 设置使用的CPU线程
|
* 工厂
|
||||||
- 将元数据提取的最大数量增加到20000(原来为2000)
|
* 夜间日光灯
|
||||||
- 将玩家指令队列的容量增加到128(原来为16)
|
* 移除部分不影响游戏逻辑的建造条件
|
||||||
+ 行星/工厂
|
* 范围升级和拆除的最大区域扩大(最大30x30)
|
||||||
- 夜间日光灯
|
* 范围铺设地基的最大区域扩大(最大30x30)
|
||||||
- 移除部分不影响游戏逻辑的建造条件
|
* 脱离网格建造以及小角度旋转
|
||||||
- 范围升级和拆除的最大区域扩大(最大30x30)
|
* 切割传送带
|
||||||
- 范围铺设地基的最大区域扩大(最大30x30)
|
* 按快捷键切割光标位置的传送带
|
||||||
- 脱离网格建造以及小角度旋转
|
* 默认快捷键是Alt+X,可以在系统选项面板中设置
|
||||||
- 切割传送带
|
* 在流速计中将堆叠物品视为单个物品
|
||||||
- 按快捷键切割光标位置的传送带
|
* 快速建造和拆除堆叠研究站/储物仓/储液罐
|
||||||
- 默认快捷键是Alt+X,可以在系统选项面板中设置
|
* 储液罐快速注入和抽取液体
|
||||||
- 在流速计中将堆叠物品视为单个物品
|
* 你可以设置储液罐操作速度的倍率
|
||||||
- 物流塔存储数量限制控制改进
|
* 影响手动注入和抽取,以及从储液罐上层传输到下层的速度
|
||||||
- 当升级`运输机舱扩容`时,不会对各种物流塔的存储限制按比例提升,除非设置为最大允许容量。
|
* 保护矿脉不会耗尽
|
||||||
- 你可以使用方向键微调物流塔存储限制
|
* 默认矿脉数量保护在100,采油速保护在1.0/s,你可以在配置文件中自行设置。
|
||||||
- 快速建造和拆除堆叠研究站/储物仓/储液罐
|
* 当达到保护值时,矿脉和油井将不再被开采。
|
||||||
- 储液罐快速注入和抽取液体
|
* 关闭此功能以恢复开采,一般是当你在`矿物利用`上有足够的等级时。
|
||||||
- 你可以设置储液罐操作速度的倍率
|
* 不渲染工厂建筑实体(除了传送带和分拣器)
|
||||||
- 影响手动注入和抽取,以及从储液罐上层传输到下层的速度
|
* 这也使玩家可以点穿工厂实体直接点到传送带和分拣器
|
||||||
- 保护矿脉不会耗尽
|
* 拖动建造电线杆时自动使用最大连接距离间隔
|
||||||
- 默认矿脉数量保护在100,采油速保护在1.0/s,你可以在配置文件中自行设置。
|
* 自动建造
|
||||||
- 当达到保护值时,矿脉和油井将不再被开采。
|
* 自动飞向待建造的建筑
|
||||||
- 关闭此功能以恢复开采,一般是当你在`矿物利用`上有足够的等级时。
|
* 拆除蓝图选中的建筑
|
||||||
- 不渲染工厂建筑实体(除了传送带和分拣器)
|
* 在蓝图复制模式下按快捷键拆除选中的建筑
|
||||||
- 这也使玩家可以点穿工厂实体直接点到传送带和分拣器
|
* 默认快捷键是Ctrl+X,可以在系统选项面板中设置
|
||||||
- 拖动建造电线杆时自动使用最大连接距离间隔
|
* 初始化本行星(不重置矿脉)
|
||||||
- 允许物流塔和大型采矿机物品溢出
|
* 有3个可返还特定物品的选项
|
||||||
- 当尝试塞入手中物品时允许溢出
|
* 快速拆除所有建筑(不掉落)
|
||||||
- 允许`物流塔存储数量限制控制改进`超过科技容量限制
|
* 快速建造轨道采集器
|
||||||
- 在加载游戏时移除物流塔容量限制检查
|
* 用于自动购买黑雾物品的传送带信号
|
||||||
- 物流控制面板改进
|
* 在信号面板上添加了6个传送带信号,可以用于自动购买黑雾道具。
|
||||||
- 打开面板时自动将鼠标指向物品设为筛选条件
|
* 生成的物品堆叠数为4。
|
||||||
- 在控制面板物流塔列表中右键点击物品图标快速设置为筛选条件
|
* 兑换比率遵循原始游戏设计,即:
|
||||||
- 物流运输站实时信息面板
|
* 1个元宇宙 = 20个黑雾矩阵
|
||||||
- 注意:如果你启用了`Auxilaryfunction`中的`展示物流站信息`,此功能将被隐藏
|
* 1个元宇宙 = 60个能量碎片
|
||||||
- 拆除蓝图选中的建筑
|
* 1个元宇宙 = 30个硅基神经元
|
||||||
- 在蓝图复制模式下按快捷键拆除选中的建筑
|
* 1个元宇宙 = 30个负熵奇点
|
||||||
- 默认快捷键是Ctrl+X,可以在系统选项面板中设置
|
* 1个元宇宙 = 30个物质重组器
|
||||||
- 初始化本行星(不重置矿脉)
|
* 1个元宇宙 = 10个核心素
|
||||||
- 快速拆除所有建筑(不掉落)
|
* 调整建筑输入缓冲
|
||||||
- 快速建造轨道采集器
|
* 工厂配方计算公式,在`工厂配方缓冲时间倍率秒数x每秒需要的原料数量`和`工厂配方缓冲最小倍率x每生产一次配方需要的原料数量`中取更大的那个值
|
||||||
- 用于自动购买黑雾物品的传送带信号
|
* `工厂配方缓冲时间倍率(秒)`:范围2-10,默认为4(同游戏)
|
||||||
- 在信号面板上添加了6个传送带信号,可以用于自动购买黑雾道具。
|
* `工厂配方缓冲最小倍率`:范围2-10,默认为2(同游戏)
|
||||||
- 生成的物品堆叠数为4。
|
* 研究站矩阵合成模式计算公式,默认缓存`研究站矩阵合成模式缓存数量`个,当使用自演化研究站时,如果配方的原始生产时间不大于9秒,则增加`自演化研究站矩阵额外缓冲数量`*(`研究站速度倍率`-1)
|
||||||
- 兑换比率遵循原始游戏设计,即:
|
* `研究站矩阵合成模式缓存数量`:范围2-20,默认为6(同游戏)
|
||||||
- 1个元宇宙 = 20个黑雾矩阵
|
* `自演化研究站矩阵额外缓冲数量`:范围1-10,默认为3(同游戏)
|
||||||
- 1个元宇宙 = 60个能量碎片
|
* `研究站科研模式缓存数量`:范围2-20,默认为10(同游戏)
|
||||||
- 1个元宇宙 = 30个硅基神经元
|
* `射线接收器透镜缓冲数量`:范围1-20,默认为1(游戏默认为20)
|
||||||
- 1个元宇宙 = 30个负熵奇点
|
* `弹射太阳帆缓冲区数量`:范围5-400(步进值为5),默认值为20(与游戏相同)
|
||||||
- 1个元宇宙 = 30个物质重组器
|
* `发射井火箭缓冲区数量`:范围1-20,默认值为20(与游戏相同)
|
||||||
- 1个元宇宙 = 10个核心素
|
* 物流
|
||||||
- 调整建筑输入缓冲
|
* 物流塔存储数量限制控制改进
|
||||||
- 工厂配方计算公式,在`工厂配方缓冲时间倍率秒数x每秒需要的原料数量`和`工厂配方缓冲最小倍率x每生产一次配方需要的原料数量`中取更大的那个值
|
* 当升级`运输机舱扩容`时,不会对各种物流塔的存储限制按比例提升,除非设置为最大允许容量或者已经超过升级后的最大容量。
|
||||||
- `工厂配方缓冲时间倍率(秒)`:范围2-10,默认为4(同游戏)
|
* 你可以使用方向键微调物流塔存储限制
|
||||||
- `工厂配方缓冲最小倍率`:范围2-10,默认为2(同游戏)
|
* 物流控制面板改进
|
||||||
- 研究站矩阵合成模式计算公式,默认缓存`研究站矩阵合成模式缓存数量`个,当使用自演化研究站时,如果配方的原始生产时间不大于9秒,则增加`自演化研究站矩阵额外缓冲数量`*(`研究站速度倍率`-1)
|
* 打开面板时自动将鼠标指向物品设为筛选条件
|
||||||
- `研究站矩阵合成模式缓存数量`:范围2-20,默认为6(同游戏)
|
* 在控制面板物流塔列表中右键点击物品图标快速设置为筛选条件
|
||||||
- `自演化研究站矩阵额外缓冲数量`:范围1-10,默认为3(同游戏)
|
* 允许物流塔和大型采矿机物品溢出
|
||||||
- `研究站科研模式缓存数量`:范围2-20,默认为10(同游戏)
|
* 当尝试塞入手中物品时允许溢出
|
||||||
- `射线接收器透镜缓冲数量`:范围1-20,默认为1(游戏默认为20)
|
* 允许`物流塔存储数量限制控制改进`超过科技容量限制
|
||||||
+ 玩家/机甲
|
* 在加载游戏时移除物流塔容量限制检查
|
||||||
- 无限交互距离
|
* 物流运输站实时信息面板
|
||||||
- 移除建造数量和范围限制
|
* 注意:如果你启用了`Auxilaryfunction`中的`展示物流站信息`,此功能将被隐藏
|
||||||
- 在行星视图中允许玩家操作
|
* 自动配置物流站
|
||||||
- 隐藏沙土数量变动的提示
|
* 自动配置的建筑包括:物流配送器、行星物流站、星际物流站、高级采矿机
|
||||||
- 手动制造物品的数量控制改进
|
* 玩家/机甲
|
||||||
- 启用显示所有星系名称的快捷键
|
* 无限交互距离
|
||||||
- 新增一个快捷键,按住后始终在星图显示所有星系名称,默认为`Alt`
|
* 移除建造数量和范围限制
|
||||||
- 新增一个快捷键,在星图视图切换三种星系名称显示状态:`原始显示状态`,`显示所有名称`,`隐藏所有名称`,默认为`Tab`,关闭星图时会恢复到原始状态
|
* 在行星视图中允许玩家操作
|
||||||
- 航行时自动导航
|
* 隐藏沙土数量变动的提示
|
||||||
- 它会保持伊卡洛斯飞向目标星球
|
* 手动制造物品的数量控制改进
|
||||||
- 它会尝试绕过途中的任何障碍物(行星、恒星或黑雾巢穴)
|
* 航行时自动导航
|
||||||
- 此外,可以在系统选项窗口中设置快捷键,用于切换`自动巡航`,实现完全自动化的飞行至目标星球。
|
* 它会保持伊卡洛斯飞向目标星球
|
||||||
- 当你选择目标星球后,自动巡航就会开始
|
* 它会尝试绕过途中的任何障碍物(行星、恒星或黑雾巢穴)
|
||||||
- 如果目标星球距离过远会自动使用曲速(超过5AU),你可以在面板上更改这个值。
|
* 此外,可以在系统选项窗口中设置快捷键,用于切换`自动巡航`,实现完全自动化的飞行至目标星球。
|
||||||
- 它会在接近目标星球时减速,以避免发生越过目标的情况
|
* 当你选择目标星球后,自动巡航就会开始
|
||||||
+ 戴森球
|
* 如果目标星球距离过远会自动使用曲速(超过5AU),你可以在面板上更改这个值。
|
||||||
- 可用节点全部造完时停止弹射
|
* 它会在接近目标星球时减速,以避免发生越过目标的情况
|
||||||
- 只建造节点不建造框架
|
* 戴森球
|
||||||
- 初始化戴森球
|
* 可用节点全部造完时停止弹射
|
||||||
- 快速拆除戴森壳
|
* 只建造节点不建造框架
|
||||||
- 戴森球自动快速建造速度倍率
|
* 初始化戴森球
|
||||||
- 注意:这仅适用于沙盒模式下的`戴森球自动快速建造`功能
|
* 快速拆除戴森壳
|
||||||
+ 科研
|
* 戴森球自动快速建造速度倍率
|
||||||
- 在升级面板上恢复`分拣器货物堆叠`的升级
|
* 注意:这仅适用于沙盒模式下的`戴森球自动快速建造`功能
|
||||||
- 将`分拣器货物堆叠`设为未研究状态
|
* 科研
|
||||||
- 买断科技也同时买断所有前置科技
|
* 在升级面板上恢复`分拣器货物堆叠`的升级
|
||||||
- 这使得可以批量买断科技及其所有前置科技。所有未解锁的科技/升级都会显示买断按钮。
|
* 将`分拣器货物堆叠`设为未研究状态
|
||||||
+ 战斗
|
* 买断科技也同时买断所有前置科技
|
||||||
- 在任意位置打开黑雾通讯器
|
* 这使得可以批量买断科技及其所有前置科技。所有未解锁的科技/升级都会显示买断按钮。
|
||||||
|
* 战斗
|
||||||
|
* 在任意位置打开黑雾通讯器
|
||||||
|
* UI
|
||||||
|
* 启用显示所有星系名称的快捷键
|
||||||
|
* 新增一个快捷键,按住后始终在星图显示所有星系名称,默认为`Alt`
|
||||||
|
* 新增一个快捷键,在星图视图切换三种星系名称显示状态:`原始显示状态`,`显示所有名称`,`隐藏所有名称`,默认为`Tab`,关闭星图时会恢复到原始状态
|
||||||
|
* 星图:
|
||||||
|
* 添加星系名过滤器,现在可以按矿物或行星类型过滤显示的星系名
|
||||||
|
* 添加了一个下拉框用以切换显示所有星系的距离和/或行星数量
|
||||||
|
* 由于原MOD缺乏维护,整合内置了[Planet Vein Untilization](https://thunderstore.io/c/dyson-sphere-program/p/testpushpleaseignore/Planet_Vein_Utilization/),并修复了一些小错误。
|
||||||
|
* 显示银河系发电量排行
|
||||||
|
* 按钮位于银河视图左上角
|
||||||
|
* 显示最近银河系上传结果
|
||||||
|
* 按钮在UXAssist的`常规`标签页内
|
||||||
|
|
||||||
## 注意事项
|
## 注意事项
|
||||||
|
|
||||||
* 如果和[BlueprintTweaks](https://dsp.thunderstore.io/package/kremnev8/BlueprintTweaks/)一起使用,请升级`BepInEx`到5.4.21或更高版本,以避免可能的冲突。
|
* 如果和[BlueprintTweaks](https://dsp.thunderstore.io/package/kremnev8/BlueprintTweaks/)一起使用,请升级`BepInEx`到5.4.21或更高版本,以避免可能的冲突。
|
||||||
+ 你可以在[这里](https://github.com/bepinex/bepinex/releases/latest)(选择x64版本)下载`BepInEx`。
|
* 你可以在[这里](https://github.com/bepinex/bepinex/releases/latest)(选择x64版本)下载`BepInEx`。
|
||||||
+ 如果使用r2modman,你可以点击`Settings` -> `Browse profile folder`,然后将下载的zip解压到该文件夹并覆盖现有文件。
|
* 如果使用r2modman,你可以点击`Settings` -> `Browse profile folder`,然后将下载的zip解压到该文件夹并覆盖现有文件。
|
||||||
|
|
||||||
## 鸣谢
|
## 鸣谢
|
||||||
|
|
||||||
@@ -279,4 +320,7 @@
|
|||||||
* [BepInEx](https://bepinex.dev/): 基础模组框架
|
* [BepInEx](https://bepinex.dev/): 基础模组框架
|
||||||
* [LSTM](https://github.com/hetima/DSP_LSTM) & [PlanetFinder](https://github.com/hetima/DSP_PlanetFinder): UI实现
|
* [LSTM](https://github.com/hetima/DSP_LSTM) & [PlanetFinder](https://github.com/hetima/DSP_PlanetFinder): UI实现
|
||||||
* [OffGridConstruction](https://github.com/Velociraptor115-DSPModding/OffGridConstruction): 脱离网格建造以及小角度旋转的实现
|
* [OffGridConstruction](https://github.com/Velociraptor115-DSPModding/OffGridConstruction): 脱离网格建造以及小角度旋转的实现
|
||||||
* [CruiseAssist](https://dsp.thunderstore.io/package/tanu/CruiseAssist/)及其扩展[AutoPilot](https://dsp.thunderstore.io/package/tanu/AutoPilot/): `航行时自动导航`和`自动巡航`的实现
|
* [CruiseAssist](https://dsp.thunderstore.io/package/tanu/CruiseAssist/)及其扩展[AutoPilot](https://dsp.thunderstore.io/package/tanu/AutoPilot/): `航行时自动导航`和`自动巡航`的实现
|
||||||
|
* [Planet Vein Untilization](https://thunderstore.io/c/dyson-sphere-program/p/testpushpleaseignore/Planet_Vein_Utilization/)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|||||||
266
UXAssist/UI/MyCheckButton.cs
Normal file
266
UXAssist/UI/MyCheckButton.cs
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
using System;
|
||||||
|
using BepInEx.Configuration;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace UXAssist.UI;
|
||||||
|
|
||||||
|
public class MyCheckButton : MonoBehaviour
|
||||||
|
{
|
||||||
|
public RectTransform rectTrans;
|
||||||
|
public UIButton uiButton;
|
||||||
|
public Image icon;
|
||||||
|
public Text labelText;
|
||||||
|
public event Action OnChecked;
|
||||||
|
private bool _checked;
|
||||||
|
private float _iconWidth = 28f;
|
||||||
|
|
||||||
|
private static GameObject _baseObject;
|
||||||
|
|
||||||
|
private static Color openMouseOverColor;
|
||||||
|
private static Color openPressColor;
|
||||||
|
private static Color openNormalColor;
|
||||||
|
private static Color closeMouseOverColor;
|
||||||
|
private static Color closePressColor;
|
||||||
|
private static Color closeNormalColor;
|
||||||
|
|
||||||
|
public static void InitBaseObject()
|
||||||
|
{
|
||||||
|
if (_baseObject) return;
|
||||||
|
var tankWindow = UIRoot.instance.uiGame.tankWindow;
|
||||||
|
openMouseOverColor = tankWindow.openMouseOverColor;
|
||||||
|
openPressColor = tankWindow.openPressColor;
|
||||||
|
openNormalColor = tankWindow.openNormalColor;
|
||||||
|
closeMouseOverColor = tankWindow.closeMouseOverColor;
|
||||||
|
closePressColor = tankWindow.closePressColor;
|
||||||
|
closeNormalColor = /*tankWindow.closeNormalColor*/ new Color(0.6557f, 0.9145f, 1f, 0.4f);
|
||||||
|
|
||||||
|
var go = Instantiate(UIRoot.instance.uiGame.beltWindow.reverseButton.gameObject);
|
||||||
|
go.name = "my-checkbutton";
|
||||||
|
go.SetActive(false);
|
||||||
|
var comp = go.transform.Find("text");
|
||||||
|
if (comp)
|
||||||
|
{
|
||||||
|
var txt = comp.GetComponent<Text>();
|
||||||
|
if (txt)
|
||||||
|
{
|
||||||
|
txt.text = "";
|
||||||
|
txt.alignment = TextAnchor.MiddleCenter;
|
||||||
|
txt.rectTransform.anchorMax = new Vector2(0f, 1f);
|
||||||
|
txt.rectTransform.anchorMin = new Vector2(0f, 1f);
|
||||||
|
txt.rectTransform.pivot = new Vector2(0f, 1f);
|
||||||
|
txt.rectTransform.localPosition = new Vector3(0f, 0f, 0f);
|
||||||
|
}
|
||||||
|
var localizer = comp.GetComponent<Localizer>();
|
||||||
|
if (localizer) DestroyImmediate(localizer);
|
||||||
|
}
|
||||||
|
_baseObject = go;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnDestroy()
|
||||||
|
{
|
||||||
|
if (_config != null) _config.SettingChanged -= _configChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MyCheckButton CreateCheckButton(float x, float y, RectTransform parent, ConfigEntry<bool> config, string label = "", int fontSize = 15)
|
||||||
|
{
|
||||||
|
return CreateCheckButton(x, y, parent, config.Value, label, fontSize).WithConfigEntry(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MyCheckButton CreateCheckButton(float x, float y, RectTransform parent, bool check, string label = "", int fontSize = 15)
|
||||||
|
{
|
||||||
|
return CreateCheckButton(x, y, parent, fontSize).WithCheck(check).WithLabelText(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MyCheckButton CreateCheckButton(float x, float y, RectTransform parent, int fontSize = 15)
|
||||||
|
{
|
||||||
|
var go = Instantiate(_baseObject);
|
||||||
|
go.name = "my-checkbutton";
|
||||||
|
go.SetActive(true);
|
||||||
|
var cb = go.AddComponent<MyCheckButton>();
|
||||||
|
var rect = Util.NormalizeRectWithTopLeft(cb, x, y, parent);
|
||||||
|
|
||||||
|
cb.rectTrans = rect;
|
||||||
|
cb.uiButton = go.GetComponent<UIButton>();
|
||||||
|
|
||||||
|
var child = go.transform.Find("text");
|
||||||
|
if (child != null)
|
||||||
|
{
|
||||||
|
cb.labelText = child.GetComponent<Text>();
|
||||||
|
if (cb.labelText)
|
||||||
|
{
|
||||||
|
cb.labelText.text = "";
|
||||||
|
cb.labelText.fontSize = fontSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cb._iconWidth = Mathf.Min(cb._iconWidth > 0f ? cb._iconWidth : 32f, rect.sizeDelta.y);
|
||||||
|
cb.UpdateCheckColor();
|
||||||
|
cb.uiButton.onClick += cb.OnClick;
|
||||||
|
cb.UpdateSize();
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Checked
|
||||||
|
{
|
||||||
|
get => _checked;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_checked = value;
|
||||||
|
UpdateCheckColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCheckedWithEvent(bool check)
|
||||||
|
{
|
||||||
|
if (_checked == check) return;
|
||||||
|
Checked = check;
|
||||||
|
OnChecked?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLabelText(string val)
|
||||||
|
{
|
||||||
|
if (labelText != null)
|
||||||
|
{
|
||||||
|
labelText.text = val.Translate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private EventHandler _configChanged;
|
||||||
|
private Action _checkedChanged;
|
||||||
|
private ConfigEntry<bool> _config;
|
||||||
|
public void SetConfigEntry(ConfigEntry<bool> config)
|
||||||
|
{
|
||||||
|
if (_checkedChanged != null) OnChecked -= _checkedChanged;
|
||||||
|
if (_configChanged != null) config.SettingChanged -= _configChanged;
|
||||||
|
|
||||||
|
_config = config;
|
||||||
|
_checkedChanged = () => config.Value = !config.Value;
|
||||||
|
OnChecked += _checkedChanged;
|
||||||
|
_configChanged = (_, _) => Checked = config.Value;
|
||||||
|
config.SettingChanged += _configChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCheckButton WithLabelText(string val)
|
||||||
|
{
|
||||||
|
SetLabelText(val);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateSize()
|
||||||
|
{
|
||||||
|
var width = rectTrans.sizeDelta.x;
|
||||||
|
var height = rectTrans.sizeDelta.y;
|
||||||
|
labelText.rectTransform.localPosition = new Vector3(icon != null ? _iconWidth : 0f, 0f, 0f);
|
||||||
|
labelText.rectTransform.sizeDelta = new Vector2(icon != null ? width - _iconWidth : width, height);
|
||||||
|
if (icon != null)
|
||||||
|
{
|
||||||
|
icon.rectTransform.sizeDelta = new Vector2(_iconWidth, _iconWidth);
|
||||||
|
icon.rectTransform.localPosition = new Vector3(0f, -height * 0.5f, 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCheckButton WithSize(float width, float height)
|
||||||
|
{
|
||||||
|
rectTrans.sizeDelta = new Vector2(width, height);
|
||||||
|
if (height < _iconWidth) _iconWidth = height;
|
||||||
|
UpdateSize();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCheckButton WithIconWidth(float width)
|
||||||
|
{
|
||||||
|
if (_iconWidth == width) return this;
|
||||||
|
var height = rectTrans.sizeDelta.y;
|
||||||
|
if (width > height)
|
||||||
|
{
|
||||||
|
width = height;
|
||||||
|
if (_iconWidth == width) return this;
|
||||||
|
}
|
||||||
|
_iconWidth = width;
|
||||||
|
if (icon != null) UpdateSize();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCheckButton WithIcon(Sprite sprite = null)
|
||||||
|
{
|
||||||
|
if (icon == null)
|
||||||
|
{
|
||||||
|
var iconGo = new GameObject("icon");
|
||||||
|
var rect = iconGo.AddComponent<RectTransform>();
|
||||||
|
(icon = iconGo.AddComponent<Image>()).sprite = sprite;
|
||||||
|
iconGo.transform.SetParent(rectTrans);
|
||||||
|
rect.sizeDelta = new Vector2(_iconWidth, _iconWidth);
|
||||||
|
rect.localScale = new Vector3(1f, 1f, 1f);
|
||||||
|
rect.anchorMax = new Vector2(0f, 1f);
|
||||||
|
rect.anchorMin = new Vector2(0f, 1f);
|
||||||
|
rect.pivot = new Vector2(0f, 0.5f);
|
||||||
|
var height = rectTrans.sizeDelta.y;
|
||||||
|
rect.localPosition = new Vector3(0f, -height * 0.5f, 0f);
|
||||||
|
iconGo.SetActive(sprite != null);
|
||||||
|
UpdateSize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetIcon(sprite);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCheckButton WithTip(string tip, float delay = 1f)
|
||||||
|
{
|
||||||
|
uiButton.tips.type = UIButton.ItemTipType.Other;
|
||||||
|
uiButton.tips.topLevel = true;
|
||||||
|
uiButton.tips.tipTitle = tip;
|
||||||
|
uiButton.tips.tipText = null;
|
||||||
|
uiButton.tips.delay = delay;
|
||||||
|
uiButton.tips.corner = 2;
|
||||||
|
uiButton.UpdateTip();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetIcon(Sprite sprite = null)
|
||||||
|
{
|
||||||
|
icon.sprite = sprite;
|
||||||
|
icon.gameObject.SetActive(sprite != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCheckButton WithCheck(bool check)
|
||||||
|
{
|
||||||
|
Checked = check;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCheckButton WithConfigEntry(ConfigEntry<bool> config)
|
||||||
|
{
|
||||||
|
SetConfigEntry(config);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClick(int obj)
|
||||||
|
{
|
||||||
|
_checked = !_checked;
|
||||||
|
UpdateCheckColor();
|
||||||
|
OnChecked?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Width => rectTrans.sizeDelta.x + labelText.rectTransform.sizeDelta.x;
|
||||||
|
public float Height => Math.Max(rectTrans.sizeDelta.y, labelText.rectTransform.sizeDelta.y);
|
||||||
|
|
||||||
|
private void UpdateCheckColor()
|
||||||
|
{
|
||||||
|
if (_checked)
|
||||||
|
{
|
||||||
|
uiButton.transitions[0].mouseoverColor = openMouseOverColor;
|
||||||
|
uiButton.transitions[0].pressedColor = openPressColor;
|
||||||
|
uiButton.transitions[0].normalColor = openNormalColor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uiButton.transitions[0].mouseoverColor = closeMouseOverColor;
|
||||||
|
uiButton.transitions[0].pressedColor = closePressColor;
|
||||||
|
uiButton.transitions[0].normalColor = closeNormalColor;
|
||||||
|
}
|
||||||
|
uiButton.RefreshTransitionsImmediately();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,9 +18,9 @@ public class MyCheckBox : MonoBehaviour
|
|||||||
|
|
||||||
private static GameObject _baseObject;
|
private static GameObject _baseObject;
|
||||||
|
|
||||||
private static readonly Color BoxColor = new Color(1f, 1f, 1f, 100f / 255f);
|
private static readonly Color BoxColor = new(1f, 1f, 1f, 100f / 255f);
|
||||||
private static readonly Color CheckColor = new Color(1f, 1f, 1f, 1f);
|
private static readonly Color CheckColor = new(1f, 1f, 1f, 1f);
|
||||||
private static readonly Color TextColor = new Color(178f / 255f, 178f / 255f, 178f / 255f, 168f / 255f);
|
private static readonly Color TextColor = new(178f / 255f, 178f / 255f, 178f / 255f, 168f / 255f);
|
||||||
|
|
||||||
public static void InitBaseObject()
|
public static void InitBaseObject()
|
||||||
{
|
{
|
||||||
@@ -41,7 +41,7 @@ public class MyCheckBox : MonoBehaviour
|
|||||||
|
|
||||||
protected void OnDestroy()
|
protected void OnDestroy()
|
||||||
{
|
{
|
||||||
_config.SettingChanged -= _configChanged;
|
if (_config != null) _config.SettingChanged -= _configChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MyCheckBox CreateCheckBox(float x, float y, RectTransform parent, ConfigEntry<bool> config, string label = "", int fontSize = 15)
|
public static MyCheckBox CreateCheckBox(float x, float y, RectTransform parent, ConfigEntry<bool> config, string label = "", int fontSize = 15)
|
||||||
@@ -66,6 +66,7 @@ public class MyCheckBox : MonoBehaviour
|
|||||||
cb.uiButton = go.GetComponent<UIButton>();
|
cb.uiButton = go.GetComponent<UIButton>();
|
||||||
cb.boxImage = go.transform.GetComponent<Image>();
|
cb.boxImage = go.transform.GetComponent<Image>();
|
||||||
cb.checkImage = go.transform.Find("checked")?.GetComponent<Image>();
|
cb.checkImage = go.transform.Find("checked")?.GetComponent<Image>();
|
||||||
|
Util.NormalizeRectWithTopLeft(cb.checkImage, 0f, 0f);
|
||||||
|
|
||||||
var child = go.transform.Find("text");
|
var child = go.transform.Find("text");
|
||||||
if (child != null)
|
if (child != null)
|
||||||
@@ -151,6 +152,16 @@ public class MyCheckBox : MonoBehaviour
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MyCheckBox WithSmallerBox(float boxSize = 20f)
|
||||||
|
{
|
||||||
|
var oldWidth = rectTrans.sizeDelta.x;
|
||||||
|
rectTrans.sizeDelta = new Vector2(boxSize, boxSize);
|
||||||
|
checkImage.rectTransform.sizeDelta = new Vector2(boxSize, boxSize);
|
||||||
|
labelText.rectTransform.sizeDelta = new Vector2(labelText.rectTransform.sizeDelta.x, boxSize);
|
||||||
|
labelText.rectTransform.localPosition = new Vector3(labelText.rectTransform.localPosition.x + boxSize - oldWidth, labelText.rectTransform.localPosition.y, labelText.rectTransform.localPosition.z);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public MyCheckBox WithEnable(bool on)
|
public MyCheckBox WithEnable(bool on)
|
||||||
{
|
{
|
||||||
SetEnable(on);
|
SetEnable(on);
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ public class MyComboBox : MonoBehaviour
|
|||||||
{
|
{
|
||||||
private RectTransform _rectTrans;
|
private RectTransform _rectTrans;
|
||||||
private UIComboBox _comboBox;
|
private UIComboBox _comboBox;
|
||||||
private Text _text;
|
|
||||||
public Action<int> OnSelChanged;
|
public Action<int> OnSelChanged;
|
||||||
|
|
||||||
private static GameObject _baseObject;
|
private static GameObject _baseObject;
|
||||||
@@ -19,24 +18,12 @@ public class MyComboBox : MonoBehaviour
|
|||||||
{
|
{
|
||||||
if (_baseObject) return;
|
if (_baseObject) return;
|
||||||
var fontSource = UIRoot.instance.uiGame.buildMenu.uxFacilityCheck.transform.Find("text")?.GetComponent<Text>();
|
var fontSource = UIRoot.instance.uiGame.buildMenu.uxFacilityCheck.transform.Find("text")?.GetComponent<Text>();
|
||||||
var go = Instantiate(UIRoot.instance.optionWindow.resolutionComp.transform.parent.gameObject);
|
var go = Instantiate(UIRoot.instance.optionWindow.resolutionComp.gameObject);
|
||||||
go.name = "my-combobox";
|
go.name = "my-combobox";
|
||||||
go.SetActive(false);
|
go.SetActive(false);
|
||||||
|
|
||||||
var txt = go.GetComponent<Text>();
|
|
||||||
if (txt) txt.text = "";
|
|
||||||
if (txt && fontSource)
|
|
||||||
{
|
|
||||||
txt.font = fontSource.font;
|
|
||||||
txt.fontSize = fontSource.fontSize;
|
|
||||||
txt.fontStyle = fontSource.fontStyle;
|
|
||||||
txt.color = new Color(1f, 1f, 1f, 0.6f);
|
|
||||||
}
|
|
||||||
var localizer = go.GetComponent<Localizer>();
|
|
||||||
if (localizer) DestroyImmediate(localizer);
|
|
||||||
|
|
||||||
var rect = (RectTransform)go.transform;
|
var rect = (RectTransform)go.transform;
|
||||||
var cbctrl = rect.transform.Find("ComboBox").GetComponent<UIComboBox>();
|
var cbctrl = rect.GetComponent<UIComboBox>();
|
||||||
foreach (var button in cbctrl.ItemButtons)
|
foreach (var button in cbctrl.ItemButtons)
|
||||||
{
|
{
|
||||||
Destroy(button.gameObject);
|
Destroy(button.gameObject);
|
||||||
@@ -52,7 +39,7 @@ public class MyComboBox : MonoBehaviour
|
|||||||
txtComp.fontSize = fontSource.fontSize;
|
txtComp.fontSize = fontSource.fontSize;
|
||||||
txtComp.fontStyle = fontSource.fontStyle;
|
txtComp.fontStyle = fontSource.fontStyle;
|
||||||
}
|
}
|
||||||
txtComp = cbctrl.transform.Find("Main Button")?.GetComponentInChildren<Text>();
|
txtComp = rect.Find("Main Button/Text")?.GetComponent<Text>();
|
||||||
if (txtComp)
|
if (txtComp)
|
||||||
{
|
{
|
||||||
txtComp.font = fontSource.font;
|
txtComp.font = fontSource.font;
|
||||||
@@ -73,8 +60,7 @@ public class MyComboBox : MonoBehaviour
|
|||||||
var cb = gameObject.AddComponent<MyComboBox>();
|
var cb = gameObject.AddComponent<MyComboBox>();
|
||||||
var rtrans = Util.NormalizeRectWithTopLeft(cb, x, y, parent);
|
var rtrans = Util.NormalizeRectWithTopLeft(cb, x, y, parent);
|
||||||
cb._rectTrans = rtrans;
|
cb._rectTrans = rtrans;
|
||||||
cb._text = gameObject.GetComponent<Text>();
|
var box = rtrans.GetComponent<UIComboBox>();
|
||||||
var box = rtrans.Find("ComboBox").GetComponent<UIComboBox>();
|
|
||||||
cb._comboBox = box;
|
cb._comboBox = box;
|
||||||
box.onItemIndexChange.AddListener(() => { cb.OnSelChanged?.Invoke(box.itemIndex); });
|
box.onItemIndexChange.AddListener(() => { cb.OnSelChanged?.Invoke(box.itemIndex); });
|
||||||
cb.UpdateComboBoxPosition();
|
cb.UpdateComboBoxPosition();
|
||||||
@@ -90,21 +76,11 @@ public class MyComboBox : MonoBehaviour
|
|||||||
private void UpdateComboBoxPosition()
|
private void UpdateComboBoxPosition()
|
||||||
{
|
{
|
||||||
var rtrans = (RectTransform)_comboBox.transform;
|
var rtrans = (RectTransform)_comboBox.transform;
|
||||||
var oldPosition = rtrans.localPosition;
|
_rectTrans.sizeDelta = new Vector2(rtrans.sizeDelta.x, _rectTrans.sizeDelta.y);
|
||||||
var pwidth = _text.preferredWidth;
|
|
||||||
rtrans.localPosition = new Vector3(pwidth + 5f, oldPosition.y, oldPosition.z);
|
|
||||||
_rectTrans.sizeDelta = new Vector2(rtrans.localPosition.x + 5f + rtrans.sizeDelta.x, _rectTrans.sizeDelta.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetPrompt(string prompt)
|
|
||||||
{
|
|
||||||
_text.text = prompt.Translate();
|
|
||||||
UpdateComboBoxPosition();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetFontSize(int size)
|
public void SetFontSize(int size)
|
||||||
{
|
{
|
||||||
_text.fontSize = size;
|
|
||||||
_comboBox.ItemButtons.ForEach(b => b.GetComponentInChildren<Text>().fontSize = size);
|
_comboBox.ItemButtons.ForEach(b => b.GetComponentInChildren<Text>().fontSize = size);
|
||||||
_comboBox.m_ListItemRes.GetComponentInChildren<Text>().fontSize = size;
|
_comboBox.m_ListItemRes.GetComponentInChildren<Text>().fontSize = size;
|
||||||
var txtComp = _comboBox.transform.Find("Main Button")?.GetComponentInChildren<Text>();
|
var txtComp = _comboBox.transform.Find("Main Button")?.GetComponentInChildren<Text>();
|
||||||
@@ -146,12 +122,6 @@ public class MyComboBox : MonoBehaviour
|
|||||||
config.SettingChanged += _configChanged;
|
config.SettingChanged += _configChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MyComboBox WithPrompt(string prompt)
|
|
||||||
{
|
|
||||||
SetPrompt(prompt);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MyComboBox WithFontSize(int size)
|
public MyComboBox WithFontSize(int size)
|
||||||
{
|
{
|
||||||
SetFontSize(size);
|
SetFontSize(size);
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ public class MyConfigWindow : MyWindowWithTabs
|
|||||||
base._OnCreate();
|
base._OnCreate();
|
||||||
_windowTrans = GetComponent<RectTransform>();
|
_windowTrans = GetComponent<RectTransform>();
|
||||||
OnUICreated?.Invoke(this, _windowTrans);
|
OnUICreated?.Invoke(this, _windowTrans);
|
||||||
AutoFitWindowSize();
|
|
||||||
SetCurrentTab(0);
|
SetCurrentTab(0);
|
||||||
OnUpdateUI?.Invoke();
|
OnUpdateUI?.Invoke();
|
||||||
}
|
}
|
||||||
|
|||||||
153
UXAssist/UI/MyCornerComboBox.cs
Normal file
153
UXAssist/UI/MyCornerComboBox.cs
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using BepInEx.Configuration;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace UXAssist.UI;
|
||||||
|
|
||||||
|
public class MyCornerComboBox : MonoBehaviour
|
||||||
|
{
|
||||||
|
private RectTransform _rectTrans;
|
||||||
|
private UIComboBox _comboBox;
|
||||||
|
public Action<int> OnSelChanged;
|
||||||
|
|
||||||
|
private static GameObject _baseObject;
|
||||||
|
|
||||||
|
public static void InitBaseObject()
|
||||||
|
{
|
||||||
|
if (_baseObject) return;
|
||||||
|
var go = Instantiate(UIRoot.instance.uiGame.starDetail.displayCombo.gameObject);
|
||||||
|
go.name = "my-small-combobox";
|
||||||
|
go.SetActive(false);
|
||||||
|
|
||||||
|
var cbctrl = go.transform.GetComponent<UIComboBox>();
|
||||||
|
cbctrl.onSubmit.RemoveAllListeners();
|
||||||
|
cbctrl.onItemIndexChange.RemoveAllListeners();
|
||||||
|
foreach (var button in cbctrl.ItemButtons)
|
||||||
|
{
|
||||||
|
Destroy(button.gameObject);
|
||||||
|
}
|
||||||
|
cbctrl.Items.Clear();
|
||||||
|
cbctrl.ItemButtons.Clear();
|
||||||
|
_baseObject = go;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MyCornerComboBox CreateComboBox(float x, float y, RectTransform parent, bool topRight = false)
|
||||||
|
{
|
||||||
|
var gameObject = Instantiate(_baseObject);
|
||||||
|
gameObject.name = "my-combobox";
|
||||||
|
gameObject.SetActive(true);
|
||||||
|
var cb = gameObject.AddComponent<MyCornerComboBox>();
|
||||||
|
RectTransform rtrans;
|
||||||
|
if (topRight)
|
||||||
|
{
|
||||||
|
rtrans = Util.NormalizeRectWithTopRight(cb, x, y, parent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rtrans = Util.NormalizeRectWithTopLeft(cb, x, y, parent);
|
||||||
|
}
|
||||||
|
cb._rectTrans = rtrans;
|
||||||
|
var box = rtrans.GetComponent<UIComboBox>();
|
||||||
|
cb._comboBox = box;
|
||||||
|
box.onItemIndexChange.AddListener(() => { cb.OnSelChanged?.Invoke(box.itemIndex); });
|
||||||
|
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnDestroy()
|
||||||
|
{
|
||||||
|
if (_config != null && _configChanged != null)
|
||||||
|
_config.SettingChanged -= _configChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFontSize(int size)
|
||||||
|
{
|
||||||
|
var textComp = _comboBox.transform.Find("Main Button")?.GetComponentInChildren<Text>();
|
||||||
|
if (textComp) textComp.fontSize = size;
|
||||||
|
_comboBox.ItemButtons.ForEach(b => b.GetComponentInChildren<Text>().fontSize = size);
|
||||||
|
_comboBox.m_ListItemRes.GetComponentInChildren<Text>().fontSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetItems(params string[] items)
|
||||||
|
{
|
||||||
|
_comboBox.Items = [.. items.Select(s => s.Translate())];
|
||||||
|
_comboBox.StartItemIndex = 0;
|
||||||
|
_comboBox.DropDownCount = items.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> Items => _comboBox.Items;
|
||||||
|
|
||||||
|
public void UpdateLabelText()
|
||||||
|
{
|
||||||
|
var textComp = _comboBox.transform.Find("Main Button")?.GetComponentInChildren<Text>();
|
||||||
|
if (textComp) textComp.text = _comboBox.Items[_comboBox.itemIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetIndex(int index) => _comboBox.itemIndex = index;
|
||||||
|
|
||||||
|
public void SetSize(float width, float height)
|
||||||
|
{
|
||||||
|
_rectTrans.sizeDelta = new Vector2(width > 0f ? width : _rectTrans.sizeDelta.x, height > 0f ? height : _rectTrans.sizeDelta.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddOnSelChanged(Action<int> action) => OnSelChanged += action;
|
||||||
|
|
||||||
|
private EventHandler _configChanged;
|
||||||
|
private Action<int> _selChanged;
|
||||||
|
private ConfigEntry<int> _config;
|
||||||
|
public void SetConfigEntry(ConfigEntry<int> config)
|
||||||
|
{
|
||||||
|
if (_selChanged != null) OnSelChanged -= _selChanged;
|
||||||
|
if (_configChanged != null) config.SettingChanged -= _configChanged;
|
||||||
|
|
||||||
|
_comboBox.itemIndex = config.Value;
|
||||||
|
_config = config;
|
||||||
|
_selChanged = value => config.Value = value;
|
||||||
|
OnSelChanged += _selChanged;
|
||||||
|
_configChanged = (_, _) => SetIndex(config.Value);
|
||||||
|
config.SettingChanged += _configChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCornerComboBox WithFontSize(int size)
|
||||||
|
{
|
||||||
|
SetFontSize(size);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCornerComboBox WithItems(params string[] items)
|
||||||
|
{
|
||||||
|
SetItems(items);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCornerComboBox WithIndex(int index)
|
||||||
|
{
|
||||||
|
SetIndex(index);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCornerComboBox WithSize(float width, float height)
|
||||||
|
{
|
||||||
|
SetSize(width, height);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCornerComboBox WithOnSelChanged(params Action<int>[] action)
|
||||||
|
{
|
||||||
|
foreach (var act in action)
|
||||||
|
AddOnSelChanged(act);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyCornerComboBox WithConfigEntry(ConfigEntry<int> config)
|
||||||
|
{
|
||||||
|
SetConfigEntry(config);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Width => _rectTrans.sizeDelta.x;
|
||||||
|
public float Height => _rectTrans.sizeDelta.y;
|
||||||
|
}
|
||||||
95
UXAssist/UI/MyFlatButton.cs
Normal file
95
UXAssist/UI/MyFlatButton.cs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace UXAssist.UI;
|
||||||
|
|
||||||
|
public class MyFlatButton : MonoBehaviour
|
||||||
|
{
|
||||||
|
public RectTransform rectTrans;
|
||||||
|
public UIButton uiButton;
|
||||||
|
public Text labelText;
|
||||||
|
|
||||||
|
private static GameObject _baseObject;
|
||||||
|
|
||||||
|
public static void InitBaseObject()
|
||||||
|
{
|
||||||
|
if (_baseObject) return;
|
||||||
|
var panel = UIRoot.instance.uiGame.dysonEditor.controlPanel.hierarchy.layerPanel;
|
||||||
|
var go = Instantiate(panel.layerButtons[0].gameObject);
|
||||||
|
var btn = go.GetComponent<UIButton>();
|
||||||
|
go.GetComponent<Image>().sprite = panel.buttonDefaultSprite;
|
||||||
|
btn.gameObject.name = "my-flatbutton";
|
||||||
|
btn.highlighted = false;
|
||||||
|
var img = btn.GetComponent<Image>();
|
||||||
|
if (img != null)
|
||||||
|
{
|
||||||
|
img.sprite = panel.buttonDefaultSprite;
|
||||||
|
img.color = new Color(img.color.r, img.color.g, img.color.b, 13f / 255f);
|
||||||
|
}
|
||||||
|
|
||||||
|
img = btn.gameObject.transform.Find("frame")?.GetComponent<Image>();
|
||||||
|
if (img != null)
|
||||||
|
{
|
||||||
|
img.color = new Color(img.color.r, img.color.g, img.color.b, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.button.onClick.RemoveAllListeners();
|
||||||
|
_baseObject = go;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MyFlatButton CreateFlatButton(float x, float y, RectTransform parent, string label = "", int fontSize = 15, Action<int> onClick = null)
|
||||||
|
{
|
||||||
|
return CreateFlatButton(x, y, parent, fontSize, onClick).WithLabelText(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MyFlatButton CreateFlatButton(float x, float y, RectTransform parent, int fontSize = 15, Action<int> onClick = null)
|
||||||
|
{
|
||||||
|
var go = Instantiate(_baseObject);
|
||||||
|
go.name = "my-flatbutton";
|
||||||
|
go.SetActive(true);
|
||||||
|
var cb = go.AddComponent<MyFlatButton>();
|
||||||
|
var rect = Util.NormalizeRectWithTopLeft(cb, x, y, parent);
|
||||||
|
|
||||||
|
cb.rectTrans = rect;
|
||||||
|
cb.uiButton = go.GetComponent<UIButton>();
|
||||||
|
|
||||||
|
cb.labelText = go.transform.Find("Text")?.GetComponent<Text>();
|
||||||
|
cb.uiButton.onClick += onClick;
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLabelText(string val)
|
||||||
|
{
|
||||||
|
if (labelText != null)
|
||||||
|
{
|
||||||
|
labelText.text = val.Translate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyFlatButton WithLabelText(string val)
|
||||||
|
{
|
||||||
|
SetLabelText(val);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyFlatButton WithSize(float width, float height)
|
||||||
|
{
|
||||||
|
rectTrans.sizeDelta = new Vector2(width, height);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyFlatButton WithTip(string tip, float delay = 1f)
|
||||||
|
{
|
||||||
|
uiButton.tips.type = UIButton.ItemTipType.Other;
|
||||||
|
uiButton.tips.topLevel = true;
|
||||||
|
uiButton.tips.tipTitle = tip;
|
||||||
|
uiButton.tips.tipText = null;
|
||||||
|
uiButton.tips.delay = delay;
|
||||||
|
uiButton.tips.corner = 2;
|
||||||
|
uiButton.UpdateTip();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public float Width => rectTrans.sizeDelta.x + labelText.rectTransform.sizeDelta.x;
|
||||||
|
public float Height => Math.Max(rectTrans.sizeDelta.y, labelText.rectTransform.sizeDelta.y);
|
||||||
|
}
|
||||||
@@ -12,35 +12,25 @@ public class MyKeyBinder : MonoBehaviour
|
|||||||
private ConfigEntry<KeyboardShortcut> _config;
|
private ConfigEntry<KeyboardShortcut> _config;
|
||||||
protected event Action OnFree;
|
protected event Action OnFree;
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField] public Text functionText;
|
||||||
public Text functionText;
|
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField] public Text keyText;
|
||||||
public Text keyText;
|
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField] public InputField setTheKeyInput;
|
||||||
public InputField setTheKeyInput;
|
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField] public Toggle setTheKeyToggle;
|
||||||
public Toggle setTheKeyToggle;
|
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField] public RectTransform rectTrans;
|
||||||
public RectTransform rectTrans;
|
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField] public UIButton inputUIButton;
|
||||||
public UIButton inputUIButton;
|
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField] public Text conflictText;
|
||||||
public Text conflictText;
|
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField] public Text waitingText;
|
||||||
public Text waitingText;
|
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField] public UIButton setDefaultUIButton;
|
||||||
public UIButton setDefaultUIButton;
|
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField] public UIButton setNoneKeyUIButton;
|
||||||
public UIButton setNoneKeyUIButton;
|
|
||||||
|
|
||||||
private bool _nextNotOn;
|
private bool _nextNotOn;
|
||||||
|
|
||||||
@@ -135,10 +125,12 @@ public class MyKeyBinder : MonoBehaviour
|
|||||||
VFInput.UseEscape();
|
VFInput.UseEscape();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Input.GetKey(KeyCode.Mouse0) || Input.GetKey(KeyCode.Mouse1))
|
if (Input.GetKey(KeyCode.Mouse0) || Input.GetKey(KeyCode.Mouse1))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var anyKey = GetIunptKeys();
|
var anyKey = GetIunptKeys();
|
||||||
if (anyKey || _lastKey == KeyCode.None) return false;
|
if (anyKey || _lastKey == KeyCode.None) return false;
|
||||||
var k = GetPressedKey();
|
var k = GetPressedKey();
|
||||||
@@ -146,20 +138,24 @@ public class MyKeyBinder : MonoBehaviour
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastKey = KeyCode.None;
|
_lastKey = KeyCode.None;
|
||||||
|
|
||||||
_config.Value = KeyboardShortcut.Deserialize(k);
|
_config.Value = KeyboardShortcut.Deserialize(k);
|
||||||
//keyText.text = k;
|
//keyText.text = k;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private KeyCode _lastKey;
|
private KeyCode _lastKey;
|
||||||
private static readonly KeyCode[] ModKeys = { KeyCode.RightShift, KeyCode.LeftShift,
|
|
||||||
KeyCode.RightControl, KeyCode.LeftControl,
|
private static readonly KeyCode[] ModKeys =
|
||||||
KeyCode.RightAlt, KeyCode.LeftAlt,
|
[
|
||||||
KeyCode.LeftCommand, KeyCode.LeftApple, KeyCode.LeftWindows,
|
KeyCode.RightShift, KeyCode.LeftShift,
|
||||||
KeyCode.RightCommand, KeyCode.RightApple, KeyCode.RightWindows };
|
KeyCode.RightControl, KeyCode.LeftControl,
|
||||||
|
KeyCode.RightAlt, KeyCode.LeftAlt,
|
||||||
|
KeyCode.LeftCommand, KeyCode.LeftApple, KeyCode.LeftWindows,
|
||||||
|
KeyCode.RightCommand, KeyCode.RightApple, KeyCode.RightWindows
|
||||||
|
];
|
||||||
|
|
||||||
private string GetPressedKey()
|
private string GetPressedKey()
|
||||||
{
|
{
|
||||||
@@ -168,6 +164,7 @@ public class MyKeyBinder : MonoBehaviour
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mod = "";
|
var mod = "";
|
||||||
foreach (var modKey in ModKeys)
|
foreach (var modKey in ModKeys)
|
||||||
{
|
{
|
||||||
@@ -181,6 +178,7 @@ public class MyKeyBinder : MonoBehaviour
|
|||||||
{
|
{
|
||||||
key += mod;
|
key += mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,8 +193,8 @@ public class MyKeyBinder : MonoBehaviour
|
|||||||
_lastKey = item;
|
_lastKey = item;
|
||||||
anyKey = true;
|
anyKey = true;
|
||||||
}
|
}
|
||||||
return anyKey;
|
|
||||||
|
|
||||||
|
return anyKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
@@ -234,4 +232,4 @@ public class MyKeyBinder : MonoBehaviour
|
|||||||
{
|
{
|
||||||
keyText.text = _config.Value.Serialize();
|
keyText.text = _config.Value.Serialize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user