First commit, phased 1 and 2 created but untested

This commit is contained in:
bepis
2026-10-20 07:40:35 +11:00
commit 7a3e408ffc
66 changed files with 5639 additions and 0 deletions
+89
View File
@@ -0,0 +1,89 @@
# GAME_DESIGN.md — Emberfall
## Setting & tone
The Ashen Realm: an old kingdom whose great Ember-Throne has gone dark. Monsters
creep out of the wilds, and heroes gather at the border town of **Cindergate** to
rekindle the Throne. Tone: classic high fantasy, slightly wry. Keep flavour text
short (1–2 sentences). Names should feel Tolkien/D&D-ish but original.
## Core loop (target session: 5–10 min, several times a day)
1. Log in → see energy (regenerated while away) and any finished expedition.
2. Spend energy: hunt monsters, or start an expedition.
3. Collect XP, gold, loot → level up → equip/upgrade → unlock harder zones.
4. Spend leftover gold in shop. Check leaderboard. Log out.
Energy limits session length; timers give reasons to return.
## Time (lazy evaluation — IMPORTANT)
- **Energy**: max 100, +1 per 180 s (3 min). Stored as `(energy, energy_updated_at)`.
On any request that needs energy: `computeEnergy()` → write back the new pair.
At max, regen stops (timestamp resets to now so no "banked" regen).
- **Expeditions**: stored with `ends_at`. "Finished" is just `now >= ends_at`.
Nothing runs at that moment; the player claims it later.
- **HP**: stored as `hp_current`. Natural regen: +1% max HP per minute, computed lazily
the same way as energy (add `hp_updated_at` column if you implement it; otherwise
HP fully restores on level-up and via Rest/potions — v1 acceptable).
- No `setInterval` for game logic. Ever.
## Classes (pick one at creation; permanent in v1)
| Class | Fantasy | Starting STR/AGI/INT/VIT | Bonus |
|---|---|---|---|
| Warrior | Armoured frontliner | 8 / 4 / 2 / 8 | +10% defense |
| Mage | Glass-cannon spellcaster | 2 / 4 / 9 / 5 | +15% damage vs. high-defense foes |
| Ranger | Fast skirmisher | 5 / 9 / 3 / 5 | +8% crit chance |
Primary stat for attack: Warrior→STR, Mage→INT, Ranger→AGI.
Each level grants **3 unspent stat points** (player allocates via API).
## Stats
- **STR** physical power, **AGI** speed & crit, **INT** magic power, **VIT** health.
- Derived stats formulas: see BALANCE.md §Derived.
## Combat (auto-resolved, server-side, turn based)
- Hero vs one monster, alternating attacks. Higher `speed` acts first each round.
- Max 20 rounds; if no one dies, the one with higher HP% wins.
- Each hit: damage formula in BALANCE.md, small random variance, crit chance.
- Output a **round-by-round log** (array of `{round, actor, damage, crit, targetHpAfter}`) for the UI to replay.
- Win: XP + gold + loot rolls. Lose: lose 10% of carried gold (min 0), HP set to 1,
no XP; deaths +1. (Never lose items in v1.)
- Hero HP persists between fights (`hp_current`). Hunting with HP < 20% of max is
blocked: `HP_TOO_LOW` (422) → player must Rest or use a potion.
- Combat resolution takes an injected `rng` so tests are deterministic.
## Zones (v1: 3 required, add more if time permits)
| Zone | Level | Energy | Theme |
|---|---|---|---|
| Whispering Meadows | 1+ | 5 | goblins, wolves, giant rats |
| Gloomroot Forest | 5+ | 8 | spiders, bandits, treants |
| Ashfang Crags | 10+ | 12 | drakes, fire imps, stone golems |
Optional: Sunken Catacombs (15+), Emberthrone Ruins (20+, boss).
## Items
Types: `weapon`, `armor`, `trinket` (equippable, one per slot), `consumable`
(stackable), `material` (stackable, sell-only in v1).
Rarity: common → uncommon → rare → epic → legendary (colour-coded in UI).
Items give flat stat/attack/defense bonuses. Class restrictions: none in v1.
Starter gear: new heroes get one common weapon appropriate to class (auto-equipped) and 2 Minor Healing Potions.
## Economy
- Gold sources: monster drops, expeditions, selling items.
- Gold sinks: shop purchases, Rest (heal to full), (stretch) market tax.
- Sell price = 40% of `buy_price` (items with `buy_price` 0 sell for rarity default: see BALANCE).
- Prices must make the 1st hour feel rewarding but not trivialise gear. See BALANCE.
- Gold can never go below 0; enforced by DB CHECK and service checks.
## Expeditions (the "offline" mechanic)
- Choose one of 3–4 definitions (e.g. "Scout the Old Road" 10 min, "Raid the Bandit Camp" 1 h, "Delve the Hollow" 4 h).
- Costs energy up-front. One active at a time. Hero cannot hunt while on expedition? **No** — hunting is still allowed (keeps it simple).
- Claim after `ends_at`: grants XP + gold (+ a loot roll for 1h+ ones). Double-claim impossible (`claimed_at` set inside the same transaction).
## Leaderboards
Top 50 by: level (tie-break xp), gold, kills. Public. Query on indexed columns. Optionally cache 30 s in memory.
## Names & content rules
- Hero names: 3–16 chars `[A-Za-z0-9 '-]`, unique case-insensitive, trimmed, no double spaces.
- Basic profanity blocklist: small array in `src/game/constants.js` (keep it short; log extension as a TODO).
## Balance targets (sanity check when testing)
- Level 1 → 5 in roughly 40–60 hunts (~2–3 energy refills).
- A fresh Level-1 hero should win ≈ 80% of Meadow fights and lose ≈ 90% against a Crag monster.
- No single item should raise power by > 25% at its tier.