From 36a5d5862c3744f899fe6a5712f81171af144795 Mon Sep 17 00:00:00 2001 From: Daniel Weipert Date: Sat, 26 Aug 2023 20:46:22 +0200 Subject: evolution items and shop interface --- resources/js/classes/State.js | 4 +-- resources/js/definitions.js | 1 + resources/js/game.js | 59 ++++++++++++++++++++++++++++++++---------- resources/js/main.js | 2 +- resources/js/memory.js | 7 ++++- resources/js/ui.js | 60 ++++++++++++++++++++++++++++++++----------- 6 files changed, 101 insertions(+), 32 deletions(-) (limited to 'resources/js') diff --git a/resources/js/classes/State.js b/resources/js/classes/State.js index 417c685..e4820d3 100644 --- a/resources/js/classes/State.js +++ b/resources/js/classes/State.js @@ -70,7 +70,7 @@ class State { activeTechnique = null; /** - * @type {InventoryItem} + * @type {ItemSlug} */ - activeBall = null; + activeBall = ''; }; diff --git a/resources/js/definitions.js b/resources/js/definitions.js index d399a3c..f39025d 100644 --- a/resources/js/definitions.js +++ b/resources/js/definitions.js @@ -1,6 +1,7 @@ /** * @typedef {string} MonsterSlug * @typedef {string} TechniqueSlug + * @typedef {string} ItemSlug * @typedef {string} AreaSlug */ diff --git a/resources/js/game.js b/resources/js/game.js index b628553..c64d744 100644 --- a/resources/js/game.js +++ b/resources/js/game.js @@ -146,7 +146,10 @@ const Game = { // whole party defeated if (!Memory.state.player.monsters.some((monster) => monster.hp > 0)) { Memory.state.Game.isInBattle = false; - Memory.state.currentArea.monsterProgress = 0; + + if (Memory.state.currentArea.monsterProgress < Memory.state.currentArea.requiredEncounters) { + Memory.state.currentArea.monsterProgress = 0; + } // go to last visited town await Game.goToArea(Memory.state.lastVisitedTown); @@ -769,6 +772,7 @@ const Game = { for (const itemConditionCode of item.conditions) { const itemCondition = new ItemCondition(itemConditionCode); let conditionIsApplicable = true; + console.log(monster.evolutions); if (itemCondition.what === 'current_hp') { const value = parseInt(itemCondition.value) * monster.stats.hp; @@ -787,6 +791,15 @@ const Game = { conditionIsApplicable = Memory.state.opponent.activeMonster.category === 'threat'; } + else if (itemCondition.what === 'level') { + const value = parseInt(itemCondition.value); + conditionIsApplicable = eval(`${monster.level} ${itemCondition.comparator} ${value}`); + } + + else if (itemCondition.what === 'has_path') { + conditionIsApplicable = monster.evolutions.some((evolution) => evolution.path === 'item' && evolution.item === item.slug) + } + else { conditionIsApplicable = false; } @@ -806,48 +819,68 @@ const Game = { * @param {Monster} */ async useItem (item, monster) { + let useLowersQuantity = false; + for (const itemEffectCode of item.effects) { const itemEffect = new ItemEffect(itemEffectCode); if (itemEffect.type === 'heal') { monster.hp += itemEffect.amount; - item.quantity--; + useLowersQuantity = true; UI.drawActiveMonster(); } if (itemEffect.type === 'revive') { monster.hp = itemEffect.amount; monster.statusEffect = null; - item.quantity--; + useLowersQuantity = true; UI.drawActiveMonster(); } else if (itemEffect.type === 'capture') { - Memory.state.activeBall = item; + Memory.state.activeBall = item.slug; UI.drawActiveBall(); } else if (itemEffect.type === 'evolve') { - const evolution = Memory.state.player.activeMonster.getPossibleEvolutions('item')[0]; + const evolution = monster.evolutions.find((evolution) => evolution.path === 'item' && evolution.item === item.slug); if (evolution) { await fetchMonster(evolution.monster_slug); - Memory.state.player.activeMonster.evolve(evolution); + monster.evolve(evolution); UI.drawActiveMonster(); - item.quantity--; + useLowersQuantity = true; } } } + // decrease quantity + if (useLowersQuantity) { + item.quantity--; + + // remove from inventory + if (item.quantity === 0) { + Game.removeItemFromInventory(Memory.state.player.inventory, item.slug); + } + } + Memory.saveToLocalStorage(); }, /** - * @param {Array} inventory - * @param {InventoryItem} item + * @param {InventoryItem[]} inventory + * @param {ItemSlug} itemSlug + */ + getItemFromInventory (inventory, itemSlug) { + return inventory.find((inventoryItem) => inventoryItem.slug === itemSlug); + }, + + /** + * @param {InventoryItem[]} inventory + * @param {ItemSlug} itemSlug */ - removeItemFromInventory (inventory, item) { - inventory.splice(inventory.indexOf(item), 1); + removeItemFromInventory (inventory, itemSlug) { + inventory.splice(inventory.findIndex((inventoryItem) => inventoryItem.slug === itemSlug), 1); }, @@ -867,13 +900,13 @@ const Game = { const playerMonster = Memory.state.player.activeMonster; const opposingMonster = Memory.state.opponent.activeMonster; - const activeBall = Memory.state.activeBall; + const activeBall = Game.getItemFromInventory(Memory.state.player.inventory, Memory.state.activeBall); // remove ball activeBall.quantity--; if (activeBall.quantity === 0) { Game.removeItemFromInventory(Memory.state.player.inventory, Memory.state.activeBall); - Memory.state.activeBall = null; + Memory.state.activeBall = ''; UI.drawActiveBall(); } diff --git a/resources/js/main.js b/resources/js/main.js index 662dff6..ff570ad 100644 --- a/resources/js/main.js +++ b/resources/js/main.js @@ -36,7 +36,7 @@ UI.createEventListener(async function () { await Memory.state.player.initialize(); Game.setActivePlayerMonster(Memory.state.player.monsters[0]); - Memory.state.activeBall = Memory.state.player.inventory[0]; // tuxeball + Memory.state.activeBall = 'tuxeball'; // set rival monster possibleStarterMonsters.splice(possibleStarterMonsters.indexOf(event.detail.monster), 1); diff --git a/resources/js/memory.js b/resources/js/memory.js index 35da905..6450136 100644 --- a/resources/js/memory.js +++ b/resources/js/memory.js @@ -212,7 +212,12 @@ const Memory = { Memory.state.opponent.activeMonster = Memory.state.opponent.monsters[loadedState.opponent.activeMonsterIdx]; Memory.state.rivalMonster = loadedState.rivalMonster; Memory.state.activeTechnique = await loadTechnique(loadedState.activeTechnique); - Memory.state.activeBall = await loadInventoryItem(loadedState.activeBall); + + if (Memory.state.activeBall instanceof String) { // backwards compat: TODO: remove check later + Memory.state.activeBall = loadedState.activeBall; + } else { + Memory.state.activeBall = loadedState.activeBall && loadedState.activeBall.slug; + } // draw game if (!Game.isTown(Memory.state.currentArea)) { diff --git a/resources/js/ui.js b/resources/js/ui.js index 006e6fc..dd287df 100644 --- a/resources/js/ui.js +++ b/resources/js/ui.js @@ -691,6 +691,8 @@ const UI = { /* Map */ + shopSelectionMode: 'buy', + /** * @returns {HTMLElement} */ @@ -785,26 +787,49 @@ const UI = { itemNode.querySelector('[data-template-slot="price"]').innerHTML = formatPrice(price); itemNode.addEventListener('click', () => { - if (Memory.state.money < price) { - alert(`Not enough ${DB.currencies.map[Memory.state.Settings.currency].symbol}.`); - return; - } + if (UI.shopSelectionMode === 'buy') { - Memory.state.money -= price; + if (Memory.state.money < price) { + alert(`Not enough ${DB.currencies.map[Memory.state.Settings.currency].symbol}.`); + return; + } - const itemInInventory = Memory.state.player.inventory.find((inventoryItem) => inventoryItem.slug === item.slug); - if (itemInInventory) { - itemInInventory.quantity++; - } else { - Memory.state.player.inventory.push(new InventoryItem(item, 1)); + Memory.state.money -= price; + + const itemInInventory = Memory.state.player.inventory.find((inventoryItem) => inventoryItem.slug === item.slug); + if (itemInInventory) { + itemInInventory.quantity++; + } else { + Memory.state.player.inventory.push(new InventoryItem(item, 1)); + } + + UI.drawStatus(); } - UI.drawStatus(); + else if (UI.shopSelectionMode === 'info') { + UI.openItemInfo(item); + } }); - template.appendChild(itemNode); + template.querySelector('[data-template-slot="items"]').appendChild(itemNode); } + const selectionModesNode = template.querySelector('[data-template-slot="modes"]'); + const selectionModeNodes = selectionModesNode.querySelectorAll('[data-selection-mode]'); + selectionModeNodes.forEach((node) => { + if (node.dataset.selectionMode === UI.shopSelectionMode) { + node.setAttribute('selected', true); + } + + node.addEventListener('click', () => { + selectionModesNode.querySelector(`[data-selection-mode="${UI.shopSelectionMode}"]`).removeAttribute('selected'); + + UI.shopSelectionMode = node.dataset.selectionMode; + + node.setAttribute('selected', true); + }); + }); + popup.querySelector('.popup').appendChild(template); UI.drawPopup(popup); }, @@ -1089,7 +1114,7 @@ const UI = { } if (Memory.state.activeBall) { - UI.elements.menuCatch.querySelector('img').src = `/modules/tuxemon/mods/tuxemon/gfx/items/${Memory.state.activeBall.slug}.png`; + UI.elements.menuCatch.querySelector('img').src = `/modules/tuxemon/mods/tuxemon/gfx/items/${Memory.state.activeBall}.png`; } else { UI.elements.menuCatch.querySelector('img').src = `/modules/tuxemon/mods/tuxemon/gfx/items/tuxeball.png`; } @@ -1546,7 +1571,12 @@ const UI = { else if (item.category === 'capture') { Game.useItem(item); } + + else if (item.category === 'booster') { + UI.openItemMonsterSelection(item); + } } + else if (UI.inventorySelectionMode === 'info') { UI.openItemInfo(item); } @@ -1586,7 +1616,6 @@ const UI = { await Game.useItem(item, monster); if (item.quantity === 0) { - Game.removeItemFromInventory(Memory.state.player.inventory, item); template.dispatchEvent(new Event('item:isExhausted')); } @@ -1639,7 +1668,7 @@ const UI = { const popup = UI.createPopup(); const template = document.createElement('div'); - template.textContent = item.conditions + ' -- ' + item.effects + ' -- ' + item.description; + template.textContent = item.description; popup.querySelector('.popup').appendChild(template); @@ -1653,6 +1682,7 @@ const UI = { const popup = UI.createPopup(); const dialog = UI.createTemplate(Template.dialogSave); + Memory.saveToLocalStorage(); const saveData = Memory.saveToString(); dialog.querySelector('[data-template-slot="saveData"]').value = saveData; -- cgit v1.2.3