metaforce/Runtime/World/CDamageVulnerability.cpp

210 lines
6.2 KiB
C++

#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)
{
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::Reflect;
}
for (int i = 15; i < propCount; ++i)
in.readUint32Big();
x5c_ = EVulnerability(in.readUint32Big());
EVulnerability* vulns2 = &x3c_chargedPower;
in.readUint32Big();
for (int i = 0; i < 4; ++i)
vulns2[i] = EVulnerability(in.readUint32Big());
x60_chargedPhazon = EVulnerability(in.readUint32Big());
EVulnerability* vulns3 = &x4c_superMissile;
in.readUint32Big();
for (int i = 0; i < 4; ++i)
vulns3[i] = EVulnerability(in.readUint32Big());
x64_phazonCombo = EVulnerability(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_ = EVulnerability::DoubleDamage;
else
x5c_ = EVulnerability(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);
}
EVulnerability CDamageVulnerability::GetPhazonVulnerability(const CWeaponMode& mode) const
{
if (mode.IsCharged())
return x60_chargedPhazon;
if (mode.IsComboed())
return x64_phazonCombo;
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;
}
}