fix(combat): show the potion heal immediately instead of folding it into the monster's reply
This commit is contained in:
@@ -339,6 +339,51 @@ describe('CombatPageComponent', () => {
|
|||||||
expect(monster?.classList.contains('sprite--lunge')).toBe(false);
|
expect(monster?.classList.contains('sprite--lunge')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('shows the potion heal at the first checkpoint instead of waiting for the riposte reveal', async () => {
|
||||||
|
const fixture = await setup({
|
||||||
|
...activeCombat,
|
||||||
|
player: { ...activeCombat.player, currentHp: 70 },
|
||||||
|
});
|
||||||
|
const healed: Combat = {
|
||||||
|
...activeCombat,
|
||||||
|
round: 3,
|
||||||
|
player: { ...activeCombat.player, currentHp: 80, potionsRemaining: 1 },
|
||||||
|
events: [
|
||||||
|
...activeCombat.events,
|
||||||
|
{ round: 2, sequence: 3, type: 'HEAL', source: 'PLAYER', target: 'PLAYER', amount: 15 },
|
||||||
|
{ round: 2, sequence: 4, type: 'DAMAGE', source: 'MONSTER', target: 'PLAYER', amount: 5 },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
combatStore.performAction.mockImplementation(async () => {
|
||||||
|
combatStore.combat.set(healed);
|
||||||
|
});
|
||||||
|
vi.useFakeTimers();
|
||||||
|
|
||||||
|
const element = fixture.nativeElement as HTMLElement;
|
||||||
|
element.querySelector<HTMLButtonElement>('[data-combat-potion]')?.click();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
// Before the checkpoint: the pre-heal HP and potion count still show.
|
||||||
|
expect(element.textContent).toContain('70 / 100');
|
||||||
|
expect(element.querySelector('[data-combat-potion]')?.textContent).toContain('Trank 2/2');
|
||||||
|
|
||||||
|
// First checkpoint: the heal already landed from the player's own action,
|
||||||
|
// so the HP bar and potion count update here -- well before the monster's
|
||||||
|
// held-back reply resolves.
|
||||||
|
await vi.advanceTimersByTimeAsync(540);
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(element.textContent).toContain('85 / 100');
|
||||||
|
expect(element.querySelector('[data-combat-potion]')?.textContent).toContain('Trank 1/2');
|
||||||
|
expect(element.textContent).toContain('Aric Duskwalker trinkt einen Trank und heilt 15 Lebenspunkte.');
|
||||||
|
|
||||||
|
// The monster's reply is still held back at this point.
|
||||||
|
expect(countOccurrences(element.textContent, monsterHitLine)).toBe(1);
|
||||||
|
|
||||||
|
await vi.advanceTimersByTimeAsync(1260);
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(element.textContent).toContain('80 / 100');
|
||||||
|
});
|
||||||
|
|
||||||
it('skips the recoil when the round ends without the monster striking back', async () => {
|
it('skips the recoil when the round ends without the monster striking back', async () => {
|
||||||
const fixture = await setup(activeCombat);
|
const fixture = await setup(activeCombat);
|
||||||
const won: Combat = {
|
const won: Combat = {
|
||||||
|
|||||||
@@ -126,9 +126,23 @@ export class CombatPageComponent implements OnInit {
|
|||||||
|
|
||||||
// Show what the player's own action produced, holding back the
|
// Show what the player's own action produced, holding back the
|
||||||
// monster's reply -- including whether it just started telegraphing.
|
// monster's reply -- including whether it just started telegraphing.
|
||||||
|
// A POTION heal lands from the player's own action, before the
|
||||||
|
// monster's reply, so it must show up here rather than being folded
|
||||||
|
// into the delayed riposte reveal.
|
||||||
|
const healEvent = roundEvents.find(
|
||||||
|
(event) => event.type === 'HEAL' && event.sequence < monsterEvent.sequence,
|
||||||
|
);
|
||||||
|
const intermediatePlayer = healEvent
|
||||||
|
? {
|
||||||
|
...before.player,
|
||||||
|
currentHp: Math.min(before.player.maxHp, before.player.currentHp + (healEvent.amount ?? 0)),
|
||||||
|
potionsRemaining: after.player.potionsRemaining,
|
||||||
|
}
|
||||||
|
: before.player;
|
||||||
|
|
||||||
this.displayed.set({
|
this.displayed.set({
|
||||||
...after,
|
...after,
|
||||||
player: before.player,
|
player: intermediatePlayer,
|
||||||
monster: {
|
monster: {
|
||||||
...(dealtDamage ? after.monster : before.monster),
|
...(dealtDamage ? after.monster : before.monster),
|
||||||
pendingIntent: before.monster.pendingIntent,
|
pendingIntent: before.monster.pendingIntent,
|
||||||
|
|||||||
Reference in New Issue
Block a user