Commit Graph

3 Commits

Author SHA1 Message Date
Zixer1 4ce57efbe2 Rebalance Doomsday Clock: late-game stalemate-breaker (10min grace + wave squeeze), slower troop drain, gentler-but-steeper warship attrition (#4518)
Resolves #<add your approved & assigned issue number>

## Description:

Rebalances the Doomsday Clock so it acts as a **late-game
stalemate-breaker** rather than an early-game culler, softens how fast
it removes troops and warships, and makes the HUD countdown clearer.

**Clock schedule (all presets):**
- A flat **10-minute grace** at 0% required share — the early game is
decided by combat, not the clock.
- Then a 6-wave squeeze at accelerating levels (4 / 9 / 16 / 26 / 40 /
55%) with short pauses, reaching the final 55% at each preset's cap:
**45 / 35 / 25 / 15 min** for slow / normal / fast / veryfast.
- `WaveSchedule` `rampSeconds`/`pauseSeconds` are now **per-wave
arrays**, so the curve can be shaped (gentle early, steeper late)
instead of one uniform ramp. `requiredBasisPoints` and the HUD companion
`doomsdayClockWaveState` walk the per-wave segments in lockstep.

**Troop drain:** warn window `10s → 30s`, drain eased (`2%→5%` over
`90s`), so a caught side takes ~2 minutes to wipe instead of ~1.

**Warship attrition:** warships get their own gentler start plus a
**convex** decay curve — a ship caught when its side is first doomed
lasts about as long as troops, but the rate ramps up steeply so a side
at full attrition still loses its fleet in ~2s. Adds a `curveExponent`
argument to `doomsdayClockDrain` (1 = linear, used for troops; higher =
convex, used for ships).

**Determinism:** the drain curve is **integer-only** (fixed-point power,
no floats), so the floored per-tick loss is bit-identical on every
client in the lockstep sim. The linear troop path keeps its exact
existing integer form; only the convex warship path is reshaped.

**HUD countdown clarity:** the clock readout now shows a live countdown
in both states — `Will reach 16% in M:SS` while the bar is actively
climbing, and `Starts rising to 26% in M:SS` during a pause (previously
`Next 26% in …`, which read as if it jumped there instantly). Backed by
a new `secondsToTarget` field on the shared wave state so the sim and
HUD stay in agreement. All display text goes through `translateText()` /
`en.json`.
<img width="278" height="116" alt="image"
src="https://github.com/user-attachments/assets/e0be3d2c-bb88-46be-b344-34d63e4859bd"
/>
<img width="304" height="171" alt="image"
src="https://github.com/user-attachments/assets/da74bd05-0b9a-4aec-bbf5-e7380fbda88e"
/>

**Danger skull:** while a side is below the bar in the warn window, its
on-map skull now blinks progressively faster as the countdown runs out
(accelerating to the moment the drain begins), then holds steady once it
is actually draining — a clearer "you are about to be hit" cue.

Rationale: the previous schedule removed players heavily in the first
half of a match and could leave a drawn-out endgame. Holding the clock
at 0% early keeps the opening about fighting, and concentrating its
pressure in the back half reserves it for actually breaking stalemates.
Values are tuning starting points and easy to adjust in
`DoomsdayClock.ts` / the config defaults.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory

## Please put your Discord username so you can be contacted if a bug or
regression is found:

<add your Discord username>
2026-07-07 19:38:36 -07:00
Zixer1 66063d6178 feat(doomsday-clock): decay warships alongside troops for doomed sides (#4499)
## Description: 

Follow-up to #4469.

The Doomsday Clock drains a doomed side's troops but leaves its navy
untouched, so a coastal or island turtle can sit below the bar
indefinitely on warship defense, exactly the stall the clock is meant to
break.

This decays the warships of a flagged (sub-threshold, non-leader) side
on the same ramp as its troops:

- Each warship loses a percentage of its (veterancy-adjusted) max health
per second, reusing `doomsdayClockDrain`, so the fleet and the army
bleed in lockstep and reach zero together (~55s from full at the default
rate).
- Destruction passes **no attacker**, so it routes through
`UnitImpl.delete` as an environmental loss: no kill credit, no
boat-destroy stats, no veterancy granted. Scoring integrity is
preserved.
- Healing is suppressed for a flagged owner
(`WarshipExecution.healWarship` early-returns), so the decay actually
sinks the fleet instead of being out-healed at a port. Inert when the
mode is off, since the mark is never set.
- The leader's fleet is spared, same as its troops.

No new config: warships reuse the existing drain curve. No HUD change,
since warships count as part of the side's forces alongside troops.

Tested: 4 new unit tests (same-ramp decay, no-kill-credit destruction,
leader spared, warn-window grace), the full `DoomsdayClockExecution` and
`Warship` suites, the whole test suite (1784 passing), `build-prod`, and
a headless full-game sim run (resolves cleanly with the decay live,
deterministic).
2026-07-03 15:07:28 -07:00
Zixer1 78ef7b56fd feat(doomsday-clock): battle-royale style zone gamemode (#4469)
Resolves Issue #4463

## Description:

An optional game mode that (almost) guarantees a finish instead of
letting late-game
stalemates drag on.
Originally called sudden death, renamed to Doomsday clock

Once enabled, every side (each player in FFA, each whole team in team
modes)
must hold a rising share of the map. A side below the bar is skulled;
after a
short warn its troops bleed to zero, forcing consolidation to a winner.

### How it works
- **Rising zone:** a grace period, then the required share ramps up
linearly to
each level with 30s pauses between (a battle-royale "zone"). Levels
track the
  ofstats FFA territory median (3/5/10/20/30%).
- **Four speed presets** (slow / normal / fast / very fast) change only
the pace:
  normal ends ~30 min, very fast ~15.
- **Troop decay:** a linear ramp as a % of max capacity, ~50s from
caught to zero
  (10s warn + ~50s ≈ 1 min total).
- **UI:** a HUD panel (live share vs target, wave/decay countdowns,
red/orange
cues) and an on-map skull above flagged players (blinks in danger,
steady while
  draining).

### Notes for review
- Off by default; no effect on existing games. However, as discussed we
can add it to the modifier pool for public games to see how popular the
gamemode is vs normal play.
- Sim is deterministic (integer-only, in `src/core`), covered by unit +
  integration tests.
- One-line addition to `GameServer.updateGameConfig` so the setting
survives the
  host → server → client round-trip.
- Status is packed into the existing name-pass data slot (`pd4.w`: 0/1/2
=
none/danger/draining); the skull is composited into the icon atlas at
load.

### Testing
`npm test`, `npm run lint`, `npx prettier --check .`, `npm run
build-prod` all pass.

### UI:
<img width="243" height="100" alt="Image"
src="https://github.com/user-attachments/assets/c4c9eeb0-4feb-437d-9aac-b2786a841b74"
/>

Dropdown between slow, normal, fast, very fast

Before zone:
<img width="302" height="175" alt="Image"
src="https://github.com/user-attachments/assets/7359a1ea-4951-446d-a23c-0711fe06cc5d"
/>

Zone started, player not affected the pannel also blinks orange for 10s:
<img width="297" height="175" alt="Image"
src="https://github.com/user-attachments/assets/fcc565a5-d5d0-47a7-97ea-d0ba9d9ad899"
/>

Player affected, grace period (Danger):
<img width="314" height="170" alt="Image"
src="https://github.com/user-attachments/assets/ff96d21e-96f3-4ef9-8190-48eecc7aac0f"
/>

Skull icon blinking over player (everyone sees it) - older screenshot,
the clipping has been fixed
<img width="462" height="145" alt="Image"
src="https://github.com/user-attachments/assets/53899211-33b1-40e1-83f2-77f2096f0cad"
/>

Player affected, grace period ended (Draining):
<img width="360" height="159" alt="Image"
src="https://github.com/user-attachments/assets/4b226d57-da4d-4866-ab5f-db48e4ed1ea2"
/>

Skull icon no longer blinking, everyone can see you are in a state of
decay, and troops are draining:
<img width="732" height="146" alt="image"
src="https://github.com/user-attachments/assets/cd10fedb-6e87-4dfc-9fbf-55d3945a7901"
/>


Skull is visible like alliances icon also on player tab
<img width="558" height="81" alt="Image"
src="https://github.com/user-attachments/assets/6acdbe91-bdd0-40c7-942b-3990d4dae87f"
/>

(just UI example, best way to see it is to hop on a solo game and play
against AI)

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory

## Please put your Discord username so you can be contacted if a bug or
regression is found:

zixer._
2026-07-02 18:42:03 -07:00