diff options
author | Daniel Weipert <code@drogueronin.de> | 2023-08-16 14:16:27 +0200 |
---|---|---|
committer | Daniel Weipert <code@drogueronin.de> | 2023-08-16 14:16:27 +0200 |
commit | bcf6e73b067af23265d0a092148d026985f2694a (patch) | |
tree | 39036715e95c311a1b500b4b8501a80c6d1ddc9f | |
parent | f2ef812f6e21582dd767814bca1b7b2e3a9aab15 (diff) |
status effect duration + hit/miss
-rw-r--r-- | script.js | 178 |
1 files changed, 142 insertions, 36 deletions
@@ -129,6 +129,7 @@ class State { activeTechnique = null; turn = 0; + currentArea = null; enemy = { monster: null, @@ -339,20 +340,22 @@ class Monster { }; class Technique { + #accuracy = 0; + #potency = 0; + #power = 0; + combatEffects = []; constructor (slug) { this.slug = slug; + + this.resetToBase(); } get types () { return DB.techniques[this.slug].types; } - get power () { - return DB.techniques[this.slug].power; - } - get range () { return DB.techniques[this.slug].range; } @@ -368,6 +371,45 @@ class Technique { get effects () { return DB.techniques[this.slug].effects; } + + get accuracy () { + return this.#accuracy; + } + set accuracy (accuracy) { + this.#accuracy = accuracy; + } + + get potency () { + return this.#potency; + } + set potency (potency) { + this.#potency = potency; + } + + get power () { + return this.#power; + } + set power (power) { + this.#power = power; + } + + get base () { + const accuracy = DB.techniques[this.slug].accuracy; + const potency = DB.techniques[this.slug].potency; + const power = DB.techniques[this.slug].power; + + return { + accuracy, + potency, + power, + }; + } + + resetToBase () { + this.accuracy = this.base.accuracy; + this.potency = this.base.potency; + this.power = this.base.power; + } } class Item {} @@ -387,16 +429,31 @@ class StatusEffect { constructor (slug) { this.slug = slug; - this.turnsLeft = Math.ceil(Math.random() * 3) + 2; if (['recover', 'lifeleech'].includes(this.slug)) { this.turnsLeft = 1; } + else if (['charging'].includes(this.slug)) { + this.turnsLeft = 2; + } + else if (this.category === 'positive') { + this.turnsLeft = Math.ceil(Math.random() * 6) + 4; + } + else if (this.category === 'negative') { + this.turnsLeft = Math.ceil(Math.random() * 3) + 2; + } + else { + this.turnsLeft = Math.ceil(Math.random() * 3) + 2; + } } get effects () { return DB.statusEffects[this.slug].effects; } + get category () { + return DB.statusEffects[this.slug].category; + } + get name () { return slugToName(this.slug); } @@ -433,6 +490,10 @@ function simpleDamageMultiplier (techniqueTypes, targetTypes) { return Math.max(0.25, Math.min(multiplier, 4)); } function simpleDamageCalculation (technique, user, target) { + if (technique.power === 0) { + return 0; + } + let userBaseStrength = user.level + 7; let userStrength = 1; let targetResist = 1; @@ -545,6 +606,7 @@ function slugToName (slug) { await fetchMonster('glombroc'), await fetchMonster('uneye'), await fetchMonster('nostray'), + await fetchMonster('dragarbor'), ]; state.activeMonster = state.partyMonsters[0]; state.activeTechnique = await fetchTechnique(state.activeMonster.moveset[0].technique); @@ -731,11 +793,6 @@ function slugToName (slug) { const movesetList = UI.getTemplate(templateMovesetList); for (const move of state.activeMonster.moveset) { const technique = await fetchTechnique(move.technique); - - if (technique.power === 0) { - continue; - } - const movesetItem = UI.getTemplate(templateMovesetItem); movesetItem.querySelector('.moveset__item__name').textContent = slugToName(technique.slug); @@ -871,7 +928,11 @@ function slugToName (slug) { continue; } - recipient.statusEffect = await fetchStatusEffect(effect.effect); + const potency = Math.random(); + const success = technique.potency >= potency; + if (success) { + recipient.statusEffect = await fetchStatusEffect(effect.effect); + } } else if (effect.application === 'remove') { if (recipient.statusEffect.slug === effect.effect) { @@ -884,7 +945,7 @@ function slugToName (slug) { technique.combatEffects = combatEffects; }, - applyStatusEffect (affectedMonster, opposingMonster) { + async applyStatusEffect (affectedMonster, opposingMonster) { if (!affectedMonster.statusEffect) { return; } @@ -913,6 +974,14 @@ function slugToName (slug) { UI.createDamage(clickEvent, statusEffectLeech); } + else if (affectedMonster.statusEffect.slug === 'charging') { + turnEndPhaseEvents.push(async () => { + if (affectedMonster.statusEffect.turnsLeft === 0) { + affectedMonster.statusEffect = await fetchStatusEffect('chargedup'); + } + }); + } + else if (affectedMonster.statusEffect.effects.includes('statchange')) { affectedMonster.resetStatusModifier(); @@ -925,12 +994,12 @@ function slugToName (slug) { } affectedMonster.statusEffect.turnsLeft--; - if (affectedMonster.statusEffect.turnsLeft === 0) { - postCleanUps.push(() => { + turnEndPhaseEvents.push(() => { + if (affectedMonster.statusEffect.turnsLeft === 0) { affectedMonster.statusEffect = null; affectedMonster.resetStatusModifier(); - }); - } + } + }); }, applyTechniqueEffect (technique, user, target) { @@ -939,6 +1008,30 @@ function slugToName (slug) { state.money += Math.floor(Math.random() * target.level); } } + + // modify technique stats + if (user.statusEffect) { + if (user.statusEffect.slug === 'grabbed') { + if ([TechniqueRange.ranged, TechniqueRange.reach].includes(technique.range)) { + technique.potency = technique.base.potency * 0.5; + technique.power = technique.base.power * 0.5; + } + } + + else if (user.statusEffect.slug === 'stuck') { + if ([TechniqueRange.melee, TechniqueRange.touch].includes(technique.range)) { + technique.potency = technique.base.potency * 0.5; + technique.power = technique.base.power * 0.5; + } + } + + // remove effect + if (user.statusEffect.turnsLeft === 0) { + turnEndPhaseEvents.push(() => { + technique.resetToBase(); + }); + } + } }, }; @@ -946,33 +1039,43 @@ function slugToName (slug) { UI.setEnemyMonster(); let clickEvent; - let postCleanUps = []; + let turnEndPhaseEvents = []; document.querySelector('#battle__enemy').addEventListener('click', async (event) => { clickEvent = event; - await Game.useTechnique(state.activeTechnique, state.activeMonster, state.enemy.monster); - Game.applyTechniqueEffect(state.activeTechnique, state.activeMonster, state.enemy.monster); + const accuracy = Math.random(); + const hit = state.activeTechnique.accuracy >= accuracy; + + if (hit) { + await Game.useTechnique(state.activeTechnique, state.activeMonster, state.enemy.monster); + } + + await Game.applyStatusEffect(state.activeMonster, state.enemy.monster); + await Game.applyStatusEffect(state.enemy.monster, state.activeMonster); - const damage = simpleDamageCalculation(state.activeTechnique, state.activeMonster, state.enemy.monster); - UI.createDamage(event, damage); + if (hit) { + Game.applyTechniqueEffect(state.activeTechnique, state.activeMonster, state.enemy.monster); - Game.applyStatusEffect(state.activeMonster, state.enemy.monster); - Game.applyStatusEffect(state.enemy.monster, state.activeMonster); + const damage = simpleDamageCalculation(state.activeTechnique, state.activeMonster, state.enemy.monster); + UI.createDamage(event, damage); - state.enemy.monster.hp -= damage; - if (state.enemy.monster.hp <= 0) { - const faintedMonster = state.enemy.monster; + state.enemy.monster.hp -= damage; + if (state.enemy.monster.hp <= 0) { + const faintedMonster = state.enemy.monster; - await UI.createNewEnemyMonster(); + await UI.createNewEnemyMonster(); - state.money += faintedMonster.level * faintedMonster.moneyModifier; + state.money += faintedMonster.level * faintedMonster.moneyModifier; - state.activeMonster.exp += calculateAwardedExperience(state.activeMonster, faintedMonster); - state.activeMonster.levelUp(); - if (state.activeMonster.canEvolve()) { - await fetchMonster(state.activeMonster.evolutions[0].monster_slug); - state.activeMonster.evolve(); + state.activeMonster.exp += calculateAwardedExperience(state.activeMonster, faintedMonster); + state.activeMonster.levelUp(); + if (state.activeMonster.canEvolve()) { + await fetchMonster(state.activeMonster.evolutions[0].monster_slug); + state.activeMonster.evolve(); + } } + } else { + UI.createDamage(event, 'MISS!'); } UI.setActiveMonster(); @@ -982,10 +1085,13 @@ function slugToName (slug) { money.textContent = state.money; - for (const cleanUp of postCleanUps) { - cleanUp(); + for (const turnEndPhaseEvent of turnEndPhaseEvents) { + const returnValue = turnEndPhaseEvent(); + if (returnValue instanceof Promise) { + await returnValue; + } } - postCleanUps = []; + turnEndPhaseEvents = []; }); document.querySelector('#menu__party').addEventListener('click', UI.openPartyMenu); |