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

57 lines
1.7 KiB
TypeScript

import { Component, type EvalContext, type World } from "../core/world";
import type { RPGAction } from "../types";
import { action, variable } from "../utils/decorators";
import { executeAction } from "../utils/variables";
export class Item extends Component {
constructor(
readonly name: string,
readonly description: string = '',
) {
super();
}
}
export class Stackable extends Component {
@variable readonly maxStack: number;
constructor(maxStack: number) {
super();
this.maxStack = maxStack;
}
}
export class Usable extends Component {
@variable readonly consumeOnUse: boolean;
constructor(private readonly actions: RPGAction[], consumeOnUse = true) {
super();
this.consumeOnUse = consumeOnUse;
}
@action
async use(arg?: EvalContext, ctx?: EvalContext): Promise<void> {
ctx = arg ?? ctx ?? this.context;
if (!ctx) return;
for (const action of this.actions) {
await 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;
}
}