From 0d917a8b39efac9f65af51ad7bde0d9bf8ede0c2 Mon Sep 17 00:00:00 2001 From: Tetardtek Date: Tue, 24 Mar 2026 21:53:45 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20audit=20Phase=201=20=E2=80=94=20P0/P1?= =?UTF-8?q?=20quick=20wins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix vitalité: HP initial = 100 + (vitalité-1)×10 - Arme de départ: Bâton de Roseau équipé à la création - Rebalance forge: niv3 200, niv4 400, niv5 700 (−30%) - Confirmation avant vente d'item (confirm dialog) - Fix forge costs dupliqués (shop sellback + inventaire) --- frontend/src/pages/GuidePage.tsx | 6 +++--- frontend/src/pages/InventoryPage.tsx | 6 +++--- src/character/character.service.ts | 20 ++++++++++++++++++++ src/forge/forge.service.ts | 6 +++--- src/shop/shop.service.ts | 2 +- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/frontend/src/pages/GuidePage.tsx b/frontend/src/pages/GuidePage.tsx index 34f20cf..60476b8 100644 --- a/frontend/src/pages/GuidePage.tsx +++ b/frontend/src/pages/GuidePage.tsx @@ -23,9 +23,9 @@ const RARITY_LABELS: Record = { const FORGE_TABLE = [ { level: 1, gold: 50, endurance: 10, risk: '0%', bonus: '+2' }, { level: 2, gold: 100, endurance: 10, risk: '0%', bonus: '+4' }, - { level: 3, gold: 250, endurance: 10, risk: '20%', bonus: '+6' }, - { level: 4, gold: 500, endurance: 10, risk: '30%', bonus: '+8' }, - { level: 5, gold: 1000, endurance: 10, risk: '40%', bonus: '+10' }, + { level: 3, gold: 200, endurance: 10, risk: '20%', bonus: '+6' }, + { level: 4, gold: 400, endurance: 10, risk: '30%', bonus: '+8' }, + { level: 5, gold: 700, endurance: 10, risk: '40%', bonus: '+10' }, ]; const TABS = [ diff --git a/frontend/src/pages/InventoryPage.tsx b/frontend/src/pages/InventoryPage.tsx index 897c495..6375436 100644 --- a/frontend/src/pages/InventoryPage.tsx +++ b/frontend/src/pages/InventoryPage.tsx @@ -16,7 +16,7 @@ function ItemCard({ ci, onEquip, onUnequip, onSell, selling }: { const forgeBonusDEF = item.type === 'armor' ? ci.forgeLevel * 2 : 0; const totalATK = item.attackBonus + forgeBonusATK; const totalDEF = item.defenseBonus + forgeBonusDEF; - const FORGE_COSTS: Record = { 1: 50, 2: 100, 3: 250, 4: 500, 5: 1000 }; + const FORGE_COSTS: Record = { 1: 50, 2: 100, 3: 200, 4: 400, 5: 700 }; let forgeInvestment = 0; for (let i = 1; i <= ci.forgeLevel; i++) forgeInvestment += FORGE_COSTS[i] ?? 0; const sellPrice = Math.floor(((item as any).buyPrice || 0) * 0.4 + forgeInvestment * 0.5); @@ -125,7 +125,7 @@ export function InventoryPage() { key={ci.id} ci={ci} onEquip={() => equipMut.mutate(ci.id)} onUnequip={() => unequipMut.mutate('weapon')} - onSell={() => sellMut.mutate(ci.id)} + onSell={() => { if (confirm(`Vendre ${ci.item.name} ?`)) sellMut.mutate(ci.id); }} selling={sellMut.isPending} /> ))} @@ -145,7 +145,7 @@ export function InventoryPage() { key={ci.id} ci={ci} onEquip={() => equipMut.mutate(ci.id)} onUnequip={() => unequipMut.mutate('armor')} - onSell={() => sellMut.mutate(ci.id)} + onSell={() => { if (confirm(`Vendre ${ci.item.name} ?`)) sellMut.mutate(ci.id); }} selling={sellMut.isPending} /> ))} diff --git a/src/character/character.service.ts b/src/character/character.service.ts index 24cb25d..de8a5b6 100644 --- a/src/character/character.service.ts +++ b/src/character/character.service.ts @@ -11,6 +11,8 @@ import { LevelThreshold } from './entities/level-threshold.entity'; import { CreateCharacterDto } from './dto/create-character.dto'; import { DistributeStatsDto } from './dto/distribute-stats.dto'; import { User } from '../user/user.entity'; +import { Item } from '../item/item.entity'; +import { CharacterItem } from '../item/character-item.entity'; import { xpRequiredForLevel } from '../combat/combat.engine'; const STAT_POOL = 10; // 5 stats × 1 base + 5 points à distribuer @@ -53,6 +55,7 @@ export class CharacterService { throw new ConflictException('Ce joueur possède déjà un personnage'); } + const baseHp = 100 + (dto.vitalite - 1) * 10; // vitalité 1 = 100 HP, chaque point = +10 const character = this.characterRepository.create({ userId: user.id, name: dto.name, @@ -61,12 +64,29 @@ export class CharacterService { intelligence: dto.intelligence, chance: dto.chance, vitalite: dto.vitalite, + hpMax: baseHp, + hpCurrent: baseHp, enduranceSaved: 100, lastEnduranceTs: new Date(), enduranceMax: 100, }); const saved = await this.characterRepository.save(character); + + // Arme de départ — Bâton de Roseau équipé automatiquement + const starterWeapon = await this.dataSource.getRepository(Item) + .findOne({ where: { name: 'Bâton de Roseau' } }); + if (starterWeapon) { + await this.dataSource.getRepository(CharacterItem).save( + this.dataSource.getRepository(CharacterItem).create({ + characterId: saved.id, + itemId: starterWeapon.id, + forgeLevel: 0, + equipped: true, + }), + ); + } + return { ...saved, enduranceCurrent: this.calculateEndurance(saved), diff --git a/src/forge/forge.service.ts b/src/forge/forge.service.ts index 75b5345..dcae870 100644 --- a/src/forge/forge.service.ts +++ b/src/forge/forge.service.ts @@ -13,9 +13,9 @@ const FORGE_BONUS_PER_LEVEL = 2; const FORGE_GOLD_COST: Record = { 1: 50, 2: 100, - 3: 250, - 4: 500, - 5: 1000, + 3: 200, + 4: 400, + 5: 700, }; const FORGE_ENDURANCE_COST = 10; diff --git a/src/shop/shop.service.ts b/src/shop/shop.service.ts index 0b040bc..09699d0 100644 --- a/src/shop/shop.service.ts +++ b/src/shop/shop.service.ts @@ -154,7 +154,7 @@ export class ShopService { if (charItem.equipped) throw new BadRequestException('Déséquipez l\'item avant de le vendre'); // Prix de vente = base + investissement forge (coûts cumulés * 50%) - const FORGE_GOLD_COST: Record = { 1: 50, 2: 100, 3: 250, 4: 500, 5: 1000 }; + const FORGE_GOLD_COST: Record = { 1: 50, 2: 100, 3: 200, 4: 400, 5: 700 }; let forgeInvestment = 0; for (let i = 1; i <= charItem.forgeLevel; i++) { forgeInvestment += FORGE_GOLD_COST[i] ?? 0;