diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index 7d7901eba..d79a994ea 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -876,7 +876,7 @@ void CStateManager::DrawWorld() const { void CStateManager::DrawActorCubeFaces(CActor& actor, int& cubeInst) const { if (!actor.m_reflectionCube || - (!TCastToPtr(actor) && (!actor.GetActive() || !actor.IsDrawEnabled() || actor.xe4_30_outOfFrustum))) + (!TCastToPtr(actor) && (!actor.GetActive() || !actor.IsDrawEnabled() || actor.xe4_30_outOfFrustum))) return; TAreaId visAreaId = actor.GetAreaIdAlways(); @@ -895,23 +895,24 @@ void CStateManager::DrawActorCubeFaces(CActor& actor, int& cubeInst) const { } for (int f = 0; f < 6; ++f) { - SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CStateManager::DrawActorCubeFaces [{}] {} {} {}"), - f, actor.GetUniqueId(), actor.GetEditorId(), actor.GetName()).c_str(), zeus::skOrange); + SCOPED_GRAPHICS_DEBUG_GROUP(fmt::format(fmt("CStateManager::DrawActorCubeFaces [{}] {} {} {}"), f, + actor.GetUniqueId(), actor.GetEditorId(), actor.GetName()) + .c_str(), + zeus::skOrange); CGraphics::g_BooMainCommandQueue->setRenderTarget(actor.m_reflectionCube, f); SetupViewForCubeFaceDraw(actor.GetRenderBounds().center(), f); CGraphics::g_BooMainCommandQueue->clearTarget(); - std::sort(std::begin(areaArr), std::begin(areaArr) + areaCount, - [visAreaId](const CGameArea* a, const CGameArea* b) { - if (a->x4_selfIdx == b->x4_selfIdx) - return false; - if (visAreaId == a->x4_selfIdx) - return false; - if (visAreaId == b->x4_selfIdx) - return true; - return CGraphics::g_ViewPoint.dot(a->GetAABB().center()) > - CGraphics::g_ViewPoint.dot(b->GetAABB().center()); - }); + std::sort( + std::begin(areaArr), std::begin(areaArr) + areaCount, [visAreaId](const CGameArea* a, const CGameArea* b) { + if (a->x4_selfIdx == b->x4_selfIdx) + return false; + if (visAreaId == a->x4_selfIdx) + return false; + if (visAreaId == b->x4_selfIdx) + return true; + return CGraphics::g_ViewPoint.dot(a->GetAABB().center()) > CGraphics::g_ViewPoint.dot(b->GetAABB().center()); + }); int pvsCount = 0; CPVSVisSet pvsArr[10]; @@ -1656,8 +1657,7 @@ void CStateManager::TestBombHittingWater(const CActor& damager, const zeus::CVec float bombMag = powerBomb ? 2.f : 1.f; if (delta <= -bombMag || delta >= 0.f) return; - CRayCastResult res = - RayStaticIntersection(pos, zeus::skDown, -delta, CMaterialFilter::skPassEverything); + CRayCastResult res = RayStaticIntersection(pos, zeus::skDown, -delta, CMaterialFilter::skPassEverything); if (res.IsInvalid() && x87c_fluidPlaneManager->GetLastRippleDeltaTime(damager.GetUniqueId()) >= 0.15f) { // Not blocked by static geometry float mag = 0.6f * bombMag + 0.4f * bombMag * std::sin(2.f * M_PIF * -delta / bombMag * 0.25f); diff --git a/Runtime/Collision/CCollidableAABox.hpp b/Runtime/Collision/CCollidableAABox.hpp index 4164980ab..f9defa46d 100644 --- a/Runtime/Collision/CCollidableAABox.hpp +++ b/Runtime/Collision/CCollidableAABox.hpp @@ -26,6 +26,7 @@ public: CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const override; const zeus::CAABox& GetBox() const { return x10_aabox; } zeus::CAABox& Box() { return x10_aabox; } + void SetBox(const zeus::CAABox& box) { x10_aabox = box; } static const CCollisionPrimitive::Type& GetType(); static void SetStaticTableIndex(u32 index); diff --git a/Runtime/Collision/CCollisionResponseData.cpp b/Runtime/Collision/CCollisionResponseData.cpp index a84c45abd..50679bc57 100644 --- a/Runtime/Collision/CCollisionResponseData.cpp +++ b/Runtime/Collision/CCollisionResponseData.cpp @@ -223,7 +223,8 @@ bool CCollisionResponseData::ResponseTypeIsEnemySpecial(EWeaponCollisionResponse } bool CCollisionResponseData::ResponseTypeIsEnemyShielded(EWeaponCollisionResponseTypes type) { - return (type >= EWeaponCollisionResponseTypes::Unknown69 && type <= EWeaponCollisionResponseTypes::AtomicAlphaReflect); + return (type >= EWeaponCollisionResponseTypes::Unknown69 && + type <= EWeaponCollisionResponseTypes::AtomicAlphaReflect); } FourCC CCollisionResponseData::UncookedResType() { return SBIG('CRSM'); } diff --git a/Runtime/MP1/World/CMetroidBeta.cpp b/Runtime/MP1/World/CMetroidBeta.cpp index 1b585e14e..dcbf1c0ab 100644 --- a/Runtime/MP1/World/CMetroidBeta.cpp +++ b/Runtime/MP1/World/CMetroidBeta.cpp @@ -1,5 +1,16 @@ #include "CMetroidBeta.hpp" +#include "CSimplePool.hpp" +#include "Collision/CCollisionActorManager.hpp" +#include "Collision/CCollisionActor.hpp" +#include "Particle/CElementGen.hpp" +#include "Particle/CParticleSwoosh.hpp" +#include "Weapon/CGameProjectile.hpp" +#include "World/CPatternedInfo.hpp" +#include "World/CPlayer.hpp" #include "World/ScriptLoader.hpp" +#include "World/CTeamAiMgr.hpp" +#include "CStateManager.hpp" +#include "GameGlobalObjects.hpp" namespace urde::MP1 { @@ -26,9 +37,238 @@ CMetroidBeta::CMetroidBeta(TUniqueId uid, std::string_view name, const CEntityIn 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, EKnockBackVariant::Large) {} + EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Large) +, x56c_metroidBetaData(metroidData) +, x67c_pathFind(nullptr, 3, pInfo.GetPathfindingIndex(), 1.f, 1.f) +, x768_colPrim(GetBoundingBox(), GetMaterialList()) +, x7b4_(GetModelData()->GetScale()) +, x7c0_(GetModelData()->GetScale()) +, x7cc_(GetModelData()->GetScale()) +, x7e4_(g_SimplePool->GetObj({FOURCC('PART'), metroidData.xf4_})) +, x7f0_(g_SimplePool->GetObj({FOURCC('SWHC'), metroidData.xf8_})) +, x7fc_(g_SimplePool->GetObj({FOURCC('PART'), metroidData.xfc_})) +, x808_(g_SimplePool->GetObj({FOURCC('PART'), metroidData.x100_})) +, x814_(g_SimplePool->GetObj({FOURCC('PART'), metroidData.x104_})) +, x820_(new CElementGen(x7e4_)) +, x824_(new CParticleSwoosh(x7f0_, 0)) +, x828_(new CElementGen(x7fc_)) +, x82c_(new CElementGen(x808_)) +, x830_(new CElementGen(x814_)) { + x820_->SetParticleEmission(false); + x828_->SetParticleEmission(false); + x82c_->SetParticleEmission(false); + x824_->DoElectricWarmup(); + const float scale = 0.75f * GetModelData()->GetScale().y(); + const zeus::CVector3f scaleVec(scale, scale, 2.f * scale); + zeus::CAABox box = {-scaleVec, scaleVec}; + SetBoundingBox(box); + x768_colPrim.SetBox(box); +} + +void CMetroidBeta::Think(float dt, CStateManager& mgr) { + if (CTeamAiMgr::GetTeamAiRole(mgr, x678_teamMgr, GetUniqueId())) { + AddToTeam(mgr); + } + + CPatterned::Think(dt, mgr); + x764_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); + // sub801c1928(mgr); + // sub801c0da4(dt, mgr); + // sub801c21b4(dt, mgr); +} +void CMetroidBeta::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CPatterned::AcceptScriptMsg(msg, uid, mgr); + switch (msg) { + case EScriptObjectMessage::Registered: { + x450_bodyController->Activate(mgr); + CreateCollisionActorManager(mgr); + //sub801c13d4(); + x760_ = GetModelData()->GetAnimationData()->GetLocatorSegId("L_Claw_1"sv); + x761_ = GetModelData()->GetAnimationData()->GetLocatorSegId("R_Claw_1"sv); + break; + } + case EScriptObjectMessage::Activate: { + x764_collisionManager->SetActive(mgr, true); + break; + } + case EScriptObjectMessage::Deactivate: { + x764_collisionManager->SetActive(mgr, false); + break; + } + case EScriptObjectMessage::Deleted: { + x764_collisionManager->Destroy(mgr); + RemoveFromTeam(mgr); + break; + } + case EScriptObjectMessage::Damage: + case EScriptObjectMessage::InvulnDamage: { + if (TCastToPtr colAct = mgr.ObjectById(uid)) { + if (TCastToConstPtr proj = mgr.GetObjectById(colAct->GetLastTouchedObject())) { + if (proj->GetOwnerId() != mgr.GetPlayer().GetUniqueId()) + break; + // sub801c14b4(proj->GetDamageInfo().GetDamage(), mgr); + const CDamageInfo& dInfo = proj->GetDamageInfo(); + if (colAct->GetDamageVulnerability()->WeaponHits(dInfo.GetWeaponMode(), false)) { + if (dInfo.GetWeaponMode().IsCharged() || dInfo.GetWeaponMode().IsComboed() || + dInfo.GetWeaponMode().GetType() == EWeaponType::Missile) { + x840_31_ = true; + x83c_ += 1.f; + } + KnockBack(proj->GetTranslation() - proj->GetPreviousPos(), mgr, dInfo, EKnockBackType::Radius, false, + dInfo.GetKnockBackPower()); + } + if (x840_25_) + x83c_ += 0.1f; + x840_26_ = true; + } + } else if (TCastToConstPtr weap = mgr.GetObjectById(uid)) { + CDamageInfo info = weap->GetDamageInfo(); + info.SetRadius(0.f); + mgr.ApplyDamage(uid, x790_, weap->GetOwnerId(), info, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); + } + break; + } + case EScriptObjectMessage::Alert: { + x840_26_ = true; + break; + } + case EScriptObjectMessage::Touched: { + break; + } + case EScriptObjectMessage::InitializedInArea: { + break; + } + case EScriptObjectMessage::SuspendedMove: { + if (x764_collisionManager) + x764_collisionManager->SetMovable(mgr, false); + break; + } + default: + break; + } +} +void CMetroidBeta::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + CPatterned::AddToRenderer(frustum, mgr); +} +void CMetroidBeta::Render(const CStateManager& mgr) const { CPatterned::Render(mgr); } +const CDamageVulnerability* CMetroidBeta::GetDamageVulnerability() const { return CAi::GetDamageVulnerability(); } +const CDamageVulnerability* CMetroidBeta::GetDamageVulnerability(const zeus::CVector3f& vec1, + const zeus::CVector3f& vec2, + const CDamageInfo& dInfo) const { + return CActor::GetDamageVulnerability(vec1, vec2, dInfo); +} +void CMetroidBeta::Touch(CActor& act, CStateManager& mgr) { CPatterned::Touch(act, mgr); } +zeus::CVector3f CMetroidBeta::GetAimPosition(const CStateManager& mgr, float dt) const { + return CPatterned::GetAimPosition(mgr, dt); +} +void CMetroidBeta::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType eType, float dt) { + CPatterned::DoUserAnimEvent(mgr, node, eType, dt); +} +const CCollisionPrimitive* CMetroidBeta::GetCollisionPrimitive() const { + return CPhysicsActor::GetCollisionPrimitive(); +} +void CMetroidBeta::CollidedWith(TUniqueId collidee, const CCollisionInfoList& info, CStateManager& mgr) { + CPatterned::CollidedWith(collidee, info, mgr); +} +zeus::CVector3f CMetroidBeta::GetOrigin(const CStateManager& mgr, const CTeamAiRole& role, + const zeus::CVector3f& aimPos) const { + return CAi::GetOrigin(mgr, role, aimPos); +} +void CMetroidBeta::Patrol(CStateManager& mgr, EStateMsg msg, float arg) { CPatterned::Patrol(mgr, msg, arg); } +void CMetroidBeta::PathFind(CStateManager& mgr, EStateMsg msg, float arg) { CPatterned::PathFind(mgr, msg, arg); } +void CMetroidBeta::SelectTarget(CStateManager& mgr, EStateMsg msg, float arg) { CAi::SelectTarget(mgr, msg, arg); } +void CMetroidBeta::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) { + CPatterned::TargetPatrol(mgr, msg, arg); +} +void CMetroidBeta::Generate(CStateManager& mgr, EStateMsg msg, float arg) { CAi::Generate(mgr, msg, arg); } +void CMetroidBeta::Attack(CStateManager& mgr, EStateMsg msg, float arg) { CAi::Attack(mgr, msg, arg); } +void CMetroidBeta::TurnAround(CStateManager& mgr, EStateMsg msg, float arg) { CAi::TurnAround(mgr, msg, arg); } +void CMetroidBeta::TelegraphAttack(CStateManager& mgr, EStateMsg msg, float arg) { + CAi::TelegraphAttack(mgr, msg, arg); +} +void CMetroidBeta::WallHang(CStateManager& mgr, EStateMsg msg, float arg) { CAi::WallHang(mgr, msg, arg); } +void CMetroidBeta::SpecialAttack(CStateManager& mgr, EStateMsg msg, float arg) { CAi::SpecialAttack(mgr, msg, arg); } +bool CMetroidBeta::InAttackPosition(CStateManager& mgr, float arg) { return CAi::InAttackPosition(mgr, arg); } +bool CMetroidBeta::Attacked(CStateManager& mgr, float arg) { return CPatterned::Attacked(mgr, arg); } +bool CMetroidBeta::PathShagged(CStateManager& mgr, float arg) { return CPatterned::PathShagged(mgr, arg); } +bool CMetroidBeta::InDetectionRange(CStateManager& mgr, float arg) { return CPatterned::InDetectionRange(mgr, arg); } +bool CMetroidBeta::AnimOver(CStateManager& mgr, float arg) { return CPatterned::AnimOver(mgr, arg); } +bool CMetroidBeta::ShouldAttack(CStateManager& mgr, float arg) { return CAi::ShouldAttack(mgr, arg); } +bool CMetroidBeta::InPosition(CStateManager& mgr, float arg) { return CPatterned::InPosition(mgr, arg); } +bool CMetroidBeta::ShouldTurn(CStateManager& mgr, float arg) { return CAi::ShouldTurn(mgr, arg); } +bool CMetroidBeta::AttackOver(CStateManager& mgr, float arg) { return CAi::AttackOver(mgr, arg); } +bool CMetroidBeta::ShotAt(CStateManager& mgr, float arg) { return CAi::ShotAt(mgr, arg); } +bool CMetroidBeta::ShouldWallHang(CStateManager& mgr, float arg) { return CAi::ShouldWallHang(mgr, arg); } +bool CMetroidBeta::StartAttack(CStateManager& mgr, float arg) { return CAi::StartAttack(mgr, arg); } +bool CMetroidBeta::BreakAttack(CStateManager& mgr, float arg) { return CAi::BreakAttack(mgr, arg); } +bool CMetroidBeta::ShouldSpecialAttack(CStateManager& mgr, float arg) { return CAi::ShouldSpecialAttack(mgr, arg); } void CMetroidBeta::RenderHitGunEffect() const {} void CMetroidBeta::RenderHitBallEffect() const {} +static SSphereJointInfo skPelvisInfo[1] { + {"Pelvis", 1.5f}, +}; +void CMetroidBeta::CreateCollisionActorManager(CStateManager& mgr) { + std::vector joints; + AddSphereJoints(skPelvisInfo, 1, joints); + + x764_collisionManager.reset(new CCollisionActorManager(mgr, GetUniqueId(), GetAreaIdAlways(), joints, false)); + x764_collisionManager->SetActive(mgr, GetActive()); + + for (u32 i = 0; i < x764_collisionManager->GetNumCollisionActors(); ++i) { + const CJointCollisionDescription& desc = x764_collisionManager->GetCollisionDescFromIndex(i); + if (TCastToPtr(mgr.ObjectById(desc.GetCollisionActorId()))) { + if (desc.GetName() == "Pelvis"sv) + x790_ = desc.GetCollisionActorId(); + } + } + + SetCollisionActorHealthAndVulnerability(mgr); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid, EMaterialTypes::Wall, EMaterialTypes::Floor, EMaterialTypes::Ceiling}, + {EMaterialTypes::CollisionActor, EMaterialTypes::Player, EMaterialTypes::Character})); + AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr); + x764_collisionManager->AddMaterial(mgr, CMaterialList(EMaterialTypes::AIJoint, EMaterialTypes::CameraPassthrough)); +} + +void CMetroidBeta::AddSphereJoints(SSphereJointInfo* sphereJoints, s32 count, + std::vector& joints) { + + for (u32 i = 0; i < count; ++i) { + CSegId id = GetModelData()->GetAnimationData()->GetLocatorSegId(sphereJoints[i].name); + if (id == 0xFF) + continue; + + joints.push_back( + CJointCollisionDescription::SphereCollision(id, sphereJoints[i].radius, sphereJoints[i].name, 1000.0f)); + } +} +void CMetroidBeta::SetCollisionActorHealthAndVulnerability(CStateManager& mgr) { + CHealthInfo* hInfo = HealthInfo(mgr); + if (TCastToPtr colAct = mgr.ObjectById(x790_)) { + *colAct->HealthInfo(mgr) = *hInfo; + colAct->SetDamageVulnerability(*GetDamageVulnerability()); + } +} +void CMetroidBeta::RemoveFromTeam(CStateManager& mgr) { + if (x678_teamMgr == kInvalidUniqueId) + return; + + if (TCastToPtr teamMgr = mgr.ObjectById(x678_teamMgr)) { + if (teamMgr->IsPartOfTeam(GetUniqueId())) + teamMgr->RemoveTeamAiRole(GetUniqueId()); + } +} +void CMetroidBeta::AddToTeam(CStateManager& mgr) { + if (x678_teamMgr == kInvalidUniqueId) + return; + + if (TCastToPtr teamMgr = mgr.ObjectById(x678_teamMgr)) { + if (!teamMgr->IsPartOfTeam(GetUniqueId())) + teamMgr->AssignTeamAiRole(*this, CTeamAiRole::ETeamAiRole::Ranged, CTeamAiRole::ETeamAiRole::Invalid, + CTeamAiRole::ETeamAiRole::Invalid); + } +} } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetroidBeta.hpp b/Runtime/MP1/World/CMetroidBeta.hpp index 9261f1105..7b74f27a7 100644 --- a/Runtime/MP1/World/CMetroidBeta.hpp +++ b/Runtime/MP1/World/CMetroidBeta.hpp @@ -1,11 +1,20 @@ #pragma once +#include +#include "World/CPathFindSearch.hpp" #include "World/CPatterned.hpp" -#include "CMetroid.hpp" +#include "CRandom16.hpp" + +namespace urde { +class CElementGen; +class CParticleSwoosh; +class CCollisionActorManager; +} namespace urde::MP1 { class CMetroidBetaData { + friend class CMetroidBeta; CDamageVulnerability x0_; CDamageVulnerability x68_; float xd0_; @@ -28,11 +37,106 @@ public: CMetroidBetaData(CInputStream&); }; class CMetroidBeta : public CPatterned { + s32 x568_progState = -1; + CMetroidBetaData x56c_metroidBetaData; + TUniqueId x678_teamMgr = kInvalidUniqueId; + CPathFindSearch x67c_pathFind; + u8 x760_ = 0xFF; + u8 x761_ = 0xFF; + std::unique_ptr x764_collisionManager; + CCollidableAABox x768_colPrim; + TUniqueId x790_ = kInvalidUniqueId; + float x794_ = 0.f; + float x798_ = 0.f; + float x79c_ = 0.f; + float x7a0_ = 0.f; + float x7a4_ = 0.f; + zeus::CVector3f x7a8_; + zeus::CVector3f x7b4_; + zeus::CVector3f x7c0_; + zeus::CVector3f x7cc_; + float x7d8_ = 0.f; + float x7dc_ = 0.f; + float x7e0_ = 0.f; + TToken x7e4_; + TToken x7f0_; + TToken x7fc_; + TToken x808_; + TToken x814_; + std::unique_ptr x820_; + std::unique_ptr x824_; + std::unique_ptr x828_; + std::unique_ptr x82c_; + std::unique_ptr x830_; + float x834_ = 0.f; + CRandom16 x838_ = CRandom16(1469); + float x83c_; + union { + struct { + bool x840_24_ : 1; + bool x840_25_ : 1; + bool x840_26_ : 1; + bool x840_27_ : 1; + bool x840_28_ : 1; + bool x840_29_ : 1; + bool x840_30_ : 1; + bool x840_31_ : 1; + }; + u32 _dummy = 0; + }; + + void CreateCollisionActorManager(CStateManager& mgr); + void AddSphereJoints(SSphereJointInfo* sphereJoints, s32 count, std::vector& joints); + void SetCollisionActorHealthAndVulnerability(CStateManager& mgr); + void RemoveFromTeam(CStateManager& mgr); + void AddToTeam(CStateManager& mgr); public: DEFINE_PATTERNED(MetroidBeta) CMetroidBeta(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms, const CMetroidBetaData& metroidData); + + void Think(float dt, CStateManager& mgr) override; + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override; + void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const override; + void Render(const CStateManager& mgr) const override; + const CDamageVulnerability* GetDamageVulnerability() const override; + const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f& vec1, const zeus::CVector3f& vec2, + const CDamageInfo& dInfo) const override; + void Touch(CActor& act, CStateManager& mgr) override; + zeus::CVector3f GetAimPosition(const CStateManager& mgr, float dt) const override; + void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType eType, float dt) override; + const CCollisionPrimitive* GetCollisionPrimitive() const override; + void CollidedWith(TUniqueId collidee, const CCollisionInfoList& info, CStateManager& mgr) override; + bool IsListening() const override { return true; } + zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role, + const zeus::CVector3f& aimPos) const override; + void Patrol(CStateManager& mgr, EStateMsg msg, float arg) override; + void PathFind(CStateManager& mgr, EStateMsg msg, float arg) override; + void SelectTarget(CStateManager& mgr, EStateMsg msg, float arg) override; + void TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) override; + void Generate(CStateManager& mgr, EStateMsg msg, float arg) override; + void Attack(CStateManager& mgr, EStateMsg msg, float arg) override; + void TurnAround(CStateManager& mgr, EStateMsg msg, float arg) override; + void TelegraphAttack(CStateManager& mgr, EStateMsg msg, float arg) override; + void WallHang(CStateManager& mgr, EStateMsg msg, float arg) override; + void SpecialAttack(CStateManager& mgr, EStateMsg msg, float arg) override; + bool InAttackPosition(CStateManager& mgr, float arg) override; + bool Attacked(CStateManager& mgr, float arg) override; + bool PathShagged(CStateManager& mgr, float arg) override; + bool InDetectionRange(CStateManager& mgr, float arg) override; + bool AnimOver(CStateManager& mgr, float arg) override; + bool ShouldAttack(CStateManager& mgr, float arg) override; + bool InPosition(CStateManager& mgr, float arg) override; + bool ShouldTurn(CStateManager& mgr, float arg) override; + bool AttackOver(CStateManager& mgr, float arg) override; + bool ShotAt(CStateManager& mgr, float arg) override; + bool ShouldWallHang(CStateManager& mgr, float arg) override; + bool StartAttack(CStateManager& mgr, float arg) override; + bool BreakAttack(CStateManager& mgr, float arg) override; + bool ShouldSpecialAttack(CStateManager& mgr, float arg) override; + CPathFindSearch* GetSearchPath() override { return &x67c_pathFind; } + void RenderHitGunEffect() const; void RenderHitBallEffect() const; }; diff --git a/Runtime/MP1/World/CRipper.cpp b/Runtime/MP1/World/CRipper.cpp index 6ba8679b6..775862024 100644 --- a/Runtime/MP1/World/CRipper.cpp +++ b/Runtime/MP1/World/CRipper.cpp @@ -1,9 +1,144 @@ #include "MP1/World/CRipper.hpp" +#include "Collision/CCollidableOBBTreeGroup.hpp" +#include "Weapon/CPlayerGun.hpp" +#include "World/CActorParameters.hpp" +#include "World/CPlayer.hpp" +#include "World/CScriptGrapplePoint.hpp" +#include "CStateManager.hpp" +#include "TCastTo.hpp" namespace urde::MP1 { CRipper::CRipper(TUniqueId uid, std::string_view name, EFlavorType type, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, - const CGrappleParameters& grappleParms) + const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, + const CActorParameters& actParms, const CGrappleParameters& grappleParms) : CPatterned(ECharacter::Ripper, uid, name, type, info, xf, std::move(mData), pInfo, EMovementType::Flyer, - EColliderType::One, EBodyType::Flyer, actParms, EKnockBackVariant::Medium) {} + EColliderType::One, EBodyType::Flyer, actParms, EKnockBackVariant::Medium) +, x568_grappleParams(grappleParms) +, x59c_24_muted(false) { + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid}, + {EMaterialTypes::NoStaticCollision, EMaterialTypes::NoPlatformCollision, EMaterialTypes::Platform})); + x460_knockBackController.SetAutoResetImpulse(false); + x460_knockBackController.SetAnimationStateRange(EKnockBackAnimationState::KnockBack, + EKnockBackAnimationState::Hurled); +} + +void CRipper::Think(float dt, CStateManager& mgr) { + + if (!GetActive()) + return; + + ProcessGrapplePoint(mgr); + const CPlayer& pl = mgr.GetPlayer(); + CGrappleArm::EArmState armState = pl.GetPlayerGun()->GetGrappleArm().GetAnimState(); + if (x598_grapplePoint == kInvalidUniqueId || pl.GetOrbitTargetId() != x598_grapplePoint || + pl.GetGrappleState() == CPlayer::EGrappleState::None) { + CPatterned::Think(dt, mgr); + if (x59c_24_muted) { + SetMuted(false); + x59c_24_muted = false; + } + } else { + if (armState == CGrappleArm::EArmState::FireGrapple) { + CPatterned::Think(dt, mgr); + } else if (armState == CGrappleArm::EArmState::IntoGrappleIdle || armState == CGrappleArm::EArmState::Three) { + Stop(); + if (!x59c_24_muted) { + SetMuted(true); + x59c_24_muted = true; + } + } + } + CPatterned::Think(dt, mgr); +} + +void CRipper::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CPatterned::AcceptScriptMsg(msg, uid, mgr); + + switch (msg) { + case EScriptObjectMessage::Deleted: + case EScriptObjectMessage::Deactivate: { + RemoveGrapplePoint(mgr); + RemovePlatform(mgr); + break; + } + case EScriptObjectMessage::Activate: { + AddGrapplePoint(mgr); + AddPlatform(mgr); + break; + } + case EScriptObjectMessage::Registered: { + x450_bodyController->Activate(mgr); + AddMaterial(EMaterialTypes::Immovable, mgr); + RemoveMaterial(EMaterialTypes::Solid, mgr); + if (x3fc_flavor != EFlavorType::One) { + AddGrapplePoint(mgr); + RemoveMaterial(EMaterialTypes::Orbit, mgr); + } + + AddPlatform(mgr); + break; + } + default: + break; + } +} +void CRipper::KnockBack(const zeus::CVector3f& dir, CStateManager& mgr, const CDamageInfo& dInfo, EKnockBackType kb, + bool inDeferred, float mag) { + CPatterned::KnockBack(dir, mgr, dInfo, kb, inDeferred, mag); +} +void CRipper::Patrol(CStateManager& mgr, EStateMsg msg, float arg) { + x450_bodyController->GetCommandMgr().SetSteeringBlendMode(ESteeringBlendMode::FullSpeed); + x450_bodyController->GetCommandMgr().SetSteeringSpeedRange(1.f, 1.f); + CPatterned::Patrol(mgr, msg, arg); +} + +void CRipper::ProcessGrapplePoint(CStateManager& mgr) { + if (x3fc_flavor == EFlavorType::One || x598_grapplePoint == kInvalidUniqueId) + return; + + if (TCastToPtr gp = mgr.ObjectById(x598_grapplePoint)) { + gp->SetTransform(GetTransform()); + } +} + +void CRipper::AddGrapplePoint(CStateManager& mgr) { + if (x598_grapplePoint != kInvalidUniqueId) + return; + + x598_grapplePoint = mgr.AllocateUniqueId(); + mgr.AddObject(new CScriptGrapplePoint(x59a_platformId, "RipperGrapplePoint"sv, + CEntityInfo(GetAreaIdAlways(), NullConnectionList), GetTransform(), true, x568_grappleParams)); +} + +void CRipper::RemoveGrapplePoint(CStateManager& mgr) { + if (x598_grapplePoint == kInvalidUniqueId) + return; + mgr.FreeScriptObject(x598_grapplePoint); +} + +void CRipper::AddPlatform(CStateManager& mgr) { + if (x59a_platformId != kInvalidUniqueId) + return; + + x59a_platformId = mgr.AllocateUniqueId(); + const zeus::CAABox bounds = GetModelData()->GetBounds(GetTransform().getRotation()); + + mgr.AddObject(new CRipperControlledPlatform(x59a_platformId, GetUniqueId(), "Ripper Controlled Platform"sv, + CEntityInfo(GetAreaIdAlways(), NullConnectionList), GetTransform(), bounds, GetActive(), {})); +} + +void CRipper::RemovePlatform(CStateManager& mgr) { + if (x59a_platformId == kInvalidUniqueId) + return; + mgr.FreeScriptObject(x59a_platformId); + x59a_platformId = kInvalidUniqueId; +} +CRipperControlledPlatform::CRipperControlledPlatform( + TUniqueId uid, TUniqueId owner, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + const zeus::CAABox& bounds, bool active, const std::optional>& colTree) +: CScriptPlatform(uid, name, info, xf, CModelData::CModelDataNull(), CActorParameters::None(), bounds, 0.f, false, 1.f, + active, CHealthInfo(FLT_MAX, 10.f), CDamageVulnerability::ImmuneVulnerabilty(), colTree, 0, 1, 1) +, x358_owner(owner) +, x35c_yaw(GetYaw()) {} } \ No newline at end of file diff --git a/Runtime/MP1/World/CRipper.hpp b/Runtime/MP1/World/CRipper.hpp index 297a4f938..f928a9fc7 100644 --- a/Runtime/MP1/World/CRipper.hpp +++ b/Runtime/MP1/World/CRipper.hpp @@ -2,13 +2,47 @@ #include "World/CPatterned.hpp" #include "World/CGrappleParameters.hpp" +#include "World/CScriptPlatform.hpp" namespace urde::MP1 { + class CRipper : public CPatterned { + CGrappleParameters x568_grappleParams; + TUniqueId x598_grapplePoint = kInvalidUniqueId; + TUniqueId x59a_platformId = kInvalidUniqueId; + bool x59c_24_muted : 1; + + void ProcessGrapplePoint(CStateManager&); + void AddGrapplePoint(CStateManager&); + void RemoveGrapplePoint(CStateManager&); + void AddPlatform(CStateManager&); + void RemovePlatform(CStateManager&); public: DEFINE_PATTERNED(Ripper) CRipper(TUniqueId uid, std::string_view name, EFlavorType type, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, const CGrappleParameters& grappleParms); + + void Think(float dt, CStateManager& mgr) override; + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override; + EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, + const CWeaponMode& wp, EProjectileAttrib) const override { + if (!GetDamageVulnerability()->WeaponHits(wp, false)) + return EWeaponCollisionResponseTypes::Unknown82; + + return EWeaponCollisionResponseTypes::Unknown32; + } + + void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo&, EKnockBackType, bool, float) override; + void Patrol(CStateManager&, EStateMsg, float) override; + bool PathOver(CStateManager&, float) override { return false; } /* They never give you up, or let you down */ +}; + +class CRipperControlledPlatform : public CScriptPlatform { + TUniqueId x358_owner; + float x35c_yaw; +public: + CRipperControlledPlatform(TUniqueId, TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, + const zeus::CAABox&, bool, const std::optional>&); }; } \ No newline at end of file diff --git a/Runtime/Weapon/CPlayerGun.cpp b/Runtime/Weapon/CPlayerGun.cpp index 49bc27459..080863948 100644 --- a/Runtime/Weapon/CPlayerGun.cpp +++ b/Runtime/Weapon/CPlayerGun.cpp @@ -1,5 +1,6 @@ -#include -#include +#include "MP1/World/CMetroidBeta.hpp" +#include "MP1/World/CMetroid.hpp" +#include "MP1/CSamusHud.hpp" #include "CSimplePool.hpp" #include "Character/CPrimitive.hpp" #include "CEnergyProjectile.hpp"