feat: greyscale death screen + one death path (#30) #126

Merged
marco merged 1 commit from feat/ghost-overlay into main 2026-07-22 06:53:47 +02:00
Owner

Summary

Closes #30. Two related "death" changes:

  • Greyscale death screen (#30): while the local player is a ghost, the world view is rendered in stark high-contrast greyscale (UO "you are dead"). The world is drawn to an offscreen RenderTarget, then blitted back desaturated (Rec.601 luminance + a slight contrast/darken); the HUD is drawn after, in colour, so it stays readable. It clears the instant the player resurrects. Client-only, no protocol/server change — and no shader/content-pipeline: a CPU post-process that runs only while dead.
  • One death path (server): every way a player's HP reaches 0 — a lethal blow, a spell bolt, a GM /kill — funnels through CombatSystem.KillPlayer, which makes the ghost and queues the death in a single _pendingDeaths list the tick drains and broadcasts. Removes the melee-only CombatResolution.Deaths + DamageResult.PlayerDeath plumbing, and fixes a latent bug: a spell that killed a player set the ghost but never broadcast PlayerDied. /kill now also slays players (→ ghost), so melee/spell/GM deaths are identical.

Screenshots / recording

Captured by piloting the client via the debug harness: login debug/kill self → screenshot.

Ghost — the world in high-contrast greyscale (journal: "Target slain."):

ghost greyscale

How it was tested

  • New tests: WorldTests.SlayPlayer_KillsThroughTheOneDeathPath_AndTheTickAnnouncesIt, CommandTests.Kill_WithPlayerTarget_SlaysThePlayer_AsAGhost; the existing melee-death test still passes (same path).
  • Drove it end-to-end via the harness (screenshot above) — the greyscale kicks in on death and clears on resurrect.
  • Whole solution builds 0 warnings; dotnet test green (340).

Checklist

  • just lint passes (CSharpier + analyzers, zero warnings)
  • just test is green
  • The whole solution builds (client and tools included)
  • Multi-platform preserved (pure .NET / MonoGame; CPU post-process, no shader)
  • Tests added/updated for this change
  • Linked the related issue (#30) and its Definition of Done is met
## Summary Closes #30. Two related "death" changes: - **Greyscale death screen (#30):** while the local player is a ghost, the world view is rendered in stark high-contrast **greyscale** (UO "you are dead"). The world is drawn to an offscreen `RenderTarget`, then blitted back desaturated (Rec.601 luminance + a slight contrast/darken); the HUD is drawn after, in colour, so it stays readable. It clears the instant the player resurrects. Client-only, no protocol/server change — and no shader/content-pipeline: a CPU post-process that runs only while dead. - **One death path (server):** every way a player's HP reaches 0 — a lethal blow, a **spell** bolt, a GM **/kill** — funnels through `CombatSystem.KillPlayer`, which makes the ghost and queues the death in a single `_pendingDeaths` list the tick drains and broadcasts. Removes the melee-only `CombatResolution.Deaths` + `DamageResult.PlayerDeath` plumbing, and **fixes a latent bug**: a spell that killed a player set the ghost but never broadcast `PlayerDied`. `/kill` now also slays players (→ ghost), so melee/spell/GM deaths are identical. ## Screenshots / recording _Captured by piloting the client via the debug harness: `login debug` → `/kill` self → screenshot._ **Ghost — the world in high-contrast greyscale (journal: "Target slain."):** ![ghost greyscale](https://git.homelab.devncode.it/attachments/97f2560b-a656-41ae-b853-a3c6bad3f501) ## How it was tested - New tests: `WorldTests.SlayPlayer_KillsThroughTheOneDeathPath_AndTheTickAnnouncesIt`, `CommandTests.Kill_WithPlayerTarget_SlaysThePlayer_AsAGhost`; the existing melee-death test still passes (same path). - Drove it end-to-end via the harness (screenshot above) — the greyscale kicks in on death and clears on resurrect. - Whole solution builds 0 warnings; `dotnet test` green (340). ## Checklist - [x] `just lint` passes (CSharpier + analyzers, zero warnings) - [x] `just test` is green - [x] The whole solution builds (client and tools included) - [x] Multi-platform preserved (pure .NET / MonoGame; CPU post-process, no shader) - [x] Tests added/updated for this change - [x] Linked the related issue (#30) and its Definition of Done is met
feat: full-screen ghost overlay + one death path (#30)
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m28s
c32c026e5e
Client (#30): while the local player is a ghost, the world view gets a translucent
grey wash (UO 'you are dead'), drawn under the HUD so chat/panels stay readable;
it clears the instant the player resurrects.

Server — one death path (the reason spell/GM deaths now behave like melee): every
way a player's HP reaches 0 — a lethal blow, a spell bolt, a GM /kill — funnels
through CombatSystem.KillPlayer, which becomes a ghost and queues the death in a
single _pendingDeaths list the tick drains and broadcasts. Removes the melee-only
CombatResolution.Deaths + DamageResult.PlayerDeath plumbing. This fixes a latent
bug: a spell that killed a player set the ghost but never broadcast PlayerDied
(the spell path only read CreatureDeath). /kill now also slays players (becoming a
ghost), so there is no melee/spell/GM difference.
marco force-pushed feat/ghost-overlay from c32c026e5e
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m28s
to 57ebfaf41d
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m35s
2026-07-22 06:51:43 +02:00
Compare
marco changed title from feat: full-screen ghost overlay + one death path (#30) to feat: greyscale death screen + one death path (#30) 2026-07-22 06:52:43 +02:00
marco merged commit bf22d9197f into main 2026-07-22 06:53:47 +02:00
marco deleted branch feat/ghost-overlay 2026-07-22 06:53:47 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
marco/IsoMmo!126
No description provided.