diff options
Diffstat (limited to 'resources/js/classes')
-rw-r--r-- | resources/js/classes/Item.js | 1 | ||||
-rw-r--r-- | resources/js/classes/Monster.js | 223 | ||||
-rw-r--r-- | resources/js/classes/State.js | 38 | ||||
-rw-r--r-- | resources/js/classes/StatusEffect.js | 55 | ||||
-rw-r--r-- | resources/js/classes/Technique.js | 77 |
5 files changed, 394 insertions, 0 deletions
diff --git a/resources/js/classes/Item.js b/resources/js/classes/Item.js new file mode 100644 index 0000000..e274a20 --- /dev/null +++ b/resources/js/classes/Item.js @@ -0,0 +1 @@ +class Item {} diff --git a/resources/js/classes/Monster.js b/resources/js/classes/Monster.js new file mode 100644 index 0000000..9023f32 --- /dev/null +++ b/resources/js/classes/Monster.js @@ -0,0 +1,223 @@ +class Monster { + #level = 2; + #hp = 0; + + exp = 1; + + tasteWarm = TasteWarm.tasteless; + tasteCold = TasteCold.tasteless; + + gender = ''; + + heldItem = null; + + /** + * @type {StatusEffect} + */ + statusEffect = null; + + statModifiers = { + hp: 0, + melee: 0, + armour: 0, + ranged: 0, + dodge: 0, + speed: 0, + }; + + experienceModifier = 1; + moneyModifier = 1; + + /** + * @type {Technique[]} + */ + activeTechniques = []; + + constructor (slug) { + this.slug = slug; + + const tasteWarm = Object.keys(TasteWarm).slice(1); + this.tasteWarm = tasteWarm[Math.floor(Math.random() * tasteWarm.length)]; + const tasteCold = Object.keys(TasteCold).slice(1); + this.tasteCold = tasteCold[Math.floor(Math.random() * tasteCold.length)]; + + this.hp = this.stats.hp; + + const possibleGenders = DB.monsters[this.slug].possible_genders; + this.gender = possibleGenders[Math.floor(Math.random() * possibleGenders.length)]; + + } + + async initialize () { + for (const move of this.getLearnableTechniques()) { + this.activeTechniques.push(await fetchTechnique(move.technique)); + } + } + + get shape () { + for (const shapeData of DB.shapes) { + if (shapeData.slug === DB.monsters[this.slug].shape) { + return shapeData; + } + } + } + + get types () { + return DB.monsters[this.slug].types; + } + + get moveset () { + return DB.monsters[this.slug].moveset; + } + + get evolutions () { + return DB.monsters[this.slug].evolutions; + } + + get level () { + return this.#level; + } + + set level (level) { + const statsPreLevelUp = this.stats; + const hpPreLevelUp = this.hp; + + this.#level = level; + + const statsPostLevelUp = this.stats; + + this.hp = statsPostLevelUp.hp - (statsPreLevelUp.hp - hpPreLevelUp); + + if (this.exp < this.getExperienceRequired(-1)) { + this.exp = this.getExperienceRequired(-1); + } + } + + get hp () { + return this.#hp; + } + + set hp (hp) { + this.#hp = Math.max(0, Math.min(hp, this.stats.hp)); + } + + get name () { + return slugToName(this.slug); + } + + getLearnableTechniques () { + return this.moveset.filter((move) => this.level >= move.level_learned); + } + + canLevelUp () { + return this.exp >= this.getExperienceRequired(); + } + + levelUp () { + while (this.canLevelUp()) { + this.level++; + } + } + + getExperienceRequired (levelOffset = 0) { + return Math.max( + Math.pow(this.level + levelOffset, 3), + 1 + ); + } + + getPossibleEvolutions () { + // return this.evolutions.filter((evolution) => this.level >= evolution.at_level && (!evolution.item || this.heldItem === evolution.item)); + return this.evolutions.filter((evolution) => evolution.path === 'standard' && this.level >= evolution.at_level); + } + + canEvolve () { + return this.getPossibleEvolutions().length > 0; + } + + evolve () { + const evolution = this.getPossibleEvolutions()[0]; + + const statsPreEvolve = this.stats; + const hpPreEvolve = this.hp; + + this.slug = evolution.monster_slug; + + const statsPostEvolve = this.stats; + + this.hp = statsPostEvolve.hp - (statsPreEvolve.hp - hpPreEvolve); + } + + getTasteStatModifier (statType, baseStat) { + let positive = 0; + let negative = 0; + + let isPositive = false; + let isNegative = false; + if (statType === StatType.melee) { + isPositive = this.tasteWarm === TasteWarm.salty; + isNegative = this.tasteCold === TasteCold.sweet; + } + else if (statType === StatType.armour) { + isPositive = this.tasteWarm === TasteWarm.hearty; + isNegative = this.tasteCold === TasteCold.soft; + } + else if (statType === StatType.ranged) { + isPositive = this.tasteWarm === TasteWarm.zesty; + isNegative = this.tasteCold === TasteCold.flakey; + } + else if (statType === StatType.dodge) { + isPositive = this.tasteWarm === TasteWarm.refined; + isNegative = this.tasteCold === TasteCold.dry; + } + else if (statType === StatType.speed) { + isPositive = this.tasteWarm === TasteWarm.peppy; + isNegative = this.tasteCold === TasteCold.mild; + } + + if (isPositive) { + positive = baseStat * 10 / 100; + } + if (isNegative) { + negative = baseStat * 10 / 100; + } + + return Math.floor(positive) - Math.floor(negative); + } + + get stats () { + const multiplier = this.level + 7; + let hp = (this.shape.hp * multiplier) + this.statModifiers.hp; + let melee = (this.shape.melee * multiplier) + this.statModifiers.melee; + let armour = (this.shape.armour * multiplier) + this.statModifiers.armour; + let ranged = (this.shape.ranged * multiplier) + this.statModifiers.ranged; + let dodge = (this.shape.dodge * multiplier) + this.statModifiers.dodge; + let speed = (this.shape.speed * multiplier) + this.statModifiers.speed; + + // Tastes + melee += this.getTasteStatModifier(StatType.melee, melee); + armour += this.getTasteStatModifier(StatType.armour, armour); + ranged += this.getTasteStatModifier(StatType.ranged, ranged); + dodge += this.getTasteStatModifier(StatType.dodge, dodge); + speed += this.getTasteStatModifier(StatType.speed, speed); + + return { + hp: hp, + [StatType.melee]: melee, + [StatType.armour]: armour, + [StatType.ranged]: ranged, + [StatType.dodge]: dodge, + [StatType.speed]: speed, + }; + } + + setStatModifier (statType, newAbsoluteValue) { + this.statModifiers[statType] = newAbsoluteValue - this.stats[statType]; + } + + resetStatModifiers () { + for (const m in this.statModifiers) { + this.statModifiers[m] = 0; + } + } +}; diff --git a/resources/js/classes/State.js b/resources/js/classes/State.js new file mode 100644 index 0000000..2384a85 --- /dev/null +++ b/resources/js/classes/State.js @@ -0,0 +1,38 @@ +class State { + /** + * @type {number} + */ + money = 0; + + /** + * @type {Monster[]} + */ + monsters = []; + + /** + * @type {Item[]} + */ + inventory = []; + + /** + * @type {Monster[]} + */ + partyMonsters = []; + + /** + * @type {Monster} + */ + activeMonster = null; + + /** + * @type {Technique} + */ + activeTechnique = null; + + enemy = { + /** + * @type {Monster} + */ + monster: null, + }; +}; diff --git a/resources/js/classes/StatusEffect.js b/resources/js/classes/StatusEffect.js new file mode 100644 index 0000000..ac6ae54 --- /dev/null +++ b/resources/js/classes/StatusEffect.js @@ -0,0 +1,55 @@ +class StatusEffect { + turnsLeft = 0; + onRemove = null; + + /** + * @type {Monster} + */ + issuer = null; + + constructor (slug) { + this.slug = slug; + + 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; + } + } + + /** + * @returns {string[]} + */ + get effects () { + return DB.statusEffects[this.slug].effects; + } + + get category () { + return DB.statusEffects[this.slug].category; + } + + get name () { + return slugToName(this.slug); + } + + get stats () { + const stats = {}; + + const statsChangeKeys = Object.keys(DB.statusEffects[this.slug]).filter((key) => key.startsWith('stat')); + for (const statChangeKey of statsChangeKeys) { + stats[statChangeKey.replace('stat', '')] = DB.statusEffects[this.slug][statChangeKey]; + } + + return stats; + } +} diff --git a/resources/js/classes/Technique.js b/resources/js/classes/Technique.js new file mode 100644 index 0000000..a24e094 --- /dev/null +++ b/resources/js/classes/Technique.js @@ -0,0 +1,77 @@ +class Technique { + #accuracy = 0; + #potency = 0; + #power = 0; + + constructor (slug) { + this.slug = slug; + + this.resetStats(); + } + + get name () { + return slugToName(this.slug); + } + + get types () { + return DB.techniques[this.slug].types; + } + + get range () { + return DB.techniques[this.slug].range; + } + + get animation () { + return DB.techniques[this.slug].animation; + } + + get sfx () { + return DB.techniques[this.slug].sfx; + } + + /** + * @returns {string[]} + */ + 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 stats () { + 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, + }; + } + + resetStats () { + this.accuracy = this.stats.accuracy; + this.potency = this.stats.potency; + this.power = this.stats.power; + } +} |