#include "Runtime/World/CDamageVulnerability.hpp" namespace metaforce { const 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); const 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); const 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); const 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_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) { return vuln == EVulnerability::Weak || vuln == EVulnerability::Normal; } static constexpr bool is_not_deflect(EVulnerability vuln) { return vuln != EVulnerability::Deflect; } void CDamageVulnerability::ConstructNew(CInputStream& in, int propCount) { propCount -= 3; for (int i = 0; i < std::min(propCount, 15); ++i) { x0_normal[i] = EVulnerability(in.ReadLong()); } if (propCount < 15) { for (int i = propCount; i < 15; ++i) { x0_normal[i] = EVulnerability::Deflect; } } for (int i = 15; i < propCount; ++i) { in.ReadLong(); } x5c_deflected = EDeflectType(in.ReadLong()); in.ReadLong(); for (int i = 0; i < 4; ++i) { x3c_charged[i] = EVulnerability(in.ReadLong()); } x60_chargedDeflected = EDeflectType(in.ReadLong()); in.ReadLong(); for (int i = 0; i < 4; ++i) { x4c_combo[i] = EVulnerability(in.ReadLong()); } x64_comboDeflected = EDeflectType(in.ReadLong()); } CDamageVulnerability::CDamageVulnerability(CInputStream& in) { u32 propCount = in.ReadLong(); if (propCount == 11) { for (int i = 0; i < 15; ++i) { x0_normal[i] = EVulnerability(in.ReadLong()); } x5c_deflected = EDeflectType(in.ReadLong()); 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 { 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; } bool normalHurts = true; 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) { normalHurts = false; } } else if (!is_normal_or_weak(vuln)) { normalHurts = false; } bool chargedHurts = true; if (mode.GetType() < EWeaponType::Bomb) { 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) { chargedHurts = false; } } 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) { comboedHurts = false; } } else if (!is_normal_or_weak(comboedVuln)) { comboedHurts = false; } } if (((!normalHurts || mode.IsCharged()) || mode.IsComboed()) && (!chargedHurts || !mode.IsCharged())) { if (!comboedHurts) { return false; } if (!mode.IsComboed()) { return false; } } return true; } 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; } const auto normalVuln = x0_normal[u32(mode.GetType())]; bool normalHits = true; if (!checkDirect) { normalHits = is_not_deflect(normalVuln); } else if (is_deflect_direct(normalVuln)) { normalHits = false; } bool chargedHits = true; if (mode.GetType() < EWeaponType::Bomb) { const auto chargedVuln = x3c_charged[u32(mode.GetType())]; if (!checkDirect) { chargedHits = is_not_deflect(chargedVuln); } else if (is_deflect_direct(normalVuln)) { chargedHits = false; } else { chargedHits = true; } } 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; } } if (normalHits && !mode.IsCharged() && !mode.IsComboed()) { return true; } if (!chargedHits || !mode.IsCharged()) { if (comboedHits) { return false; } if (!mode.IsComboed()) { return false; } } return true; } EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const { const auto type = mode.GetType(); if (type <= EWeaponType::None || type >= EWeaponType::Max) { return EVulnerability::Deflect; } if (mode.IsInstantKill()) { return EVulnerability::Normal; } auto vuln = x0_normal[u32(type)]; if (mode.IsCharged()) { if (type < EWeaponType::Bomb) { vuln = x3c_charged[u32(type)]; } else { vuln = EVulnerability::Normal; } } if (mode.IsComboed()) { if (type < EWeaponType::Bomb) { vuln = x4c_combo[u32(type)]; } 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 metaforce