From d6051f880814fa35403608154a50bf992d41a1cf Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sun, 4 Nov 2018 20:12:53 -1000 Subject: [PATCH] Implement CKnockBackController --- Runtime/CStateManager.cpp | 2 +- Runtime/Character/CharacterCommon.hpp | 4 +- Runtime/Graphics/CVertexMorphEffect.cpp | 7 + Runtime/Graphics/CVertexMorphEffect.hpp | 15 +- Runtime/MP1/World/CAtomicAlpha.cpp | 2 +- Runtime/MP1/World/CBabygoth.cpp | 2 +- Runtime/MP1/World/CBeetle.cpp | 2 +- Runtime/MP1/World/CBloodFlower.cpp | 2 +- Runtime/MP1/World/CBurrower.cpp | 2 +- Runtime/MP1/World/CChozoGhost.cpp | 2 +- Runtime/MP1/World/CElitePirate.cpp | 2 +- Runtime/MP1/World/CEyeball.cpp | 2 +- Runtime/MP1/World/CFireFlea.cpp | 2 +- Runtime/MP1/World/CFlickerBat.cpp | 2 +- Runtime/MP1/World/CFlyingPirate.cpp | 2 +- Runtime/MP1/World/CMagdolite.cpp | 2 +- Runtime/MP1/World/CMetaree.cpp | 2 +- Runtime/MP1/World/CMetroid.cpp | 2 +- Runtime/MP1/World/CMetroidBeta.cpp | 2 +- Runtime/MP1/World/CMetroidPrimeExo.cpp | 2 +- Runtime/MP1/World/CNewIntroBoss.cpp | 2 +- Runtime/MP1/World/CParasite.cpp | 8 +- Runtime/MP1/World/CPuddleToadGamma.cpp | 2 +- Runtime/MP1/World/CPuffer.cpp | 2 +- Runtime/MP1/World/CRidley.cpp | 3 +- Runtime/MP1/World/CSeedling.cpp | 3 +- Runtime/MP1/World/CSpacePirate.cpp | 2 +- Runtime/MP1/World/CThardusRockProjectile.cpp | 2 +- Runtime/MP1/World/CTryclops.cpp | 2 +- Runtime/MP1/World/CWarWasp.cpp | 2 +- Runtime/World/CAi.hpp | 12 +- Runtime/World/CAiFuncMap.hpp | 3 +- Runtime/World/CKnockBackController.cpp | 671 +++++++++++++++++++ Runtime/World/CKnockBackController.hpp | 154 +++++ Runtime/World/CMakeLists.txt | 1 + Runtime/World/CPatterned.cpp | 73 +- Runtime/World/CPatterned.hpp | 43 +- Runtime/World/CWallWalker.cpp | 2 +- Runtime/World/CWallWalker.hpp | 2 +- 39 files changed, 947 insertions(+), 102 deletions(-) create mode 100644 Runtime/World/CKnockBackController.cpp create mode 100644 Runtime/World/CKnockBackController.hpp diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index 2525c88ae..7a36044bb 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -1746,7 +1746,7 @@ bool CStateManager::ApplyLocalDamage(const zeus::CVector3f& vec1, const zeus::CV if (significant) ai->TakeDamage(vec2, mulDam); if (newHp <= 0.f) - ai->Death(*this, vec2, EStateMsg::Twenty); + ai->Death(vec2, *this, EScriptObjectState::DeathRattle); } return significant; diff --git a/Runtime/Character/CharacterCommon.hpp b/Runtime/Character/CharacterCommon.hpp index 350513a30..8e32fa5b3 100644 --- a/Runtime/Character/CharacterCommon.hpp +++ b/Runtime/Character/CharacterCommon.hpp @@ -141,7 +141,9 @@ enum class EStepType enum class ESeverity { - Invalid = -1 + Invalid = -1, + Zero = 0, + One = 1 }; enum class EGetupType diff --git a/Runtime/Graphics/CVertexMorphEffect.cpp b/Runtime/Graphics/CVertexMorphEffect.cpp index efddf2b1c..b270a67b8 100644 --- a/Runtime/Graphics/CVertexMorphEffect.cpp +++ b/Runtime/Graphics/CVertexMorphEffect.cpp @@ -4,6 +4,13 @@ namespace urde { +CVertexMorphEffect::CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus::CVector3f& v2, + float diagExtent, float f2, CRandom16& random) +: x0_(v1), x20_diagExtent(diagExtent), x24_random(random) +{ + +} + void CVertexMorphEffect::MorphVertices(std::vector>& vn, const float* magnitudes, const TLockedToken& skinRules, const CPoseAsTransforms& pose) const diff --git a/Runtime/Graphics/CVertexMorphEffect.hpp b/Runtime/Graphics/CVertexMorphEffect.hpp index 9bdc9262f..9cb88b0a2 100644 --- a/Runtime/Graphics/CVertexMorphEffect.hpp +++ b/Runtime/Graphics/CVertexMorphEffect.hpp @@ -6,12 +6,23 @@ namespace urde { class CSkinRules; +class CRandom16; class CVertexMorphEffect { - u32 x0_ = 0; - u32 x4_ = 1; + zeus::CUnitVector3f x0_; + float xc_ = 0.f; + float x10_ = 0.f; + float x14_ = 0.f; + float x18_ = 0.f; + float x1c_ = 0.f; + float x20_diagExtent; + CRandom16& x24_random; + std::vector x28_; + std::vector x38_; public: + CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus::CVector3f& v2, + float diagExtent, float f2, CRandom16& random); void MorphVertices(std::vector>& vn, const float* magnitudes, const TLockedToken& skinRules, const CPoseAsTransforms& pose) const; diff --git a/Runtime/MP1/World/CAtomicAlpha.cpp b/Runtime/MP1/World/CAtomicAlpha.cpp index cdda9e479..606aa3729 100644 --- a/Runtime/MP1/World/CAtomicAlpha.cpp +++ b/Runtime/MP1/World/CAtomicAlpha.cpp @@ -7,7 +7,7 @@ CAtomicAlpha::CAtomicAlpha(TUniqueId uid, std::string_view name, const CEntityIn CAssetId wpsc, const CDamageInfo& dInfo, float f1, float f2, float f3, CAssetId cmdl, bool b1, bool b2) : CPatterned(ECharacter::AtomicAlpha, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, actParms, 1) + EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, actParms, EKnockBackVariant::One) { } diff --git a/Runtime/MP1/World/CBabygoth.cpp b/Runtime/MP1/World/CBabygoth.cpp index d68b0ef40..defe077c6 100644 --- a/Runtime/MP1/World/CBabygoth.cpp +++ b/Runtime/MP1/World/CBabygoth.cpp @@ -35,7 +35,7 @@ CBabygothData::CBabygothData(CInputStream& in) CBabygoth::CBabygoth(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, const CBabygothData& babyData) : CPatterned(ECharacter::Babygoth, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Ground, - EColliderType::One, EBodyType::BiPedal, actParms, 1) + EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::One) { } diff --git a/Runtime/MP1/World/CBeetle.cpp b/Runtime/MP1/World/CBeetle.cpp index b6c1b6c64..0043565aa 100644 --- a/Runtime/MP1/World/CBeetle.cpp +++ b/Runtime/MP1/World/CBeetle.cpp @@ -11,7 +11,7 @@ CBeetle::CBeetle(TUniqueId uid, std::string_view name, const CEntityInfo& info, const CDamageVulnerability&, const zeus::CVector3f&, float, float, float, const CDamageVulnerability&, const CActorParameters& aParams, const std::experimental::optional) : CPatterned(ECharacter::Beetle, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Ground, - EColliderType::One, EBodyType::BiPedal, aParams, bool(flavor)) + EColliderType::One, EBodyType::BiPedal, aParams, EKnockBackVariant(flavor)) { } diff --git a/Runtime/MP1/World/CBloodFlower.cpp b/Runtime/MP1/World/CBloodFlower.cpp index 565e26a89..1361a8158 100644 --- a/Runtime/MP1/World/CBloodFlower.cpp +++ b/Runtime/MP1/World/CBloodFlower.cpp @@ -8,5 +8,5 @@ CBloodFlower::CBloodFlower(TUniqueId uid, std::string_view name, const CEntityIn const CDamageInfo& dInfo2, const CDamageInfo& dInfo3, CAssetId partId2, CAssetId partId3, CAssetId partId4, float f1, CAssetId partId5, u32 soundId) : CPatterned(ECharacter::BloodFlower, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Ground, EColliderType::One, EBodyType::Restricted, actParms, 1) {} + EMovementType::Ground, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::One) {} } \ No newline at end of file diff --git a/Runtime/MP1/World/CBurrower.cpp b/Runtime/MP1/World/CBurrower.cpp index 2493cd5a6..89ad2bf36 100644 --- a/Runtime/MP1/World/CBurrower.cpp +++ b/Runtime/MP1/World/CBurrower.cpp @@ -7,7 +7,7 @@ CBurrower::CBurrower(TUniqueId uid, std::string_view name, const CEntityInfo& in CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, CAssetId, CAssetId, CAssetId, const CDamageInfo&, CAssetId, u32, CAssetId) : CPatterned(ECharacter::Burrower, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, 0) + EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Zero) { } diff --git a/Runtime/MP1/World/CChozoGhost.cpp b/Runtime/MP1/World/CChozoGhost.cpp index f3bb2ca25..1f5da6684 100644 --- a/Runtime/MP1/World/CChozoGhost.cpp +++ b/Runtime/MP1/World/CChozoGhost.cpp @@ -22,7 +22,7 @@ CChozoGhost::CChozoGhost(TUniqueId uid, std::string_view name, const CEntityInfo const CBehaveChance& chance3, u16 sId1, float f5, u16 sId2, u16 sId3, u32 w1, float f6, u32 w2, float f7, CAssetId partId, s16 sId4, float f8, float f9, u32 w3, u32 w4) : CPatterned(ECharacter::ChozoGhost, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::Zero, EBodyType::BiPedal, actParms, 1) + EMovementType::Flyer, EColliderType::Zero, EBodyType::BiPedal, actParms, EKnockBackVariant::One) { } diff --git a/Runtime/MP1/World/CElitePirate.cpp b/Runtime/MP1/World/CElitePirate.cpp index 6aa5b6c9a..2081bb945 100644 --- a/Runtime/MP1/World/CElitePirate.cpp +++ b/Runtime/MP1/World/CElitePirate.cpp @@ -19,7 +19,7 @@ CElitePirate::CElitePirate(TUniqueId uid, std::string_view name, const CEntityIn CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, const CElitePirateData& eliteData) : CPatterned(ECharacter::ElitePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, 2) + EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Two) { } diff --git a/Runtime/MP1/World/CEyeball.cpp b/Runtime/MP1/World/CEyeball.cpp index 65290cc4d..f2b2aed7d 100644 --- a/Runtime/MP1/World/CEyeball.cpp +++ b/Runtime/MP1/World/CEyeball.cpp @@ -7,7 +7,7 @@ CEyeball::CEyeball(TUniqueId uid, std::string_view name, CPatterned::EFlavorType CAssetId, const CDamageInfo&, CAssetId, CAssetId, CAssetId, CAssetId, u32, u32, u32, u32, u32, const CActorParameters& actParms, bool) : CPatterned(ECharacter::EyeBall, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, - EColliderType::Zero, EBodyType::Restricted, actParms, 1) + EColliderType::Zero, EBodyType::Restricted, actParms, EKnockBackVariant::One) { } diff --git a/Runtime/MP1/World/CFireFlea.cpp b/Runtime/MP1/World/CFireFlea.cpp index ff170e1a6..f42dce2f0 100644 --- a/Runtime/MP1/World/CFireFlea.cpp +++ b/Runtime/MP1/World/CFireFlea.cpp @@ -6,7 +6,7 @@ namespace urde::MP1 CFireFlea::CFireFlea(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, float) : CPatterned(ECharacter::FireFlea, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, 0) + EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::Zero) { } diff --git a/Runtime/MP1/World/CFlickerBat.cpp b/Runtime/MP1/World/CFlickerBat.cpp index 91595cfa8..f3cb2ce5b 100644 --- a/Runtime/MP1/World/CFlickerBat.cpp +++ b/Runtime/MP1/World/CFlickerBat.cpp @@ -7,7 +7,7 @@ CFlickerBat::CFlickerBat(TUniqueId uid, std::string_view name, CPatterned::EFlav const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, EColliderType colType, bool b1, const CActorParameters& actParms, bool b2) : CPatterned(ECharacter::FlickerBat, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, colType, - EBodyType::Pitchable, actParms, 0) + EBodyType::Pitchable, actParms, EKnockBackVariant::Zero) { } diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index e1d10fef5..106ef2224 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -7,7 +7,7 @@ CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntity CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, CInputStream& in, u32 propCount) : CPatterned(ECharacter::FlyingPirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, 1) + EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::One) { } diff --git a/Runtime/MP1/World/CMagdolite.cpp b/Runtime/MP1/World/CMagdolite.cpp index b36321aa8..f354439bb 100644 --- a/Runtime/MP1/World/CMagdolite.cpp +++ b/Runtime/MP1/World/CMagdolite.cpp @@ -21,7 +21,7 @@ CMagdolite::CMagdolite(TUniqueId uid, std::string_view name, const CEntityInfo& const CDamageVulnerability& dVuln2, CAssetId modelId, CAssetId skinId, float f3, float f4, float f5, float f6, const urde::MP1::CMagdolite::CMagdoliteData& magData, float f7, float f8, float f9) : CPatterned(ECharacter::Magdolite, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::BiPedal, actParms, 2) + EMovementType::Flyer, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Two) { } diff --git a/Runtime/MP1/World/CMetaree.cpp b/Runtime/MP1/World/CMetaree.cpp index e018be456..ee54e8d27 100644 --- a/Runtime/MP1/World/CMetaree.cpp +++ b/Runtime/MP1/World/CMetaree.cpp @@ -7,7 +7,7 @@ CMetaree::CMetaree(TUniqueId uid, std::string_view name, EFlavorType flavor, con float f1, const zeus::CVector3f& v1, float f2, EBodyType bodyType, float f3, float f4, const CActorParameters& aParms) : CPatterned(ECharacter::Metaree, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, - EColliderType::Zero, bodyType, aParms, 0) + EColliderType::Zero, bodyType, aParms, EKnockBackVariant::Zero) , x568_(f3) , x56c_(f4) , x570_(f1) diff --git a/Runtime/MP1/World/CMetroid.cpp b/Runtime/MP1/World/CMetroid.cpp index c8bd54c38..b9eb7f5e6 100644 --- a/Runtime/MP1/World/CMetroid.cpp +++ b/Runtime/MP1/World/CMetroid.cpp @@ -24,7 +24,7 @@ CMetroid::CMetroid(TUniqueId uid, std::string_view name, EFlavorType flavor, con const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms, const CMetroidData& metroidData) : CPatterned(ECharacter::Metroid, uid, name, flavor, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, true) + EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::One) { } diff --git a/Runtime/MP1/World/CMetroidBeta.cpp b/Runtime/MP1/World/CMetroidBeta.cpp index e219c54c9..17f27d673 100644 --- a/Runtime/MP1/World/CMetroidBeta.cpp +++ b/Runtime/MP1/World/CMetroidBeta.cpp @@ -29,7 +29,7 @@ CMetroidBeta::CMetroidBeta(TUniqueId uid, std::string_view name, const CEntityIn const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms, const CMetroidBetaData& metroidData) : CPatterned(ECharacter::MetroidBeta, uid, name, EFlavorType::One, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, 2) + EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Two) { } diff --git a/Runtime/MP1/World/CMetroidPrimeExo.cpp b/Runtime/MP1/World/CMetroidPrimeExo.cpp index 0a4fdff50..44c01f58c 100644 --- a/Runtime/MP1/World/CMetroidPrimeExo.cpp +++ b/Runtime/MP1/World/CMetroidPrimeExo.cpp @@ -142,7 +142,7 @@ CMetroidPrimeExo::CMetroidPrimeExo(TUniqueId uid, std::string_view name, const C CAssetId particle3, CAssetId particle4, const rstl::reserved_vector& struct6s) : CPatterned(ECharacter::MetroidPrimeExo, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, 2) + EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Two) { } diff --git a/Runtime/MP1/World/CNewIntroBoss.cpp b/Runtime/MP1/World/CNewIntroBoss.cpp index eacc647f9..c42382fa6 100644 --- a/Runtime/MP1/World/CNewIntroBoss.cpp +++ b/Runtime/MP1/World/CNewIntroBoss.cpp @@ -10,7 +10,7 @@ CNewIntroBoss::CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntity const CActorParameters& actParms, float, u32, const CDamageInfo& dInfo, u32, u32, u32, u32) : CPatterned(ECharacter::NewIntroBoss, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, true) + EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::One) { } diff --git a/Runtime/MP1/World/CParasite.cpp b/Runtime/MP1/World/CParasite.cpp index 799a6cc32..b73e65a2e 100644 --- a/Runtime/MP1/World/CParasite.cpp +++ b/Runtime/MP1/World/CParasite.cpp @@ -24,7 +24,7 @@ CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, c bool b1, u32 w1, const CDamageVulnerability& dVuln,const CDamageInfo& parInfo, u16 sfxId1, u16 sfxId2, u16 sfxId3, u32 w2, u32 w3, float f19, const CActorParameters &aParams) : CWallWalker(ECharacter::Parasite, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, - EColliderType::Zero, bodyType, aParams, f7, f4, 0, f2, w1, f17, b1) + EColliderType::Zero, bodyType, aParams, f7, f4, EKnockBackVariant::Zero, f2, w1, f17, b1) , x64c_(dVuln) , x6b4_(parInfo) , x6d0_(f1) @@ -53,9 +53,9 @@ CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, c switch(x5d0_) { case 2: - //x460_.x81_25_ = false; + x460_knockBackController.SetX81_25(false); case 1: - //x460_.sub80233d64(false); + x460_knockBackController.SetAutoResetImpulse(false); break; case 3: @@ -163,7 +163,7 @@ void CParasite::Think(float dt, CStateManager& mgr) } } - if (x400_25_) + if (x400_25_alive) { CPlayer* pl = mgr.Player(); float radius; diff --git a/Runtime/MP1/World/CPuddleToadGamma.cpp b/Runtime/MP1/World/CPuddleToadGamma.cpp index a7c69bcf7..49d09b2cc 100644 --- a/Runtime/MP1/World/CPuddleToadGamma.cpp +++ b/Runtime/MP1/World/CPuddleToadGamma.cpp @@ -9,7 +9,7 @@ CPuddleToadGamma::CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavor const zeus::CVector3f& v1, float f4, float f5, float f6, const CDamageInfo& dInfo1, const CDamageInfo& dInfo2) : CPatterned(ECharacter::PuddleToad, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, - EColliderType::Zero, EBodyType::Restricted, aParms, 2) + EColliderType::Zero, EBodyType::Restricted, aParms, EKnockBackVariant::Two) { } diff --git a/Runtime/MP1/World/CPuffer.cpp b/Runtime/MP1/World/CPuffer.cpp index 2c98f73ba..796917a83 100644 --- a/Runtime/MP1/World/CPuffer.cpp +++ b/Runtime/MP1/World/CPuffer.cpp @@ -8,7 +8,7 @@ CPuffer::CPuffer(TUniqueId uid, std::string_view name, const CEntityInfo& info, float hoverSpeed, CAssetId cloudEffect, const CDamageInfo& cloudDamage, CAssetId cloudSteam, float f2, bool b1, bool b2, bool b3, const CDamageInfo& explosionDamage, s16 sfxId) : CPatterned(ECharacter::Puffer, uid, name, EFlavorType::Zero, info, xf, std::move(modelData), patternedInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::RestrictedFlyer, actorParameters, 0) + EMovementType::Flyer, EColliderType::One, EBodyType::RestrictedFlyer, actorParameters, EKnockBackVariant::Zero) { } diff --git a/Runtime/MP1/World/CRidley.cpp b/Runtime/MP1/World/CRidley.cpp index 1b07861ea..18380bd71 100644 --- a/Runtime/MP1/World/CRidley.cpp +++ b/Runtime/MP1/World/CRidley.cpp @@ -22,7 +22,8 @@ CRidley::CRidley(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, CInputStream& in, u32 propCount) : CPatterned(ECharacter::Ridley, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::Zero, EBodyType::Flyer, actParms, 2), x568_(in, propCount) + EMovementType::Flyer, EColliderType::Zero, EBodyType::Flyer, actParms, EKnockBackVariant::Two), + x568_(in, propCount) { } } diff --git a/Runtime/MP1/World/CSeedling.cpp b/Runtime/MP1/World/CSeedling.cpp index 35be285da..1fe6e4fb6 100644 --- a/Runtime/MP1/World/CSeedling.cpp +++ b/Runtime/MP1/World/CSeedling.cpp @@ -10,7 +10,8 @@ CSeedling::CSeedling(TUniqueId uid, std::string_view name, const CEntityInfo& in CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, CAssetId, CAssetId, const CDamageInfo&, const CDamageInfo&, float f1, float f2, float f3, float f4) : CWallWalker(ECharacter::Seedling, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Ground, EColliderType::Zero, EBodyType::WallWalker, actParms, f1, f2, 0, f3, 4, f4, false) + EMovementType::Ground, EColliderType::Zero, EBodyType::WallWalker, actParms, f1, f2, + EKnockBackVariant::Zero, f3, 4, f4, false) { } diff --git a/Runtime/MP1/World/CSpacePirate.cpp b/Runtime/MP1/World/CSpacePirate.cpp index 8a30ae89d..b9734509a 100644 --- a/Runtime/MP1/World/CSpacePirate.cpp +++ b/Runtime/MP1/World/CSpacePirate.cpp @@ -22,7 +22,7 @@ CSpacePirate::CSpacePirate(TUniqueId uid, std::string_view name, const CEntityIn CModelData&& mData, const CActorParameters& aParams, const CPatternedInfo& pInfo, CInputStream& in, u32 propCount) : CPatterned(ECharacter::SpacePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Ground, - EColliderType::One, EBodyType::BiPedal, aParams, true) + EColliderType::One, EBodyType::BiPedal, aParams, EKnockBackVariant::One) , x568_(in, propCount) { } diff --git a/Runtime/MP1/World/CThardusRockProjectile.cpp b/Runtime/MP1/World/CThardusRockProjectile.cpp index f1cd63edc..8352ba2aa 100644 --- a/Runtime/MP1/World/CThardusRockProjectile.cpp +++ b/Runtime/MP1/World/CThardusRockProjectile.cpp @@ -8,7 +8,7 @@ CThardusRockProjectile::CThardusRockProjectile( const zeus::CTransform& xf, CModelData&& modelData, const CActorParameters& aParms, const CPatternedInfo& patternedInfo, const std::vector& mDataVec, u32) : CPatterned(ECharacter::ThardusRockProjectile, uid, name, EFlavorType::Zero, info, xf, std::move(modelData), - patternedInfo, EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, true) + patternedInfo, EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::One) { } diff --git a/Runtime/MP1/World/CTryclops.cpp b/Runtime/MP1/World/CTryclops.cpp index 276685113..1cb42de5e 100644 --- a/Runtime/MP1/World/CTryclops.cpp +++ b/Runtime/MP1/World/CTryclops.cpp @@ -5,6 +5,6 @@ namespace urde::MP1 CTryclops::CTryclops(urde::TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, urde::CModelData&& mData, const urde::CPatternedInfo& pInfo, const urde::CActorParameters& actParms, float, float, float, float) : CPatterned(ECharacter::Tryclops, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, 0) + EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Zero) {} } \ No newline at end of file diff --git a/Runtime/MP1/World/CWarWasp.cpp b/Runtime/MP1/World/CWarWasp.cpp index 66f954dde..4d0b9af8b 100644 --- a/Runtime/MP1/World/CWarWasp.cpp +++ b/Runtime/MP1/World/CWarWasp.cpp @@ -9,7 +9,7 @@ CWarWasp::CWarWasp(TUniqueId uid, std::string_view name, const CEntityInfo& info CPatterned::EColliderType collider, const CDamageInfo& dInfo1, const CActorParameters& actorParms, CAssetId weapon, const CDamageInfo& dInfo2, CAssetId particle, u32 w3) : CPatterned(ECharacter::WarWasp, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, collider, - EBodyType::Flyer, actorParms, false) + EBodyType::Flyer, actorParms, EKnockBackVariant::Zero) { } diff --git a/Runtime/World/CAi.hpp b/Runtime/World/CAi.hpp index 053adeead..cbad8b626 100644 --- a/Runtime/World/CAi.hpp +++ b/Runtime/World/CAi.hpp @@ -8,6 +8,7 @@ #include "CDamageVulnerability.hpp" #include "CHealthInfo.hpp" #include "CStateMachine.hpp" +#include "CKnockBackController.hpp" #include "zeus/zeus.hpp" @@ -21,12 +22,6 @@ enum class EListenNoiseType Projectile }; -enum class EKnockBackType -{ - Zero, - One -}; - class CAiFuncMap; class CStateManager; class CScriptWater; @@ -50,8 +45,9 @@ public: virtual void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); virtual CHealthInfo* HealthInfo(CStateManager&) { return &x258_healthInfo; } - virtual void Death(CStateManager&, const zeus::CVector3f&, EStateMsg)=0; - virtual void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, EKnockBackType, bool, float)=0; + virtual void Death(const zeus::CVector3f&, CStateManager&, EScriptObjectState)=0; + virtual void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, + EKnockBackType type, bool inDeferred, float magnitude)=0; virtual const CDamageVulnerability* GetDamageVulnerability() const { return &x260_damageVulnerability; } virtual const CDamageVulnerability* GetDamageVulnerability() { return &x260_damageVulnerability; } virtual void TakeDamage(const zeus::CVector3f&, float) {} diff --git a/Runtime/World/CAiFuncMap.hpp b/Runtime/World/CAiFuncMap.hpp index d22133225..91e51e29d 100644 --- a/Runtime/World/CAiFuncMap.hpp +++ b/Runtime/World/CAiFuncMap.hpp @@ -8,8 +8,7 @@ namespace urde enum class EStateMsg { One = 1, - Two = 2, - Twenty = 20 + Two = 2 }; class CStateManager; diff --git a/Runtime/World/CKnockBackController.cpp b/Runtime/World/CKnockBackController.cpp new file mode 100644 index 000000000..a884337ad --- /dev/null +++ b/Runtime/World/CKnockBackController.cpp @@ -0,0 +1,671 @@ +#include "CKnockBackController.hpp" +#include "CPatterned.hpp" +#include "CStateManager.hpp" +#include "Character/CPASAnimParmData.hpp" + +namespace urde +{ + +static const CKnockBackController::KnockBackParms KnockBackParmsTable[3][19][4] = +{ + { + { + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Flinch, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 1.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Two, 2.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 2.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Two, 4.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 4.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 0.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Two, 4.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Two, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 2.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 2.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 5.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 5.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 8.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 4.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Flinch, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Six, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + }, + { + { + {EKnockBackAnimationState::Flinch, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Flinch, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 2.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 1.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Two, 2.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 2.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 2.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Two, 4.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Two, 4.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 0.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Two, 4.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Two, 4.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Two, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 2.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 2.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 5.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 5.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 8.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 8.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 4.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 4.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Three, 6.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Eight, 6.000000f, -1.000000f}, + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Three, 6.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Eight, 6.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Eight, 6.000000f, -1.000000f}, + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Three, 6.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Three, 6.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Eight, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Three, 6.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Seven, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Nine, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Nine, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Flinch, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Four, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + }, + { + { + {EKnockBackAnimationState::Flinch, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Flinch, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 2.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 1.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::Flinch, EKnockBackAnimationCondition::Two, 2.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 2.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 2.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Two, 4.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Two, 4.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Two, 4.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Two, 4.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Two, 4.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Two, 4.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 2.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 2.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 2.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 2.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 4.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 4.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 2.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::One, 2.500000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Flinch, EKnockBackAnimationCondition::Three, 6.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Three, 6.000000f, -1.000000f}, + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Three, 6.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Three, 6.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Three, 6.000000f, -1.000000f}, + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Three, 6.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Three, 6.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Eight, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Three, 6.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Flinch, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::KnockBack, EKnockBackAnimationCondition::Seven, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Flinch, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::None, EKnockBackAnimationCondition::Zero, 0.000000f, 0.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Nine, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Nine, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + { + {EKnockBackAnimationState::Flinch, EKnockBackAnimationCondition::Zero, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Four, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Hurled, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + {EKnockBackAnimationState::Fall, EKnockBackAnimationCondition::Seven, 0.000000f, -1.000000f}, + }, + }, +}; + +CKnockBackController::CKnockBackController(EKnockBackVariant variant) +: x0_variant(variant) +{ + x81_24_autoResetImpulse = true; + x81_25_ = true; + x81_27_ = true; + x81_28_ = true; + x81_29_ = true; + x81_30_ = true; + x81_31_ = true; + x82_24_ = true; + for (int i = 0; i < 4; ++i) + { + x24_.push_back(std::make_pair(0.f, FLT_MAX)); + x80_availableStates.set(i); + } +} + +static const float ImpulseDurationTable[] = { 0.1f, 0.3f }; + +void CKnockBackController::ApplyImpulse(float dt, CPatterned& parent) +{ + x60_impulseRemTime = std::max(0.f, x60_impulseRemTime - dt); + if (!parent.GetMaterialList().HasMaterial(EMaterialTypes::Immovable) && x60_impulseRemTime > 0.f) + { + float remFac = 1.f; + if (x20_impulseDurationIdx == 1) + remFac = x60_impulseRemTime / ImpulseDurationTable[x20_impulseDurationIdx]; + parent.ApplyImpulseWR( + parent.GetMoveToORImpulseWR( + parent.GetTransform().transposeRotate(x50_impulseDir * + (remFac * x5c_impulseMag * dt / ImpulseDurationTable[x20_impulseDurationIdx])), dt), + zeus::CAxisAngle::sIdentity); + } +} + +bool CKnockBackController::TickDeferredTimer(float dt) +{ + x68_deferRemTime -= dt; + if (x14_deferWeaponType != EWeaponType::None) + return x68_deferRemTime <= 0.f; + return false; +} + +EKnockBackCharacterState CKnockBackController::GetKnockBackCharacterState(CPatterned& parent) +{ + if (parent.BodyController()->IsFrozen()) + return parent.IsAlive() ? EKnockBackCharacterState::FrozenAlive : EKnockBackCharacterState::FrozenDead; + return parent.IsAlive() ? EKnockBackCharacterState::Alive : EKnockBackCharacterState::Dead; +} + +void CKnockBackController::ValidateState(CPatterned& parent) +{ + if (x4_activeParms.x0_animState < x18_minAnimState) + x4_activeParms.x0_animState = x18_minAnimState; + else if (x4_activeParms.x0_animState > x1c_maxAnimState) + x4_activeParms.x0_animState = x1c_maxAnimState; + + EKnockBackAnimationState useState = EKnockBackAnimationState::Invalid; + if (parent.IsAlive()) + { + if (parent.BodyController()->HasBodyState(pas::EAnimationState::Hurled) && + x80_availableStates.test(3) && x4_activeParms.x0_animState >= EKnockBackAnimationState::Hurled) + { + useState = EKnockBackAnimationState::Hurled; + } + else if (parent.BodyController()->HasBodyState(pas::EAnimationState::KnockBack) && + x80_availableStates.test(2) && x4_activeParms.x0_animState >= EKnockBackAnimationState::KnockBack) + { + useState = EKnockBackAnimationState::KnockBack; + } + else if (parent.BodyController()->HasBodyState(pas::EAnimationState::AdditiveFlinch) && + x80_availableStates.test(1) && x4_activeParms.x0_animState >= EKnockBackAnimationState::Flinch) + { + useState = EKnockBackAnimationState::Flinch; + } + } + else + { + if (parent.BodyController()->HasBodyState(pas::EAnimationState::Fall) && x80_availableStates.test(4) && + (x4_activeParms.x0_animState >= EKnockBackAnimationState::Fall || + (!parent.BodyController()->HasBodyState(pas::EAnimationState::Hurled) + && x4_activeParms.x0_animState >= EKnockBackAnimationState::Hurled))) + { + useState = EKnockBackAnimationState::Fall; + } + else if (parent.BodyController()->HasBodyState(pas::EAnimationState::Hurled) && + x80_availableStates.test(3) && x4_activeParms.x0_animState >= EKnockBackAnimationState::Hurled) + { + useState = EKnockBackAnimationState::Hurled; + } + } + + x4_activeParms.x0_animState = (useState != EKnockBackAnimationState::Invalid) ? + useState : EKnockBackAnimationState::None; + + bool r4 = false; + switch (x4_activeParms.x4_animCondition) + { + case EKnockBackAnimationCondition::One: + r4 = !x81_25_; + break; + case EKnockBackAnimationCondition::Two: + r4 = !x81_26_; + break; + case EKnockBackAnimationCondition::Three: + r4 = !x81_27_; + break; + case EKnockBackAnimationCondition::Six: + r4 = !x81_29_; + break; + case EKnockBackAnimationCondition::Seven: + r4 = !x81_29_; + break; + case EKnockBackAnimationCondition::Eight: + r4 = !x81_28_; + break; + case EKnockBackAnimationCondition::Nine: + r4 = !x81_30_; + break; + default: + break; + } + + if (r4) + { + x4_activeParms.x4_animCondition = EKnockBackAnimationCondition::Zero; + x4_activeParms.x8_ = 0.f; + } +} + +float CKnockBackController::CalculateExtraHurlVelocity(CStateManager& mgr, float magnitude, float kbResistance) +{ + if (magnitude > kbResistance) + return (1.1f - 0.2f * mgr.GetActiveRandom()->Float()) * 2.f * (magnitude - kbResistance); + return 0.f; +} + +void CKnockBackController::DoKnockBackAnimation(const zeus::CVector3f& backVec, CStateManager& mgr, + CPatterned& parent, float magnitude) +{ + switch (x4_activeParms.x0_animState) + { + case EKnockBackAnimationState::Hurled: + { + float hurlVel = 5.f; + if (CHealthInfo* hInfo = parent.HealthInfo(mgr)) + hurlVel += CalculateExtraHurlVelocity(mgr, magnitude, hInfo->GetKnockbackResistance()); + hurlVel = std::sqrt(parent.GetGravityConstant() * 0.5f * hurlVel); + zeus::CVector3f backUpVec = backVec + backVec.magnitude() * zeus::CVector3f::skUp; + if (backUpVec.canBeNormalized()) + { + parent.BodyController()->GetCommandMgr().DeliverCmd( + CBCHurledCmd(-backVec, backUpVec.normalized() * hurlVel)); + parent.SetMomentumWR({0.f, 0.f, parent.GetGravityConstant() * -parent.GetMass()}); + } + break; + } + case EKnockBackAnimationState::Fall: + { + parent.BodyController()->GetCommandMgr().DeliverCmd(CBCKnockDownCmd(-backVec, x7c_severity)); + break; + } + case EKnockBackAnimationState::KnockBack: + { + parent.BodyController()->GetCommandMgr().DeliverCmd(CBCKnockBackCmd(-backVec, x7c_severity)); + break; + } + case EKnockBackAnimationState::Flinch: + { + std::pair bestAnim = + parent.BodyController()->GetPASDatabase().FindBestAnimation( + CPASAnimParmData(23), *mgr.GetActiveRandom(), -1); + if (bestAnim.first > 0.f) + { + parent.ModelData()->AnimationData()->AddAdditiveAnimation(bestAnim.second, 1.f, false, true); + x64_flinchRemTime = std::max( + parent.ModelData()->AnimationData()->GetAnimationDuration(bestAnim.second), x64_flinchRemTime); + } + break; + } + default: + break; + } +} + +void CKnockBackController::ResetKnockBackImpulse(CPatterned& parent, const zeus::CVector3f& backVec, float magnitude) +{ + if (x81_24_autoResetImpulse && x4_activeParms.x0_animState == EKnockBackAnimationState::KnockBack && + x4_activeParms.x4_animCondition != EKnockBackAnimationCondition::One) + { + x50_impulseDir = backVec.canBeNormalized() ? backVec.normalized() : -parent.GetTransform().basis[1]; + if (x60_impulseRemTime <= 0.f) + x5c_impulseMag = magnitude; + else + x5c_impulseMag += magnitude * (1.f - x60_impulseRemTime / ImpulseDurationTable[x20_impulseDurationIdx]); + x60_impulseRemTime = ImpulseDurationTable[x20_impulseDurationIdx]; + } +} + +void CKnockBackController::DoDeferredKnockBack(CStateManager& mgr, CPatterned& parent) +{ + if (x14_deferWeaponType == EWeaponType::Wave) + { + x4_activeParms = KnockBackParmsTable[int(x0_variant)][int(EKnockBackWeaponType::WaveExtra)] + [int(GetKnockBackCharacterState(parent))]; + ValidateState(parent); + if (CHealthInfo* hInfo = parent.HealthInfo(mgr)) + { + zeus::CVector3f backVec = -parent.GetTransform().basis[1]; + DoKnockBackAnimation(backVec, mgr, parent, 10.f); + ResetKnockBackImpulse(parent, backVec, 2.f); + x82_25_inDeferredKnockBack = true; + parent.KnockBack(backVec, mgr, + CDamageInfo({x14_deferWeaponType, false, true, false}, 0.f, 0.f, 10.f), + EKnockBackType::One, x82_25_inDeferredKnockBack, 10.f); + x82_25_inDeferredKnockBack = false; + } + } + x68_deferRemTime = 0.f; + x4_activeParms = KnockBackParms{}; + x14_deferWeaponType = EWeaponType::None; +} + +void CKnockBackController::sub80233d40(int i, float f1, float f2) +{ + if (i < 0 || i > 4) + return; + x24_[i] = std::make_pair(f1, f2); +} + +void CKnockBackController::SetAutoResetImpulse(bool b) +{ + x81_24_autoResetImpulse = b; + if (!b) + { + x5c_impulseMag = 0.f; + x60_impulseRemTime = 0.f; + } +} + +void CKnockBackController::Update(float dt, CStateManager& mgr, CPatterned& parent) +{ + ApplyImpulse(dt, parent); + x64_flinchRemTime -= dt; + if (TickDeferredTimer(dt)) + DoDeferredKnockBack(mgr, parent); + if (x82_26_ && parent.BodyController()->IsElectrocuting()) + parent.BodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Locomotion)); +} + +EKnockBackWeaponType CKnockBackController::GetKnockBackWeaponType(const CDamageInfo& info, EWeaponType wType, + EKnockBackType type) +{ + int stacking = 0; + if (info.GetWeaponMode().IsCharged()) + stacking = 1; + else if (info.GetWeaponMode().IsComboed()) + stacking = 2; + if (wType > EWeaponType::Phazon) + return EKnockBackWeaponType::Invalid; + switch (wType) + { + case EWeaponType::Power: + return EKnockBackWeaponType(type != EKnockBackType::Zero ? stacking : stacking + 1); + case EWeaponType::Ice: + return EKnockBackWeaponType(type != EKnockBackType::Zero ? stacking + 8 : stacking + 9); + case EWeaponType::Wave: + return EKnockBackWeaponType(stacking + 4); + case EWeaponType::Plasma: + return EKnockBackWeaponType(stacking + 12); + case EWeaponType::Bomb: + return EKnockBackWeaponType::Bomb; + case EWeaponType::PowerBomb: + return EKnockBackWeaponType::PowerBomb; + case EWeaponType::Missile: + return EKnockBackWeaponType::Missile; + case EWeaponType::Phazon: + return EKnockBackWeaponType::Phazon; + default: + return EKnockBackWeaponType::Invalid; + } +} + +void CKnockBackController::SelectDamageState(CPatterned& parent, const CDamageInfo& info, + EWeaponType wType, EKnockBackType type) +{ + EKnockBackWeaponType weaponType = GetKnockBackWeaponType(info, wType, type); + if (weaponType != EKnockBackWeaponType::Invalid) + { + x4_activeParms = KnockBackParmsTable[int(x0_variant)][int(weaponType)] + [int(GetKnockBackCharacterState(parent))]; + ValidateState(parent); + } +} + +void CKnockBackController::KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, + const CDamageInfo& info, EKnockBackType type, float magnitude) +{ + if (!x82_25_inDeferredKnockBack) + { + zeus::CVector3f vec(backVec.toVec2f()); + if (!vec.isMagnitudeSafe()) + vec = -parent.GetTransform().basis[1]; + SelectDamageState(parent, info, info.GetWeaponMode().GetType(), type); + DoKnockBackAnimation(vec, mgr, parent, magnitude); + ResetKnockBackImpulse(parent, vec, 2.f); + } +} + +} diff --git a/Runtime/World/CKnockBackController.hpp b/Runtime/World/CKnockBackController.hpp new file mode 100644 index 000000000..c3826e00d --- /dev/null +++ b/Runtime/World/CKnockBackController.hpp @@ -0,0 +1,154 @@ +#pragma once +#include "RetroTypes.hpp" +#include "zeus/CVector3f.hpp" +#include "Character/CharacterCommon.hpp" +#include "Weapon/WeaponCommon.hpp" + +namespace urde +{ +class CPatterned; +class CDamageInfo; + +enum class EKnockBackType +{ + Zero, + One +}; + +enum class EKnockBackVariant +{ + Zero, + One, + Two +}; + +enum class EKnockBackWeaponType +{ + Invalid = -1, + Power, + PowerCharged, + PowerComboed, + PowerExtra, + Wave, + WaveCharged, + WaveComboed, + WaveExtra, + Ice, + IceCharged, + IceComboed, + IceExtra, + Plasma, + PlasmaCharged, + PlasmaComboed, + Missile, + Bomb, + PowerBomb, + Phazon +}; + +enum class EKnockBackCharacterState +{ + Alive, + Dead, + FrozenAlive, + FrozenDead +}; + +enum class EKnockBackAnimationState +{ + Invalid = -1, + None, + Flinch, + KnockBack, + Hurled, + Fall +}; + +enum class EKnockBackAnimationCondition +{ + Invalid = -1, + Zero, + One, + Two, + Three, + Four, + Five, + Six, + Seven, + Eight, + Nine +}; + +class CKnockBackController +{ +public: + struct KnockBackParms + { + EKnockBackAnimationState x0_animState; + EKnockBackAnimationCondition x4_animCondition; + float x8_; + float xc_; + }; +private: + friend class CPatterned; + EKnockBackVariant x0_variant; + KnockBackParms x4_activeParms; + EWeaponType x14_deferWeaponType = EWeaponType::None; + EKnockBackAnimationState x18_minAnimState = EKnockBackAnimationState::None; + EKnockBackAnimationState x1c_maxAnimState = EKnockBackAnimationState::Fall; + u32 x20_impulseDurationIdx = 0; + rstl::reserved_vector, 4> x24_; + zeus::CVector3f x50_impulseDir; + float x5c_impulseMag = 0.f; + float x60_impulseRemTime = 0.f; + float x64_flinchRemTime = 0.f; + float x68_deferRemTime = 0.f; + u32 x6c_ = 0; + u32 x70_ = 0; + u32 x74_ = 0; + pas::ESeverity x7c_severity = pas::ESeverity::One; + std::bitset<4> x80_availableStates; + union + { + struct + { + bool x81_24_autoResetImpulse : 1; // t + bool x81_25_ : 1; // t + bool x81_26_ : 1; + bool x81_27_ : 1; // t + bool x81_28_ : 1; // t + bool x81_29_ : 1; // t + bool x81_30_ : 1; // t + bool x81_31_ : 1; // t + bool x82_24_ : 1; // t + bool x82_25_inDeferredKnockBack : 1; + bool x82_26_ : 1; + }; + u32 dummy = 0; + }; + void ApplyImpulse(float dt, CPatterned& parent); + bool TickDeferredTimer(float dt); + EKnockBackCharacterState GetKnockBackCharacterState(CPatterned& parent); + void ValidateState(CPatterned& parent); + float CalculateExtraHurlVelocity(CStateManager& mgr, float magnitude, float kbResistance); + void DoKnockBackAnimation(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, float magnitude); + void ResetKnockBackImpulse(CPatterned& parent, const zeus::CVector3f& backVec, float magnitude); + void DoDeferredKnockBack(CStateManager& mgr, CPatterned& parent); + EKnockBackWeaponType GetKnockBackWeaponType(const CDamageInfo& info, EWeaponType wType, EKnockBackType type); + void SelectDamageState(CPatterned& parent, const CDamageInfo& info, EWeaponType wType, EKnockBackType type); +public: + explicit CKnockBackController(EKnockBackVariant variant); + void SetKnockBackVariant(EKnockBackVariant v) { x0_variant = v; } + void DeferKnockBack(EWeaponType tp) { x14_deferWeaponType = tp; x68_deferRemTime = 0.05f; } + void sub80233d40(int i, float f1, float f2); + void SetAutoResetImpulse(bool b); + void SetImpulseDurationIdx(u32 i) { x20_impulseDurationIdx = i; } + void SetAnimationStateRange(EKnockBackAnimationState a, EKnockBackAnimationState b) + { x18_minAnimState = a; x1c_maxAnimState = b; } + void Update(float dt, CStateManager& mgr, CPatterned& parent); + void KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, + const CDamageInfo& info, EKnockBackType type, float magnitude); + void SetX81_25(bool b) { x81_25_ = b; } +}; + +} \ No newline at end of file diff --git a/Runtime/World/CMakeLists.txt b/Runtime/World/CMakeLists.txt index c319b0753..5a98b9951 100644 --- a/Runtime/World/CMakeLists.txt +++ b/Runtime/World/CMakeLists.txt @@ -15,6 +15,7 @@ set(WORLD_SOURCES CAiFuncMap.hpp CAiFuncMap.cpp CStateMachine.hpp CStateMachine.cpp CPatterned.hpp CPatterned.cpp + CKnockBackController.hpp CKnockBackController.cpp CPathFindArea.hpp CPathFindArea.cpp CPathFindRegion.hpp CPathFindRegion.cpp CPathFindSearch.hpp CPathFindSearch.cpp diff --git a/Runtime/World/CPatterned.cpp b/Runtime/World/CPatterned.cpp index b2c8322a9..9b6d1f438 100644 --- a/Runtime/World/CPatterned.cpp +++ b/Runtime/World/CPatterned.cpp @@ -28,7 +28,7 @@ CPatterned::CPatterned(ECharacter character, TUniqueId uid, std::string_view nam const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, CPatterned::EMovementType moveType, CPatterned::EColliderType colliderType, EBodyType bodyType, const CActorParameters& actorParms, - int variant) + EKnockBackVariant kbVariant) : CAi(uid, pInfo.xf8_active, name, info, xf, std::move(mData), zeus::CAABox(pInfo.xcc_bodyOrigin - zeus::CVector3f{pInfo.xc4_halfExtent, pInfo.xc4_halfExtent, 0.f}, pInfo.xcc_bodyOrigin + @@ -50,12 +50,13 @@ x3c4_detectionAngle(std::cos(zeus::degToRad(pInfo.x14_dectectionAngle))), x3c8_leashRadius(pInfo.x28_leashRadius), x3cc_playerLeashRadius(pInfo.x2c_playerLeashRadius), x3d0_playerLeashTime(pInfo.x30_playerLeashTime), -x3fc_flavor(flavor) +x3fc_flavor(flavor), +x460_knockBackController(kbVariant) { - x400_25_ = true; + x400_25_alive = true; x400_31_ = moveType == CPatterned::EMovementType::Flyer; x402_29_ = true; - x402_30_ = x402_31_ = actorParms.HasThermalHeat(); + x402_30_ = x402_31_thawed = actorParms.HasThermalHeat(); x403_25_ = true; x403_26_ = true; x404_contactDamage = pInfo.x34_contactDamageInfo; @@ -67,7 +68,6 @@ x3fc_flavor(flavor) x4fc_ = pInfo.x108_; x508_colliderType = colliderType; x50c_thermalMag = actorParms.GetThermalMag(); - x510_.reset(new CVertexMorphEffect); x514_ = pInfo.x110_particle1Scale; x540_ = pInfo.x124_particle2Scale; @@ -84,7 +84,7 @@ x3fc_flavor(flavor) x404_contactDamage.SetRadius(0.f); xe6_29_renderParticleDBInside = false; - x402_27_ = x64_modelData->HasModel(CModelData::EWhichModel::XRay); + x402_27_ = !x64_modelData->HasModel(CModelData::EWhichModel::XRay); BuildBodyController(bodyType); } @@ -101,7 +101,7 @@ void CPatterned::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CState { case EScriptObjectMessage::Registered: { - if (x508_colliderType == EColliderType::Zero) + if (x508_colliderType != EColliderType::One) { CMaterialList include = GetMaterialFilter().GetIncludeList(); CMaterialList exclude = GetMaterialFilter().GetExcludeList(); @@ -112,7 +112,10 @@ void CPatterned::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CState if (HasModelData() && GetModelData()->HasAnimData() && GetModelData()->GetAnimationData()->GetIceModel()) { - /* TODO Initialize CVertexMorphEffect located at 0x8007CC7C */ + const auto& baseAABB = GetBaseBoundingBox(); + float diagExtent = (baseAABB.max - baseAABB.min).magnitude() * 0.5f; + x510_vertexMorph = std::make_shared(zeus::CVector3f::skRight, + zeus::CVector3f{}, diagExtent, 0.f, *mgr.GetActiveRandom()); } xf8_25_angularEnabled = true; @@ -155,20 +158,21 @@ void CPatterned::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CState const CDamageInfo& info = proj->GetDamageInfo(); if (info.GetWeaponMode().GetType() == EWeaponType::Wave) { - if (x460_.x81_26_ && info.GetWeaponMode().IsComboed() && HealthInfo(mgr)) + if (x460_knockBackController.x81_26_ && info.GetWeaponMode().IsComboed() && HealthInfo(mgr)) { x401_31_ = true; KnockBack(GetTransform().frontVector(), mgr, info, EKnockBackType::One, false, info.GetKnockBackPower()); -// x460_.sub80233D30(2); + x460_knockBackController.DeferKnockBack(EWeaponType::Wave); } } else if (info.GetWeaponMode().GetType() == EWeaponType::Plasma) { - if (x460_.x81_27_ && info.GetWeaponMode().IsCharged() && HealthInfo(mgr)) + if (x460_knockBackController.x81_27_ && info.GetWeaponMode().IsCharged() && HealthInfo(mgr)) { - KnockBack(GetTransform().frontVector(), mgr, info, EKnockBackType::One, false, info.GetKnockBackPower()); - // x460_.sub80233D30(2); + KnockBack(GetTransform().frontVector(), mgr, info, EKnockBackType::One, + false, info.GetKnockBackPower()); + x460_knockBackController.DeferKnockBack(EWeaponType::Plasma); } } if (mgr.GetPlayer().GetUniqueId() == proj->GetOwnerId()) @@ -189,18 +193,24 @@ void CPatterned::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CState } } +void CPatterned::UpdateFrozenState(bool thawed) +{ + x402_31_thawed = thawed; + if (x403_24_keepThermalVisorState) + return; + xe6_27_thermalVisorFlags = thawed ? 2 : 1; +} + void CPatterned::Think(float dt, CStateManager& mgr) { if (!GetActive()) return; -#if 0 if (x402_30_) - sub80077854(x450_bodyController->GetPercentageFrozen() == 0.f); -#endif + UpdateFrozenState(x450_bodyController->GetPercentageFrozen() == 0.f); if (x64_modelData->GetAnimationData()->GetIceModel()) - x510_->Update(dt); + x510_vertexMorph->Update(dt); if (x402_26_) { @@ -209,7 +219,7 @@ void CPatterned::Think(float dt, CStateManager& mgr) x400_29_ = true; } - if (x400_25_ && !x400_28_ && x400_29_) + if (x400_25_alive && !x400_28_ && x400_29_) { if (x3e0_ > 0.f && x400_29_) { @@ -253,7 +263,7 @@ void CPatterned::Think(float dt, CStateManager& mgr) else x4f0_ = 0.f; - if (x460_.x81_26_ && x401_31_ && x402_24_) + if (x460_knockBackController.x81_26_ && x401_31_ && x402_24_) Shock(0.5f + mgr.GetActiveRandom()->Range(0.f, 0.5f), 0.2f); x402_24_ = x401_24_; @@ -261,7 +271,7 @@ void CPatterned::Think(float dt, CStateManager& mgr) if (x450_bodyController->IsElectrocuting()) { mgr.GetActorModelParticles()->StartElectric(*this); - if (x3f0_ > 0.f && x400_25_) + if (x3f0_ > 0.f && x400_25_alive) { CDamageInfo dInfo({EWeaponType::Wave}, x3f0_, 0.f, 0.f); mgr.ApplyDamage(kInvalidUniqueId, GetUniqueId(), kInvalidUniqueId, dInfo, @@ -279,7 +289,7 @@ void CPatterned::Think(float dt, CStateManager& mgr) if (x450_bodyController->IsOnFire()) { - if (x400_25_) + if (x400_25_alive) { mgr.GetActorModelParticles()->LightDudeOnFire(*this); CDamageInfo dInfo({EWeaponType::Wave}, x3f0_, 0.f, 0.f); @@ -300,10 +310,10 @@ void CPatterned::Think(float dt, CStateManager& mgr) if (x401_30_) { x401_30_ = false; - Death(mgr, GetTransform().frontVector(), EStateMsg::Twenty); + Death(GetTransform().frontVector(), mgr, EScriptObjectState::DeathRattle); } - float thinkDt = (x400_25_ ? dt : dt * sub80078a88()); + float thinkDt = (x400_25_alive ? dt : dt * sub80078a88()); x450_bodyController->Update(thinkDt, mgr); x450_bodyController->MultiplyPlaybackRate(x3b4_speed); @@ -317,7 +327,7 @@ void CPatterned::Think(float dt, CStateManager& mgr) ThinkAboutMove(thinkDt); - //x460_.sub80233b58(thinkDt, mgr, *this); + x460_knockBackController.Update(thinkDt, mgr, *this); x4e4_ = GetTranslation() + PredictMotion(thinkDt).x0_translation; x328_26_ = false; if (x420_curDamageTime > 0.f) @@ -352,7 +362,7 @@ void CPatterned::Think(float dt, CStateManager& mgr) void CPatterned::Touch(CActor& act, CStateManager& mgr) { - if (!x400_25_) + if (!x400_25_alive) return; if (TCastToPtr proj = act) @@ -397,6 +407,17 @@ zeus::CVector3f CPatterned::GetAimPosition(const urde::CStateManager& mgr, float return offset + GetBoundingBox().center(); } +void CPatterned::KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, const CDamageInfo& info, + EKnockBackType type, bool inDeferred, float magnitude) +{ + CHealthInfo* hInfo = HealthInfo(mgr); + if (!x401_27_ && !x401_28_ && hInfo) + { + x460_knockBackController.KnockBack(backVec, mgr, *this, info, type, magnitude); + /* TODO: Finish */ + } +} + void CPatterned::BuildBodyController(EBodyType bodyType) { if (x450_bodyController) @@ -406,7 +427,7 @@ void CPatterned::BuildBodyController(EBodyType bodyType) auto anim = x450_bodyController->GetPASDatabase().FindBestAnimation(CPASAnimParmData(24, CPASAnimParm::FromEnum(0)), -1); /* TODO: Double check this */ - x460_.x81_26_ = anim.first != 0.f; + x460_knockBackController.x81_26_ = anim.first != 0.f; } zeus::CVector3f CPatterned::GetGunEyePos() const diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index 691349a19..a4c197d88 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -8,6 +8,7 @@ #include "Particle/CElectricDescription.hpp" #include "TCastTo.hpp" #include "CDamageInfo.hpp" +#include "CKnockBackController.hpp" #ifndef DEFINE_PATTERNED #define DEFINE_PATTERNED(type) static constexpr ECharacter CharacterType = ECharacter::type; @@ -17,29 +18,6 @@ namespace urde { class CPatternedInfo; class CProjectileInfo; -class CPatternedUnknown2 -{ - friend class CPatterned; - u8 x80_ = 0; - union - { - struct - { - bool x81_24_ : 1; - bool x81_25_ : 1; - bool x81_26_ : 1; - bool x81_27_ : 1; - bool x81_28_ : 1; - bool x81_29_ : 1; - bool x81_30_ : 1; - bool x81_31_ : 1; - bool x82_24_ : 1; - bool x82_25_ : 1; - bool x82_26_ : 1; - }; - u32 dummy = 0; - }; -}; class CPatterned : public CAi { @@ -173,7 +151,7 @@ protected: struct { bool x400_24_ : 1; - bool x400_25_ : 1; // t + bool x400_25_alive : 1; // t bool x400_26_ : 1; bool x400_27_ : 1; bool x400_28_ : 1; @@ -195,8 +173,8 @@ protected: bool x402_28_ : 1; bool x402_29_ : 1; // t bool x402_30_ : 1; - bool x402_31_ : 1; - bool x403_24_ : 1; + bool x402_31_thawed : 1; + bool x403_24_keepThermalVisorState : 1; bool x403_25_ : 1; // t bool x403_26_ : 1; // t }; @@ -216,7 +194,7 @@ protected: u32 x454_deathSfx; u32 x458_iceShatterSfx; - CPatternedUnknown2 x460_; + CKnockBackController x460_knockBackController; zeus::CVector3f x4e4_; float x4f0_ = 0.f; float x4f4_; @@ -226,18 +204,19 @@ protected: float x504_damageDur = 0.f; EColliderType x508_colliderType; float x50c_thermalMag; - std::unique_ptr x510_; + std::shared_ptr x510_vertexMorph; zeus::CVector3f x514_; std::experimental::optional> x520_; std::experimental::optional> x530_; zeus::CVector3f x540_; std::experimental::optional> x54c_; zeus::CVector3f x55c_; + void UpdateFrozenState(bool thawed); public: CPatterned(ECharacter character, TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pinfo, CPatterned::EMovementType movement, EColliderType collider, EBodyType body, - const CActorParameters& params, int variant); + const CActorParameters& params, EKnockBackVariant kbVariant); void Accept(IVisitor&); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); @@ -255,8 +234,9 @@ public: zeus::CVector3f GetAimPosition(const CStateManager& mgr, float) const; - void Death(CStateManager&, const zeus::CVector3f&, EStateMsg) {} - void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, EKnockBackType, bool, float) {} + void Death(const zeus::CVector3f&, CStateManager&, EScriptObjectState) {} + void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, + EKnockBackType type, bool inDeferred, float magnitude); void TakeDamage(const zeus::CVector3f&, float) { x428_ = 0.33f;} bool FixedRandom(CStateManager&, float) { return x330_stateMachineState.GetRandom() < x330_stateMachineState.x14_; } bool Random(CStateManager&, float dt) { return x330_stateMachineState.GetRandom() < dt; } @@ -279,6 +259,7 @@ public: virtual TLockedToken& GetX520() { return x520_.value(); } float GetDamageDuration() const { return x504_damageDur; } zeus::CVector3f GetGunEyePos() const; + bool IsAlive() const { return x400_25_alive; } void BuildBodyController(EBodyType); const CBodyController* GetBodyController() const { return x450_bodyController.get(); } diff --git a/Runtime/World/CWallWalker.cpp b/Runtime/World/CWallWalker.cpp index 2c87aaa87..231d19ef5 100644 --- a/Runtime/World/CWallWalker.cpp +++ b/Runtime/World/CWallWalker.cpp @@ -10,7 +10,7 @@ CWallWalker::CWallWalker(ECharacter chr, TUniqueId uid, std::string_view name, E const CEntityInfo& eInfo, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, EMovementType mType, EColliderType colType, EBodyType bType, const CActorParameters& aParms, float f1, float f2, - s32 w1, float f3, u32 w2, float f4, bool b1) + EKnockBackVariant w1, float f3, u32 w2, float f4, bool b1) : CPatterned(chr, uid, name, flavType, eInfo, xf, std::move(mData), pInfo, mType, colType, bType, aParms, w1) , x590_colSphere(zeus::CSphere(zeus::CVector3f::skZero, pInfo.GetHalfExtent()), x68_material) , x5b0_(f1) diff --git a/Runtime/World/CWallWalker.hpp b/Runtime/World/CWallWalker.hpp index 0c61af5c0..ffcd664be 100644 --- a/Runtime/World/CWallWalker.hpp +++ b/Runtime/World/CWallWalker.hpp @@ -32,7 +32,7 @@ protected: public: CWallWalker(ECharacter, TUniqueId, std::string_view, EFlavorType, const CEntityInfo&, const zeus::CTransform&, CModelData&&, const CPatternedInfo&, EMovementType, EColliderType, EBodyType, - const CActorParameters&, float, float, s32, float, u32, float, bool); + const CActorParameters&, float, float, EKnockBackVariant, float, u32, float, bool); void PreThink(float, CStateManager&); void Think(float, CStateManager&);