diff options
-rw-r--r-- | script.js | 192 |
1 files changed, 127 insertions, 65 deletions
@@ -128,6 +128,8 @@ class State { activeMonster = null; activeTechnique = null; + turn = 0; + enemy = { monster: null, }; @@ -135,7 +137,6 @@ class State { class Monster { #level = 1; - #status = null; #hp = 0; exp = 1; @@ -264,33 +265,6 @@ class Monster { this.hp = statusPostEvolve.hp - (statusPreEvolve.hp - hpPreEvolve); } - async useTechnique(technique, enemy) { - const additionalEffects = technique.effects - .filter((effect) => !['damage', 'splash', 'area'].includes(effect)) - .map((effect) => new TechniqueEffect(effect)); - - for (const effect of additionalEffects) { - let recipient; - - if (effect.recipient === 'user') { - recipient = this; - } else { - recipient = enemy; - } - - if (effect.type === 'status') { - if (effect.application === 'give') { - recipient.statusEffect = await fetchStatusEffect(effect.effect); - } - else if (effect.application === 'remove') { - if (recipient.statusEffect.slug === effect.effect) { - recipient.statusEffect = ''; - } - } - } - } - } - getTasteStatusModifier (statusName, baseStatus) { let positive = 0; let negative = 0; @@ -329,10 +303,6 @@ class Monster { } get status () { - if (this.#status) { - return this.#status; - } - const multiplier = this.level + 7; let hp = (this.shape.hp * multiplier) + this.statusModifier.hp; let melee = (this.shape.melee * multiplier) + this.statusModifier.melee; @@ -348,7 +318,7 @@ class Monster { dodge += this.getTasteStatusModifier('dodge', melee); speed += this.getTasteStatusModifier('speed', melee); - this.#status = { + return { hp, melee, armour, @@ -356,21 +326,21 @@ class Monster { dodge, speed, }; - - return this.#status; } - set status (status) { - this.#status = status; + setStatusModifier (statusType, newAbsoluteValue) { + this.statusModifier[statusType] = newAbsoluteValue - this.status[statusType]; } - - resetStatus () { - this.#status = null; - this.status; + resetStatusModifier () { + for (const m in this.statusModifier) { + this.statusModifier[m] = 0; + } } }; class Technique { + combatEffects = []; + constructor (slug) { this.slug = slug; } @@ -412,8 +382,15 @@ class TechniqueEffect { } class StatusEffect { + turnsLeft = 0; + constructor (slug) { this.slug = slug; + + this.turnsLeft = Math.ceil(Math.random() * 3) + 2; + if (['recover', 'lifeleech'].includes(this.slug)) { + this.turnsLeft = 1; + } } get effects () { @@ -566,6 +543,8 @@ function slugToName (slug) { await fetchMonster('prophetoise'), await fetchMonster('drashimi'), await fetchMonster('glombroc'), + await fetchMonster('uneye'), + await fetchMonster('nostray'), ]; state.activeMonster = state.partyMonsters[0]; state.activeTechnique = await fetchTechnique(state.activeMonster.moveset[0].technique); @@ -698,14 +677,13 @@ function slugToName (slug) { if (where === 'player') { UI.setExp(monster, battleMonster.querySelector('.exp')); - battleMonster.querySelector('.battle__monster-technique').innerHTML = - slugToName(state.activeTechnique.slug) + ' ' - + state.activeTechnique.types.map((type) => UI.createElementTypeIcon(type)).join(''); battleMonster.querySelector('.battle__monster-technique').addEventListener('click', UI.openMovesetSelection); battleMonster.classList.add('battle__monster--player'); battlePlayer.querySelector('.battle__monster') && battlePlayer.removeChild(battlePlayer.querySelector('.battle__monster')); battlePlayer.appendChild(battleMonster); + + UI.setActiveTechnique(); } else { battleMonster.classList.add('battle__monster--enemy'); @@ -731,14 +709,20 @@ function slugToName (slug) { UI.setBattleMonster(state.activeMonster, 'player'); }, - async setActiveTechnique () { + setActiveTechnique () { + battlePlayer.querySelector('.battle__monster-technique').innerHTML = + slugToName(state.activeTechnique.slug) + ' ' + + state.activeTechnique.types.map((type) => UI.createElementTypeIcon(type)).join(''); + }, + + async chooseActiveTechnique () { let activeMoveIndex = 0; while ((await fetchTechnique(state.activeMonster.moveset[activeMoveIndex].technique)).power === 0) { activeMoveIndex++; } state.activeTechnique = await fetchTechnique(state.activeMonster.moveset[activeMoveIndex].technique); - UI.setBattleMonster(state.activeMonster, 'player'); + UI.setActiveTechnique(); }, async openMovesetSelection () { @@ -765,7 +749,7 @@ function slugToName (slug) { } state.activeTechnique = technique; - UI.setBattleMonster(state.activeMonster, 'player'); + UI.setActiveTechnique(); popup.remove(); }); @@ -825,14 +809,14 @@ function slugToName (slug) { partyMonster.dataset.slug = monster.slug; partyMonster.querySelector('img').src = `/modules/tuxemon/mods/tuxemon/gfx/sprites/battle/${monster.slug}-front.png`; - partyMonster.addEventListener('click', (event) => { + partyMonster.addEventListener('click', async (event) => { let target = event.target; while (target.parentNode.id !== 'party') { target = target.parentNode; } state.activeMonster = state.partyMonsters[Array.prototype.indexOf.call(document.querySelector('#party').children, target)]; - UI.setActiveTechnique(); + await UI.chooseActiveTechnique(); UI.setActiveMonster(); popup.remove(); @@ -859,29 +843,100 @@ function slugToName (slug) { }; const Game = { - applyEffect (monster) { - if (!monster.statusEffect) { + async useTechnique(technique, user, target) { + let statusEffects = []; + let combatEffects = []; + + for (const effect of technique.effects) { + if (effect.includes('status_')) { + statusEffects.push(new TechniqueEffect(effect)); + } + else if (!['damage', 'splash', 'area'].includes(effect)) { + combatEffects.push(effect); + } + } + + for (const effect of statusEffects) { + let recipient; + + if (effect.recipient === 'user') { + recipient = user; + } else { + recipient = target; + } + + if (effect.type === 'status') { + if (effect.application === 'give') { + if (recipient.statusEffect) { + continue; + } + + recipient.statusEffect = await fetchStatusEffect(effect.effect); + } + else if (effect.application === 'remove') { + if (recipient.statusEffect.slug === effect.effect) { + recipient.statusEffect = ''; + } + } + } + } + + technique.combatEffects = combatEffects; + }, + + applyStatusEffect (affectedMonster, opposingMonster) { + if (!affectedMonster.statusEffect) { + return; + } + + if (! (affectedMonster.statusEffect instanceof StatusEffect)) { return; } - if (monster.statusEffect.slug === 'poison' || monster.statusEffect.slug === 'burn') { - const statusEffectDamage = Math.floor(monster.status.hp / 8); + if (affectedMonster.statusEffect.slug === 'poison' || affectedMonster.statusEffect.slug === 'burn') { + const statusEffectDamage = Math.floor(affectedMonster.status.hp / 8); + affectedMonster.hp -= statusEffectDamage; + UI.createDamage(clickEvent, statusEffectDamage); - monster.hp -= statusEffectDamage; } - if (monster.statusEffect.slug === 'recover') { - const statusEffectHeal = Math.floor(monster.status.hp / 16); - monster.hp += statusEffectHeal; + else if (affectedMonster.statusEffect.slug === 'recover') { + const statusEffectHeal = Math.floor(affectedMonster.status.hp / 16); + affectedMonster.hp += statusEffectHeal; + } + + else if (affectedMonster.statusEffect.slug === 'lifeleech') { + const statusEffectLeech = Math.floor(affectedMonster.status.hp / 16); + affectedMonster.hp -= statusEffectLeech; + opposingMonster.hp += statusEffectLeech; + + UI.createDamage(clickEvent, statusEffectLeech); } - if (monster.statusEffect.effects.includes('statchange')) { - monster.resetStatus(); + else if (affectedMonster.statusEffect.effects.includes('statchange')) { + affectedMonster.resetStatusModifier(); - for (const statusType in monster.statusEffect.status) { - const statusChange = monster.statusEffect.status[statusType]; + for (const statusType in affectedMonster.statusEffect.status) { + const statusChange = affectedMonster.statusEffect.status[statusType]; - monster.status[statusType] = Math.floor(eval(`${monster.status[statusType]} ${statusChange.operation} ${statusChange.value}`)); + const modifiedValue = Math.floor(eval(`${affectedMonster.status[statusType]} ${statusChange.operation} ${statusChange.value}`)); + affectedMonster.setStatusModifier(statusType, modifiedValue); + } + } + + affectedMonster.statusEffect.turnsLeft--; + if (affectedMonster.statusEffect.turnsLeft === 0) { + postCleanUps.push(() => { + affectedMonster.statusEffect = null; + affectedMonster.resetStatusModifier(); + }); + } + }, + + applyTechniqueEffect (technique, user, target) { + for (const effect of technique.combatEffects) { + if (effect === 'money') { + state.money += Math.floor(Math.random() * target.level); } } }, @@ -891,16 +946,18 @@ function slugToName (slug) { UI.setEnemyMonster(); let clickEvent; + let postCleanUps = []; document.querySelector('#battle__enemy').addEventListener('click', async (event) => { clickEvent = event; - Game.applyEffect(state.activeMonster); - Game.applyEffect(state.enemy.monster); + await Game.useTechnique(state.activeTechnique, state.activeMonster, state.enemy.monster); + Game.applyTechniqueEffect(state.activeTechnique, state.activeMonster, state.enemy.monster); const damage = simpleDamageCalculation(state.activeTechnique, state.activeMonster, state.enemy.monster); UI.createDamage(event, damage); - await state.activeMonster.useTechnique(state.activeTechnique, state.enemy.monster); + Game.applyStatusEffect(state.activeMonster, state.enemy.monster); + Game.applyStatusEffect(state.enemy.monster, state.activeMonster); state.enemy.monster.hp -= damage; if (state.enemy.monster.hp <= 0) { @@ -924,6 +981,11 @@ function slugToName (slug) { UI.setHp(state.enemy.monster, battleEnemy); money.textContent = state.money; + + for (const cleanUp of postCleanUps) { + cleanUp(); + } + postCleanUps = []; }); document.querySelector('#menu__party').addEventListener('click', UI.openPartyMenu); |