1
0
Fork 0
tsgames/src/common/rpg/utils/variables.ts

67 lines
2.3 KiB
TypeScript

import type { RPGAction, RPGActions, RPGVariables } from "../types";
import type { EvalContext, Entity } from "../core/world";
export function resolveVariables(entity: Entity): RPGVariables {
const result: RPGVariables = {};
for (const [key, component] of entity) {
for (const [varKey, value] of Object.entries(component.getVariables())) {
if (value != null) {
if (varKey && varKey !== '.') {
result[`${key}.${varKey}`] = value;
} else {
result[key] = value;
}
}
}
}
return result;
}
export function resolveVariable(name: string, ctx: EvalContext): RPGVariables[string] {
// $. prefix → world globals
if (name.startsWith('$.')) {
return ctx.world.globals[name.slice(2)];
}
// @entityId.component.variable → another entity
if (name.startsWith('@')) {
const dotIdx = name.indexOf('.', 1);
if (dotIdx === -1) return undefined;
const entityId = name.slice(1, dotIdx);
const varName = name.slice(dotIdx + 1);
const entity = ctx.world.getEntity(entityId);
if (!entity) return undefined;
return resolveVariables(entity)[varName];
}
// bare name → self entity
return resolveVariables(ctx.self)[name];
}
export function resolveActions(entity: Entity): RPGActions {
const result: RPGActions = {};
for (const [key, component] of entity) {
for (const [actionKey, fn] of Object.entries(component.getActions())) {
result[`${key}.${actionKey}`] = fn;
}
}
return result;
}
export async function executeAction(action: RPGAction, ctx: EvalContext): Promise<unknown> {
let entity = ctx.self;
let actionType = action.type;
// @entityId.component.action → dispatch to another entity
if (action.type.startsWith('@')) {
const dotIdx = action.type.indexOf('.', 1);
if (dotIdx === -1) return;
const entityId = action.type.slice(1, dotIdx);
const found = ctx.world.getEntity(entityId);
if (!found) return;
entity = found;
actionType = action.type.slice(dotIdx + 1);
}
const actions = resolveActions(entity);
return actions[actionType]?.(action.arg);
}