/src/script/menu.ts
import { ScriptInstruction, InstructionPromise, InstructionStatus, executeInstructions } from './';
import gs from '../gamestate';
enum MenuOptionType {
Item,
Buy,
Exit,
}
enum MenuConditionType {
Flag,
Object,
}
interface MenuOptionCommon {
kind: MenuOptionType
label: string
condition?: {
negate: boolean,
type: MenuConditionType,
name: string,
}
}
interface MenuItem extends MenuOptionCommon {
kind: MenuOptionType.Item
instructions: ScriptInstruction[]
}
interface MenuBuy extends MenuOptionCommon {
kind: MenuOptionType.Buy
object: string
value: number
}
interface MenuExit extends MenuOptionCommon {
kind: MenuOptionType.Exit
}
type MenuOption = MenuItem | MenuBuy | MenuExit
export class MenuInstruction implements ScriptInstruction {
options: MenuOption[]
constructor(options: any[]) {
this.options = options.map(o => {
const condition = o[0] && {
negate: o[0][2] != null,
type: o[0][3][0].value == '$' ? MenuConditionType.Flag : MenuConditionType.Object,
name: o[0][3][1].value,
};
switch(o[1].value) {
case 'item':
return <MenuItem>{
kind: MenuOptionType.Item,
label: o[3],
instructions: o[5],
condition,
};
case 'buy':
const obj = gs.objects.get(o[3][1].value);
if (!obj) {
throw new Error('Object with id ' + o[3][1].value + ' doesn\'t exist in this world.');
}
let label;
if (o[5].value == 0) {
label = 'Take ' + obj.name;
} else {
label = 'Buy ' + obj.name + ' ($' + o[5].value + ')';
}
return <MenuBuy>{
kind: MenuOptionType.Buy,
label,
object: o[3][1].value,
value: o[5].value,
condition,
};
case 'exit':
return <MenuExit>{
kind: MenuOptionType.Exit,
label: o[3],
condition,
};
default:
throw new Error('Unknown menu item type: ' + o[1].value);
}
});
}
execute(): InstructionPromise {
return new Promise( (resolve, reject) => {
gs.actions.clear();
for (let o of this.options) {
if (o.condition) {
switch(o.condition.type) {
case MenuConditionType.Flag:
// TODO flags
break;
case MenuConditionType.Object:
let status = gs.playerInventory.has(o.condition.name) && gs.playerInventory.get(o.condition.name) > 0;
if (o.condition.negate) {
status = !status;
}
console.log(o.condition, status);
if (!status) continue;
break;
}
}
gs.actions.addAction(o.label, () => {
gs.actions.clear();
switch(o.kind) {
case MenuOptionType.Item:
resolve(executeInstructions(o.instructions));
break;
case MenuOptionType.Buy:
console.log('Buy', o.object, 'for', o.value);
gs.addInventory(o.object);
const objectName = gs.objects.get(o.object).name;
if (o.value == 0) {
gs.print("You have taken the", objectName);
} else {
gs.print("You have bought a", objectName, "for", '$' + o.value);
}
resolve({ status: InstructionStatus.OK });
break;
case MenuOptionType.Exit:
resolve({ status: InstructionStatus.OK });
break;
}
});
}
});
}
}