7th-saga/web/static/calc.js
2021-03-16 13:16:28 -07:00

264 lines
5.8 KiB
JavaScript

// https://gamefaqs.gamespot.com/snes/563501-the-7th-saga/faqs/54038
(function(exports) {
exports.physicalAttack = (
attackerPowerInnate,
attackerPowerWeapon,
targetGuardInnate,
targetGuardArmor,
targetGuardAccessory,
options = {},
) => {
let attackPower = attackerPowerInnate;
if (options.attackerDefending) {
attackPower *= 1.5;
}
if (options.attackerPowerUp) {
attackPower *= 2;
}
let weaponPower = attackerPowerWeapon;
if (options.attackerDefending) {
weaponPower *= 1.5;
}
let guardPower = targetGuardInnate;
if (options.targetGuardDown) {
guardPower /= 2;
}
const totalAttackPower = attackPower + weaponPower;
const totalGuardPower = guardPower + targetGuardArmor + targetGuardAccessory;
let averageDamage = totalAttackPower - (totalGuardPower / 2);
if (options.targetGuardUp) {
averageDamage /= 2;
}
if (options.targetDefending) {
averageDamage /= 2;
}
let minDamage = averageDamage * 0.75;
let maxDamage = averageDamage * 1.25;
const absoluteMin = 1;
return {
normal: {
avg: Math.max(absoluteMin, averageDamage),
min: Math.max(absoluteMin, minDamage),
max: Math.max(absoluteMin, maxDamage),
},
critical: {
avg: Math.max(absoluteMin, averageDamage * 2),
min: Math.max(absoluteMin, minDamage * 2),
max: Math.max(absoluteMin, maxDamage * 2),
},
};
};
exports.magicalAttack = (
attackerMagicInnate,
targetMagicInnate,
targetResistanceInnate,
targetResistanceArmor,
targetResistanceAccessory,
spellPower,
options = {},
) => {
let attackerPower = attackerMagicInnate;
let targetPower = targetMagicInnate;
if (options.targetMagicUp) {
targetPower += 40;
}
const targetResistance = 100 - targetResistanceInnate - targetResistanceArmor - targetResistanceAccessory;
const spellBonusAttackPower = attackerPower + (options.attackerMagicUp ? 40 : 0);
const spellBonus = ((spellBonusAttackPower / 2) + spellPower) * (targetResistance / 100);
const averageDamage = attackerPower - targetPower + spellBonus;
return {
avg: Math.max(1, averageDamage),
min: Math.max(1, averageDamage * 0.75),
max: Math.max(1, averageDamage * 1.25),
};
};
exports.hpCatcherAttack = (
attackerMagicInnate,
attackerMaxHP,
attackerCurrentHP,
targetCurrentHP,
options = {},
) => {
let attackerPower = attackerMagicInnate;
if (options.attackerMagicUp) {
attackerPower += 40;
}
const adjust = dmg => Math.min(attackerMaxHP - attackerCurrentHP, Math.min(Math.min(dmg, 50), targetCurrentHP));
const minDamage = attackerPower / 2;
return {
min: adjust(minDamage),
max: adjust(minDamage + 15),
};
};
exports.mpCatcherAttack = (
attackerMagicInnate,
attackerMaxMP,
attackerCurrentMP,
targetCurrentMP,
options = {},
) => {
let attackerPower = attackerMagicInnate;
if (options.attackerMagicUp) {
attackerPower += 40;
}
const adjust = dmg => Math.min(attackerMaxMP - attackerCurrentMP, Math.min(Math.min(dmg, 40), targetCurrentMP));
const minDamage = attackerPower / 2;
return {
min: adjust(minDamage),
max: adjust(minDamage + 15),
};
};
exports.effectSpellHitRate = (
attackerMagicInnate,
targetMagicInnate,
targetResistanceInnate,
targetResistanceArmor,
targetResistanceAccessory,
options = {},
) => {
if (targetResistanceInnate === null) {
// e.g. "Class 1" enemies
return 0;
}
const targetResistance = targetResistanceInnate + targetResistanceArmor + targetResistanceAccessory;
let attackerMagic = attackerMagicInnate;
let targetMagic = targetMagicInnate;
if (options.attackerMagicUp) {
attackerMagic += 40;
}
if (options.targetMagicUp) {
targetMagic += 40;
}
if (options.tas) {
const magicCalc = 256 * (attackerMagic - targetMagic) / attackerMagic;
let magicResult;
if (magicCalc > targetResistance) {
magicResult = 0;
} else {
magicResult = magicCalc;
}
return Math.max(0, 100 - (targetResistance - magicResult));
}
return Math.max(5, 100 - targetResistance);
};
exports.hitRate = (
attackerSpeedInnate,
targetSpeedInnate,
options = {},
) => {
let attackerSpeed = attackerSpeedInnate;
if (options.attackerSpeedUp) {
attackerSpeed += 30;
}
let targetSpeed = targetSpeedInnate;
if (options.targetSpeedUp) {
targetSpeed += 30;
}
if (options.tas) {
const diff = attackerSpeed - targetSpeed;
let hitRate;
if (diff <= -89) {
hitRate = 26;
} else if (diff <= -59) {
hitRate = 77;
} else if (diff <= -29) {
hitRate = 128;
} else if (diff <= -19) {
hitRate = 154;
} else if (diff <= -9) {
hitRate = 181;
} else if (diff <= -4) {
hitRate = 203;
} else if (diff <= 2) {
hitRate = 213;
} else if (diff <= 6) {
hitRate = 218;
} else if (diff <= 11) {
hitRate = 231;
} else if (diff <= 21) {
hitRate = 244;
} else {
hitRate = 251;
}
return (hitRate / 256) * 100;
}
const hitRate = 85 + (0.8 * (attackerSpeed - targetSpeed));
return Math.max(10, Math.min(98, hitRate));
};
exports.runRate = (
attackerSpeedInnate,
targetSpeedInnate,
options = {},
) => {
let attackerSpeed = attackerSpeedInnate;
if (options.attackerSpeedUp) {
attackerSpeed += 30;
}
let targetSpeed = targetSpeedInnate;
if (options.targetSpeedUp) {
targetSpeed += 30;
}
if (options.tas) {
const diff = attackerSpeed - targetSpeed;
if (diff <= -42) {
return 2;
}
if (diff <= -12) {
return 5;
}
if (diff <= -7) {
return 10;
}
if (diff <= 3) {
return 30;
}
if (diff <= 18) {
return 40;
}
if (diff <= 48) {
return 60;
}
return 80;
}
const runRate = 25 + (1.6 * (attackerSpeed - targetSpeed));
return Math.max(10, Math.min(80, runRate));
};
}(typeof(module) !== 'undefined' ? module.exports : window.saga.calc));