diff --git a/DataSpec/DNACommon/Tweaks/ITweakGui.hpp b/DataSpec/DNACommon/Tweaks/ITweakGui.hpp index d0293e59a..09c3a2616 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakGui.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakGui.hpp @@ -9,6 +9,7 @@ namespace DataSpec struct ITweakGui : ITweak { + virtual float GetScanAppearanceOffset() const = 0; virtual float GetScanSpeed(int idx) const=0; virtual float GetXrayBlurScaleLinear() const=0; virtual float GetXrayBlurScaleQuadratic() const=0; diff --git a/DataSpec/DNAMP1/Tweaks/CTweakGui.hpp b/DataSpec/DNAMP1/Tweaks/CTweakGui.hpp index ecf6b0339..76b443c50 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakGui.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakGui.hpp @@ -136,7 +136,7 @@ struct CTweakGui : ITweakGui Value x238_; Value x23c_; Value x240_; - Value x244_; + Value x244_scanAppearanceOffset; Value x248_; Value x24c_; Value x250_; @@ -194,6 +194,8 @@ struct CTweakGui : ITweakGui CTweakGui() = default; CTweakGui(athena::io::IStreamReader& r) { this->read(r); } + + float GetScanAppearanceOffset() const { return x244_scanAppearanceOffset; } float GetXrayBlurScaleLinear() const { return x204_xrayBlurScaleLinear; } float GetXrayBlurScaleQuadratic() const { return x208_xrayBlurScaleQuadratic; } diff --git a/Runtime/CScannableObjectInfo.cpp b/Runtime/CScannableObjectInfo.cpp index 3f15660a9..830561fd7 100644 --- a/Runtime/CScannableObjectInfo.cpp +++ b/Runtime/CScannableObjectInfo.cpp @@ -7,6 +7,26 @@ CScannableObjectInfo::CScannableObjectInfo(CInputStream& in, ResId resId) : x0_s { u32 version = in.readUint32Big(); Load(in, version); + + float appearanceOffset = g_tweakGui->GetScanAppearanceOffset(); + for (u32 i = 0 ; i < x14_buckets.size(); ++i) + { + if (x14_buckets[i].x8_imagePos != -1) + { + x14_buckets[i].x4_appearanceRange += appearanceOffset; + for (u32 j = i; j < x14_buckets.size(); j++) + x14_buckets[j].x4_appearanceRange += appearanceOffset; + } + } + + for (u32 i = 0; i < x14_buckets.size() - 1; ++i) + { + for (u32 j = i + 1; j < x14_buckets.size(); ++j) + { + if (x14_buckets[i].x8_imagePos == x14_buckets[j].x8_imagePos && x14_buckets[i].x8_imagePos != -1) + x14_buckets[j].x8_imagePos = -1; + } + } } ResId CScannableObjectInfo::GetScannableObjectId() const { return x0_scannableObjectId; } diff --git a/Runtime/World/CDamageInfo.cpp b/Runtime/World/CDamageInfo.cpp index 3ccb1e836..48c8619a9 100644 --- a/Runtime/World/CDamageInfo.cpp +++ b/Runtime/World/CDamageInfo.cpp @@ -5,8 +5,6 @@ namespace urde { -float CDamageInfo::GetRadiusDamage(const CDamageVulnerability& dVuln) { return 0.f; } - CDamageInfo::CDamageInfo(const DataSpec::SShotParam& other) : x0_weaponMode(CWeaponMode(EWeaponType(other.weaponType), other.Charged(), other.Comboed(), other.InstaKill())) , x8_damage(other.damage) @@ -26,4 +24,27 @@ CDamageInfo& CDamageInfo::operator=(const DataSpec::SShotParam& other) x18_ = false; return *this; } + +float CDamageInfo::GetDamage(const CDamageVulnerability& dVuln) +{ + EVulnerability vuln = dVuln.GetVulnerability(x0_weaponMode, false); + if (vuln == EVulnerability::Reflect) + return 0.f; + else if (vuln == EVulnerability::DoubleDamage) + return 2.f * x8_damage; + + return x8_damage; +} + +float CDamageInfo::GetRadiusDamage(const CDamageVulnerability& dVuln) +{ + EVulnerability vuln = dVuln.GetVulnerability(x0_weaponMode, false); + if (vuln == EVulnerability::Reflect) + return 0.f; + else if (vuln == EVulnerability::DoubleDamage) + return 2.f * xc_radiusDamage; + + return xc_radiusDamage; +} + } diff --git a/Runtime/World/CDamageInfo.hpp b/Runtime/World/CDamageInfo.hpp index 3a0b7ecb1..f91abe656 100644 --- a/Runtime/World/CDamageInfo.hpp +++ b/Runtime/World/CDamageInfo.hpp @@ -47,7 +47,7 @@ public: void SetRadius(float r) { x10_radius = r; } float GetKnockBackPower() const { return x14_knockback; } float GetDamage() const { return x8_damage; } - void GetDamage(const CDamageVulnerability& dVuln); + float GetDamage(const CDamageVulnerability& dVuln); float GetRadiusDamage() const { return xc_radiusDamage; } float GetRadiusDamage(const CDamageVulnerability& dVuln); }; diff --git a/Runtime/World/CDamageVulnerability.cpp b/Runtime/World/CDamageVulnerability.cpp new file mode 100644 index 000000000..a495c22ba --- /dev/null +++ b/Runtime/World/CDamageVulnerability.cpp @@ -0,0 +1,208 @@ +#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; +} +} diff --git a/Runtime/World/CDamageVulnerability.hpp b/Runtime/World/CDamageVulnerability.hpp index 8fc495155..6cfcb0819 100644 --- a/Runtime/World/CDamageVulnerability.hpp +++ b/Runtime/World/CDamageVulnerability.hpp @@ -15,7 +15,8 @@ enum class EVulnerability Immune, PassThrough, DirectDouble, - Direct + DirectNormal, + DirectImmune }; class CDamageVulnerability @@ -50,78 +51,17 @@ class CDamageVulnerability u32 x60_; u32 x64_; - void ConstructNew(CInputStream& in, int propCount) - { - EVulnerability* vulns = &x0_power; - for (int i=0 ; i int(EWeaponType::Unused2)) - return EVulnerability::Reflect; - - if (!mode.IsInstantKill()) - return EVulnerability::Normal; - // TODO: Finish - return EVulnerability::Normal; - } + bool WeaponHurts(const CWeaponMode&, bool ignoreDirect) const; + bool WeaponHits(const CWeaponMode& mode, bool checkDirect) const; + EVulnerability GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const; }; - } #endif // __URDE_CDAMAGEVULNERABILITY_HPP__ diff --git a/Runtime/World/CMakeLists.txt b/Runtime/World/CMakeLists.txt index b1c06a394..196fc022a 100644 --- a/Runtime/World/CMakeLists.txt +++ b/Runtime/World/CMakeLists.txt @@ -93,7 +93,7 @@ set(WORLD_SOURCES CVisorParameters.hpp CAnimationParameters.hpp CDamageInfo.hpp CDamageInfo.cpp - CDamageVulnerability.hpp + CDamageVulnerability.hpp CDamageVulnerability.cpp CFluidUVMotion.hpp CFluidUVMotion.cpp CPatternedInfo.hpp CPatternedInfo.cpp CHealthInfo.hpp CHealthInfo.cpp