fix: endurance regen 6min→3min dans combat/forge/craft + potions d'énergie
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 32s

Bug: combat/forge/craft calculaient la regen à 1pt/6min (ancien) alors que
character.service utilisait 1pt/3min (nouveau). Le joueur voyait 8 endurance
dans le HUD mais le backend refusait le combat avec 4.

Potions d'énergie: Potion (30 endurance, 20 or) + Grande (60 endurance, 45 or).
Consommable instantané via la boutique — le joueur peut acheter du temps de jeu.
This commit is contained in:
2026-03-24 17:51:30 +01:00
parent 1ffde61f97
commit 8cb5fcd5ba
6 changed files with 49 additions and 10 deletions

View File

@@ -57,7 +57,7 @@ export class CombatService {
// Calculer l'endurance actuelle (lazy pattern)
const elapsedMinutes = (Date.now() - character.lastEnduranceTs.getTime()) / 60_000;
const recharge = Math.floor(elapsedMinutes / 6);
const recharge = Math.floor(elapsedMinutes / 3);
const enduranceCurrent = Math.min(character.enduranceSaved + recharge, character.enduranceMax);
if (enduranceCurrent < COMBAT_ENDURANCE_COST) {

View File

@@ -40,7 +40,7 @@ export class CraftService {
// Calculer endurance actuelle (lazy pattern)
const elapsedMinutes = (Date.now() - char.lastEnduranceTs.getTime()) / 60_000;
const recharge = Math.floor(elapsedMinutes / 6);
const recharge = Math.floor(elapsedMinutes / 3);
const enduranceCurrent = Math.min(char.enduranceSaved + recharge, char.enduranceMax);
if (enduranceCurrent < recipe.enduranceCost) {

View File

@@ -47,8 +47,11 @@ const ITEMS = [
{ name: 'Armure du Pharaon', type: 'armor', rarity: 'epic', attackBonus: 0, defenseBonus: 18, buyPrice: 1300, minLevel: 13, zone: 'desert', description: 'Dorée et ancienne, elle irradie de puissance.' },
// Potions — consommables
{ name: 'Potion de soin', type: 'consumable', rarity: 'common', attackBonus: 0, defenseBonus: 0, buyPrice: 15, minLevel: 1, zone: null, description: 'Restaure 50% des PV.' },
{ name: 'Grande potion de soin', type: 'consumable', rarity: 'rare', attackBonus: 0, defenseBonus: 0, buyPrice: 40, minLevel: 5, zone: null, description: 'Restaure 50% des PV. (même effet, plus cher — placeholder pour futur)' },
// HP potions: forceBonus = 0 → heal 50% HP
{ name: 'Potion de soin', type: 'consumable', rarity: 'common', attackBonus: 0, defenseBonus: 0, forceBonus: 0, buyPrice: 15, minLevel: 1, zone: null, description: 'Restaure 50% des PV.' },
// Endurance potions: forceBonus > 0 → restore N endurance
{ name: 'Potion d\'énergie', type: 'consumable', rarity: 'common', attackBonus: 0, defenseBonus: 0, forceBonus: 30, buyPrice: 20, minLevel: 1, zone: null, description: 'Restaure 30 points d\'endurance.' },
{ name: 'Grande potion d\'énergie', type: 'consumable', rarity: 'rare', attackBonus: 0, defenseBonus: 0, forceBonus: 60, buyPrice: 45, minLevel: 3, zone: null, description: 'Restaure 60 points d\'endurance.' },
];
export async function seedZones(dataSource: DataSource) {

View File

@@ -70,7 +70,7 @@ export class ForgeService {
// Vérifier endurance
const elapsedMinutes = (Date.now() - char.lastEnduranceTs.getTime()) / 60_000;
const recharge = Math.floor(elapsedMinutes / 6);
const recharge = Math.floor(elapsedMinutes / 3);
const enduranceCurrent = Math.min(char.enduranceSaved + recharge, char.enduranceMax);
if (enduranceCurrent < FORGE_ENDURANCE_COST) {

View File

@@ -62,12 +62,42 @@ export class ShopService {
// Consumable = effet immédiat, pas d'inventaire
if (item.type === 'consumable') {
char.gold -= item.buyPrice;
// Endurance potion: forceBonus > 0 = endurance restore amount
const isEndurancePotion = item.forceBonus > 0;
if (isEndurancePotion) {
// Calc current endurance (lazy)
const elapsed = (Date.now() - char.lastEnduranceTs.getTime()) / 60_000;
const recharge = Math.floor(elapsed / 3);
const currentEndurance = Math.min(char.enduranceSaved + recharge, char.enduranceMax);
if (currentEndurance >= char.enduranceMax) {
throw new BadRequestException('Endurance déjà au maximum');
}
char.gold -= item.buyPrice;
const endBefore = currentEndurance;
const restored = Math.min(item.forceBonus, char.enduranceMax - currentEndurance);
char.enduranceSaved = currentEndurance + restored;
char.lastEnduranceTs = new Date();
await manager.save(char);
return {
bought: true,
item: item.name,
type: 'consumable',
effectType: 'endurance',
goldSpent: item.buyPrice,
effect: { enduranceBefore: endBefore, enduranceAfter: char.enduranceSaved, restored },
};
}
// HP potion
if (char.hpCurrent >= char.hpMax) {
throw new BadRequestException('PV déjà au maximum');
}
char.gold -= item.buyPrice;
const hpBefore = char.hpCurrent;
char.hpCurrent = Math.min(char.hpMax, char.hpCurrent + Math.floor(char.hpMax * POTION_HEAL_RATIO));
await manager.save(char);
@@ -76,6 +106,7 @@ export class ShopService {
bought: true,
item: item.name,
type: 'consumable',
effectType: 'hp',
goldSpent: item.buyPrice,
effect: { hpBefore, hpAfter: char.hpCurrent, healed: char.hpCurrent - hpBefore },
};