mh3-data
Version:
Monster Hunter Tri data for monsters, quests, and weapons
108 lines • 4.97 kB
JavaScript
import { Weapons } from '../../model';
import { WeaponClass } from '../../model/weapons';
import { assertSwitchAxeWeaponMultipliers } from './assertions';
import { applyDefenseMultiplier, calculateElementalDamage, getRawMultiplier, getSharpnessRawMultiplier, getWeaponClassMultiplier, validateWeaponSharpness } from './damage-util';
const SWITCH_AXE_PHIAL_MULTIPLIER = 1.25;
/**
* @returns Attack properties for a {@link SwitchAxeTypes.SwitchAxeAttack}
*/
function getSwitchAxeAttack(switchAxeMode, attackName) {
const switchAxeAttacks = Weapons.getWeaponDamageProperties(WeaponClass.SWITCH_AXE).attackModes.find(atkGroup => atkGroup.name === switchAxeMode);
if (!switchAxeAttacks) {
throw new Error(`'${switchAxeMode}' is not a valid switch axe mode`);
}
const result = switchAxeAttacks.attacks.find(atk => atk.name === attackName);
if (!result) {
throw new Error(`'${attackName}' is not a valid Switch Axe attack for '${switchAxeMode}' mode`);
}
return result;
}
/**
* Determines special var multipliers for {@link SwitchAxeTypes.SwitchAxe}
*
* Power phials receive a 1.25 bonus to RAW damage
* Element phials receive a 1.25 bonus to ELEMENTAL damage
*/
function getSwitchAxeSpecialVarMultiplier(switchAxe, switchAxeMode) {
const noMulitiplier = 1;
if (switchAxeMode === 'axe')
return {
rawSpecialVarMultiplier: noMulitiplier,
elementSpecialVarMultiplier: noMulitiplier
};
const rawSpecialVarMultiplier = switchAxe.phial === 'power' ? SWITCH_AXE_PHIAL_MULTIPLIER : noMulitiplier;
const elementSpecialVarMultiplier = switchAxe.phial === 'element' ? SWITCH_AXE_PHIAL_MULTIPLIER : noMulitiplier;
return { rawSpecialVarMultiplier, elementSpecialVarMultiplier };
}
/**
* Special-case function for Dragon Phial switch axes
* @returns
*/
function dragonPhialElementArgs(switchAxe, switchAxeMode, elementArgs) {
if (!elementArgs || switchAxe.phial !== 'dragon' || switchAxeMode === 'axe')
return elementArgs;
// Ensures the phial type is 'dragon'
if (switchAxeMode === 'sword') {
// Dragon phial draws from secondaryAttack value as if it were awakened
return {
...elementArgs,
awaken: true
};
}
}
function validateSwitchAxe(weapon) {
if (weapon.type !== WeaponClass.SWITCH_AXE ||
weapon.phial === undefined) {
throw new Error(`'${weapon.name}' is not a '${WeaponClass.SWITCH_AXE}'`);
}
}
/**
* Calculates damage for a {@link SwitchAxeTypes.SwitchAxe}.
*/
export function calculateSwitchAxeDamage(weaponArgs, monsterMultipliers, damageBuffArgs) {
const { weaponId, attackName, sharpness } = weaponArgs;
const { switchAxeMode } = weaponArgs.weaponMultipliers;
const { hitzoneValues, statMultipliers: levelMultipliers } = monsterMultipliers;
const { rawArgs, elementArgs, weaponClassArgs } = damageBuffArgs;
const switchAxe = Weapons.getWeapon(Weapons.WeaponClass.SWITCH_AXE, weaponId);
validateSwitchAxe(switchAxe);
validateWeaponSharpness(switchAxe, sharpness);
assertSwitchAxeWeaponMultipliers(switchAxeMode);
const { classModifier } = Weapons.getWeaponDamageProperties(WeaponClass.SWITCH_AXE);
const sharpnessMultiplier = getSharpnessRawMultiplier(sharpness);
const attack = getSwitchAxeAttack(switchAxeMode, attackName);
const { rawSpecialVarMultiplier, elementSpecialVarMultiplier } = getSwitchAxeSpecialVarMultiplier(switchAxe, switchAxeMode);
const rawMultiplier = getRawMultiplier(rawArgs);
const attackBuffMultiplier = getWeaponClassMultiplier(weaponClassArgs);
const attackWithBuffs = switchAxe.attack + attackBuffMultiplier * classModifier;
return attack.hits.map(hit => {
const isCut = Weapons.isCutHit(hit);
const hitzoneMultiplier = isCut ? hitzoneValues.cut : hitzoneValues.impact;
const rawDamage = (attackWithBuffs *
hit.power *
rawMultiplier *
sharpnessMultiplier *
hitzoneMultiplier *
rawSpecialVarMultiplier) /
classModifier;
const elementalDamage = calculateElementalDamage({
weapon: switchAxe,
sharpness,
hitzoneValues,
elementArgs: dragonPhialElementArgs(switchAxe, switchAxeMode, elementArgs)
}) * elementSpecialVarMultiplier;
// Decimal is dropped
const totalDamage = applyDefenseMultiplier(rawDamage + elementalDamage, levelMultipliers.defense);
// KO is always rounded down
const koDamage = !isCut
? Math.floor(hit.ko * sharpnessMultiplier)
: undefined;
return {
rawDamage: applyDefenseMultiplier(rawDamage, levelMultipliers.defense),
elementalDamage: applyDefenseMultiplier(elementalDamage, levelMultipliers.defense),
totalDamage,
koDamage
};
});
}
//# sourceMappingURL=switch-axe-damage.js.map