Pass context to all actions
This commit is contained in:
parent
f6b3b5b66e
commit
5dec0901ac
|
|
@ -1,7 +1,6 @@
|
||||||
import { Component, type EvalContext } from "../core/world";
|
import { Component, type EvalContext } from "../core/world";
|
||||||
import { isQuest, type Quest, type QuestStage, type RPGVariables } from "../types";
|
import { isQuest, type Quest, type QuestStage, type RPGVariables } from "../types";
|
||||||
import { evaluateCondition, parseCondition } from "../utils/conditions";
|
import { evaluateCondition } from "../utils/conditions";
|
||||||
import { action } from "../utils/decorators";
|
|
||||||
|
|
||||||
export type QuestStatus = 'inactive' | 'active' | 'completed' | 'failed';
|
export type QuestStatus = 'inactive' | 'active' | 'completed' | 'failed';
|
||||||
|
|
||||||
|
|
@ -42,22 +41,18 @@ export class QuestLog extends Component {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
|
||||||
start(questId: string): boolean {
|
start(questId: string): boolean {
|
||||||
return this.#transition('start', questId, 'inactive', 'active', 'started');
|
return this.#transition('start', questId, 'inactive', 'active', 'started');
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
|
||||||
complete(questId: string): boolean {
|
complete(questId: string): boolean {
|
||||||
return this.#transition('complete', questId, 'active', 'completed', 'completed');
|
return this.#transition('complete', questId, 'active', 'completed', 'completed');
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
|
||||||
fail(questId: string): boolean {
|
fail(questId: string): boolean {
|
||||||
return this.#transition('fail', questId, 'active', 'failed', 'failed');
|
return this.#transition('fail', questId, 'active', 'failed', 'failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
|
||||||
abandon(questId: string): boolean {
|
abandon(questId: string): boolean {
|
||||||
return this.#transition('abandon', questId, 'active', 'inactive', 'abandoned');
|
return this.#transition('abandon', questId, 'active', 'inactive', 'abandoned');
|
||||||
}
|
}
|
||||||
|
|
@ -71,7 +66,7 @@ export class QuestLog extends Component {
|
||||||
if (!entry) return false;
|
if (!entry) return false;
|
||||||
const { quest } = entry;
|
const { quest } = entry;
|
||||||
if (!quest.conditions?.length) return true;
|
if (!quest.conditions?.length) return true;
|
||||||
return quest.conditions.every(c => evaluateCondition(parseCondition(c), ctx));
|
return quest.conditions.every(c => evaluateCondition(c, ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
getStage(questId: string): QuestStage | undefined {
|
getStage(questId: string): QuestStage | undefined {
|
||||||
|
|
@ -89,7 +84,7 @@ export class QuestLog extends Component {
|
||||||
return stage.objectives.map(obj => ({
|
return stage.objectives.map(obj => ({
|
||||||
id: obj.id,
|
id: obj.id,
|
||||||
description: obj.description,
|
description: obj.description,
|
||||||
done: evaluateCondition(parseCondition(obj.condition), ctx),
|
done: evaluateCondition(obj.condition, ctx),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,11 +93,6 @@ export class QuestLog extends Component {
|
||||||
return this.#quests.entries();
|
return this.#quests.entries();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal called by QuestSystem when a fail condition is met */
|
|
||||||
_fail(questId: string): void {
|
|
||||||
this.#transition('_fail', questId, 'active', 'failed', 'failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @internal called by QuestSystem after stage actions complete */
|
/** @internal called by QuestSystem after stage actions complete */
|
||||||
_advance(questId: string): void {
|
_advance(questId: string): void {
|
||||||
const entry = this.#quests.get(questId);
|
const entry = this.#quests.get(questId);
|
||||||
|
|
@ -117,6 +107,21 @@ export class QuestLog extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override getActions() {
|
||||||
|
const result = { ...super.getActions() };
|
||||||
|
for (const questId of this.#quests.keys()) {
|
||||||
|
const entry = this.#quests.get(questId)!;
|
||||||
|
if (entry.state.status === 'inactive') {
|
||||||
|
result[`${questId}.start`] = this.start.bind(this, questId);
|
||||||
|
} else if (entry.state.status === 'active') {
|
||||||
|
result[`${questId}.complete`] = this.complete.bind(this, questId);
|
||||||
|
result[`${questId}.fail`] = this.fail.bind(this, questId);
|
||||||
|
result[`${questId}.abandon`] = this.abandon.bind(this, questId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
override getVariables(): RPGVariables {
|
override getVariables(): RPGVariables {
|
||||||
const result: RPGVariables = {};
|
const result: RPGVariables = {};
|
||||||
for (const [questId, { state }] of this.#quests) {
|
for (const [questId, { state }] of this.#quests) {
|
||||||
|
|
|
||||||
|
|
@ -59,14 +59,14 @@ export abstract class Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
get context(): EvalContext {
|
get context(): EvalContext {
|
||||||
return { self: this.entity, world: this.entity.world };
|
return this.entity.context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class System {
|
export abstract class System {
|
||||||
onAdd(_world: World): void { }
|
onAdd(_world: World): void { }
|
||||||
onRemove(_world: World): void { }
|
onRemove(_world: World): void { }
|
||||||
abstract update(world: World, dt: number): void;
|
update(_world: World, _dt: number): void { };
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Entity {
|
export class Entity {
|
||||||
|
|
@ -77,6 +77,10 @@ export class Entity {
|
||||||
readonly world: World,
|
readonly world: World,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
|
get context(): EvalContext {
|
||||||
|
return { self: this, world: this.world };
|
||||||
|
}
|
||||||
|
|
||||||
add<T extends Component>(key: string, component: T): T {
|
add<T extends Component>(key: string, component: T): T {
|
||||||
const existing = this.#components.get(key);
|
const existing = this.#components.get(key);
|
||||||
if (existing) existing.onRemove();
|
if (existing) existing.onRemove();
|
||||||
|
|
@ -207,7 +211,9 @@ export class World {
|
||||||
*query<T extends Component>(ctor: Class<T>): Generator<[Entity, string, T]> {
|
*query<T extends Component>(ctor: Class<T>): Generator<[Entity, string, T]> {
|
||||||
for (const entity of this.#entities.values()) {
|
for (const entity of this.#entities.values()) {
|
||||||
for (const [key, component] of entity) {
|
for (const [key, component] of entity) {
|
||||||
if (component instanceof ctor) yield [entity, key, component as T];
|
if (component instanceof ctor) {
|
||||||
|
yield [entity, key, component as T]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import {
|
||||||
type Dialog,
|
type Dialog,
|
||||||
type DialogChoice,
|
type DialogChoice,
|
||||||
type DialogNode,
|
type DialogNode,
|
||||||
|
type RPGAction,
|
||||||
type RPGActions,
|
type RPGActions,
|
||||||
type RPGVariables,
|
type RPGVariables,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
@ -233,7 +234,7 @@ export class DialogEngine {
|
||||||
return this.options.variables;
|
return this.options.variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async runAction(action: { type: string; arg?: string | number | boolean }): Promise<void> {
|
private async runAction(action: RPGAction): Promise<void> {
|
||||||
if (isEvalContext(this.options)) {
|
if (isEvalContext(this.options)) {
|
||||||
await executeAction(action, this.options);
|
await executeAction(action, this.options);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,14 @@
|
||||||
import { System, type Entity, type World } from "../core/world";
|
import { System, type Entity, type World } from "../core/world";
|
||||||
import { evaluateCondition, parseCondition } from "../utils/conditions";
|
import { evaluateCondition } from "../utils/conditions";
|
||||||
import { executeAction } from "../utils/variables";
|
import { executeAction } from "../utils/variables";
|
||||||
import { QuestLog } from "../components/questLog";
|
import { QuestLog } from "../components/questLog";
|
||||||
|
|
||||||
export class QuestSystem extends System {
|
export class QuestSystem extends System {
|
||||||
override update(world: World, _dt: number): void {
|
async triggerCheck(world: World): Promise<void> {
|
||||||
for (const [entity] of world.query(QuestLog)) {
|
for (const [entity] of world.query(QuestLog)) {
|
||||||
void this.#checkEntity(entity, world);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async triggerCheck(entity: Entity, world: World): Promise<void> {
|
|
||||||
await this.#checkEntity(entity, world);
|
await this.#checkEntity(entity, world);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async #checkEntity(entity: Entity, world: World): Promise<void> {
|
async #checkEntity(entity: Entity, world: World): Promise<void> {
|
||||||
const questLog = entity.get(QuestLog);
|
const questLog = entity.get(QuestLog);
|
||||||
|
|
@ -31,16 +27,16 @@ export class QuestSystem extends System {
|
||||||
|
|
||||||
if (stage.failConditions?.length) {
|
if (stage.failConditions?.length) {
|
||||||
const failed = stage.failConditions.some(c =>
|
const failed = stage.failConditions.some(c =>
|
||||||
evaluateCondition(parseCondition(c), ctx)
|
evaluateCondition(c, ctx)
|
||||||
);
|
);
|
||||||
if (failed) {
|
if (failed) {
|
||||||
questLog._fail(questId);
|
questLog.fail(questId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const allDone = stage.objectives.every(obj =>
|
const allDone = stage.objectives.every(obj =>
|
||||||
evaluateCondition(parseCondition(obj.condition), ctx)
|
evaluateCondition(obj.condition, ctx)
|
||||||
);
|
);
|
||||||
if (!allDone) continue;
|
if (!allDone) continue;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
import { Type, type Static } from '../typebox';
|
import { Type, type Static } from '../typebox';
|
||||||
|
import type { EvalContext } from './core/world';
|
||||||
|
|
||||||
// ── Shared ────────────────────────────────────────────────────────────────────
|
// ── Shared ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
const RPGActionScheme = Type.Object({
|
const RPGActionScheme = Type.Object({
|
||||||
type: Type.String(),
|
type: Type.String(),
|
||||||
arg: Type.Optional(Type.Union([Type.String(), Type.Number(), Type.Boolean()])),
|
arg: Type.Optional(Type.Any()),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type RPGCondition = string;
|
export type RPGCondition = string;
|
||||||
export type RPGVariables = Record<string, string | number | boolean | undefined>;
|
export type RPGVariables = Record<string, string | number | boolean | undefined>;
|
||||||
export type RPGActions = Record<string, (arg?: any) => unknown>;
|
export type RPGActions = Record<string, (arg?: any, ctx?: EvalContext) => unknown>;
|
||||||
export type RPGAction = Static<typeof RPGActionScheme>;
|
export type RPGAction = Static<typeof RPGActionScheme>;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type { RPGCondition, RPGVariables } from "../types";
|
import type { RPGCondition, RPGVariables } from "../types";
|
||||||
import type { EvalContext } from "../core/world";
|
import { isEvalContext, type EvalContext } from "../core/world";
|
||||||
import { resolveVariable } from "./variables";
|
import { resolveVariable } from "./variables";
|
||||||
|
|
||||||
type ConditionOperator = '==' | '!=' | '>' | '<' | '>=' | '<=' | 'null' | '~null';
|
type ConditionOperator = '==' | '!=' | '>' | '<' | '>=' | '<=' | 'null' | '~null';
|
||||||
|
|
@ -60,21 +60,22 @@ function evalParsed({ negate, operator, value }: ParsedCondition, val: RPGVariab
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function evaluateCondition(parsed: ParsedCondition, variables: RPGVariables): boolean;
|
type Cond = ParsedCondition | RPGCondition;
|
||||||
export function evaluateCondition(parsed: ParsedCondition, ctx: EvalContext): boolean;
|
|
||||||
export function evaluateCondition(parsed: ParsedCondition, variablesOrCtx: RPGVariables | EvalContext): boolean {
|
export function evaluateCondition(condition: Cond, variables: RPGVariables): boolean;
|
||||||
|
export function evaluateCondition(condition: Cond, ctx: EvalContext): boolean;
|
||||||
|
export function evaluateCondition(condition: Cond, variablesOrCtx: RPGVariables | EvalContext): boolean {
|
||||||
|
const parsed = typeof condition === 'string' ? parseCondition(condition) : condition;
|
||||||
const val = isEvalContext(variablesOrCtx)
|
const val = isEvalContext(variablesOrCtx)
|
||||||
? resolveVariable(parsed.variable, variablesOrCtx)
|
? resolveVariable(parsed.variable, variablesOrCtx)
|
||||||
: variablesOrCtx[parsed.variable];
|
: variablesOrCtx[parsed.variable];
|
||||||
|
|
||||||
return evalParsed(parsed, val);
|
return evalParsed(parsed, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function evaluateConditions(conditions: RPGCondition[], variables: RPGVariables): boolean;
|
|
||||||
export function evaluateConditions(conditions: RPGCondition[], ctx: EvalContext): boolean;
|
|
||||||
export function evaluateConditions(conditions: RPGCondition[], variablesOrCtx: RPGVariables | EvalContext): boolean {
|
|
||||||
return conditions.every(c => evaluateCondition(parseCondition(c), variablesOrCtx as RPGVariables));
|
|
||||||
}
|
|
||||||
|
|
||||||
function isEvalContext(v: RPGVariables | EvalContext): v is EvalContext {
|
export function evaluateConditions(conditions: Cond[], variables: RPGVariables): boolean;
|
||||||
return 'self' in v && 'world' in v;
|
export function evaluateConditions(conditions: Cond[], ctx: EvalContext): boolean;
|
||||||
|
export function evaluateConditions(conditions: Cond[], variablesOrCtx: RPGVariables | EvalContext): boolean {
|
||||||
|
return conditions.every(c => evaluateCondition(c, variablesOrCtx as RPGVariables));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,14 @@ import type { EvalContext, Entity } from "../core/world";
|
||||||
export function resolveVariables(entity: Entity): RPGVariables;
|
export function resolveVariables(entity: Entity): RPGVariables;
|
||||||
export function resolveVariables(world: World): RPGVariables;
|
export function resolveVariables(world: World): RPGVariables;
|
||||||
export function resolveVariables(entityOrWorld: Entity | World): RPGVariables {
|
export function resolveVariables(entityOrWorld: Entity | World): RPGVariables {
|
||||||
if (entityOrWorld instanceof World) {
|
|
||||||
const result: RPGVariables = {};
|
const result: RPGVariables = {};
|
||||||
|
if (entityOrWorld instanceof World) {
|
||||||
for (const entity of entityOrWorld) {
|
for (const entity of entityOrWorld) {
|
||||||
for (const [key, value] of Object.entries(resolveVariables(entity))) {
|
for (const [key, value] of Object.entries(resolveVariables(entity))) {
|
||||||
result[`${entity.id}.${key}`] = value;
|
result[`${entity.id}.${key}`] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
} else {
|
||||||
}
|
|
||||||
const result: RPGVariables = {};
|
|
||||||
for (const [key, component] of entityOrWorld) {
|
for (const [key, component] of entityOrWorld) {
|
||||||
for (const [varKey, value] of Object.entries(component.getVariables())) {
|
for (const [varKey, value] of Object.entries(component.getVariables())) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
|
|
@ -26,6 +24,7 @@ export function resolveVariables(entityOrWorld: Entity | World): RPGVariables {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,14 +49,23 @@ export function resolveVariable(name: string, ctx: EvalContext): RPGVariables[st
|
||||||
// bare name → self entity
|
// bare name → self entity
|
||||||
return resolveVariables(ctx.self)[name];
|
return resolveVariables(ctx.self)[name];
|
||||||
}
|
}
|
||||||
|
export function resolveActions(entity: Entity): RPGActions;
|
||||||
export function resolveActions(entity: Entity): RPGActions {
|
export function resolveActions(world: World): RPGActions;
|
||||||
|
export function resolveActions(entityOrWorld: Entity | World): RPGActions {
|
||||||
const result: RPGActions = {};
|
const result: RPGActions = {};
|
||||||
for (const [key, component] of entity) {
|
if (entityOrWorld instanceof World) {
|
||||||
|
for (const entity of entityOrWorld) {
|
||||||
|
for (const [key, value] of Object.entries(resolveActions(entity))) {
|
||||||
|
result[`${entity.id}.${key}`] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const [key, component] of entityOrWorld) {
|
||||||
for (const [actionKey, fn] of Object.entries(component.getActions())) {
|
for (const [actionKey, fn] of Object.entries(component.getActions())) {
|
||||||
result[`${key}.${actionKey}`] = fn;
|
result[`${key}.${actionKey}`] = fn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,5 +95,5 @@ export async function executeAction(action: RPGAction, ctx: EvalContext): Promis
|
||||||
console.warn(`[executeAction] action '${actionType}' not found on entity '${entity.id}'`);
|
console.warn(`[executeAction] action '${actionType}' not found on entity '${entity.id}'`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return actions[actionType](action.arg);
|
return actions[actionType](action.arg, ctx);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,14 @@ const GlobalNumber = Number;
|
||||||
const GlobalArray = Array;
|
const GlobalArray = Array;
|
||||||
|
|
||||||
export namespace Type {
|
export namespace Type {
|
||||||
|
export function Any(args: { description?: string } = {}) {
|
||||||
|
const result: TAny = {};
|
||||||
|
if (args.description) {
|
||||||
|
result.description = args.description;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
export function String<S extends string = string>(args: { description?: string, enum?: S[] } = {}) {
|
export function String<S extends string = string>(args: { description?: string, enum?: S[] } = {}) {
|
||||||
const result: TString<S> = {
|
const result: TString<S> = {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
|
@ -106,6 +114,8 @@ export namespace Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
function check(scheme: TScheme, value: unknown, path: string): CheckError[] {
|
function check(scheme: TScheme, value: unknown, path: string): CheckError[] {
|
||||||
|
if (!('type' in scheme)) return [];
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
if ((scheme as any)[optional]) return [];
|
if ((scheme as any)[optional]) return [];
|
||||||
return [{ path, message: `Expected ${scheme.type} at ${path}, got ${value}` }];
|
return [{ path, message: `Expected ${scheme.type} at ${path}, got ${value}` }];
|
||||||
|
|
@ -187,6 +197,10 @@ export namespace Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TAny {
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TString<T extends string = string> {
|
export interface TString<T extends string = string> {
|
||||||
type: 'string';
|
type: 'string';
|
||||||
enum?: T[];
|
enum?: T[];
|
||||||
|
|
@ -219,6 +233,10 @@ export interface TObject<T extends TProperties = TProperties> {
|
||||||
required?: string[];
|
required?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TOptionalAny extends TAny {
|
||||||
|
[optional]: true;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TOptionalString<T extends string = string> extends TString<T> {
|
export interface TOptionalString<T extends string = string> extends TString<T> {
|
||||||
[optional]: true;
|
[optional]: true;
|
||||||
}
|
}
|
||||||
|
|
@ -256,11 +274,12 @@ export type TOptional<T extends TScheme = TScheme> =
|
||||||
T extends TArray<infer I> ? TOptionalArray<I> :
|
T extends TArray<infer I> ? TOptionalArray<I> :
|
||||||
T extends TObject<infer P> ? TOptionalObject<P> :
|
T extends TObject<infer P> ? TOptionalObject<P> :
|
||||||
T extends TUnion<infer U> ? TOptionalUnion<U> :
|
T extends TUnion<infer U> ? TOptionalUnion<U> :
|
||||||
|
T extends TAny ? TOptionalAny :
|
||||||
never;
|
never;
|
||||||
|
|
||||||
export type IsOptional<T> = T extends { [optional]: true } ? true : false;
|
export type IsOptional<T> = T extends { [optional]: true } ? true : false;
|
||||||
|
|
||||||
export type TScheme = TString | TNumber | TBoolean | TArray | TObject | TUnion | TOptionalString | TOptionalNumber | TOptionalBoolean | TOptionalArray | TOptionalObject | TOptionalUnion;
|
export type TScheme = TAny | TString | TNumber | TBoolean | TArray | TObject | TUnion | TOptionalString | TOptionalNumber | TOptionalBoolean | TOptionalArray | TOptionalObject | TOptionalUnion;
|
||||||
|
|
||||||
type Prettify<T> = { [K in keyof T]: T[K] } & {};
|
type Prettify<T> = { [K in keyof T]: T[K] } & {};
|
||||||
|
|
||||||
|
|
@ -282,6 +301,8 @@ type StaticUnion<T extends TScheme[]> =
|
||||||
? Static<First> | StaticUnion<Rest>
|
? Static<First> | StaticUnion<Rest>
|
||||||
: never;
|
: never;
|
||||||
|
|
||||||
|
type StaticAny = any;
|
||||||
|
|
||||||
export type Static<T extends TScheme> =
|
export type Static<T extends TScheme> =
|
||||||
T extends TString<infer S> ? S :
|
T extends TString<infer S> ? S :
|
||||||
T extends TNumber<infer N> ? N :
|
T extends TNumber<infer N> ? N :
|
||||||
|
|
@ -289,4 +310,5 @@ export type Static<T extends TScheme> =
|
||||||
T extends TArray<infer I> ? Static<I>[] :
|
T extends TArray<infer I> ? Static<I>[] :
|
||||||
T extends TObject<infer P> ? StaticObject<P> :
|
T extends TObject<infer P> ? StaticObject<P> :
|
||||||
T extends TUnion<infer U> ? StaticUnion<U> :
|
T extends TUnion<infer U> ? StaticUnion<U> :
|
||||||
|
T extends TAny ? StaticAny :
|
||||||
never;
|
never;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { Variables } from "@common/rpg/components/variables";
|
||||||
import { QuestLog } from "@common/rpg/components/questLog";
|
import { QuestLog } from "@common/rpg/components/questLog";
|
||||||
import { QuestSystem } from "@common/rpg/systems/questSystem";
|
import { QuestSystem } from "@common/rpg/systems/questSystem";
|
||||||
import { Items } from "@common/rpg/components/item";
|
import { Items } from "@common/rpg/components/item";
|
||||||
import { resolveVariables, resolveActions } from "@common/rpg/utils/variables";
|
import { resolveVariables, resolveActions, executeAction } from "@common/rpg/utils/variables";
|
||||||
|
|
||||||
export default async function main() {
|
export default async function main() {
|
||||||
const world = new World();
|
const world = new World();
|
||||||
|
|
@ -33,9 +33,11 @@ export default async function main() {
|
||||||
const inventory = player.get(Inventory)!;
|
const inventory = player.get(Inventory)!;
|
||||||
inventory.add({ itemId: 'helmet', amount: 1, slotId: 'head' });
|
inventory.add({ itemId: 'helmet', amount: 1, slotId: 'head' });
|
||||||
|
|
||||||
const actions = resolveActions(player);
|
const vars = player.get(Variables)!;
|
||||||
actions['inventory.add']({ itemId: 'boots', amount: 2 });
|
vars.set({ key: 'test', value: 'test' });
|
||||||
|
|
||||||
console.log(actions);
|
await executeAction({ type: 'inventory.add', arg: { itemId: 'boots', amount: 2 } }, player.context);
|
||||||
|
|
||||||
|
console.log(resolveActions(world));
|
||||||
console.log(resolveVariables(world));
|
console.log(resolveVariables(world));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue