feat: multi-combat ×5/×10 + cooldown anti-spam
Some checks failed
CI/CD — Build & Deploy / Build & Deploy (push) Failing after 30s
Some checks failed
CI/CD — Build & Deploy / Build & Deploy (push) Failing after 30s
- Backend: startMultiCombat boucle séquentielle, arrêt sur défaite - Frontend: cooldown 1.5s entre combats, boutons ×1/×5/×10 - Frontend: résumé multi-combat (wins/losses, XP/Or/loot totaux) - Fix: lock contention par spam de clics résolu
This commit is contained in:
@@ -287,6 +287,40 @@ export class CombatService {
|
||||
return txResult.response;
|
||||
}
|
||||
|
||||
async startMultiCombat(dto: StartCombatDto, user: User, count: number) {
|
||||
const results: any[] = [];
|
||||
const totals = { wins: 0, losses: 0, xp: 0, gold: 0, goldLost: 0, loot: [] as { name: string; quantity: number }[], levelsGained: 0 };
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
try {
|
||||
const result = await this.startCombat(dto, user);
|
||||
results.push(result);
|
||||
if (result.winner === 'player') {
|
||||
totals.wins++;
|
||||
totals.xp += result.rewards.xp;
|
||||
totals.gold += result.rewards.gold;
|
||||
if (result.rewards.levelUp) totals.levelsGained++;
|
||||
if (result.rewards.loot) totals.loot.push(result.rewards.loot);
|
||||
} else {
|
||||
totals.losses++;
|
||||
totals.goldLost += result.rewards.goldLost ?? 0;
|
||||
break; // Défaite = arrêt de la série
|
||||
}
|
||||
} catch {
|
||||
break; // Endurance insuffisante ou autre erreur = arrêt
|
||||
}
|
||||
}
|
||||
|
||||
const lastResult = results[results.length - 1];
|
||||
return {
|
||||
mode: 'multi',
|
||||
count: results.length,
|
||||
totals,
|
||||
lastResult,
|
||||
character: lastResult?.character,
|
||||
};
|
||||
}
|
||||
|
||||
async getHistory(user: User) {
|
||||
const character = await this.characterRepository.findOne({
|
||||
where: { userId: user.id },
|
||||
|
||||
Reference in New Issue
Block a user