From c7573ae52f3b4b24137db1587007c4759b39920e Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sun, 9 Dec 2018 21:12:55 -0800 Subject: [PATCH 1/3] Finalize CFireFlea --- Runtime/AutoMapper/CMapWorldInfo.cpp | 6 +- Runtime/MP1/MP1.cpp | 1 + Runtime/MP1/World/CFireFlea.cpp | 116 ++++++++++++++++++++++++++- Runtime/MP1/World/CFireFlea.hpp | 10 ++- hecl | 2 +- 5 files changed, 126 insertions(+), 9 deletions(-) diff --git a/Runtime/AutoMapper/CMapWorldInfo.cpp b/Runtime/AutoMapper/CMapWorldInfo.cpp index 5831a3e61..762d3bd56 100644 --- a/Runtime/AutoMapper/CMapWorldInfo.cpp +++ b/Runtime/AutoMapper/CMapWorldInfo.cpp @@ -92,11 +92,7 @@ void CMapWorldInfo::SetIsMapped(TAreaId aid, bool mapped) { bool CMapWorldInfo::IsWorldVisible(TAreaId aid) const { return x38_mapStationUsed || IsMapped(aid); } -bool CMapWorldInfo::IsAreaVisible(TAreaId aid) const { - if (IsAreaVisted(aid) || IsMapped(aid)) - return true; - return false; -} +bool CMapWorldInfo::IsAreaVisible(TAreaId aid) const { return IsAreaVisted(aid) || IsMapped(aid); } bool CMapWorldInfo::IsAnythingSet() const { for (int i = 0; i < x0_visitedAreasAllocated; ++i) diff --git a/Runtime/MP1/MP1.cpp b/Runtime/MP1/MP1.cpp index 695b33859..9d4943fcc 100644 --- a/Runtime/MP1/MP1.cpp +++ b/Runtime/MP1/MP1.cpp @@ -623,6 +623,7 @@ void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarMana m_mainWindow = window; m_cvarMgr = cvarMgr; m_console = std::make_unique(m_cvarMgr); + m_console->init(window); m_console->registerCommand("Quit"sv, "Quits the game immediately"sv, ""sv, std::bind(&CMain::quit, this, std::placeholders::_1, std::placeholders::_2)); m_console->registerCommand("Give"sv, "Gives the player the specified item, maxing it out"sv, ""sv, diff --git a/Runtime/MP1/World/CFireFlea.cpp b/Runtime/MP1/World/CFireFlea.cpp index da8023c6e..618a358f7 100644 --- a/Runtime/MP1/World/CFireFlea.cpp +++ b/Runtime/MP1/World/CFireFlea.cpp @@ -90,6 +90,120 @@ void CFireFlea::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM bool CFireFlea::InPosition(CStateManager& mgr, float dt) { if (x2dc_destObj == kInvalidUniqueId) return false; - return (xd80_ - GetTranslation()).magnitude() < 25.f; + return (xd80_targetPos - GetTranslation()).magnitude() < 25.f; +} + +bool CFireFlea::HearShot(urde::CStateManager& mgr, float arg) { + x570_nearList.clear(); + mgr.BuildNearList(x570_nearList, zeus::CAABox(GetTranslation() - 10.f, GetTranslation() + 10.f), + CMaterialFilter::MakeInclude({EMaterialTypes::Projectile}), nullptr); + + return !x570_nearList.empty(); +} + +void CFireFlea::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + CPatterned::Patrol(mgr, msg, arg); + UpdateDest(mgr); + xd80_targetPos = x2e0_destPos; + } else if (msg == EStateMsg::Update) { + if (auto* pathFind = GetSearchPath()) { + if (pathFind->GetResult() != CPathFindSearch::EResult::Success) { + zeus::CVector3f closestPoint = zeus::CVector3f::skZero; + if (pathFind->FindClosestReachablePoint(GetTranslation(), closestPoint) == CPathFindSearch::EResult::Success) { + zeus::CVector3f delta = FindSafeRoute(mgr, x45c_steeringBehaviors.Arrival(*this, xd80_targetPos, 5.f)); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(delta, {}, 1.f)); + } + } else { + PathFind(mgr, msg, arg); + } + } else { + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCLocomotionCmd(x45c_steeringBehaviors.Arrival(*this, xd80_targetPos, 5.f), {}, 1.f)); + } + } +} + +zeus::CVector3f CFireFlea::FindSafeRoute(CStateManager& mgr, const zeus::CVector3f& forward) { + float mag = forward.magnitude(); + if (mag > 0.f) { + CRayCastResult res = mgr.RayStaticIntersection(GetTranslation(), forward.normalized(), 1.f, + CMaterialFilter::MakeInclude({EMaterialTypes::Solid})); + if (res.IsValid() || CheckNearWater(mgr, forward.normalized())) { + zeus::CVector3f right = forward.normalized().cross(zeus::CVector3f::skUp).normalized(); + CRayCastResult res1 = mgr.RayStaticIntersection(GetTranslation(), right, 1.f, + CMaterialFilter::MakeInclude({EMaterialTypes::Solid})); + if (res1.IsValid()) { + zeus::CVector3f left = -right; + CRayCastResult res2 = mgr.RayStaticIntersection(GetTranslation(), left, 1.f, + CMaterialFilter::MakeInclude({EMaterialTypes::Solid})); + if (res2.IsValid()) { + zeus::CVector3f up = right.cross(forward.normalized()); + CRayCastResult res3 = mgr.RayStaticIntersection(GetTranslation(), up, 1.f, + CMaterialFilter::MakeInclude({EMaterialTypes::Solid})); + if (res3.IsValid()) { + zeus::CVector3f down = -up; + CRayCastResult res4 = mgr.RayStaticIntersection(GetTranslation(), down, 1.f, + CMaterialFilter::MakeInclude({EMaterialTypes::Solid})); + if (res4.IsValid()) { + return mag * down; + } else { + return -forward; + } + } else { + return mag * up; + } + } else { + return mag * left; + } + } else { + return mag * right; + } + } else { + return forward; + } + } + return {}; +} + +bool CFireFlea::CheckNearWater(const CStateManager& mgr, const zeus::CVector3f& dir) { + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, GetTranslation(), dir, 2.f, CMaterialFilter::skPassEverything, nullptr); + + for (TUniqueId id : nearList) { + if (TCastToConstPtr water = mgr.GetObjectById(id)) + return true; + } + + return false; +} + +void CFireFlea::Patrol(CStateManager& mgr, EStateMsg msg, float arg) { + if (!zeus::close_enough(x310_moveVec, {})) + x310_moveVec.normalize(); + + x310_moveVec = FindSafeRoute(mgr, x310_moveVec); + CPatterned::Patrol(mgr, msg, arg); + if (x2d8_patrolState == EPatrolState::Done) + mgr.FreeScriptObject(GetUniqueId()); +} + +void CFireFlea::Flee(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + } else if (msg == EStateMsg::Update) { + if (x570_nearList.empty()) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(FindSafeRoute(mgr, xd74_), {}, 1.f)); + } else { + for (TUniqueId id : x570_nearList) { + if (const CActor* act = static_cast(mgr.GetObjectById(id))) { + zeus::CVector3f fleeDirection = x45c_steeringBehaviors.Flee(*this, act->GetTranslation()); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(FindSafeRoute(mgr, fleeDirection), {}, 1.f)); + } + } + } + } else if (msg == EStateMsg::Deactivate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + } } } // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CFireFlea.hpp b/Runtime/MP1/World/CFireFlea.hpp index 5c8612773..c42dbdba0 100644 --- a/Runtime/MP1/World/CFireFlea.hpp +++ b/Runtime/MP1/World/CFireFlea.hpp @@ -24,13 +24,15 @@ class CFireFlea : public CPatterned { }; float x568_ = 1.f; float x56c_; - u32 x570_ = 0; + rstl::reserved_vector x570_nearList; float xe64_; zeus::CVector3f xd74_; - zeus::CVector3f xd80_; + zeus::CVector3f xd80_targetPos; CPathFindSearch xd8c_pathFind; static s32 sLightIdx; + zeus::CVector3f FindSafeRoute(CStateManager& mgr, const zeus::CVector3f& forward); + bool CheckNearWater(const CStateManager&, const zeus::CVector3f& dir); public: DEFINE_PATTERNED(FireFlea) @@ -43,6 +45,10 @@ public: void Dead(CStateManager&, EStateMsg msg, float dt); bool Delay(CStateManager&, float arg); bool InPosition(CStateManager& mgr, float dt); + bool HearShot(CStateManager&, float); + void TargetPatrol(CStateManager&, EStateMsg, float); + void Patrol(CStateManager&, EStateMsg, float); + void Flee(CStateManager&, EStateMsg, float); CPathFindSearch* GetSearchPath() { return &xd8c_pathFind; } }; } // namespace urde::MP1 \ No newline at end of file diff --git a/hecl b/hecl index 82a7890e9..395cf73e4 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 82a7890e99da98fcc9770fb21c73f7837f285f66 +Subproject commit 395cf73e46fd746fb0c8ffb77b1c11c9f2148803 From 11c3c557bda5f7d1e6bacbfba79f9b0f0cbde443 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Mon, 10 Dec 2018 20:17:02 -0800 Subject: [PATCH 2/3] Initiial CPuddleSpore imp --- Runtime/MP1/World/CMakeLists.txt | 3 +- Runtime/MP1/World/CPuddleSpore.cpp | 68 ++++++++++++++++++++++++++++++ Runtime/MP1/World/CPuddleSpore.hpp | 42 ++++++++++++++++++ Runtime/World/CPatternedInfo.hpp | 1 + Runtime/World/ScriptLoader.cpp | 20 ++++++++- 5 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 Runtime/MP1/World/CPuddleSpore.cpp create mode 100644 Runtime/MP1/World/CPuddleSpore.hpp diff --git a/Runtime/MP1/World/CMakeLists.txt b/Runtime/MP1/World/CMakeLists.txt index 5090d44f8..0e26acd38 100644 --- a/Runtime/MP1/World/CMakeLists.txt +++ b/Runtime/MP1/World/CMakeLists.txt @@ -29,6 +29,7 @@ set(MP1_WORLD_SOURCES CRidley.hpp CRidley.cpp CPuddleToadGamma.hpp CPuddleToadGamma.cpp CFlaahgraProjectile.hpp CFlaahgraProjectile.cpp - CSpankWeed.hpp CSpankWeed.cpp) + CSpankWeed.hpp CSpankWeed.cpp + CPuddleSpore.hpp CPuddleSpore.cpp) runtime_add_list(World MP1_WORLD_SOURCES) diff --git a/Runtime/MP1/World/CPuddleSpore.cpp b/Runtime/MP1/World/CPuddleSpore.cpp new file mode 100644 index 000000000..746c42620 --- /dev/null +++ b/Runtime/MP1/World/CPuddleSpore.cpp @@ -0,0 +1,68 @@ +#include "CPuddleSpore.hpp" +#include "World/CPatternedInfo.hpp" +#include "CStateManager.hpp" +#include "GameGlobalObjects.hpp" +#include "CSimplePool.hpp" +#include "TCastTo.hpp" + +namespace urde::MP1 { +const std::string_view CPuddleSpore::kEyeLocators[16] = { + "Glow_1_LCTR"sv, + "Glow_2_LCTR"sv, + "Glow_3_LCTR"sv, + "Glow_4_LCTR"sv, + "Glow_5_LCTR"sv, + "Glow_6_LCTR"sv, + "Glow_7_LCTR"sv, + "Glow_8_LCTR"sv, + "Glow_9_LCTR"sv, + "Glow_10_LCTR"sv, + "Glow_11_LCTR"sv, + "Glow_12_LCTR"sv, + "Glow_13_LCTR"sv, + "Glow_14_LCTR"sv, + "Glow_15_LCTR"sv, + "Glow_16_LCTR"sv, +}; +CPuddleSpore::CPuddleSpore(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, + const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, + EColliderType colType, CAssetId glowFx, float f1, float f2, float f3, float f4, float f5, + const CActorParameters& actParms, CAssetId weapon, const CDamageInfo& dInfo) +: CPatterned(ECharacter::PuddleSpore, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, + colType, EBodyType::Restricted, actParms, EKnockBackVariant::Medium) +, x570_(f1) +, x574_(f2) +, x578_(f3) +, x57c_(f4) +, x580_(f5) +, x584_bodyOrigin(pInfo.GetBodyOrigin()) +, x590_halfExtent(pInfo.GetHalfExtent()) +, x594_height(pInfo.GetHeight()) +, x5a0_(CalculateBoundingBox(), GetMaterialList()) +, x5ec_projectileInfo(weapon, dInfo) +, x5d0_(g_SimplePool->GetObj({SBIG('PART'), glowFx})) +, x614_24(false) +, x614_25(false) { + x5dc_.reserve(kEyeCount); + for (u32 i = 0; i < kEyeCount; ++i) + x5dc_.emplace_back(new CElementGen(x5d0_)); + const_cast*>(&x5ec_projectileInfo.Token())->Lock(); + x460_knockBackController.SetAutoResetImpulse(false); +} + +zeus::CAABox CPuddleSpore::CalculateBoundingBox() const { + return {((zeus::CVector3f(-x590_halfExtent, -x590_halfExtent, x598_) + x584_bodyOrigin) * 0.5f) + + (GetBaseBoundingBox().min * 0.95f), + ((zeus::CVector3f(x590_halfExtent, x590_halfExtent, (x594_height * x59c_) + x598_) + x584_bodyOrigin) * 0.5f) + + (GetBaseBoundingBox().max * 0.95f)}; +} + +void CPuddleSpore::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::InvulnDamage) + return; + if (msg == EScriptObjectMessage::Registered) + x450_bodyController->Activate(mgr); + + CPatterned::AcceptScriptMsg(msg, uid, mgr); +} +} \ No newline at end of file diff --git a/Runtime/MP1/World/CPuddleSpore.hpp b/Runtime/MP1/World/CPuddleSpore.hpp new file mode 100644 index 000000000..00fd5c667 --- /dev/null +++ b/Runtime/MP1/World/CPuddleSpore.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "World/CPatterned.hpp" +#include "Weapon/CProjectileInfo.hpp" +#include "Particle/CElementGen.hpp" + +namespace urde::MP1 { +class CPuddleSpore : public CPatterned { + static constexpr u32 kEyeCount = 16; + static const std::string_view kEyeLocators[16]; + float x568_ = 0.f; + float x56c_ = 0.f; + float x570_; + float x574_; + float x578_; + float x57c_; + float x580_; + zeus::CVector3f x584_bodyOrigin; + float x590_halfExtent; + float x594_height; + float x598_ = 0.f; + float x59c_ = 1.f; + CCollidableAABox x5a0_; + u32 x5c8_ = 0; + u32 x5cc_ = 0; + TToken x5d0_; + std::vector> x5dc_; // originally a vector of CElementGen + CProjectileInfo x5ec_projectileInfo; + bool x614_24 : 1; + bool x614_25 : 1; +public: + DEFINE_PATTERNED(PuddleSpore) + + CPuddleSpore(TUniqueId, std::string_view, EFlavorType, const CEntityInfo&, const zeus::CTransform&, + CModelData&&, const CPatternedInfo&, EColliderType, CAssetId, float, float, float, float, float, + const CActorParameters&, CAssetId, const CDamageInfo&); + + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); + zeus::CAABox CalculateBoundingBox() const; + CProjectileInfo* GetProjectileInfo() { return &x5ec_projectileInfo; } +}; +} \ No newline at end of file diff --git a/Runtime/World/CPatternedInfo.hpp b/Runtime/World/CPatternedInfo.hpp index c4308470b..67536d236 100644 --- a/Runtime/World/CPatternedInfo.hpp +++ b/Runtime/World/CPatternedInfo.hpp @@ -61,6 +61,7 @@ public: float GetHalfExtent() const { return xc4_halfExtent; } float GetHeight() const { return xc8_height; } const CHealthInfo& GetHealthInfo() const { return x54_healthInfo; } + zeus::CVector3f GetBodyOrigin() const { return xcc_bodyOrigin; } CAnimationParameters& GetAnimationParameters() { return xec_animParams; } const CAnimationParameters& GetAnimationParameters() const { return xec_animParams; } u32 GetPathfindingIndex() const { return x10c_pathfindingIndex; } diff --git a/Runtime/World/ScriptLoader.cpp b/Runtime/World/ScriptLoader.cpp index be9dbcde0..da4b61ee4 100644 --- a/Runtime/World/ScriptLoader.cpp +++ b/Runtime/World/ScriptLoader.cpp @@ -48,6 +48,7 @@ #include "CScriptEffect.hpp" #include "CScriptGenerator.hpp" #include "CScriptGrapplePoint.hpp" +#include "MP1/World/CPuddleSpore.hpp" #include "CScriptHUDMemo.hpp" #include "CScriptMazeNode.hpp" #include "CScriptMemoryRelay.hpp" @@ -1605,8 +1606,25 @@ CEntity* ScriptLoader::LoadPuddleSpore(CStateManager& mgr, CInputStream& in, int return nullptr; CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + bool b1 = in.readBool(); + CAssetId w1(in); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + float f5 = in.readFloatBig(); + CAssetId w2(in); + CDamageInfo dInfo(in); - return nullptr; + const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); + if (g_ResFactory->GetResourceTypeById(animParms.GetACSFile()) != SBIG('ANCS')) + return nullptr; + + CModelData mData( + CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true)); + return new MP1::CPuddleSpore(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, + CPatterned::EColliderType(b1), w1, f1, f2, f3, f4, f5, actParms, w2, dInfo); } CEntity* ScriptLoader::LoadDebugCameraWaypoint(CStateManager& mgr, CInputStream& in, int propCount, From d30ceb66114b463183d8c768592c57cab7ce479b Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Wed, 12 Dec 2018 11:50:37 -0800 Subject: [PATCH 3/3] More CPuddleSpore implementations --- Runtime/Character/CharacterCommon.hpp | 2 +- Runtime/MP1/World/CPuddleSpore.cpp | 248 +++++++++++++++++++++++++- Runtime/MP1/World/CPuddleSpore.hpp | 43 ++++- Runtime/Particle/CElementGen.cpp | 2 +- Runtime/World/CPatterned.cpp | 5 + Runtime/World/CPatterned.hpp | 1 + 6 files changed, 296 insertions(+), 5 deletions(-) diff --git a/Runtime/Character/CharacterCommon.hpp b/Runtime/Character/CharacterCommon.hpp index 4354a5e60..8349174fd 100644 --- a/Runtime/Character/CharacterCommon.hpp +++ b/Runtime/Character/CharacterCommon.hpp @@ -80,7 +80,7 @@ enum class EStepType { Normal = 0, Dodge = 1 }; enum class ESeverity { Invalid = -1, Zero = 0, One = 1 }; -enum class EGetupType { Invalid = -1 }; +enum class EGetupType { Invalid = -1, Zero }; enum class ELoopState { Invalid = -1, Begin, Loop, End }; diff --git a/Runtime/MP1/World/CPuddleSpore.cpp b/Runtime/MP1/World/CPuddleSpore.cpp index 746c42620..851930713 100644 --- a/Runtime/MP1/World/CPuddleSpore.cpp +++ b/Runtime/MP1/World/CPuddleSpore.cpp @@ -1,5 +1,10 @@ #include "CPuddleSpore.hpp" +#include "Collision/CGameCollision.hpp" +#include "Weapon/CEnergyProjectile.hpp" +#include "Weapon/CGameProjectile.hpp" #include "World/CPatternedInfo.hpp" +#include "World/CPlayer.hpp" +#include "World/CScriptWater.hpp" #include "CStateManager.hpp" #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" @@ -43,9 +48,9 @@ CPuddleSpore::CPuddleSpore(TUniqueId uid, std::string_view name, EFlavorType fla , x5d0_(g_SimplePool->GetObj({SBIG('PART'), glowFx})) , x614_24(false) , x614_25(false) { - x5dc_.reserve(kEyeCount); + x5dc_elemGens.reserve(kEyeCount); for (u32 i = 0; i < kEyeCount; ++i) - x5dc_.emplace_back(new CElementGen(x5d0_)); + x5dc_elemGens.emplace_back(new CElementGen(x5d0_)); const_cast*>(&x5ec_projectileInfo.Token())->Lock(); x460_knockBackController.SetAutoResetImpulse(false); } @@ -65,4 +70,243 @@ void CPuddleSpore::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSta CPatterned::AcceptScriptMsg(msg, uid, mgr); } + +bool CPuddleSpore::HitShell(const zeus::CVector3f& point) const { + if (x5c8_ != 1) + return true; + float distance = GetTransform().upVector().dot(zeus::CUnitVector3f(point - GetBoundingBox().center())); + return (distance <= -0.5f || distance >= 0.5f); +} + +void CPuddleSpore::KnockPlayer(CStateManager&, float) { + +} + +void CPuddleSpore::UpdateBoundingState(const zeus::CAABox& box, CStateManager& mgr, float dt) { + SetBoundingBox(box); + x5a0_ = CCollidableAABox(box, x68_material); + zeus::CAABox plBox; + CPlayer& player = mgr.GetPlayer(); + zeus::CAABox selfBox = GetBoundingBox(); + if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) { + const float ballRad = player.GetMorphBall()->GetBallRadius(); + zeus::CVector3f ballOffset = (player.GetTranslation() + zeus::CVector3f{0.f, 0.f, ballRad}); + plBox = zeus::CAABox(ballOffset - ballRad, ballOffset + ballRad); + } else { + plBox = player.GetBoundingBox(); + } + + if (selfBox.intersects(plBox)) { + float bias = (x5c8_ == 2 ? 0.001f : -0.0001f) + (selfBox.max.z() - plBox.min.z()); + if (bias > 0.f && selfBox.max.z() < plBox.max.z()) { + bool hadPlayerMat = player.GetMaterialList().HasMaterial(EMaterialTypes::Player); + if (hadPlayerMat) + player.RemoveMaterial(EMaterialTypes::GroundCollider, mgr); + player.RemoveMaterial(EMaterialTypes::Player, mgr); + CPhysicsState state = player.GetPhysicsState(); + player.MoveToOR(bias * zeus::CVector3f{0.f, 0.f, 1.f}, dt); + CGameCollision::Move(mgr, player, dt, nullptr); + state.SetTranslation(player.GetTranslation()); + player.SetPhysicsState(state); + if (hadPlayerMat) + player.AddMaterial(EMaterialTypes::GroundCollider, mgr); + player.AddMaterial(EMaterialTypes::Player, mgr); + } + } +} + +void CPuddleSpore::PreThink(float dt, CStateManager& mgr) { + if (x5c8_ == 2) + AddMaterial(EMaterialTypes::SolidCharacter, mgr); + else + RemoveMaterial(EMaterialTypes::SolidCharacter, mgr); + + UpdateBoundingState(CalculateBoundingBox(), mgr, dt); + CPatterned::PreThink(dt, mgr); +} + +void CPuddleSpore::Think(float dt, CStateManager& mgr) { + if (x614_25) + x56c_ += dt; + if (x614_24) + x568_ += dt; + HealthInfo(mgr)->SetHP(1000000.0f); + float t = (x56c_ / x570_) - 1.f >= -0.f ? 1.f : x56c_ / x570_; + zeus::CColor modColor = zeus::CColor::lerp(zeus::CColor::skWhite, zeus::CColor(1.f, 1.f, 1.f, 0.f), t); + for (u32 i = 0 ; i < kEyeCount ; ++i) { + const auto& elemGen = x5dc_elemGens[i]; + elemGen->SetModulationColor(modColor); + elemGen->SetTranslation(GetLctrTransform(kEyeLocators[i]).origin); + elemGen->Update(dt); + } + + CPatterned::Think(dt, mgr); +} + +void CPuddleSpore::Render(const CStateManager& mgr) const { + CPatterned::Render(mgr); + if (x56c_ > 0.01f) { + for (const auto& elemGen : x5dc_elemGens) + elemGen->Render(GetActorLights()); + } +} + +void CPuddleSpore::Touch(CActor& act, CStateManager& mgr) { + if (!x400_25_alive) + return; + + if (TCastToPtr proj = act) { + if (proj->GetOwnerId() == mgr.GetPlayer().GetUniqueId()) + x400_24_hitByPlayerProjectile = HitShell(proj->GetTranslation()); + } +} + +void CPuddleSpore::FluidFXThink(EFluidState fState, CScriptWater& water, CStateManager& mgr) { + if (fState != EFluidState::InFluid) + return; + + CFluidPlaneManager* planeManager = mgr.GetFluidPlaneManager(); + if (planeManager->GetLastRippleDeltaTime(GetUniqueId()) >= 2.9f) { + zeus::CVector3f point = GetTranslation(); + point.z() = float(water.GetTriggerBoundsWR().max.z()); + water.GetFluidPlane().AddRipple(2.f, GetUniqueId(), point, water, mgr); + } +} + +void CPuddleSpore::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { + if (type == EUserEventType::Projectile) { + CProjectileInfo* projInfo = GetProjectileInfo(); + if (projInfo->Token() && projInfo->Token().IsLocked() && + mgr.CanCreateProjectile(GetUniqueId(), EWeaponType::AI, 16)) { + mgr.AddObject(new CEnergyProjectile(true, projInfo->Token(), EWeaponType::AI, + GetLctrTransform(node.GetLocatorName()), EMaterialTypes::Character, + projInfo->GetDamage(), mgr.AllocateUniqueId(), GetAreaIdAlways(), + GetUniqueId(), kInvalidUniqueId, EProjectileAttrib::None, false, + zeus::CVector3f::skOne, {}, 0xFFFF, false)); + } + } else + CPatterned::DoUserAnimEvent(mgr, node, type, dt); +} + +bool CPuddleSpore::ShouldTurn(CStateManager& mgr, float) { + zeus::CAABox plBox = mgr.GetPlayer().GetBoundingBox(); + zeus::CAABox selfBox = GetBoundingBox(); + + if (plBox.max.z() >= selfBox.min.z() + selfBox.max.z() * 0.5f || + plBox.max.x() < selfBox.min.x() || + plBox.max.y() < selfBox.min.y() || + selfBox.max.x() < plBox.min.y() || + selfBox.max.y() < plBox.min.y() || + x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Getup) + return x568_ >= x578_; + + return true; +} + +void CPuddleSpore::InActive(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + x56c_ = 0.f; + x598_ = -1.f; + } +} + +void CPuddleSpore::Active(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + x568_ = 0.f; + x56c_ = 0.f; + x598_ = 0.f; + x614_24 = true; + x614_25 = true; + } else if (msg == EStateMsg::Deactivate) { + x614_24 = false; + x614_25 = false; + } +} + +void CPuddleSpore::Run(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x5c8_ = 1; + x5cc_ = 0; + x568_ = 0.f; + x614_24 = false; + x598_ = 0.f; + x59c_ = 1.5f; + } else if (msg == EStateMsg::Update) { + if (x5cc_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::LoopReaction) { + x5cc_ = 1; + x614_24 = true; + } else { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType::Zero)); + } + } else if (x5cc_ == 1 && + x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::LoopReaction) { + x5cc_ = 2; + } + } else if (msg == EStateMsg::Deactivate) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); + x5c8_ = 0; + x59c_ = 1.f; + x614_24 = false; + } +} + +void CPuddleSpore::TurnAround(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x568_ = 0.f; + x56c_ = 0.f; + x400_24_hitByPlayerProjectile = false; + x598_ = -2.5f; + x5c8_ = 2; + x5cc_ = 0; + x614_24 = false; + } else if (msg == EStateMsg::Update) { + if (x5cc_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::LieOnGround) { + x5cc_ = 1; + x614_24 = true; + } else { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCKnockDownCmd({1.f, 0.f, 0.f}, pas::ESeverity::One)); + } + } else if (x5cc_ == 1 && x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::LieOnGround) { + x5cc_ = 2; + } + } else if (msg == EStateMsg::Deactivate) { + x614_24 = false; + } +} + +void CPuddleSpore::GetUp(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType::Zero)); + KnockPlayer(mgr, x580_); + x56c_ = 0.f; + x598_ = -1.f; + x5cc_ = 0; + } else if (msg == EStateMsg::Update) { + KnockPlayer(mgr, x580_ * 0.25f); + if (x5cc_ == 0) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType::Zero)); + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Getup) + x5cc_ = 1; + } else if (x5cc_ == 1 && x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Getup) { + x5cc_ = 1; + } + } else if (msg == EStateMsg::Deactivate) { + x5c8_ = 0; + } +} + +void CPuddleSpore::Attack(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x32c_animState = EAnimState::One; + x598_ = 0.f; + } else if (msg == EStateMsg::Update) { + TryCommand(mgr, pas::EAnimationState::MeleeAttack, &CPatterned::TryMeleeAttack, 1); + } else if (msg == EStateMsg::Deactivate) { + x32c_animState = EAnimState::Zero; + } +} } \ No newline at end of file diff --git a/Runtime/MP1/World/CPuddleSpore.hpp b/Runtime/MP1/World/CPuddleSpore.hpp index 00fd5c667..ffde9979e 100644 --- a/Runtime/MP1/World/CPuddleSpore.hpp +++ b/Runtime/MP1/World/CPuddleSpore.hpp @@ -24,10 +24,14 @@ class CPuddleSpore : public CPatterned { u32 x5c8_ = 0; u32 x5cc_ = 0; TToken x5d0_; - std::vector> x5dc_; // originally a vector of CElementGen + std::vector> x5dc_elemGens; // originally a vector of CElementGen CProjectileInfo x5ec_projectileInfo; bool x614_24 : 1; bool x614_25 : 1; + + bool HitShell(const zeus::CVector3f& ) const; + void KnockPlayer(CStateManager&, float); + void UpdateBoundingState(const zeus::CAABox&, CStateManager&, float); public: DEFINE_PATTERNED(PuddleSpore) @@ -36,7 +40,44 @@ public: const CActorParameters&, CAssetId, const CDamageInfo&); void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); + void PreThink(float, CStateManager&); + void Think(float, CStateManager&); + void Render(const CStateManager&) const; + void Touch(CActor&, CStateManager&); + void FluidFXThink(EFluidState, CScriptWater&, CStateManager&); + void KnockBack(const zeus::CVector3f& dir, CStateManager& mgr, const CDamageInfo& dInfo, EKnockBackType type, + bool inDeferred, float dt) + { + if (x5c8_ == 1) + return; + CPatterned::KnockBack(dir, mgr, dInfo, type, inDeferred, dt); + } + EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f& point, const zeus::CVector3f&, + const CWeaponMode&, EProjectileAttrib) const + { + return HitShell(point) ? EWeaponCollisionResponseTypes::Unknown84 : EWeaponCollisionResponseTypes::Unknown34; + } + void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float); + void CollidedWith(TUniqueId uid, const CCollisionInfoList& colList, CStateManager& mgr) + { + if (x5c8_ == 2) + return; + CPatterned::CollidedWith(uid, colList, mgr); + } + const CCollisionPrimitive* GetCollisionPrimitive() const { return &x5a0_; } zeus::CAABox CalculateBoundingBox() const; CProjectileInfo* GetProjectileInfo() { return &x5ec_projectileInfo; } + + bool InAttackPosition(CStateManager&, float) { return x568_ >= x570_; } + bool ShouldAttack(CStateManager&, float) { return x568_ >= x574_; } + bool ShouldTurn(CStateManager&, float); + bool AnimOver(CStateManager&, float) { return x5cc_ == 2; } + + void InActive(CStateManager&, EStateMsg, float); + void Active(CStateManager&, EStateMsg, float); + void Run(CStateManager&, EStateMsg, float); + void TurnAround(CStateManager&, EStateMsg, float); + void GetUp(CStateManager&, EStateMsg, float); + void Attack(CStateManager&, EStateMsg, float); }; } \ No newline at end of file diff --git a/Runtime/Particle/CElementGen.cpp b/Runtime/Particle/CElementGen.cpp index 638d57d97..e2e0e2c2e 100644 --- a/Runtime/Particle/CElementGen.cpp +++ b/Runtime/Particle/CElementGen.cpp @@ -795,7 +795,7 @@ void CElementGen::Render(const CActorLights* actorLights) { CGraphics::DisableAllLights(); for (std::unique_ptr& child : x290_activePartChildren) - child->Render(); + child->Render(actorLights); CParticleGlobals::SParticleSystem* prevSystem = CParticleGlobals::g_currentParticleSystem; CParticleGlobals::SParticleSystem thisSystem{FOURCC('PART'), this}; diff --git a/Runtime/World/CPatterned.cpp b/Runtime/World/CPatterned.cpp index d99f42d7d..884bdffdf 100644 --- a/Runtime/World/CPatterned.cpp +++ b/Runtime/World/CPatterned.cpp @@ -835,6 +835,9 @@ void CPatterned::TryLoopReaction(CStateManager& mgr, int arg) { void CPatterned::TryProjectileAttack(CStateManager&, int arg) { x450_bodyController->GetCommandMgr().DeliverCmd(CBCProjectileAttackCmd(pas::ESeverity(arg), x2e0_destPos, false)); } +void CPatterned::TryMeleeAttack(CStateManager& mgr, int arg) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity(arg))); +} void CPatterned::TryGenerate(CStateManager& mgr, int arg) { x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType(arg), x2e0_destPos, true)); @@ -1566,4 +1569,6 @@ bool CPatterned::ApplyBoneTracking() const { return false; } + + } // namespace urde diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index 7675d7e95..9f5ff284c 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -318,6 +318,7 @@ public: void TryCommand(CStateManager& mgr, pas::EAnimationState state, CPatternedTryFunc func, int arg); void TryLoopReaction(CStateManager& mgr, int arg); void TryProjectileAttack(CStateManager& mgr, int arg); + void TryMeleeAttack(CStateManager& mgr, int arg); void TryGenerate(CStateManager& mgr, int arg); virtual bool KnockbackWhenFrozen() const { return true; }