Implement CEyeBall, disable CPuddleToadGamma (preventing softlocks), initial CSpankWeed

This commit is contained in:
Phillip Stephens 2018-12-01 18:32:26 -08:00
parent 9948532957
commit 9b2fd002c6
10 changed files with 251 additions and 42 deletions

View File

@ -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<CPlasmaProjectile*>(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<CPlasmaProjectile*>(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<CPlasmaProjectile*>(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<CPlasmaProjectile*>(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);
}
}

View File

@ -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; }
};
}

View File

@ -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)

View File

@ -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;

View File

@ -0,0 +1,49 @@
#include "CSpankWeed.hpp"
#include "World/CPatternedInfo.hpp"
#include <logvisor/logvisor.hpp>
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);
}
}

View File

@ -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<CCollisionActorManager> 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);
};
}

View File

@ -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);

View File

@ -18,4 +18,9 @@ void CPlasmaProjectile::Accept(IVisitor& visitor)
visitor.Visit(this);
}
void CPlasmaProjectile::Fire(const zeus::CTransform&, CStateManager&, bool)
{
SetActive(true);
}
}

View File

@ -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);
};
}

View File

@ -59,13 +59,13 @@ public:
CPatternedInfo(CInputStream& in, u32 pcount);
static std::pair<bool, u32> 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; }
};
}