Combatants can now be assigned to party or enemy side via a toggle in the difficulty breakdown panel. Party-side NPCs subtract their XP from the encounter total, letting allied NPCs reduce difficulty. PCs default to party, non-PCs to enemy — users who don't use sides see no change. Side persists across reload and export/import. Closes #22 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
180 lines
4.3 KiB
TypeScript
180 lines
4.3 KiB
TypeScript
import type { ConditionId } from "./conditions.js";
|
|
import type { CreatureId } from "./creature-types.js";
|
|
import type { PlayerCharacterId } from "./player-character-types.js";
|
|
import type { CombatantId } from "./types.js";
|
|
|
|
export interface TurnAdvanced {
|
|
readonly type: "TurnAdvanced";
|
|
readonly previousCombatantId: CombatantId;
|
|
readonly newCombatantId: CombatantId;
|
|
readonly roundNumber: number;
|
|
}
|
|
|
|
export interface RoundAdvanced {
|
|
readonly type: "RoundAdvanced";
|
|
readonly newRoundNumber: number;
|
|
}
|
|
|
|
export interface CombatantAdded {
|
|
readonly type: "CombatantAdded";
|
|
readonly combatantId: CombatantId;
|
|
readonly name: string;
|
|
readonly position: number;
|
|
readonly init?: {
|
|
readonly maxHp?: number;
|
|
readonly ac?: number;
|
|
readonly initiative?: number;
|
|
readonly creatureId?: CreatureId;
|
|
readonly color?: string;
|
|
readonly icon?: string;
|
|
readonly playerCharacterId?: PlayerCharacterId;
|
|
};
|
|
}
|
|
|
|
export interface CombatantRemoved {
|
|
readonly type: "CombatantRemoved";
|
|
readonly combatantId: CombatantId;
|
|
readonly name: string;
|
|
}
|
|
|
|
export interface CombatantUpdated {
|
|
readonly type: "CombatantUpdated";
|
|
readonly combatantId: CombatantId;
|
|
readonly oldName: string;
|
|
readonly newName: string;
|
|
}
|
|
|
|
export interface InitiativeSet {
|
|
readonly type: "InitiativeSet";
|
|
readonly combatantId: CombatantId;
|
|
readonly previousValue: number | undefined;
|
|
readonly newValue: number | undefined;
|
|
}
|
|
|
|
export interface MaxHpSet {
|
|
readonly type: "MaxHpSet";
|
|
readonly combatantId: CombatantId;
|
|
readonly previousMaxHp: number | undefined;
|
|
readonly newMaxHp: number | undefined;
|
|
readonly previousCurrentHp: number | undefined;
|
|
readonly newCurrentHp: number | undefined;
|
|
}
|
|
|
|
export interface CurrentHpAdjusted {
|
|
readonly type: "CurrentHpAdjusted";
|
|
readonly combatantId: CombatantId;
|
|
readonly previousHp: number;
|
|
readonly newHp: number;
|
|
readonly delta: number;
|
|
}
|
|
|
|
export interface TempHpSet {
|
|
readonly type: "TempHpSet";
|
|
readonly combatantId: CombatantId;
|
|
readonly previousTempHp: number | undefined;
|
|
readonly newTempHp: number | undefined;
|
|
}
|
|
|
|
export interface TurnRetreated {
|
|
readonly type: "TurnRetreated";
|
|
readonly previousCombatantId: CombatantId;
|
|
readonly newCombatantId: CombatantId;
|
|
readonly roundNumber: number;
|
|
}
|
|
|
|
export interface RoundRetreated {
|
|
readonly type: "RoundRetreated";
|
|
readonly newRoundNumber: number;
|
|
}
|
|
|
|
export interface AcSet {
|
|
readonly type: "AcSet";
|
|
readonly combatantId: CombatantId;
|
|
readonly previousAc: number | undefined;
|
|
readonly newAc: number | undefined;
|
|
}
|
|
|
|
export interface CrSet {
|
|
readonly type: "CrSet";
|
|
readonly combatantId: CombatantId;
|
|
readonly previousCr: string | undefined;
|
|
readonly newCr: string | undefined;
|
|
}
|
|
|
|
export interface SideSet {
|
|
readonly type: "SideSet";
|
|
readonly combatantId: CombatantId;
|
|
readonly previousSide: "party" | "enemy" | undefined;
|
|
readonly newSide: "party" | "enemy";
|
|
}
|
|
|
|
export interface ConditionAdded {
|
|
readonly type: "ConditionAdded";
|
|
readonly combatantId: CombatantId;
|
|
readonly condition: ConditionId;
|
|
}
|
|
|
|
export interface ConditionRemoved {
|
|
readonly type: "ConditionRemoved";
|
|
readonly combatantId: CombatantId;
|
|
readonly condition: ConditionId;
|
|
}
|
|
|
|
export interface ConcentrationStarted {
|
|
readonly type: "ConcentrationStarted";
|
|
readonly combatantId: CombatantId;
|
|
}
|
|
|
|
export interface ConcentrationEnded {
|
|
readonly type: "ConcentrationEnded";
|
|
readonly combatantId: CombatantId;
|
|
}
|
|
|
|
export interface EncounterCleared {
|
|
readonly type: "EncounterCleared";
|
|
readonly combatantCount: number;
|
|
}
|
|
|
|
export interface PlayerCharacterCreated {
|
|
readonly type: "PlayerCharacterCreated";
|
|
readonly playerCharacterId: PlayerCharacterId;
|
|
readonly name: string;
|
|
}
|
|
|
|
export interface PlayerCharacterUpdated {
|
|
readonly type: "PlayerCharacterUpdated";
|
|
readonly playerCharacterId: PlayerCharacterId;
|
|
readonly oldName: string;
|
|
readonly newName: string;
|
|
}
|
|
|
|
export interface PlayerCharacterDeleted {
|
|
readonly type: "PlayerCharacterDeleted";
|
|
readonly playerCharacterId: PlayerCharacterId;
|
|
readonly name: string;
|
|
}
|
|
|
|
export type DomainEvent =
|
|
| TurnAdvanced
|
|
| RoundAdvanced
|
|
| CombatantAdded
|
|
| CombatantRemoved
|
|
| CombatantUpdated
|
|
| InitiativeSet
|
|
| MaxHpSet
|
|
| CurrentHpAdjusted
|
|
| TempHpSet
|
|
| TurnRetreated
|
|
| RoundRetreated
|
|
| AcSet
|
|
| CrSet
|
|
| SideSet
|
|
| ConditionAdded
|
|
| ConditionRemoved
|
|
| ConcentrationStarted
|
|
| ConcentrationEnded
|
|
| EncounterCleared
|
|
| PlayerCharacterCreated
|
|
| PlayerCharacterUpdated
|
|
| PlayerCharacterDeleted;
|