264 lines
5.8 KiB
JavaScript
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));
|