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

View File

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

View File

@ -12,7 +12,7 @@ namespace urde
CParticleDatabase::CParticleDatabase() CParticleDatabase::CParticleDatabase()
{ {
xb4_24_active = true; xb4_24_updatesEnabled = true;
xb4_25_anySystemsDrawnWithModel = false; 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, void CParticleDatabase::Update(float dt, const CPoseAsTransforms& pose, const CCharLayoutInfo& charInfo,
const zeus::CTransform& xf, const zeus::CVector3f& scale, CStateManager& stateMgr) const zeus::CTransform& xf, const zeus::CVector3f& scale, CStateManager& stateMgr)
{ {
if (!xb4_24_active) if (!xb4_24_updatesEnabled)
return; return;
UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, x3c_rendererDrawLoop, true); 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>> x78_rendererDraw;
std::map<std::string, std::unique_ptr<CParticleGenInfo>> x8c_firstDraw; std::map<std::string, std::unique_ptr<CParticleGenInfo>> x8c_firstDraw;
std::map<std::string, std::unique_ptr<CParticleGenInfo>> xa0_lastDraw; 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; bool xb4_25_anySystemsDrawnWithModel : 1;
static void SetModulationColorAllActiveEffectsForParticleDB(const zeus::CColor& color, static void SetModulationColorAllActiveEffectsForParticleDB(const zeus::CColor& color,
@ -69,6 +69,7 @@ public:
void InsertParticleGen(bool oneShot, int flags, std::string_view name, void InsertParticleGen(bool oneShot, int flags, std::string_view name,
std::unique_ptr<CParticleGenInfo>&& gen); std::unique_ptr<CParticleGenInfo>&& gen);
bool AreAnySystemsDrawnWithModel() const { return xb4_25_anySystemsDrawnWithModel; } bool AreAnySystemsDrawnWithModel() const { return xb4_25_anySystemsDrawnWithModel; }
void SetUpdatesEnabled(bool active) { xb4_24_updatesEnabled = active; }
}; };
} }

View File

@ -3,9 +3,111 @@
namespace urde 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 zeus::CVector3f
CSteeringBehaviors::ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeus::CVector3f& vel, CSteeringBehaviors::ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeus::CVector3f& vel,
const zeus::CVector3f& orbitPoint, float dt, float preThinkDt) const zeus::CVector3f& orbitPoint, float dt, float preThinkDt)
{ {
zeus::CVector3f usePos = pos; zeus::CVector3f usePos = pos;
if (vel.canBeNormalized()) if (vel.canBeNormalized())
@ -35,15 +137,4 @@ CSteeringBehaviors::ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeu
return usePos; 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 namespace urde
{ {
class CPhysicsActor;
class CStateManager;
class CSteeringBehaviors class CSteeringBehaviors
{ {
float x0_ = M_PIF / 2.f; float x0_ = M_PIF / 2.f;
public: public:
static zeus::CVector3f ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeus::CVector3f& vel, zeus::CVector3f Flee(const CPhysicsActor& actor, const zeus::CVector3f& v0) const;
const zeus::CVector3f& orbitPoint, float dt, float preThinkDt); 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 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);
}; };
} }

View File

@ -166,7 +166,9 @@ enum class ELoopAttackType
enum class EGenerateType enum class EGenerateType
{ {
Invalid = -1 Invalid = -1,
Zero,
One
}; };
enum class ESlideType 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 zeus::CSphere CCollidableSphere::Transform(const zeus::CTransform& xf) const
{ {
return zeus::CSphere(xf * x10_sphere.position, x10_sphere.radius); return zeus::CSphere(xf * x10_sphere.position, x10_sphere.radius);
@ -257,10 +250,6 @@ CRayCastResult CCollidableSphere::CastRayInternal(const CInternalRayCastStructur
return {}; 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, bool CCollidableSphere::CollideMovingAABox(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir,
double& dOut, CCollisionInfo& infoOut) double& dOut, CCollisionInfo& infoOut)
{ {

View File

@ -22,8 +22,8 @@ class CCollidableSphere : public CCollisionPrimitive
public: public:
CCollidableSphere(const zeus::CSphere&, const CMaterialList&); CCollidableSphere(const zeus::CSphere&, const CMaterialList&);
const zeus::CSphere& GetSphere() const; const zeus::CSphere& GetSphere() const { return x10_sphere; }
void SetSphereCenter(const zeus::CVector3f& center); void SetSphereCenter(const zeus::CVector3f& center) { x10_sphere.position = center; }
zeus::CSphere Transform(const zeus::CTransform& xf) const; zeus::CSphere Transform(const zeus::CTransform& xf) const;
virtual u32 GetTableIndex() const; virtual u32 GetTableIndex() const;
@ -32,8 +32,8 @@ public:
virtual FourCC GetPrimType() const; virtual FourCC GetPrimType() const;
virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const; virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const;
static const Type& GetType(); static const Type& GetType() { return sType; }
static void SetStaticTableIndex(u32 index); static void SetStaticTableIndex(u32 index) { sTableIndex = index; }
static bool CollideMovingAABox(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, static bool CollideMovingAABox(const CInternalCollisionStructure&, const zeus::CVector3f&, double&,
CCollisionInfo&); CCollisionInfo&);
static bool CollideMovingSphere(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, 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, void MorphVertices(std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn,
const float* magnitudes, const TLockedToken<CSkinRules>& skinRules, const float* magnitudes, const TLockedToken<CSkinRules>& skinRules,
const CPoseAsTransforms& pose) const; const CPoseAsTransforms& pose) const;
void Reset(const zeus::CVector3f& dir, const zeus::CVector3f& pos, float duration) {}
void Update(float) {} void Update(float) {}
}; };

View File

@ -5,8 +5,13 @@
#include "World/CWorld.hpp" #include "World/CWorld.hpp"
#include "World/CGameArea.hpp" #include "World/CGameArea.hpp"
#include "World/CPlayer.hpp" #include "World/CPlayer.hpp"
#include "World/CScriptWaypoint.hpp"
#include "CStateManager.hpp" #include "CStateManager.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "Graphics/CSkinnedModel.hpp"
#include "Collision/CGameCollision.hpp"
namespace urde::MP1 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, 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 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, 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, bool b1, EWalkerType wType, const CDamageVulnerability& dVuln,const CDamageInfo& parInfo, u16 sfxId1,
u16 sfxId2, u16 sfxId3, u32 w2, u32 w3, float f19, const CActorParameters &aParams) 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, : 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) , x64c_(dVuln)
, x6b4_(parInfo) , x6b4_(parInfo)
, x6d0_(f1) , x6d0_(f1)
@ -43,28 +48,38 @@ CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, c
, x708_(pInfo.GetHeight() * 0.5f) , x708_(pInfo.GetHeight() * 0.5f)
, x710_(f18) , x710_(f18)
, x714_(f19) , x714_(f19)
, x73c_(CSfxManager::TranslateSFXID(sfxId1)) , x73c_haltSfx(CSfxManager::TranslateSFXID(sfxId1))
, x73e_(CSfxManager::TranslateSFXID(sfxId2)) , x73e_getUpSfx(CSfxManager::TranslateSFXID(sfxId2))
, x740_(CSfxManager::TranslateSFXID(sfxId3)) , x740_crouchSfx(CSfxManager::TranslateSFXID(sfxId3))
{ {
x742_28_ = true; x742_28_onGround = true;
x742_30_ = true; x742_30_attackOver = true;
switch(x5d0_) switch (x5d0_walkerType)
{ {
case 2: case EWalkerType::Geemer:
x460_knockBackController.SetEnableFreeze(false); x460_knockBackController.SetEnableFreeze(false);
case 1: case EWalkerType::Oculus:
x460_knockBackController.SetAutoResetImpulse(false); x460_knockBackController.SetAutoResetImpulse(false);
break; 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: default:
break; 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) else if (msg == EScriptObjectMessage::Deleted)
{ {
//mgr.xf54_.sub80125d88(GetUniqueId()); //mgr.xf54_.sub80125d88(GetUniqueId());
if (x5d0_ != 3) if (x5d0_walkerType != EWalkerType::IceZoomer)
DestroyActorManager(mgr); DestroyActorManager(mgr);
} }
else if (msg == EScriptObjectMessage::Jumped && x742_25_) else if (msg == EScriptObjectMessage::Jumped && x742_25_jumpVelDirty)
{ {
UpdateJumpVelocity(); UpdateJumpVelocity();
x742_25_ = false; x742_25_jumpVelDirty = false;
} }
else if (msg == EScriptObjectMessage::Activate) else if (msg == EScriptObjectMessage::Activate)
{ {
x5d6_27_ = false; x5d6_27_ = false;
if (x5d0_ != 0) if (x5d0_walkerType != EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
} }
else if (msg == EScriptObjectMessage::SuspendedMove) else if (msg == EScriptObjectMessage::SuspendedMove)
@ -103,7 +118,7 @@ void CParasite::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM
void CParasite::PreThink(float dt, CStateManager& mgr) void CParasite::PreThink(float dt, CStateManager& mgr)
{ {
CWallWalker::PreThink(dt, mgr); CWallWalker::PreThink(dt, mgr);
x743_26_ = false; x743_26_oculusShotAt = false;
} }
void CParasite::Think(float dt, CStateManager& mgr) void CParasite::Think(float dt, CStateManager& mgr)
@ -112,7 +127,7 @@ void CParasite::Think(float dt, CStateManager& mgr)
return; return;
++x5d4_; ++x5d4_;
if (x5d0_ == 3) if (x5d0_walkerType == EWalkerType::IceZoomer)
UpdateCollisionActors(mgr); UpdateCollisionActors(mgr);
x5d6_26_ = false; x5d6_26_ = false;
@ -167,7 +182,7 @@ void CParasite::Think(float dt, CStateManager& mgr)
{ {
CPlayer* pl = mgr.Player(); CPlayer* pl = mgr.Player();
float radius; float radius;
if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && !x742_30_) if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && !x742_30_attackOver)
radius = x590_colSphere.GetSphere().radius; radius = x590_colSphere.GetSphere().radius;
else else
radius = x708_; radius = x708_;
@ -177,10 +192,10 @@ void CParasite::Think(float dt, CStateManager& mgr)
if (plBox && plBox->intersects(aabox)) if (plBox && plBox->intersects(aabox))
{ {
if (!x742_30_) if (!x742_30_attackOver)
{ {
x742_30_ = true; x742_30_attackOver = true;
x742_27_ = false; x742_27_landed = false;
} }
if (x420_curDamageRemTime <= 0.f) if (x420_curDamageRemTime <= 0.f)
@ -204,7 +219,628 @@ void CParasite::Think(float dt, CStateManager& mgr)
if (x5d6_24_) if (x5d6_24_)
AlignToFloor(mgr, x590_colSphere.GetSphere().radius, GetTranslation() + 2.f * dt * x138_velocity, dt); 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) void CParasite::DestroyActorManager(CStateManager& mgr)
@ -214,12 +850,10 @@ void CParasite::DestroyActorManager(CStateManager& mgr)
void CParasite::UpdateJumpVelocity() void CParasite::UpdateJumpVelocity()
{ {
x150_momentum.x = 0; SetMomentumWR({0.f, 0.f, -GetWeight()});
x150_momentum.y = 0;
x150_momentum.z = -GetWeight();
zeus::CVector3f vec; zeus::CVector3f vec;
if (!x742_30_) if (!x742_30_attackOver)
{ {
vec = skAttackVelocity * GetTransform().frontVector(); vec = skAttackVelocity * GetTransform().frontVector();
vec.z = 0.5f * skRetreatVelocity; vec.z = 0.5f * skRetreatVelocity;
@ -231,10 +865,8 @@ void CParasite::UpdateJumpVelocity()
} }
float f30 = x150_momentum.z / xe8_mass; float f30 = x150_momentum.z / xe8_mass;
float f31 = x600_ - GetTranslation().z; float f31 = x5f8_.z - GetTranslation().z;
zeus::CVector3f vec2; zeus::CVector3f vec2 = x5f8_ - GetTranslation();
vec2.x = x5f8_ - GetTranslation().x;
vec2.y = x5fc_ * GetTranslation().y;
vec2.z = 0.f; vec2.z = 0.f;
float f29 = vec2.magnitude(); float f29 = vec2.magnitude();

View File

@ -13,6 +13,12 @@ class CParasite : public CWallWalker
{ {
class CRepulsor 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 flt_805A8FB0;
static const float skAttackVelocity; static const float skAttackVelocity;
@ -24,23 +30,16 @@ class CParasite : public CWallWalker
float x5ec_ = 0.f; float x5ec_ = 0.f;
float x5f0_ = 0.f; float x5f0_ = 0.f;
float x5f4_ = 0.f; float x5f4_ = 0.f;
float x5f8_ = 0.f; zeus::CVector3f x5f8_;
float x5fc_ = 0.f;
float x600_ = 0.f;
float x604_ = 1.f; float x604_ = 1.f;
float x608_ = 0.f; float x608_ = 0.f;
float x60c_ = 0.f; float x60c_ = 0.f;
zeus::CVector3f x614_; zeus::CVector3f x614_;
std::unique_ptr<CCollisionActorManager> x620_ = 0; std::unique_ptr<CCollisionActorManager> x620_ = 0;
u32 x624_ = 0; TLockedToken<CSkinnedModel> x624_extraModel;
float x628_ = 0.f; zeus::CVector3f x628_;
float x62c_ = 0.f; zeus::CVector3f x634_;
float x630_ = 0.f; zeus::CVector3f x640_;
float x634_ = 0.f;
float x638_ = 0.f;
float x640_ = 0.f;
float x644_ = 0.f;
float x648_ = 0.f;
CDamageVulnerability x64c_; CDamageVulnerability x64c_;
CDamageInfo x6b4_; CDamageInfo x6b4_;
float x6d0_; float x6d0_;
@ -68,46 +67,85 @@ class CParasite : public CWallWalker
float x730_ = 0.f; float x730_ = 0.f;
float x734_ = 0.f; float x734_ = 0.f;
float x738_ = 0.f; float x738_ = 0.f;
s16 x73c_; u16 x73c_haltSfx;
s16 x73e_; u16 x73e_getUpSfx;
s16 x740_; u16 x740_crouchSfx;
union union
{ {
struct struct
{ {
bool x742_24_ : 1; bool x742_24_ : 1;
bool x742_25_ : 1; bool x742_25_jumpVelDirty : 1;
bool x742_26_ : 1; bool x742_26_ : 1;
bool x742_27_ : 1; bool x742_27_landed : 1;
bool x742_28_ : 1; bool x742_28_onGround : 1;
bool x742_29_ : 1; bool x742_29_ : 1;
bool x742_30_ : 1; bool x742_30_attackOver : 1;
bool x742_31_ : 1; bool x742_31_ : 1;
bool x743_24_ : 1; bool x743_24_ : 1;
bool x743_25_ : 1; bool x743_25_ : 1;
bool x743_26_ : 1; bool x743_26_oculusShotAt : 1;
bool x743_27_ : 1; bool x743_27_inJump : 1;
}; };
u16 _dummy = 0; 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: public:
DEFINE_PATTERNED(Parasite) DEFINE_PATTERNED(Parasite)
CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo&, EBodyType, float, float, float, 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, 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&); const CActorParameters&);
void Accept(IVisitor&); void Accept(IVisitor&);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void PreThink(float, CStateManager&); void PreThink(float, CStateManager&);
void Think(float dt, CStateManager& mgr); 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 DestroyActorManager(CStateManager& mgr);
void UpdateJumpVelocity(); void UpdateJumpVelocity();
void UpdateCollisionActors(CStateManager&) {} void UpdateCollisionActors(CStateManager&) {}
CDamageInfo GetContactDamage() const CDamageInfo GetContactDamage() const
{ {
if (x5d0_ == 1 && x743_24_) if (x5d0_walkerType == EWalkerType::Oculus && x743_24_)
return x6b4_; return x6b4_;
return CPatterned::GetContactDamage(); 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) 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, : CWallWalker(ECharacter::Seedling, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Ground, EColliderType::Zero, EBodyType::WallWalker, actParms, f1, f2, 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, virtual void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info,
EKnockBackType type, bool inDeferred, float magnitude)=0; EKnockBackType type, bool inDeferred, float magnitude)=0;
virtual const CDamageVulnerability* GetDamageVulnerability() const { return &x260_damageVulnerability; } 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 void TakeDamage(const zeus::CVector3f& direction, float magnitude) {}
virtual bool CanBeShot(const CStateManager&, int) { return true; } virtual bool CanBeShot(const CStateManager&, int) { return true; }
virtual bool IsListening() const { return false; } virtual bool IsListening() const { return false; }

View File

@ -485,7 +485,7 @@ void CKnockBackController::ValidateState(CPatterned& parent)
if (disableFollowup) if (disableFollowup)
{ {
x4_activeParms.x4_animFollowup = EKnockBackAnimationFollowUp::None; 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; EKnockBackAnimationState x0_animState;
EKnockBackAnimationFollowUp x4_animFollowup; EKnockBackAnimationFollowUp x4_animFollowup;
float x8_followupMagnitude; float x8_followupDuration;
float xc_; float xc_intoFreezeDur;
}; };
private: private:
friend class CPatterned; friend class CPatterned;
@ -149,6 +149,12 @@ public:
void KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, void KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent,
const CDamageInfo& info, EKnockBackType type, float magnitude); const CDamageInfo& info, EKnockBackType type, float magnitude);
void SetEnableFreeze(bool b) { x81_25_enableFreeze = b; } 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; } const KnockBackParms& GetActiveParms() const { return x4_activeParms; }
EKnockBackVariant GetVariant() const { return x0_variant; } EKnockBackVariant GetVariant() const { return x0_variant; }
}; };

View File

@ -11,6 +11,7 @@
#include "Character/CAnimData.hpp" #include "Character/CAnimData.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "MP1/World/CSpacePirate.hpp" #include "MP1/World/CSpacePirate.hpp"
#include "MP1/World/CMetroid.hpp"
#include "World/CStateMachine.hpp" #include "World/CStateMachine.hpp"
#include "CExplosion.hpp" #include "CExplosion.hpp"
#include "Graphics/CSkinnedModel.hpp" #include "Graphics/CSkinnedModel.hpp"
@ -419,6 +420,17 @@ zeus::CVector3f CPatterned::GetAimPosition(const urde::CStateManager& mgr, float
return offset + GetBoundingBox().center(); 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) void CPatterned::DeathDelete(CStateManager& mgr)
{ {
SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); 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) if (!x401_27_phazingOut && !x401_28_burning && hInfo)
{ {
x460_knockBackController.KnockBack(backVec, mgr, *this, info, type, magnitude); 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(); x450_bodyController->FrozenBreakout();
switch (x460_knockBackController.GetActiveParms().x4_animFollowup) switch (x460_knockBackController.GetActiveParms().x4_animFollowup)
{ {
case EKnockBackAnimationFollowUp::Freeze: case EKnockBackAnimationFollowUp::Freeze:
Freeze(mgr, zeus::CVector3f::skZero, zeus::CUnitVector3f(x34_transform.transposeRotate(backVec)), Freeze(mgr, zeus::CVector3f::skZero, zeus::CUnitVector3f(x34_transform.transposeRotate(backVec)),
x460_knockBackController.GetActiveParms().x8_followupMagnitude); x460_knockBackController.GetActiveParms().x8_followupDuration);
break; break;
case EKnockBackAnimationFollowUp::PhazeOut: case EKnockBackAnimationFollowUp::PhazeOut:
PhazeOut(mgr); PhazeOut(mgr);
break; break;
case EKnockBackAnimationFollowUp::Shock: case EKnockBackAnimationFollowUp::Shock:
Shock(x460_knockBackController.GetActiveParms().x8_followupMagnitude, -1.f); Shock(x460_knockBackController.GetActiveParms().x8_followupDuration, -1.f);
break; break;
case EKnockBackAnimationFollowUp::Burn: case EKnockBackAnimationFollowUp::Burn:
Burn(x460_knockBackController.GetActiveParms().x8_followupMagnitude, 0.25f); Burn(x460_knockBackController.GetActiveParms().x8_followupDuration, 0.25f);
break; break;
case EKnockBackAnimationFollowUp::LaggedBurnDeath: case EKnockBackAnimationFollowUp::LaggedBurnDeath:
x401_29_laggedBurnDeath = true; x401_29_laggedBurnDeath = true;
case EKnockBackAnimationFollowUp::BurnDeath: 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); Death(mgr, zeus::CVector3f::skZero, EScriptObjectState::DeathRattle);
x400_28_pendingMassiveDeath = x400_29_pendingMassiveFrozenDeath = false; x400_28_pendingMassiveDeath = x400_29_pendingMassiveFrozenDeath = false;
x400_27_fadeToDeath = x401_28_burning = true; x400_27_fadeToDeath = x401_28_burning = true;
@ -561,7 +573,7 @@ bool CPatterned::Random(CStateManager&, float arg)
bool CPatterned::CodeTrigger(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) bool CPatterned::FixedDelay(CStateManager&, float arg)
@ -779,7 +791,7 @@ bool CPatterned::OffLine(CStateManager&, float arg)
return distSq > arg * 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()) 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) 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) 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) 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) 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) 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) void CPatterned::BuildBodyController(EBodyType bodyType)
{ {
if (x450_bodyController) if (x450_bodyController)
@ -1067,6 +1095,75 @@ void CPatterned::MassiveFrozenDeath(CStateManager& mgr)
x400_28_pendingMassiveDeath = x400_29_pendingMassiveFrozenDeath = false; 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 CPatterned::GetGunEyePos() const
{ {
zeus::CVector3f origin = GetOrigin(); zeus::CVector3f origin = GetOrigin();
@ -1684,4 +1781,13 @@ void CPatterned::ThinkAboutMove(float dt)
RotateToOR(x440_rotDelta, 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 CPatternedInfo;
class CProjectileInfo; class CProjectileInfo;
class CPathFindSearch; class CPathFindSearch;
typedef void (CPatterned::*CPatternedTryFunc)(CStateManager&, int);
class CPatterned : public CAi class CPatterned : public CAi
{ {
@ -133,7 +134,7 @@ public:
{ {
Zero, Zero,
One, One,
Two, Repeat,
Over Over
}; };
class CPatternNode class CPatternNode
@ -327,6 +328,8 @@ public:
return GetAimPosition(mgr, 0.f); return GetAimPosition(mgr, 0.f);
} }
zeus::CVector3f GetAimPosition(const CStateManager& mgr, float) const; 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 DeathDelete(CStateManager& mgr);
void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state); void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state);
@ -363,21 +366,24 @@ public:
bool InRange(CStateManager&, float arg); bool InRange(CStateManager&, float arg);
bool OffLine(CStateManager&, float arg); bool OffLine(CStateManager&, float arg);
bool Default(CStateManager&, float arg) { return true; } bool Default(CStateManager&, float arg) { return true; }
void PathFind(CStateManager&, EStateMsg msg, float arg); void PathFind(CStateManager&, EStateMsg msg, float dt);
void Dead(CStateManager&, EStateMsg msg, float arg); void Dead(CStateManager&, EStateMsg msg, float dt);
void TargetPlayer(CStateManager&, EStateMsg msg, float arg); void TargetPlayer(CStateManager&, EStateMsg msg, float dt);
void TargetPatrol(CStateManager&, EStateMsg msg, float arg); void TargetPatrol(CStateManager&, EStateMsg msg, float dt);
void FollowPattern(CStateManager&, EStateMsg msg, float arg); void FollowPattern(CStateManager&, EStateMsg msg, float dt);
void Patrol(CStateManager&, EStateMsg msg, float arg); void Patrol(CStateManager&, EStateMsg msg, float dt);
void Start(CStateManager&, EStateMsg msg, float arg) {} 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 bool KnockbackWhenFrozen() const { return true; }
virtual void MassiveDeath(CStateManager& mgr); virtual void MassiveDeath(CStateManager& mgr);
virtual void MassiveFrozenDeath(CStateManager& mgr); virtual void MassiveFrozenDeath(CStateManager& mgr);
virtual void Burn(float, float) {} virtual void Burn(float, float);
virtual void Shock(float, float) {} virtual void Shock(float, float);
virtual void Freeze(CStateManager& mgr, const zeus::CVector3f& pos, 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 void ThinkAboutMove(float);
virtual CPathFindSearch* GetSearchPath() { return nullptr; } virtual CPathFindSearch* GetSearchPath() { return nullptr; }
virtual CDamageInfo GetContactDamage() const { return x404_contactDamage; } virtual CDamageInfo GetContactDamage() const { return x404_contactDamage; }
@ -385,7 +391,7 @@ public:
virtual bool IsOnGround() const { return x328_27_onGround; } virtual bool IsOnGround() const { return x328_27_onGround; }
virtual float GetGravityConstant() const { return 24.525002f; } virtual float GetGravityConstant() const { return 24.525002f; }
virtual CProjectileInfo* GetProjectileInfo() { return nullptr; } virtual CProjectileInfo* GetProjectileInfo() { return nullptr; }
virtual void PhazeOut(CStateManager&) {} virtual void PhazeOut(CStateManager&);
virtual const std::experimental::optional<TLockedToken<CGenDescription>>& virtual const std::experimental::optional<TLockedToken<CGenDescription>>&
GetDeathExplosionParticle() const { return x520_deathExplosionParticle; } GetDeathExplosionParticle() const { return x520_deathExplosionParticle; }
float GetDamageDuration() const { return x504_damageDur; } float GetDamageDuration() const { return x504_damageDur; }

View File

@ -61,7 +61,7 @@ CStateMachine::CStateMachine(CInputStream& in)
s32 CStateMachine::GetStateIndex(std::string_view state) const 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); return (strncmp(st.GetName(), state.data(), 31) == 0);
}); });
if (it == x0_states.end()) 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->CallFunc(mgr, ai, EStateMsg::Deactivate, 0.f);
x4_state = state; x4_state = state;
x8_time = 0.f; x8_time = 0.f;
x18_24_ = false; x18_24_codeTrigger = false;
xc_random = mgr.GetActiveRandom()->Float(); xc_random = mgr.GetActiveRandom()->Float();
x4_state->CallFunc(mgr, ai, EStateMsg::Activate, delta); x4_state->CallFunc(mgr, ai, EStateMsg::Activate, delta);
return; return;
@ -115,7 +115,7 @@ void CStateMachineState::SetState(CStateManager& mgr, CAi& ai, s32 idx)
x4_state = state; x4_state = state;
x8_time = 0.f; x8_time = 0.f;
xc_random = mgr.GetActiveRandom()->Float(); xc_random = mgr.GetActiveRandom()->Float();
x18_24_ = false; x18_24_codeTrigger = false;
x4_state->CallFunc(mgr, ai, EStateMsg::Activate, 0.f); x4_state->CallFunc(mgr, ai, EStateMsg::Activate, 0.f);
} }
} }

View File

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

View File

@ -9,16 +9,16 @@ namespace urde
CWallWalker::CWallWalker(ECharacter chr, TUniqueId uid, std::string_view name, EFlavorType flavType, CWallWalker::CWallWalker(ECharacter chr, TUniqueId uid, std::string_view name, EFlavorType flavType,
const CEntityInfo& eInfo, const zeus::CTransform& xf, const CEntityInfo& eInfo, const zeus::CTransform& xf,
CModelData&& mData, const CPatternedInfo& pInfo, EMovementType mType, CModelData&& mData, const CPatternedInfo& pInfo, EMovementType mType,
EColliderType colType, EBodyType bType, const CActorParameters& aParms, float f1, float f2, EColliderType colType, EBodyType bType, const CActorParameters& aParms,
EKnockBackVariant w1, float f3, u32 w2, float f4, bool b1) 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, w1) : 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) , x590_colSphere(zeus::CSphere(zeus::CVector3f::skZero, pInfo.GetHalfExtent()), x68_material)
, x5b0_(f1) , x5b0_collisionCloseMargin(f1)
, x5b4_(f2) , x5b4_(f2)
, x5c0_advanceWpRadius(f3) , x5c0_advanceWpRadius(f3)
, x5c4_(f4) , x5c4_(f4)
, x5cc_bendingHackAnim(GetModelData()->GetAnimationData()->GetCharacterInfo().GetAnimationIndex("BendingAnimationHack"sv)) , x5cc_bendingHackAnim(GetModelData()->GetAnimationData()->GetCharacterInfo().GetAnimationIndex("BendingAnimationHack"sv))
, x5d0_(w2) , x5d0_walkerType(wType)
, x5d6_24_(false) , x5d6_24_(false)
, x5d6_25_(false) , x5d6_25_(false)
, x5d6_26_(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) void CWallWalker::PreThink(float dt, CStateManager& mgr)
{ {
CPatterned::PreThink(dt, mgr); CPatterned::PreThink(dt, mgr);
@ -45,11 +76,9 @@ void CWallWalker::PreThink(float dt, CStateManager& mgr)
SetTranslation(GetTranslation() * (1.f - futureDt) + SetTranslation(GetTranslation() * (1.f - futureDt) +
(((GetTranslation() - ((plane.vec.dot(GetTranslation())) - plane.d) - (((GetTranslation() - ((plane.vec.dot(GetTranslation())) - plane.d) -
x590_colSphere.GetSphere().radius - 0.1f) * plane.vec) * futureDt)); x590_colSphere.GetSphere().radius - 0.1f) * plane.vec) * futureDt));
} }
else else
MoveCollisionPrimitive(zeus::CVector3f::skZero); MoveCollisionPrimitive(zeus::CVector3f::skZero);
} }
void CWallWalker::Think(float dt, CStateManager& mgr) 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) void CWallWalker::UpdateWPDestination(CStateManager& mgr)
{ {
if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(x2dc_destObj)) if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(x2dc_destObj))
@ -103,7 +137,7 @@ void CWallWalker::UpdateWPDestination(CStateManager& mgr)
if (std::fabs(wp->GetPause()) > 0.00001f) if (std::fabs(wp->GetPause()) > 0.00001f)
{ {
x5bc_ = wp->GetPause(); x5bc_ = wp->GetPause();
if (x5d0_ == 0) if (x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived); mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived);
} }

View File

@ -8,12 +8,21 @@ namespace urde
{ {
class CWallWalker : public CPatterned class CWallWalker : public CPatterned
{ {
public:
enum class EWalkerType
{
Parasite = 0,
Oculus = 1,
Geemer = 2,
IceZoomer = 3,
Seedling = 4
};
protected: protected:
CCollisionSurface x568_ = CCollisionSurface(zeus::CVector3f(), CCollisionSurface x568_ = CCollisionSurface(zeus::CVector3f(),
zeus::CVector3f::skForward, zeus::CVector3f::skForward,
zeus::CVector3f::skRight, -1); zeus::CVector3f::skRight, -1);
CCollidableSphere x590_colSphere; CCollidableSphere x590_colSphere;
float x5b0_; float x5b0_collisionCloseMargin;
float x5b4_; float x5b4_;
float x5b8_ = 0.f; float x5b8_ = 0.f;
float x5bc_ = 0.f; float x5bc_ = 0.f;
@ -21,7 +30,7 @@ protected:
float x5c4_; float x5c4_;
float x5c8_bendingHackWeight = 0.f; float x5c8_bendingHackWeight = 0.f;
s32 x5cc_bendingHackAnim; s32 x5cc_bendingHackAnim;
u32 x5d0_; EWalkerType x5d0_walkerType;
s16 x5d4_ = 0; s16 x5d4_ = 0;
bool x5d6_24_ : 1; bool x5d6_24_ : 1;
bool x5d6_25_ : 1; bool x5d6_25_ : 1;
@ -29,13 +38,20 @@ protected:
bool x5d6_27_ : 1; bool x5d6_27_ : 1;
bool x5d6_28_addBendingWeight : 1; bool x5d6_28_addBendingWeight : 1;
bool x5d6_29_applyBendingHack : 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: public:
CWallWalker(ECharacter, TUniqueId, std::string_view, EFlavorType, const CEntityInfo&, const zeus::CTransform&, CWallWalker(ECharacter, TUniqueId, std::string_view, EFlavorType, const CEntityInfo&, const zeus::CTransform&,
CModelData&&, const CPatternedInfo&, EMovementType, EColliderType, EBodyType, 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 PreThink(float, CStateManager&);
void Think(float, CStateManager&); void Think(float, CStateManager&);
void Render(const CStateManager&) const;
const CCollisionPrimitive* GetCollisionPrimitive() const { return &x590_colSphere; } const CCollisionPrimitive* GetCollisionPrimitive() const { return &x590_colSphere; }
void UpdateWPDestination(CStateManager&); 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)); CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true));
return new MP1::CParasite(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, 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, 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(), f16, f17, 0.f, b1, CWallWalker::EWalkerType::Parasite,
-1, -1, -1, -1, -1, 0.f, aParms); CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(),
-1, -1, -1, {}, {}, 0.f, aParms);
} }
CEntity* ScriptLoader::LoadPlayerHint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) 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, 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, actHead.x10_transform, std::move(mData), pInfo, EBodyType::WallWalker, 0.f, f1, f2, f3,
f4, 0.2f, 0.4f, 0.f, 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, CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(), sId1, sId2, sId3, -1,
-1, 0.f, actParms); -1, 0.f, actParms);
} }

View File

@ -159,7 +159,7 @@ enum class EScriptObjectState
CameraTarget = 16, CameraTarget = 16,
UNKS2 = 17, UNKS2 = 17,
Play = 18, Play = 18,
MassiveDeath = 19, MassiveDeath = 19,
DeathRattle = 20, DeathRattle = 20,
AboutToMassivelyDie = 21, AboutToMassivelyDie = 21,
Damage = 22, Damage = 22,