From 9b2fd002c656ddbe2fd329a115128197597ac29c Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sat, 1 Dec 2018 18:32:26 -0800 Subject: [PATCH] Implement CEyeBall, disable CPuddleToadGamma (preventing softlocks), initial CSpankWeed --- Runtime/MP1/World/CEyeball.cpp | 152 ++++++++++++++++++++++--- Runtime/MP1/World/CEyeball.hpp | 38 ++++--- Runtime/MP1/World/CMakeLists.txt | 3 +- Runtime/MP1/World/CPuddleToadGamma.cpp | 3 + Runtime/MP1/World/CSpankWeed.cpp | 49 ++++++++ Runtime/MP1/World/CSpankWeed.hpp | 31 +++++ Runtime/Weapon/CBomb.cpp | 2 +- Runtime/Weapon/CPlasmaProjectile.cpp | 5 + Runtime/Weapon/CPlasmaProjectile.hpp | 2 +- Runtime/World/CPatternedInfo.hpp | 8 +- 10 files changed, 251 insertions(+), 42 deletions(-) create mode 100644 Runtime/MP1/World/CSpankWeed.cpp create mode 100644 Runtime/MP1/World/CSpankWeed.hpp diff --git a/Runtime/MP1/World/CEyeball.cpp b/Runtime/MP1/World/CEyeball.cpp index f5165e339..4858b6aee 100644 --- a/Runtime/MP1/World/CEyeball.cpp +++ b/Runtime/MP1/World/CEyeball.cpp @@ -3,6 +3,8 @@ #include "Weapon/CGameProjectile.hpp" #include "Weapon/CPlasmaProjectile.hpp" #include "World/CPlayer.hpp" +#include "World/CWorld.hpp" +#include "World/CGameArea.hpp" #include "CStateManager.hpp" #include "TCastTo.hpp" namespace urde::MP1 @@ -13,13 +15,18 @@ CEyeball::CEyeball(TUniqueId uid, std::string_view name, CPatterned::EFlavorType u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, bool b1, const CActorParameters& actParms) : CPatterned(ECharacter::EyeBall, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, - EColliderType::Zero, EBodyType::Restricted, actParms, EKnockBackVariant::Medium), x568_(f1), x56c_(f2), + EColliderType::Zero, EBodyType::Restricted, actParms, EKnockBackVariant::Medium), x568_attackDelay(f1), x56c_maxAttackDelay(f2), x570_boneTracking(*GetModelData()->GetAnimationData(), "Eye"sv, zeus::degToRad(45.f), zeus::degToRad(180.f), true), x5b4_projectileInfo(aId1, dInfo), x5dc_(aId2), x5e0_(aId3), x5e4_(aId4), - x5e8_(aId5), x5f4_(w1), x5f8_(w2), x5fc_(w3), x600_(w4), x604_(CSfxManager::TranslateSFXID(w5)), x60c_24_(false), - x60c_25_(false), x60c_26_alert(false), x60c_27_(b1), x60c_28_(false) + x5e8_(aId5), x604_beamSfxId(CSfxManager::TranslateSFXID(w5)), x60c_24_canAttack(false), + x60c_25_playerInRange(false), x60c_26_alert(false), x60c_27_attackDisabled(b1), x60c_28_firingBeam(false) { + x5f4_animIdxs[0] = w1; + x5f4_animIdxs[1] = w2; + x5f4_animIdxs[2] = w3; + x5f4_animIdxs[3] = w4; + x460_knockBackController.SetAutoResetImpulse(false); } @@ -61,10 +68,10 @@ void CEyeball::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMa if (x5ec_projectileId != kInvalidUniqueId) { mgr.FreeScriptObject(x5ec_projectileId); - if (x608_) + if (x608_beamSfx) { - CSfxManager::RemoveEmitter(x608_); - x608_.reset(); + CSfxManager::RemoveEmitter(x608_beamSfx); + x608_beamSfx.reset(); } } x5ec_projectileId = kInvalidUniqueId; @@ -76,6 +83,47 @@ void CEyeball::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMa CPatterned::AcceptScriptMsg(msg, uid, mgr); } +static float kMinAngle = std::cos(zeus::degToRad(45.f)); +void CEyeball::Think(float dt, CStateManager& mgr) +{ + CPatterned::Think(dt, mgr); + if (!GetActive()) + return; + + CPlayer& player = mgr.GetPlayer(); + zeus::CVector3f direction = (player.GetTranslation() - GetTranslation()).normalized(); + + x60c_25_playerInRange = (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && + direction.dot(GetTransform().frontVector()) > kMinAngle); + + if (x60c_25_playerInRange) + { + x570_boneTracking.SetActive(true); + x5a8_targetPosition = player.GetTranslation() - (0.5f * player.GetVelocity()); + x570_boneTracking.SetTargetPosition(x5a8_targetPosition); + x570_boneTracking.Update(dt); + ModelData()->AnimationData()->PreRender(); + x570_boneTracking.PreRender(mgr, *ModelData()->AnimationData(), GetTransform(), GetModelData()->GetScale(), + *x450_bodyController.get()); + } else + x570_boneTracking.SetActive(false); + + if (GetActive()) + { + CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x5ec_projectileId)); + if (projectile && projectile->GetActive()) + projectile->UpdateFX(GetLctrTransform(skEyeLocator), dt, mgr); + } + + if (x60c_28_firingBeam) + { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways()); + if (area->GetActive() && area->IsPostConstructed() && + area->GetPostConstructed()->x10dc_occlusionState == CGameArea::EOcclusionState::Occluded) + ResetBeamState(mgr); + } +} + void CEyeball::CreateBeam(CStateManager& mgr) { if (x5ec_projectileId != kInvalidUniqueId) @@ -102,8 +150,8 @@ void CEyeball::Cover(CStateManager&, EStateMsg msg, float) if (msg == EStateMsg::Activate) { x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); - x60c_24_ = false; - x330_stateMachineState.SetDelay(x568_); + x60c_24_canAttack = false; + x330_stateMachineState.SetDelay(x568_attackDelay); } } @@ -112,7 +160,7 @@ void CEyeball::Flinch(CStateManager& mgr, EStateMsg msg, float arg) if (msg == EStateMsg::Activate) { x32c_animState = EAnimState::One; - x330_stateMachineState.SetDelay(x568_); + x330_stateMachineState.SetDelay(x568_attackDelay); } else if (msg == EStateMsg::Update) TryCommand(mgr, pas::EAnimationState::KnockBack, CPatternedTryFunc(&CEyeball::TryFlinch), 0); @@ -131,31 +179,99 @@ void CEyeball::Active(CStateManager& mgr, EStateMsg msg, float) { x400_24_hitByPlayerProjectile = 0; x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); - x60c_24_ = false; + x60c_24_canAttack = false; } else if (msg == EStateMsg::Update) { - if (x330_stateMachineState.GetDelay() > x56c_) - x60c_24_ = true; + if (x330_stateMachineState.GetDelay() > x56c_maxAttackDelay) + x60c_24_canAttack = true; - sub802249c8(); + UpdateAnimation(); } else if (msg == EStateMsg::Deactivate) { - x330_stateMachineState.SetDelay(x568_); + x330_stateMachineState.SetDelay(x568_attackDelay); if (CPlasmaProjectile* proj = static_cast(mgr.ObjectById(x5ec_projectileId))) proj->ResetBeam(mgr, true); - x60c_24_ = false; + x60c_24_canAttack = false; - CSfxManager::RemoveEmitter(x608_); - x608_.reset(); + CSfxManager::RemoveEmitter(x608_beamSfx); + x608_beamSfx.reset(); } } -void CEyeball::sub802249c8() +void CEyeball::UpdateAnimation() { + if (std::fabs(GetModelData()->GetAnimationData()->GetAnimTimeRemaining("Whole Body"sv) - 0.f) >= 0.00001f) + return; + x5f0_currentAnim = (x5f0_currentAnim + 1) & 3; + for (u32 i=0 ; i<4 ; ++i) + { + if (x5f4_animIdxs[x5f0_currentAnim] != -1) + break; + + x5f0_currentAnim = (x5f0_currentAnim + 1) & 3; + } + s32 animIdx = x5f4_animIdxs[x5f0_currentAnim]; + if (animIdx != -1) + x450_bodyController->GetCommandMgr().DeliverCmd(CBCScriptedCmd(animIdx, false, false, 0.f)); } +void CEyeball::ResetBeamState(CStateManager& mgr) +{ + if (CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x5ec_projectileId))) + projectile->ResetBeam(mgr, true); + + x60c_28_firingBeam = false; + if (x608_beamSfx) + { + CSfxManager::RemoveEmitter(x608_beamSfx); + x608_beamSfx.reset(); + } +} + +void CEyeball::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) +{ + if (type == EUserEventType::DamageOff) + ResetBeamState(mgr); + else if (type == EUserEventType::DamageOn && x60c_24_canAttack) + FireBeam(mgr, GetLctrTransform(node.GetLocatorName())); + else + CPatterned::DoUserAnimEvent(mgr, node, type, dt); +} + +void CEyeball::FireBeam(CStateManager& mgr, const zeus::CTransform& xf) +{ + if (CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x5ec_projectileId))) + { + if (!projectile->GetActive()) + { + projectile->Fire(xf, mgr, false); + x60c_28_firingBeam = true; + if (!x608_beamSfx) + { + CAudioSys::C3DEmitterParmData + parmData{GetTranslation(), {}, 50.f, 0.1f, 0x1, x604_beamSfxId, 1.f /* 127 */, 0.15f /* 20 / 127 */, + false, 127}; + x608_beamSfx = CSfxManager::AddEmitter(parmData, true, 127, true, GetAreaIdAlways()); + } + } + } +} + +void CEyeball::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) +{ + CPatterned::PreRender(mgr, frustum); + x570_boneTracking.PreRender(mgr, *ModelData()->AnimationData(), GetTransform(), GetModelData()->GetScale(), + *x450_bodyController); +} + +void CEyeball::Death(CStateManager& mgr, const zeus::CVector3f& pos, EScriptObjectState state) +{ + zeus::CTransform oldXf = GetTransform(); + CPatterned::Death(mgr, pos, state); + SetTransform(oldXf); +} } \ No newline at end of file diff --git a/Runtime/MP1/World/CEyeball.hpp b/Runtime/MP1/World/CEyeball.hpp index 26689b5e9..27696f5a2 100644 --- a/Runtime/MP1/World/CEyeball.hpp +++ b/Runtime/MP1/World/CEyeball.hpp @@ -8,33 +8,32 @@ namespace urde::MP1 { class CEyeball : public CPatterned { - float x568_; - float x56c_; + static constexpr std::string_view skEyeLocator="Laser_LCTR"sv; + float x568_attackDelay; + float x56c_maxAttackDelay; CBoneTracking x570_boneTracking; - zeus::CVector3f x5a8_; + zeus::CVector3f x5a8_targetPosition; CProjectileInfo x5b4_projectileInfo; CAssetId x5dc_; CAssetId x5e0_; CAssetId x5e4_; CAssetId x5e8_; TUniqueId x5ec_projectileId = kInvalidUniqueId; - u32 x5f0_ = 0; - u32 x5f4_; - u32 x5f8_; - u32 x5fc_; - u32 x600_; - s16 x604_; - CSfxHandle x608_ = 0; - bool x60c_24_ : 1; - bool x60c_25_ : 1; + u32 x5f0_currentAnim = 0; + s32 x5f4_animIdxs[4]; + u16 x604_beamSfxId; + CSfxHandle x608_beamSfx = 0; + bool x60c_24_canAttack : 1; + bool x60c_25_playerInRange : 1; bool x60c_26_alert : 1; - bool x60c_27_ : 1; - bool x60c_28_ : 1; + bool x60c_27_attackDisabled : 1; + bool x60c_28_firingBeam : 1; void CreateBeam(CStateManager&); - + void FireBeam(CStateManager&, const zeus::CTransform&); void TryFlinch(CStateManager&, int); - void sub802249c8(); + void UpdateAnimation(); + void ResetBeamState(CStateManager&); public: DEFINE_PATTERNED(EyeBall) @@ -43,8 +42,13 @@ public: CAssetId, CAssetId, u32, u32, u32, u32, u32, bool, const CActorParameters&); void Accept(IVisitor& visitor); + void PreRender(CStateManager&, const zeus::CFrustum&); + void Touch(CActor&, CStateManager&) {}; + void Death(CStateManager&, const zeus::CVector3f&, EScriptObjectState); void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); + void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float); + void Think(float, CStateManager&); void Flinch(CStateManager&, EStateMsg, float); void Active(CStateManager&, EStateMsg, float); void InActive(CStateManager&, EStateMsg, float); @@ -52,6 +56,6 @@ public: void Cover(CStateManager&, EStateMsg, float); bool ShouldAttack(CStateManager&, float) { return x60c_26_alert; } - bool ShouldFire(CStateManager&, float) { return !x60c_27_; } + bool ShouldFire(CStateManager&, float) { return !x60c_27_attackDisabled; } }; } \ No newline at end of file diff --git a/Runtime/MP1/World/CMakeLists.txt b/Runtime/MP1/World/CMakeLists.txt index 489a8bb6e..5090d44f8 100644 --- a/Runtime/MP1/World/CMakeLists.txt +++ b/Runtime/MP1/World/CMakeLists.txt @@ -28,6 +28,7 @@ set(MP1_WORLD_SOURCES CSeedling.hpp CSeedling.cpp CRidley.hpp CRidley.cpp CPuddleToadGamma.hpp CPuddleToadGamma.cpp - CFlaahgraProjectile.hpp CFlaahgraProjectile.cpp) + CFlaahgraProjectile.hpp CFlaahgraProjectile.cpp + CSpankWeed.hpp CSpankWeed.cpp) runtime_add_list(World MP1_WORLD_SOURCES) diff --git a/Runtime/MP1/World/CPuddleToadGamma.cpp b/Runtime/MP1/World/CPuddleToadGamma.cpp index 84b0178d9..ec3c4794e 100644 --- a/Runtime/MP1/World/CPuddleToadGamma.cpp +++ b/Runtime/MP1/World/CPuddleToadGamma.cpp @@ -207,6 +207,7 @@ void CPuddleToadGamma::Active(CStateManager& mgr, EStateMsg msg, float) void CPuddleToadGamma::Suck(CStateManager& mgr, EStateMsg msg, float arg) { + return; if (msg == EStateMsg::Activate) { SetSolid(mgr, false); @@ -252,6 +253,7 @@ void CPuddleToadGamma::SuckPlayer(CStateManager& mgr, float arg) void CPuddleToadGamma::Attack(CStateManager& mgr, EStateMsg msg, float) { + return; if (msg == EStateMsg::Activate) { mgr.GetPlayer().Stop(); @@ -318,6 +320,7 @@ bool CPuddleToadGamma::Inside(CStateManager& mgr, float) void CPuddleToadGamma::Crouch(CStateManager& mgr, EStateMsg msg, float) { + return; if (msg == EStateMsg::Activate) { x568_ = 0; diff --git a/Runtime/MP1/World/CSpankWeed.cpp b/Runtime/MP1/World/CSpankWeed.cpp new file mode 100644 index 000000000..5f9637c93 --- /dev/null +++ b/Runtime/MP1/World/CSpankWeed.cpp @@ -0,0 +1,49 @@ +#include "CSpankWeed.hpp" +#include "World/CPatternedInfo.hpp" +#include + +namespace urde::MP1 +{ +logvisor::Module SpankLog("urde::MP1::SpankWeed"); +CSpankWeed::CSpankWeed(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, float f1, + float f2, float f3, float f4) +: CPatterned(ECharacter::SpankWeed, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, + EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::Medium) +, x568_(f1) +, x56c_(pInfo.GetDetectionHeightRange()) +, x570_(f2) +, x574_(f3) +, x578_(f4) +, x584_(xf.origin) +{ + SetCallTouch(false); + CreateShadow(false); + + zeus::CVector3f modelScale = GetModelData()->GetScale(); + if (modelScale.x != modelScale.y || modelScale.x != modelScale.z) + { + float scale = modelScale.magnitude() / std::sqrt(3.f); + + ModelData()->SetScale(zeus::CVector3f(scale)); + SpankLog.report(logvisor::Level::Warning, "WARNING: Non-uniform scale (%.2f, %.2f, %.2f) applied to Spank Weed" + "...changing scale to (%.2f, %.2f, %.2f)\n", + modelScale.x, modelScale.y, modelScale.z, + scale, scale, scale); + } + CMaterialList list = GetMaterialFilter().GetExcludeList(); + list.Add(EMaterialTypes::Character); + list.Add(EMaterialTypes::Player); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(GetMaterialFilter().GetIncludeList(), list)); + + CSegId segId = GetModelData()->GetAnimationData()->GetLocatorSegId("lockon_target_LCTR"sv); + if (segId != 0xFF) + { + zeus::CTransform locatorXf = GetTransform() * zeus::CTransform::Scale(GetModelData()->GetScale()) * + GetModelData()->GetAnimationData()->GetLocatorTransform(segId, nullptr); + x5a8_ = locatorXf.origin; + x59c_ = locatorXf.origin - GetTranslation(); + } + x460_knockBackController.SetAutoResetImpulse(false); +} +} \ No newline at end of file diff --git a/Runtime/MP1/World/CSpankWeed.hpp b/Runtime/MP1/World/CSpankWeed.hpp new file mode 100644 index 000000000..cf4a93f2f --- /dev/null +++ b/Runtime/MP1/World/CSpankWeed.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "World/CPatterned.hpp" +#include "Collision/CCollisionActorManager.hpp" + +namespace urde::MP1 +{ +class CSpankWeed : public CPatterned +{ + float x568_; + float x56c_; + float x570_; + float x574_; + float x578_; + bool x57c_ = false; + float x580_ = 0.f; + std::unique_ptr x594_collisionMgr; + zeus::CVector3f x584_; + zeus::CVector3f x59c_; + zeus::CVector3f x5a8_; + s32 x5b4_ = -1; + s32 x5b8_ = -1; + s32 x5bc_ = -1; + +public: + DEFINE_PATTERNED(SpankWeed) + + CSpankWeed(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CActorParameters&, const CPatternedInfo&, float, float, float, float); +}; +} \ No newline at end of file diff --git a/Runtime/Weapon/CBomb.cpp b/Runtime/Weapon/CBomb.cpp index 2af600825..476a46a03 100644 --- a/Runtime/Weapon/CBomb.cpp +++ b/Runtime/Weapon/CBomb.cpp @@ -136,7 +136,7 @@ void CBomb::AddToRenderer(const zeus::CFrustum& frustum, const urde::CStateManag zeus::CAABox aabox(origin - (0.9f * ballRadius), origin + (0.9f * ballRadius)); zeus::CVector3f closestPoint = aabox.closestPointAlongVector(CGraphics::g_ViewMatrix.frontVector()); - if (x190_24_isNotDetonated&& x17c_fuseTime > 0.5f) + if (x190_24_isNotDetonated && x17c_fuseTime > 0.5f) g_Renderer->AddParticleGen(*x180_particle1, closestPoint, aabox); else g_Renderer->AddParticleGen(*x184_particle2, closestPoint, aabox); diff --git a/Runtime/Weapon/CPlasmaProjectile.cpp b/Runtime/Weapon/CPlasmaProjectile.cpp index 8878eae91..a4a6edf71 100644 --- a/Runtime/Weapon/CPlasmaProjectile.cpp +++ b/Runtime/Weapon/CPlasmaProjectile.cpp @@ -18,4 +18,9 @@ void CPlasmaProjectile::Accept(IVisitor& visitor) visitor.Visit(this); } +void CPlasmaProjectile::Fire(const zeus::CTransform&, CStateManager&, bool) +{ + SetActive(true); +} + } diff --git a/Runtime/Weapon/CPlasmaProjectile.hpp b/Runtime/Weapon/CPlasmaProjectile.hpp index 47e63f3bb..6898efbdc 100644 --- a/Runtime/Weapon/CPlasmaProjectile.hpp +++ b/Runtime/Weapon/CPlasmaProjectile.hpp @@ -17,7 +17,7 @@ public: void Accept(IVisitor& visitor); void UpdateFx(const zeus::CTransform&, float, CStateManager&) {} - void Fire(const zeus::CTransform&, CStateManager&, bool) {} + void Fire(const zeus::CTransform&, CStateManager&, bool); }; } diff --git a/Runtime/World/CPatternedInfo.hpp b/Runtime/World/CPatternedInfo.hpp index 436f207ec..60fb3a532 100644 --- a/Runtime/World/CPatternedInfo.hpp +++ b/Runtime/World/CPatternedInfo.hpp @@ -59,13 +59,13 @@ public: CPatternedInfo(CInputStream& in, u32 pcount); static std::pair HasCorrectParameterCount(CInputStream& in); - CAnimationParameters& GetAnimationParameters() { return xec_animParams; } - const CAnimationParameters& GetAnimationParameters() const { return xec_animParams; } - + float GetDetectionHeightRange() const { return x10_detectionHeightRange; } float GetHalfExtent() const { return xc4_halfExtent; } float GetHeight() const { return xc8_height; } - u32 GetPathfindingIndex() const { return x10c_pathfindingIndex; } const CHealthInfo& GetHealthInfo() const { return x54_healthInfo; } + CAnimationParameters& GetAnimationParameters() { return xec_animParams; } + const CAnimationParameters& GetAnimationParameters() const { return xec_animParams; } + u32 GetPathfindingIndex() const { return x10c_pathfindingIndex; } }; }