1
0
Fork 0
tsgames/src/common/rpg/components/item.ts

79 lines
2.2 KiB
TypeScript

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