feat: Sprint 2 — moteur de combat PvE TetaRdPG
Moteur combat stateless (POST /api/combat/start résout le combat complet). Formules GDD : Mêlée/Distance/Magie × 1.5, critique (5% + Chance×0.2%), esquive (5% + Chance×0.1%). 5 monstres seedés (Têtard Vase → Golem de Boue, level 1–9). Level up : XP → seuil atteint → level++, +5 statPoints. Persiste combat_logs (jsonb rounds). Validé : victoire, défaite, 401, 400, 404.
This commit is contained in:
126
SPRINT2.md
Normal file
126
SPRINT2.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# TetaRdPG — Brief Sprint 2
|
||||
|
||||
> Statut : 🔄 En cours
|
||||
> Objectif : Moteur de combat PvE + retours textuels (logs)
|
||||
> Stack : NestJS · PostgreSQL · TypeORM (synchronize dev)
|
||||
> Prérequis : Sprint 1 livré ✅
|
||||
|
||||
---
|
||||
|
||||
## Scope Sprint 2
|
||||
|
||||
### ✅ In scope
|
||||
|
||||
- Entité `monsters` (5 monstres seedés, level 1–8)
|
||||
- Moteur de combat PvE — résolution stateless côté serveur (un POST = combat complet)
|
||||
- Formules GDD : Mêlée/Distance/Magie × 1.5 | Critique | Esquive
|
||||
- Fin de combat : Victoire (XP + Or + +10% PV) / Défaite (20% PV + −50 endurance + perte or)
|
||||
- Persistance des combats (`combat_logs`)
|
||||
- Mise à jour character post-combat : hpCurrent, endurance, xp, gold, level, statPoints
|
||||
- Level up basique : XP → seuil atteint → level++, +5 statPoints
|
||||
- API : `GET /api/monsters`, `POST /api/combat/start`, `GET /api/combat/history`
|
||||
|
||||
### ❌ Out of scope
|
||||
|
||||
- Interactivité tour par tour (choix action par round) — Sprint 3
|
||||
- Équipement / armure / arme → défense joueur = 0 Sprint 2
|
||||
- Forge, artisanat, boutique
|
||||
- Twitch, PvP
|
||||
- Frontend React
|
||||
|
||||
---
|
||||
|
||||
## Décisions de design (game-designer)
|
||||
|
||||
| Décision | Valeur Sprint 2 | Justification |
|
||||
|----------|----------------|---------------|
|
||||
| Dégâts joueur | `Math.floor(stat × 1.5)` | Arme = 0 (pas d'équipement) |
|
||||
| Défense joueur | 0 | Pas d'armure Sprint 2 |
|
||||
| Crit | `5% + Chance × 0.2%` → dégâts ×1.5 | GDD |
|
||||
| Esquive | `5% + Chance × 0.1%` → annule dégâts | GDD |
|
||||
| Crit/Esquive monstres | Non (Sprint 2) | Simplification, fairness joueur |
|
||||
| Défaite HP | 20% hpMax (retour auberge) | GDD "retour auberge" |
|
||||
| Coût combat défaite | −10 (start) + −50 (peine) = −60 | GDD |
|
||||
| Level up | `XP requise = round(100 × level^1.5)` | Formule GDD |
|
||||
| Stat points / level | +5 par level franchi | GDD |
|
||||
|
||||
---
|
||||
|
||||
## Monstres seedés
|
||||
|
||||
| Nom | Level min | Level max | HP | Attaque | Défense | Type | XP | Or (min-max) |
|
||||
|-----|-----------|-----------|-----|---------|---------|------|----|-------------|
|
||||
| Têtard Vase | 1 | 2 | 40 | 5 | 0 | melee | 25 | 3–8 |
|
||||
| Grenouille Boueuse | 2 | 4 | 65 | 8 | 1 | melee | 45 | 6–15 |
|
||||
| Serpent des Marais | 3 | 6 | 90 | 11 | 2 | ranged | 70 | 10–25 |
|
||||
| Champi Vénéneux | 2 | 5 | 75 | 9 | 3 | magic | 60 | 8–20 |
|
||||
| Golem de Boue | 6 | 9 | 150 | 16 | 5 | melee | 130 | 25–60 |
|
||||
|
||||
---
|
||||
|
||||
## API Sprint 2
|
||||
|
||||
```
|
||||
GET /api/monsters → liste tous les monstres
|
||||
POST /api/combat/start → { monsterId, attackType: 'melee'|'ranged'|'magic' }
|
||||
GET /api/combat/history → combats du personnage connecté
|
||||
```
|
||||
|
||||
### Format réponse POST /api/combat/start
|
||||
|
||||
```json
|
||||
{
|
||||
"winner": "player",
|
||||
"rounds": [
|
||||
{
|
||||
"round": 1,
|
||||
"playerDamage": 6, "playerCrit": true, "monsterDodged": false,
|
||||
"monsterDamage": 5, "playerDodged": false,
|
||||
"playerHp": 95, "monsterHp": 34,
|
||||
"log": ["Tetard frappe le Têtard Vase pour 6 dégâts (CRITIQUE) !", "Le Têtard Vase frappe Tetard pour 5 dégâts."]
|
||||
}
|
||||
],
|
||||
"summary": "Victoire en 7 tours ! +25 XP, +5 Or.",
|
||||
"rewards": { "xp": 25, "gold": 5, "levelUp": false },
|
||||
"character": { "level": 1, "xp": 25, "gold": 5, "hpCurrent": 75, "enduranceCurrent": 90 }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Architecture modules
|
||||
|
||||
```
|
||||
src/
|
||||
├── monster/
|
||||
│ ├── monster.entity.ts
|
||||
│ ├── monster.module.ts
|
||||
│ ├── monster.service.ts
|
||||
│ └── monster.controller.ts
|
||||
├── combat/
|
||||
│ ├── combat.engine.ts → fonctions pures (pas de dépendances NestJS)
|
||||
│ ├── combat-log.entity.ts
|
||||
│ ├── combat.service.ts
|
||||
│ ├── combat.controller.ts
|
||||
│ ├── combat.module.ts
|
||||
│ └── dto/start-combat.dto.ts
|
||||
└── database/
|
||||
└── monsters-seed.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Critères de validation integrator
|
||||
|
||||
- [ ] `GET /api/monsters` → liste 5 monstres
|
||||
- [ ] `POST /api/combat/start` → combat résolu, log retourné
|
||||
- [ ] Personnage level 1 peut vaincre Têtard Vase
|
||||
- [ ] XP et or crédités après victoire
|
||||
- [ ] `hpCurrent` mis à jour en DB après combat
|
||||
- [ ] Endurance déduite (−10) après combat
|
||||
- [ ] Défaite : `hpCurrent` = 20% hpMax, endurance −60 total
|
||||
- [ ] `GET /api/combat/history` → historique retourné
|
||||
- [ ] Sans cookie → 401
|
||||
- [ ] Endurance insuffisante (< 10) → 400
|
||||
- [ ] Monster inexistant → 404
|
||||
- [ ] Level up déclenché si XP seuil atteint
|
||||
Reference in New Issue
Block a user