#include "World/CDamageVulnerability.hpp" namespace urde { static inline bool is_normal_or_weak(EVulnerability vuln) { return (vuln == EVulnerability::DoubleDamage || vuln == EVulnerability::Normal); } static inline bool is_not_immune(EVulnerability vuln) { return vuln != EVulnerability::Immune && vuln != EVulnerability::DirectImmune; } void CDamageVulnerability::ConstructNew(CInputStream& in, int propCount) { EVulnerability* vulns = &x0_power; for (int i = 0; i < std::min(propCount - 3, 15); ++i) vulns[i] = EVulnerability(in.readUint32Big()); if (propCount < 15) { for (int i = propCount; i < 15; ++i) vulns[i] = EVulnerability::Reflect; } for (int i = 15; i < propCount; ++i) in.readUint32Big(); x5c_ = in.readUint32Big(); EVulnerability* vulns2 = &x3c_chargedPower; in.readUint32Big(); for (int i = 0; i < 4; ++i) vulns2[i] = EVulnerability(in.readUint32Big()); x60_ = in.readUint32Big(); EVulnerability* vulns3 = &x4c_superMissile; in.readUint32Big(); for (int i = 0; i < 4; ++i) vulns3[i] = EVulnerability(in.readUint32Big()); x64_ = 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_ = 0; else x5c_ = 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); } u32 CDamageVulnerability::sub80102490(const CWeaponMode& mode) const { if (mode.IsCharged()) return x60_; if (mode.IsComboed()) return x64_; return x5c_; } bool CDamageVulnerability::WeaponHurts(const CWeaponMode& mode, bool ignoreDirect) const { if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::Unused2) return false; if (mode.IsInstantKill()) return true; EVulnerability normalVuln = (&x0_power)[u32(mode.GetType())]; bool normalHurts = true; if (ignoreDirect) normalHurts = is_not_immune(normalVuln); else { if (is_not_immune(normalVuln) && (normalVuln != EVulnerability::DirectDouble && 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_not_immune(chargedVuln); comboedHurts = is_not_immune(comboedVuln); } else { if (is_not_immune(chargedVuln) && (chargedVuln != EVulnerability::DirectDouble && chargedVuln != EVulnerability::DirectNormal)) chargedHurts = false; if (is_not_immune(comboedVuln) && (comboedVuln != EVulnerability::DirectDouble && comboedVuln != EVulnerability::DirectNormal)) comboedHurts = false; } } if (normalHurts && !mode.IsCharged() && !mode.IsComboed()) return true; if (chargedHurts && mode.IsCharged()) return true; if (comboedHurts && mode.IsComboed()) return true; return false; } bool CDamageVulnerability::WeaponHits(const CWeaponMode& mode, bool checkDirect) const { if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::Unused2) 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; if (comboedVuln && mode.IsComboed()) return true; return false; } EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const { if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::Unused2) return EVulnerability::Reflect; 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::DirectDouble) return EVulnerability::DoubleDamage; else if (vuln == EVulnerability::DirectNormal) return EVulnerability::Normal; else if (vuln == EVulnerability::DirectImmune) return EVulnerability::Immune; return vuln; } }