feat(sprint3): items + forge + craft + loot — équipement, artisanat lazy-calc, forge risque GDD
This commit is contained in:
244
SPRINT3.md
Normal file
244
SPRINT3.md
Normal file
@@ -0,0 +1,244 @@
|
||||
# TetaRdPG — Brief Sprint 3
|
||||
|
||||
> Statut : 🔄 En cours
|
||||
> Objectif : Items + Inventaire + Artisanat (Craft) + Forge
|
||||
> Stack : NestJS · PostgreSQL · TypeORM (synchronize dev)
|
||||
> Prérequis : Sprint 2 livré ✅
|
||||
|
||||
---
|
||||
|
||||
## Scope Sprint 3
|
||||
|
||||
### ✅ In scope
|
||||
|
||||
- Entité `items` (armes + armures) avec bonus stats
|
||||
- Inventaire joueur (`character_items`) — possession + équipement actif
|
||||
- Intégration combat : `player.attack` et `player.defense` depuis l'équipement équipé
|
||||
- Entité `materials` + inventaire joueur (`character_materials`) — loot post-combat
|
||||
- Entité `recipes` + ingrédients en jsonb
|
||||
- Artisanat (`craft_jobs`) — lazy calc timer (même pattern que endurance)
|
||||
- Forge — amélioration item niveau 1–5 avec risque croissant
|
||||
- Seeds : 5 items de base, 5 matériaux, 3 recettes
|
||||
- API : voir section dédiée
|
||||
|
||||
### ❌ Out of scope
|
||||
|
||||
- Boutique (achat/vente) — Sprint 4
|
||||
- Bonus de sets d'équipement — Sprint 4
|
||||
- TetardCoin (accélération craft, forge garantie) — sprint monétisation
|
||||
- Twitch, PvP, guildes
|
||||
- Frontend React
|
||||
|
||||
---
|
||||
|
||||
## Décisions de design (game-designer)
|
||||
|
||||
| Décision | Valeur | Justification |
|
||||
|----------|--------|---------------|
|
||||
| Slots équipement | weapon + armor | Simplifié Sprint 3 — casque/bottes Sprint 4 |
|
||||
| Player.attack en combat | `char.weapon?.attackBonus ?? 0` | Remplace attack=0 Sprint 2 |
|
||||
| Player.defense en combat | `char.armor?.defenseBonus ?? 0` | Remplace defense=0 Sprint 2 |
|
||||
| Loot drop | 40% de chance après victoire | 1 matériau aléatoire parmi ceux du monstre |
|
||||
| Craft timer | lazy calc : `startedAt + durationMs` | Même pattern endurance — zéro job schedulé |
|
||||
| Forge risque | Niv.1–2 : 0% | 3 : 20% | 4 : 30% | 5 : 40% | GDD exact |
|
||||
| Forge succès garanti | 12 TetardCoin (non implémenté Sprint 3) | Placeholder, champ `forcedSuccess` |
|
||||
| Forge échec | item inchangé, pas de coût matériaux Sprint 3 | coût matériaux forge = Sprint 4 |
|
||||
| Durée craft | court: 15s (dev) / long: 60s (dev) | Valeurs réelles en prod : 15min–2h |
|
||||
|
||||
---
|
||||
|
||||
## Schéma DB
|
||||
|
||||
### `items`
|
||||
```
|
||||
id uuid PK
|
||||
name varchar(100)
|
||||
description text
|
||||
type varchar(20) -- 'weapon' | 'armor'
|
||||
rarity varchar(20) -- 'common' | 'rare' | 'epic' | 'legendary'
|
||||
attack_bonus int default 0
|
||||
defense_bonus int default 0
|
||||
force_bonus int default 0
|
||||
agilite_bonus int default 0
|
||||
intelligence_bonus int default 0
|
||||
chance_bonus int default 0
|
||||
vitalite_bonus int default 0
|
||||
```
|
||||
|
||||
### `character_items`
|
||||
```
|
||||
id uuid PK
|
||||
character_id uuid FK characters
|
||||
item_id uuid FK items
|
||||
forge_level int default 0 -- 0 = non forgé
|
||||
equipped boolean default false
|
||||
acquired_at timestamp
|
||||
```
|
||||
|
||||
### `materials`
|
||||
```
|
||||
id uuid PK
|
||||
name varchar(100)
|
||||
description text
|
||||
rarity varchar(20)
|
||||
```
|
||||
|
||||
### `character_materials`
|
||||
```
|
||||
id uuid PK
|
||||
character_id uuid FK characters
|
||||
material_id uuid FK materials
|
||||
quantity int default 0
|
||||
```
|
||||
|
||||
### `recipes`
|
||||
```
|
||||
id uuid PK
|
||||
name varchar(100)
|
||||
result_item_id uuid FK items
|
||||
craft_duration_seconds int
|
||||
endurance_cost int
|
||||
ingredients jsonb -- [{ materialId, quantity }]
|
||||
```
|
||||
|
||||
### `craft_jobs`
|
||||
```
|
||||
id uuid PK
|
||||
character_id uuid FK characters
|
||||
recipe_id uuid FK recipes
|
||||
started_at timestamp
|
||||
completed_at timestamp -- lazy : startedAt + duration
|
||||
collected boolean default false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Seeds
|
||||
|
||||
### Items (5)
|
||||
|
||||
| Nom | Type | Rareté | Attack | Defense | Notes |
|
||||
|-----|------|--------|--------|---------|-------|
|
||||
| Bâton de Roseau | weapon | common | 3 | 0 | Arme de départ |
|
||||
| Dague Rouillée | weapon | common | 5 | 0 | |
|
||||
| Épée Courte | weapon | rare | 9 | 0 | |
|
||||
| Gilet de Cuir | armor | common | 0 | 3 | |
|
||||
| Cotte de Mailles | armor | rare | 0 | 7 | |
|
||||
|
||||
### Matériaux (5)
|
||||
|
||||
| Nom | Rareté | Sources |
|
||||
|-----|--------|---------|
|
||||
| Bave de Têtard | common | Têtard Vase |
|
||||
| Écailles de Grenouille | common | Grenouille Boueuse |
|
||||
| Venin de Serpent | rare | Serpent des Marais |
|
||||
| Spores Vénéneuses | rare | Champi Vénéneux |
|
||||
| Fragment de Boue | common | Golem de Boue |
|
||||
|
||||
### Recettes (3)
|
||||
|
||||
| Nom | Résultat | Durée (dev) | Endurance | Ingrédients |
|
||||
|-----|----------|-------------|-----------|-------------|
|
||||
| Forge Bâton Renforcé | Bâton de Roseau+? | 15s | 5 | 2× Bave de Têtard |
|
||||
| Craft Dague | Dague Rouillée | 15s | 8 | 3× Bave + 1× Écaille |
|
||||
| Craft Gilet de Cuir | Gilet de Cuir | 30s | 10 | 3× Écaille + 2× Fragment |
|
||||
|
||||
---
|
||||
|
||||
## API Sprint 3
|
||||
|
||||
```
|
||||
# Items
|
||||
GET /api/items → liste tous les items (catalogue)
|
||||
GET /api/items/inventory → inventaire du personnage connecté
|
||||
POST /api/items/equip/:itemId → équiper un item (character_items.id)
|
||||
POST /api/items/unequip/:slot → déséquiper un slot (weapon|armor)
|
||||
|
||||
# Materials
|
||||
GET /api/materials → catalogue matériaux
|
||||
GET /api/materials/inventory → matériaux du personnage connecté
|
||||
|
||||
# Craft
|
||||
GET /api/craft/recipes → liste recettes
|
||||
POST /api/craft/start → { recipeId } → lance le craft
|
||||
GET /api/craft/active → craft en cours (lazy status)
|
||||
POST /api/craft/collect/:jobId → collecter si terminé
|
||||
|
||||
# Forge
|
||||
POST /api/forge/upgrade → { characterItemId } → tente amélioration
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Architecture modules
|
||||
|
||||
```
|
||||
src/
|
||||
├── item/
|
||||
│ ├── item.entity.ts
|
||||
│ ├── character-item.entity.ts
|
||||
│ ├── item.module.ts
|
||||
│ ├── item.service.ts
|
||||
│ └── item.controller.ts
|
||||
├── material/
|
||||
│ ├── material.entity.ts
|
||||
│ ├── character-material.entity.ts
|
||||
│ ├── material.module.ts
|
||||
│ ├── material.service.ts
|
||||
│ └── material.controller.ts
|
||||
├── craft/
|
||||
│ ├── recipe.entity.ts
|
||||
│ ├── craft-job.entity.ts
|
||||
│ ├── craft.module.ts
|
||||
│ ├── craft.service.ts
|
||||
│ └── craft.controller.ts
|
||||
├── forge/
|
||||
│ ├── forge.module.ts
|
||||
│ ├── forge.service.ts
|
||||
│ └── forge.controller.ts
|
||||
└── database/
|
||||
└── items-seed.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Intégration combat (CombatEngine)
|
||||
|
||||
```typescript
|
||||
// Dans CombatService.startCombat() — charger l'équipement
|
||||
const weaponBonus = char.equippedWeapon?.item.attackBonus ?? 0;
|
||||
const armorBonus = char.equippedArmor?.item.defenseBonus ?? 0;
|
||||
|
||||
const playerStats: CombatantStats = {
|
||||
...
|
||||
attack: weaponBonus, // était 0 Sprint 2
|
||||
defense: armorBonus, // était 0 Sprint 2
|
||||
};
|
||||
```
|
||||
|
||||
Loot post-victoire :
|
||||
```typescript
|
||||
if (result.winner === 'player' && Math.random() < 0.4) {
|
||||
// créditer 1 matériau aléatoire dans character_materials
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Critères de validation integrator
|
||||
|
||||
- [ ] `GET /api/items` → 5 items seedés
|
||||
- [ ] `GET /api/materials` → 5 matériaux seedés
|
||||
- [ ] `POST /api/items/equip/:id` → item équipé, character mis à jour
|
||||
- [ ] Combat avec arme équipée → player.attack = weaponBonus
|
||||
- [ ] Victoire combat → chance de loot matériau (40%)
|
||||
- [ ] `GET /api/materials/inventory` → quantité augmentée après loot
|
||||
- [ ] `GET /api/craft/recipes` → 3 recettes disponibles
|
||||
- [ ] `POST /api/craft/start` → job créé, endurance déduite
|
||||
- [ ] `GET /api/craft/active` → status `pending` | `ready` | `none`
|
||||
- [ ] `POST /api/craft/collect/:jobId` → item ajouté à l'inventaire
|
||||
- [ ] Collect avant fin → 400 "not ready yet"
|
||||
- [ ] `POST /api/forge/upgrade` → niveau 1 : succès garanti
|
||||
- [ ] Forge niveau 3 → 20% chance échec (matériaux déduits, forgeLvl inchangé)
|
||||
- [ ] Sans cookie → 401 sur toutes les routes protégées
|
||||
- [ ] Endurance insuffisante pour craft → 400
|
||||
Reference in New Issue
Block a user