import { Component, type EvalContext, type World } from "../core/world"; import { component } from "../core/registry"; import type { RPGAction } from "../types"; import { action, variable } from "../utils/decorators"; import { executeAction } from "../utils/variables"; interface ItemState { name: string; description: string; } @component export class Item extends Component { constructor(name: string, description = '') { super({ name, description }); } get name(): string { return this.state.name; } get description(): string { return this.state.description; } } interface StackableState { maxStack: number; } @component export class Stackable extends Component { constructor(maxStack: number) { super({ maxStack }); } @variable get maxStack(): number { return this.state.maxStack; } } interface UsableState { actions: RPGAction[]; consumeOnUse: boolean; } @component export class Usable extends Component { constructor(actions: RPGAction[], consumeOnUse = true) { super({ actions, consumeOnUse }); } @variable get consumeOnUse(): boolean { return this.state.consumeOnUse; } @action use(arg?: EvalContext, ctx?: EvalContext): void { ctx = arg ?? ctx ?? this.context; if (!ctx) return; for (const action of this.state.actions) { executeAction(action, ctx); } } } export namespace Items { export interface RegisterOptions { maxStack?: number; description?: string; usable?: { actions: RPGAction[]; consumeOnUse?: boolean }; } export function register(world: World, id: string, name: string, options?: RegisterOptions) { const entity = world.createEntity(id); entity.add('item', new Item(name, options?.description)); if (options?.maxStack !== undefined) entity.add('stackable', new Stackable(options.maxStack)); if (options?.usable) entity.add('usable', new Usable(options.usable.actions, options.usable.consumeOnUse)); return entity; } }