packages/calc/src/hyperStats.js

const {ADDED_STATS, PURE_STATS} = require('./constants.js');
/**
 * Internal class for calculating hyper stat modifiers
 * @class
 * @ignore
 */
class Util {
  /**
   * Calculates hyper pure stat modifier
   * @static
   * @param {HyperStats} scope
   * @param {string} stat
   * @return {number}
   */
  static calcPureStat(scope, stat) {
    return scope.hyper[stat] * 30;
  }
  /**
   * Calculates the Max HP hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcMaxHP(scope) {
    return scope.base.maxHP * scope.hyper.maxHP * 0.02;
  }
  /**
   * Calculates the Max MP hyper stat modifier
   * @static
   * @param {HyperStats} scope 
   * @return {number}
   */
  static calcMaxMP(scope) {
    return scope.base.maxMP * scope.hyper.maxMP * 0.02;
  }
  /**
   * Calculates the demon force hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcMaxDF(scope) {
    return scope.hyper.maxDF * 10;
  }
  /**
   * Calculates the time force hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcMaxTF(scope) {
    return scope.hyper.maxTF * 10;
  }
  /**
   * Calculates the hyper critical rate % stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcCrit(scope) {
    if (scope.hyper.crit < 6) return scope.hyper.crit;
    return 5 + (scope.hyper.crit - 5) * 2;
  }
  /**
   * Calculates the critical damage % hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcCritDmg(scope) {
    return scope.hyper.critDmg;
  }
  /**
   * Calculates the ignore defense % hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcIgnoreDef(scope) {
    return scope.hyper.ignoreDef * 3;
  }
  /**
   * Calculates the boss dmg % hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcBossDmg(scope) {
    if (scope.hyper.bossDmg < 6) return scope.hyper.bossDmg * 3;
    return 15 + ((scope.hyper.bossDmg - 5) * 4);
  }
  /**
   * Calculates the dmg % hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcDmg(scope) {
    return scope.hyper.dmg * 3;
  }
  /**
   * Calculates the status resistance hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcStatusResist(scope) {
    if (scope.hyper.statusResist < 6) return scope.hyper.statusResist;
    return 5 + ((scope.hyper.statusResist - 5) * 2);
  }
  /**
   * Calculates the stance hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcStance(scope) {
    return scope.hyper.stance * 2;
  }
  /**
   * Calculates the weapon ATT hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcWeaponAtt(scope) {
    return scope.hyper.weaponAtt * 3;
  }
  /**
   * Calculates the magic ATT hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcMagicAtt(scope) {
    return scope.hyper.magicAtt * 3;
  }
  /**
   * Calculates the bonus EXP % hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcBonusExp(scope) {
    if (scope.hyper.bonusExp < 11) return 0.5 * scope.hyper.bonusExp;
    return scope.hyper.bonusExp - 5;
  }
  /**
   * Calculates the arcane force hyper stat modifier
   * @static
   * @param {HyperStats} scope
   * @return {number}
   */
  static calcArcaneForce(scope) {
    if (scope.hyper.arcaneForce < 11) return scope.hyper.arcaneForce * 5;
    return 50 + (scope.hyper.arcaneForce - 10) * 10;
  }
}
/**
 * Provides hyper stat calculations for MapleStory characters
 * @class
 * @memberof module:@perion/calc
 */
class HyperStats {
  /**
   * Use HyperStats.from()
   * @param {Object} playerStats An object containing the player stats
   */
  constructor({base, hyper}) {
    const cloned = Object.assign({}, {base, hyper});
    this.base = cloned.base;
    this.hyper = cloned.hyper;
    this.modified = {};
  }
  /**
   * Creates a HyperStats object
   * @param {Object} playerStats An object containing the player stats
   * @return {HyperStats} A reference to the current HyperStats object
   */
  static from({base, hyper}) {
    return new HyperStats({base, hyper});
  }
  /**
   * Applies the hyper pure stat modifiers
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyPureStats() {
    for (const name of PURE_STATS) {
      const addition = Util.calcPureStat(this, name);
      this.modified[name] = this.base[name] + addition;
    }
    return this;
  };
  /**
   * Applies the Max HP hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyMaxHP() {
    const addition = Util.calcMaxHP(this);
    this.modified.maxHP = this.base.maxHP + addition;
    return this;
  };
  /**
   * Applies the Max MP hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyMaxMP() {
    const addition = Util.calcMaxMP(this);
    this.modified.maxMP = this.base.maxMP + addition;
    return this;
  };
  /**
   * Applies the demon force hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyMaxDF() {
    const addition = Util.calcMaxDF(this);
    this.modified.maxDF = this.base.maxDF + addition;
    return this;
  };
  /**
   * Applies the time force hyper stat modifiers
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyMaxTF() {
    const addition = Util.calcMaxTF(this);
    this.modified.maxTF = this.base.maxTF + addition;
    return this;
  };
  /**
   * Applies the hyper critical rate % hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyCrit() {
    const addition = Util.calcCrit(this);
    this.modified.crit = this.base.crit + addition;
    return this;
  };
  /**
   * Applies the critical damage % hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyCritDmg() {
    const addition = Util.calcCritDmg(this);
    this.modified.critDmg = this.base.critDmg + addition;
    return this;
  };
  /**
   * Applies the ignore defense % hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyIgnoreDef() {
    const addition = Util.calcIgnoreDef(this);
    this.modified.ignoreDef = this.base.ignoreDef + addition;
    return this;
  };
  /**
   * Applies the boss dmg % hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyBossDmg() {
    this.modified.bossDmg = this.base.bossDmg + Util.calcBossDmg(this);
    return this;
  };
  /**
   * Applies the dmg % hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyDmg() {
    this.modified.dmg = this.base.dmg + Util.calcDmg(this);
    return this;
  };
  /**
   * Applies the status resistance hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyStatusResist() {
    const addition = Util.calcStatusResist(this);
    this.modified.statusResist = this.base.statusResist + addition;
    return this;
  };
  /**
   * Applies the stance hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyStance() {
    const addition = Util.calcStance(this);
    this.modified.stance = this.base.stance + addition;
    return this;
  };
  /**
   * Applies the weapon ATT hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyWeaponAtt() {
    const addition = Util.calcWeaponAtt(this);
    this.modified.weaponAtt = this.base.weaponAtt + addition;
    return this;
  };
  /**
   * Applies the magic ATT hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyMagicAtt() {
    const addition = Util.calcMagicAtt(this);
    this.modified.magicAtt = this.base.magicAtt + addition;
    return this;
  };
  /**
   * Applies the bonus EXP % hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyBonusExp() {
    const addition = Util.calcBonusExp(this);
    this.modified.bonusExp = this.base.bonusExp + addition;
    return this;
  };
  /**
   * Applies the arcane force hyper stat modifier
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyArcaneForce() {
    const addition = Util.calcArcaneForce(this);
    this.modified.arcaneForce = this.base.arcaneForce + addition;
    return this;
  };
  /**
   * Applies all the hyper stat modifiers
   * @return {HyperStats} A reference to the current HyperStats object
   */
  applyAll() {
    this.applyArcaneForce();
    this.applyBonusExp();
    this.applyCrit();
    this.applyCritDmg();
    this.applyMaxDF();
    this.applyMaxTF();
    this.applyDmg();
    this.applyIgnoreDef();
    this.applyMaxHP();
    this.applyMaxMP();
    this.applyPureStats();
    this.applyStance();
    this.applyStatusResist();
    this.applyWeaponAtt();
    this.applyMagicAtt();
    return this;
  };
  /**
   * Gets the modified stat values
   * @return {Object} The modified player stats Object
   */
   get() {
    return this.modified;
  }
}
module.exports = {HyperStats, Util};