1
0
mirror of https://github.com/soarqin/DSP_Mods.git synced 2025-12-14 23:13:50 +08:00

work in progress

This commit is contained in:
2025-05-20 19:02:33 +08:00
parent b6c182168b
commit d5f09972b1
2 changed files with 271 additions and 2 deletions

View File

@@ -1,4 +1,9 @@
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Drawing.Text;
using System.Linq;
using HarmonyLib;
using UnityEngine;
using UXAssist.Common;
namespace CheatEnabler.Functions;
@@ -76,7 +81,7 @@ public static class DysonSphereFunctions
dysonNode.spOrdered = 0;
dysonNode._spReq = 0;
totalNodeSp += dysonNode.spMax;
var diff = dysonNode.spMax - dysonNode.sp;
var diff = dysonNode.spMax - dysonNode.sp;
if (diff > 0)
{
rocketCount += diff;
@@ -149,4 +154,265 @@ public static class DysonSphereFunctions
}
});
}
private static DysonFrame QuickAddDysonFrame(this DysonSphereLayer layer, int protoId, DysonNode nodeA, DysonNode nodeB, bool euler)
{
int newId;
if (layer.frameRecycleCursor > 0)
{
var array = layer.frameRecycle;
var index = layer.frameRecycleCursor - 1;
layer.frameRecycleCursor = index;
newId = array[index];
}
else
{
var index = layer.frameCursor;
layer.frameCursor = index + 1;
newId = index;
if (newId == layer.frameCapacity)
{
layer.SetFrameCapacity(layer.frameCapacity * 2);
}
}
DysonFrame frame = layer.framePool[newId];
if (frame == null)
{
frame = new DysonFrame();
layer.framePool[newId] = frame;
}
else
{
frame = layer.framePool[newId];
frame.SetEmpty();
}
frame.id = newId;
frame.layerId = layer.id;
frame.protoId = protoId + DysonSphereSegmentRenderer.nodeProtoCount;
frame.reserved = false;
frame.nodeA = nodeA;
frame.nodeB = nodeB;
frame.euler = euler;
frame.spA = 0;
frame.spB = 0;
frame.spMax = frame.segCount * DysonFrame.kSpPerSeg;
nodeA.frames.Add(frame);
nodeB.frames.Add(frame);
return frame;
}
private static int QuickAddDysonShell(this DysonSphereLayer layer, int protoId, DysonNode[] nodes, DysonFrame[] frames)
{
int shellId = 0;
if (layer.shellRecycleCursor > 0)
{
int[] array = layer.shellRecycle;
int index = layer.shellRecycleCursor - 1;
layer.shellRecycleCursor = index;
shellId = array[index];
}
else
{
int index = layer.shellCursor;
layer.shellCursor = index + 1;
shellId = index;
if (shellId == layer.shellCapacity)
{
layer.SetShellCapacity(layer.shellCapacity * 2);
}
}
var shell = layer.shellPool[shellId];
if (shell == null)
{
shell = new DysonShell(layer);
layer.shellPool[shellId] = shell;
}
else
{
shell.SetEmpty();
}
shell.id = shellId;
shell.layerId = layer.id;
shell.protoId = protoId;
shell.randSeed = layer.id * 10000 + shellId;
for (int j = 0; j < nodes.Length; j++)
{
DysonNode dysonNode = nodes[j];
DysonNode dysonNode2 = nodes[(j + 1) % nodes.Length];
DysonFrame dysonFrame = frames[j];
List<Vector3> segments = dysonFrame.GetSegments();
if (dysonNode == dysonFrame.nodeA)
{
for (int k = 0; k < segments.Count - 1; k++)
{
shell.polygon.Add(segments[k]);
}
}
else
{
for (int l = segments.Count - 1; l >= 1; l--)
{
shell.polygon.Add(segments[l]);
}
}
shell.nodeIndexMap[nodes[j % nodes.Length].id] = shell.nodes.Count;
shell.nodes.Add(dysonNode);
shell.frames.Add(dysonFrame);
if (!dysonNode.shells.Contains(shell))
{
dysonNode.shells.Add(shell);
}
}
shell.GenerateGeometry();
shell.GenerateModelObjects();
CheatEnabler.Logger.LogInfo($"QuickAddDysonShell: {DysonShell.s_vmap.Count}");
return shellId;
}
private struct SupposedShell
{
public DysonNode nodeA;
public DysonNode nodeB;
public DysonNode nodeC;
public float area;
}
public static void CreatePossibleFramesAndShells()
{
StarData star = null;
var dysonEditor = UIRoot.instance?.uiGame?.dysonEditor;
if (dysonEditor != null && dysonEditor.gameObject.activeSelf)
{
star = dysonEditor.selection.viewStar;
}
if (star == null)
{
star = GameMain.data?.localStar;
if (star == null)
{
UIMessageBox.Show("CheatEnabler".Translate(), "You are not in any system.".Translate(), "确定".Translate(), 3, null);
return;
}
}
var dysonSphere = GameMain.data?.dysonSpheres[star.index];
if (dysonSphere == null || dysonSphere.layerCount == 0)
{
UIMessageBox.Show("CheatEnabler".Translate(), string.Format("There is no Dyson Sphere shell on \"{0}\".".Translate(), star.displayName), "确定".Translate(), 3, null);
return;
}
var framesChanged = false;
var shellsChanged = false;
for (var i = 1; i < dysonSphere.layersIdBased.Length; i++)
{
Dictionary<(int, int), int> availableFrames = [];
HashSet<(int, int, int)> availableShells = [];
HashSet<DysonNode> spDirtyNodes = [];
HashSet<DysonNode> cpDirtyNodes = [];
var layer = dysonSphere.layersIdBased[i];
if (layer == null || layer.id != i) continue;
for (var j = 1; j < layer.frameCursor; j++)
{
var frame = layer.framePool[j];
if (frame == null || frame.id != j) continue;
var idA = frame.nodeA.id;
var idB = frame.nodeB.id;
if (idA > idB)
{
(idA, idB) = (idB, idA);
}
availableFrames[(idA, idB)] = j;
}
for (var j = 1; j < layer.shellCursor; j++)
{
var shell = layer.shellPool[j];
if (shell == null || shell.id != j) continue;
if (shell.nodes.Count != 3) continue;
var ids = shell.nodes.Select(node => node.id).OrderBy(id => id).ToArray();
availableShells.Add((ids[0], ids[1], ids[2]));
}
int nodeCount = layer.nodeCursor;
List<SupposedShell> supposedShells = [];
for (var j = 1; j < nodeCount; j++)
{
var nodeA = layer.nodePool[j];
if (nodeA == null || nodeA.id != j) continue;
for (var k = j + 1; k < nodeCount; k++)
{
var nodeB = layer.nodePool[k];
if (nodeB == null || nodeB.id != k) continue;
for (var l = k + 1; l < nodeCount; l++)
{
var nodeC = layer.nodePool[l];
if (nodeC == null || nodeC.id != l) continue;
var area = Vector3.Cross(nodeB.pos - nodeA.pos, nodeC.pos - nodeA.pos).sqrMagnitude;
supposedShells.Add(new SupposedShell { nodeA = nodeA, nodeB = nodeB, nodeC = nodeC, area = area });
}
}
}
supposedShells.Sort((a, b) => b.area.CompareTo(a.area));
var count = Math.Min(supposedShells.Count, 1);
for (var j = 0; j < count; j++)
{
var shell = supposedShells[j];
if (availableShells.TryGetValue((shell.nodeA.id, shell.nodeB.id, shell.nodeC.id), out _)) continue;
if (!availableFrames.TryGetValue((shell.nodeA.id, shell.nodeB.id), out _)) {
var frame = layer.QuickAddDysonFrame(0, shell.nodeA, shell.nodeB, false);
availableFrames[(shell.nodeA.id, shell.nodeB.id)] = frame.id;
spDirtyNodes.Add(shell.nodeA);
spDirtyNodes.Add(shell.nodeB);
}
if (!availableFrames.TryGetValue((shell.nodeA.id, shell.nodeC.id), out _)) {
var frame = layer.QuickAddDysonFrame(0, shell.nodeA, shell.nodeC, false);
availableFrames[(shell.nodeA.id, shell.nodeC.id)] = frame.id;
spDirtyNodes.Add(shell.nodeA);
spDirtyNodes.Add(shell.nodeC);
}
if (!availableFrames.TryGetValue((shell.nodeB.id, shell.nodeC.id), out _)) {
var frame = layer.QuickAddDysonFrame(0, shell.nodeB, shell.nodeC, false);
availableFrames[(shell.nodeB.id, shell.nodeC.id)] = frame.id;
spDirtyNodes.Add(shell.nodeB);
spDirtyNodes.Add(shell.nodeC);
}
}
foreach (var node in spDirtyNodes)
{
node.RecalcSpReq();
}
framesChanged = framesChanged || spDirtyNodes.Count > 0;
for (var j = 0; j < count; j++)
{
var shell = supposedShells[j];
if (availableShells.TryGetValue((shell.nodeA.id, shell.nodeB.id, shell.nodeC.id), out _)) continue;
DysonFrame[] frames = [layer.framePool[availableFrames[(shell.nodeA.id, shell.nodeB.id)]], layer.framePool[availableFrames[(shell.nodeA.id, shell.nodeC.id)]], layer.framePool[availableFrames[(shell.nodeB.id, shell.nodeC.id)]]];
DysonNode[] nodes = [shell.nodeA, shell.nodeB, shell.nodeC];
layer.QuickAddDysonShell(0, nodes, frames);
cpDirtyNodes.Add(shell.nodeA);
cpDirtyNodes.Add(shell.nodeB);
cpDirtyNodes.Add(shell.nodeC);
shellsChanged = true;
}
foreach (var node in cpDirtyNodes)
{
node.RecalcCpReq();
}
}
if (framesChanged)
{
dysonSphere.CheckAutoNodes();
if (dysonSphere.autoNodeCount <= 0)
{
dysonSphere.PickAutoNode();
}
}
if (shellsChanged)
{
GameMain.gameScenario.NotifyOnPlanDysonShell();
}
if (framesChanged || shellsChanged)
{
dysonSphere.modelRenderer.RebuildModels();
}
}
}

View File

@@ -65,6 +65,7 @@ public static class UIConfigWindow
I18N.Add("Overclock Ejectors", "Overclock Ejectors (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("Generate tricky dyson shells", "Generate tricky dyson shells (Put/Paste nodes first)", "生成仙术戴森壳(请先设置/粘贴节点)");
I18N.Add("Complete Dyson Sphere shells instantly", "Complete Dyson Sphere shells instantly", "立即完成戴森壳建造");
I18N.Add("Terraform without enough soil piles", "Terraform without enough soil piles", "沙土不够时依然可以整改地形");
I18N.Add("Instant hand-craft", "Instant hand-craft", "快速手动制造");
@@ -259,6 +260,8 @@ public static class UIConfigWindow
x = 300f;
y = 10f;
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, "Generate tricky dyson shells", 16, "button-generate-tricky-dyson-shells", DysonSphereFunctions.CreatePossibleFramesAndShells);
var tab5 = wnd.AddTab(_windowTrans, "Mecha/Combat");
x = 0f;