summaryrefslogtreecommitdiff
path: root/resources/js
diff options
context:
space:
mode:
Diffstat (limited to 'resources/js')
-rw-r--r--resources/js/classes/Area.js18
-rw-r--r--resources/js/game.js85
-rw-r--r--resources/js/story.js30
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;