#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_not_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::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::Deflect; } else { normalVuln = is_not_deflect_direct((&x0_power)[u32(mode.GetType())]); } bool chargedVuln = true; bool comboedVuln = true; if (mode.GetType() < EWeaponType::Bomb) { const EVulnerability chargedPowerVuln = (&x3c_chargedPower)[u32(mode.GetType())]; const EVulnerability superMissileVuln = (&x4c_superMissile)[u32(mode.GetType())]; if (!checkDirect) { chargedVuln = chargedPowerVuln != EVulnerability::Deflect; comboedVuln = superMissileVuln != EVulnerability::Deflect; } else { chargedVuln = is_not_deflect_direct(chargedPowerVuln); comboedVuln = is_not_deflect_direct(superMissileVuln); } } 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 metaforce