Expand room generation fidelity and magic item actions

This commit is contained in:
Keith Solomon
2026-03-20 17:06:45 -05:00
parent 37e2b27870
commit 9f494461de
19 changed files with 3800 additions and 6 deletions
+37 -2
View File
@@ -7,6 +7,12 @@ import type {
import type { AdventurerState, CombatState, CombatantState } from "@/types/state";
import type { LogEntry } from "@/types/rules";
import {
INSIGHTFUL_COMBAT_STATUS_ID,
SLEEPING_STATUS_ID,
consumeWardReduction,
consumeStatusValue,
} from "./magicItems";
import { roll2D6, type DiceRoller } from "./dice";
export type ResolvePlayerAttackOptions = {
@@ -138,9 +144,11 @@ export function resolvePlayerAttack(
}
const roll = roll2D6(options.roller);
const insightfulBonus = consumeStatusValue(combat.player.statuses, INSIGHTFUL_COMBAT_STATUS_ID);
const accuracy =
(roll.total ?? 0) +
combat.player.precision +
insightfulBonus +
(manoeuvre.precisionModifier ?? 0);
const targetNumber = BASE_TARGET_NUMBER + (target.armourValue ?? 0);
const hit = accuracy >= targetNumber;
@@ -207,15 +215,42 @@ export function resolveEnemyTurn(
throw new Error("No living enemies are available to act.");
}
const sleptThroughTurn = consumeStatusValue(attacker.statuses, SLEEPING_STATUS_ID) > 0;
if (sleptThroughTurn) {
combat.actingSide = "player";
combat.round += 1;
const logEntries: LogEntry[] = [
createLogEntry(
`${combat.id}.enemy.${combat.combatLog.length + 1}`,
at,
`${attacker.name} sleeps through the turn.`,
[attacker.id, combat.player.id],
),
];
combat.combatLog.push(...logEntries);
return {
combat,
logEntries,
defeatedEnemyIds: [],
combatEnded: false,
};
}
const roll = roll2D6(options.roller);
const armourValue = getPlayerArmourValue(options.content, options.adventurer);
const accuracy = (roll.total ?? 0) + attacker.precision;
const targetNumber = BASE_TARGET_NUMBER + armourValue;
const hit = accuracy >= targetNumber;
const rawDamage = hit ? Math.max(1, 1 + attacker.discipline) : 0;
const damageReduction = hit ? consumeWardReduction(combat.player.statuses) : 0;
const damage = hit ? Math.max(0, rawDamage - damageReduction) : 0;
if (hit) {
combat.player.hpCurrent = Math.max(0, combat.player.hpCurrent - rawDamage);
combat.player.hpCurrent = Math.max(0, combat.player.hpCurrent - damage);
}
combat.lastRoll = roll;
@@ -227,7 +262,7 @@ export function resolveEnemyTurn(
`${combat.id}.enemy.${combat.combatLog.length + 1}`,
at,
hit
? `${attacker.name} attacks ${combat.player.name}, rolls ${roll.total}, and deals ${rawDamage} damage.`
? `${attacker.name} attacks ${combat.player.name}, rolls ${roll.total}, and deals ${damage} damage${damageReduction > 0 ? ` after resistance reduces it by ${damageReduction}` : ""}.`
: `${attacker.name} attacks ${combat.player.name}, rolls ${roll.total}, and misses.`,
[attacker.id, combat.player.id],
),