From dbcb7aef8d1dfa834d194efacf2186096567cb82 Mon Sep 17 00:00:00 2001 From: iTNTPiston Date: Thu, 23 Jun 2022 07:32:45 -0700 Subject: [PATCH] shoot arrow WIP --- src/App.css | 7 +- src/core/Command.ts | 418 ++++++++++++++++++--------------- src/core/GameData.ts | 5 + src/core/Parser.ts | 254 +++++++++++++------- src/core/SimulationState.ts | 63 +++-- src/core/Slots.ts | 282 +++++++++++----------- src/core/VisibleInventory.ts | 53 ++++- src/core/serialize.ts | 66 ------ src/surfaces/ReferencePage.tsx | 83 +++++++ 9 files changed, 731 insertions(+), 500 deletions(-) delete mode 100644 src/core/serialize.ts diff --git a/src/App.css b/src/App.css index 974ba49..2f1a372 100644 --- a/src/App.css +++ b/src/App.css @@ -116,5 +116,10 @@ p.Example { h3.Reference { margin-top: 30px; - margin-bottom: 0 + margin-bottom: 0; +} + +h3.Reference2 { + margin-top: 0; + margin-bottom: 0; } diff --git a/src/core/Command.ts b/src/core/Command.ts index 3c4ac33..e807557 100644 --- a/src/core/Command.ts +++ b/src/core/Command.ts @@ -29,12 +29,7 @@ export class CommandInitialize implements Command { state.initialize(this.stacks); } public getDisplayString(): string { - const parts = ["Initialize"]; - this.stacks.forEach(({item, count})=>{ - parts.push(""+count); - parts.push(item); - }); - return parts.join(" "); + return joinItemStackString("Initialize", this.stacks); } } @@ -104,7 +99,239 @@ export class CommandBreakSlots implements Command { } } +export class CommandAdd implements Command { + private verb: string; + private count: number; + private item: Item; + constructor(verb: string, count: number, item: Item){ + this.verb = verb; + this.count = count; + this.item = item; + } + public execute(state: SimulationState): void { + state.obtain(this.item, this.count); + } + public getDisplayString(): string { + return `${this.verb} ${this.count} ${this.item}`; + } +} + +export class CommandAddWithoutCount implements Command { + private verb: string; + private item: Item; + constructor(verb: string, item: Item){ + this.verb = verb; + this.item = item; + } + + public execute(state: SimulationState): void { + state.obtain(this.item, 1); + } + public getDisplayString(): string { + return `${this.verb} ${this.item}`; + } +} + +export class CommandAddMultiple implements Command { + private verb: string; + private stacks: ItemStack[]; + constructor(verb: string, stacks: ItemStack[]){ + this.verb = verb; + this.stacks = stacks; + } + + public execute(state: SimulationState): void { + this.stacks.forEach(({item, count})=>state.obtain(item,count)); + } + public getDisplayString(): string { + return joinItemStackString(this.verb, this.stacks); + + } +} + +export class CommandRemove implements Command { + private verb: string; + private count: number; + private item: Item; + private slot: number; + private noSlot: boolean; + constructor(verb: string, count: number, item: Item, slot: number, noSlot: boolean){ + this.verb = verb; + this.count = count; + this.item = item; + this.slot = slot; + this.noSlot = noSlot; + } + public execute(state: SimulationState): void { + state.remove(this.item, this.count, this.slot); + } + public getDisplayString(): string { + const slotString = this.noSlot ? "" : ` From Slot ${this.slot+1}`; + return `${this.verb} ${this.count} ${this.item}${slotString}`; + } +} + +export class CommandRemoveWithoutCount implements Command { + private verb: string; + private item: Item; + private slot: number; + private noSlot: boolean; + constructor(verb: string, item: Item, slot: number, noSlot: boolean){ + this.verb = verb; + this.item = item; + this.slot = slot; + this.noSlot = noSlot; + } + public execute(state: SimulationState): void { + state.remove(this.item, 1, this.slot); + } + public getDisplayString(): string { + const slotString = this.noSlot ? "" : ` From Slot ${this.slot+1}`; + return `${this.verb} ${this.item}${slotString}`; + } +} + +export class CommandRemoveMultiple implements Command { + private verb: string; + private stacks: ItemStack[]; + constructor(verb: string, stacks: ItemStack[]){ + this.verb = verb; + this.stacks = stacks; + } + + public execute(state: SimulationState): void { + this.stacks.forEach(({item, count})=>state.remove(item,count,0)); + } + public getDisplayString(): string { + return joinItemStackString(this.verb, this.stacks); + } +} + +const joinItemStackString = (initial: string, stacks: ItemStack[]): string => { + const parts: string[] = [initial]; + stacks.forEach(({item, count})=>{ + parts.push(""+count); + parts.push(item); + }); + return parts.join(" "); +} + +export class CommandDaP implements Command { + private count: number; + private item: Item; + + constructor(count: number, item: Item,){ + this.count = count; + this.item = item; + } + public execute(state: SimulationState): void { + state.remove(this.item, this.count, 0); + state.obtain(this.item, this.count); + } + public getDisplayString(): string { + return `D&P ${this.count} ${this.item}`; + } +} + +export class CommandEquip implements Command { + private item: Item; + private slot: number; + private noSlot: boolean; + constructor(item: Item, slot: number, noSlot: boolean){ + this.item = item; + this.slot = slot; + this.noSlot = noSlot; + } + + public execute(state: SimulationState): void { + state.equip(this.item, this.slot); + } + public getDisplayString(): string { + const slotString = this.noSlot ? "" : ` In Slot ${this.slot+1}`; + return `Equip ${this.item}${slotString}`; + } +} + +export class CommandUnequip implements Command { + private item: Item; + private slot: number; + private noSlot: boolean; + constructor(item: Item, slot: number, noSlot: boolean){ + this.item = item; + this.slot = slot; + this.noSlot = noSlot; + } + + public execute(state: SimulationState): void { + state.unequip(this.item, this.slot); + } + public getDisplayString(): string { + const slotString = this.noSlot ? "" : ` In Slot ${this.slot+1}`; + return `Unequip ${this.item}${slotString}`; + } +} + +export class CommandShootArrow implements Command { + private count: number + constructor(count: number){ + this.count = count; + } + + public execute(state: SimulationState): void { + state.shootArrow(this.count); + } + public getDisplayString(): string { + return `Shoot ${this.count} Arrow`; + } +} + + +// export class CommandEquipArrow implements Command { +// private item: Item; +// private slot: number; +// private noSlot: boolean; +// constructor(item: Item, slot: number, noSlot: boolean){ +// this.item = item; +// this.slot = slot; +// this.noSlot = noSlot; +// } + +// public execute(inv: Inventory): void { +// inv.equipEquipmentOrArrow(this.item, this.slot); +// } +// public getDisplayString(): string { +// const slotString = this.noSlot ? "" : ` In Slot ${this.slot+1}`; +// return `Equip ${itemToArrowType(this.item)} Arrow${slotString}`; +// } +// } + + + + + + +// export class CommandCloseGame implements Command { +// public execute(inv: Inventory): void { +// inv.closeGame(); +// } +// public getDisplayString(): string { +// return "Close Game"; +// } +// } + +export class CommandComment implements Command { + private name: string; + constructor(name: string){ + this.name = name; + } + public execute(_state: SimulationState): void { + // nothing + } + public getDisplayString(): string { + return `# ${this.name}`; + } +} // export class CommandSortKey implements Command { // static Op = 0x5; @@ -141,182 +368,3 @@ export class CommandBreakSlots implements Command { // return "Sort Material"; // } // } - -// const Verbs = ["?", "Remove", "Drop", "Sell", "Eat", "Cook", "Get", "Add", "Pickup"]; -// const VerbToId = { -// "Remove" : 1, -// "Drop": 2, -// "Sell": 3, -// "Eat": 4, -// "Cook": 5, -// "Get": 6, -// "Add": 7, -// "Pickup": 8 -// }; - -// export class CommandRemoveMaterial implements Command { -// static Op = 0x7; -// private verb: number; -// private count: number; -// private item: Item; -// private slot: number; -// private noSlot: boolean; -// constructor(verb: string, count: number, item: Item, slot: number, noSlot: boolean){ -// this.verb = VerbToId[verb as keyof typeof VerbToId] || 0; -// this.count = count; -// this.item = item; -// this.slot = slot; -// this.noSlot = noSlot; -// } -// public execute(inv: Inventory): void { -// inv.remove(this.item, this.count, this.slot); -// } -// public getDisplayString(): string { -// const slotString = this.noSlot ? "" : ` From Slot ${this.slot+1}`; -// return `${Verbs[this.verb]} ${this.count} ${this.item}${slotString}`; -// } -// } - -// export class CommandRemoveUnstackableMaterial implements Command { -// static Op = 0x8; -// private verb: number; -// private item: Item; -// private slot: number; -// private noSlot: boolean; -// constructor(verb: string,item: Item, slot: number, noSlot: boolean){ -// this.verb = VerbToId[verb as keyof typeof VerbToId] || 0; -// this.item = item; -// this.slot = slot; -// this.noSlot = noSlot; -// } -// public execute(inv: Inventory): void { -// inv.remove(this.item, 1, this.slot); -// } -// public getDisplayString(): string { -// const slotString = this.noSlot ? "" : ` From Slot ${this.slot+1}`; -// return `${Verbs[this.verb]} ${this.item}${slotString}`; -// } -// } - -// export class CommandAddMaterial implements Command { -// static Op = 0x9; -// private verb: number; -// private count: number; -// private item: Item; -// constructor(verb: string, count: number, item: Item){ -// this.verb = VerbToId[verb as keyof typeof VerbToId] || 0; -// this.count = count; -// this.item = item; -// } -// // public fromBuffer(buf: Buffer): number { -// // let read = 0; -// // const id = buf.readInt8(read); -// // read+=1; -// // this.item = idToItemData(id).item; - -// // this.count = buf.readInt16LE(read); -// // read+=2; -// // this.verb = buf.readInt8(read); -// // read++; -// // return read; -// // } -// // public toBuffer(): Buffer { -// // const buf: Buffer = Buffer.alloc(1+1+2+1); -// // let write = 0; -// // buf.writeInt8(CommandAddMaterial.Op); -// // write++; -// // buf.writeInt8(itemToItemData(this.item).id, write); -// // write++; -// // buf.writeInt16LE(this.count, write); -// // write+=2; -// // buf.writeInt8(this.verb, write); -// // return buf; -// // } -// public execute(inv: Inventory): void { -// inv.add(this.item, this.count); -// } -// public getDisplayString(): string { -// return `${Verbs[this.verb]} ${this.count} ${this.item}`; -// } -// } - -// export class CommandEquipArrow implements Command { -// private item: Item; -// private slot: number; -// private noSlot: boolean; -// constructor(item: Item, slot: number, noSlot: boolean){ -// this.item = item; -// this.slot = slot; -// this.noSlot = noSlot; -// } - -// public execute(inv: Inventory): void { -// inv.equipEquipmentOrArrow(this.item, this.slot); -// } -// public getDisplayString(): string { -// const slotString = this.noSlot ? "" : ` In Slot ${this.slot+1}`; -// return `Equip ${itemToArrowType(this.item)} Arrow${slotString}`; -// } -// } - -// export class CommandEquip implements Command { -// private item: Item; -// private slot: number; -// private noSlot: boolean; -// constructor(item: Item, slot: number, noSlot: boolean){ -// this.item = item; -// this.slot = slot; -// this.noSlot = noSlot; -// } - -// public execute(inv: Inventory): void { -// inv.equipEquipmentOrArrow(this.item, this.slot); -// } -// public getDisplayString(): string { -// const slotString = this.noSlot ? "" : ` In Slot ${this.slot+1}`; -// return `Equip ${this.item}${slotString}`; -// } -// } - -// export class CommandUnequip implements Command { -// private item: Item; -// private slot: number; -// private noSlot: boolean; -// constructor(item: Item, slot: number, noSlot: boolean){ -// this.item = item; -// this.slot = slot; -// this.noSlot = noSlot; -// } - -// public execute(inv: Inventory): void { -// inv.unequipEquipment(this.item, this.slot); -// } -// public getDisplayString(): string { -// const slotString = this.noSlot ? "" : ` In Slot ${this.slot+1}`; -// return `Unequip ${this.item}${slotString}`; -// } -// } - - - -// export class CommandCloseGame implements Command { -// public execute(inv: Inventory): void { -// inv.closeGame(); -// } -// public getDisplayString(): string { -// return "Close Game"; -// } -// } - -export class CommandComment implements Command { - private name: string; - constructor(name: string){ - this.name = name; - } - public execute(_state: SimulationState): void { - // nothing - } - public getDisplayString(): string { - return `# ${this.name}`; - } -} diff --git a/src/core/GameData.ts b/src/core/GameData.ts index 7a1e395..545d36e 100644 --- a/src/core/GameData.ts +++ b/src/core/GameData.ts @@ -1,4 +1,5 @@ import { DisplayableInventory, DisplayableSlot, itemStackToDisplayableSlot } from "./DisplayableInventory"; +import { Item, itemToItemData } from "./Item"; import { Slots } from "./Slots"; import { VisibleInventory } from "./VisibleInventory"; @@ -20,6 +21,10 @@ export class GameData implements DisplayableInventory { this.slots = pouch.getSlots().deepClone(); } + public updateDurability(durability: number, slot: number){ + this.slots.corrupt(durability, slot); + } + public addAllToPouchOnReload(pouch: VisibleInventory) { this.slots.getSlotsRef().forEach(stack=>pouch.addWhenReload(stack.item, stack.count, stack.equipped)); } diff --git a/src/core/Parser.ts b/src/core/Parser.ts index f6bf5dd..4b7e4b9 100644 --- a/src/core/Parser.ts +++ b/src/core/Parser.ts @@ -1,12 +1,22 @@ import { Command, + CommandAdd, + CommandAddMultiple, + CommandAddWithoutCount, CommandBreakSlots, CommandComment, + CommandDaP, + CommandEquip, CommandInitialize, CommandNothing, CommandReload, + CommandRemove, + CommandRemoveMultiple, + CommandRemoveWithoutCount, CommandSave, CommandSaveAs, + CommandShootArrow, + CommandUnequip, CommandUse } from "./Command"; import { Item, ItemStack } from "./Item"; @@ -21,23 +31,9 @@ export const parseCommand = (cmdString: string): Command | undefined => { return new CommandNothing(); } // intialize - if(tokens.length>1 && tokens[0] === "Initialize" && tokens.length%2 === 1){ - const stacks: ItemStack[] = []; - for(let i=1;i1 && tokens[0] === "Initialize"){ + const stacks = parseItemStacks(tokens, 1); + return stacks ? new CommandInitialize(stacks) : undefined; } // Save/Reload if(tokens.length===1 && tokens[0] === "Save"){ @@ -65,6 +61,121 @@ export const parseCommand = (cmdString: string): Command | undefined => { return new CommandBreakSlots(slots); } } + + // add material + if (tokens.length === 3 && isAddVerb(tokens[0])){ + const count = parseInt(tokens[1]); + const item = tokens[2]; + if(Number.isInteger(count) && item in Item){ + return new CommandAdd(tokens[0], count, Item[item as keyof typeof Item]); + } + return undefined; + } + if (tokens.length === 2 && isAddVerb(tokens[0])){ + const item = tokens[1]; + if(item in Item){ + return new CommandAddWithoutCount(tokens[0], Item[item as keyof typeof Item]); + } + return undefined; + } + if(tokens.length>2 && isAddVerb(tokens[0])){ + const stacks = parseItemStacks(tokens, 1); + return stacks ? new CommandAddMultiple(tokens[0], stacks) : undefined; + } + // remove X item From Slot Y + if (tokens.length === 6 && isRemoveVerb(tokens[0]) && tokens[3] === "From" && tokens[4] ==="Slot" ){ + const count = parseInt(tokens[1]); + const item = tokens[2]; + const slot = parseInt(tokens[5]); + if(Number.isInteger(count) && Number.isInteger(slot) && item in Item){ + return new CommandRemove(tokens[0], count, Item[item as keyof typeof Item], slot-1, false); + } + return undefined; + } + // remove X item + if (tokens.length === 3 && isRemoveVerb(tokens[0]) ){ + const count = parseInt(tokens[1]); + const item = tokens[2]; + if(Number.isInteger(count) && item in Item){ + return new CommandRemove(tokens[0], count, Item[item as keyof typeof Item], 0, true); + } + return undefined; + } + // remove item From Slot Y + if (tokens.length === 5 && isRemoveVerb(tokens[0]) && tokens[2] === "From" && tokens[3] ==="Slot" ){ + const item = tokens[1]; + const slot = parseInt(tokens[4]); + if(Number.isInteger(slot) && item in Item){ + return new CommandRemoveWithoutCount(tokens[0], Item[item as keyof typeof Item], slot-1, false); + } + return undefined; + } + // remove item + if (tokens.length === 2 && isRemoveVerb(tokens[0]) ){ + const item = tokens[1]; + if(item in Item){ + return new CommandRemoveWithoutCount(tokens[0], Item[item as keyof typeof Item], 0, true); + } + return undefined; + } + // remove multiple + if(tokens.length>2 && isRemoveVerb(tokens[0])){ + const stacks = parseItemStacks(tokens, 1); + return stacks ? new CommandRemoveMultiple(tokens[0], stacks) : undefined; + } + //Shortcut for drop and pick up + if (tokens.length === 3 && tokens[0] === "D&P" ){ + const count = parseInt(tokens[1]); + const item = tokens[2]; + if(Number.isInteger(count) && item in Item){ + return new CommandDaP(count, Item[item as keyof typeof Item]); + } + return undefined; + } + + // Equip item In Slot X + if (tokens.length === 5 && tokens[0] === "Equip" && tokens[2] === "In" && tokens[3] ==="Slot" ){ + const item = tokens[1]; + const slot = parseInt(tokens[4]); + if( Number.isInteger(slot) && item in Item){ + return new CommandEquip(Item[item as keyof typeof Item], slot-1, false); + } + return undefined; + } + // Equip item + if (tokens.length === 2 && tokens[0] === "Equip"){ + const item = tokens[1]; + if( item in Item){ + return new CommandEquip(Item[item as keyof typeof Item], 0, true); + } + return undefined; + } + // Unequip item in slot X + if (tokens.length === 5 && tokens[0] === "Unequip" && tokens[2] === "In" && tokens[3] ==="Slot" ){ + const item = tokens[1]; + const slot = parseInt(tokens[4]); + if( Number.isInteger(slot) && item in Item){ + return new CommandUnequip(Item[item as keyof typeof Item], slot-1, false); + } + return undefined; + } + // Unequip item + if (tokens.length === 2 && tokens[0] === "Unequip"){ + const item = tokens[1]; + if( item in Item){ + return new CommandUnequip(Item[item as keyof typeof Item], -1, true); + } + return undefined; + } + // Shoot X Arrow + if (tokens.length === 3 && tokens[0] === "Shoot" && tokens[2] === "Arrow"){ + const count = parseInt(tokens[1]); + if( Number.isInteger(count) ){ + return new CommandShootArrow(count); + } + return undefined; + } + // if(tokens.length===2 && tokens[0] === "Sort" && tokens[1] === "Key"){ // return new CommandSortKey(); // } @@ -78,80 +189,10 @@ export const parseCommand = (cmdString: string): Command | undefined => { // return undefined; // } // // remove material - // if (tokens.length === 6 && (tokens[0] === "Remove" || tokens[0] === "Sell" || tokens[0] === "Drop"|| tokens[0] === "Eat") && tokens[3] === "From" && tokens[4] ==="Slot" ){ - // const count = parseInt(tokens[1]); - // const item = tokens[2]; - // const slot = parseInt(tokens[5]); - // if(Number.isInteger(count) && Number.isInteger(slot) && item in Item){ - // return new CommandRemoveMaterial(tokens[0], count, Item[item as keyof typeof Item], slot-1, false); - // } - // return undefined; - // } - // if (tokens.length === 3 && (tokens[0] === "Remove" || tokens[0] === "Sell" || tokens[0] === "Drop"|| tokens[0] === "Eat")){ - // const count = parseInt(tokens[1]); - // const item = tokens[2]; - // if(Number.isInteger(count) && item in Item){ - // return new CommandRemoveMaterial(tokens[0], count, Item[item as keyof typeof Item], 0, true); - // } - // return undefined; - // } - // // remove 1 material - // if (tokens.length === 5 && (tokens[0] === "Remove" || tokens[0] === "Sell" || tokens[0] === "Eat") && tokens[2] === "From" && tokens[3] ==="Slot" ){ - // const item = tokens[1]; - // const slot = parseInt(tokens[4]); - // if(Number.isInteger(slot) && item in Item){ - // return new CommandRemoveUnstackableMaterial(tokens[0], Item[item as keyof typeof Item], slot-1, false); - // } - // return undefined; - // } - // if (tokens.length === 2 && (tokens[0] === "Remove" || tokens[0] === "Sell" || tokens[0] === "Eat")){ - // const item = tokens[1]; - // if(item in Item){ - // return new CommandRemoveUnstackableMaterial(tokens[0], Item[item as keyof typeof Item], 0, true); - // } - // return undefined; - // } - // // add material - // if (tokens.length === 3 && (tokens[0] === "Get" || tokens[0] === "Cook" || tokens[0] === "Add" || tokens[0] === "Pickup")){ - // const count = parseInt(tokens[1]); - // const item = tokens[2]; - // if(Number.isInteger(count) && item in Item){ - // return new CommandAddMaterial(tokens[0], count, Item[item as keyof typeof Item]); - // } - // return undefined; - // } - // // Equip Equipment - // if (tokens.length === 5 && tokens[0] === "Equip" && tokens[2] === "In" && tokens[3] ==="Slot" ){ - // const item = tokens[1]; - // const slot = parseInt(tokens[4]); - // if( Number.isInteger(slot) && item in Item){ - // return new CommandEquip(Item[item as keyof typeof Item], slot-1, false); - // } - // return undefined; - // } - // if (tokens.length === 2 && tokens[0] === "Equip"){ - // const item = tokens[1]; - // if( item in Item){ - // return new CommandEquip(Item[item as keyof typeof Item], 0, true); - // } - // return undefined; - // } - // // Unequip Equipment - // if (tokens.length === 5 && tokens[0] === "Unequip" && tokens[2] === "In" && tokens[3] ==="Slot" ){ - // const item = tokens[1]; - // const slot = parseInt(tokens[4]); - // if( Number.isInteger(slot) && item in Item){ - // return new CommandUnequip(Item[item as keyof typeof Item], slot-1, false); - // } - // return undefined; - // } - // if (tokens.length === 2 && tokens[0] === "Unequip"){ - // const item = tokens[1]; - // if( item in Item){ - // return new CommandUnequip(Item[item as keyof typeof Item], -1, true); - // } - // return undefined; - // } + + + + // // Equip Arrow // if (tokens.length === 6 && tokens[0] === "Equip" && tokens[2] === "Arrow" && tokens[3] === "In" && tokens[4] ==="Slot" ){ // const item = tokens[1]+"Arrow"; @@ -171,3 +212,34 @@ export const parseCommand = (cmdString: string): Command | undefined => { return undefined; }; + +const isAddVerb = (token: string): boolean => { + return token === "Get" || token === "Cook" || token === "Add" || token === "Pickup" +} + +const isRemoveVerb = (token: string): boolean => { + return token === "Remove" || token === "Sell" || token === "Eat" || token === "Drop" +} + +const parseItemStacks = (tokens: string[], from: number): ItemStack[] | undefined => { + if((tokens.length-from)%2 !== 0){ + return undefined; + } + + const stacks: ItemStack[] = []; + for(let i=from;i - save to a auto save slot -// Reload - reload hard save -// Reload - reload a named auto save -// Use - no effect, but next Reload reloads the named auto save -// Break X Slots -// Sort Key (In Tab X) -// Sort Material (In Tab X) -// Get/Add/Cook/Pickup X , X can be omitted and default to 1 -// Get/Add/Cook/Pickup X Y ... -// Remove/Drop/Sell/Eat X From Slot Y, X can be omitted and default to 1 -// Remove/Drop/Sell/Eat X Y ... -// D&P X , drop and pick up (to sort) -// Equip (In Slot X) -// Unequip (In Slot X), without slot, it unequipps the first equipped + + + // Shoot X Arrow, x can be ommited and default to 1 + // Close Game // Close Inventory, same as Resync GameData +// Enter Eventide / Leave Eventide +// Sort Key (In Tab X) - need more research on which tab is sorted. (might not be possible to select which tab to sort) +// Sort Material (In Tab X) - need more research on which tab is sorted diff --git a/src/core/Slots.ts b/src/core/Slots.ts index 2d1572f..874151c 100644 --- a/src/core/Slots.ts +++ b/src/core/Slots.ts @@ -61,7 +61,7 @@ export class Slots { public addStackDirectly(stack: ItemStack): number { const data = itemToItemData(stack.item); if(data.stackable){ - this.internalSlots.push(stack); + this.internalSlots.push({...stack}); return 1; } for(let i=0;i 0;i++){ - // if(this.internalSlots[i].item === item){ - // if(s 0;i++){ + if(this.internalSlots[i].item === item){ + if(scount>0); - // } + } + } + } + + this.internalSlots = this.internalSlots.filter(({count})=>count>0); + return oldLength-this.internalSlots.length; + } // Add something to inventory in game // returns number of slots added @@ -153,140 +159,140 @@ export class Slots { // Checks finish, do add new slot if(data.stackable){ - if(data.type===ItemType.Arrow){ - // if currently equipped arrow == 0. new arrows are equiped - // TODO: botw needs more testing on how arrows are handled in various cases - const shouldEquipNew = this.internalSlots.filter(s=>{ - const sData = itemToItemData(s.item); - return sData.type === data.type && s.equipped && s.count > 0; - }).length === 0; - this.addSlot({item,count,equipped:shouldEquipNew}, mCount+1); + if(reloading){ + this.addSlot({item,count,equipped:equippedDuringReload}, mCount+1); }else{ - this.addSlot({item,count,equipped:false}, mCount+1); + if(data.type===ItemType.Arrow){ + // if currently equipped arrow == 0. new arrows are equiped + // TODO: botw needs more testing on how arrows are handled in various cases + const shouldEquipNew = this.internalSlots.filter(s=>{ + const sData = itemToItemData(s.item); + return sData.type === data.type && s.equipped && s.count > 0; + }).length === 0; + this.addSlot({item,count,equipped:shouldEquipNew}, mCount+1); + }else{ + this.addSlot({item,count,equipped:false}, mCount+1); + } } + return 1; } - if(data.type===ItemType.Weapon || data.type===ItemType.Bow || data.type===ItemType.Shield){ - //Check equip - const shouldEquipNew = !reloading && this.internalSlots.filter(s=>{ - const sData = itemToItemData(s.item); - return sData.type === data.type && s.equipped; - }).length === 0; - this.addSlot({item,count:1,equipped: shouldEquipNew}, mCount+1); - for(let i=1;i{ + const sData = itemToItemData(s.item); + return sData.type === data.type && s.equipped; + }).length === 0; + this.addSlot({item,count:1,equipped: shouldEquipNew}, mCount+1); + for(let i=1;i 0 && this.internalSlots[i].count + count > 999){ - // return 0; // Skip, do not add new stack at all - // } - // // Otherwise push the entire new stack - // this.internalSlots.push({item, count, equipped}); - // }else{ - // this.internalSlots[i].count = Math.min(999, this.internalSlots[i].count+count); - // added = true; - // } - - // break; - // } - // } - // } - // if(!added){ - // const after = this.removeFromEnd(this.getAfterType(data.type).length); - // if(data.stackable){ - // if(data.type===ItemType.Arrow){ - // // if currently equipped arrow == 0. new arrows are equiped - // const shouldEquipNew = this.internalSlots.filter(s=>{ - // const sData = itemToItemData(s.item); - // return sData.type === data.type && s.equipped && s.count > 0; - // }).length === 0; - // this.addStack({item,count,equipped:shouldEquipNew}); - // }else{ - // this.addStack({item,count,equipped:false}); - // } - - // }else{ - // if(data.type===ItemType.Weapon || data.type===ItemType.Bow || data.type===ItemType.Shield){ - // //Check equip - // const shouldEquipNew = this.internalSlots.filter(s=>{ - // const sData = itemToItemData(s.item); - // return sData.type === data.type && s.equipped; - // }).length === 0; - // this.addStack({item,count:1,equipped: shouldEquipNew}); - // for(let i=1;i= this.internalSlots.length){ + return; + } + const thisData = itemToItemData(this.internalSlots[slot].item); + if(thisData.stackable){ + this.internalSlots[slot].count = durability; + } + } - // // this is for both equipments and arrows - // public equip(item: Item, slot: number) { - // let s = 0; - // const type = itemToItemData(item).type; - // const filtered = this.internalSlots.filter(s=>itemToItemData(s.item).type === type); - // for(let i = 0; i=this.internalSlots.length){ + //can't find equipped arrow + return -1; + } + const equippedArrow = this.internalSlots[i].item; + // now find the first slot of that arrow and update + for(let j=0;j{ + if(equipped){ + const type = itemToItemData(item).type; + if(type === ItemType.Weapon && !foundWeapon){ + gameData.updateDurability(999, i); + foundWeapon = true; + } + if(type === ItemType.Bow && !foundBow){ + gameData.updateDurability(999, i); + foundBow = true; + } + if(type === ItemType.Shield && !foundShield){ + gameData.updateDurability(999, i); + foundShield = true; + } + } + }) + } + + public shootArrow(count: number, gameData: GameData) { + const updatedSlot = this.slots.shootArrow(count); + if(updatedSlot>=0){ + const durability = this.slots.getSlotsRef()[updatedSlot].count; + gameData.updateDurability(durability, updatedSlot); + } + } + public getCount(): number { return this.count; } diff --git a/src/core/serialize.ts b/src/core/serialize.ts deleted file mode 100644 index fdc0f8f..0000000 --- a/src/core/serialize.ts +++ /dev/null @@ -1,66 +0,0 @@ -export {}; -// import { Command, CommandAddMaterial, CommandBreakSlots, CommandInitialize, CommandNothing, CommandReload, CommandRemoveMaterial, CommandRemoveUnstackableMaterial, CommandSave, CommandSortKey, CommandSortMaterial } from "./Command"; -// import { Item } from "./Item"; - -// const Buffer = require("buffer/").Buffer; /* eslint-disable-line @typescript-eslint/no-var-requires*/ - -// export const serializeCommands = (commands: Command[]): string => { -// const sizeBuf: Buffer = Buffer.alloc(4); -// sizeBuf.writeInt32LE(commands.length); - -// const commandBuffers = commands.map(c=>c.toBuffer()); -// const allBufs = Buffer.concat([sizeBuf, ...commandBuffers]); - -// return allBufs.toString("base64"); -// }; - -// export const deserialzeCommands = (base64str: string): Command[] => { -// const buf: Buffer = Buffer.from(base64str, "base64"); -// const size = buf.readInt32LE(); -// let off = 4; -// const commands: Command[] = []; -// for(let i=0;i{

Example: Break 4 Slots

+ +

Get/Add/Cook/Pickup item

+

Get/Add/Cook/Pickup X item

+

Get/Add/Cook/Pickup X item1 Y item2 Z item3 ...

+

Simulate obtaining items in game

+

+ Add the item(s) to visible inventory. Sync with Game Data unless you are on Eventide or inside TOTS +

+

+ Like in game, you won't be able to obtain multiple unstackable key items, or multiple master sword in this way. + If a stackable item is at 999 or more when you invoke this command, the count is set to 999 (not fully accurate since you won't be able to pick up more items in game). +

+

+ If you specify a count for unstackable items, they are added in different slots as if you pick them up in game, one after another. +

+

+ Note that you must not enter plural forms for the item name. +

+ +

Example 1: Add Apple

+

Example 2: Get 10 Apple

+

Example 3: Pickup 10 Apple 5 Diamond 1 Slate 5 MasterSword

+ +

Remove/Sell/Eat/Drop item

+

Remove/Sell/Eat/Drop X item

+

Remove/Sell/Eat/Drop item From Slot Y

+

Remove/Sell/Eat/Drop X item From Slot Y

+

Remove/Sell/Eat/Drop X item1 Y item2 Z item3 ...

+

Simulate removing items in game

+

+ Remove the item(s) to visible inventory. Sync with Game Data unless you are on Eventide or inside TOTS +

+

+ When number of item is not specified, it defaults to 1. Up to X items will be removed from inventory, even when they span multiple slots. + If X > total number of items in inventory, all of them will be removed. +

+

+ When slot is specified, it starts removing from slot X (slot 1 is the leftmost slot with that item, slot 2 is the second leftmost slot with that item). +

+

+ Note that you must not enter plural forms for the item name. +

+ +

Example 1: Remove Apple

+

Example 2: Drop 10 Diamond

+

Example 3: Sell 10 Apple 5 Diamond

+

Example 4: Sell 5 Apple From Slot 3

+ +

D&P X item

+

Shortcut for drop and pick up, for sorting inventory

+

+ This command drops X item from the first slot, then pick them up +

+

Example: D&P 5 Diamond

+ +

Equip item

+

Equip item In Slot X

+

Simulates equipping something

+

+ When equipping an item, all other item of the same type in the first tab is unequipped, then the item selected is equipped. +

+

+ Slot can be used if you have multiple of the same item. When slot is not specified, the leftmost item will be equipped. + Note that you can use this command to equip something that is already equipped, which is not possible in game. + You can also equip unequippable items like materials, but it is not meaningful +

+

Example 1: Equip Weapon

+

Example 2: Equip Weapon In Slot 3

+ +

Unequip item

+

Unequip item In Slot X

+

Simulates unequipping something

+

+ When unequipping an item, only the selected item is unequipped. +

+

+ Slot can be used if you have multiple of the same item. When slot is not specified, the leftmost equipped item will be unequipped. + Note that you can use this command to unequip something that is already unequipped, which is useless. + You cannot unequip arrows. +

+

Example 1: Unequip Shield

+

Example 2: Unequip Shield In Slot 5

+ )