Run Re-Do

This commit is contained in:
2026-07-02 20:41:43 -07:00
parent 86575dd5bc
commit 16e396841e
188 changed files with 8291 additions and 2429 deletions
@@ -94,7 +94,7 @@ namespace ProjectM.Client
Body(c, "Turret (40 Ore) — auto-fires at enemies. Needs Charge as ammo.");
Body(c, "Fabricator (30 Ore) — converts Ore → Charge so turrets keep firing.");
Body(c, "Wall (Biomass) — a cheap barrier that blocks enemies.");
Body(c, "Aether — spend it on UPGRADE DMG to boost your damage.");
Body(c, "Aether — rare; fuels PERMANENT class upgrades at the base between runs.");
Body(c, "Open Build with Tab (Y), pick a piece, click a green tile to place it.");
break;
case 3: // Threats
@@ -55,6 +55,11 @@ namespace ProjectM.Client
public Sprite FabricatorIcon;
public Sprite ConveyorIcon;
[Header("Build-ghost preview meshes (authored real-size, ground pivot — BuildSendSystem)")]
public Mesh TurretGhostMesh;
public Mesh WallGhostMesh;
public Mesh FabricatorGhostMesh;
[Header("Build-mode control glyphs")]
public Sprite KbmPlace; // LMB
public Sprite KbmCancel; // RMB
@@ -91,6 +96,18 @@ namespace ProjectM.Client
}
}
/// <summary>Placement-ghost preview mesh for a <see cref="StructureType"/> byte (null → the cube fallback).</summary>
public Mesh StructureGhostMesh(byte type)
{
switch (type)
{
case StructureType.Turret: return TurretGhostMesh;
case StructureType.Wall: return WallGhostMesh;
case StructureType.Fabricator: return FabricatorGhostMesh;
default: return null;
}
}
// ---- cached SDF font definitions (one FontAsset per font, built once, reset per play session) ----
static FontAsset _displayFa, _bodyFa, _bodyLightFa;
static bool _displayTried, _bodyTried, _bodyLightTried;
@@ -120,7 +120,16 @@ namespace ProjectM.Client
if (data == null) return;
var em = server.EntityManager;
var e = em.CreateEntity();
em.AddComponentData(e, new PendingSave { GoalCharge = data.GoalCharge, GoalTarget = data.GoalTarget, CoreCurrent = data.CoreCurrent, RunOutcome = (byte)data.RunOutcome, HasData = 1 });
// v5->v6 migration (operator-approved): an old save's Charge counted boss-cleared runs (DR-042), so a
// missing RunsCompleted floors to it — the HUD never shows "Charge 3/4" beside "Runs completed: 0".
int runsCompleted = data.RunsCompleted > data.GoalCharge ? data.RunsCompleted : data.GoalCharge;
em.AddComponentData(e, new PendingSave { GoalCharge = data.GoalCharge, GoalTarget = data.GoalTarget, CoreCurrent = data.CoreCurrent, RunOutcome = (byte)data.RunOutcome, RunsCompleted = runsCompleted, MaxDepthReached = data.MaxDepthReached, HasData = 1 });
// v6: stage the meta tiers UNCONDITIONALLY (empty OK — the Bursted spawn system GetBuffers it in the
// HasData block; a conditional buffer would throw on any v<=5 Continue). Rows verbatim, no clamping.
var mbuf = em.AddBuffer<PendingMetaRow>(e);
if (data.MetaUpgrades != null)
foreach (var mrow in data.MetaUpgrades)
mbuf.Add(new PendingMetaRow { ClassId = mrow.ClassId, UpgradeId = mrow.UpgradeId, Tier = mrow.Tier });
var buf = em.AddBuffer<PendingSaveLedgerRow>(e);
if (data.Ledger != null)
foreach (var row in data.Ledger)
@@ -167,6 +176,9 @@ namespace ProjectM.Client
var st = tq.GetSingleton<NetworkTime>().ServerTick;
if (st.IsValid) nowTick = st.TickIndexForValidTick;
}
// v6: the permanent-meta slice via the ONE shared collector — omitting it HERE (the most common
// exit path) would silently WIPE all meta progression on quit (the meta review's top blocker).
MetaSaveScan.Collect(em, dir, out var metaRows, out var runsCompleted, out var maxDepth);
SaveStructureScan.Collect(em, nowTick, out var structures, out var structureIo);
SaveService.Save(new SaveData
@@ -174,6 +186,9 @@ namespace ProjectM.Client
GoalCharge = goal.Charge,
GoalTarget = goal.Target,
CoreCurrent = core.Current,
RunsCompleted = runsCompleted,
MaxDepthReached = maxDepth,
MetaUpgrades = metaRows,
RunOutcome = outcome.Value,
Ledger = rows,