feat(api): mirror HP onto the character each round and resume regen at combat end

This commit is contained in:
Bastian Wagner
2026-08-21 15:08:04 +02:00
parent ac1329be46
commit b070bf2b0d
2 changed files with 51 additions and 4 deletions

View File

@@ -579,6 +579,41 @@ describe('CombatService', () => {
});
});
it('mirrors the player HP onto the character each round while the fight continues', async () => {
const { dataSource, service, combatId } = await startedCombat();
await service.performAction(CHARACTER_ID, combatId, CombatAction.ATTACK);
expect(dataSource.state.characters[0].currentHp).toBe(95);
expect(dataSource.state.characters[0].hpRegenSince).toBeNull();
});
it('restarts regeneration on the character once the fight is won', async () => {
const state = createState({ monsters: [monster({ maxHp: 10 })] });
const { dataSource, service, combatId } = await startedCombat(state);
await service.performAction(CHARACTER_ID, combatId, CombatAction.ATTACK);
expect(dataSource.state.characters[0].currentHp).toBe(
dataSource.state.combats[0].playerCurrentHp,
);
expect(dataSource.state.characters[0].hpRegenSince).toEqual(
new Date('2026-08-18T09:00:00.000Z'),
);
});
it('restarts regeneration from 0 HP once the fight is lost', async () => {
const state = createState({ characters: [character({ baseHp: 1, currentHp: 1 })] });
const { dataSource, service, combatId } = await startedCombat(state);
await service.performAction(CHARACTER_ID, combatId, CombatAction.ATTACK);
expect(dataSource.state.characters[0].currentHp).toBe(0);
expect(dataSource.state.characters[0].hpRegenSince).toEqual(
new Date('2026-08-18T09:00:00.000Z'),
);
});
it('ends the combat as WON, stops persisting new rounds, and rejects further actions', async () => {
const state = createState({ monsters: [monster({ maxHp: 10 })] });
const { dataSource, service, combatId } = await startedCombat(state);
@@ -650,11 +685,19 @@ describe('CombatService', () => {
);
});
it('lets a lost encounter be fought again as a fresh combat', async () => {
it('lets a lost encounter be fought again once the character has recovered HP', async () => {
const state = createState({ characters: [character({ baseHp: 1, currentHp: 1 })] });
const { dataSource, service, combatId } = await startedCombat(state);
await service.performAction(CHARACTER_ID, combatId, CombatAction.ATTACK);
// The loss now mirrors 0 HP onto the character (this task); simulate
// that regeneration has since restored it before retrying. This test
// is about the encounter itself being retryable once the character
// can fight again, not about regen math (covered by
// CharacterVitalsService's own tests).
dataSource.state.characters[0].currentHp = 1;
dataSource.state.characters[0].hpRegenSince = null;
const retry = await service.startCombat(CHARACTER_ID, ENCOUNTER_ID);
expect(retry.id).not.toBe(combatId);