diff options
Diffstat (limited to 'resources/js')
-rw-r--r-- | resources/js/game.js | 14 | ||||
-rw-r--r-- | resources/js/main.js | 4 | ||||
-rw-r--r-- | resources/js/memory.js | 2 | ||||
-rw-r--r-- | resources/js/ui.js | 114 |
4 files changed, 74 insertions, 60 deletions
diff --git a/resources/js/game.js b/resources/js/game.js index c64d744..c463ab8 100644 --- a/resources/js/game.js +++ b/resources/js/game.js @@ -179,7 +179,7 @@ const Game = { else { Game.playerIsChoosingNextMonster = true; const monsterSelectionNode = UI.createPlayerDefeatedMonsterSelection(); - monsterSelectionNode.addEventListener('monster:selected', UI.createEventListener(() => Memory.saveToLocalStorage())); + monsterSelectionNode.addEventListener('monster:selected', UI.wrapCallback(() => Memory.saveToLocalStorage())); UI.openPlayerDefeatedMonsterSelection(monsterSelectionNode); } } @@ -570,7 +570,7 @@ const Game = { else if (levelDifference <= -10) levelDifference = levelDifference / 10; const opponentActiveMonster = Memory.state.opponent.activeMonster; - Game.opponentActionTimeout = setTimeout(async () => { + Game.opponentActionTimeout = setTimeout(UI.wrapCallback(async () => { if (opponentActiveMonster.hp <= 0) { Game.opponentActionTimeout = null; return; @@ -592,7 +592,7 @@ const Game = { } Game.opponentActionTimeout = null; - }, Math.max(levelDifference < 10 ? 500 : 50, Math.min(2000 - (speedDifference * 10) - (levelDifference * 100), 3000))); + }), Math.max(levelDifference < 10 ? 500 : 50, Math.min(2000 - (speedDifference * 10) - (levelDifference * 100), 3000))); console.log( 'Opponent Attack Timeout', Memory.state.opponent.activeMonster.stats.speed, Memory.state.player.activeMonster.stats.speed, @@ -999,7 +999,7 @@ const Game = { }; // Game click bindings -UI.elements.nextTrainer.addEventListener('click', UI.createEventListener(Game.encounterTrainer)); -UI.elements.battleOpponent.addEventListener('click', UI.createEventListener(Game.battleClick)); -UI.elements.techniques.addEventListener('click', UI.createEventListener(Game.techniqueClick)); -UI.elements.menuCatch.addEventListener('click', UI.createEventListener(Game.catchMonster)); +UI.elements.nextTrainer.addEventListener('click', UI.wrapCallback(Game.encounterTrainer)); +UI.elements.battleOpponent.addEventListener('click', UI.wrapCallback(Game.battleClick)); +UI.elements.techniques.addEventListener('click', UI.wrapCallback(Game.techniqueClick)); +UI.elements.menuCatch.addEventListener('click', UI.wrapCallback(Game.catchMonster)); diff --git a/resources/js/main.js b/resources/js/main.js index ff570ad..f472a14 100644 --- a/resources/js/main.js +++ b/resources/js/main.js @@ -1,4 +1,4 @@ -UI.createEventListener(async function () { +UI.wrapCallback(async function () { await initializeDB(); // Load existing state @@ -19,7 +19,7 @@ UI.createEventListener(async function () { ); const monsterSelection = UI.openStarterMonsterSelection(possibleStarterMonsters); - monsterSelection.addEventListener('starter:monster:selected', UI.createEventListener(async (event) => { + monsterSelection.addEventListener('starter:monster:selected', UI.wrapCallback(async (event) => { if (!confirm(`Select ${event.detail.monster.name}?`)) { return; } diff --git a/resources/js/memory.js b/resources/js/memory.js index 6450136..1511c25 100644 --- a/resources/js/memory.js +++ b/resources/js/memory.js @@ -213,7 +213,7 @@ const Memory = { Memory.state.rivalMonster = loadedState.rivalMonster; Memory.state.activeTechnique = await loadTechnique(loadedState.activeTechnique); - if (Memory.state.activeBall instanceof String) { // backwards compat: TODO: remove check later + if (typeof loadedState.activeBall === 'string') { // backwards compat: TODO: remove check later Memory.state.activeBall = loadedState.activeBall; } else { Memory.state.activeBall = loadedState.activeBall && loadedState.activeBall.slug; diff --git a/resources/js/ui.js b/resources/js/ui.js index dd287df..089a3c3 100644 --- a/resources/js/ui.js +++ b/resources/js/ui.js @@ -352,9 +352,9 @@ const UI = { battleMonsterNode.classList.add('battle__monster--player'); - battleMonsterNode.querySelector('[data-template-slot="sprite"]').addEventListener('click', () => { + battleMonsterNode.querySelector('[data-template-slot="sprite"]').addEventListener('click', UI.wrapCallback(() => { UI.openStatsMenu(Memory.state.player.activeMonster); - }); + })); if (UI.isHighlighting) { battleMonsterNode.querySelector('[data-template-slot="sprite"]').classList.add(UI.highlightClassName); } @@ -472,7 +472,7 @@ const UI = { const x = UI.battleClickEvent.clientX; const y = UI.battleClickEvent.clientY; - const techniqueAnimationLoop = () => { + const techniqueAnimationLoop = UI.wrapCallback(() => { UI.elements.battleOpponentAnimation.src = `/modules/tuxemon/mods/tuxemon/animations/technique/${animation}_${("00" + UI.techniqueAnimationNumber).slice(-2)}.png`; UI.elements.battleOpponentAnimation.style.top = y - (UI.elements.battleOpponentAnimation.clientHeight / 2) + 'px'; UI.elements.battleOpponentAnimation.style.left = x - (UI.elements.battleOpponentAnimation.clientWidth / 2) + 'px'; @@ -488,7 +488,7 @@ const UI = { } setTimeout(() => requestAnimationFrame(techniqueAnimationLoop), 1000 / UI.techniqueAnimationFps); - }; + }); requestAnimationFrame(techniqueAnimationLoop); }, @@ -673,7 +673,10 @@ const UI = { UI.elements.battleOpponentSprite.classList.add('damaged'); clearTimeout(UI.damageHighlightClickTimeout); - UI.damageHighlightClickTimeout = setTimeout(() => UI.elements.battleOpponentSprite.classList.remove('damaged'), UI.damageHighlightClickDuration * 1000); + UI.damageHighlightClickTimeout = setTimeout( + UI.wrapCallback(() => UI.elements.battleOpponentSprite.classList.remove('damaged')), + UI.damageHighlightClickDuration * 1000 + ); }, /** @@ -706,7 +709,7 @@ const UI = { for (const locationId of Object.keys(currentArea.locations)) { const location = currentArea.locations[locationId]; - template.querySelector(`[data-location="${locationId}"]`).addEventListener('click', () => { + template.querySelector(`[data-location="${locationId}"]`).addEventListener('click', UI.wrapCallback(() => { if (location.type === 'healingCenter') { UI.openHealingCenter(location); } @@ -714,7 +717,7 @@ const UI = { else if (location.type === 'shop') { UI.openShop(location); } - }); + })); } } @@ -731,7 +734,7 @@ const UI = { const price = convertToCurrencyBase(healingCenter.price); template.querySelector('[data-template-slot="price"]').innerHTML = formatPrice(price); - template.querySelector('[data-template-slot="heal"]').addEventListener('click', () => { + template.querySelector('[data-template-slot="heal"]').addEventListener('click', UI.wrapCallback(() => { const applicableMonsters = Memory.state.player.monsters.filter((monster) => { return monster.hp < monster.stats.hp || (monster.statusEffect && monster.statusEffect.category === 'negative') }); @@ -764,7 +767,7 @@ const UI = { monsterSelectionPopup.querySelector('.popup').appendChild(monsterSelection); UI.drawPopup(monsterSelectionPopup); - }); + })); popup.querySelector('.popup').appendChild(template); UI.drawPopup(popup); @@ -786,7 +789,7 @@ const UI = { itemNode.querySelector('[data-template-slot="name"]').innerHTML = item.name; itemNode.querySelector('[data-template-slot="price"]').innerHTML = formatPrice(price); - itemNode.addEventListener('click', () => { + itemNode.addEventListener('click', UI.wrapCallback(() => { if (UI.shopSelectionMode === 'buy') { if (Memory.state.money < price) { @@ -809,7 +812,7 @@ const UI = { else if (UI.shopSelectionMode === 'info') { UI.openItemInfo(item); } - }); + })); template.querySelector('[data-template-slot="items"]').appendChild(itemNode); } @@ -821,13 +824,13 @@ const UI = { node.setAttribute('selected', true); } - node.addEventListener('click', () => { + node.addEventListener('click', UI.wrapCallback(() => { selectionModesNode.querySelector(`[data-selection-mode="${UI.shopSelectionMode}"]`).removeAttribute('selected'); UI.shopSelectionMode = node.dataset.selectionMode; node.setAttribute('selected', true); - }); + })); }); popup.querySelector('.popup').appendChild(template); @@ -855,14 +858,14 @@ const UI = { for (const monster of monsters) { const monsterNode = UI.createMonsterSelectionMonster(monster); - monsterNode.addEventListener('monster:selected', (event) => { + monsterNode.addEventListener('monster:selected', UI.wrapCallback((event) => { template.dispatchEvent(new CustomEvent('monster:selected', { detail: { node: monsterNode, monster: event.detail.monster, }, })); - }); + })); template.appendChild(monsterNode); } @@ -927,13 +930,13 @@ const UI = { node.setAttribute('selected', true); } - node.addEventListener('click', () => { + node.addEventListener('click', UI.wrapCallback(() => { selectionModesNode.querySelector(`[data-party-selection-mode="${UI.partySelectionMode}"]`).removeAttribute('selected'); UI.partySelectionMode = node.dataset.partySelectionMode; node.setAttribute('selected', true); - }); + })); }); return party; @@ -1066,14 +1069,14 @@ const UI = { connectionNode.setAttribute('disabled', true); } - connectionNode.addEventListener('click', () => { + connectionNode.addEventListener('click', UI.wrapCallback(() => { if (canGo) { Game.goToArea(connectionSlug); popup.remove(); } else { alert("Can\'t go there yet!"); } - }); + })); template.appendChild(connectionNode); } @@ -1198,13 +1201,13 @@ const UI = { node.setAttribute('selected', true); } - node.addEventListener('click', () => { + node.addEventListener('click', UI.wrapCallback(() => { selectionModesNode.querySelector(`[data-selection-mode="${UI.inventorySelectionMode}"]`).removeAttribute('selected'); UI.inventorySelectionMode = node.dataset.selectionMode; node.setAttribute('selected', true); - }); + })); }); popup.querySelector('.popup').appendChild(inventory); @@ -1217,11 +1220,11 @@ const UI = { const popup = UI.createPopup(); const journal = UI.createTemplate(Template.menuJournal); - journal.querySelector('[data-template-slot="save"]').addEventListener('click', UI.createEventListener(() => { + journal.querySelector('[data-template-slot="save"]').addEventListener('click', UI.wrapCallback(() => { UI.openSaveDialog(); })); - journal.querySelector('[data-template-slot="load"]').addEventListener('click', UI.createEventListener(() => { + journal.querySelector('[data-template-slot="load"]').addEventListener('click', UI.wrapCallback(() => { UI.openLoadDialog(); })); @@ -1269,7 +1272,7 @@ const UI = { languageSelectNode.appendChild(languageOptionNode); } - languageSelectNode.addEventListener('change', async () => { + languageSelectNode.addEventListener('change', UI.wrapCallback(async () => { const selected = [...languageSelectNode.children].find((node) => node.selected === true); Memory.state.Settings.language = selected.value; @@ -1277,7 +1280,7 @@ const UI = { applyTranslation(); UI.drawArea(); - }); + })); /* Currency */ @@ -1304,7 +1307,7 @@ const UI = { currencySelectNode.appendChild(currencyOptionNode); } - currencySelectNode.addEventListener('change', async () => { + currencySelectNode.addEventListener('change', UI.wrapCallback(async () => { const selected = [...currencySelectNode.children].find((node) => node.selected === true); const previousCurrencyCode = Memory.state.Settings.currency; const newCurrencyCode = selected.value; @@ -1320,14 +1323,14 @@ const UI = { UI.drawArea(); UI.drawStatus(); - }); + })); template.querySelector('[data-template-slot="currency.lastUpdated"]').textContent = DB.currencies.last_updated; // Highlight - template.querySelector('[data-template-slot="highlight"]').addEventListener('click', () => { + template.querySelector('[data-template-slot="highlight"]').addEventListener('click', UI.wrapCallback(() => { UI.isHighlighting = !UI.isHighlighting; const elements = [ @@ -1360,6 +1363,10 @@ const UI = { ]; for (const element of elements) { + if (!element) { + continue; + } + if (UI.isHighlighting) { element.classList.add(UI.highlightClassName); } else { @@ -1373,18 +1380,22 @@ const UI = { Template.map.content.firstElementChild, ]; for (const element of mapElements) { + if (!element) { + continue; + } + if (UI.isHighlighting) { element.classList.add(`${UI.highlightClassName}--map`); } else { element.classList.remove(`${UI.highlightClassName}--map`); } } - }); + })); // Clear save data - template.querySelector('[data-template-slot="clearLocalSaveData"]').addEventListener('click', UI.createEventListener(() => { + template.querySelector('[data-template-slot="clearLocalSaveData"]').addEventListener('click', UI.wrapCallback(() => { if (confirm(translate('ui:settings:clear_local_save_data:confirm', true))) { localStorage.removeItem('state'); window.location.reload(); @@ -1445,7 +1456,7 @@ const UI = { template.querySelector('[data-template-slot="stats.dodge.value"]').textContent = monster.stats.dodge; template.querySelector('[data-template-slot="stats.speed.value"]').textContent = monster.stats.speed; - template.querySelector('[data-template-slot="techniques"]').addEventListener('click', () => UI.openMovesetSelection(monster)); + template.querySelector('[data-template-slot="techniques"]').addEventListener('click', UI.wrapCallback(() => UI.openMovesetSelection(monster))); return template; }, @@ -1479,7 +1490,7 @@ const UI = { } // clicked - movesetItemNode.addEventListener('click', () => { + movesetItemNode.addEventListener('click', UI.wrapCallback(() => { if (movesetItemNode.getAttribute('disabled')) { return false; } @@ -1508,7 +1519,7 @@ const UI = { }, }); UI.events.dispatchEvent(event); - }); + })); movesetListNode.appendChild(movesetItemNode); } @@ -1535,7 +1546,7 @@ const UI = { const movesetSelection = await UI.createMovesetSelection(monster); popup.querySelector('.popup').appendChild(movesetSelection); - popup.addEventListener('close', () => UI.drawActiveTechniques()); + popup.addEventListener('close', UI.wrapCallback(() => UI.drawActiveTechniques())); UI.drawPopup(popup); }, @@ -1558,7 +1569,7 @@ const UI = { inventoryItemNode.querySelector('[data-template-slot="name"]').textContent = item.name; inventoryItemNode.querySelector('[data-template-slot="quantity"]').textContent = item.quantity; - inventoryItemNode.addEventListener('click', async () => { + inventoryItemNode.addEventListener('click', UI.wrapCallback(async () => { if (UI.inventorySelectionMode === 'use') { if (item.category === 'potion') { UI.openItemMonsterSelection(item); @@ -1580,7 +1591,7 @@ const UI = { else if (UI.inventorySelectionMode === 'info') { UI.openItemInfo(item); } - }); + })); return inventoryItemNode; }, @@ -1686,7 +1697,7 @@ const UI = { const saveData = Memory.saveToString(); dialog.querySelector('[data-template-slot="saveData"]').value = saveData; - dialog.querySelector('[data-template-slot="saveClipboard"]').addEventListener('click', UI.createEventListener(async () => { + dialog.querySelector('[data-template-slot="saveClipboard"]').addEventListener('click', UI.wrapCallback(async () => { if (navigator.clipboard) { await navigator.clipboard.writeText(saveData); alert('Saved to clipboard!'); @@ -1703,7 +1714,7 @@ const UI = { const popup = UI.createPopup(); const dialog = UI.createTemplate(Template.dialogLoad); - dialog.querySelector('[data-template-slot="load"]').addEventListener('click', UI.createEventListener(() => { + dialog.querySelector('[data-template-slot="load"]').addEventListener('click', UI.wrapCallback(() => { Memory.loadFromString( dialog.querySelector('[data-template-slot="saveData"]').value.trim() ); @@ -1719,17 +1730,20 @@ const UI = { // Error /** - * @param {Function} listener + * @param {Function} callback * * @returns {Function} */ - createEventListener (listener) { - return (event) => { + wrapCallback (callback) { + return async (...arguments) => { try { - listener(event); + await callback(...arguments); } catch (exception) { console.log(exception); - UI.showErrorMessage(exception); + UI.showErrorMessage( + `${exception}\n\n${exception.stack}\n` + + 'Please report at https://gitlab.com/dweipert.de/games/tuxemonclicker!' + ); } }; }, @@ -1743,10 +1757,10 @@ const UI = { }; // UI element click bindings -UI.elements.showMap.addEventListener('click', UI.createEventListener(UI.openMap)); -UI.elements.changeArea.addEventListener('click', UI.createEventListener(UI.createEventListener(UI.openAreaSelection))); -UI.elements.menuParty.addEventListener('click', UI.createEventListener(UI.openPartyMenu)); -UI.elements.menuInventory.addEventListener('click', UI.createEventListener(UI.openInventoryMenu)); -UI.elements.menuLog.addEventListener('click', UI.createEventListener(UI.toggleLog)); -UI.elements.menuJournal.addEventListener('click', UI.createEventListener(UI.openJournalMenu)); -UI.elements.menuSettings.addEventListener('click', UI.createEventListener(UI.openSettingsMenu)); +UI.elements.showMap.addEventListener('click', UI.wrapCallback(UI.openMap)); +UI.elements.changeArea.addEventListener('click', UI.wrapCallback(UI.openAreaSelection)); +UI.elements.menuParty.addEventListener('click', UI.wrapCallback(UI.openPartyMenu)); +UI.elements.menuInventory.addEventListener('click', UI.wrapCallback(UI.openInventoryMenu)); +UI.elements.menuLog.addEventListener('click', UI.wrapCallback(UI.toggleLog)); +UI.elements.menuJournal.addEventListener('click', UI.wrapCallback(UI.openJournalMenu)); +UI.elements.menuSettings.addEventListener('click', UI.wrapCallback(UI.openSettingsMenu)); |