import type { GameEvents } from "./events.js"; export interface QuestObjective { id: string; kind: "kill" | "collect" | string; target?: string; item?: string; count: number; partyShare?: { radius: number; credit: "all" | "tagger"; }; } export interface QuestRewards { xp?: { amount: number; }; economy?: Record; items?: { item: string; count: number; inventory: string; }[]; unlocks?: string[]; quests?: string[]; } export interface QuestDef { id: string; title: string; description?: string; giver?: string; turnIn?: string; requires?: string[]; objectives: QuestObjective[]; rewards?: QuestRewards; } export type QuestStatus = "active" | "completed"; export interface QuestObjectiveProgress { id: string; kind: string; count: number; progress: number; complete: boolean; } export interface QuestInstance { questId: string; status: QuestStatus; objectives: QuestObjectiveProgress[]; } export type QuestSnapshotEntry = { questId: string; status: QuestStatus; progress: Record; }; export interface QuestJournalDeps { events: GameEvents; rewards: { grantXp(userId: string, amount: number): void; grantEconomy(userId: string, currencyId: string, amount: number): void; grantItem(userId: string, inventoryId: string, itemId: string, count: number): { reason: string; } | null; /** Grant the whole item batch, or reject without granting any items. Required for multiple item rewards. */ grantItems?(userId: string, items: Readonly>): { reason: string; } | null; grantUnlock(userId: string, unlockId: string): void; }; hasUnlock?(userId: string, id: string): boolean; partyMembersNear?(userId: string, radius: number): string[]; } export interface QuestJournal { /** Add or replace definitions and refresh active credit indexes; re-register after editing objectives. */ register(catalog: readonly QuestDef[] | Record): void; has(questId: string): boolean; canAccept(userId: string, questId: string): { reason: string; } | null; accept(userId: string, questId: string): { reason: string; } | null; abandon(userId: string, questId: string): void; progress(userId: string, questId: string, objectiveId: string, delta: number): void; canTurnIn(userId: string, questId: string): { reason: string; } | null; turnIn(userId: string, questId: string): { reason: string; } | null; grant(userId: string, questId: string, options?: { completed?: boolean; }): void; revoke(userId: string, questId: string): void; list(userId: string): QuestInstance[]; /** Credit objectives active at event start in catalog order; quests activated during credit join the next event. */ bind(action: "entity.died" | "inventory.added"): () => void; snapshot(userId: string): QuestSnapshotEntry[]; hydrate(userId: string, data: QuestSnapshotEntry[]): void; /** Whole-store capture across every user — the world-save/replication seam (per-user `snapshot` can't enumerate users). */ snapshotAll(): Record; hydrateAll(data: Record): void; } /** * Track accepted quests and their per-objective progress, granting rewards on completion. * * @capability quest-log track accepted quests and their per-objective progress */ export declare function createQuestJournal(deps: QuestJournalDeps): QuestJournal; /** One objective as a tracker/HUD reads it — label + progress toward its count. */ export interface TrackedObjectiveView { id: string; /** Human label (e.g. "Defeat 3 wraiths"); falls back to the objective id. */ label: string; count: number; progress: number; complete: boolean; } /** A quest as a tracker/HUD reads it — title, status, and per-objective progress. */ export interface TrackedQuestView { id: string; title: string; status: QuestStatus; objectives: TrackedObjectiveView[]; } /** Default objective label: a readable "verb count noun" from a {@link QuestObjective}. */ export declare function defaultObjectiveLabel(objective: QuestObjective): string; /** * Join a quest's static {@link QuestDef} with a player's live {@link QuestInstance} * into a flat, renderer-free view a HUD tracker draws (title, status, labelled * objective progress). Pass `label` to override the derived objective text. * * @capability quest-tracker-view join a QuestDef + live QuestInstance into a flat labelled view for a quest/objective HUD tracker */ export declare function describeTrackedQuest(def: QuestDef, instance: QuestInstance, label?: (objective: QuestObjective) => string): TrackedQuestView; export interface QuestAcceptOptions { hasUnlock?(id: string): boolean; } export interface QuestTurnIn { state: QuestSnapshotEntry[]; rewards: QuestRewards | null; } export interface QuestEvaluator { has(questId: string): boolean; get(questId: string): QuestDef | null; canAccept(state: readonly QuestSnapshotEntry[], questId: string, options?: QuestAcceptOptions): { reason: string; } | null; accept(state: readonly QuestSnapshotEntry[], questId: string, options?: QuestAcceptOptions): QuestSnapshotEntry[] | { reason: string; }; abandon(state: readonly QuestSnapshotEntry[], questId: string): QuestSnapshotEntry[]; progress(state: readonly QuestSnapshotEntry[], questId: string, objectiveId: string, delta: number): QuestSnapshotEntry[]; canTurnIn(state: readonly QuestSnapshotEntry[], questId: string): { reason: string; } | null; turnIn(state: readonly QuestSnapshotEntry[], questId: string): QuestTurnIn | { reason: string; }; grant(state: readonly QuestSnapshotEntry[], questId: string, options?: { completed?: boolean; }): QuestSnapshotEntry[]; revoke(state: readonly QuestSnapshotEntry[], questId: string): QuestSnapshotEntry[]; creditKill(state: readonly QuestSnapshotEntry[], targetCatalogId: string): QuestSnapshotEntry[]; creditCollect(state: readonly QuestSnapshotEntry[], itemId: string, count: number): QuestSnapshotEntry[]; list(state: readonly QuestSnapshotEntry[]): QuestInstance[]; } /** * Apply items before XP, currency, and unlocks. Multiple items require an all-or-reject `grantItems` * callback; legacy single-item appliers remain supported. Rejected callbacks must make no writes. * Arbitrary callback side effects or thrown exceptions cannot be rolled back by this helper. */ export declare function applyQuestRewards(rewards: QuestRewards, appliers: { grantXp?(amount: number): void; grantEconomy?(currencyId: string, amount: number): void; grantItem?(inventoryId: string, itemId: string, count: number): { reason: string; } | null | void; /** Grant every item, or reject without writes. Takes precedence over `grantItem`. */ grantItems?(items: Readonly>): { reason: string; } | null | void; grantUnlock?(unlockId: string): void; }): { reason: string; } | null; export declare function createQuestEvaluator(defs: QuestDef[] | Record): QuestEvaluator;