Scale health and damage by ten so percentages have somewhere to land

A shot is 60, a fresh character has 1000, the Warden has 36000. Enemy health,
boss health and every emitter's damage were scaled with them, so every ratio
is unchanged and time to kill is exactly what it was -- tests/unit/test_content
now pins shots-to-kill per enemy and hits-to-kill a player so a careless edit
to either side shows up as a number a designer recognises.

The reason is rounding rather than balance. Damage is an integer, and at a base
of 6 the +5% every upgrade carries computed to 6.3 and rounded straight back to
6: a player took their first upgrade, was told it made them stronger, and
nothing happened. diag_upgrades used to print "damage matches the formula
(6 -> 6)"; it now prints (60 -> 63). The boss's per-phase armour multiplier had
the same problem, turning 1.15 into an effective 1.17.

The practice dummy stopped relying on a huge health pool at the same time. Its
old 100000 was already past the u16 the snapshot sends enemy health in, and
once a shot did 60 a patient player could have destroyed the hub's only
practice target for everyone until the next restart. EnemyDef.indestructible
says what was actually meant, and a test asserts nothing else uses it.

check.sh clean, 364 tests, SMOKE PASS, all four diagnostics green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-06 16:16:38 +02:00
parent b351bc2d55
commit cb2c1e7840
14 changed files with 185 additions and 54 deletions
+22
View File
@@ -340,3 +340,25 @@ pins the clamp.
reliable channel, and the client learns enemy health from the snapshot anyway.
Death is still announced, because the experience award is keyed on that event
and a kill by poison has to score.
---
## The scale of the numbers
**Health and damage are ten times what they started as, and every ratio is
unchanged.** A shot is 60, a fresh character has 1000, the Warden has 36000,
and enemy health and emitter damage were scaled with them — time to kill is
exactly what it was.
The reason is rounding, not balance. Damage is an integer, and at a base of 6
the +5% that every upgrade carries computed to 6.3 and rounded back to 6: a
player took their first upgrade, was told it made them stronger, and it did
nothing. Ten times the base means every 5% step is worth 3 damage. The same
applies to the boss's per-phase armour multiplier, which at 6 damage rounded
1.15 into 1.17.
**The practice dummy is indestructible by flag, not by a large number.** The
old 100000 health was already past the u16 the snapshot sends enemy health in,
and once a shot did 60 a patient player could have worn it down and left the
hub without a practice target until the next restart. A flag says what was
actually meant.
+24 -17
View File
@@ -20,7 +20,7 @@ What "everything passes" currently means. Numbers move; the shape does not.
| Gate | Covers | Runtime |
| --- | --- | --- |
| `tools/check.sh` | every script parses and type-checks | ~5s |
| `tools/test.sh` | 357 GUT tests, no SceneTree | ~4s |
| `tools/test.sh` | 364 GUT tests, no SceneTree | ~4s |
| `tools/smoke.sh` | 18 assertions over a real ENet socket: handshake, auth, character creation and persistence, both dungeon kinds, escape, hard kill, polite disconnect | ~40s |
| `diag_prediction.tscn` | client-prediction gap, with injected clock drift | ~10s |
| `diag_progression.tscn` | kill → xp → level → health, death → retire → roster, swap guards | ~10s |
@@ -219,6 +219,29 @@ shares the interact key.
---
## The scale of health and damage
Health and damage are an order of magnitude larger than they started. A shot is
60, a fresh character has 1000, the Warden has 36000. **Every ratio is
unchanged** — enemy health, boss health and every emitter's damage were scaled
together, so time to kill is exactly what it was.
The reason is rounding. At the old base of 6 damage, the +5% every upgrade
carries computed to 6.3 and rounded straight back to 6, so a player's first
upgrade visibly did nothing. At 60 it is +3, and every percentage in the game
now has somewhere to land.
`tests/unit/test_content.gd` pins both halves of that: that a single upgrade
changes damage, and that shots-to-kill for each enemy is what it was before.
Do not tidy these numbers back down without scaling `content.gd` with them.
The hub's practice dummy stopped relying on a huge health pool at the same
time: it is `indestructible` by flag now. The old 100000 was already past the
u16 the snapshot sends enemy health in, and after the rescale a patient player
could have destroyed the hub's only practice target for everyone.
---
## Stage 4 — Upgrades · *done*
Every level gained banks one choice. Choices are spent at the **quartermaster**,
@@ -284,9 +307,6 @@ All four settled with the user; the reasoning is in
### Known gaps
- **The +5% is invisible on the first upgrade.** `PLAYER_BULLET_DAMAGE` is 6, so
6 × 1.05 rounds back to 6. It accumulates correctly (14 upgrades → +70% → 10
damage), but the first one visibly does nothing. See the open question below.
- **One panel, not two screens.** The brief asked for a separate screen listing
upgrades taken; it is the lower half of the choice panel instead, because the
two are read together.
@@ -337,19 +357,6 @@ Not oversights — each was considered and rejected for now, with the reasoning
Genuinely unspecified. **Do not guess at these** — each changes the design, and
several have no obvious default.
### Worth a decision soon
1. **Base damage is too small for the +5% to show.** `PLAYER_BULLET_DAMAGE` is
6, and 6 × 1.05 rounds to 6 — so the flat bonus every upgrade carries does
nothing at all until the second one. It comes out right in aggregate, but a
player who takes Split Shot and sees no damage change has been told
something untrue.
The clean fix is to scale base damage and enemy health together — ×4 would
put a shot at 24 and make every 5% step land — which changes no time-to-kill
but touches every number in `content.gd`. That is a balance edit, so it is
yours to call rather than mine.
### Blocking nothing yet
8. **What advances dungeon depth?** `--depth` is a dev flag; nothing raises it