From 91d048ef0f994446aaee91e3afcbd99788e439d7 Mon Sep 17 00:00:00 2001 From: Daniel Weipert Date: Fri, 18 Aug 2023 23:19:13 +0200 Subject: item effects,conditions --- index.html | 6 +- resources/css/menu.css | 12 + resources/js/classes/InventoryItem.js | 8 + resources/js/classes/Item.js | 8 + resources/js/classes/Technique.js | 6 +- resources/js/classes/utility/ItemCondition.js | 18 ++ resources/js/classes/utility/ItemEffect.js | 51 +++ resources/js/classes/utility/TechniqueEffect.js | 72 +++++ resources/js/definitions.js | 7 + resources/js/game.js | 405 +++++++++++------------- resources/js/main.js | 47 +++ resources/js/ui.js | 57 ++-- 12 files changed, 456 insertions(+), 241 deletions(-) create mode 100644 resources/js/classes/utility/ItemCondition.js create mode 100644 resources/js/classes/utility/ItemEffect.js create mode 100644 resources/js/classes/utility/TechniqueEffect.js create mode 100644 resources/js/main.js diff --git a/index.html b/index.html index 39dc63e..e59faa5 100644 --- a/index.html +++ b/index.html @@ -198,7 +198,7 @@ - + @@ -253,6 +253,9 @@ + + + @@ -263,5 +266,6 @@ + diff --git a/resources/css/menu.css b/resources/css/menu.css index de8d8ce..d87e6c8 100644 --- a/resources/css/menu.css +++ b/resources/css/menu.css @@ -16,6 +16,8 @@ .popup { max-width: 100%; + max-height: 80vh; + overflow-y: scroll; background-image: url('/modules/tuxemon/mods/tuxemon/gfx/ui/background/spyder_empty.png'); background-size: cover; @@ -123,6 +125,16 @@ font-size: 1.25rem; } +.inventory__tab { + display: grid; + grid-template-columns: 1fr 1fr 1fr; +} + +.inventory__item { + padding: 0.5rem; + text-align: center; +} + .menu__journal { diff --git a/resources/js/classes/InventoryItem.js b/resources/js/classes/InventoryItem.js index 9dfdbcc..2e9b764 100644 --- a/resources/js/classes/InventoryItem.js +++ b/resources/js/classes/InventoryItem.js @@ -37,4 +37,12 @@ class InventoryItem { get sprite () { return this.item.sprite; } + + get conditions () { + return this.item.conditions; + } + + get effects () { + return this.item.effects; + } } diff --git a/resources/js/classes/Item.js b/resources/js/classes/Item.js index 6207cc2..8a12b9a 100644 --- a/resources/js/classes/Item.js +++ b/resources/js/classes/Item.js @@ -18,4 +18,12 @@ class Item { get sprite () { return DB.items[this.slug].sprite; } + + get conditions () { + return DB.items[this.slug].conditions; + } + + get effects () { + return DB.items[this.slug].effects; + } } diff --git a/resources/js/classes/Technique.js b/resources/js/classes/Technique.js index 7558748..39028be 100644 --- a/resources/js/classes/Technique.js +++ b/resources/js/classes/Technique.js @@ -44,12 +44,12 @@ class Technique { return DB.techniques[this.slug].recharge; } - isUsable () { + isRecharging () { if (this.turnLastUse >= Game.turn) { - return true; + return false; } - return Game.turn - this.turnLastUse >= this.rechargeLength; + return this.rechargeLength > Game.turn - this.turnLastUse; } use () { diff --git a/resources/js/classes/utility/ItemCondition.js b/resources/js/classes/utility/ItemCondition.js new file mode 100644 index 0000000..c8c1fe2 --- /dev/null +++ b/resources/js/classes/utility/ItemCondition.js @@ -0,0 +1,18 @@ +class ItemCondition { + /** + * @param {string} conditionCode + */ + constructor (conditionCode) { + this.is = conditionCode.split(' ')[0]; + this.what = conditionCode.split(' ')[1]; + + if (conditionCode.includes(',')) { + this.comparator = conditionCode.split(' ')[2].split(',')[0]; + this.value = conditionCode.split(' ')[2].split(',')[1]; + } + + else { + this.value = conditionCode.split(' ')[2]; + } + } +} diff --git a/resources/js/classes/utility/ItemEffect.js b/resources/js/classes/utility/ItemEffect.js new file mode 100644 index 0000000..aa1c1df --- /dev/null +++ b/resources/js/classes/utility/ItemEffect.js @@ -0,0 +1,51 @@ +class ItemEffect { + /** + * @type {string} + */ + type = ''; + + /** + * @type {('increase')} + */ + application = ''; + + /** + * @type {number} + */ + amount = 0; + + /** + * @param {string} effectCode + */ + constructor (effectCode) { + if (effectCode.startsWith('heal')) { + this.type = 'heal'; + + this.amount = parseInt(effectCode.split(' ')[1]); + } + + else if (effectCode.startsWith('revive')) { + this.type = 'revive'; + + this.amount = effectCode.split(' ')[1]; + } + + else if (effectCode.startsWith('learn_')) { + this.type = effectCode.split(' ')[0]; + + this.what = effectCode.split(' ')[1]; + } + + else if (Object.values(StatType).includes(effectCode.split(' ')[1] || '')) { + this.type = 'stat'; + + this.application = effectCode.split(' ')[0]; + this.what = effectCode.split(' ')[1].split(',')[0]; + this.amount = effectCode.split(' ')[1].split(',')[1]; + } + + else { + this.type = effectCode; + } + } +} diff --git a/resources/js/classes/utility/TechniqueEffect.js b/resources/js/classes/utility/TechniqueEffect.js new file mode 100644 index 0000000..10e9399 --- /dev/null +++ b/resources/js/classes/utility/TechniqueEffect.js @@ -0,0 +1,72 @@ +class TechniqueEffect { + /** + * @type {string} + */ + type = ''; + + /** + * @type {(('user' | 'target')|Monster)} + */ + recipient = null; + + /** + * @type {('give' | 'remove')} + */ + application = ''; + + /** + * @type {StatusEffectType} + */ + statusEffect = null; + + /** + * @type {Monster} + */ + user = null; + + /** + * @type {Monster} + */ + target = null; + + /** + * @param {string} effectCode + */ + constructor (effectCode) { + if (effectCode.includes('status_')) { + this.type = 'status'; + + this.recipient = effectCode.split(',')[1]; + this.application = effectCode.split(' ')[0]; + this.statusEffect = effectCode.split(',')[0].split(' ')[1].split('_')[1]; + } + + else if (effectCode.includes('healing')) { + this.type = 'healing'; + + this.recipient = effectCode.split(' ')[1]; + } + + else { + this.type = effectCode; + } + } + + /** + * @type {Monster} + */ + setUser (user) { + if (this.recipient === 'user') { + this.recipient = user; + } + } + + /** + * @type {Monster} + */ + setTarget (target) { + if (this.recipient === 'target') { + this.recipient = target; + } + } +} diff --git a/resources/js/definitions.js b/resources/js/definitions.js index b8c5071..22dac16 100644 --- a/resources/js/definitions.js +++ b/resources/js/definitions.js @@ -65,6 +65,10 @@ const TasteWarm = { refined: 'refined', }; +/** + * @readonly + * @enum {string} + */ const TasteCold = { tasteless: 'tasteless', mild: 'mild', @@ -94,6 +98,9 @@ const StatType = { }; +/** + * @enum + */ const StatusEffectType = { blinded: 'blinded', burn: 'burn', diff --git a/resources/js/game.js b/resources/js/game.js index 1ca9387..f68e2fb 100644 --- a/resources/js/game.js +++ b/resources/js/game.js @@ -12,6 +12,132 @@ const Game = { turn: 0, + /** + * @returns {string} + */ + save () { + const saveMonster = (monsterData, monsterState) => { + monsterData.level = monsterState.level; + monsterData.hp = monsterState.hp; + + if (monsterData.statusEffect && monsterData.statusEffect.slug === 'lifeleech') { + monsterData.statusEffect = null; + } + + return monsterData; + }; + + const saveData = JSON.parse(JSON.stringify(state)); + + for (const idx in saveData.monsters) { + saveData.monsters[idx] = saveMonster(saveData.monsters[idx], state.monsters[idx]); + } + + for (const idx in saveData.partyMonsters) { + saveData.partyMonsters[idx] = saveMonster(saveData.partyMonsters[idx], state.partyMonsters[idx]); + } + + saveData.activeMonsterIdx = state.partyMonsters.indexOf(state.activeMonster); + + saveData.enemy.monster = saveMonster(saveData.enemy.monster, state.enemy.monster); + + return btoa(JSON.stringify(saveData)); + }, + + /** + * @param {string} saveData + */ + async load (saveData) { + /** + * @param {Monster} monsterData + */ + const loadMonster = async (monsterData) => { + const monster = await fetchMonster(monsterData.slug); + + monster.level = monsterData.level; + monster.hp = monsterData.hp; + monster.exp = monsterData.exp; + monster.tasteWarm = monsterData.tasteWarm; + monster.tasteCold = monsterData.tasteCold; + monster.gender = monsterData.gender; + monster.heldItem = await loadItem(monsterData.heldItem); + monster.statusEffect = await loadStatusEffect(monsterData.statusEffect); + monster.statModifiers = monsterData.statModifiers; + monster.experienceModifier = monsterData.experienceModifier; + monster.moneyModifier = monsterData.moneyModifier; + monster.activeTechniques = await Promise.all(monsterData.activeTechniques.map(async (technique) => { + return loadTechnique(technique); + })); + + return monster; + }; + + /** + * @param {InventoryItem} inventoryItemData + */ + const loadInventoryItem = async (inventoryItemData) => { + const inventoryItem = new InventoryItem(await fetchItem(inventoryItemData.item.slug)); + + inventoryItem.quantity = inventoryItemData.quantity; + + return inventoryItem; + }; + + /** + * @param {Item} itemData + */ + const loadItem = async (itemData) => { + if (!itemData) { + return null; + } + + const item = await fetchItem(itemData.slug); + + return item; + }; + + /** + * @param {StatusEffect} statusEffectData + */ + const loadStatusEffect = async (statusEffectData) => { + if (!statusEffectData) { + return null; + } + + const statusEffect = await fetchStatusEffect(statusEffectData.slug); + + statusEffect.turnsLeft = statusEffectData.turnsLeft; + + return statusEffect; + }; + + /** + * @param {Technique} techniqueData + */ + const loadTechnique = async (techniqueData) => { + const technique = await fetchTechnique(techniqueData.slug); + + return technique; + }; + + /** + * @type {State} + */ + const loadedState = JSON.parse(atob(saveData)); + + state.money = loadedState.money; + state.monsters = await Promise.all(loadedState.monsters.map(async (monsterData) => await loadMonster(monsterData))); + state.inventory = await Promise.all(loadedState.inventory.map(async (itemData) => await loadInventoryItem(itemData))); + state.partyMonsters = await Promise.all(loadedState.partyMonsters.map(async (monsterData) => await loadMonster(monsterData))); + state.activeMonster = state.partyMonsters[loadedState.activeMonsterIdx]; + state.activeTechnique = await loadTechnique(loadedState.activeTechnique); + state.enemy.monster = await loadMonster(loadedState.enemy.monster); + + UI.drawEnemyMonster(); + UI.drawActiveMonster(); + UI.drawActiveTechniques(); + }, + async progressTurn () { Game.turn++; @@ -62,18 +188,56 @@ const Game = { * @param {Monster} user * @param {Monster} target */ - async useTechnique (technique, user, target) { - technique.use(); + async tryUseTechnique (technique, user, target) { + let canUse = true; - if (!Game.didTechniqueHit) { - UI.drawDamageMiss(UI.createDamageMiss()); - return; + // recharge + if (technique.isRecharging()) { + const feedbackNode = UI.createActionFeedback('recharge'); + UI.drawActionFeedback(feedbackNode); + + canUse = false; } - for (const techniqueEffect of technique.effects) { + // noddingoff + if (user.statusEffect && user.statusEffect.slug === StatusEffectType.noddingoff) { + const feedbackNode = UI.createActionFeedback('noddingoff'); + UI.drawActionFeedback(feedbackNode); + + canUse = false; + } + + if (canUse) { + + // hit? + const accuracy = Math.random(); + Game.didTechniqueHit = technique.accuracy >= accuracy; + if (!Game.didTechniqueHit) { + technique.use(); + UI.drawDamageMiss(UI.createDamageMiss()); + + return; + } + + await Game.useTechnique(technique, user, target); + } + }, + + /** + * @param {Technique} technique + * @param {Monster} user + * @param {Monster} target + */ + async useTechnique (technique, user, target) { + technique.use(); + + for (const techniqueEffectCode of technique.effects) { + const techniqueEffect = new TechniqueEffect(techniqueEffectCode); + techniqueEffect.setUser(user); + techniqueEffect.setTarget(target); // damage - if (['damage', 'splash', 'area'].includes(techniqueEffect)) { + if (['damage', 'splash', 'area'].includes(techniqueEffect.type)) { Game.phases.action.push(() => { const damage = simpleDamageCalculation(state.activeTechnique, state.activeMonster, state.enemy.monster); @@ -82,11 +246,12 @@ const Game = { UI.applyMultiplierToDamage(damageNode, simpleDamageMultiplier(state.activeTechnique.types, state.enemy.monster.types)); UI.applyTechniqueToDamage(damageNode, state.activeTechnique); UI.drawDamage(damageNode); - UI.drawTechniqueAnimation(); + UI.drawTechniqueAnimation(technique); }); } - else if (techniqueEffect === 'money') { + // money + else if (techniqueEffect.type === 'money') { Game.phases.action.push(() => { const money = Math.max(1, Math.floor(Math.random() * target.level)); state.money += money; @@ -94,34 +259,28 @@ const Game = { const damageNode = UI.createDamage(`${money} €`); UI.applyTechniqueToDamage(damageNode, state.activeTechnique); UI.drawDamage(damageNode); - UI.drawTechniqueAnimation(); + UI.drawTechniqueAnimation(technique); }); } - else if (techniqueEffect === 'enhance') { - UI.drawTechniqueAnimation(); + // healing + else if (techniqueEffect.type === 'healing') { + techniqueEffect.recipient.hp = techniqueEffect.recipient.stats.hp; } - // status effect - else if (techniqueEffect.includes('status_')) { - const statusEffect_recipient = techniqueEffect.split(',')[1]; - const statusEffect_application = techniqueEffect.split(' ')[0]; - const statusEffect_type = techniqueEffect.split(',')[0].split(' ')[1].split('_')[0]; - const statusEffect_effect = techniqueEffect.split(',')[0].split(' ')[1].split('_')[1]; + // enhance + else if (techniqueEffect.type === 'enhance') { + UI.drawTechniqueAnimation(technique); + } - const statusEffect = await fetchStatusEffect(statusEffect_effect); + // status effect + else if (techniqueEffect.type === 'status') { + const statusEffect = await fetchStatusEffect(techniqueEffect.statusEffect); if (statusEffect.slug === 'lifeleech') { statusEffect.issuer = user; } - let recipient; - if (statusEffect_recipient === 'user') { - recipient = user; - } else { - recipient = target; - } - Game.phases.postAction.push(() => { // add status effect const potency = Math.random(); @@ -129,22 +288,17 @@ const Game = { if (success) { // TODO: check replace - if (recipient.statusEffect) return; + if (techniqueEffect.recipient.statusEffect) return; - recipient.statusEffect = statusEffect; + techniqueEffect.recipient.statusEffect = statusEffect; } }); - UI.drawTechniqueAnimation(); + UI.drawTechniqueAnimation(technique); } } }, - rechargeTechnique () { - const feedbackNode = UI.createActionFeedback('recharge'); - UI.drawActionFeedback(feedbackNode); - }, - /** * @param {Monster} monster */ @@ -288,15 +442,7 @@ const Game = { async battleClick (event) { UI.battleClickEvent = event; - // hit? - const accuracy = Math.random(); - Game.didTechniqueHit = state.activeTechnique.accuracy >= accuracy; - - if (state.activeTechnique.isUsable()) { - await Game.useTechnique(state.activeTechnique, state.activeMonster, state.enemy.monster); - } else { - Game.rechargeTechnique(); - } + await Game.tryUseTechnique(state.activeTechnique, state.activeMonster, state.enemy.monster); Game.progressTurn(); }, @@ -338,182 +484,9 @@ const Game = { Game.spawnEnemyMonster(); }, - - /** - * @returns {string} - */ - save () { - const saveMonster = (monsterData, monsterState) => { - monsterData.level = monsterState.level; - monsterData.hp = monsterState.hp; - - if (monsterData.statusEffect && monsterData.statusEffect.slug === 'lifeleech') { - monsterData.statusEffect = null; - } - - return monsterData; - }; - - const saveData = JSON.parse(JSON.stringify(state)); - - for (const idx in saveData.monsters) { - saveData.monsters[idx] = saveMonster(saveData.monsters[idx], state.monsters[idx]); - } - - for (const idx in saveData.partyMonsters) { - saveData.partyMonsters[idx] = saveMonster(saveData.partyMonsters[idx], state.partyMonsters[idx]); - } - - saveData.activeMonsterIdx = state.partyMonsters.indexOf(state.activeMonster); - - saveData.enemy.monster = saveMonster(saveData.enemy.monster, state.enemy.monster); - - return btoa(JSON.stringify(saveData)); - }, - - /** - * @param {string} saveData - */ - async load (saveData) { - /** - * @param {Monster} monsterData - */ - const loadMonster = async (monsterData) => { - const monster = await fetchMonster(monsterData.slug); - - monster.level = monsterData.level; - monster.hp = monsterData.hp; - monster.exp = monsterData.exp; - monster.tasteWarm = monsterData.tasteWarm; - monster.tasteCold = monsterData.tasteCold; - monster.gender = monsterData.gender; - monster.heldItem = await loadItem(monsterData.heldItem); - monster.statusEffect = await loadStatusEffect(monsterData.statusEffect); - monster.statModifiers = monsterData.statModifiers; - monster.experienceModifier = monsterData.experienceModifier; - monster.moneyModifier = monsterData.moneyModifier; - monster.activeTechniques = await Promise.all(monsterData.activeTechniques.map(async (technique) => { - return loadTechnique(technique); - })); - - return monster; - }; - - /** - * @param {InventoryItem} inventoryItemData - */ - const loadInventoryItem = async (inventoryItemData) => { - const inventoryItem = new InventoryItem(await fetchItem(inventoryItemData.item.slug)); - - inventoryItem.quantity = inventoryItemData.quantity; - - return inventoryItem; - }; - - /** - * @param {Item} itemData - */ - const loadItem = async (itemData) => { - if (!itemData) { - return null; - } - - const item = await fetchItem(itemData.slug); - - return item; - }; - - /** - * @param {StatusEffect} statusEffectData - */ - const loadStatusEffect = async (statusEffectData) => { - if (!statusEffectData) { - return null; - } - - const statusEffect = await fetchStatusEffect(statusEffectData.slug); - - statusEffect.turnsLeft = statusEffectData.turnsLeft; - - return statusEffect; - }; - - /** - * @param {Technique} techniqueData - */ - const loadTechnique = async (techniqueData) => { - const technique = await fetchTechnique(techniqueData.slug); - - return technique; - }; - - /** - * @type {State} - */ - const loadedState = JSON.parse(atob(saveData)); - - state.money = loadedState.money; - state.monsters = await Promise.all(loadedState.monsters.map(async (monsterData) => await loadMonster(monsterData))); - state.inventory = await Promise.all(loadedState.inventory.map(async (itemData) => await loadInventoryItem(itemData))); - state.partyMonsters = await Promise.all(loadedState.partyMonsters.map(async (monsterData) => await loadMonster(monsterData))); - state.activeMonster = state.partyMonsters[loadedState.activeMonsterIdx]; - state.activeTechnique = await loadTechnique(loadedState.activeTechnique); - state.enemy.monster = await loadMonster(loadedState.enemy.monster); - - UI.drawEnemyMonster(); - UI.drawActiveMonster(); - UI.drawActiveTechniques(); - }, }; // Game click bindings UI.elements.battleEnemy.addEventListener('click', Game.battleClick); UI.elements.techniques.addEventListener('click', Game.techniqueClick); UI.elements.menuCatch.addEventListener('click', Game.catchMonster); - - -(async function () { - await initializeDB(); - - const possibleStarterMonsters = ['budaye', 'dollfin', 'grintot', 'ignibus', 'memnomnom']; - - // state.enemy.monster = await fetchMonster('grintot'); - state.enemy.monster = await fetchMonster(possibleStarterMonsters[Math.round(Math.random() * (possibleStarterMonsters.length - 1))]); - - state.partyMonsters = [ - await fetchMonster('dollfin'), - await fetchMonster(possibleStarterMonsters[Math.round(Math.random() * (possibleStarterMonsters.length - 1))]), - await fetchMonster('corvix'), - await fetchMonster('lunight'), - await fetchMonster('prophetoise'), - await fetchMonster('drashimi'), - await fetchMonster('glombroc'), - await fetchMonster('uneye'), - await fetchMonster('nostray'), - await fetchMonster('dragarbor'), - await fetchMonster('mk01_omega'), - ]; - - state.activeMonster = state.partyMonsters[0]; - state.activeTechnique = state.activeMonster.activeTechniques[0]; - - state.inventory = [ - new InventoryItem(await fetchItem('tuxeball')), - new InventoryItem(await fetchItem('ancient_egg')), - new InventoryItem(await fetchItem('sweet_sand')), - new InventoryItem(await fetchItem('tectonic_drill')), - new InventoryItem(await fetchItem('surfboard')), - new InventoryItem(await fetchItem('sledgehammer')), - new InventoryItem(await fetchItem('raise_melee')), - new InventoryItem(await fetchItem('raise_speed')), - new InventoryItem(await fetchItem('mm_fire')), - new InventoryItem(await fetchItem('mm_water')), - new InventoryItem(await fetchItem('cureall')), - new InventoryItem(await fetchItem('potion')), - new InventoryItem(await fetchItem('super_potion')), - ]; - - UI.drawEnemyMonster(); - UI.drawActiveMonster(); - UI.drawActiveTechniques(); -})(); diff --git a/resources/js/main.js b/resources/js/main.js new file mode 100644 index 0000000..d5bf6fe --- /dev/null +++ b/resources/js/main.js @@ -0,0 +1,47 @@ +(async function () { + await initializeDB(); + + const possibleStarterMonsters = ['budaye', 'dollfin', 'grintot', 'ignibus', 'memnomnom']; + + // state.enemy.monster = await fetchMonster('grintot'); + state.enemy.monster = await fetchMonster(possibleStarterMonsters[Math.round(Math.random() * (possibleStarterMonsters.length - 1))]); + + state.partyMonsters = [ + await fetchMonster('dollfin'), + await fetchMonster(possibleStarterMonsters[Math.round(Math.random() * (possibleStarterMonsters.length - 1))]), + await fetchMonster('corvix'), + await fetchMonster('lunight'), + await fetchMonster('prophetoise'), + await fetchMonster('drashimi'), + await fetchMonster('glombroc'), + await fetchMonster('uneye'), + await fetchMonster('nostray'), + await fetchMonster('dragarbor'), + await fetchMonster('mk01_omega'), + await fetchMonster('jelillow'), + ]; + + state.activeMonster = state.partyMonsters[0]; + state.activeTechnique = state.activeMonster.activeTechniques[0]; + + state.inventory = [ + new InventoryItem(await fetchItem('tuxeball')), + new InventoryItem(await fetchItem('ancient_egg')), + new InventoryItem(await fetchItem('sweet_sand')), + new InventoryItem(await fetchItem('tectonic_drill')), + new InventoryItem(await fetchItem('surfboard')), + new InventoryItem(await fetchItem('sledgehammer')), + new InventoryItem(await fetchItem('raise_melee')), + new InventoryItem(await fetchItem('raise_speed')), + new InventoryItem(await fetchItem('mm_fire')), + new InventoryItem(await fetchItem('mm_water')), + new InventoryItem(await fetchItem('cureall')), + new InventoryItem(await fetchItem('potion')), + new InventoryItem(await fetchItem('super_potion')), + new InventoryItem(await fetchItem('revive')), + ]; + + UI.drawEnemyMonster(); + UI.drawActiveMonster(); + UI.drawActiveTechniques(); +})(); diff --git a/resources/js/ui.js b/resources/js/ui.js index b80ff6f..08e09e2 100644 --- a/resources/js/ui.js +++ b/resources/js/ui.js @@ -332,7 +332,7 @@ const UI = { techniqueNode.querySelector('[data-template-slot="power"]').textContent = technique.power; techniqueNode.querySelector('[data-template-slot="accuracy"]').textContent = technique.accuracy; - if (!technique.isUsable()) { + if (technique.isRecharging()) { techniqueNode.setAttribute('disabled', true); } @@ -384,35 +384,44 @@ const UI = { }, /** + * @param {Technique} technique + * * @returns {void} */ - drawTechniqueAnimation () { + drawTechniqueAnimation (technique) { + const animation = technique.animation; + + if (!(animation && DB.allAnimations[animation])) { + return; + } + + if (UI.techniqueAnimationIsRunning) { + return; + } + UI.techniqueAnimationIsRunning = true; + const x = UI.battleClickEvent.clientX; const y = UI.battleClickEvent.clientY; - if (!UI.techniqueAnimationIsRunning && state.activeTechnique.animation && DB.allAnimations[state.activeTechnique.animation]) { - UI.techniqueAnimationIsRunning = true; + const techniqueAnimationLoop = () => { + UI.elements.battleEnemyAnimation.src = `/modules/tuxemon/mods/tuxemon/animations/technique/${animation}_${("00" + UI.techniqueAnimationNumber).slice(-2)}.png`; + UI.elements.battleEnemyAnimation.style.top = y - (UI.elements.battleEnemyAnimation.clientHeight / 2) + 'px'; + UI.elements.battleEnemyAnimation.style.left = x - (UI.elements.battleEnemyAnimation.clientWidth / 2) + 'px'; + // console.log(UI.elements.battleEnemyAnimation.src); - const techniqueAnimationLoop = () => { - UI.elements.battleEnemyAnimation.src = `/modules/tuxemon/mods/tuxemon/animations/technique/${state.activeTechnique.animation}_${("00" + UI.techniqueAnimationNumber).slice(-2)}.png`; - UI.elements.battleEnemyAnimation.style.top = y - (UI.elements.battleEnemyAnimation.clientHeight / 2) + 'px'; - UI.elements.battleEnemyAnimation.style.left = x - (UI.elements.battleEnemyAnimation.clientWidth / 2) + 'px'; - // console.log(UI.elements.battleEnemyAnimation.src); + UI.techniqueAnimationNumber++; - UI.techniqueAnimationNumber++; - - if (UI.techniqueAnimationNumber >= DB.allAnimations[state.activeTechnique.animation].length) { - UI.techniqueAnimationIsRunning = false; - UI.techniqueAnimationNumber = 0; - UI.elements.battleEnemyAnimation.src = ''; - return; - } + if (UI.techniqueAnimationNumber >= DB.allAnimations[animation].length) { + UI.techniqueAnimationIsRunning = false; + UI.techniqueAnimationNumber = 0; + UI.elements.battleEnemyAnimation.src = ''; + return; + } - setTimeout(() => requestAnimationFrame(techniqueAnimationLoop), 1000 / UI.techniqueAnimationFps); - }; + setTimeout(() => requestAnimationFrame(techniqueAnimationLoop), 1000 / UI.techniqueAnimationFps); + }; - requestAnimationFrame(techniqueAnimationLoop); - } + requestAnimationFrame(techniqueAnimationLoop); }, @@ -426,6 +435,7 @@ const UI = { damageHighlightClickDuration: 0.1, damageHighlightClickTimeout: null, + /** * @param {any} feedback * @@ -638,6 +648,10 @@ const UI = { inventoryItemNode.querySelector('[data-template-slot="name"]').textContent = item.name; inventoryItemNode.querySelector('[data-template-slot="quantity"]').textContent = item.quantity; + inventoryItemNode.addEventListener('click', () => { + alert(item.conditions + item.effects); + }); + if (['potion', 'revive'].includes(item.category)) { tabs['heal'].items.push(inventoryItemNode); } @@ -660,6 +674,7 @@ const UI = { const tabsNode = UI.createTabs(Object.values(tabs).map((tab) => { const content = document.createElement('div'); + content.classList.add('inventory__tab'); for (const item of tab.items) { content.appendChild(item); } -- cgit v1.2.3