Add poison effect to enemies
This commit is contained in:
parent
62a1ef051c
commit
02f9e1ec2c
3 changed files with 83 additions and 0 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
import { beforeAll, describe, expect, test } from "bun:test";
|
import { beforeAll, describe, expect, test } from "bun:test";
|
||||||
import { initCards } from "./cards.js";
|
import { initCards } from "./cards.js";
|
||||||
import { checkCombatEnd, resolveEnemyTurn, startTurn } from "./combat.js";
|
import { checkCombatEnd, resolveEnemyTurn, startTurn } from "./combat.js";
|
||||||
|
import { resolveEffects } from "./effects.js";
|
||||||
import { initEnemies } from "./enemies.js";
|
import { initEnemies } from "./enemies.js";
|
||||||
import { createCombatState } from "./state.js";
|
import { createCombatState } from "./state.js";
|
||||||
|
|
||||||
|
|
@ -144,3 +145,80 @@ describe("checkCombatEnd - multiplayer", () => {
|
||||||
expect(checkCombatEnd(state)).toBe("defeat");
|
expect(checkCombatEnd(state)).toBe("defeat");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("poison effect", () => {
|
||||||
|
test("applying poison adds poison to target enemy", () => {
|
||||||
|
let state = createCombatState("ironclad", "jaw_worm");
|
||||||
|
state = {
|
||||||
|
...state,
|
||||||
|
enemies: [{ ...state.enemies[0], poison: 0 }],
|
||||||
|
enemy: { ...state.enemy, poison: 0 },
|
||||||
|
};
|
||||||
|
const next = resolveEffects(
|
||||||
|
state,
|
||||||
|
[{ type: "poison", value: 3 }],
|
||||||
|
{ type: "player", index: 0 },
|
||||||
|
{ type: "enemy", index: 0 },
|
||||||
|
);
|
||||||
|
expect(next.enemies[0].poison).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("poison stacks additively up to 30", () => {
|
||||||
|
let state = createCombatState("ironclad", "jaw_worm");
|
||||||
|
state = {
|
||||||
|
...state,
|
||||||
|
enemies: [{ ...state.enemies[0], poison: 0 }],
|
||||||
|
enemy: { ...state.enemy, poison: 0 },
|
||||||
|
};
|
||||||
|
let next = resolveEffects(
|
||||||
|
state,
|
||||||
|
[{ type: "poison", value: 20 }],
|
||||||
|
{ type: "player", index: 0 },
|
||||||
|
{ type: "enemy", index: 0 },
|
||||||
|
);
|
||||||
|
next = resolveEffects(
|
||||||
|
next,
|
||||||
|
[{ type: "poison", value: 15 }],
|
||||||
|
{ type: "player", index: 0 },
|
||||||
|
{ type: "enemy", index: 0 },
|
||||||
|
);
|
||||||
|
expect(next.enemies[0].poison).toBe(30);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("poison tick", () => {
|
||||||
|
test("poison damages enemy and decrements at start of enemy turn", () => {
|
||||||
|
let state = createCombatState("ironclad", "jaw_worm");
|
||||||
|
const poisonedEnemy = { ...state.enemies[0], poison: 5, hp: 10 };
|
||||||
|
state = {
|
||||||
|
...state,
|
||||||
|
enemies: [poisonedEnemy],
|
||||||
|
enemy: poisonedEnemy,
|
||||||
|
combat: { ...state.combat, dieResult: 1 },
|
||||||
|
};
|
||||||
|
const next = resolveEnemyTurn(state);
|
||||||
|
expect(next.enemies[0].hp).toBe(5);
|
||||||
|
expect(next.enemies[0].poison).toBe(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("enemy dies from poison", () => {
|
||||||
|
let state = createCombatState("ironclad", "jaw_worm");
|
||||||
|
const poisonedEnemy = { ...state.enemies[0], poison: 10, hp: 3 };
|
||||||
|
state = {
|
||||||
|
...state,
|
||||||
|
enemies: [poisonedEnemy],
|
||||||
|
enemy: poisonedEnemy,
|
||||||
|
combat: { ...state.combat, dieResult: 1 },
|
||||||
|
};
|
||||||
|
const next = resolveEnemyTurn(state);
|
||||||
|
expect(next.enemies[0].hp).toBe(0);
|
||||||
|
expect(next.enemies[0].poison).toBe(9);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("zero poison does not tick", () => {
|
||||||
|
let state = createCombatState("ironclad", "jaw_worm");
|
||||||
|
state = { ...state, combat: { ...state.combat, dieResult: 1 } };
|
||||||
|
const next = resolveEnemyTurn(state);
|
||||||
|
expect(next.enemies[0].poison).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
||||||
2
src/effects.js
vendored
2
src/effects.js
vendored
|
|
@ -71,6 +71,8 @@ function resolveSingleEffect(state, effect, source, target) {
|
||||||
return applyStatus(state, target, "vulnerable", effect.value, 3);
|
return applyStatus(state, target, "vulnerable", effect.value, 3);
|
||||||
case "weak":
|
case "weak":
|
||||||
return applyStatus(state, target, "weak", effect.value, 3);
|
return applyStatus(state, target, "weak", effect.value, 3);
|
||||||
|
case "poison":
|
||||||
|
return applyStatus(state, target, "poison", effect.value, 30);
|
||||||
case "strength":
|
case "strength":
|
||||||
return applyStatus(state, source, "strength", effect.value, 8);
|
return applyStatus(state, source, "strength", effect.value, 8);
|
||||||
case "draw": {
|
case "draw": {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ function makePlayer(character, index) {
|
||||||
strength: 0,
|
strength: 0,
|
||||||
vulnerable: 0,
|
vulnerable: 0,
|
||||||
weak: 0,
|
weak: 0,
|
||||||
|
poison: 0,
|
||||||
drawPile: shuffle([...getStarterDeck(character)]),
|
drawPile: shuffle([...getStarterDeck(character)]),
|
||||||
hand: [],
|
hand: [],
|
||||||
discardPile: [],
|
discardPile: [],
|
||||||
|
|
@ -34,6 +35,7 @@ function makeEnemy(enemyId, index) {
|
||||||
strength: 0,
|
strength: 0,
|
||||||
vulnerable: 0,
|
vulnerable: 0,
|
||||||
weak: 0,
|
weak: 0,
|
||||||
|
poison: 0,
|
||||||
actionType: enemy.actionType,
|
actionType: enemy.actionType,
|
||||||
actions: enemy.actions,
|
actions: enemy.actions,
|
||||||
actionTrack: enemy.actionTrack || null,
|
actionTrack: enemy.actionTrack || null,
|
||||||
|
|
@ -88,6 +90,7 @@ export function createCombatFromRun(run, enemyIdOrIds) {
|
||||||
strength: 0,
|
strength: 0,
|
||||||
vulnerable: 0,
|
vulnerable: 0,
|
||||||
weak: 0,
|
weak: 0,
|
||||||
|
poison: 0,
|
||||||
drawPile: shuffle([...run.deck]),
|
drawPile: shuffle([...run.deck]),
|
||||||
hand: [],
|
hand: [],
|
||||||
discardPile: [],
|
discardPile: [],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue