/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; } }); } }); } }