A UI pass: prompts that tell the truth, and a HUD that does not collide
ci / verify (push) Successful in 53s

Prompts named the default keys whatever was bound. Every action is
rebindable, but the HUD said "WASD move", "LMB fire", "hold F" and "1-4
use", the quartermaster said "E talk" and the upgrade screen "Close (E)".
All of them now go through Settings.short_label(), and a test rebinds
fire, escape, interact and a slot key and checks each prompt follows.

The HUD's top-left was a developer's status line -- name, instance id,
health as text, frame rate -- with the boss bar drawn over its right end
and the level-up notice sharing a row with the escape bar. It is now
name and level, where you are, health with its numbers, experience,
escape and level-ups, stacked by a running cursor so nothing has a fixed
row to collide on. Instance and fps moved behind F1, which is who they
were for. Arrival protection is a centred banner rather than a note
beside the health bar, because it is the one moment the rules change.

A hit used to tint the whole screen red, which in a bullet hell dims the
bullets at exactly the moment you are among them. It is an edge now, and
the same edge pulses below a third of your health. New: a message feed
above the inventory for what the server just confirmed -- items taken,
used and dropped, levels gained -- and party health top-right in a
dungeon, where the hub shows who is online. The pickup prompt now also
names the dungeon under your feet when you stand on its ring, in the
same order the server resolves that key: loot first, then the entrance.

The boss bar used to announce the boss to anyone within the actor
interest radius -- which passes through walls -- so a player in the
entrance room was told the Warden was near. It waits until the fog has
actually lit the boss once, then stays for the fight.

Permadeath was announced only by the roster screen appearing. The client
records its own death from the server's event and the roster says who
fell, at what level, and where. The connect screen lost a name field
that did nothing for a person -- it only named the characters bots
create -- gained a proper panel, remembers the last server, and shows
the protocol number a mismatch refusal will quote.

And screenshot.tscn ran as the player's real account against their real
character store, walking their character into dungeons for pictures --
with health now carried between runs, a stray hit would have stuck. It
has its own store and account now, like every diagnostic, and a seeded
character. The real store was checked: nothing it carries changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
claudeandClaude Opus 5.5 committed 2026-10-05 10:41:04 +02:00
1 parent 069abdb3fa
commit 19d2295bec
14 files changed
+903 -229

No files matched your search

+9 -3
View File
@@ -13,7 +13,7 @@ the obvious default.
```bash
tools/check.sh # parse-check every script (~5s) -- run after every edit
tools/test.sh # 534 GUT tests, headless (~4s)
tools/test.sh # 551 GUT tests, headless (~4s)
tools/smoke.sh # real server + 4 bot clients over ENet (~40s)
tools/server.sh # dedicated server
tools/client.sh --listen # host and play, no menu
@@ -29,7 +29,7 @@ godot --headless --path . res://tools/diag_loot.tscn # drop -> pick up
godot --headless --path . res://tools/diag_upgrades.tscn # level -> choice -> taken at the NPC -> new stats
godot --headless --path . --script tools/bench.gd # sim cost per tick
python3 tools/build_local_assets.py # rebuild the local-only bullet atlas
SHOT_DIR=/tmp/shots godot --path . res://tools/screenshot.tscn # menus, HUD, roster, and the fog in a dungeon and a tunnel (needs a display)
SHOT_DIR=/tmp/shots godot --path . res://tools/screenshot.tscn # every screen, the fog, a staged boss fight (needs a display; own store and account)
```
`diag_progression`, `diag_loot` and `diag_upgrades` exist because the bot smoke
@@ -37,6 +37,11 @@ test cannot cover any of them: bots are poor shots, so they rarely kill
anything, which means they neither earn levels, produce drops, nor ever reach
the quartermaster.
**Every key the game names to the player goes through `Settings.short_label()`.**
All of them are rebindable, and a prompt that names the default is wrong for
anyone who changed it — the HUD said "LMB fire" and the upgrade screen said
"Close (E)" whatever those were bound to.
**Nothing automated can see the screen.** `check.sh`, the suite and `smoke.sh`
have all passed with the entire interface rendering unstyled, an invisible
slider and an invisible scrollbar. After touching anything under `src/ui/` or
@@ -51,7 +56,8 @@ Everything after `--` goes to `GameOpts.parse()`:
| `--join` | Skip the menu and connect. |
| `--listen` | Skip the menu and host a listen server with a local player. |
| `--bot` | Scripted input instead of the keyboard. Implies `--join`. |
| `--host`, `--port`, `--name` | Connection details. |
| `--host`, `--port` | Connection details. |
| `--name` | Bots only: what a bot calls the character it creates. People name characters on the roster screen; the connect screen no longer asks. |
| `--autoquit N` | Quit after N physics ticks. |
| `--boss-rush` | Server-side: dungeons spawn the boss and no trash. |
| `--depth N` | Server-side: depth of new dungeons, which drives map size. |