Hub character swapping, XP percentage, passive health regeneration
ci / verify (push) Successful in 47s

Character swapping is hub-only, and refused by the SERVER rather than merely
greyed out in the menu. Allowing it inside a dungeon would be an instant,
uninterruptible exit from danger -- strictly better than the one-second escape
channel, which would make that channel pointless. Creating a character in a
dungeon is refused for the same reason. Both are covered by diag_progression.

Health regenerates at 0.5% of MAXIMUM per second. A percentage rather than a
flat rate so it does not become irrelevant at level 15: a capped character
regains 1.2 hp/s against a level 1's 0.5, and both take about 200 seconds to
heal from nothing. No out-of-combat gate -- at this rate it cannot out-heal
anything actually shooting at you, and a trickle that never stops is easier to
reason about than a timer players have to learn. A fractional carry is needed
because a tick heals well under one hit point, so truncating each tick would
heal exactly nothing; there is a test for that specifically.

The XP bar now states the percentage and the level it leads to, since a bar
answers "how far" vaguely and a number answers it exactly.

Recorded the two Stage 3 answers: 4 inventory slots, and the boss's food item
is player-instanced now so the mechanism gets exercised rather than deferred.

Writing the swap guard's test caught my own mistake: the first version created
its spare character through the store, which has no opinion about where you
are, so it bypassed the guard it was meant to prove and left a stray character
behind that broke a later assertion.

200 tests. check.sh, test.sh, smoke.sh and both diagnostics pass.
This commit is contained in:
2026-09-04 00:56:29 +02:00
parent 4765bbce28
commit 7ef972e3b3
14 changed files with 243 additions and 15 deletions
+13
View File
@@ -161,3 +161,16 @@ and then overwrite every character on the first level-up.
**Account ids are written as decimal strings in JSON.** They are 64-bit and JSON
numbers are doubles, which would silently round them.
**Character swapping is hub-only, enforced on the server.** Swapping inside a
dungeon would be an instant, uninterruptible exit from danger — strictly better
than the one-second escape channel, and it would make that channel pointless.
The menu greys the button out so the rule is visible, but the server refuses
regardless of what any client's UI allows.
**Health regenerates at 0.5% of MAXIMUM per second, with no out-of-combat
gate.** A percentage rather than a flat rate, so it does not become irrelevant
at level 15 — a capped character regains 1.2 hp/s against a level 1's 0.5, and
both take about 200 seconds to heal from nothing. No combat gate because at this
rate it cannot out-heal anything actually shooting at you, and a trickle that
never stops is easier to reason about than a timer players have to learn.
+13 -7
View File
@@ -84,6 +84,9 @@ play off server events. Enough to prove the pipeline, not a finished look.
| Levels 115, +10 max HP each | done | [src/meta/progression.gd](../src/meta/progression.gd) |
| XP from kills, bosses worth far more | done | `ServerRuntime._award_kill` |
| Colour visible in world and on the HUD | done | snapshot carries it; `WorldView._draw_ship` tints |
| Swap character from the hub | done | Esc menu → Change character; refused server-side in a dungeon |
| XP percentage to next level | done | `HUD._draw_xp_bar` |
| Passive health regeneration | done | `SimPlayer.regenerate`, 0.5%/s of maximum |
Verified end to end by `tools/diag_progression.tscn`, which drives the real
server through kill → xp → level → health and death → retire → roster. That
@@ -139,10 +142,10 @@ bullets spawn per shot, so they belong in the same place.
| Feature | Notes |
| --- | --- |
| Small always-on-screen inventory | Slot count unspecified. |
| Small always-on-screen inventory | **4 slots** for now, may grow. |
| Health potions: rare from trash, guaranteed from bosses | |
| World-shared loot | Player-instanced loot planned later. |
| A unique, useless food item from bosses | Exists specifically to test player-instanced loot. Confirm whether it should be instanced *now* or just marked for it. |
| A unique, useless food item from bosses | **Player-instanced now**, so the mechanism is exercised rather than deferred. |
| Dropping items so others can pick them up | |
---
@@ -185,13 +188,16 @@ Not oversights — each was considered and rejected for now, with the reasoning
Genuinely unspecified; do not guess at these, they change the design:
Deferred to the Stage 4 discussion (upgrades), but they block that stage:
1. Damage stacking order — additive pool then multiplicative, or something else?
2. Rarity weights for the four upgrade tiers.
3. Split shot geometry: ±22.5° from the original heading, or 45° to each side?
4. Poison: do applications stack, or refresh a single DoT?
5. Eraser: does it delete *enemy bullets* it passes through?
6. Inventory slot count.
7. Do unclaimed level-ups queue at the NPC?
8. Does the 5-character cap count only active characters?
9. Glass cannon's 50% health: of base HP, or of levelled max HP?
10. What advances dungeon depth? `--depth` is a dev flag; nothing raises it in play.
6. Do unclaimed level-ups queue at the NPC?
7. Glass cannon's 50% health: of base HP, or of levelled max HP?
Still open outside Stage 4:
8. What advances dungeon depth? `--depth` is a dev flag; nothing raises it in play.