metaforce/Runtime/World/CDamageVulnerability.cpp

222 lines
8.5 KiB
C++

#include "Runtime/World/CDamageVulnerability.hpp"
namespace urde {
constexpr CDamageVulnerability CDamageVulnerability::sNormalVulnerability(
EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EDeflectType::None);
constexpr CDamageVulnerability CDamageVulnerability::sImmuneVulnerability(
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::None);
constexpr CDamageVulnerability CDamageVulnerability::sReflectVulnerability(
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::One);
constexpr CDamageVulnerability CDamageVulnerability::sPassThroughVulnerability(
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EDeflectType::None);
static constexpr bool is_not_immune(EVulnerability vuln) {
return vuln != EVulnerability::Immune && vuln != EVulnerability::DirectImmune;
}
static constexpr bool is_normal_or_weak(EVulnerability vuln) {
return vuln == EVulnerability::Normal || vuln == EVulnerability::Weak;
}
void CDamageVulnerability::ConstructNew(CInputStream& in, int propCount) {
propCount -= 3;
EVulnerability* vulns = &x0_power;
for (int i = 0; i < std::min(propCount, 15); ++i)
vulns[i] = EVulnerability(in.readUint32Big());
if (propCount < 15) {
for (int i = propCount; i < 15; ++i)
vulns[i] = EVulnerability::Deflect;
}
for (int i = 15; i < propCount; ++i)
in.readUint32Big();
x5c_deflected = EDeflectType(in.readUint32Big());
EVulnerability* vulns2 = &x3c_chargedPower;
in.readUint32Big();
for (int i = 0; i < 4; ++i)
vulns2[i] = EVulnerability(in.readUint32Big());
x60_chargedDeflected = EDeflectType(in.readUint32Big());
EVulnerability* vulns3 = &x4c_superMissile;
in.readUint32Big();
for (int i = 0; i < 4; ++i)
vulns3[i] = EVulnerability(in.readUint32Big());
x64_comboDeflected = EDeflectType(in.readUint32Big());
}
CDamageVulnerability::CDamageVulnerability(CInputStream& in) {
u32 propCount = in.readUint32Big();
if (propCount == 11) {
EVulnerability* vulns = &x0_power;
for (int i = 0; i < 15; ++i)
vulns[i] = EVulnerability(in.readUint32Big());
if (propCount == 15)
x5c_deflected = EDeflectType::None;
else
x5c_deflected = EDeflectType(in.readUint32Big());
x3c_chargedPower = x0_power;
x4c_superMissile = x0_power;
x40_chargedIce = x4_ice;
x50_iceSpreader = x4_ice;
x44_chargedWave = x8_wave;
x54_wavebuster = x8_wave;
x48_chargedPlasma = xc_plasma;
x58_flamethrower = xc_plasma;
} else
ConstructNew(in, propCount);
}
EDeflectType CDamageVulnerability::GetDeflectionType(const CWeaponMode& mode) const {
if (mode.IsCharged())
return x60_chargedDeflected;
if (mode.IsComboed())
return x64_comboDeflected;
return x5c_deflected;
}
bool CDamageVulnerability::WeaponHurts(const CWeaponMode& mode, bool ignoreDirect) const {
if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon)
return false;
if (mode.IsInstantKill())
return true;
EVulnerability normalVuln = (&x0_power)[u32(mode.GetType())];
bool normalHurts = true;
if (ignoreDirect) {
normalHurts = is_normal_or_weak(normalVuln);
} else {
if (!is_normal_or_weak(normalVuln) &&
(normalVuln != EVulnerability::DirectWeak && normalVuln != EVulnerability::DirectNormal))
normalHurts = false;
}
bool chargedHurts = true;
bool comboedHurts = true;
if (mode.GetType() < EWeaponType::Bomb) {
EVulnerability chargedVuln = (&x3c_chargedPower)[u32(mode.GetType())];
EVulnerability comboedVuln = (&x4c_superMissile)[u32(mode.GetType())];
if (ignoreDirect) {
chargedHurts = is_normal_or_weak(chargedVuln);
comboedHurts = is_normal_or_weak(comboedVuln);
} else {
if (!is_normal_or_weak(chargedVuln) &&
(chargedVuln != EVulnerability::DirectWeak && chargedVuln != EVulnerability::DirectNormal))
chargedHurts = false;
if (!is_normal_or_weak(comboedVuln) &&
(comboedVuln != EVulnerability::DirectWeak && comboedVuln != EVulnerability::DirectNormal))
comboedHurts = false;
}
}
if (normalHurts && !mode.IsCharged() && !mode.IsComboed())
return true;
if (chargedHurts && mode.IsCharged())
return true;
return comboedHurts && mode.IsComboed();
}
bool CDamageVulnerability::WeaponHits(const CWeaponMode& mode, bool checkDirect) const {
if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon)
return false;
if (mode.IsInstantKill())
return true;
bool normalVuln;
if (!checkDirect)
normalVuln = (&x0_power)[u32(mode.GetType())] != EVulnerability::Immune;
else
normalVuln = is_not_immune((&x0_power)[u32(mode.GetType())]);
bool chargedVuln = true;
bool comboedVuln = true;
if (mode.GetType() < EWeaponType::Bomb) {
if (!checkDirect) {
chargedVuln = (&x3c_chargedPower)[u32(mode.GetType())] != EVulnerability::Immune;
comboedVuln = (&x4c_superMissile)[u32(mode.GetType())] != EVulnerability::Immune;
} else {
chargedVuln = is_not_immune((&x3c_chargedPower)[u32(mode.GetType())]);
comboedVuln = is_not_immune((&x4c_superMissile)[u32(mode.GetType())]);
}
}
if (normalVuln && !mode.IsCharged() && !mode.IsComboed())
return true;
if (chargedVuln && mode.IsCharged())
return true;
return comboedVuln && mode.IsComboed();
}
EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const {
if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon) {
return EVulnerability::Deflect;
}
if (mode.IsInstantKill()) {
return EVulnerability::Normal;
}
EVulnerability vuln = (&x0_power)[u32(mode.GetType())];
if (mode.IsCharged()) {
if (mode.GetType() < EWeaponType::Bomb) {
vuln = (&x3c_chargedPower)[u32(mode.GetType())];
} else {
vuln = EVulnerability::Normal;
}
}
if (mode.IsComboed()) {
if (mode.GetType() < EWeaponType::Bomb) {
vuln = (&x3c_chargedPower)[u32(mode.GetType())];
} else {
vuln = EVulnerability::Normal;
}
}
if (ignoreDirect) {
return vuln;
}
if (vuln == EVulnerability::DirectWeak) {
return EVulnerability::Weak;
}
if (vuln == EVulnerability::DirectNormal) {
return EVulnerability::Normal;
}
if (vuln == EVulnerability::DirectImmune) {
return EVulnerability::Immune;
}
return vuln;
}
} // namespace urde