From 02d54fd5cad926cb5749fd961aeb6a9eb0b6d8fc Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sun, 16 Sep 2018 16:22:35 -0700 Subject: [PATCH] Initial CParasite implementation --- Runtime/CStateManager.cpp | 2 +- Runtime/Character/CAnimData.cpp | 4 +- Runtime/Character/CAnimData.hpp | 4 +- Runtime/Character/CBodyController.hpp | 2 + Runtime/Character/CCharacterInfo.cpp | 17 +- Runtime/Character/CCharacterInfo.hpp | 4 +- Runtime/Character/CSteeringBehaviors.cpp | 11 + Runtime/Character/CSteeringBehaviors.hpp | 1 + Runtime/MP1/World/CParasite.cpp | 269 ++++++++++++++++++++++- Runtime/MP1/World/CParasite.hpp | 128 ++++++++--- Runtime/MP1/World/CSeedling.cpp | 5 +- Runtime/Weapon/CBeamProjectile.cpp | 2 + Runtime/World/CPatterned.cpp | 6 +- Runtime/World/CPatterned.hpp | 8 +- Runtime/World/CPatternedInfo.hpp | 3 + Runtime/World/CPhysicsActor.cpp | 19 +- Runtime/World/CScriptWaypoint.hpp | 1 + Runtime/World/CWallWalker.cpp | 110 ++++++++- Runtime/World/CWallWalker.hpp | 30 ++- Runtime/World/ScriptLoader.cpp | 16 +- 20 files changed, 564 insertions(+), 78 deletions(-) diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index c9417623b..7c5dca6fe 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -1734,7 +1734,7 @@ bool CStateManager::ApplyLocalDamage(const zeus::CVector3f& vec1, const zeus::CV hInfo->SetHP(newHp); bool significant = std::fabs(newHp - hInfo->GetHP()) >= 0.00001; - if (player) + if (player && GetPlayerState()->CanTakeDamage()) { player->TakeDamage(significant, vec1, mulDam, weapMode.GetType(), *this); if (newHp <= 0.f) diff --git a/Runtime/Character/CAnimData.cpp b/Runtime/Character/CAnimData.cpp index 216940639..50906b7da 100644 --- a/Runtime/Character/CAnimData.cpp +++ b/Runtime/Character/CAnimData.cpp @@ -237,7 +237,7 @@ bool CAnimData::IsAdditiveAnimationActive(u32 idx) const return search->second.IsActive(); } -void CAnimData::DelAdditiveAnimation(u32 idx) +void CAnimData::DelAdditiveAnimation(s32 idx) { u32 animIdx = xc_charInfo.GetAnimationIndex(idx); for (std::pair& anim : x434_additiveAnims) @@ -252,7 +252,7 @@ void CAnimData::DelAdditiveAnimation(u32 idx) } } -void CAnimData::AddAdditiveAnimation(u32 idx, float weight, bool active, bool fadeOut) +void CAnimData::AddAdditiveAnimation(s32 idx, float weight, bool active, bool fadeOut) { u32 animIdx = xc_charInfo.GetAnimationIndex(idx); for (std::pair& anim : x434_additiveAnims) diff --git a/Runtime/Character/CAnimData.hpp b/Runtime/Character/CAnimData.hpp index 5c7a675a3..49d656946 100644 --- a/Runtime/Character/CAnimData.hpp +++ b/Runtime/Character/CAnimData.hpp @@ -176,8 +176,8 @@ public: const std::shared_ptr& GetRootAnimationTree() const { return x1f8_animRoot; } const std::shared_ptr& GetAdditiveAnimationTree(u32) const; bool IsAdditiveAnimationActive(u32) const; - void DelAdditiveAnimation(u32); - void AddAdditiveAnimation(u32, float, bool, bool); + void DelAdditiveAnimation(s32); + void AddAdditiveAnimation(s32, float, bool, bool); float GetAdditiveAnimationWeight(u32 idx) const; std::shared_ptr GetAnimationManager(); const CCharacterInfo& GetCharacterInfo() const { return xc_charInfo; } diff --git a/Runtime/Character/CBodyController.hpp b/Runtime/Character/CBodyController.hpp index 60137f40e..2b5612c5c 100644 --- a/Runtime/Character/CBodyController.hpp +++ b/Runtime/Character/CBodyController.hpp @@ -63,6 +63,7 @@ public: const CBodyStateInfo& GetBodyStateInfo() const { return x2a4_bodyStateInfo; } CBodyStateInfo& BodyStateInfo() { return x2a4_bodyStateInfo; } float GetTurnSpeed() const { return x2fc_turnSpeed; } + void SetLocomotionType(pas::ELocomotionType type) { x2ec_locomotionType = type; } pas::ELocomotionType GetLocomotionType() const { return x2ec_locomotionType; } CActor& GetOwner() const { return x0_actor; } bool IsAnimationOver() const { return x300_24_animationOver; } @@ -106,6 +107,7 @@ public: EBodyType GetBodyType() const { return x2f4_bodyType; } bool HasBeenFrozen() const { return x300_27_hasBeenFrozen; } float GetRestrictedFlyerMoveSpeed() const { return x330_restrictedFlyerMoveSpeed; } + bool GetActive() const { return x300_25_active; } }; } diff --git a/Runtime/Character/CCharacterInfo.cpp b/Runtime/Character/CCharacterInfo.cpp index 31ad5fa5f..4c72fa0cb 100644 --- a/Runtime/Character/CCharacterInfo.cpp +++ b/Runtime/Character/CCharacterInfo.cpp @@ -29,15 +29,15 @@ CCharacterInfo::CParticleResData::CParticleResData(CInputStream& in, u16 tableCo } } -static std::vector>> +static std::vector>> MakeAnimInfoVector(CInputStream& in) { - std::vector>> ret; + std::vector>> ret; u32 animInfoCount = in.readUint32Big(); ret.reserve(animInfoCount); for (u32 i=0 ; i>> x20_animInfo; + std::vector>> x20_animInfo; CPASDatabase x30_pasDatabase; CParticleResData x44_partRes; u32 x84_unk; @@ -61,6 +61,8 @@ public: const CParticleResData& GetParticleResData() const { return x44_partRes; } s32 GetAnimationIndex(s32 idx) const { return xb0_animIdxs.at(idx); } const CPASDatabase& GetPASDatabase() const { return x30_pasDatabase; } + + const s32 GetAnimationIndex(std::string_view) const; }; } diff --git a/Runtime/Character/CSteeringBehaviors.cpp b/Runtime/Character/CSteeringBehaviors.cpp index 65971f3dc..2360a9532 100644 --- a/Runtime/Character/CSteeringBehaviors.cpp +++ b/Runtime/Character/CSteeringBehaviors.cpp @@ -35,4 +35,15 @@ CSteeringBehaviors::ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeu return usePos; } +bool CSteeringBehaviors::SolveQuadratic(float f30, float f31, float f3, float f4, float& out1, float& out2) +{ + float f1 = f31 * f31 - 4.f * f30 * f3; + if (f1 > FLT_EPSILON && std::fabs(f1) < FLT_EPSILON) + return false; + + out1 = -f31 + std::sqrt(f1) / 2.f * f30; + out2 = -f31 - std::sqrt(f1) / 2.f * f30; + return true; +} + } diff --git a/Runtime/Character/CSteeringBehaviors.hpp b/Runtime/Character/CSteeringBehaviors.hpp index 1eb442fc8..86a33bc86 100644 --- a/Runtime/Character/CSteeringBehaviors.hpp +++ b/Runtime/Character/CSteeringBehaviors.hpp @@ -13,6 +13,7 @@ class CSteeringBehaviors public: static zeus::CVector3f ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeus::CVector3f& vel, const zeus::CVector3f& orbitPoint, float dt, float preThinkDt); + static bool SolveQuadratic(float, float, float, float, float&, float&); }; } diff --git a/Runtime/MP1/World/CParasite.cpp b/Runtime/MP1/World/CParasite.cpp index 57b8683f1..799a6cc32 100644 --- a/Runtime/MP1/World/CParasite.cpp +++ b/Runtime/MP1/World/CParasite.cpp @@ -1,19 +1,270 @@ #include "CParasite.hpp" #include "Character/CModelData.hpp" -#include "TCastTo.hpp" #include "World/CActorParameters.hpp" #include "World/CPatternedInfo.hpp" +#include "World/CWorld.hpp" +#include "World/CGameArea.hpp" +#include "World/CPlayer.hpp" +#include "CStateManager.hpp" +#include "TCastTo.hpp" -namespace urde::MP1 { - -CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo &info, const zeus::CTransform &xf, - CModelData &&mData, const CPatternedInfo &pInfo, u32, float, float, float, float, float, float, float, float, - float, float, float, float, float, float, float, float, float, float, bool, u32, const CDamageVulnerability &, - const CParasiteInfo &, u16, u16, u16, u32, u32, float, const CActorParameters &aParams) - : CWallWalker(ECharacter::Parasite, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Ground, EColliderType::One, EBodyType::WallWalker, - aParams, -1, 0) +namespace urde::MP1 { + +const float CParasite::flt_805A8FB0 = 2.f * std::sqrt(2.5f / 24.525002f); +const float CParasite::skAttackVelocity = 15.f / 2.f * (std::sqrt(2.5f / 24.525002f)); +short CParasite::word_805A8FC0 = 0; +const float CParasite::flt_805A8FB8 = 2.f * std::sqrt(2.5f / 24.525002f); +const float CParasite::skRetreatVelocity = 3.f / 2.f * std::sqrt(2.5f / 24.525002f); + +CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo &info, + const zeus::CTransform &xf, CModelData &&mData, const CPatternedInfo &pInfo, EBodyType bodyType, + float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, + float f10, float f11, float f12, float f13, float f14, float f15, float f16, float f17, float f18, + 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) +, x64c_(dVuln) +, x6b4_(parInfo) +, x6d0_(f1) +, x6d4_(f3) +, x6dc_(f5) +, x6e0_(f6) +, x6e4_(f8) +, x6e8_(f9) +, x6ec_(f10) +, x6f0_(f11) +, x6f4_(f12) +, x6f8_(f13) +, x6fc_(f14) +, x700_(f15) +, x704_(f16) +, x708_(pInfo.GetHeight() * 0.5f) +, x710_(f18) +, x714_(f19) +, x73c_(CSfxManager::TranslateSFXID(sfxId1)) +, x73e_(CSfxManager::TranslateSFXID(sfxId2)) +, x740_(CSfxManager::TranslateSFXID(sfxId3)) +{ + x742_28_ = true; + x742_30_ = true; + + switch(x5d0_) + { + case 2: + //x460_.x81_25_ = false; + case 1: + //x460_.sub80233d64(false); + break; + case 3: + + default: + break; + } + if (x5d0_ == 1) + { + + } } void CParasite::Accept(IVisitor &visitor) { visitor.Visit(this); } + +void CParasite::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) +{ + CPatterned::AcceptScriptMsg(msg, uid, mgr); + if (msg == EScriptObjectMessage::Registered) + { + x450_bodyController->Activate(mgr); + /* TODO: Finish 8015A0E8*/ + } + else if (msg == EScriptObjectMessage::Deleted) + { + //mgr.xf54_.sub80125d88(GetUniqueId()); + if (x5d0_ != 3) + DestroyActorManager(mgr); + } + else if (msg == EScriptObjectMessage::Jumped && x742_25_) + { + UpdateJumpVelocity(); + x742_25_ = false; + } + else if (msg == EScriptObjectMessage::Activate) + { + x5d6_27_ = false; + if (x5d0_ != 0) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + } + else if (msg == EScriptObjectMessage::SuspendedMove) + { + } +} + +void CParasite::PreThink(float dt, CStateManager& mgr) +{ + CWallWalker::PreThink(dt, mgr); + x743_26_ = false; +} + +void CParasite::Think(float dt, CStateManager& mgr) +{ + if (!GetActive()) + return; + + ++x5d4_; + if (x5d0_ == 3) + UpdateCollisionActors(mgr); + + x5d6_26_ = false; + CGameArea* area = mgr.WorldNC()->GetArea(GetAreaIdAlways()); + + CGameArea::EOcclusionState r6 = CGameArea::EOcclusionState::Occluded; + if (area->IsPostConstructed()) + r6 = area->GetPostConstructed()->x10dc_occlusionState; + if (r6 != CGameArea::EOcclusionState::Visible) + x5d6_26_ = true; + + if (!x5d6_26_) + { + zeus::CVector3f plVec = mgr.GetPlayer().GetTranslation(); + float distance = (GetTranslation() - plVec).magnitude() ; + + if (distance > x5c4_) + { + CRayCastResult res = mgr.RayStaticIntersection(plVec, (GetTranslation() - plVec).normalized(), distance, + CMaterialFilter::skPassEverything); + if (res.IsValid()) + x5d6_26_ = true; + } + } + + if (x5d6_26_) + { + xf8_24_movable = x5d6_26_; + return; + } + + xf8_24_movable = !xf8_24_movable; + + if (!x5d6_27_) + { + if (x450_bodyController->IsFrozen()) + { + if ((GetTranslation() - x614_).magSquared() < 0.3f /* <- Used to be a static variable */ * dt) + x60c_ += dt; + else + x60c_ = 0.f; + + x614_ = GetTranslation(); + if (x608_ > 0.f) + x608_ -= dt; + else + x608_ = 0.f; + } + } + + if (x400_25_) + { + CPlayer* pl = mgr.Player(); + float radius; + if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && !x742_30_) + radius = x590_colSphere.GetSphere().radius; + else + radius = x708_; + + zeus::CAABox aabox{GetTranslation() - radius, GetTranslation() + radius}; + auto plBox = pl->GetTouchBounds(); + + if (plBox && plBox->intersects(aabox)) + { + if (!x742_30_) + { + x742_30_ = true; + x742_27_ = false; + } + + if (x420_curDamageTime <= 0.f) + { + mgr.ApplyDamage(GetUniqueId(), pl->GetUniqueId(), GetUniqueId(), GetContactDamage(), + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); + x420_curDamageTime = x424_damageWaitTime; + } + } + } + + CWallWalker::Think(dt, mgr); + + if (x5d6_27_) + return; + + if (x450_bodyController->IsFrozen()) + return; + + x3b4_speed = x604_; + if (x5d6_24_) + AlignToFloor(mgr, x590_colSphere.GetSphere().radius, GetTranslation() + 2.f * dt * x138_velocity, dt); + + x742_27_ = false; +} + +void CParasite::DestroyActorManager(CStateManager& mgr) +{ + //x620_->Destroy(mgr); +} + +void CParasite::UpdateJumpVelocity() +{ + x150_momentum.x = 0; + x150_momentum.y = 0; + x150_momentum.z = -GetWeight(); + zeus::CVector3f vec; + + if (!x742_30_) + { + vec = skAttackVelocity * GetTransform().frontVector(); + vec.z = 0.5f * skRetreatVelocity; + } + else + { + vec = skRetreatVelocity * GetTransform().frontVector(); + vec.z = 0.5f * skAttackVelocity; + } + + float f30 = x150_momentum.z / xe8_mass; + float f31 = x600_ - GetTranslation().z; + zeus::CVector3f vec2; + vec2.x = x5f8_ - GetTranslation().x; + vec2.y = x5fc_ * GetTranslation().y; + vec2.z = 0.f; + float f29 = vec2.magnitude(); + + if (f29 > FLT_EPSILON) + { + vec2 *= zeus::CVector3f{1.f / f29}; + float f28 = vec2.dot(vec); + if (f28 > FLT_EPSILON) + { + float f27 = 0.f; + bool isNeg = f31 < 0.f; + float out1, out2; + if (CSteeringBehaviors::SolveQuadratic(f30, vec.z, -f31, vec2.y, out1, out2)) + f27 = isNeg ? out1 : out2; + + if (!isNeg) + f27 = f27 * f29 / f28; + + if (f27 < 10.f) + { + vec = f29 / f27 * vec2; + vec.z = (0.5f * f30 * f27 + f31 / f27); + } + } + } + SetVelocityWR(vec); +} + +void CParasite::AlignToFloor(CStateManager&, float, const zeus::CVector3f&, float) +{ +} + } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CParasite.hpp b/Runtime/MP1/World/CParasite.hpp index 21ecc993f..1835d79fc 100644 --- a/Runtime/MP1/World/CParasite.hpp +++ b/Runtime/MP1/World/CParasite.hpp @@ -2,7 +2,7 @@ #define __URDE_MP1_CPARASITE_HPP__ #include "World/CWallWalker.hpp" - +#include "Collision/CCollisionActorManager.hpp" namespace urde { class CModelData; @@ -10,41 +10,109 @@ class CModelData; namespace urde::MP1 { -struct CParasiteInfo -{ - u32 x0_ = 0; - union - { - struct - { - bool x4_24_ : 1; bool x4_26_ : 1; - }; - u32 x4_dummy = 0; - }; - float x8_ = 0.f; - float xc_ = 0.f; - float x10_ = 0.f; - float x14_ = 0.f; - union - { - struct - { - bool x18_24_ : 1; - }; - u32 x18_dummy = 0; - }; -}; - class CParasite : public CWallWalker { + class CRepulsor + { + }; + static const float flt_805A8FB0; + static const float skAttackVelocity; + static short word_805A8FC0; + static const float flt_805A8FB8; + static const float skRetreatVelocity; + std::vector x5d8_doorRepulsors; + s32 x5e8_ = -1; + float x5ec_ = 0.f; + float x5f0_ = 0.f; + float x5f4_ = 0.f; + float x5f8_ = 0.f; + float x5fc_ = 0.f; + float x600_ = 0.f; + float x604_ = 1.f; + float x608_ = 0.f; + float x60c_ = 0.f; + zeus::CVector3f x614_; + std::unique_ptr x620_ = 0; + u32 x624_ = 0; + float x628_ = 0.f; + float x62c_ = 0.f; + float x630_ = 0.f; + float x634_ = 0.f; + float x638_ = 0.f; + float x640_ = 0.f; + float x644_ = 0.f; + float x648_ = 0.f; + CDamageVulnerability x64c_; + CDamageInfo x6b4_; + float x6d0_; + float x6d4_; + float x6dc_; + float x6e0_; + float x6e4_; + float x6e8_; + float x6ec_; + float x6f0_; + float x6f4_; + float x6f8_; + float x6fc_; + float x700_; + float x704_; + float x708_; + float x710_; + float x714_; + float x718_ = 0.f; + float x71c_ = 0.f; + float x720_ = 0.f; + float x724_ = 0.f; + float x728_ = 0.f; + float x72c_ = 0.f; + float x730_ = 0.f; + float x734_ = 0.f; + float x738_ = 0.f; + s16 x73c_; + s16 x73e_; + s16 x740_; + union + { + struct + { + bool x742_24_ : 1; + bool x742_25_ : 1; + bool x742_26_ : 1; + bool x742_27_ : 1; + bool x742_28_ : 1; + bool x742_29_ : 1; + bool x742_30_ : 1; + bool x742_31_ : 1; + bool x743_24_ : 1; + bool x743_25_ : 1; + bool x743_26_ : 1; + bool x743_27_ : 1; + }; + u16 _dummy = 0; + }; public: DEFINE_PATTERNED(Parasite) - CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, const zeus::CTransform& xf, - CModelData&& mData, const CPatternedInfo&, u32, float, float, float, float, float, float, float, float, float, - float, float, float, float, float, float, float, float, float, bool, u32, const CDamageVulnerability&, const CParasiteInfo&, u16, u16, - u16, u32, u32, float, const CActorParameters&); + CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, + const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo&, EBodyType, float, float, float, + float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, + bool, u32, const CDamageVulnerability&, const CDamageInfo&, u16, u16, u16, u32, u32, float, + const CActorParameters&); void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void PreThink(float, CStateManager&); + void Think(float dt, CStateManager& mgr); + void DestroyActorManager(CStateManager& mgr); + void UpdateJumpVelocity(); + void UpdateCollisionActors(CStateManager&) {} + CDamageInfo GetContactDamage() const + { + if (x5d0_ == 1 && x743_24_) + return x6b4_; + return CPatterned::GetContactDamage(); + } + void AlignToFloor(CStateManager&, float, const zeus::CVector3f&, float); }; } #endif // __URDE_MP1_CPARASITE_HPP__ diff --git a/Runtime/MP1/World/CSeedling.cpp b/Runtime/MP1/World/CSeedling.cpp index 52dc9fe89..35be285da 100644 --- a/Runtime/MP1/World/CSeedling.cpp +++ b/Runtime/MP1/World/CSeedling.cpp @@ -8,8 +8,9 @@ namespace MP1 CSeedling::CSeedling(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, - CAssetId, CAssetId, const CDamageInfo&, const CDamageInfo&, float, float, float, float) -: CWallWalker(ECharacter::Seedling, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Ground, EColliderType::Zero, EBodyType::WallWalker, actParms, 0, 4) + 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) { } diff --git a/Runtime/Weapon/CBeamProjectile.cpp b/Runtime/Weapon/CBeamProjectile.cpp index acfb0740f..2025d52b5 100644 --- a/Runtime/Weapon/CBeamProjectile.cpp +++ b/Runtime/Weapon/CBeamProjectile.cpp @@ -15,9 +15,11 @@ CBeamProjectile::CBeamProjectile(const TToken& wDesc, std::s , x2f0_(1.f / x2ec_) , x2f4_(f1) , x300_(b1 == false ? x2ec_ : 0.f) +, x308_(f2) , x464_24_(b1) , x464_25_(false) { + } std::experimental::optional CBeamProjectile::GetTouchBounds() const diff --git a/Runtime/World/CPatterned.cpp b/Runtime/World/CPatterned.cpp index eaf250991..b2c8322a9 100644 --- a/Runtime/World/CPatterned.cpp +++ b/Runtime/World/CPatterned.cpp @@ -320,8 +320,8 @@ void CPatterned::Think(float dt, CStateManager& mgr) //x460_.sub80233b58(thinkDt, mgr, *this); x4e4_ = GetTranslation() + PredictMotion(thinkDt).x0_translation; x328_26_ = false; - if (x420_ > 0.f) - x420_ -= dt; + if (x420_curDamageTime > 0.f) + x420_curDamageTime -= dt; if (x401_28_ && x3f4_ > dt) x3f4_ -= dt; @@ -527,7 +527,7 @@ void CPatterned::ThinkAboutMove(float dt) if (!x401_26_ && doMove) { const CBodyState* state = x450_bodyController->GetBodyStateInfo().GetCurrentState(); - if (state->ApplyAnimationDeltas() && !zeus::close_enough(x2e0_ - GetTranslation(), {})) + if (state->ApplyAnimationDeltas() && !zeus::close_enough(x2e0_destPos - GetTranslation(), {})) MoveToOR((x64_modelData->GetScale() * x434_posDelta) * x55c_, dt); } diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index 961ec2d56..5cc704289 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -107,7 +107,7 @@ public: protected: u32 x2d8_ = -1; TUniqueId x2dc_ = kInvalidUniqueId; - zeus::CVector3f x2e0_; + zeus::CVector3f x2e0_destPos; zeus::CVector3f x2ec_; float x2f8_ = 0.f; float x2fc_minAttackRange; @@ -205,7 +205,7 @@ protected: }; CDamageInfo x404_contactDamage; - float x420_ = 0.f; + float x420_curDamageTime = 0.f; float x424_damageWaitTime; float x428_ = -1.f; zeus::CColor x42c_ = zeus::CColor::skBlack; @@ -242,6 +242,7 @@ public: void Accept(IVisitor&); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void PreThink(float, CStateManager& mgr) { CEntity::Think(x500_, mgr); } void Think(float, CStateManager&); void PreRender(CStateManager&, const zeus::CFrustum&); @@ -270,7 +271,7 @@ public: virtual void Shock(float, float) {} virtual void ThinkAboutMove(float); virtual void GetSearchPath() {} - virtual CDamageInfo GetContactDamage() { return x404_contactDamage; } + virtual CDamageInfo GetContactDamage() const { return x404_contactDamage; } virtual u8 GetModelAlphau8(const CStateManager&) const { return u8(x42c_.a * 255);} virtual bool IsOnGround() const { return x328_27_onGround; } virtual float GetGravityConstant() const { return 24.525002f; } @@ -286,6 +287,7 @@ public: void SetupPlayerCollision(bool); + void SetDestPos(const zeus::CVector3f& pos) { x2e0_destPos = pos; } void sub8007a68c(float, CStateManager&) {} float sub80078a88(); void sub8007a5b8(float) {} diff --git a/Runtime/World/CPatternedInfo.hpp b/Runtime/World/CPatternedInfo.hpp index e20f3c2f5..b5d0955ab 100644 --- a/Runtime/World/CPatternedInfo.hpp +++ b/Runtime/World/CPatternedInfo.hpp @@ -62,6 +62,9 @@ public: CAnimationParameters& GetAnimationParameters() { return xec_animParams; } const CAnimationParameters& GetAnimationParameters() const { return xec_animParams; } + + float GetHalfExtent() const { return xc4_halfExtent; } + float GetHeight() const { return xc8_height; } }; } diff --git a/Runtime/World/CPhysicsActor.cpp b/Runtime/World/CPhysicsActor.cpp index e86602329..d68e74722 100644 --- a/Runtime/World/CPhysicsActor.cpp +++ b/Runtime/World/CPhysicsActor.cpp @@ -247,17 +247,14 @@ void CPhysicsActor::ComputeDerivedQuantities() bool CPhysicsActor::WillMove(const CStateManager&) { - if (!zeus::close_enough(zeus::CVector3f::skZero, x138_velocity) || - !zeus::close_enough(zeus::CVector3f::skZero, x168_impulse) || - !zeus::close_enough(zeus::CVector3f::skZero, x174_torque) || - !zeus::close_enough(zeus::CVector3f::skZero, x18c_moveImpulse) || - !zeus::close_enough(zeus::CVector3f::skZero, x144_angularVelocity) || - !zeus::close_enough(zeus::CVector3f::skZero, x180_angularImpulse) || - !zeus::close_enough(zeus::CVector3f::skZero, x198_moveAngularImpulse) || - !zeus::close_enough(zeus::CVector3f::skZero, GetTotalForcesWR())) - return true; - - return false; + return !zeus::close_enough(zeus::CVector3f::skZero, x138_velocity) || + !zeus::close_enough(zeus::CVector3f::skZero, x168_impulse) || + !zeus::close_enough(zeus::CVector3f::skZero, x174_torque) || + !zeus::close_enough(zeus::CVector3f::skZero, x18c_moveImpulse) || + !zeus::close_enough(zeus::CVector3f::skZero, x144_angularVelocity) || + !zeus::close_enough(zeus::CVector3f::skZero, x180_angularImpulse) || + !zeus::close_enough(zeus::CVector3f::skZero, x198_moveAngularImpulse) || + !zeus::close_enough(zeus::CVector3f::skZero, GetTotalForcesWR()); } void CPhysicsActor::SetPhysicsState(const CPhysicsState& state) diff --git a/Runtime/World/CScriptWaypoint.hpp b/Runtime/World/CScriptWaypoint.hpp index 1c930b398..441a06a0a 100644 --- a/Runtime/World/CScriptWaypoint.hpp +++ b/Runtime/World/CScriptWaypoint.hpp @@ -28,6 +28,7 @@ public: TUniqueId FollowWaypoint(CStateManager& mgr) const; TUniqueId NextWaypoint(CStateManager& mgr) const; float GetSpeed() const { return xe8_speed; } + float GetF0() const { return xf0_; } }; } diff --git a/Runtime/World/CWallWalker.cpp b/Runtime/World/CWallWalker.cpp index 250d73423..2c87aaa87 100644 --- a/Runtime/World/CWallWalker.cpp +++ b/Runtime/World/CWallWalker.cpp @@ -1,11 +1,115 @@ #include "CWallWalker.hpp" +#include "CPatternedInfo.hpp" +#include "CStateManager.hpp" +#include "TCastTo.hpp" +#include "CScriptWaypoint.hpp" namespace urde { CWallWalker::CWallWalker(ECharacter chr, TUniqueId uid, std::string_view name, EFlavorType flavType, const CEntityInfo& eInfo, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, EMovementType mType, - EColliderType colType, EBodyType bType, const CActorParameters& aParms, s32 w1, u32 w2) - : CPatterned(chr, uid, name, flavType, eInfo, xf, std::move(mData), pInfo, mType, colType, bType, aParms, w1) -{} + EColliderType colType, EBodyType bType, const CActorParameters& aParms, float f1, float f2, + s32 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) +, x5b4_(f2) +, x5c0_(f3) +, x5c4_(f4) +, x5cc_bendingHackAnim(GetModelData()->GetAnimationData()->GetCharacterInfo().GetAnimationIndex("BendingAnimationHack"sv)) +, x5d0_(w2) +, x5d6_24_(false) +, x5d6_25_(false) +, x5d6_26_(false) +, x5d6_27_(b1) +, x5d6_28_addBendingWeight(true) +, x5d6_29_applyBendingHack(false) +{ +} + +void CWallWalker::PreThink(float dt, CStateManager& mgr) +{ + CPatterned::PreThink(dt, mgr); + if (!GetActive() || x5d6_26_ || x5bc_ > 0.f || x5d6_27_ || x450_bodyController->IsFrozen() || !x5d6_24_) + return; + + zeus::CQuaternion quat(GetTransform().buildMatrix3f()); + AddMotionState(PredictMotion(dt)); + zeus::CQuaternion quat2(GetTransform().buildMatrix3f()); + ClearForcesAndTorques(); + if (x5d6_25_) + { + zeus::CPlane plane = x568_.GetPlane(); + const float futureDt = (10.f * dt); + SetTranslation(GetTranslation() * (1.f - futureDt) + + (((GetTranslation() - ((plane.vec.dot(GetTranslation())) - plane.d) - + x590_colSphere.GetSphere().radius - 0.1f) * plane.vec) * futureDt)); + + } + else + MoveCollisionPrimitive(zeus::CVector3f::skZero); + +} + +void CWallWalker::Think(float dt, CStateManager& mgr) +{ + if (!x450_bodyController->GetActive()) + x450_bodyController->Activate(mgr); + CPatterned::Think(dt, mgr); + + if (x5cc_bendingHackAnim == -1) + return; + + if (x5d6_28_addBendingWeight) + { + if (x5c8_bendingHackWeight < 1.f) + { + x5c8_bendingHackWeight += (dt * x138_velocity.magnitude()) / 0.6f; + if (x5c8_bendingHackWeight >= 1.f) + x5c8_bendingHackWeight = 1.f; + } + } + else if (x5c8_bendingHackWeight > 0.f) + { + x5c8_bendingHackWeight -= (dt * x138_velocity.magnitude()) / 1.5f; + if (x5c8_bendingHackWeight < 0.f) + x5c8_bendingHackWeight = 0.f; + } + + if (x5c8_bendingHackWeight <= 0.f && !x5d6_29_applyBendingHack) + return; + + if (x5c8_bendingHackWeight > 0.0001f) + { + ModelData()->AnimationData()->AddAdditiveAnimation(x5cc_bendingHackAnim, x5c8_bendingHackWeight, true, false); + x5d6_29_applyBendingHack = true; + } + else + { + ModelData()->AnimationData()->DelAdditiveAnimation(x5cc_bendingHackAnim); + x5d6_29_applyBendingHack = false; + } +} + +void CWallWalker::UpdateWPDestination(CStateManager& mgr) +{ + if (TCastToPtr wp = mgr.ObjectById(x2dc_)) + { + zeus::CVector3f wpPos = wp->GetTranslation(); + if ((wpPos - GetTranslation()).magSquared() < x5c0_ * x5c0_) + { + x2dc_ = wp->NextWaypoint(mgr); + if (std::fabs(wp->GetF0()) > 0.00001f) + { + x5bc_ = wp->GetF0(); + if (x5d0_ == 0) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived); + } + } + + SetDestPos(wpPos); + } +} } diff --git a/Runtime/World/CWallWalker.hpp b/Runtime/World/CWallWalker.hpp index 7146bcf46..38f3b7373 100644 --- a/Runtime/World/CWallWalker.hpp +++ b/Runtime/World/CWallWalker.hpp @@ -2,15 +2,43 @@ #define __URDE_CWALLWALKER_HPP__ #include "CPatterned.hpp" +#include "Collision/CCollisionSurface.hpp" +#include "Collision/CCollidableSphere.hpp" namespace urde { class CWallWalker : public CPatterned { +protected: + CCollisionSurface x568_ = CCollisionSurface(zeus::CVector3f(), + zeus::CVector3f::skForward, + zeus::CVector3f::skRight, -1); + CCollidableSphere x590_colSphere; + float x5b0_; + float x5b4_; + float x5b8_ = 0.f; + float x5bc_ = 0.f; + float x5c0_; + float x5c4_; + float x5c8_bendingHackWeight = 0.f; + s32 x5cc_bendingHackAnim; + u32 x5d0_; + s16 x5d4_ = 0; + bool x5d6_24_ : 1; + bool x5d6_25_ : 1; + bool x5d6_26_ : 1; + bool x5d6_27_ : 1; + bool x5d6_28_addBendingWeight : 1; + bool x5d6_29_applyBendingHack : 1; public: CWallWalker(ECharacter, TUniqueId, std::string_view, EFlavorType, const CEntityInfo&, const zeus::CTransform&, CModelData&&, const CPatternedInfo&, EMovementType, EColliderType, EBodyType, - const CActorParameters&, s32, u32); + const CActorParameters&, float, float, s32, float, u32, float, bool); + + void PreThink(float, CStateManager&); + void Think(float, CStateManager&); + const CCollisionPrimitive* GetCollisionPrimitive() const { return &x590_colSphere; } + void UpdateWPDestination(CStateManager&); }; } #endif // __URDE_CWALLWALKER_HPP__ diff --git a/Runtime/World/ScriptLoader.cpp b/Runtime/World/ScriptLoader.cpp index ff2367e5a..1c5e8aeea 100644 --- a/Runtime/World/ScriptLoader.cpp +++ b/Runtime/World/ScriptLoader.cpp @@ -1652,10 +1652,10 @@ CEntity* ScriptLoader::LoadParasite(CStateManager& mgr, CInputStream& in, int pr const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); CModelData mData( CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true)); - return new MP1::CParasite(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, 6, f1, f2, f3, - f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, 0.f, b1, 0, - CDamageVulnerability::NormalVulnerabilty(), MP1::CParasiteInfo(), -1, -1, -1, -1, -1, 0.f, - aParms); + return new MP1::CParasite(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, + EBodyType::WallWalker, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, + f16, f17, 0.f, b1, 0, CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(), + -1, -1, -1, -1, -1, 0.f, aParms); } CEntity* ScriptLoader::LoadPlayerHint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) @@ -2584,9 +2584,11 @@ CEntity* ScriptLoader::LoadGeemer(CStateManager& mgr, CInputStream& in, int prop CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - return new MP1::CParasite(mgr.AllocateUniqueId(), actHead.x0_name, CPatterned::EFlavorType::Zero, info, actHead.x10_transform, - std::move(mData), pInfo, 6, 0.f, f1, f2, f3, f4, 0.2f, 0.4f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, f7, 0.f, 0.f, - f5, f6, false, 2, CDamageVulnerability::NormalVulnerabilty(), MP1::CParasiteInfo(), sId1, sId2, sId3, -1, -1, 0.f, actParms); + return new MP1::CParasite(mgr.AllocateUniqueId(), actHead.x0_name, CPatterned::EFlavorType::Zero, info, + actHead.x10_transform, std::move(mData), pInfo, EBodyType::WallWalker, 0.f, f1, f2, f3, f4, 0.2f, 0.4f, 0.f, + 0.f, 0.f, 0.f, 0.f, 1.f, f7, 0.f, 0.f, f5, f6, false, 2, + CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(), sId1, sId2, sId3, -1, + -1, 0.f, actParms); } CEntity* ScriptLoader::LoadSpindleCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)