metaforce/Runtime/World/CDamageVulnerability.cpp

285 lines
9.2 KiB
C++
Raw Normal View History

#include "Runtime/World/CDamageVulnerability.hpp"
2021-04-10 08:42:06 +00:00
namespace metaforce {
2020-05-27 17:02:20 +00:00
const CDamageVulnerability CDamageVulnerability::sNormalVulnerability(
2017-03-01 03:42:06 +00:00
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);
2017-03-01 03:42:06 +00:00
2020-05-27 17:02:20 +00:00
const CDamageVulnerability CDamageVulnerability::sImmuneVulnerability(
2018-02-12 05:30:21 +00:00
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);
2020-05-27 17:02:20 +00:00
const CDamageVulnerability CDamageVulnerability::sReflectVulnerability(
2018-02-12 05:30:21 +00:00
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);
2017-03-01 03:42:06 +00:00
2020-05-27 17:02:20 +00:00
const CDamageVulnerability CDamageVulnerability::sPassThroughVulnerability(
2017-03-01 03:42:06 +00:00
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);
2021-05-09 03:14:38 +00:00
static constexpr bool is_deflect_direct(EVulnerability vuln) {
return vuln == EVulnerability::Deflect || vuln == EVulnerability::DirectWeak ||
vuln == EVulnerability::DirectNormal || vuln == EVulnerability::DirectImmune;
}
static constexpr bool is_normal_or_weak(EVulnerability vuln) {
2021-05-09 03:14:38 +00:00
return vuln == EVulnerability::Weak || vuln == EVulnerability::Normal;
}
static constexpr bool is_not_deflect(EVulnerability vuln) {
return vuln != EVulnerability::Deflect;
2018-11-19 01:19:44 +00:00
}
2018-12-08 05:30:43 +00:00
void CDamageVulnerability::ConstructNew(CInputStream& in, int propCount) {
propCount -= 3;
2021-05-09 03:14:38 +00:00
for (int i = 0; i < std::min(propCount, 15); ++i) {
x0_normal[i] = EVulnerability(in.readUint32Big());
}
2018-12-08 05:30:43 +00:00
if (propCount < 15) {
2021-05-09 03:14:38 +00:00
for (int i = propCount; i < 15; ++i) {
x0_normal[i] = EVulnerability::Deflect;
}
2018-12-08 05:30:43 +00:00
}
2021-05-09 03:14:38 +00:00
for (int i = 15; i < propCount; ++i) {
in.readUint32Big();
2021-05-09 03:14:38 +00:00
}
x5c_deflected = EDeflectType(in.readUint32Big());
2018-12-08 05:30:43 +00:00
in.readUint32Big();
2021-05-09 03:14:38 +00:00
for (int i = 0; i < 4; ++i) {
x3c_charged[i] = EVulnerability(in.readUint32Big());
}
2018-12-08 05:30:43 +00:00
x60_chargedDeflected = EDeflectType(in.readUint32Big());
2018-12-08 05:30:43 +00:00
in.readUint32Big();
2021-05-09 03:14:38 +00:00
for (int i = 0; i < 4; ++i) {
x4c_combo[i] = EVulnerability(in.readUint32Big());
}
x64_comboDeflected = EDeflectType(in.readUint32Big());
}
2018-12-08 05:30:43 +00:00
CDamageVulnerability::CDamageVulnerability(CInputStream& in) {
u32 propCount = in.readUint32Big();
if (propCount == 11) {
2021-05-09 03:14:38 +00:00
for (int i = 0; i < 15; ++i) {
x0_normal[i] = EVulnerability(in.readUint32Big());
}
2018-12-08 05:30:43 +00:00
2021-05-09 03:14:38 +00:00
if (propCount == 15) {
x5c_deflected = EDeflectType::None;
2021-05-09 03:14:38 +00:00
} else {
x5c_deflected = EDeflectType(in.readUint32Big());
2021-05-09 03:14:38 +00:00
}
2018-12-08 05:30:43 +00:00
2021-05-09 03:14:38 +00:00
x3c_charged[0] = x0_normal[0];
x4c_combo[0] = x0_normal[0];
x3c_charged[1] = x0_normal[1];
x4c_combo[1] = x0_normal[1];
x3c_charged[2] = x0_normal[2];
x4c_combo[2] = x0_normal[2];
x3c_charged[3] = x0_normal[3];
x4c_combo[3] = x0_normal[3];
} else {
2018-12-08 05:30:43 +00:00
ConstructNew(in, propCount);
2021-05-09 03:14:38 +00:00
}
}
EDeflectType CDamageVulnerability::GetDeflectionType(const CWeaponMode& mode) const {
2021-05-09 03:14:38 +00:00
if (mode.IsCharged()) {
2018-12-08 05:30:43 +00:00
return x60_chargedDeflected;
2021-05-09 03:14:38 +00:00
}
if (mode.IsComboed()) {
2018-12-08 05:30:43 +00:00
return x64_comboDeflected;
2021-05-09 03:14:38 +00:00
}
2018-12-08 05:30:43 +00:00
return x5c_deflected;
2017-03-01 03:42:06 +00:00
}
2018-12-08 05:30:43 +00:00
bool CDamageVulnerability::WeaponHurts(const CWeaponMode& mode, bool ignoreDirect) const {
2021-05-09 03:14:38 +00:00
if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon) {
2018-12-08 05:30:43 +00:00
return false;
2021-05-09 03:14:38 +00:00
}
if (mode.IsInstantKill()) {
2018-12-08 05:30:43 +00:00
return true;
2021-05-09 03:14:38 +00:00
}
2018-12-08 05:30:43 +00:00
bool normalHurts = true;
2021-05-09 03:14:38 +00:00
const auto vuln = x0_normal[u32(mode.GetType())];
if (!ignoreDirect) {
bool directHurts = true;
if (!is_normal_or_weak(vuln) && vuln != EVulnerability::DirectWeak) {
directHurts = false;
}
if (!directHurts && vuln != EVulnerability::DirectNormal) {
2018-12-08 05:30:43 +00:00
normalHurts = false;
2021-05-09 03:14:38 +00:00
}
} else if (!is_normal_or_weak(vuln)) {
normalHurts = false;
2018-12-08 05:30:43 +00:00
}
bool chargedHurts = true;
if (mode.GetType() < EWeaponType::Bomb) {
2021-05-09 03:14:38 +00:00
const auto chargedVuln = x3c_charged[u32(mode.GetType())];
if (!ignoreDirect) {
bool directHurts = true;
if (!is_normal_or_weak(chargedVuln) && chargedVuln != EVulnerability::DirectWeak) {
directHurts = false;
}
if (!directHurts && chargedVuln != EVulnerability::DirectNormal) {
2018-12-08 05:30:43 +00:00
chargedHurts = false;
2021-05-09 03:14:38 +00:00
}
} else if (!is_normal_or_weak(chargedVuln)) {
chargedHurts = false;
}
}
bool comboedHurts = true;
if (mode.GetType() < EWeaponType::Bomb) {
const auto comboedVuln = x4c_combo[u32(mode.GetType())];
if (!ignoreDirect) {
bool directHurts = true;
if (!is_normal_or_weak(comboedVuln) && comboedVuln != EVulnerability::DirectWeak) {
directHurts = false;
}
if (!directHurts && comboedVuln != EVulnerability::DirectNormal) {
2018-12-08 05:30:43 +00:00
comboedHurts = false;
2021-05-09 03:14:38 +00:00
}
} else if (!is_normal_or_weak(comboedVuln)) {
comboedHurts = false;
}
2018-12-08 05:30:43 +00:00
}
2021-05-09 03:14:38 +00:00
if (((!normalHurts || mode.IsCharged()) || mode.IsComboed()) && (!chargedHurts || !mode.IsCharged())) {
if (!comboedHurts) {
return false;
}
if (!mode.IsComboed()) {
return false;
}
}
return true;
}
2018-12-08 05:30:43 +00:00
bool CDamageVulnerability::WeaponHits(const CWeaponMode& mode, bool checkDirect) const {
2020-05-17 16:25:04 +00:00
if (mode.GetType() <= EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon) {
return false;
2020-05-17 16:25:04 +00:00
}
if (mode.IsInstantKill()) {
2018-12-08 05:30:43 +00:00
return true;
2020-05-17 16:25:04 +00:00
}
2021-05-09 03:14:38 +00:00
const auto normalVuln = x0_normal[u32(mode.GetType())];
bool normalHits = true;
2020-05-17 16:25:04 +00:00
if (!checkDirect) {
2021-05-09 03:14:38 +00:00
normalHits = is_not_deflect(normalVuln);
} else if (is_deflect_direct(normalVuln)) {
normalHits = false;
2020-05-17 16:25:04 +00:00
}
2018-12-08 05:30:43 +00:00
2021-05-09 03:14:38 +00:00
bool chargedHits = true;
2018-12-08 05:30:43 +00:00
if (mode.GetType() < EWeaponType::Bomb) {
2021-05-09 03:14:38 +00:00
const auto chargedVuln = x3c_charged[u32(mode.GetType())];
2018-12-08 05:30:43 +00:00
if (!checkDirect) {
2021-05-09 03:14:38 +00:00
chargedHits = is_not_deflect(chargedVuln);
} else if (is_deflect_direct(normalVuln)) {
chargedHits = false;
2018-12-08 05:30:43 +00:00
} else {
2021-05-09 03:14:38 +00:00
chargedHits = true;
2018-12-08 05:30:43 +00:00
}
}
2021-05-09 03:14:38 +00:00
bool comboedHits = true;
if (mode.GetType() < EWeaponType::Bomb) {
const auto chargedVuln = x3c_charged[u32(mode.GetType())];
if (!checkDirect) {
comboedHits = is_not_deflect(chargedVuln);
} else if (is_deflect_direct(normalVuln)) {
comboedHits = false;
} else {
comboedHits = true;
}
2020-05-17 16:25:04 +00:00
}
2021-05-09 03:14:38 +00:00
if (normalHits && !mode.IsCharged() && !mode.IsComboed()) {
2018-12-08 05:30:43 +00:00
return true;
2020-05-17 16:25:04 +00:00
}
2021-05-09 03:14:38 +00:00
if (!chargedHits || !mode.IsCharged()) {
if (comboedHits) {
return false;
}
if (!mode.IsComboed()) {
return false;
}
}
return true;
}
2018-12-08 05:30:43 +00:00
EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const {
2021-05-09 03:14:38 +00:00
const auto type = mode.GetType();
if (type <= EWeaponType::None || type >= EWeaponType::Max) {
2018-12-08 05:30:43 +00:00
return EVulnerability::Deflect;
}
if (mode.IsInstantKill()) {
2018-12-08 05:30:43 +00:00
return EVulnerability::Normal;
}
2021-05-09 03:14:38 +00:00
auto vuln = x0_normal[u32(type)];
2018-12-08 05:30:43 +00:00
if (mode.IsCharged()) {
2021-05-09 03:14:38 +00:00
if (type < EWeaponType::Bomb) {
vuln = x3c_charged[u32(type)];
} else {
2018-12-08 05:30:43 +00:00
vuln = EVulnerability::Normal;
}
2018-12-08 05:30:43 +00:00
}
2018-12-08 05:30:43 +00:00
if (mode.IsComboed()) {
2021-05-09 03:14:38 +00:00
if (type < EWeaponType::Bomb) {
vuln = x4c_combo[u32(type)];
} else {
2018-12-08 05:30:43 +00:00
vuln = EVulnerability::Normal;
}
2018-12-08 05:30:43 +00:00
}
if (ignoreDirect) {
return vuln;
}
2018-12-08 05:30:43 +00:00
if (vuln == EVulnerability::DirectWeak) {
2018-12-08 05:30:43 +00:00
return EVulnerability::Weak;
}
2021-05-09 03:14:38 +00:00
if (vuln == EVulnerability::DirectNormal) {
2018-12-08 05:30:43 +00:00
return EVulnerability::Normal;
}
2021-05-09 03:14:38 +00:00
if (vuln == EVulnerability::DirectImmune) {
2018-12-08 05:30:43 +00:00
return EVulnerability::Immune;
}
2018-12-08 05:30:43 +00:00
return vuln;
}
2021-04-10 08:42:06 +00:00
} // namespace metaforce