diff options
Diffstat (limited to 'resources/js')
-rw-r--r-- | resources/js/classes/Area.js | 18 | ||||
-rw-r--r-- | resources/js/game.js | 85 | ||||
-rw-r--r-- | resources/js/story.js | 30 |
3 files changed, 125 insertions, 8 deletions
diff --git a/resources/js/classes/Area.js b/resources/js/classes/Area.js index 1b07e35..3a20d21 100644 --- a/resources/js/classes/Area.js +++ b/resources/js/classes/Area.js @@ -31,14 +31,30 @@ class Area { return DB.areas[this.slug].encounter_percent_total; } - get requiredEncounters () { + get requiredEncountersBase () { return DB.areas[this.slug].requiredEncounters; } + get requiredEncounters () { + return this.requiredEncountersBase * (this.trainerProgress + 1); + } + get trainers () { return DB.areas[this.slug].trainers; } + /** + * @typedef {Object} AreaItem + * @property {ItemSlug} slug + * @property {number} dropRatio + * @inner + * + * @returns {AreaItem[]} + */ + get items () { + return DB.areas[this.slug].items; + } + get environment () { return DB.areas[this.slug].environment; } diff --git a/resources/js/game.js b/resources/js/game.js index 309d013..c2b20da 100644 --- a/resources/js/game.js +++ b/resources/js/game.js @@ -101,6 +101,32 @@ const Game = { Game.log(translate('game:battle:money:get').replace('{amount}', money)); }); + // item + if (Memory.state.currentArea.items.length > 0) { + const itemDropChance = Memory.state.currentArea.monsterProgress * 0.1; + const itemDropCheck = Math.random() * 100; + if (itemDropChance > itemDropCheck) { + const itemDropRatioMax = Memory.state.currentArea.items.reduce((accumulator, itemData) => accumulator + itemData.dropRatio, 0); + const itemDropRatioCheck = Math.random() * itemDropRatioMax; + let accumulator = 0; + for (const itemData of Memory.state.currentArea.items) { + const lowerBounds = accumulator; + accumulator += itemData.dropRatio; + const upperBounds = accumulator; + if (itemDropRatioCheck >= lowerBounds && itemDropRatioCheck <= upperBounds) { + await Game.addItemToInventory(Memory.state.player.inventory, itemData.slug, 1); + + const droppedItem = await fetchItem(itemData.slug); + Game.addPhaseEvent('postTurn', () => { + Game.log(translate('game:battle:item:get').replace('{name}', droppedItem.name)); + }); + + break; + } + } + } + } + // exp Memory.state.player.activeMonster.exp += calculateAwardedExperience(Memory.state.opponent.activeMonster, [Memory.state.player.activeMonster])[0]; @@ -114,12 +140,16 @@ const Game = { Memory.state.Game.isInBattle = false; if (Memory.state.opponent.type === 'monster') { - Memory.state.currentArea.monsterProgress++; + if ( + Memory.state.currentArea.monsterProgress < Memory.state.currentArea.requiredEncounters || + Memory.state.currentArea.isCompleted + ) { + Memory.state.currentArea.monsterProgress++; + } await Game.encounterWildMonster(); } else if (Memory.state.opponent.type === 'trainer') { if (Memory.state.opponent.activeMonster === Memory.state.opponent.monsters[Memory.state.opponent.monsters.length - 1]) { Memory.state.currentArea.trainerProgress++; - Memory.state.currentArea.monsterProgress = 0; if (Memory.state.currentArea.encounters.length > 0) { await Game.encounterWildMonster(); } else if (Memory.state.currentArea.trainers.length > 0) { @@ -783,6 +813,31 @@ const Game = { Game.isLoadingArea = true; Game.clearCurrentTurn(); + + // on leave + let onLeaveStoryIsDone = true; + if (Memory.state.currentArea.events?.onLeave?.length > 0) { + Game.isLoadingArea = false; + + for (const event of Memory.state.currentArea.events.onLeave) { + if (event.type === 'story') { + UI.showMap(); + UI.drawTown(); + + onLeaveStoryIsDone = await Story.progress(event.story); + } + } + } + + if (!onLeaveStoryIsDone) { + return; + } + + Game.isLoadingArea = true; + + + // after on leave events resolved + if (Memory.state.currentArea) { Memory.state.areaProgress[Memory.state.currentArea.slug] = Memory.state.currentArea; } @@ -791,8 +846,8 @@ const Game = { // on enter - let storyIsDone = true; - if (Memory.state.currentArea.events?.onEnter.length > 0) { + let onEnterStoryIsDone = true; + if (Memory.state.currentArea.events?.onEnter?.length > 0) { Game.isLoadingArea = false; for (const event of Memory.state.currentArea.events.onEnter) { @@ -800,19 +855,19 @@ const Game = { UI.showMap(); UI.drawTown(); - storyIsDone = await Story.progress(event.story); + onEnterStoryIsDone = await Story.progress(event.story); } } } - if (!storyIsDone) { + if (!onEnterStoryIsDone) { return; } Game.isLoadingArea = true; - // after events resolved + // after on enter events resolved if (Game.isTown(Memory.state.currentArea)) { if (Object.values(Memory.state.currentArea.locations).some((location) => location.type === 'healingCenter')) { @@ -948,6 +1003,8 @@ const Game = { /** * @param {InventoryItem[]} inventory * @param {ItemSlug} itemSlug + * + * @returns {(InventoryItem|undefined)} */ getItemFromInventory (inventory, itemSlug) { return inventory.find((inventoryItem) => inventoryItem.slug === itemSlug); @@ -956,6 +1013,20 @@ const Game = { /** * @param {InventoryItem[]} inventory * @param {ItemSlug} itemSlug + * @param {number} quantity + */ + async addItemToInventory (inventory, itemSlug, quantity = 1) { + const inventoryItem = Game.getItemFromInventory(inventory, itemSlug); + if (inventoryItem) { + inventoryItem.quantity += quantity; + } else { + inventory.push(new InventoryItem(await fetchItem(itemSlug), quantity)); + } + }, + + /** + * @param {InventoryItem[]} inventory + * @param {ItemSlug} itemSlug */ removeItemFromInventory (inventory, itemSlug) { inventory.splice(inventory.findIndex((inventoryItem) => inventoryItem.slug === itemSlug), 1); diff --git a/resources/js/story.js b/resources/js/story.js index bb6fc4b..9d64a2a 100644 --- a/resources/js/story.js +++ b/resources/js/story.js @@ -134,6 +134,36 @@ const Story = { return didWin; }, + 'battle-rival-three': async () => { + const story = await fetchStory('battle-rival-three'); + const characterRival = story.characters.rival; + const npcRival = await fetchNpc(story.characters.rival.slug); + + await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[0]) }); + await Story.setupBattle(npcRival, characterRival.monsters); + const didWin = await Story.battle(); + if (didWin) { + await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[1]) }); + } + + return didWin; + }, + + 'battle-rival-four': async () => { + const story = await fetchStory('battle-rival-four'); + const characterRival = story.characters.rival; + const npcRival = await fetchNpc(story.characters.rival.slug); + + await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[0]) }); + await Story.setupBattle(npcRival, characterRival.monsters); + const didWin = await Story.battle(); + if (didWin) { + await UI.buildAndShowStoryPopup({ speaker: npcRival, text: translate(characterRival.text[1]) }); + } + + return didWin; + }, + 'hospital-floor-1': async () => { const story = await fetchStory('hospital-floor-1'); const characterAurora = story.characters.aurora; |