Lots of CParasite implementations

This commit is contained in:
Jack Andersen 2018-11-11 18:21:36 -10:00
parent 94333e4726
commit bf3636a16e
24 changed files with 1093 additions and 144 deletions

View File

@ -202,7 +202,7 @@ private:
EThermalDrawFlag xf34_thermalFlag = EThermalDrawFlag::Bypass;
TUniqueId xf38_skipCineSpecialFunc = kInvalidUniqueId;
std::list<u32> xf3c_;
std::list<u32> xf54_;
std::list<TUniqueId> xf54_parasiteTelegraphs;
TUniqueId xf6c_playerActorHead = kInvalidUniqueId;
u32 xf70_ = 0;
@ -470,6 +470,7 @@ public:
}
TUniqueId GetPlayerActorHead() const { return xf6c_playerActorHead; }
void SetPlayerActorHead(TUniqueId id) { xf6c_playerActorHead = id; }
std::list<TUniqueId>& GetParasiteTelegraphs() { return xf54_parasiteTelegraphs; }
std::shared_ptr<CWorldLayerState>& WorldLayerStateNC() { return x8c8_worldLayerState; }
static float g_EscapeShakeCountdown;
static bool g_EscapeShakeCountdownInit;

View File

@ -88,8 +88,9 @@ class CBCGenerateCmd : public CBodyStateCmd
bool x1c_25_overrideAnim : 1;
public:
CBCGenerateCmd() : CBodyStateCmd(EBodyStateCmd::Generate) { x1c_24_targetTransform = false; x1c_25_overrideAnim = false; }
CBCGenerateCmd(pas::EGenerateType type, int i)
: CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type) { x1c_24_targetTransform = false; x1c_25_overrideAnim = false; }
CBCGenerateCmd(pas::EGenerateType type, s32 animId = -1)
: CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), x18_animId(animId)
{ x1c_24_targetTransform = false; x1c_25_overrideAnim = false; }
CBCGenerateCmd(pas::EGenerateType type, const zeus::CVector3f& vec)
: CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), xc_targetPos(vec)
{ x1c_24_targetTransform = false; x1c_25_overrideAnim = false; }

View File

@ -12,7 +12,7 @@ namespace urde
CParticleDatabase::CParticleDatabase()
{
xb4_24_active = true;
xb4_24_updatesEnabled = true;
xb4_25_anySystemsDrawnWithModel = false;
}
@ -227,7 +227,7 @@ void CParticleDatabase::UpdateParticleGenDB(float dt, const CPoseAsTransforms& p
void CParticleDatabase::Update(float dt, const CPoseAsTransforms& pose, const CCharLayoutInfo& charInfo,
const zeus::CTransform& xf, const zeus::CVector3f& scale, CStateManager& stateMgr)
{
if (!xb4_24_active)
if (!xb4_24_updatesEnabled)
return;
UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, x3c_rendererDrawLoop, true);

View File

@ -25,7 +25,7 @@ class CParticleDatabase
std::map<std::string, std::unique_ptr<CParticleGenInfo>> x78_rendererDraw;
std::map<std::string, std::unique_ptr<CParticleGenInfo>> x8c_firstDraw;
std::map<std::string, std::unique_ptr<CParticleGenInfo>> xa0_lastDraw;
bool xb4_24_active : 1;
bool xb4_24_updatesEnabled : 1;
bool xb4_25_anySystemsDrawnWithModel : 1;
static void SetModulationColorAllActiveEffectsForParticleDB(const zeus::CColor& color,
@ -69,6 +69,7 @@ public:
void InsertParticleGen(bool oneShot, int flags, std::string_view name,
std::unique_ptr<CParticleGenInfo>&& gen);
bool AreAnySystemsDrawnWithModel() const { return xb4_25_anySystemsDrawnWithModel; }
void SetUpdatesEnabled(bool active) { xb4_24_updatesEnabled = active; }
};
}

View File

@ -3,6 +3,108 @@
namespace urde
{
zeus::CVector3f CSteeringBehaviors::Flee(const CPhysicsActor& actor,
const zeus::CVector3f& v0) const
{
return {};
}
zeus::CVector3f CSteeringBehaviors::Seek(const CPhysicsActor& actor,
const zeus::CVector3f& v0) const
{
return {};
}
zeus::CVector3f CSteeringBehaviors::Arrival(const CPhysicsActor& actor,
const zeus::CVector3f& v0, float f1) const
{
return {};
}
zeus::CVector3f CSteeringBehaviors::Pursuit(const CPhysicsActor& actor,
const zeus::CVector3f& v0, const zeus::CVector3f& v1) const
{
return {};
}
zeus::CVector3f CSteeringBehaviors::Separation(const CPhysicsActor& actor,
const zeus::CVector3f& v0, float f1) const
{
return {};
}
zeus::CVector3f CSteeringBehaviors::Alignment(const CPhysicsActor& actor,
rstl::reserved_vector<TUniqueId, 1024>& list, const CStateManager& mgr) const
{
return {};
}
zeus::CVector3f CSteeringBehaviors::Cohesion(const CPhysicsActor& actor,
rstl::reserved_vector<TUniqueId, 1024>& list, float f1, const CStateManager& mgr) const
{
return {};
}
zeus::CVector3f CSteeringBehaviors::Flee2D(const CPhysicsActor& actor,
const zeus::CVector2f& v0) const
{
return {};
}
zeus::CVector3f CSteeringBehaviors::Arrival2D(const CPhysicsActor& actor,
const zeus::CVector2f& v0, float f1) const
{
return {};
}
bool CSteeringBehaviors::SolveQuadratic(float f30, float f31, float f3, float f4, float& out1, float& out2)
{
float f1 = f31 * f31 - 4.f * f30 * f3;
if (f1 > FLT_EPSILON && std::fabs(f1) < FLT_EPSILON)
return false;
out1 = -f31 + std::sqrt(f1) / 2.f * f30;
out2 = -f31 - std::sqrt(f1) / 2.f * f30;
return true;
}
bool CSteeringBehaviors::SolveCubic(
const rstl::reserved_vector<float, 4>& in, rstl::reserved_vector<float, 4>& out)
{
return false;
}
bool CSteeringBehaviors::SolveQuartic(
const rstl::reserved_vector<float, 5>& in, rstl::reserved_vector<float, 4>& out)
{
return false;
}
zeus::CVector3f CSteeringBehaviors::ProjectLinearIntersection(const zeus::CVector3f& v0, float f1,
const zeus::CVector3f& v1, const zeus::CVector3f& v2, zeus::CVector3f& v3)
{
return {};
}
zeus::CVector3f CSteeringBehaviors::ProjectLinearIntersection(const zeus::CVector3f& v0, float f1,
const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3, zeus::CVector3f& v4)
{
return {};
}
zeus::CVector3f CSteeringBehaviors::ProjectOrbitalIntersection(const zeus::CVector3f& v0, float f1,
const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3, zeus::CVector3f& v4)
{
return {};
}
zeus::CVector3f CSteeringBehaviors::ProjectOrbitalIntersection(const zeus::CVector3f& v0, float f1,
const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3,
const zeus::CVector3f& v4, zeus::CVector3f& v5)
{
return {};
}
zeus::CVector3f
CSteeringBehaviors::ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeus::CVector3f& vel,
const zeus::CVector3f& orbitPoint, float dt, float preThinkDt)
@ -35,15 +137,4 @@ CSteeringBehaviors::ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeu
return usePos;
}
bool CSteeringBehaviors::SolveQuadratic(float f30, float f31, float f3, float f4, float& out1, float& out2)
{
float f1 = f31 * f31 - 4.f * f30 * f3;
if (f1 > FLT_EPSILON && std::fabs(f1) < FLT_EPSILON)
return false;
out1 = -f31 + std::sqrt(f1) / 2.f * f30;
out2 = -f31 - std::sqrt(f1) / 2.f * f30;
return true;
}
}

View File

@ -5,14 +5,40 @@
namespace urde
{
class CPhysicsActor;
class CStateManager;
class CSteeringBehaviors
{
float x0_ = M_PIF / 2.f;
public:
zeus::CVector3f Flee(const CPhysicsActor& actor, const zeus::CVector3f& v0) const;
zeus::CVector3f Seek(const CPhysicsActor& actor, const zeus::CVector3f& v0) const;
zeus::CVector3f Arrival(const CPhysicsActor& actor, const zeus::CVector3f& v0, float f1) const;
zeus::CVector3f Pursuit(const CPhysicsActor& actor, const zeus::CVector3f& v0, const zeus::CVector3f& v1) const;
zeus::CVector3f Separation(const CPhysicsActor& actor, const zeus::CVector3f& v0, float f1) const;
zeus::CVector3f Alignment(const CPhysicsActor& actor, rstl::reserved_vector<TUniqueId, 1024>& list,
const CStateManager& mgr) const;
zeus::CVector3f Cohesion(const CPhysicsActor& actor, rstl::reserved_vector<TUniqueId, 1024>& list,
float f1, const CStateManager& mgr) const;
zeus::CVector3f Flee2D(const CPhysicsActor& actor, const zeus::CVector2f& v0) const;
zeus::CVector3f Arrival2D(const CPhysicsActor& actor, const zeus::CVector2f& v0, float f1) const;
static bool SolveQuadratic(float, float, float, float, float&, float&);
static bool SolveCubic(const rstl::reserved_vector<float, 4>& in, rstl::reserved_vector<float, 4>& out);
static bool SolveQuartic(const rstl::reserved_vector<float, 5>& in, rstl::reserved_vector<float, 4>& out);
static zeus::CVector3f ProjectLinearIntersection(const zeus::CVector3f& v0, float f1,
const zeus::CVector3f& v1, const zeus::CVector3f& v2, zeus::CVector3f& v3);
static zeus::CVector3f ProjectLinearIntersection(const zeus::CVector3f& v0, float f1,
const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3,
zeus::CVector3f& v4);
static zeus::CVector3f ProjectOrbitalIntersection(const zeus::CVector3f& v0, float f1,
const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3,
zeus::CVector3f& v4);
static zeus::CVector3f ProjectOrbitalIntersection(const zeus::CVector3f& v0, float f1,
const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3,
const zeus::CVector3f& v4, zeus::CVector3f& v5);
static zeus::CVector3f ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeus::CVector3f& vel,
const zeus::CVector3f& orbitPoint, float dt, float preThinkDt);
static bool SolveQuadratic(float, float, float, float, float&, float&);
};
}

View File

@ -166,7 +166,9 @@ enum class ELoopAttackType
enum class EGenerateType
{
Invalid = -1
Invalid = -1,
Zero,
One
};
enum class ESlideType

View File

@ -208,13 +208,6 @@ CCollidableSphere::CCollidableSphere(const zeus::CSphere& sphere, const CMateria
{
}
const zeus::CSphere& CCollidableSphere::GetSphere() const { return x10_sphere; }
void CCollidableSphere::SetSphereCenter(const zeus::CVector3f& center)
{
x10_sphere.position = center;
}
zeus::CSphere CCollidableSphere::Transform(const zeus::CTransform& xf) const
{
return zeus::CSphere(xf * x10_sphere.position, x10_sphere.radius);
@ -257,10 +250,6 @@ CRayCastResult CCollidableSphere::CastRayInternal(const CInternalRayCastStructur
return {};
}
const CCollisionPrimitive::Type& CCollidableSphere::GetType() { return sType; }
void CCollidableSphere::SetStaticTableIndex(u32 index) { sTableIndex = index; }
bool CCollidableSphere::CollideMovingAABox(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir,
double& dOut, CCollisionInfo& infoOut)
{

View File

@ -22,8 +22,8 @@ class CCollidableSphere : public CCollisionPrimitive
public:
CCollidableSphere(const zeus::CSphere&, const CMaterialList&);
const zeus::CSphere& GetSphere() const;
void SetSphereCenter(const zeus::CVector3f& center);
const zeus::CSphere& GetSphere() const { return x10_sphere; }
void SetSphereCenter(const zeus::CVector3f& center) { x10_sphere.position = center; }
zeus::CSphere Transform(const zeus::CTransform& xf) const;
virtual u32 GetTableIndex() const;
@ -32,8 +32,8 @@ public:
virtual FourCC GetPrimType() const;
virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const;
static const Type& GetType();
static void SetStaticTableIndex(u32 index);
static const Type& GetType() { return sType; }
static void SetStaticTableIndex(u32 index) { sTableIndex = index; }
static bool CollideMovingAABox(const CInternalCollisionStructure&, const zeus::CVector3f&, double&,
CCollisionInfo&);
static bool CollideMovingSphere(const CInternalCollisionStructure&, const zeus::CVector3f&, double&,

View File

@ -26,7 +26,7 @@ public:
void MorphVertices(std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn,
const float* magnitudes, const TLockedToken<CSkinRules>& skinRules,
const CPoseAsTransforms& pose) const;
void Reset(const zeus::CVector3f& dir, const zeus::CVector3f& pos, float duration) {}
void Update(float) {}
};

View File

@ -5,8 +5,13 @@
#include "World/CWorld.hpp"
#include "World/CGameArea.hpp"
#include "World/CPlayer.hpp"
#include "World/CScriptWaypoint.hpp"
#include "CStateManager.hpp"
#include "TCastTo.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "Graphics/CSkinnedModel.hpp"
#include "Collision/CGameCollision.hpp"
namespace urde::MP1
{
@ -21,10 +26,10 @@ CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, c
const zeus::CTransform &xf, CModelData &&mData, const CPatternedInfo &pInfo, EBodyType bodyType,
float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9,
float f10, float f11, float f12, float f13, float f14, float f15, float f16, float f17, float f18,
bool b1, u32 w1, const CDamageVulnerability& dVuln,const CDamageInfo& parInfo, u16 sfxId1,
u16 sfxId2, u16 sfxId3, u32 w2, u32 w3, float f19, const CActorParameters &aParams)
bool b1, EWalkerType wType, const CDamageVulnerability& dVuln,const CDamageInfo& parInfo, u16 sfxId1,
u16 sfxId2, u16 sfxId3, CAssetId modelRes, CAssetId skinRes, float f19, const CActorParameters &aParams)
: CWallWalker(ECharacter::Parasite, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer,
EColliderType::Zero, bodyType, aParams, f7, f4, EKnockBackVariant::Small, f2, w1, f17, b1)
EColliderType::Zero, bodyType, aParams, f7, f4, EKnockBackVariant::Small, f2, wType, f17, b1)
, x64c_(dVuln)
, x6b4_(parInfo)
, x6d0_(f1)
@ -43,28 +48,38 @@ CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, c
, x708_(pInfo.GetHeight() * 0.5f)
, x710_(f18)
, x714_(f19)
, x73c_(CSfxManager::TranslateSFXID(sfxId1))
, x73e_(CSfxManager::TranslateSFXID(sfxId2))
, x740_(CSfxManager::TranslateSFXID(sfxId3))
, x73c_haltSfx(CSfxManager::TranslateSFXID(sfxId1))
, x73e_getUpSfx(CSfxManager::TranslateSFXID(sfxId2))
, x740_crouchSfx(CSfxManager::TranslateSFXID(sfxId3))
{
x742_28_ = true;
x742_30_ = true;
x742_28_onGround = true;
x742_30_attackOver = true;
switch(x5d0_)
switch (x5d0_walkerType)
{
case 2:
case EWalkerType::Geemer:
x460_knockBackController.SetEnableFreeze(false);
case 1:
case EWalkerType::Oculus:
x460_knockBackController.SetAutoResetImpulse(false);
break;
case 3:
case EWalkerType::IceZoomer:
{
TLockedToken<CModel> model = g_SimplePool->GetObj({FOURCC('CMDL'), modelRes});
TLockedToken<CModel> skin = g_SimplePool->GetObj({FOURCC('CSKR'), skinRes});
x624_extraModel = CToken(
TObjOwnerDerivedFromIObj<CSkinnedModel>::GetNewDerivedObject(std::make_unique<CSkinnedModel>(
model, skin, x64_modelData->AnimationData()->GetModelData()->GetLayoutInfo(), 1, 1)));
}
default:
break;
}
if (x5d0_ == 1)
if (x5d0_walkerType == EWalkerType::Oculus)
{
x460_knockBackController.SetEnableShock(false);
x460_knockBackController.SetEnableBurn(false);
x460_knockBackController.SetEnableBurnDeath(false);
x460_knockBackController.SetEnableExplodeDeath(false);
x460_knockBackController.SetX82_24(false);
}
}
@ -81,18 +96,18 @@ void CParasite::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM
else if (msg == EScriptObjectMessage::Deleted)
{
//mgr.xf54_.sub80125d88(GetUniqueId());
if (x5d0_ != 3)
if (x5d0_walkerType != EWalkerType::IceZoomer)
DestroyActorManager(mgr);
}
else if (msg == EScriptObjectMessage::Jumped && x742_25_)
else if (msg == EScriptObjectMessage::Jumped && x742_25_jumpVelDirty)
{
UpdateJumpVelocity();
x742_25_ = false;
x742_25_jumpVelDirty = false;
}
else if (msg == EScriptObjectMessage::Activate)
{
x5d6_27_ = false;
if (x5d0_ != 0)
if (x5d0_walkerType != EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
}
else if (msg == EScriptObjectMessage::SuspendedMove)
@ -103,7 +118,7 @@ void CParasite::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM
void CParasite::PreThink(float dt, CStateManager& mgr)
{
CWallWalker::PreThink(dt, mgr);
x743_26_ = false;
x743_26_oculusShotAt = false;
}
void CParasite::Think(float dt, CStateManager& mgr)
@ -112,7 +127,7 @@ void CParasite::Think(float dt, CStateManager& mgr)
return;
++x5d4_;
if (x5d0_ == 3)
if (x5d0_walkerType == EWalkerType::IceZoomer)
UpdateCollisionActors(mgr);
x5d6_26_ = false;
@ -167,7 +182,7 @@ void CParasite::Think(float dt, CStateManager& mgr)
{
CPlayer* pl = mgr.Player();
float radius;
if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && !x742_30_)
if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && !x742_30_attackOver)
radius = x590_colSphere.GetSphere().radius;
else
radius = x708_;
@ -177,10 +192,10 @@ void CParasite::Think(float dt, CStateManager& mgr)
if (plBox && plBox->intersects(aabox))
{
if (!x742_30_)
if (!x742_30_attackOver)
{
x742_30_ = true;
x742_27_ = false;
x742_30_attackOver = true;
x742_27_landed = false;
}
if (x420_curDamageRemTime <= 0.f)
@ -204,7 +219,628 @@ void CParasite::Think(float dt, CStateManager& mgr)
if (x5d6_24_)
AlignToFloor(mgr, x590_colSphere.GetSphere().radius, GetTranslation() + 2.f * dt * x138_velocity, dt);
x742_27_ = false;
x742_27_landed = false;
}
void CParasite::Render(const CStateManager& mgr) const
{
CWallWalker::Render(mgr);
}
const CDamageVulnerability* CParasite::GetDamageVulnerability() const
{
switch (x5d0_walkerType)
{
case EWalkerType::Oculus:
if (x743_24_)
return &x64c_;
break;
case EWalkerType::IceZoomer:
if (!x743_25_)
return &CDamageVulnerability::ImmuneVulnerabilty();
break;
default:
break;
}
return CAi::GetDamageVulnerability();
}
void CParasite::Touch(CActor& actor, CStateManager& mgr)
{
CPatterned::Touch(actor, mgr);
}
zeus::CVector3f CParasite::GetAimPosition(const CStateManager&, float) const
{
return GetTranslation();
}
void CParasite::CollidedWith(TUniqueId uid, const CCollisionInfoList& list, CStateManager&)
{
static CMaterialList testList(EMaterialTypes::Character, EMaterialTypes::Player);
if (x743_27_inJump)
{
for (const auto& info : list)
{
if (!x5d6_24_ && info.GetMaterialLeft().Intersection(testList) == 0)
{
OrientToSurfaceNormal(info.GetNormalLeft(), 360.f);
CPhysicsActor::Stop();
SetVelocityWR(zeus::CVector3f::skZero);
x742_27_landed = true;
x742_28_onGround = true;
}
}
}
}
void CParasite::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state)
{
CPhysicsActor::Stop();
TelegraphAttack(mgr, EStateMsg::Activate, 0.f);
SetMomentumWR({0.f, 0.f, -GetWeight()});
CPatterned::Death(mgr, direction, state);
}
void CParasite::Patrol(CStateManager& mgr, EStateMsg msg, float dt)
{
switch (msg)
{
case EStateMsg::Activate:
x742_26_ = true;
x5d6_24_ = true;
if (!x5d6_27_ && x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
SetMomentumWR(zeus::CVector3f::skZero);
x5d6_25_ = false;
xf8_24_movable = false;
break;
case EStateMsg::Update:
if (x5bc_ > 0.f)
{
x5bc_ -= dt;
if (x5bc_ <= 0.f)
{
if (x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
x5bc_ = 0.f;
}
}
GotoNextWaypoint(mgr);
if (x5bc_ <= 0.f && !x5d6_27_)
DoFlockingBehavior(mgr);
break;
case EStateMsg::Deactivate:
x5d6_24_ = false;
xf8_24_movable = true;
break;
default:
break;
}
}
void CParasite::UpdatePFDestination(CStateManager& mgr)
{
// Empty
}
void CParasite::DoFlockingBehavior(CStateManager& mgr)
{
zeus::CVector3f upVec = x34_transform.basis[2];
rstl::reserved_vector<TUniqueId, 1024> _834;
zeus::CAABox aabb(GetTranslation() - x6e4_, GetTranslation() + x6e4_);
if (x5d4_ % 6 == 0)
{
rstl::reserved_vector<TUniqueId, 1024> nearList;
static CMaterialFilter filter = CMaterialFilter::MakeInclude(EMaterialTypes::Character);
CParasite* closestParasite = nullptr;
float minDistSq = 2.f + x6e8_ * x6e8_;
mgr.BuildNearList(nearList, aabb, filter, nullptr);
for (TUniqueId id : nearList)
{
if (CParasite* parasite = CPatterned::CastTo<CParasite>(mgr.ObjectById(id)))
{
if (parasite != this && parasite->IsAlive())
{
_834.push_back(parasite->GetUniqueId());
float distSq = (parasite->GetTranslation() - GetTranslation()).magSquared();
if (distSq < minDistSq)
{
minDistSq = distSq;
closestParasite = parasite;
}
}
}
}
if (closestParasite && x6ec_ > 0.f && x6e8_ > 0.f)
x628_ = x45c_steeringBehaviors.Separation(*this, closestParasite->GetTranslation(), x6e8_) * x604_;
else
x628_ = zeus::CVector3f::skZero;
x634_ = x45c_steeringBehaviors.Cohesion(*this, _834, 0.6f, mgr) * x604_;
x640_ = x45c_steeringBehaviors.Alignment(*this, _834, mgr) * x604_;
}
if ((mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() < x700_ * x700_)
{
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane(
x45c_steeringBehaviors.Separation(*this, mgr.GetPlayer().GetTranslation(), x700_), upVec) * x604_,
zeus::CVector3f::skZero, x704_));
}
if (x628_ != zeus::CVector3f::skZero)
{
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane(
x628_, upVec), zeus::CVector3f::skZero, x6ec_));
}
for (const auto& r : x5d8_doorRepulsors)
{
if ((r.GetVector() - GetTranslation()).magSquared() < r.GetFloat() * r.GetFloat())
{
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane(
x45c_steeringBehaviors.Separation(*this, r.GetVector(), r.GetFloat()) * x604_, upVec),
zeus::CVector3f::skZero, 1.f));
}
}
if (x608_ <= 0.f)
{
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane(
x634_, upVec), zeus::CVector3f::skZero, x6f4_));
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane(
x640_, upVec), zeus::CVector3f::skZero, x6f0_));
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(
ProjectVectorToPlane(ProjectVectorToPlane(
x45c_steeringBehaviors.Seek(*this, x2e0_destPos), upVec) * x604_, upVec),
zeus::CVector3f::skZero, x6f8_));
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(
x34_transform.basis[1] * x604_, zeus::CVector3f::skZero, x6fc_));
}
}
void CParasite::PathFind(CStateManager& mgr, EStateMsg msg, float dt)
{
switch (msg)
{
case EStateMsg::Activate:
x742_26_ = true;
x5d6_24_ = true;
if (x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
SetMomentumWR(zeus::CVector3f::skZero);
xf8_24_movable = false;
break;
case EStateMsg::Update:
UpdatePFDestination(mgr);
DoFlockingBehavior(mgr);
break;
case EStateMsg::Deactivate:
xf8_24_movable = true;
x5d6_24_ = false;
x742_26_ = false;
break;
default:
break;
}
}
void CParasite::TargetPlayer(CStateManager& mgr, EStateMsg msg, float dt)
{
switch (msg)
{
case EStateMsg::Activate:
x5f8_ = mgr.GetPlayer().GetTranslation() + zeus::CVector3f(0.f, 0.f, 1.5f);
break;
case EStateMsg::Update:
x450_bodyController->FaceDirection3D(
ProjectVectorToPlane(x5f8_ - GetTranslation(), x34_transform.basis[2]),
x34_transform.basis[1], 2.f);
break;
default:
break;
}
}
TUniqueId CParasite::RecursiveFindClosestWayPoint(CStateManager& mgr, TUniqueId id, float& dist)
{
TUniqueId ret = id;
TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(id);
if (!wp)
return ret;
wp->SetActive(false);
dist = (wp->GetTranslation() - GetTranslation()).magSquared();
for (const auto& conn : wp->GetConnectionList())
{
if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next)
{
TUniqueId nextId = mgr.GetIdForScript(conn.x8_objId);
if (nextId != kInvalidUniqueId)
{
if (TCastToConstPtr<CScriptWaypoint> wp2 = mgr.GetObjectById(nextId))
{
if (wp2->GetActive())
{
float nextDist;
TUniqueId closestWp = RecursiveFindClosestWayPoint(mgr, nextId, nextDist);
if (nextDist < dist)
{
dist = nextDist;
ret = closestWp;
}
}
}
}
}
}
wp->SetActive(true);
return ret;
}
TUniqueId CParasite::GetClosestWaypointForState(EScriptObjectState state, CStateManager& mgr)
{
float minDist = FLT_MAX;
TUniqueId ret = kInvalidUniqueId;
for (const auto& conn : GetConnectionList())
{
if (conn.x0_state == state && conn.x4_msg == EScriptObjectMessage::Follow)
{
TUniqueId id = mgr.GetIdForScript(conn.x8_objId);
float dist;
TUniqueId closestWp = RecursiveFindClosestWayPoint(mgr, id, dist);
if (dist < minDist)
{
minDist = dist;
ret = closestWp;
}
}
}
return ret;
}
void CParasite::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt)
{
if (msg == EStateMsg::Activate)
{
SetMomentumWR(zeus::CVector3f::skZero);
TUniqueId wpId = GetClosestWaypointForState(EScriptObjectState::Patrol, mgr);
if (wpId != kInvalidUniqueId)
x2dc_destObj = wpId;
}
}
void CParasite::Halt(CStateManager& mgr, EStateMsg msg, float)
{
switch (msg)
{
case EStateMsg::Activate:
x330_stateMachineState.SetDelay(x710_);
x32c_animState = EAnimState::One;
x743_24_ = true;
x5d6_24_ = true;
if (x5d0_walkerType == EWalkerType::Geemer)
CSfxManager::AddEmitter(x73c_haltSfx, GetTranslation(), zeus::CVector3f::skZero,
true, false, 0x7f, kInvalidAreaId);
break;
case EStateMsg::Update:
TryCommand(mgr, pas::EAnimationState::LoopReaction, &CPatterned::TryLoopReaction, 1);
x400_24_hitByPlayerProjectile = false;
break;
case EStateMsg::Deactivate:
x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState));
x32c_animState = EAnimState::Zero;
x743_24_ = false;
x5d6_24_ = false;
break;
default:
break;
}
}
void CParasite::Run(CStateManager&, EStateMsg, float)
{
// Empty
}
void CParasite::Generate(CStateManager&, EStateMsg msg, float)
{
switch (msg)
{
case EStateMsg::Activate:
x5e8_ = 0;
break;
case EStateMsg::Update:
switch (x5e8_)
{
case 0:
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate)
x5e8_ = 1;
else
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero));
break;
case 1:
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate)
x5e8_ = 2;
break;
default:
break;
}
break;
default:
break;
}
}
void CParasite::Deactivate(CStateManager& mgr, EStateMsg msg, float)
{
switch (msg)
{
case EStateMsg::Activate:
x5e8_ = 0;
SendScriptMsgs(EScriptObjectState::UNKS2, mgr, EScriptObjectMessage::None);
mgr.FreeScriptObject(GetUniqueId());
break;
case EStateMsg::Update:
if (x5e8_ == 0)
{
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate)
x5e8_ = 1;
else
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::One));
}
break;
default:
break;
}
}
void CParasite::Attack(CStateManager& mgr, EStateMsg msg, float)
{
switch (msg)
{
case EStateMsg::Activate:
x608_ = 0.f;
if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed)
{
float rz = mgr.GetActiveRandom()->Float();
float ry = mgr.GetActiveRandom()->Float();
float rx = mgr.GetActiveRandom()->Float();
x5f8_ = (zeus::CVector3f(rx, ry, rz) - 0.5f) * 0.5f + mgr.GetPlayer().GetTranslation();
}
else
{
float rz = mgr.GetActiveRandom()->Float();
float ry = mgr.GetActiveRandom()->Float();
float rx = mgr.GetActiveRandom()->Float();
x5f8_ = (zeus::CVector3f(rx, ry, rz) + mgr.GetPlayer().GetTranslation() - GetTranslation())
.normalized() * 15.f + GetTranslation();
}
FaceTarget(x5f8_);
x5e8_ = 0;
x742_30_attackOver = false;
x742_24_ = false;
x742_28_onGround = false;
break;
case EStateMsg::Update:
switch (x5e8_)
{
case 0:
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Jump)
{
x5e8_ = 1;
}
else
{
x742_25_jumpVelDirty = true;
FaceTarget(x5f8_);
x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(x5f8_, pas::EJumpType::Normal));
}
break;
default:
break;
}
break;
case EStateMsg::Deactivate:
x742_28_onGround = true;
x742_30_attackOver = true;
break;
default:
break;
}
}
void CParasite::Crouch(CStateManager&, EStateMsg msg, float)
{
if (msg == EStateMsg::Activate)
{
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch);
if (x5d0_walkerType == EWalkerType::Geemer)
CSfxManager::AddEmitter(x740_crouchSfx, GetTranslation(), zeus::CVector3f::skZero,
true, false, 0x7f, kInvalidAreaId);
}
}
void CParasite::GetUp(CStateManager&, EStateMsg msg, float)
{
if (msg == EStateMsg::Activate)
{
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
if (x5d0_walkerType == EWalkerType::Geemer)
CSfxManager::AddEmitter(x73e_getUpSfx, GetTranslation(), zeus::CVector3f::skZero,
true, false, 0x7f, kInvalidAreaId);
}
}
void CParasite::TelegraphAttack(CStateManager& mgr, EStateMsg msg, float)
{
switch (msg)
{
case EStateMsg::Activate:
for (auto it = mgr.GetParasiteTelegraphs().begin(); it != mgr.GetParasiteTelegraphs().end();)
{
CParasite* other = CPatterned::CastTo<CParasite>(mgr.ObjectById(*it));
if (!other)
{
it = mgr.GetParasiteTelegraphs().erase(it);
continue;
}
if (other != this && other->IsAlive() &&
(other->GetTranslation() - GetTranslation()).magSquared() < x6d0_ * x6d0_)
{
other->x742_24_ = true;
other->x608_ = mgr.GetActiveRandom()->Float() * 0.5f + 0.5f;
other->x5f8_ = GetTranslation();
}
++it;
}
x400_24_hitByPlayerProjectile = false;
break;
default:
break;
}
}
void CParasite::Jump(CStateManager& mgr, EStateMsg msg, float)
{
switch (msg)
{
case EStateMsg::Activate:
AddMaterial(EMaterialTypes::GroundCollider, mgr);
SetMomentumWR({0.f, 0.f, -GetWeight()});
x742_28_onGround = false;
x5d6_24_ = false;
x742_27_landed = false;
x743_27_inJump = true;
break;
case EStateMsg::Update:
SetMomentumWR({0.f, 0.f, -GetWeight()});
break;
case EStateMsg::Deactivate:
RemoveMaterial(EMaterialTypes::GroundCollider, mgr);
SetMomentumWR(zeus::CVector3f::skZero);
x742_28_onGround = true;
x742_27_landed = false;
x743_27_inJump = false;
break;
}
}
void CParasite::FaceTarget(const zeus::CVector3f& target)
{
zeus::CQuaternion q =
zeus::CQuaternion::lookAt(zeus::CTransform::Identity().basis[1],
target - GetTranslation(), zeus::degToRad(360.f));
SetTransform(q.toTransform(GetTranslation()));
}
void CParasite::Retreat(CStateManager& mgr, EStateMsg msg, float)
{
switch (msg)
{
case EStateMsg::Activate:
{
zeus::CVector3f dir = mgr.GetPlayer().GetTranslation() - GetTranslation();
dir.z = 0.f;
if (dir.canBeNormalized())
dir.normalize();
else
dir = mgr.GetPlayer().GetTransform().basis[1];
x5f8_ = GetTranslation() - dir * 3.f;
FaceTarget(x5f8_);
x5e8_ = 0;
x742_27_landed = false;
x742_28_onGround = false;
x742_25_jumpVelDirty = true;
x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(x5f8_, pas::EJumpType::One));
break;
}
case EStateMsg::Update:
x3b4_speed = 1.f;
break;
case EStateMsg::Deactivate:
x742_28_onGround = true;
break;
}
}
bool CParasite::AnimOver(CStateManager&, float)
{
return x5e8_ == 2;
}
bool CParasite::ShouldAttack(CStateManager& mgr, float arg)
{
bool shouldAttack = false;
if (x742_24_ && x608_ > 0.1f)
shouldAttack = true;
if (!TooClose(mgr, arg) && InMaxRange(mgr, arg))
return shouldAttack || InDetectionRange(mgr, 0.f);
return false;
}
bool CParasite::CloseToWall(CStateManager& mgr)
{
static CMaterialFilter filter = CMaterialFilter::MakeInclude(EMaterialTypes::Solid);
zeus::CAABox aabb = CPhysicsActor::GetBoundingBox();
float margin = x590_colSphere.GetSphere().radius + x5b0_collisionCloseMargin;
aabb.min -= zeus::CVector3f(margin);
aabb.max += zeus::CVector3f(margin);
CCollidableAABox cAABB(aabb, x68_material);
return CGameCollision::DetectStaticCollisionBoolean(mgr, cAABB, {}, filter);
}
bool CParasite::HitSomething(CStateManager& mgr, float)
{
if (x5d4_ & 0x1)
return true;
return x5b8_ < 270.f && CloseToWall(mgr);
}
bool CParasite::Stuck(CStateManager&, float)
{
return x60c_ > x6e0_;
}
bool CParasite::Landed(CStateManager&, float)
{
return x742_27_landed;
}
bool CParasite::AttackOver(CStateManager&, float)
{
return x742_30_attackOver;
}
bool CParasite::ShotAt(CStateManager&, float)
{
if (x5d0_walkerType != EWalkerType::Oculus)
return x400_24_hitByPlayerProjectile;
return x743_26_oculusShotAt;
}
void CParasite::MassiveDeath(CStateManager& mgr)
{
CPatterned::MassiveDeath(mgr);
}
void CParasite::MassiveFrozenDeath(CStateManager& mgr)
{
CPatterned::MassiveFrozenDeath(mgr);
}
void CParasite::ThinkAboutMove(float dt)
{
if (!x68_material.HasMaterial(EMaterialTypes::GroundCollider))
CPatterned::ThinkAboutMove(dt);
}
bool CParasite::IsOnGround() const
{
return x742_28_onGround;
}
void CParasite::UpdateWalkerAnimation(CStateManager& mgr, float dt)
{
CActor::UpdateAnimation(dt, mgr, true);
}
void CParasite::DestroyActorManager(CStateManager& mgr)
@ -214,12 +850,10 @@ void CParasite::DestroyActorManager(CStateManager& mgr)
void CParasite::UpdateJumpVelocity()
{
x150_momentum.x = 0;
x150_momentum.y = 0;
x150_momentum.z = -GetWeight();
SetMomentumWR({0.f, 0.f, -GetWeight()});
zeus::CVector3f vec;
if (!x742_30_)
if (!x742_30_attackOver)
{
vec = skAttackVelocity * GetTransform().frontVector();
vec.z = 0.5f * skRetreatVelocity;
@ -231,10 +865,8 @@ void CParasite::UpdateJumpVelocity()
}
float f30 = x150_momentum.z / xe8_mass;
float f31 = x600_ - GetTranslation().z;
zeus::CVector3f vec2;
vec2.x = x5f8_ - GetTranslation().x;
vec2.y = x5fc_ * GetTranslation().y;
float f31 = x5f8_.z - GetTranslation().z;
zeus::CVector3f vec2 = x5f8_ - GetTranslation();
vec2.z = 0.f;
float f29 = vec2.magnitude();

View File

@ -13,6 +13,12 @@ class CParasite : public CWallWalker
{
class CRepulsor
{
zeus::CVector3f x0_v;
float xc_f;
public:
CRepulsor(const zeus::CVector3f& v, float f) : x0_v(v), xc_f(f) {}
const zeus::CVector3f& GetVector() const { return x0_v; }
float GetFloat() const { return xc_f; }
};
static const float flt_805A8FB0;
static const float skAttackVelocity;
@ -24,23 +30,16 @@ class CParasite : public CWallWalker
float x5ec_ = 0.f;
float x5f0_ = 0.f;
float x5f4_ = 0.f;
float x5f8_ = 0.f;
float x5fc_ = 0.f;
float x600_ = 0.f;
zeus::CVector3f x5f8_;
float x604_ = 1.f;
float x608_ = 0.f;
float x60c_ = 0.f;
zeus::CVector3f x614_;
std::unique_ptr<CCollisionActorManager> x620_ = 0;
u32 x624_ = 0;
float x628_ = 0.f;
float x62c_ = 0.f;
float x630_ = 0.f;
float x634_ = 0.f;
float x638_ = 0.f;
float x640_ = 0.f;
float x644_ = 0.f;
float x648_ = 0.f;
TLockedToken<CSkinnedModel> x624_extraModel;
zeus::CVector3f x628_;
zeus::CVector3f x634_;
zeus::CVector3f x640_;
CDamageVulnerability x64c_;
CDamageInfo x6b4_;
float x6d0_;
@ -68,46 +67,85 @@ class CParasite : public CWallWalker
float x730_ = 0.f;
float x734_ = 0.f;
float x738_ = 0.f;
s16 x73c_;
s16 x73e_;
s16 x740_;
u16 x73c_haltSfx;
u16 x73e_getUpSfx;
u16 x740_crouchSfx;
union
{
struct
{
bool x742_24_ : 1;
bool x742_25_ : 1;
bool x742_25_jumpVelDirty : 1;
bool x742_26_ : 1;
bool x742_27_ : 1;
bool x742_28_ : 1;
bool x742_27_landed : 1;
bool x742_28_onGround : 1;
bool x742_29_ : 1;
bool x742_30_ : 1;
bool x742_30_attackOver : 1;
bool x742_31_ : 1;
bool x743_24_ : 1;
bool x743_25_ : 1;
bool x743_26_ : 1;
bool x743_27_ : 1;
bool x743_26_oculusShotAt : 1;
bool x743_27_inJump : 1;
};
u16 _dummy = 0;
};
bool CloseToWall(CStateManager& mgr);
void FaceTarget(const zeus::CVector3f& target);
TUniqueId RecursiveFindClosestWayPoint(CStateManager& mgr, TUniqueId id, float& dist);
TUniqueId GetClosestWaypointForState(EScriptObjectState state, CStateManager& mgr);
void UpdatePFDestination(CStateManager& mgr);
void DoFlockingBehavior(CStateManager& mgr);
public:
DEFINE_PATTERNED(Parasite)
CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo&, EBodyType, float, float, float,
float, float, float, float, float, float, float, float, float, float, float, float, float, float, float,
bool, u32, const CDamageVulnerability&, const CDamageInfo&, u16, u16, u16, u32, u32, float,
bool, EWalkerType wType, const CDamageVulnerability&, const CDamageInfo&, u16, u16, u16, CAssetId, CAssetId, float,
const CActorParameters&);
void Accept(IVisitor&);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void PreThink(float, CStateManager&);
void Think(float dt, CStateManager& mgr);
void Render(const CStateManager&) const;
const CDamageVulnerability* GetDamageVulnerability() const;
void Touch(CActor& actor, CStateManager&);
zeus::CVector3f GetAimPosition(const CStateManager&, float) const;
void CollidedWith(TUniqueId uid, const CCollisionInfoList&, CStateManager&);
void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state);
void Patrol(CStateManager&, EStateMsg msg, float dt);
void PathFind(CStateManager&, EStateMsg msg, float dt);
void TargetPlayer(CStateManager&, EStateMsg msg, float dt);
void TargetPatrol(CStateManager&, EStateMsg msg, float dt);
void Halt(CStateManager&, EStateMsg, float);
void Run(CStateManager&, EStateMsg, float);
void Generate(CStateManager&, EStateMsg, float);
void Deactivate(CStateManager&, EStateMsg, float);
void Attack(CStateManager&, EStateMsg, float);
void Crouch(CStateManager&, EStateMsg, float);
void GetUp(CStateManager&, EStateMsg, float);
void TelegraphAttack(CStateManager&, EStateMsg, float);
void Jump(CStateManager&, EStateMsg, float);
void Retreat(CStateManager&, EStateMsg, float);
bool AnimOver(CStateManager&, float);
bool ShouldAttack(CStateManager&, float);
bool HitSomething(CStateManager&, float);
bool Stuck(CStateManager&, float);
bool Landed(CStateManager&, float);
bool AttackOver(CStateManager&, float);
bool ShotAt(CStateManager&, float);
void MassiveDeath(CStateManager&);
void MassiveFrozenDeath(CStateManager&);
void ThinkAboutMove(float);
bool IsOnGround() const;
virtual void UpdateWalkerAnimation(CStateManager&, float);
void DestroyActorManager(CStateManager& mgr);
void UpdateJumpVelocity();
void UpdateCollisionActors(CStateManager&) {}
CDamageInfo GetContactDamage() const
{
if (x5d0_ == 1 && x743_24_)
if (x5d0_walkerType == EWalkerType::Oculus && x743_24_)
return x6b4_;
return CPatterned::GetContactDamage();
}

View File

@ -11,7 +11,7 @@ CSeedling::CSeedling(TUniqueId uid, std::string_view name, const CEntityInfo& in
CAssetId, CAssetId, const CDamageInfo&, const CDamageInfo&, float f1, float f2, float f3, float f4)
: CWallWalker(ECharacter::Seedling, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Ground, EColliderType::Zero, EBodyType::WallWalker, actParms, f1, f2,
EKnockBackVariant::Small, f3, 4, f4, false)
EKnockBackVariant::Small, f3, EWalkerType::Seedling, f4, false)
{
}

View File

@ -49,7 +49,6 @@ public:
virtual void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info,
EKnockBackType type, bool inDeferred, float magnitude)=0;
virtual const CDamageVulnerability* GetDamageVulnerability() const { return &x260_damageVulnerability; }
virtual const CDamageVulnerability* GetDamageVulnerability() { return &x260_damageVulnerability; }
virtual void TakeDamage(const zeus::CVector3f& direction, float magnitude) {}
virtual bool CanBeShot(const CStateManager&, int) { return true; }
virtual bool IsListening() const { return false; }

View File

@ -485,7 +485,7 @@ void CKnockBackController::ValidateState(CPatterned& parent)
if (disableFollowup)
{
x4_activeParms.x4_animFollowup = EKnockBackAnimationFollowUp::None;
x4_activeParms.x8_followupMagnitude = 0.f;
x4_activeParms.x8_followupDuration = 0.f;
}
}

View File

@ -86,8 +86,8 @@ public:
{
EKnockBackAnimationState x0_animState;
EKnockBackAnimationFollowUp x4_animFollowup;
float x8_followupMagnitude;
float xc_;
float x8_followupDuration;
float xc_intoFreezeDur;
};
private:
friend class CPatterned;
@ -149,6 +149,12 @@ public:
void KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent,
const CDamageInfo& info, EKnockBackType type, float magnitude);
void SetEnableFreeze(bool b) { x81_25_enableFreeze = b; }
void SetEnableShock(bool b) { x81_26_enableShock = b; }
void SetEnableBurn(bool b) { x81_27_enableBurn = b; }
void SetEnableBurnDeath(bool b) { x81_28_enableBurnDeath = b; }
void SetEnableExplodeDeath(bool b) { x81_29_enableExplodeDeath = b; }
void SetEnableLaggedBurnDeath(bool b) { x81_30_enableLaggedBurnDeath = b; }
void SetX82_24(bool b) { x82_24_ = b; }
const KnockBackParms& GetActiveParms() const { return x4_activeParms; }
EKnockBackVariant GetVariant() const { return x0_variant; }
};

View File

@ -11,6 +11,7 @@
#include "Character/CAnimData.hpp"
#include "TCastTo.hpp"
#include "MP1/World/CSpacePirate.hpp"
#include "MP1/World/CMetroid.hpp"
#include "World/CStateMachine.hpp"
#include "CExplosion.hpp"
#include "Graphics/CSkinnedModel.hpp"
@ -419,6 +420,17 @@ zeus::CVector3f CPatterned::GetAimPosition(const urde::CStateManager& mgr, float
return offset + GetBoundingBox().center();
}
zeus::CTransform CPatterned::GetLctrTransform(std::string_view name) const
{
return x34_transform * GetScaledLocatorTransform(name);
}
zeus::CTransform CPatterned::GetLctrTransform(CSegId id) const
{
zeus::CTransform xf = x64_modelData->GetAnimationData()->GetLocatorTransform(id, nullptr);
return x34_transform * zeus::CTransform(xf.buildMatrix3f(), x64_modelData->GetScale() * xf.origin);
}
void CPatterned::DeathDelete(CStateManager& mgr)
{
SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None);
@ -487,27 +499,27 @@ void CPatterned::KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, c
if (!x401_27_phazingOut && !x401_28_burning && hInfo)
{
x460_knockBackController.KnockBack(backVec, mgr, *this, info, type, magnitude);
if (x450_bodyController->IsFrozen() && x460_knockBackController.GetActiveParms().xc_ >= 0.f)
if (x450_bodyController->IsFrozen() && x460_knockBackController.GetActiveParms().xc_intoFreezeDur >= 0.f)
x450_bodyController->FrozenBreakout();
switch (x460_knockBackController.GetActiveParms().x4_animFollowup)
{
case EKnockBackAnimationFollowUp::Freeze:
Freeze(mgr, zeus::CVector3f::skZero, zeus::CUnitVector3f(x34_transform.transposeRotate(backVec)),
x460_knockBackController.GetActiveParms().x8_followupMagnitude);
x460_knockBackController.GetActiveParms().x8_followupDuration);
break;
case EKnockBackAnimationFollowUp::PhazeOut:
PhazeOut(mgr);
break;
case EKnockBackAnimationFollowUp::Shock:
Shock(x460_knockBackController.GetActiveParms().x8_followupMagnitude, -1.f);
Shock(x460_knockBackController.GetActiveParms().x8_followupDuration, -1.f);
break;
case EKnockBackAnimationFollowUp::Burn:
Burn(x460_knockBackController.GetActiveParms().x8_followupMagnitude, 0.25f);
Burn(x460_knockBackController.GetActiveParms().x8_followupDuration, 0.25f);
break;
case EKnockBackAnimationFollowUp::LaggedBurnDeath:
x401_29_laggedBurnDeath = true;
case EKnockBackAnimationFollowUp::BurnDeath:
Burn(x460_knockBackController.GetActiveParms().x8_followupMagnitude, -1.f);
Burn(x460_knockBackController.GetActiveParms().x8_followupDuration, -1.f);
Death(mgr, zeus::CVector3f::skZero, EScriptObjectState::DeathRattle);
x400_28_pendingMassiveDeath = x400_29_pendingMassiveFrozenDeath = false;
x400_27_fadeToDeath = x401_28_burning = true;
@ -561,7 +573,7 @@ bool CPatterned::Random(CStateManager&, float arg)
bool CPatterned::CodeTrigger(CStateManager&, float arg)
{
return x330_stateMachineState.x18_24_;
return x330_stateMachineState.x18_24_codeTrigger;
}
bool CPatterned::FixedDelay(CStateManager&, float arg)
@ -779,7 +791,7 @@ bool CPatterned::OffLine(CStateManager&, float arg)
return distSq > arg * arg;
}
void CPatterned::PathFind(CStateManager& mgr, EStateMsg msg, float arg)
void CPatterned::PathFind(CStateManager& mgr, EStateMsg msg, float dt)
{
if (CPathFindSearch* search = GetSearchPath())
{
@ -826,7 +838,7 @@ void CPatterned::PathFind(CStateManager& mgr, EStateMsg msg, float arg)
}
}
void CPatterned::Dead(CStateManager& mgr, EStateMsg msg, float arg)
void CPatterned::Dead(CStateManager& mgr, EStateMsg msg, float dt)
{
switch (msg)
{
@ -852,7 +864,7 @@ void CPatterned::Dead(CStateManager& mgr, EStateMsg msg, float arg)
}
}
void CPatterned::TargetPlayer(CStateManager& mgr, EStateMsg msg, float arg)
void CPatterned::TargetPlayer(CStateManager& mgr, EStateMsg msg, float dt)
{
if (msg == EStateMsg::Activate)
{
@ -863,7 +875,7 @@ void CPatterned::TargetPlayer(CStateManager& mgr, EStateMsg msg, float arg)
}
}
void CPatterned::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg)
void CPatterned::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt)
{
if (msg == EStateMsg::Activate)
{
@ -875,7 +887,7 @@ void CPatterned::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg)
}
}
void CPatterned::FollowPattern(CStateManager& mgr, EStateMsg msg, float arg)
void CPatterned::FollowPattern(CStateManager& mgr, EStateMsg msg, float dt)
{
switch (msg)
{
@ -923,7 +935,7 @@ void CPatterned::FollowPattern(CStateManager& mgr, EStateMsg msg, float arg)
}
}
void CPatterned::Patrol(CStateManager& mgr, EStateMsg msg, float arg)
void CPatterned::Patrol(CStateManager& mgr, EStateMsg msg, float dt)
{
switch (msg)
{
@ -992,6 +1004,22 @@ void CPatterned::Patrol(CStateManager& mgr, EStateMsg msg, float arg)
}
}
void CPatterned::TryCommand(CStateManager& mgr, pas::EAnimationState state,
CPatternedTryFunc func, int arg)
{
if (state == x450_bodyController->GetCurrentStateId())
x32c_animState = EAnimState::Repeat;
else if (x32c_animState == EAnimState::One)
(this->*func)(mgr, arg);
else
x32c_animState = EAnimState::Over;
}
void CPatterned::TryLoopReaction(CStateManager& mgr, int arg)
{
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType(arg)));
}
void CPatterned::BuildBodyController(EBodyType bodyType)
{
if (x450_bodyController)
@ -1067,6 +1095,75 @@ void CPatterned::MassiveFrozenDeath(CStateManager& mgr)
x400_28_pendingMassiveDeath = x400_29_pendingMassiveFrozenDeath = false;
}
void CPatterned::Burn(float duration, float damage)
{
switch (GetDamageVulnerability()->GetVulnerability(CWeaponMode(EWeaponType::Plasma), false))
{
case EVulnerability::DoubleDamage:
x450_bodyController->SetOnFire(1.5f * duration);
x3ec_pendingFireDamage = 1.5f * damage;
break;
case EVulnerability::Normal:
x450_bodyController->SetOnFire(duration);
x3ec_pendingFireDamage = damage;
break;
default:
break;
}
}
void CPatterned::Shock(float duration, float damage)
{
switch (GetDamageVulnerability()->GetVulnerability(CWeaponMode(EWeaponType::Wave), false))
{
case EVulnerability::DoubleDamage:
x450_bodyController->SetElectrocuting(1.5f * duration);
x3f0_pendingShockDamage = 1.5f * damage;
break;
case EVulnerability::Normal:
x450_bodyController->SetElectrocuting(duration);
x3f0_pendingShockDamage = damage;
break;
default:
break;
}
}
void CPatterned::Freeze(CStateManager& mgr, const zeus::CVector3f& pos,
const zeus::CUnitVector3f& dir, float frozenDur)
{
if (x402_25_lostMassiveFrozenHP)
x402_26_dieIf80PercFrozen = true;
bool playSfx = false;
if (x450_bodyController->IsFrozen())
{
x450_bodyController->Freeze(x460_knockBackController.GetActiveParms().xc_intoFreezeDur,
frozenDur, x4f8_outofFreezeDur);
mgr.GetActorModelParticles()->EnsureElectricLoaded(*this);
playSfx = true;
}
else if (!x450_bodyController->IsElectrocuting() &&
!x450_bodyController->IsOnFire())
{
x450_bodyController->Freeze(x4f4_intoFreezeDur, frozenDur, x4f8_outofFreezeDur);
if (x510_vertexMorph)
x510_vertexMorph->Reset(dir, pos, x4f4_intoFreezeDur);
playSfx = true;
}
if (playSfx)
{
u16 sfx;
if (x460_knockBackController.GetVariant() != EKnockBackVariant::Small &&
CPatterned::CastTo<MP1::CMetroid>(mgr.GetObjectById(GetUniqueId())))
sfx = SFXsfx0701;
else
sfx = SFXsfx0708;
CSfxManager::AddEmitter(sfx, GetTranslation(), zeus::CVector3f::skZero,
true, false, 0x7f, kInvalidAreaId);
}
}
zeus::CVector3f CPatterned::GetGunEyePos() const
{
zeus::CVector3f origin = GetOrigin();
@ -1684,4 +1781,13 @@ void CPatterned::ThinkAboutMove(float dt)
RotateToOR(x440_rotDelta, dt);
}
void CPatterned::PhazeOut(CStateManager& mgr)
{
if (!x400_27_fadeToDeath)
SendScriptMsgs(EScriptObjectState::DeathRattle, mgr, EScriptObjectMessage::None);
x401_27_phazingOut = true;
x450_bodyController->SetPlaybackRate(0.f);
x64_modelData->AnimationData()->GetParticleDB().SetUpdatesEnabled(false);
}
}

View File

@ -19,6 +19,7 @@ namespace urde
class CPatternedInfo;
class CProjectileInfo;
class CPathFindSearch;
typedef void (CPatterned::*CPatternedTryFunc)(CStateManager&, int);
class CPatterned : public CAi
{
@ -133,7 +134,7 @@ public:
{
Zero,
One,
Two,
Repeat,
Over
};
class CPatternNode
@ -327,6 +328,8 @@ public:
return GetAimPosition(mgr, 0.f);
}
zeus::CVector3f GetAimPosition(const CStateManager& mgr, float) const;
zeus::CTransform GetLctrTransform(std::string_view name) const;
zeus::CTransform GetLctrTransform(CSegId id) const;
void DeathDelete(CStateManager& mgr);
void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state);
@ -363,21 +366,24 @@ public:
bool InRange(CStateManager&, float arg);
bool OffLine(CStateManager&, float arg);
bool Default(CStateManager&, float arg) { return true; }
void PathFind(CStateManager&, EStateMsg msg, float arg);
void Dead(CStateManager&, EStateMsg msg, float arg);
void TargetPlayer(CStateManager&, EStateMsg msg, float arg);
void TargetPatrol(CStateManager&, EStateMsg msg, float arg);
void FollowPattern(CStateManager&, EStateMsg msg, float arg);
void Patrol(CStateManager&, EStateMsg msg, float arg);
void Start(CStateManager&, EStateMsg msg, float arg) {}
void PathFind(CStateManager&, EStateMsg msg, float dt);
void Dead(CStateManager&, EStateMsg msg, float dt);
void TargetPlayer(CStateManager&, EStateMsg msg, float dt);
void TargetPatrol(CStateManager&, EStateMsg msg, float dt);
void FollowPattern(CStateManager&, EStateMsg msg, float dt);
void Patrol(CStateManager&, EStateMsg msg, float dt);
void Start(CStateManager&, EStateMsg msg, float dt) {}
void TryCommand(CStateManager& mgr, pas::EAnimationState state, CPatternedTryFunc func, int arg);
void TryLoopReaction(CStateManager& mgr, int arg);
virtual bool KnockbackWhenFrozen() const { return true; }
virtual void MassiveDeath(CStateManager& mgr);
virtual void MassiveFrozenDeath(CStateManager& mgr);
virtual void Burn(float, float) {}
virtual void Shock(float, float) {}
virtual void Burn(float, float);
virtual void Shock(float, float);
virtual void Freeze(CStateManager& mgr, const zeus::CVector3f& pos,
const zeus::CUnitVector3f& dir, float magnitude) {}
const zeus::CUnitVector3f& dir, float frozenDur);
virtual void ThinkAboutMove(float);
virtual CPathFindSearch* GetSearchPath() { return nullptr; }
virtual CDamageInfo GetContactDamage() const { return x404_contactDamage; }
@ -385,7 +391,7 @@ public:
virtual bool IsOnGround() const { return x328_27_onGround; }
virtual float GetGravityConstant() const { return 24.525002f; }
virtual CProjectileInfo* GetProjectileInfo() { return nullptr; }
virtual void PhazeOut(CStateManager&) {}
virtual void PhazeOut(CStateManager&);
virtual const std::experimental::optional<TLockedToken<CGenDescription>>&
GetDeathExplosionParticle() const { return x520_deathExplosionParticle; }
float GetDamageDuration() const { return x504_damageDur; }

View File

@ -61,7 +61,7 @@ CStateMachine::CStateMachine(CInputStream& in)
s32 CStateMachine::GetStateIndex(std::string_view state) const
{
auto it = std::find_if(x0_states.begin(), x0_states.end(), [&state](const CAiState& st) {
auto it = std::find_if(x0_states.begin(), x0_states.end(), [state](const CAiState& st) {
return (strncmp(st.GetName(), state.data(), 31) == 0);
});
if (it == x0_states.end())
@ -96,7 +96,7 @@ void CStateMachineState::Update(CStateManager& mgr, CAi& ai, float delta)
x4_state->CallFunc(mgr, ai, EStateMsg::Deactivate, 0.f);
x4_state = state;
x8_time = 0.f;
x18_24_ = false;
x18_24_codeTrigger = false;
xc_random = mgr.GetActiveRandom()->Float();
x4_state->CallFunc(mgr, ai, EStateMsg::Activate, delta);
return;
@ -115,7 +115,7 @@ void CStateMachineState::SetState(CStateManager& mgr, CAi& ai, s32 idx)
x4_state = state;
x8_time = 0.f;
xc_random = mgr.GetActiveRandom()->Float();
x18_24_ = false;
x18_24_codeTrigger = false;
x4_state->CallFunc(mgr, ai, EStateMsg::Activate, 0.f);
}
}

View File

@ -51,14 +51,14 @@ class CAiState
{
friend class CStateMachineState;
CAiStateFunc x0_func;
char xc_name[32];
char xc_name[32] = {};
u32 x2c_numTriggers;
CAiTrigger* x30_firstTrigger;
public:
CAiState(CAiStateFunc func, const char* name)
{
x0_func = func;
strncpy(xc_name, name, 32);
strncpy(xc_name, name, 31);
}
s32 GetNumTriggers() const { return x2c_numTriggers; }
@ -97,7 +97,7 @@ class CStateMachineState
{
struct
{
bool x18_24_ : 1;
bool x18_24_codeTrigger : 1;
};
u32 dummy = 0;
};

View File

@ -9,16 +9,16 @@ namespace urde
CWallWalker::CWallWalker(ECharacter chr, TUniqueId uid, std::string_view name, EFlavorType flavType,
const CEntityInfo& eInfo, const zeus::CTransform& xf,
CModelData&& mData, const CPatternedInfo& pInfo, EMovementType mType,
EColliderType colType, EBodyType bType, const CActorParameters& aParms, float f1, float f2,
EKnockBackVariant w1, float f3, u32 w2, float f4, bool b1)
: CPatterned(chr, uid, name, flavType, eInfo, xf, std::move(mData), pInfo, mType, colType, bType, aParms, w1)
EColliderType colType, EBodyType bType, const CActorParameters& aParms,
float f1, float f2, EKnockBackVariant kbVariant, float f3, EWalkerType wType, float f4, bool b1)
: CPatterned(chr, uid, name, flavType, eInfo, xf, std::move(mData), pInfo, mType, colType, bType, aParms, kbVariant)
, x590_colSphere(zeus::CSphere(zeus::CVector3f::skZero, pInfo.GetHalfExtent()), x68_material)
, x5b0_(f1)
, x5b0_collisionCloseMargin(f1)
, x5b4_(f2)
, x5c0_advanceWpRadius(f3)
, x5c4_(f4)
, x5cc_bendingHackAnim(GetModelData()->GetAnimationData()->GetCharacterInfo().GetAnimationIndex("BendingAnimationHack"sv))
, x5d0_(w2)
, x5d0_walkerType(wType)
, x5d6_24_(false)
, x5d6_25_(false)
, x5d6_26_(false)
@ -28,6 +28,37 @@ CWallWalker::CWallWalker(ECharacter chr, TUniqueId uid, std::string_view name, E
{
}
void CWallWalker::OrientToSurfaceNormal(const zeus::CVector3f& normal, float clampAngle)
{
float dot = x34_transform.basis[2].dot(normal);
if (zeus::close_enough(dot, 1.f) || dot < -0.999f)
return;
zeus::CQuaternion q =
zeus::CQuaternion::clampedRotateTo(x34_transform.basis[2], normal, zeus::degToRad(clampAngle));
q.setImaginary(x34_transform.transposeRotate(q.getImaginary()));
SetTransform((zeus::CQuaternion(x34_transform.basis) * q).normalized().toTransform(GetTranslation()));
}
void CWallWalker::GotoNextWaypoint(CStateManager& mgr)
{
if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(x2dc_destObj))
{
zeus::CVector3f wpPos = wp->GetTranslation();
if ((wpPos - GetTranslation()).magSquared() < x5c0_advanceWpRadius * x5c0_advanceWpRadius)
{
x2dc_destObj = wp->NextWaypoint(mgr);
if (!zeus::close_enough(wp->GetPause(), 0.f))
{
x5bc_ = wp->GetPause();
if (x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
}
mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived);
}
SetDestPos(wpPos);
}
}
void CWallWalker::PreThink(float dt, CStateManager& mgr)
{
CPatterned::PreThink(dt, mgr);
@ -45,11 +76,9 @@ void CWallWalker::PreThink(float dt, CStateManager& mgr)
SetTranslation(GetTranslation() * (1.f - futureDt) +
(((GetTranslation() - ((plane.vec.dot(GetTranslation())) - plane.d) -
x590_colSphere.GetSphere().radius - 0.1f) * plane.vec) * futureDt));
}
else
MoveCollisionPrimitive(zeus::CVector3f::skZero);
}
void CWallWalker::Think(float dt, CStateManager& mgr)
@ -92,6 +121,11 @@ void CWallWalker::Think(float dt, CStateManager& mgr)
}
}
void CWallWalker::Render(const CStateManager& mgr) const
{
CPatterned::Render(mgr);
}
void CWallWalker::UpdateWPDestination(CStateManager& mgr)
{
if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(x2dc_destObj))
@ -103,7 +137,7 @@ void CWallWalker::UpdateWPDestination(CStateManager& mgr)
if (std::fabs(wp->GetPause()) > 0.00001f)
{
x5bc_ = wp->GetPause();
if (x5d0_ == 0)
if (x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived);
}

View File

@ -8,12 +8,21 @@ namespace urde
{
class CWallWalker : public CPatterned
{
public:
enum class EWalkerType
{
Parasite = 0,
Oculus = 1,
Geemer = 2,
IceZoomer = 3,
Seedling = 4
};
protected:
CCollisionSurface x568_ = CCollisionSurface(zeus::CVector3f(),
zeus::CVector3f::skForward,
zeus::CVector3f::skRight, -1);
CCollidableSphere x590_colSphere;
float x5b0_;
float x5b0_collisionCloseMargin;
float x5b4_;
float x5b8_ = 0.f;
float x5bc_ = 0.f;
@ -21,7 +30,7 @@ protected:
float x5c4_;
float x5c8_bendingHackWeight = 0.f;
s32 x5cc_bendingHackAnim;
u32 x5d0_;
EWalkerType x5d0_walkerType;
s16 x5d4_ = 0;
bool x5d6_24_ : 1;
bool x5d6_25_ : 1;
@ -29,13 +38,20 @@ protected:
bool x5d6_27_ : 1;
bool x5d6_28_addBendingWeight : 1;
bool x5d6_29_applyBendingHack : 1;
static zeus::CVector3f ProjectVectorToPlane(const zeus::CVector3f& v0, const zeus::CVector3f& v1)
{
return v0 - v1 * v0.dot(v1);
}
void OrientToSurfaceNormal(const zeus::CVector3f& normal, float clampAngle);
void GotoNextWaypoint(CStateManager& mgr);
public:
CWallWalker(ECharacter, TUniqueId, std::string_view, EFlavorType, const CEntityInfo&, const zeus::CTransform&,
CModelData&&, const CPatternedInfo&, EMovementType, EColliderType, EBodyType,
const CActorParameters&, float, float, EKnockBackVariant, float, u32, float, bool);
const CActorParameters&, float, float, EKnockBackVariant, float, EWalkerType wType, float, bool);
void PreThink(float, CStateManager&);
void Think(float, CStateManager&);
void Render(const CStateManager&) const;
const CCollisionPrimitive* GetCollisionPrimitive() const { return &x590_colSphere; }
void UpdateWPDestination(CStateManager&);
};

View File

@ -1924,8 +1924,9 @@ CEntity* ScriptLoader::LoadParasite(CStateManager& mgr, CInputStream& in, int pr
CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true));
return new MP1::CParasite(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo,
EBodyType::WallWalker, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
f16, f17, 0.f, b1, 0, CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(),
-1, -1, -1, -1, -1, 0.f, aParms);
f16, f17, 0.f, b1, CWallWalker::EWalkerType::Parasite,
CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(),
-1, -1, -1, {}, {}, 0.f, aParms);
}
CEntity* ScriptLoader::LoadPlayerHint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
@ -2970,7 +2971,7 @@ CEntity* ScriptLoader::LoadGeemer(CStateManager& mgr, CInputStream& in, int prop
return new MP1::CParasite(mgr.AllocateUniqueId(), actHead.x0_name, CPatterned::EFlavorType::Zero, info,
actHead.x10_transform, std::move(mData), pInfo, EBodyType::WallWalker, 0.f, f1, f2, f3,
f4, 0.2f, 0.4f, 0.f,
0.f, 0.f, 0.f, 0.f, 1.f, f7, 0.f, 0.f, f5, f6, false, 2,
0.f, 0.f, 0.f, 0.f, 1.f, f7, 0.f, 0.f, f5, f6, false, CWallWalker::EWalkerType::Geemer,
CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(), sId1, sId2, sId3, -1,
-1, 0.f, actParms);
}