mirror of https://github.com/AxioDL/metaforce.git
More CPuddleSpore implementations
This commit is contained in:
parent
11c3c557bd
commit
d30ceb6611
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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<TToken<CWeaponDescription>*>(&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<CGameProjectile> 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,10 +24,14 @@ class CPuddleSpore : public CPatterned {
|
|||
u32 x5c8_ = 0;
|
||||
u32 x5cc_ = 0;
|
||||
TToken<CGenDescription> x5d0_;
|
||||
std::vector<std::unique_ptr<CElementGen>> x5dc_; // originally a vector of CElementGen
|
||||
std::vector<std::unique_ptr<CElementGen>> 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);
|
||||
};
|
||||
}
|
|
@ -795,7 +795,7 @@ void CElementGen::Render(const CActorLights* actorLights) {
|
|||
CGraphics::DisableAllLights();
|
||||
|
||||
for (std::unique_ptr<CParticleGen>& child : x290_activePartChildren)
|
||||
child->Render();
|
||||
child->Render(actorLights);
|
||||
|
||||
CParticleGlobals::SParticleSystem* prevSystem = CParticleGlobals::g_currentParticleSystem;
|
||||
CParticleGlobals::SParticleSystem thisSystem{FOURCC('PART'), this};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
Loading…
Reference in New Issue