summaryrefslogtreecommitdiff
path: root/resources
diff options
context:
space:
mode:
Diffstat (limited to 'resources')
-rw-r--r--resources/js/game.js14
-rw-r--r--resources/js/main.js4
-rw-r--r--resources/js/memory.js2
-rw-r--r--resources/js/ui.js114
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));