metaforce/Runtime/World/CDamageVulnerability.cpp

276 lines
10 KiB
C++

#include "World/CDamageVulnerability.hpp"
namespace urde
{
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, EVulnerability::DoubleDamage);
const CDamageVulnerability CDamageVulnerability::sImmuneVulnerability(
EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect,
EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect,
EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect,
EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect,
EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect,
EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::DoubleDamage);
/* LOL, thanks retro */
const CDamageVulnerability CDamageVulnerability::sReflectVulnerability(
EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect,
EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect,
EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect,
EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect,
EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect,
EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::Reflect, EVulnerability::DoubleDamage);
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, EVulnerability::DoubleDamage);
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);
}
CDamageVulnerability::CDamageVulnerability(EVulnerability power, EVulnerability ice, EVulnerability wave,
EVulnerability plasma, EVulnerability bomb, EVulnerability powerBomb,
EVulnerability missile, EVulnerability boostBall, EVulnerability phazon,
EVulnerability enemyWp1, EVulnerability enemyWp2, EVulnerability enemyWp3,
EVulnerability enemyWp4, EVulnerability v1, EVulnerability v2,
EVulnerability chargedPower, EVulnerability chargedIce,
EVulnerability chargedWave, EVulnerability chargedPlasma,
EVulnerability superMissile, EVulnerability iceSpreader,
EVulnerability waveBuster, EVulnerability flameThrower, EVulnerability v3)
: x0_power(power)
, x4_ice(ice)
, x8_wave(wave)
, xc_plasma(plasma)
, x10_bomb(bomb)
, x14_powerbomb(powerBomb)
, x18_missile(missile)
, x1c_boostBall(boostBall)
, x20_phazon(phazon)
, x24_enemyWp1(enemyWp1)
, x28_enemyWp2Poison(enemyWp2)
, x2c_enemyWp3Lava(enemyWp3)
, x30_enemyWp4(enemyWp4)
, x34_unk1(v1)
, x38_unk2(v2)
, x3c_chargedPower(chargedPower)
, x40_chargedIce(chargedIce)
, x44_chargedWave(chargedWave)
, x48_chargedPlasma(chargedPlasma)
, x4c_superMissile(superMissile)
, x50_iceSpreader(iceSpreader)
, x54_wavebuster(waveBuster)
, x58_flamethrower(flameThrower)
, x5c_(v3)
{
}
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;
}
}