Skip to content

Commit

Permalink
feat(command): implement actor hit command
Browse files Browse the repository at this point in the history
  • Loading branch information
ssube committed May 16, 2021
1 parent 2266380 commit e25be91
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/model/State.ts
Expand Up @@ -13,7 +13,7 @@ export enum SidebarConfig {
}

/**
* @todo needs a better name
* A saved world state.
*/
export interface State {
config: {
Expand Down
2 changes: 0 additions & 2 deletions src/model/World.ts
Expand Up @@ -14,8 +14,6 @@ export interface World {

/**
* Starting rooms and character selection.
*
* @todo is there a better name? spawn?
*/
start: {
actors: Array<string>;
Expand Down
2 changes: 1 addition & 1 deletion src/service/random/SeedRandom.ts
Expand Up @@ -5,7 +5,7 @@ import { BYTE_RANGE } from '../../util/constants';

export class SeedRandomGenerator implements RandomGenerator {
protected lastId: number;
protected source: ReturnType<typeof alea>; // TODO: this should be importable, but... that is an error, this works
protected source: ReturnType<typeof alea>; // this should be imported above, but... that is an error, this works

constructor() {
this.lastId = 0;
Expand Down
14 changes: 11 additions & 3 deletions src/service/script/common/ActorHit.ts
@@ -1,10 +1,18 @@
import { mustExist } from '@apextoaster/js-utils';
import { InvalidArgumentError, mustExist } from '@apextoaster/js-utils';

import { ScriptScope, ScriptTarget } from '..';
import { isActor } from '../../../model/entity/Actor';
import { decrementKey } from '../../../util/map';

export async function ActorHit(this: ScriptTarget, scope: ScriptScope): Promise<void> {
if (!isActor(this)) {
throw new InvalidArgumentError('invalid entity type');
}

const attacker = mustExist(scope.actor);
//const item = mustExist(scope.item);
const item = mustExist(scope.item);

scope.logger.debug(`${this.meta.name} has been hit by ${attacker.meta.name}!`); // with the ${item.meta.name}!`);
const health = decrementKey(this.stats, 'health');
await scope.render.show(`${attacker.meta.name} has hit ${this.meta.name} with a ${item.meta.name}!`);
await scope.render.show(`${this.meta.name} has ${health} health left`);
}
34 changes: 31 additions & 3 deletions src/service/script/common/ActorStep.ts
@@ -1,9 +1,21 @@
import { doesExist, InvalidArgumentError, isNil, mustExist } from '@apextoaster/js-utils';

import { ScriptScope, ScriptTarget } from '..';
import { WorldEntity } from '../../../model/entity';
import { Actor, ActorType, isActor } from '../../../model/entity/Actor';
import { SLOT_HIT, SLOT_USE, VERB_DROP, VERB_HIT, VERB_LOOK, VERB_MOVE, VERB_TAKE, VERB_USE, VERB_WAIT } from '../../../util/constants';
import {
SLOT_HIT,
SLOT_USE,
VERB_DROP,
VERB_HIT,
VERB_LOOK,
VERB_MOVE,
VERB_TAKE,
VERB_USE,
VERB_WAIT,
} from '../../../util/constants';
import { decrementKey, getKey } from '../../../util/map';
import { searchStateString } from '../../../util/state';

export async function ActorStep(this: ScriptTarget, scope: ScriptScope): Promise<void> {
scope.logger.debug({
Expand Down Expand Up @@ -73,8 +85,24 @@ export async function ActorStepCommand(this: Actor, scope: ScriptScope): Promise
}

export async function ActorStepHit(this: Actor, scope: ScriptScope): Promise<void> {
const target = this; // TODO: find actual target
await scope.script.invoke(target, SLOT_HIT, scope);
const cmd = mustExist(scope.command);
const [target] = searchStateString(scope.state, cmd.target);

if (!isActor(target)) {
await scope.render.show(`${target} is not an actor`);
return;
}

if (this.items.length === 0) {
await scope.render.show(`You cannot hit ${target.meta.name}, you are not holding anything!`);
return;
}

await scope.script.invoke(target as WorldEntity, SLOT_HIT, {
...scope,
actor: target,
item: this.items[0],
}); // TODO: fix entity cast
}

export async function ActorStepLook(this: Actor, scope: ScriptScope): Promise<void> {
Expand Down
3 changes: 2 additions & 1 deletion src/service/script/common/RoomStep.ts
Expand Up @@ -2,6 +2,7 @@ import { InvalidArgumentError } from '@apextoaster/js-utils';

import { ScriptScope, ScriptTarget } from '..';
import { isRoom } from '../../../model/entity/Room';
import { SLOT_USE } from '../../../util/constants';

export async function RoomStep(this: ScriptTarget, scope: ScriptScope): Promise<void> {
scope.logger.debug({
Expand All @@ -21,5 +22,5 @@ export async function RoomStep(this: ScriptTarget, scope: ScriptScope): Promise<
room: {
id: this.meta.id,
},
}, 'use', scope);
}, SLOT_USE, scope);
}
1 change: 0 additions & 1 deletion src/service/state/LocalStateController.ts
Expand Up @@ -532,7 +532,6 @@ export class LocalStateController implements StateController {

// get template
const template = findByTemplateId(mustExist(this.world).templates.rooms, room.meta.template);
// TODO: filter out previously-created destination portals
const portals = template.base.portals.filter((it) => {
this.logger.debug({ it, room }, 'looking for portal matching template in room');

Expand Down
15 changes: 10 additions & 5 deletions src/util/state/index.ts
Expand Up @@ -4,15 +4,18 @@ import { WorldEntity, WorldEntityType } from '../../model/entity';
import { Entity } from '../../model/entity/Base';
import { Metadata } from '../../model/meta/Metadata';
import { State } from '../../model/State';
import { Immutable } from '../types';

export interface SearchParams {
meta: Partial<Metadata>;
room: Partial<Metadata>
type: WorldEntityType;
}

export function searchState(state: State, search: Partial<SearchParams>): Array<WorldEntity> {
const results: Array<WorldEntity> = [];
export function searchState(state: State, search: Partial<SearchParams>): Array<WorldEntity>;
export function searchState(state: Immutable<State>, search: Partial<SearchParams>): Array<Immutable<WorldEntity>>;
export function searchState(state: Immutable<State>, search: Partial<SearchParams>): Array<Immutable<WorldEntity>> {
const results: Array<Immutable<WorldEntity>> = [];

for (const room of state.rooms) {
if (doesExist(search.room)) {
Expand Down Expand Up @@ -47,7 +50,9 @@ export function searchState(state: State, search: Partial<SearchParams>): Array<
return results;
}

export function searchStateString(state: State, value: string): Array<WorldEntity> {
export function searchStateString(state: State, value: string): Array<WorldEntity>;
export function searchStateString(state: Immutable<State>, value: string): Array<Immutable<WorldEntity>>;
export function searchStateString(state: Immutable<State>, value: string): Array<Immutable<WorldEntity>> {
return [
...searchState(state, {
meta: {
Expand All @@ -62,7 +67,7 @@ export function searchStateString(state: State, value: string): Array<WorldEntit
];
}

export function matchEntity(entity: Entity, search: Partial<SearchParams>): boolean {
export function matchEntity(entity: Immutable<Entity>, search: Partial<SearchParams>): boolean {
let matched = true;

if (doesExist(search.type)) {
Expand All @@ -76,7 +81,7 @@ export function matchEntity(entity: Entity, search: Partial<SearchParams>): bool
return matched;
}

export function matchMetadata(entity: Entity, filter: Partial<Metadata>): boolean {
export function matchMetadata(entity: Immutable<Entity>, filter: Partial<Metadata>): boolean {
let matched = true;

if (doesExist(filter.id)) {
Expand Down
3 changes: 1 addition & 2 deletions src/util/template/JoinChain.ts
Expand Up @@ -11,10 +11,9 @@ interface JoinOptions {
* A string building construct that:
*
* - takes a nested list of input fragments
* - takes a list of joiners and operators (TODO)
* - takes a list of joiners
* - for each fragment of the input chain:
* - modulo select a joiner
* - TODO: modulo select an operator
* - select one or more items using level operator
* - recurse into child chains
* - join items with level joiner
Expand Down

0 comments on commit e25be91

Please sign in to comment.