Expand room generation fidelity and magic item actions
This commit is contained in:
@@ -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],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user