Implement body state classes

This commit is contained in:
Jack Andersen 2017-07-09 18:55:51 -10:00
parent 778b37e0f8
commit 56bfc276d6
43 changed files with 4087 additions and 248 deletions

View File

@ -23,7 +23,7 @@ struct Waypoint : IScriptObject
Value<atUint32> unknown6; Value<atUint32> unknown6;
Value<atUint32> unknown7; Value<atUint32> unknown7;
Value<atUint32> unknown8; Value<atUint32> unknown8;
Value<atUint32> unknown9; Value<atUint32> jumpFlags; // 0x2: single, 0x4: double
Value<atUint32> unknown10; Value<atUint32> unknown10;
}; };
} }

View File

View File

@ -0,0 +1,38 @@
#ifndef __URDE_CADDITIVEBODYSTATE_HPP__
#define __URDE_CADDITIVEBODYSTATE_HPP__
#include "RetroTypes.hpp"
#include "CharacterCommon.hpp"
#include "CBodyStateCmdMgr.hpp"
namespace urde
{
class CAdditiveBodyState
{
};
class CABSAim : public CAdditiveBodyState
{
};
class CABSFlinch : public CAdditiveBodyState
{
};
class CABSIdle : public CAdditiveBodyState
{
};
class CABSReaction : public CAdditiveBodyState
{
};
}
#endif // __URDE_CADDITIVEBODYSTATE_HPP__

View File

@ -30,6 +30,7 @@ rstl::reserved_vector<CBoolPOINode, 8>CAnimData::g_BoolPOINodes;
rstl::reserved_vector<CInt32POINode, 16> CAnimData::g_Int32POINodes; rstl::reserved_vector<CInt32POINode, 16> CAnimData::g_Int32POINodes;
rstl::reserved_vector<CParticlePOINode, 20> CAnimData::g_ParticlePOINodes; rstl::reserved_vector<CParticlePOINode, 20> CAnimData::g_ParticlePOINodes;
rstl::reserved_vector<CSoundPOINode, 20> CAnimData::g_SoundPOINodes; rstl::reserved_vector<CSoundPOINode, 20> CAnimData::g_SoundPOINodes;
rstl::reserved_vector<CInt32POINode, 16> CAnimData::g_TransientInt32POINodes;
void CAnimData::FreeCache() void CAnimData::FreeCache()
{ {
@ -73,6 +74,7 @@ CAnimData::CAnimData(ResId id,
g_Int32POINodes.resize(16); g_Int32POINodes.resize(16);
g_ParticlePOINodes.resize(20); g_ParticlePOINodes.resize(20);
g_SoundPOINodes.resize(20); g_SoundPOINodes.resize(20);
g_TransientInt32POINodes.resize(16);
x108_aabb = xd8_modelData->GetModel()->GetAABB(); x108_aabb = xd8_modelData->GetModel()->GetAABB();
x120_particleDB.CacheParticleDesc(xc_charInfo.GetParticleResData()); x120_particleDB.CacheParticleDesc(xc_charInfo.GetParticleResData());
@ -127,7 +129,7 @@ SAdvancementDeltas CAnimData::AdvanceAdditiveAnims(float dt)
std::shared_ptr<CAnimTreeNode>& anim = additive.second.GetAnim(); std::shared_ptr<CAnimTreeNode>& anim = additive.second.GetAnim();
if (additive.second.IsActive()) if (additive.second.IsActive())
{ {
while (time.GreaterThanZero() && std::fabs(time) >= 0.00001f) while (time.GreaterThanZero() && std::fabs(time.GetSeconds()) >= 0.00001f)
{ {
x210_passedIntCount += anim->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0); x210_passedIntCount += anim->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0);
x20c_passedBoolCount += anim->GetBoolPOIList(time, g_BoolPOINodes.data(), 8, x20c_passedBoolCount, 0); x20c_passedBoolCount += anim->GetBoolPOIList(time, g_BoolPOINodes.data(), 8, x20c_passedBoolCount, 0);
@ -143,7 +145,7 @@ SAdvancementDeltas CAnimData::AdvanceAdditiveAnims(float dt)
else else
{ {
CCharAnimTime remTime = anim->VGetTimeRemaining(); CCharAnimTime remTime = anim->VGetTimeRemaining();
while (remTime.GreaterThanZero() && std::fabs(remTime) >= 0.00001f) while (remTime.GreaterThanZero() && std::fabs(remTime.GetSeconds()) >= 0.00001f)
{ {
x210_passedIntCount += anim->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0); x210_passedIntCount += anim->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0);
x20c_passedBoolCount += anim->GetBoolPOIList(time, g_BoolPOINodes.data(), 8, x20c_passedBoolCount, 0); x20c_passedBoolCount += anim->GetBoolPOIList(time, g_BoolPOINodes.data(), 8, x20c_passedBoolCount, 0);
@ -276,9 +278,25 @@ SAdvancementDeltas CAnimData::GetAdvancementDeltas(const CCharAnimTime& a,
return x1f8_animRoot->VGetAdvancementResults(a, b).x8_deltas; return x1f8_animRoot->VGetAdvancementResults(a, b).x8_deltas;
} }
CCharAnimTime CAnimData::GetTimeOfUserEvent(EUserEventType, const CCharAnimTime& time) const CCharAnimTime CAnimData::GetTimeOfUserEvent(EUserEventType type, const CCharAnimTime& time) const
{ {
return {}; u32 count = x1f8_animRoot->GetInt32POIList(time, g_TransientInt32POINodes.data(), 16, 0, 64);
for (int i=0 ; i<count ; ++i)
{
CInt32POINode& poi = g_TransientInt32POINodes[i];
if (poi.GetPoiType() == EPOIType::UserEvent &&
EUserEventType(poi.GetValue()) == type)
{
for (; i<count ; ++i)
g_TransientInt32POINodes[i] = CInt32POINode();
return poi.GetTime();
}
else
{
poi = CInt32POINode();
}
}
return CCharAnimTime::Infinity();
} }
void CAnimData::MultiplyPlaybackRate(float mul) void CAnimData::MultiplyPlaybackRate(float mul)
@ -291,13 +309,193 @@ void CAnimData::SetPlaybackRate(float set)
x200_speedScale = set; x200_speedScale = set;
} }
void CAnimData::SetRandomPlaybackRate(CRandom16&) void CAnimData::SetRandomPlaybackRate(CRandom16& r)
{ {
for (int i=0 ; i<x210_passedIntCount ; ++i)
{
CInt32POINode& poi = g_Int32POINodes[i];
if (poi.GetPoiType() == EPOIType::RandRate)
{
float tmp = (r.Next() % poi.GetValue()) / 100.f;
if ((r.Next() % 100) < 50)
x200_speedScale = 1.f + tmp;
else
x200_speedScale = 1.f - tmp;
break;
}
}
} }
void CAnimData::CalcPlaybackAlignmentParms(const CAnimPlaybackParms& parms, void CAnimData::CalcPlaybackAlignmentParms(const CAnimPlaybackParms& parms,
const std::shared_ptr<CAnimTreeNode>& node) const std::shared_ptr<CAnimTreeNode>& node)
{ {
zeus::CQuaternion orient;
x1e8_alignRot = zeus::CQuaternion::skNoRotation;
x220_27_ = false;
if (parms.GetDeltaOrient() && parms.GetObjectXform())
{
ResetPOILists();
x210_passedIntCount += node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(),
16, x210_passedIntCount, 64);
for (int i=0 ; i<x210_passedIntCount ; ++i)
{
CInt32POINode& poi = g_Int32POINodes[i];
if (poi.GetPoiType() == EPOIType::UserEvent &&
EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetRot)
{
SAdvancementResults res = node->VGetAdvancementResults(poi.GetTime(), 0.f);
orient = zeus::CQuaternion::slerp(zeus::CQuaternion::skNoRotation,
*parms.GetDeltaOrient() *
zeus::CQuaternion(parms.GetObjectXform()->buildMatrix3f().inverted()) *
res.x8_deltas.xc_rotDelta.inverse(),
1.f / (60.f * poi.GetTime().GetSeconds()));
x1e8_alignRot = orient;
x220_27_ = true;
}
}
}
if (!x220_27_)
{
bool didAlign = false;
bool didStart = false;
zeus::CVector3f posStart, posAlign;
CCharAnimTime timeStart, timeAlign;
if (parms.GetTargetPos() && parms.GetObjectXform())
{
ResetPOILists();
x210_passedIntCount += node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(),
16, x210_passedIntCount, 64);
for (int i=0 ; i<x210_passedIntCount ; ++i)
{
CInt32POINode& poi = g_Int32POINodes[i];
if (poi.GetPoiType() == EPOIType::UserEvent)
{
if (EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetPosStart)
{
didStart = true;
SAdvancementResults res = node->VGetAdvancementResults(poi.GetTime(), 0.f);
posStart = res.x8_deltas.x0_posDelta;
timeStart = poi.GetTime();
if (parms.GetIsUseLocator())
posStart += GetLocatorTransform(poi.GetLocatorName(), &poi.GetTime()).origin;
if (didAlign)
break;
}
else if (EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetPos)
{
didAlign = true;
SAdvancementResults res = node->VGetAdvancementResults(poi.GetTime(), 0.f);
posAlign = res.x8_deltas.x0_posDelta;
timeAlign = poi.GetTime();
if (parms.GetIsUseLocator())
posAlign += GetLocatorTransform(poi.GetLocatorName(), &poi.GetTime()).origin;
if (didStart)
break;
}
}
}
if (didAlign && didStart)
{
zeus::CVector3f scaleStart = *parms.GetObjectScale() * posStart;
zeus::CVector3f scaleAlign = *parms.GetObjectScale() * posAlign;
x1dc_alignPos = (parms.GetObjectXform()->inverse() * *parms.GetTargetPos() - scaleStart -
(scaleAlign - scaleStart)) / *parms.GetObjectScale() *
(1.f / (timeAlign.GetSeconds() - timeStart.GetSeconds()));
x220_28_ = true;
x220_26_ = false;
}
else
{
x1dc_alignPos = zeus::CVector3f::skZero;
x220_28_ = false;
x220_26_ = false;
}
}
}
else
{
bool didStart = false;
bool didAlign = false;
CCharAnimTime timeStart, timeAlign;
zeus::CVector3f startPos;
if (parms.GetTargetPos() && parms.GetObjectXform())
{
ResetPOILists();
x210_passedIntCount += node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(),
16, x210_passedIntCount, 64);
for (int i=0 ; i<x210_passedIntCount ; ++i)
{
CInt32POINode& poi = g_Int32POINodes[i];
if (poi.GetPoiType() == EPOIType::UserEvent)
{
if (EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetPosStart)
{
didStart = true;
timeStart = poi.GetTime();
if (didAlign)
break;
}
else if (EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetPos)
{
didAlign = true;
timeAlign = poi.GetTime();
if (didStart)
break;
}
}
}
if (didAlign && didStart)
{
CCharAnimTime frameInterval(1.f / 60.f);
orient = zeus::CQuaternion::skNoRotation;
x1e8_alignRot = zeus::CQuaternion::skNoRotation;
x220_27_ = true;
CCharAnimTime time;
zeus::CVector3f pos;
zeus::CQuaternion quat;
bool foundStartPos = false;
while (time < timeAlign)
{
SAdvancementResults res = node->VGetAdvancementResults(frameInterval, time);
pos += quat.toTransform() * res.x8_deltas.x0_posDelta;
quat *= (res.x8_deltas.xc_rotDelta * orient);
if (!foundStartPos && time >= timeStart)
{
startPos = pos;
foundStartPos = true;
}
time += frameInterval;
}
zeus::CVector3f scaleStart = startPos * *parms.GetObjectScale();
zeus::CVector3f scaleAlign = pos * *parms.GetObjectScale();
x1dc_alignPos = (parms.GetObjectXform()->inverse() * *parms.GetTargetPos() - scaleStart -
(scaleAlign - scaleStart)) / *parms.GetObjectScale() *
(1.f / (timeAlign.GetSeconds() - timeStart.GetSeconds()));
x220_28_ = true;
x220_26_ = false;
}
else
{
x1dc_alignPos = zeus::CVector3f::skZero;
x220_28_ = false;
x220_26_ = false;
}
}
else
{
x1dc_alignPos = zeus::CVector3f::skZero;
x220_28_ = false;
x220_26_ = false;
}
}
} }
zeus::CTransform CAnimData::GetLocatorTransform(CSegId id, const CCharAnimTime* time) const zeus::CTransform CAnimData::GetLocatorTransform(CSegId id, const CCharAnimTime* time) const
@ -330,12 +528,12 @@ bool CAnimData::IsAnimTimeRemaining(float rem, const std::string& name) const
{ {
if (!x1f8_animRoot) if (!x1f8_animRoot)
return false; return false;
return float(x1f8_animRoot->VGetTimeRemaining()) <= rem; return x1f8_animRoot->VGetTimeRemaining().GetSeconds() <= rem;
} }
float CAnimData::GetAnimTimeRemaining(const std::string& name) const float CAnimData::GetAnimTimeRemaining(const std::string& name) const
{ {
float rem = x1f8_animRoot->VGetTimeRemaining(); float rem = x1f8_animRoot->VGetTimeRemaining().GetSeconds();
if (x200_speedScale) if (x200_speedScale)
return rem / x200_speedScale; return rem / x200_speedScale;
return rem; return rem;
@ -373,7 +571,7 @@ float CAnimData::GetAnimationDuration(int animIn) const
} }
} }
durAccum += dur; durAccum += dur.GetSeconds();
} }
if (anim->GetType() == EMetaAnimType::Random) if (anim->GetType() == EMetaAnimType::Random)
@ -491,52 +689,52 @@ void CAnimData::PrimitiveSetToTokenVector(const std::set<CPrimitive>& primSet,
void CAnimData::GetAnimationPrimitives(const CAnimPlaybackParms& parms, std::set<CPrimitive>& primsOut) const void CAnimData::GetAnimationPrimitives(const CAnimPlaybackParms& parms, std::set<CPrimitive>& primsOut) const
{ {
std::shared_ptr<IMetaAnim> animA = std::shared_ptr<IMetaAnim> animA =
x100_animMgr->GetMetaAnimation(xc_charInfo.GetAnimationIndex(parms.x0_animA)); x100_animMgr->GetMetaAnimation(xc_charInfo.GetAnimationIndex(parms.GetAnimationId()));
animA->GetUniquePrimitives(primsOut); animA->GetUniquePrimitives(primsOut);
if (parms.x4_animB != -1) if (parms.GetSecondAnimationId() != -1)
{ {
std::shared_ptr<IMetaAnim> animB = std::shared_ptr<IMetaAnim> animB =
x100_animMgr->GetMetaAnimation(xc_charInfo.GetAnimationIndex(parms.x4_animB)); x100_animMgr->GetMetaAnimation(xc_charInfo.GetAnimationIndex(parms.GetSecondAnimationId()));
animB->GetUniquePrimitives(primsOut); animB->GetUniquePrimitives(primsOut);
} }
} }
void CAnimData::SetAnimation(const CAnimPlaybackParms& parms, bool noTrans) void CAnimData::SetAnimation(const CAnimPlaybackParms& parms, bool noTrans)
{ {
if (parms.x0_animA == x40c_playbackParms.x0_animA || if (parms.GetAnimationId() == x40c_playbackParms.GetAnimationId() ||
(parms.x4_animB == x40c_playbackParms.x4_animB && (parms.GetSecondAnimationId() == x40c_playbackParms.GetSecondAnimationId() &&
parms.x8_blendWeight == x40c_playbackParms.x8_blendWeight && parms.GetBlendFactor() == x40c_playbackParms.GetBlendFactor() &&
parms.x8_blendWeight != 1.f) || parms.GetBlendFactor() != 1.f) ||
parms.x4_animB == -1) parms.GetSecondAnimationId() == -1)
{ {
if (x220_29_animationJustStarted) if (x220_29_animationJustStarted)
return; return;
} }
x40c_playbackParms.x0_animA = parms.x0_animA; x40c_playbackParms.SetAnimationId(parms.GetAnimationId());
x40c_playbackParms.x4_animB = parms.x4_animB; x40c_playbackParms.SetSecondAnimationId(parms.GetSecondAnimationId());
x40c_playbackParms.x8_blendWeight = parms.x8_blendWeight; x40c_playbackParms.SetBlendFactor(parms.GetBlendFactor());
x200_speedScale = 1.f; x200_speedScale = 1.f;
x208_defaultAnim = parms.x0_animA; x208_defaultAnim = parms.GetAnimationId();
u32 animIdxA = xc_charInfo.GetAnimationIndex(parms.x0_animA); u32 animIdxA = xc_charInfo.GetAnimationIndex(parms.GetAnimationId());
ResetPOILists(); ResetPOILists();
std::shared_ptr<CAnimTreeNode> blendNode; std::shared_ptr<CAnimTreeNode> blendNode;
if (parms.x4_animB != -1) if (parms.GetSecondAnimationId() != -1)
{ {
u32 animIdxB = xc_charInfo.GetAnimationIndex(parms.x4_animB); u32 animIdxB = xc_charInfo.GetAnimationIndex(parms.GetSecondAnimationId());
std::shared_ptr<CAnimTreeNode> treeA = std::shared_ptr<CAnimTreeNode> treeA =
x100_animMgr->GetAnimationTree(animIdxA, CMetaAnimTreeBuildOrders::NoSpecialOrders()); x100_animMgr->GetAnimationTree(animIdxA, CMetaAnimTreeBuildOrders::NoSpecialOrders());
std::shared_ptr<CAnimTreeNode> treeB = std::shared_ptr<CAnimTreeNode> treeB =
x100_animMgr->GetAnimationTree(animIdxB, CMetaAnimTreeBuildOrders::NoSpecialOrders()); x100_animMgr->GetAnimationTree(animIdxB, CMetaAnimTreeBuildOrders::NoSpecialOrders());
blendNode = std::make_shared<CAnimTreeBlend>(false, treeA, treeB, parms.x8_blendWeight, blendNode = std::make_shared<CAnimTreeBlend>(false, treeA, treeB, parms.GetBlendFactor(),
CAnimTreeBlend::CreatePrimitiveName(treeA, treeB, CAnimTreeBlend::CreatePrimitiveName(treeA, treeB,
parms.x8_blendWeight)); parms.GetBlendFactor()));
} }
else else
{ {
@ -548,7 +746,7 @@ void CAnimData::SetAnimation(const CAnimPlaybackParms& parms, bool noTrans)
else else
x1f8_animRoot = blendNode; x1f8_animRoot = blendNode;
x220_24_animating = parms.xc_animating; x220_24_animating = parms.GetIsPlayAnimation();
CalcPlaybackAlignmentParms(parms, blendNode); CalcPlaybackAlignmentParms(parms, blendNode);
ResetPOILists(); ResetPOILists();
x220_29_animationJustStarted = true; x220_29_animationJustStarted = true;
@ -608,7 +806,7 @@ SAdvancementDeltas CAnimData::DoAdvance(float dt, bool& suspendParticles, CRando
x218_passedSoundCount += x1f8_animRoot->GetSoundPOIList(time, g_SoundPOINodes.data(), 16, x218_passedSoundCount, 0); x218_passedSoundCount += x1f8_animRoot->GetSoundPOIList(time, g_SoundPOINodes.data(), 16, x218_passedSoundCount, 0);
AdvanceAnim(time, offsetPost, quatPost); AdvanceAnim(time, offsetPost, quatPost);
remTime = x1f8_animRoot->VGetTimeRemaining(); remTime = x1f8_animRoot->VGetTimeRemaining();
time = std::max(0.f, std::min(float(remTime), float(time))); time = std::max(0.f, std::min(remTime.GetSeconds(), time.GetSeconds()));
if (remTime.EpsilonZero()) if (remTime.EpsilonZero())
{ {
x220_24_animating = false; x220_24_animating = false;
@ -703,7 +901,7 @@ void CAnimData::AdvanceAnim(CCharAnimTime& time, zeus::CVector3f& offset, zeus::
offset += results.x8_deltas.x0_posDelta; offset += results.x8_deltas.x0_posDelta;
if (x220_26_) if (x220_26_)
offset += x1dc_alignPos * time; offset += x1dc_alignPos * time.GetSeconds();
zeus::CQuaternion rot = results.x8_deltas.xc_rotDelta * x1e8_alignRot; zeus::CQuaternion rot = results.x8_deltas.xc_rotDelta * x1e8_alignRot;
quat = quat * rot; quat = quat * rot;
@ -771,8 +969,8 @@ float CAnimData::GetAverageVelocity(int animIn) const
} }
} }
velAccum += dur * avgVel; velAccum += dur.GetSeconds() * avgVel;
durAccum += dur; durAccum += dur.GetSeconds();
} }
if (durAccum > 0.f) if (durAccum > 0.f)

View File

@ -139,6 +139,7 @@ class CAnimData
static rstl::reserved_vector<CInt32POINode, 16> g_Int32POINodes; static rstl::reserved_vector<CInt32POINode, 16> g_Int32POINodes;
static rstl::reserved_vector<CParticlePOINode, 20> g_ParticlePOINodes; static rstl::reserved_vector<CParticlePOINode, 20> g_ParticlePOINodes;
static rstl::reserved_vector<CSoundPOINode, 20> g_SoundPOINodes; static rstl::reserved_vector<CSoundPOINode, 20> g_SoundPOINodes;
static rstl::reserved_vector<CInt32POINode, 16> g_TransientInt32POINodes;
int m_drawInstCount; int m_drawInstCount;
@ -184,6 +185,7 @@ public:
float GetAnimationDuration(int) const; float GetAnimationDuration(int) const;
bool GetIsLoop() const {return x220_25_loop;} bool GetIsLoop() const {return x220_25_loop;}
void EnableLooping(bool val) {x220_25_loop = val; x220_24_animating = true;} void EnableLooping(bool val) {x220_25_loop = val; x220_24_animating = true;}
void EnableAnimation(bool val) {x220_24_animating = val;}
bool IsAnimating() const {return x220_24_animating;} bool IsAnimating() const {return x220_24_animating;}
std::shared_ptr<CAnimSysContext> GetAnimSysContext() const; std::shared_ptr<CAnimSysContext> GetAnimSysContext() const;
std::shared_ptr<CAnimationManager> GetAnimationManager() const; std::shared_ptr<CAnimationManager> GetAnimationManager() const;

View File

@ -2,27 +2,42 @@
#define __CANIMPLAYBACKPARMS_HPP__ #define __CANIMPLAYBACKPARMS_HPP__
#include "RetroTypes.hpp" #include "RetroTypes.hpp"
#include "zeus/CQuaternion.hpp"
namespace urde namespace urde
{ {
class CAnimPlaybackParms class CAnimPlaybackParms
{ {
friend class CAnimData;
s32 x0_animA = -1; s32 x0_animA = -1;
s32 x4_animB = -1; s32 x4_animB = -1;
float x8_blendWeight = 1.f; float x8_blendWeight = 1.f;
bool xc_animating = true; bool xc_animating = true;
s32 x10_ = 0; s32 x10_ = 0;
s32 x14_ = 0; const zeus::CVector3f* x14_targetPos = nullptr;
bool x18_ = false; bool x18_useLocator = false;
s32 x1c_ = 0; const zeus::CQuaternion* x1c_deltaOrient = nullptr;
s32 x20_ = 0; const zeus::CTransform* x20_objectXf = nullptr;
s32 x24_ = 0; const zeus::CVector3f* x24_objectScale = nullptr;
public: public:
CAnimPlaybackParms() = default; CAnimPlaybackParms() = default;
CAnimPlaybackParms(s32 animA, s32 animB, float blendWeight, bool animating) CAnimPlaybackParms(s32 animA, s32 animB, float blendWeight, bool animating)
: x0_animA(animA), x4_animB(animB), x8_blendWeight(blendWeight), xc_animating(animating) : x0_animA(animA), x4_animB(animB), x8_blendWeight(blendWeight), xc_animating(animating) {}
{} CAnimPlaybackParms(s32 anim, const zeus::CQuaternion* deltaOrient, const zeus::CVector3f* targetPos,
const zeus::CTransform* xf, const zeus::CVector3f* scale, bool useLocator)
: x0_animA(anim), x14_targetPos(targetPos), x18_useLocator(useLocator), x1c_deltaOrient(deltaOrient),
x20_objectXf(xf), x24_objectScale(scale) {}
const zeus::CTransform* GetObjectXform() const { return x20_objectXf; }
const zeus::CQuaternion* GetDeltaOrient() const { return x1c_deltaOrient; }
const zeus::CVector3f* GetTargetPos() const { return x14_targetPos; }
bool GetIsUseLocator() const { return x18_useLocator; }
const zeus::CVector3f* GetObjectScale() const { return x24_objectScale; }
s32 GetAnimationId() const { return x0_animA; }
s32 GetSecondAnimationId() const { return x4_animB; }
float GetBlendFactor() const { return x8_blendWeight; }
void SetAnimationId(s32 id) { x0_animA = id; }
void SetSecondAnimationId(s32 id) { x4_animB = id; }
void SetBlendFactor(float f) { x8_blendWeight = f; }
bool GetIsPlayAnimation() const { return xc_animating; }
}; };
} }

View File

@ -120,7 +120,7 @@ void CAnimSource::CalcAverageVelocity()
if (frameVel > 0.00001f) if (frameVel > 0.00001f)
accum += frameVel; accum += frameVel;
} }
x60_averageVelocity = accum / x0_duration; x60_averageVelocity = accum / x0_duration.GetSeconds();
} }
CAnimSource::CAnimSource(CInputStream& in, IObjectStore& store) CAnimSource::CAnimSource(CInputStream& in, IObjectStore& store)
@ -146,10 +146,10 @@ void CAnimSource::GetSegStatementSet(const CSegIdList& list,
const CCharAnimTime& time) const const CCharAnimTime& time) const
{ {
u32 frameIdx = unsigned(time / x8_interval); u32 frameIdx = unsigned(time / x8_interval);
float remTime = time - frameIdx * x8_interval; float remTime = time.GetSeconds() - frameIdx * x8_interval.GetSeconds();
if (std::fabs(remTime) < 0.00001f) if (std::fabs(remTime) < 0.00001f)
remTime = 0.f; remTime = 0.f;
float t = ClampZeroToOne(remTime / x8_interval); float t = ClampZeroToOne(remTime / x8_interval.GetSeconds());
const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4; const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4;
const u32 rotFloatsPerFrame = x40_data.xc_rotPerFrame * 4; const u32 rotFloatsPerFrame = x40_data.xc_rotPerFrame * 4;
@ -209,10 +209,10 @@ zeus::CQuaternion CAnimSource::GetRotation(const CSegId& seg, const CCharAnimTim
if (rotIdx != 0xff) if (rotIdx != 0xff)
{ {
u32 frameIdx = unsigned(time / x8_interval); u32 frameIdx = unsigned(time / x8_interval);
float remTime = time - frameIdx * x8_interval; float remTime = time.GetSeconds() - frameIdx * x8_interval.GetSeconds();
if (std::fabs(remTime) < 0.00001f) if (std::fabs(remTime) < 0.00001f)
remTime = 0.f; remTime = 0.f;
float t = ClampZeroToOne(remTime / x8_interval); float t = ClampZeroToOne(remTime / x8_interval.GetSeconds());
const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4; const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4;
const float* frameDataA = const float* frameDataA =
@ -240,10 +240,10 @@ zeus::CVector3f CAnimSource::GetOffset(const CSegId& seg, const CCharAnimTime& t
return {}; return {};
u32 frameIdx = unsigned(time / x8_interval); u32 frameIdx = unsigned(time / x8_interval);
float remTime = time - frameIdx * x8_interval; float remTime = time.GetSeconds() - frameIdx * x8_interval.GetSeconds();
if (std::fabs(remTime) < 0.00001f) if (std::fabs(remTime) < 0.00001f)
remTime = 0.f; remTime = 0.f;
float t = ClampZeroToOne(remTime / x8_interval); float t = ClampZeroToOne(remTime / x8_interval.GetSeconds());
const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4; const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4;
const u32 rotFloatsPerFrame = x40_data.xc_rotPerFrame * 4; const u32 rotFloatsPerFrame = x40_data.xc_rotPerFrame * 4;

View File

@ -298,7 +298,7 @@ SAdvancementResults CAnimSourceReader::VGetAdvancementResults(const CCharAnimTim
void CAnimSourceReader::VSetPhase(float phase) void CAnimSourceReader::VSetPhase(float phase)
{ {
xc_curTime = phase * x54_source->GetDuration(); xc_curTime = phase * x54_source->GetDuration().GetSeconds();
if (x54_source->GetPOIData()) if (x54_source->GetPOIData())
{ {
UpdatePOIStates(); UpdatePOIStates();

View File

@ -53,7 +53,7 @@ CCharAnimTime CAnimTreeSequence::VGetTimeRemaining() const
{ {
if (x38_curIdx == x28_.size() - 1) if (x38_curIdx == x28_.size() - 1)
return x14_child->VGetTimeRemaining(); return x14_child->VGetTimeRemaining();
return x3c_fundamentals.GetSteadyStateAnimInfo().GetDuration() - x94_curTime; return x3c_fundamentals.GetSteadyStateAnimInfo().GetDuration() - x94_curTime.GetSeconds();
} }
CSteadyStateAnimInfo CAnimTreeSequence::VGetSteadyStateAnimInfo() const CSteadyStateAnimInfo CAnimTreeSequence::VGetSteadyStateAnimInfo() const

View File

@ -3,13 +3,15 @@
namespace urde namespace urde
{ {
CAnimTreeTimeScale::CAnimTreeTimeScale(const std::weak_ptr<CAnimTreeNode>& node, float scale, const std::string& name) CAnimTreeTimeScale::CAnimTreeTimeScale(const std::weak_ptr<CAnimTreeNode>& node, float scale,
const std::string& name)
: CAnimTreeSingleChild(node, name) : CAnimTreeSingleChild(node, name)
, x18_timeScale(new CConstantAnimationTimeScale(scale)) , x18_timeScale(new CConstantAnimationTimeScale(scale))
{ {
} }
std::string CAnimTreeTimeScale::CreatePrimitiveName(const std::weak_ptr<CAnimTreeNode>&, float, const CCharAnimTime&, float) std::string CAnimTreeTimeScale::CreatePrimitiveName(const std::weak_ptr<CAnimTreeNode>&, float,
const CCharAnimTime&, float)
{ {
return {}; return {};
} }
@ -22,13 +24,16 @@ CCharAnimTime CAnimTreeTimeScale::GetRealLifeTime(const CCharAnimTime& time) con
if (x28_ > CCharAnimTime()) if (x28_ > CCharAnimTime())
{ {
if (tmp < CCharAnimTime(x28_ * x20_)) if (tmp < CCharAnimTime(x28_ * x20_))
return x18_timeScale->VTimeScaleIntegral(x20_, x20_ + tmp); return x18_timeScale->VTimeScaleIntegral(x20_.GetSeconds(),
(x20_ + tmp).GetSeconds());
else else
{ {
CCharAnimTime integral = x18_timeScale->VTimeScaleIntegral(x20_, x28_); CCharAnimTime integral =
x18_timeScale->VTimeScaleIntegral(x20_.GetSeconds(), x28_.GetSeconds());
if (integral > tmp) if (integral > tmp)
return x18_timeScale->VFindUpperLimit(x20_, tmp) * x20_; return x18_timeScale->VFindUpperLimit(x20_.GetSeconds(), tmp.GetSeconds()) *
x20_.GetSeconds();
else else
return integral + (integral * tmp); return integral + (integral * tmp);
} }

View File

@ -71,7 +71,7 @@ void CAnimTreeTransition::SetBlendingWeight(float w)
float CAnimTreeTransition::VGetBlendingWeight() const float CAnimTreeTransition::VGetBlendingWeight() const
{ {
if (x24_.GreaterThanZero()) if (x24_.GreaterThanZero())
return (1.f / x24_) * x2c_; return (1.f / x24_.GetSeconds()) * x2c_.GetSeconds();
return 0.f; return 0.f;
} }
} }

View File

@ -0,0 +1,81 @@
#include "CBodyController.hpp"
#include "World/CActor.hpp"
#include "TCastTo.hpp"
#include "World/CPhysicsActor.hpp"
namespace urde
{
CBodyController::CBodyController(CActor& actor, float f1, EBodyType bodyType)
: x0_actor(actor), x2a4_bodyStateInfo(actor, bodyType),
x2f4_bodyType(bodyType), x2fc_rotRate(f1)
{
x300_28_playDeathAnims = true;
x2a4_bodyStateInfo.x18_bodyController = this;
}
void CBodyController::EnableAnimation(bool e)
{
x0_actor.ModelData()->AnimationData()->EnableAnimation(e);
}
float CBodyController::GetAnimTimeRemaining() const
{
return x0_actor.GetModelData()->GetAnimationData()->GetAnimTimeRemaining("Whole Body");
}
const CPASDatabase& CBodyController::GetPASDatabase() const
{
return x0_actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase();
}
void CBodyController::FaceDirection(const zeus::CVector3f& v0, float dt)
{
if (x300_26_)
return;
zeus::CVector3f noZ = v0;
noZ.z = 0.f;
if (noZ.canBeNormalized())
{
if (TCastToPtr<CPhysicsActor> act = x0_actor)
{
zeus::CQuaternion rot =
zeus::CQuaternion::lookAt(act->GetTransform().basis[1],
noZ.normalized(), zeus::degToRad(dt * x2fc_rotRate));
rot.setImaginary(act->GetTransform().transposeRotate(rot.getImaginary()));
act->RotateInOneFrameOR(rot, dt);
}
}
}
void CBodyController::FaceDirection3D(const zeus::CVector3f& v0, const zeus::CVector3f& v1, float dt)
{
if (x300_26_)
return;
if (v0.canBeNormalized() && v1.canBeNormalized())
{
if (TCastToPtr<CPhysicsActor> act = x0_actor)
{
zeus::CUnitVector3f uv0 = v0;
zeus::CUnitVector3f uv1 = v1;
float dot = uv0.dot(uv1);
if (std::fabs(dot - 1.f) > 0.00001f)
{
if (dot < -0.9999f)
{
zeus::CQuaternion rot =
zeus::CQuaternion::fromAxisAngle(act->GetTransform().basis[2],
zeus::degToRad(dt * x2fc_rotRate));
rot.setImaginary(act->GetTransform().transposeRotate(rot.getImaginary()));
act->RotateInOneFrameOR(rot, dt);
}
else
{
/* TODO: Finish */
}
}
}
}
}
}

View File

@ -4,6 +4,8 @@
#include "RetroTypes.hpp" #include "RetroTypes.hpp"
#include "zeus/CQuaternion.hpp" #include "zeus/CQuaternion.hpp"
#include "CharacterCommon.hpp" #include "CharacterCommon.hpp"
#include "CBodyStateCmdMgr.hpp"
#include "CBodyStateInfo.hpp"
namespace urde namespace urde
{ {
@ -14,26 +16,60 @@ class CFinalInput;
class CPASAnimParmData; class CPASAnimParmData;
class CRandom16; class CRandom16;
class CStateManager; class CStateManager;
class CPASDatabase;
class CBodyController class CBodyController
{ {
CActor& x0_actor;
CBodyStateCmdMgr x4_cmdMgr;
CBodyStateInfo x2a4_bodyStateInfo;
zeus::CQuaternion x2dc_rot;
pas::ELocomotionType x2ec_locomotionType = pas::ELocomotionType::Relaxed;
pas::EFallState x2f0_fallState = pas::EFallState::Zero;
EBodyType x2f4_bodyType;
s32 x2f8_curAnim = -1;
float x2fc_rotRate;
union
{
struct
{
bool x300_24_animationOver : 1;
bool x300_25_ : 1;
bool x300_26_ : 1;
bool x300_27_ : 1;
bool x300_28_playDeathAnims : 1;
};
u32 _dummy = 0;
};
float x304_ = 0.f;
float x308_ = 0.f;
float x30c_ = 0.f;
float x310_ = 0.f;
zeus::CVector3f x314_;
float x320_ = 0.f;
float x324_ = 0.f;
float x328_ = 0.f;
float x32c_ = 0.f;
float x330_restrictedFlyerMoveSpeed = 0.f;
public: public:
CBodyController(CActor&, float, EBodyType); CBodyController(CActor& owner, float f1, EBodyType bodyType);
void GetCurrentStateId() const; void GetCurrentStateId() const;
void GetComandMgr(); CBodyStateCmdMgr& GetCommandMgr() { return x4_cmdMgr; }
void SetDoDeathAnims(bool); const CBodyStateCmdMgr& GetCommandMgr() const { return x4_cmdMgr; }
void SetDoDeathAnims(bool d) { x300_28_playDeathAnims = d; }
bool IsElectrocuting() const; bool IsElectrocuting() const;
bool IsOnFire() const; bool IsOnFire() const;
bool IsFrozen() const; bool IsFrozen() const;
void GetBodyStateInfo() const; const CBodyStateInfo& GetBodyStateInfo() const { return x2a4_bodyStateInfo; }
bool GetIsActive() const; bool GetIsActive() const;
void BodyStateInfo(); void BodyStateInfo();
float GetTurnSpeed() const; float GetTurnSpeed() const;
pas::ELocomotionType GetLocomotionType() const; pas::ELocomotionType GetLocomotionType() const { return x2ec_locomotionType; }
void GetOwner(); CActor& GetOwner() const { return x0_actor; }
bool IsAnimationOver() const; bool IsAnimationOver() const { return x300_24_animationOver; }
void EnableAnimation(bool); void EnableAnimation(bool e);
bool ShouldPlayDeathAnims() const; bool ShouldPlayDeathAnims() const { return x300_28_playDeathAnims; }
void GetCurrentAnimId() const; s32 GetCurrentAnimId() const { return x2f8_curAnim; }
void Activate(CStateManager&); void Activate(CStateManager&);
void GetCurrentAdditiveState(); void GetCurrentAdditiveState();
void SetState(pas::EAnimationState); void SetState(pas::EAnimationState);
@ -47,15 +83,15 @@ public:
void SetAdditiveState(pas::EAnimationState); void SetAdditiveState(pas::EAnimationState);
void SetTurnSpeed(float); void SetTurnSpeed(float);
void SetCurrentAnimation(const CAnimPlaybackParms&, bool, bool); void SetCurrentAnimation(const CAnimPlaybackParms&, bool, bool);
void GetAnimTimeRemaining() const; float GetAnimTimeRemaining() const;
void SetPlaybackRate(float); void SetPlaybackRate(float);
void MultiplyPlaybackRate(float); void MultiplyPlaybackRate(float);
void SetDeltaRotation(const zeus::CQuaternion&); void SetDeltaRotation(const zeus::CQuaternion& q) { x2dc_rot *= q; }
void FaceDirection(const zeus::CVector3f&, float); void FaceDirection(const zeus::CVector3f&, float);
void FaceDirection3D(const zeus::CVector3f&, float); void FaceDirection3D(const zeus::CVector3f&, const zeus::CVector3f&, float);
void HasBodyInfo(CActor&); void HasBodyInfo(CActor&);
void ProcessInput(const CFinalInput&); void ProcessInput(const CFinalInput&);
void GetPASDatabase() const; const CPASDatabase& GetPASDatabase() const;
void PlayBestAnimation(const CPASAnimParmData&, CRandom16&); void PlayBestAnimation(const CPASAnimParmData&, CRandom16&);
void LoopBestAnimation(const CPASAnimParmData&, CRandom16&); void LoopBestAnimation(const CPASAnimParmData&, CRandom16&);
void Freeze(float, float, float); void Freeze(float, float, float);
@ -67,9 +103,9 @@ public:
void DouseElectrocuting(); void DouseElectrocuting();
void UpdateFrozenInfo(float, CStateManager&); void UpdateFrozenInfo(float, CStateManager&);
void GetCurrentAdditiveStateId() const; void GetCurrentAdditiveStateId() const;
EBodyType GetBodyType() const; EBodyType GetBodyType() const { return x2f4_bodyType; }
bool HasBeenFrozen() const; bool HasBeenFrozen() const;
void GetOwner() const; float GetRestrictedFlyerMoveSpeed() const { return x330_restrictedFlyerMoveSpeed; }
}; };
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,128 +1,431 @@
#ifndef CBODYSTATE_HPP #ifndef CBODYSTATE_HPP
#define CBODYSTATE_HPP #define CBODYSTATE_HPP
#include "RetroTypes.hpp" #include "RetroTypes.hpp"
#include "CharacterCommon.hpp" #include "CharacterCommon.hpp"
#include "CBodyStateCmdMgr.hpp"
namespace urde namespace urde
{ {
class CBodyController; class CBodyController;
class CStateManager; class CStateManager;
class CActor;
class CBodyState class CBodyState
{ {
public: public:
virtual bool IsInAir(const CBodyController&) const { return false; } virtual bool IsInAir(const CBodyController&) const { return false; }
virtual bool IsDead() const { return false; } virtual bool IsDead() const { return false; }
virtual bool IsDying() const { return false; }
virtual bool IsMoving() const { return false; } virtual bool IsMoving() const { return false; }
virtual bool ApplyGravity() const { return true; } virtual bool ApplyGravity() const { return true; }
virtual bool ApplyHeadTracking() const { return true; } virtual bool ApplyHeadTracking() const { return true; }
virtual bool ApplyAnimationDeltas() const { return true; } virtual bool ApplyAnimationDeltas() const { return true; }
virtual bool CanShoot() const { return false; } virtual bool CanShoot() const { return false; }
virtual void Start(CBodyController&, CStateManager&) = 0; virtual void Start(CBodyController&, CStateManager&) = 0;
virtual void UpdateBody(float, CBodyController&, CStateManager&) = 0; virtual pas::EAnimationState UpdateBody(float, CBodyController&, CStateManager&) = 0;
virtual void Shutdown(CBodyController&)=0; virtual void Shutdown(CBodyController&)=0;
}; };
class CBSAttack : public CBodyState class CBSAttack : public CBodyState
{ {
pas::EAnimationState x4_nextState = pas::EAnimationState::Invalid;
CBCSlideCmd x8_slide;
zeus::CVector3f x20_targetPos;
float x2c_alignTargetPosStartTime = -1.f;
float x30_alignTargetPosTime = -1.f;
float x34_curTime = 0.f;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
void UpdatePhysicsActor(CBodyController& bc, float dt);
public: public:
virtual bool CanShoot() const { return false; } bool CanShoot() const { return false; }
virtual void Start(CBodyController &, CStateManager &) {} void Start(CBodyController& bc, CStateManager & mgr);
virtual void UpdateBody(float, CBodyController &, CStateManager&); pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
virtual void Shutdown(CBodyController&) {} void Shutdown(CBodyController&) {}
};
class CBSProjectileAttack : public CBodyState
{
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public:
bool CanShoot() const { return true; }
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
}; };
class CBSDie : public CBodyState class CBSDie : public CBodyState
{ {
float x4_remTime = 0.f;
bool x8_isDead = false; bool x8_isDead = false;
public: public:
bool IsDead() const { return x8_isDead; } bool IsDead() const { return x8_isDead; }
void Start(CBodyController &, CStateManager &) {} bool IsDying() const { return true; }
void UpdateBody(float, CBodyController &, CStateManager&) {} void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {} void Shutdown(CBodyController&) {}
}; };
class CBSFall : public CBodyState class CBSFall : public CBodyState
{ {
float x4_rotateSpeed = 0.f;
float x8_remTime = 0.f;
pas::EFallState xc_fallState = pas::EFallState::Invalid;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public: public:
void Start(CBodyController &, CStateManager &) {} void Start(CBodyController& bc, CStateManager& mgr);
void UpdateBody(float, CBodyController &, CStateManager&) {} pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController &) {} void Shutdown(CBodyController& bc);
}; };
class CBSGetup : public CBodyState class CBSGetup : public CBodyState
{ {
pas::EFallState x4_fallState = pas::EFallState::Invalid;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public: public:
void Start(CBodyController &, CStateManager &) {} void Start(CBodyController& bc, CStateManager& mgr);
void UpdateBody(float, CBodyController &, CStateManager&) {} pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController &) {} void Shutdown(CBodyController& bc);
}; };
class CBSKnockBack : public CBodyState class CBSKnockBack : public CBodyState
{ {
float x4_curTime = 0.f;
float x8_rotateSpeed = 0.f;
float xc_remTime = 0.f;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public: public:
bool IsMoving() const { return true; } bool IsMoving() const { return true; }
void Start(CBodyController &, CStateManager &) {} void Start(CBodyController& bc, CStateManager& mgr);
void UpdateBody(float, CBodyController &, CStateManager&) {} pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {} void Shutdown(CBodyController&) {}
}; };
class CBSLieOnGround : public CBodyState class CBSLieOnGround : public CBodyState
{ {
bool x4_24_hasGroundHit : 1;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public: public:
void Start(CBodyController &, CStateManager &) {} CBSLieOnGround(CActor& actor);
void UpdateBody(float, CBodyController &, CStateManager&) {} void Start(CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController &) {} pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController& bc);
}; };
class CBSStep : public CBodyState class CBSStep : public CBodyState
{ {
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public: public:
bool IsMoving() const { return true; } bool IsMoving() const { return true; }
bool CanShoot() const { return true; } bool CanShoot() const { return true; }
void Start(CBodyController &, CStateManager &) {} void Start(CBodyController& bc, CStateManager& mgr);
void UpdateBody(float, CBodyController &, CStateManager&) {} pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {} void Shutdown(CBodyController&) {}
}; };
class CBSTurn : public CBodyState class CBSTurn : public CBodyState
{ {
protected:
float x4_rotateSpeed = 0.f;
zeus::CVector2f x8_dest;
pas::ETurnDirection x10_turnDir = pas::ETurnDirection::Invalid;
bool FacingDest(CBodyController& bc) const;
public: public:
virtual bool CanShoot() const { return true; } bool CanShoot() const { return true; }
virtual void Start(CBodyController &, CStateManager &) {} void Start(CBodyController& bc, CStateManager& mgr);
virtual void UpdateBody(float, CBodyController &, CStateManager&) {} pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
virtual void Shutdown(CBodyController &) {} void Shutdown(CBodyController&) {}
virtual void GetBodyStateTransition(float, CBodyController&); virtual pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
}; };
class CBSFlyerTurn : public CBSTurn class CBSFlyerTurn : public CBSTurn
{ {
public: public:
virtual void Start(CBodyController &, CStateManager &) {} void Start(CBodyController& bc, CStateManager& mgr);
virtual void UpdateBody(float, CBodyController &, CStateManager&) {} pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
}; };
class CBSLoopAttack : public CBodyState class CBSLoopAttack : public CBodyState
{ {
pas::ELoopState x4_state = pas::ELoopState::Invalid;
pas::ELoopAttackType x8_loopAttackType = pas::ELoopAttackType::Invalid;
bool xc_24_waitForAnimOver : 1;
bool xc_25_advance : 1;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public: public:
virtual bool CanShoot() const { return true; } CBSLoopAttack() { xc_24_waitForAnimOver = false; xc_25_advance = false; }
virtual void Start(CBodyController &, CStateManager &) {} bool CanShoot() const { return true; }
virtual void UpdateBody(float, CBodyController &, CStateManager&); void Start(CBodyController& bc, CStateManager& mgr);
virtual void Shutdown(CBodyController&) {} pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
};
class CBSLoopReaction : public CBodyState
{
pas::ELoopState x4_state = pas::ELoopState::Invalid;
pas::EReactionType x8_reactionType = pas::EReactionType::Invalid;
bool xc_24_loopHit : 1;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
bool PlayExitAnimation(CBodyController& bc, CStateManager& mgr) const;
public:
CBSLoopReaction() { xc_24_loopHit = false; }
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
};
class CBSGroundHit : public CBodyState
{
float x4_rotateSpeed = 0.f;
float x8_remTime = 0.f;
pas::EFallState xc_fallState = pas::EFallState::Invalid;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public:
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController& bc);
};
class CBSGenerate : public CBodyState
{
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public:
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
};
class CBSJump : public CBodyState
{
pas::EJumpState x4_state = pas::EJumpState::Invalid;
pas::EJumpType x8_jumpType;
zeus::CVector3f xc_waypoint1;
zeus::CVector3f x18_velocity;
zeus::CVector3f x24_waypoint2;
union
{
struct
{
bool x30_24_bodyForceSet : 1;
bool x30_25_wallJump : 1;
bool x30_26_wallBounceRight : 1;
bool x30_27_wallBounceComplete : 1;
bool x30_28_startInJumpLoop : 1;
};
u32 _dummy = 0;
};
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
bool CheckForWallJump(CBodyController& bc, CStateManager& mgr);
void CheckForLand(CBodyController& bc, CStateManager& mgr);
void PlayJumpLoop(CStateManager& mgr, CBodyController& bc);
public:
bool IsMoving() const { return true; }
bool ApplyHeadTracking() const { return false; }
bool CanShoot() const;
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
bool ApplyAnimationDeltas() const;
bool IsInAir(const CBodyController& bc) const;
void Shutdown(CBodyController&) {}
};
class CBSHurled : public CBodyState
{
pas::EHurledState x4_state = pas::EHurledState::Invalid;
float x8_knockAngle = 0.f;
int xc_animSeries = -1;
float x10_rotateSpeed = 0.f;
float x14_remTime = 0.f;
float x18_curTime = 0.f;
mutable zeus::CVector3f x1c_lastTranslation;
mutable float x28_landedDur = 0.f;
bool x2c_24_needsRecover : 1;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
void Recover(CStateManager& mgr, CBodyController& bc, pas::EHurledState state);
void PlayStrikeWallAnimation(CBodyController& bc, CStateManager& mgr);
void PlayLandAnimation(CBodyController& bc, CStateManager& mgr);
bool ShouldStartStrikeWall(CBodyController& bc) const;
bool ShouldStartLand(float dt, CBodyController& bc) const;
public:
CBSHurled() { x2c_24_needsRecover = false; }
bool IsMoving() const { return true; }
bool IsInAir(const CBodyController&) const { return true; }
bool ApplyHeadTracking() const { return false; }
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
};
class CBSSlide : public CBodyState
{
float x4_rotateSpeed = 0.f;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public:
bool ApplyHeadTracking() const { return false; }
bool IsMoving() const { return true; }
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
};
class CBSTaunt : public CBodyState
{
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public:
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
};
class CBSScripted : public CBodyState
{
union
{
struct
{
bool x4_24_loopAnim : 1;
bool x4_25_timedLoop : 1;
};
u32 _dummy = 0;
};
float x8_remTime = 0.f;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public:
bool ApplyHeadTracking() const { return false; }
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
};
class CBSCover : public CBodyState
{
pas::ECoverState x4_state = pas::ECoverState::Invalid;
pas::ECoverDirection x8_coverDirection = pas::ECoverDirection::Invalid;
bool xc_needsExit = false;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public:
bool ApplyHeadTracking() const { return false; }
bool IsMoving() const { return true; }
bool CanShoot() const { return x4_state == pas::ECoverState::Lean; }
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
};
class CBSWallHang : public CBodyState
{
pas::EWallHangState x4_state = pas::EWallHangState::Invalid;
TUniqueId x8_wpId = kInvalidUniqueId;
zeus::CVector3f xc_launchVel;
union
{
struct
{
bool x18_24_launched : 1;
bool x18_25_needsExit : 1;
};
u32 _dummy = 0;
};
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
void FixInPlace(CBodyController& bc);
bool CheckForLand(CBodyController& bc, CStateManager& mgr);
bool CheckForWall(CBodyController& bc, CStateManager& mgr);
void SetLaunchVelocity(CBodyController& bc);
public:
bool IsMoving() const { return true; }
bool CanShoot() const { return x4_state == pas::EWallHangState::WallHang; }
bool IsInAir(const CBodyController& bc) const;
bool ApplyGravity() const;
bool ApplyHeadTracking() const;
bool ApplyAnimationDeltas() const;
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
}; };
class CBSLocomotion : public CBodyState class CBSLocomotion : public CBodyState
{ {
protected:
pas::ELocomotionType x4_locomotionType = pas::ELocomotionType::Invalid;
float GetStartVelocityMagnitude(CBodyController& bc);
void ReStartBodyState(CBodyController& bc, bool);
float ComputeWeightPercentage(const std::pair<s32, float>& a,
const std::pair<s32, float>& b, float f) const;
public: public:
virtual bool IsMoving() const = 0; bool IsMoving() const = 0;
virtual bool CanShoot() const { return true; } bool CanShoot() const { return true; }
virtual void Start(CBodyController &, CStateManager &) {} void Start(CBodyController& bc, CStateManager& mgr);
virtual void UpdateBody(float, CBodyController &, CStateManager&) {} pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
virtual void Shutdown() const {} void Shutdown(CBodyController& bc);
virtual bool IsPitchable() const { return true; } virtual bool IsPitchable() const { return false; }
virtual float GetLocomotionSpeed(pas::ELocomotionType, pas::ELocomotionAnim) = 0; virtual float GetLocomotionSpeed(pas::ELocomotionType type, pas::ELocomotionAnim anim) const = 0;
virtual void ApplyLocomotionPysics(float, CBodyController&) {} virtual float ApplyLocomotionPhysics(float dt, CBodyController& bc);
virtual void UpdateLocomotionAnimation(float, const CBodyController& )=0; virtual float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init) = 0;
virtual void GetBodyStateTransition(float, CBodyState&) {} virtual pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
};
class CBSBiPedLocomotion : public CBSLocomotion
{
protected:
rstl::reserved_vector<rstl::reserved_vector<std::pair<s32, float>, 8>, 14> x8_anims;
pas::ELocomotionAnim x3c4_anim = pas::ELocomotionAnim::Invalid;
float x3c8_primeTime;
float UpdateRun(float vel, CBodyController& bc, pas::ELocomotionAnim anim);
float UpdateWalk(float vel, CBodyController& bc, pas::ELocomotionAnim anim);
float UpdateStrafe(float vel, CBodyController& bc, pas::ELocomotionAnim anim);
const std::pair<s32, float>&
GetLocoAnimation(pas::ELocomotionType type, pas::ELocomotionAnim anim) const
{ return x8_anims[int(type)][int(anim)]; }
public:
CBSBiPedLocomotion(CActor& actor);
bool IsMoving() const { return x3c4_anim != pas::ELocomotionAnim::Idle; }
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
float GetLocomotionSpeed(pas::ELocomotionType type, pas::ELocomotionAnim anim) const;
float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init);
virtual bool IsStrafing(const CBodyController& bc) const;
};
class CBSFlyerLocomotion : public CBSBiPedLocomotion
{
bool x3cc_pitchable;
public:
CBSFlyerLocomotion(CActor& actor, bool pitchable);
bool IsPitchable() const { return x3cc_pitchable; }
float ApplyLocomotionPhysics(float dt, CBodyController& bc);
virtual bool IsBackPedal(CBodyController& bc) const { return false; }
};
class CBSWallWalkerLocomotion : public CBSBiPedLocomotion
{
public:
CBSWallWalkerLocomotion(CActor& actor);
float ApplyLocomotionPhysics(float dt, CBodyController& bc);
};
class CBSNewFlyerLocomotion : public CBSBiPedLocomotion
{
public:
CBSNewFlyerLocomotion(CActor& actor);
float ApplyLocomotionPhysics(float dt, CBodyController& bc);
float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init);
};
class CBSRestrictedLocomotion : public CBSLocomotion
{
rstl::reserved_vector<s32, 14> x8_anims;
pas::ELocomotionAnim x44_anim = pas::ELocomotionAnim::Invalid;
public:
CBSRestrictedLocomotion(CActor& actor);
bool IsMoving() const { return false; }
float GetLocomotionSpeed(pas::ELocomotionType type, pas::ELocomotionAnim anim) const { return 0.f; }
float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init);
};
class CBSRestrictedFlyerLocomotion : public CBSRestrictedLocomotion
{
public:
CBSRestrictedFlyerLocomotion(CActor& actor);
float ApplyLocomotionPhysics(float dt, CBodyController& bc);
}; };
} }
#endif // CBODYSTATE_HPP #endif // CBODYSTATE_HPP

View File

@ -35,4 +35,63 @@ CBodyStateCmdMgr::CBodyStateCmdMgr()
x40_commandTable.push_back(&x298_); x40_commandTable.push_back(&x298_);
} }
void CBodyStateCmdMgr::DeliverCmd(const CBCLocomotionCmd& cmd)
{
if (cmd.GetWeight() <= FLT_EPSILON)
return;
x3c_steeringSpeed += cmd.GetWeight();
x0_move += cmd.GetMoveVector() * cmd.GetWeight();
xc_face += cmd.GetFaceVector() * cmd.GetWeight();
}
void CBodyStateCmdMgr::BlendSteeringCmds()
{
if (x3c_steeringSpeed > FLT_EPSILON)
{
float stepMul = 1.f / x3c_steeringSpeed;
xc_face *= stepMul;
switch (x30_steeringMode)
{
case ESteeringBlendMode::Normal:
x0_move *= stepMul;
break;
case ESteeringBlendMode::FullSpeed:
if (!zeus::close_enough(x0_move, zeus::CVector3f::skZero, 0.0001f))
{
x0_move.normalize();
x0_move *= x38_steeringSpeedMax;
}
break;
case ESteeringBlendMode::Clamped:
x0_move *= stepMul;
if (!zeus::close_enough(x0_move, zeus::CVector3f::skZero, 0.0001f))
{
if (x0_move.magnitude() < x34_steeringSpeedMin)
x0_move = x0_move.normalized() * x34_steeringSpeedMin;
else if (x0_move.magnitude() > x38_steeringSpeedMax)
x0_move = x0_move.normalized() * x38_steeringSpeedMax;
}
break;
default: break;
}
}
}
void CBodyStateCmdMgr::Reset()
{
x0_move = zeus::CVector3f::skZero;
xc_face = zeus::CVector3f::skZero;
x18_target = zeus::CVector3f::skZero;
x3c_steeringSpeed = 0.f;
xb4_deliveredCmdMask = 0;
}
void CBodyStateCmdMgr::ClearLocomotionCmds()
{
x0_move = zeus::CVector3f::skZero;
xc_face = zeus::CVector3f::skZero;
x3c_steeringSpeed = 0.f;
}
} }

View File

@ -20,23 +20,29 @@ public:
class CBCMeleeAttackCmd : public CBodyStateCmd class CBCMeleeAttackCmd : public CBodyStateCmd
{ {
pas::ESeverity x8_severity = pas::ESeverity::Invalid; pas::ESeverity x8_severity = pas::ESeverity::Invalid;
zeus::CVector3f xc_; zeus::CVector3f xc_targetPos;
bool x18_ = false; bool x18_hasTargetPos = false;
public: public:
CBCMeleeAttackCmd() : CBodyStateCmd(EBodyStateCmd::MeleeAttack) {} CBCMeleeAttackCmd() : CBodyStateCmd(EBodyStateCmd::MeleeAttack) {}
CBCMeleeAttackCmd(pas::ESeverity severity) CBCMeleeAttackCmd(pas::ESeverity severity)
: CBodyStateCmd(EBodyStateCmd::MeleeAttack), x8_severity(severity) {} : CBodyStateCmd(EBodyStateCmd::MeleeAttack), x8_severity(severity) {}
pas::ESeverity GetAttackSeverity() const { return x8_severity; }
bool HasAttackTargetPos() const { return x18_hasTargetPos; }
const zeus::CVector3f& GetAttackTargetPos() const { return xc_targetPos; }
}; };
class CBCProjectileAttackCmd : public CBodyStateCmd class CBCProjectileAttackCmd : public CBodyStateCmd
{ {
pas::ESeverity x8_severity = pas::ESeverity::Invalid; pas::ESeverity x8_severity = pas::ESeverity::Invalid;
zeus::CVector3f xc_; zeus::CVector3f xc_target;
bool x18_ = false; bool x18_blendAnims = false;
public: public:
CBCProjectileAttackCmd() : CBodyStateCmd(EBodyStateCmd::ProjectileAttack) {} CBCProjectileAttackCmd() : CBodyStateCmd(EBodyStateCmd::ProjectileAttack) {}
CBCProjectileAttackCmd(pas::ESeverity severity, const zeus::CVector3f& vec, bool b) CBCProjectileAttackCmd(pas::ESeverity severity, const zeus::CVector3f& vec, bool b)
: CBodyStateCmd(EBodyStateCmd::ProjectileAttack), x8_severity(severity), xc_(vec), x18_(b) {} : CBodyStateCmd(EBodyStateCmd::ProjectileAttack), x8_severity(severity), xc_target(vec), x18_blendAnims(b) {}
pas::ESeverity GetAttackSeverity() const { return x8_severity; }
const zeus::CVector3f& GetTargetPosition() const { return xc_target; }
bool BlendTwoClosest() const { return x18_blendAnims; }
}; };
class CBCStepCmd : public CBodyStateCmd class CBCStepCmd : public CBodyStateCmd
@ -47,52 +53,80 @@ public:
CBCStepCmd() : CBodyStateCmd(EBodyStateCmd::Step) {} CBCStepCmd() : CBodyStateCmd(EBodyStateCmd::Step) {}
CBCStepCmd(pas::EStepDirection dir, pas::EStepType type) CBCStepCmd(pas::EStepDirection dir, pas::EStepType type)
: CBodyStateCmd(EBodyStateCmd::Step), x8_dir(dir), xc_type(type) {} : CBodyStateCmd(EBodyStateCmd::Step), x8_dir(dir), xc_type(type) {}
pas::EStepDirection GetStepDirection() const { return x8_dir; }
pas::EStepType GetStepType() const { return xc_type; }
}; };
class CBCJumpCmd : public CBodyStateCmd class CBCJumpCmd : public CBodyStateCmd
{ {
pas::EJumpType x8_type = pas::EJumpType::Zero; pas::EJumpType x8_type = pas::EJumpType::Normal;
zeus::CVector3f xc_; zeus::CVector3f xc_waypoint1;
zeus::CVector3f x18_; zeus::CVector3f x18_waypoint2;
bool x24_24_ : 1; bool x24_24_wallJump : 1;
bool x24_25_ : 1; bool x24_25_startInJumpLoop : 1;
public: public:
CBCJumpCmd() CBCJumpCmd()
: CBodyStateCmd(EBodyStateCmd::Jump) { x24_24_ = false; x24_25_ = false; } : CBodyStateCmd(EBodyStateCmd::Jump) { x24_24_wallJump = false; x24_25_startInJumpLoop = false; }
CBCJumpCmd(const zeus::CVector3f& vec, pas::EJumpType type) CBCJumpCmd(const zeus::CVector3f& wp1, pas::EJumpType type, bool startInLoop = false)
: CBodyStateCmd(EBodyStateCmd::Jump), x8_type(type), xc_(vec) { x24_24_ = false; x24_25_ = false; } : CBodyStateCmd(EBodyStateCmd::Jump), x8_type(type), xc_waypoint1(wp1)
{ x24_24_wallJump = false; x24_25_startInJumpLoop = startInLoop; }
CBCJumpCmd(const zeus::CVector3f& wp1, const zeus::CVector3f& wp2, pas::EJumpType type)
: CBodyStateCmd(EBodyStateCmd::Jump), x8_type(type), xc_waypoint1(wp1), x18_waypoint2(wp2)
{ x24_24_wallJump = true; x24_25_startInJumpLoop = false; }
pas::EJumpType GetJumpType() const { return x8_type; }
const zeus::CVector3f& GetJumpTarget() const { return xc_waypoint1; }
const zeus::CVector3f& GetSecondJumpTarget() const { return x18_waypoint2; }
bool IsWallJump() const { return x24_24_wallJump; }
bool StartInJumpLoop() const { return x24_25_startInJumpLoop; }
}; };
class CBCGenerateCmd : public CBodyStateCmd class CBCGenerateCmd : public CBodyStateCmd
{ {
pas::EGenerateType x8_type = pas::EGenerateType::Invalid; pas::EGenerateType x8_type = pas::EGenerateType::Invalid;
zeus::CVector3f xc_targetPos;
s32 x18_animId = -1;
bool x1c_24_targetTransform : 1;
bool x1c_25_overrideAnim : 1;
public: public:
CBCGenerateCmd() : CBodyStateCmd(EBodyStateCmd::Generate) {} CBCGenerateCmd() : CBodyStateCmd(EBodyStateCmd::Generate) { x1c_24_targetTransform = false; x1c_25_overrideAnim = false; }
CBCGenerateCmd(pas::EGenerateType type, int i) CBCGenerateCmd(pas::EGenerateType type, int i)
: CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type) {} : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type) { 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) {} : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type) { x1c_24_targetTransform = false; x1c_25_overrideAnim = false; }
pas::EGenerateType GetGenerateType() const { return x8_type; }
const zeus::CVector3f& GetExitTargetPos() const { return xc_targetPos; }
bool HasExitTargetPos() const { return x1c_24_targetTransform; }
s32 GetSpecialAnimId() const { return x18_animId; }
bool UseSpecialAnimId() const { return x1c_25_overrideAnim; }
}; };
class CBCKnockBackCmd : public CBodyStateCmd class CBCKnockBackCmd : public CBodyStateCmd
{ {
zeus::CVector3f x8_; zeus::CVector3f x8_dir;
pas::ESeverity x14_severity = pas::ESeverity::Invalid; pas::ESeverity x14_severity = pas::ESeverity::Invalid;
public: public:
CBCKnockBackCmd() : CBodyStateCmd(EBodyStateCmd::KnockBack) {} CBCKnockBackCmd() : CBodyStateCmd(EBodyStateCmd::KnockBack) {}
CBCKnockBackCmd(const zeus::CVector3f& vec, pas::ESeverity severity) CBCKnockBackCmd(const zeus::CVector3f& vec, pas::ESeverity severity)
: CBodyStateCmd(EBodyStateCmd::KnockBack), x8_(vec), x14_severity(severity) {} : CBodyStateCmd(EBodyStateCmd::KnockBack), x8_dir(vec), x14_severity(severity) {}
const zeus::CVector3f& GetHitDirection() const { return x8_dir; }
pas::ESeverity GetHitSeverity() const { return x14_severity; }
}; };
class CBCHurledCmd : public CBodyStateCmd class CBCHurledCmd : public CBodyStateCmd
{ {
zeus::CVector3f x8_v0; zeus::CVector3f x8_direction;
zeus::CVector3f x14_v1; zeus::CVector3f x14_launchVel;
bool x20_ = false; bool x20_startInKnockLoop = false;
public: public:
CBCHurledCmd() : CBodyStateCmd(EBodyStateCmd::Hurled) {} CBCHurledCmd() : CBodyStateCmd(EBodyStateCmd::Hurled) {}
CBCHurledCmd(const zeus::CVector3f& v0, const zeus::CVector3f& v1) CBCHurledCmd(const zeus::CVector3f& dir, const zeus::CVector3f& launchVel,
: CBodyStateCmd(EBodyStateCmd::Hurled), x8_v0(v0), x14_v1(v1) {} bool startInLoop = false)
: CBodyStateCmd(EBodyStateCmd::Hurled), x8_direction(dir), x14_launchVel(launchVel),
x20_startInKnockLoop(startInLoop) {}
const zeus::CVector3f& GetHitDirection() const { return x8_direction; }
const zeus::CVector3f& GetLaunchVelocity() const { return x14_launchVel; }
bool GetSkipLaunchState() const { return x20_startInKnockLoop; }
void SetSkipLaunchState(bool s) { x20_startInKnockLoop = s; }
}; };
class CBCGetupCmd : public CBodyStateCmd class CBCGetupCmd : public CBodyStateCmd
@ -102,6 +136,7 @@ public:
CBCGetupCmd() : CBodyStateCmd(EBodyStateCmd::Getup) {} CBCGetupCmd() : CBodyStateCmd(EBodyStateCmd::Getup) {}
CBCGetupCmd(pas::EGetupType type) CBCGetupCmd(pas::EGetupType type)
: CBodyStateCmd(EBodyStateCmd::Getup), x8_type(type) {} : CBodyStateCmd(EBodyStateCmd::Getup), x8_type(type) {}
pas::EGetupType GetGetupType() const { return x8_type; }
}; };
class CBCLoopReactionCmd : public CBodyStateCmd class CBCLoopReactionCmd : public CBodyStateCmd
@ -111,6 +146,7 @@ public:
CBCLoopReactionCmd() : CBodyStateCmd(EBodyStateCmd::LoopReaction) {} CBCLoopReactionCmd() : CBodyStateCmd(EBodyStateCmd::LoopReaction) {}
CBCLoopReactionCmd(pas::EReactionType type) CBCLoopReactionCmd(pas::EReactionType type)
: CBodyStateCmd(EBodyStateCmd::LoopReaction), x8_type(type) {} : CBodyStateCmd(EBodyStateCmd::LoopReaction), x8_type(type) {}
pas::EReactionType GetReactionType() const { return x8_type; }
}; };
class CBCLoopHitReactionCmd : public CBodyStateCmd class CBCLoopHitReactionCmd : public CBodyStateCmd
@ -120,58 +156,73 @@ public:
CBCLoopHitReactionCmd() : CBodyStateCmd(EBodyStateCmd::LoopHitReaction) {} CBCLoopHitReactionCmd() : CBodyStateCmd(EBodyStateCmd::LoopHitReaction) {}
CBCLoopHitReactionCmd(pas::EReactionType type) CBCLoopHitReactionCmd(pas::EReactionType type)
: CBodyStateCmd(EBodyStateCmd::LoopHitReaction), x8_type(type) {} : CBodyStateCmd(EBodyStateCmd::LoopHitReaction), x8_type(type) {}
pas::EReactionType GetReactionType() const { return x8_type; }
}; };
class CBCKnockDownCmd : public CBodyStateCmd class CBCKnockDownCmd : public CBodyStateCmd
{ {
zeus::CVector3f x8_; zeus::CVector3f x8_dir;
pas::ESeverity x14_severity = pas::ESeverity::Invalid; pas::ESeverity x14_severity = pas::ESeverity::Invalid;
public: public:
CBCKnockDownCmd() : CBodyStateCmd(EBodyStateCmd::KnockDown) {} CBCKnockDownCmd() : CBodyStateCmd(EBodyStateCmd::KnockDown) {}
CBCKnockDownCmd(const zeus::CVector3f& vec, pas::ESeverity severity) CBCKnockDownCmd(const zeus::CVector3f& vec, pas::ESeverity severity)
: CBodyStateCmd(EBodyStateCmd::KnockDown), x8_(vec), x14_severity(severity) {} : CBodyStateCmd(EBodyStateCmd::KnockDown), x8_dir(vec), x14_severity(severity) {}
const zeus::CVector3f& GetHitDirection() const { return x8_dir; }
pas::ESeverity GetHitSeverity() const { return x14_severity; }
}; };
class CBCSlideCmd : public CBodyStateCmd class CBCSlideCmd : public CBodyStateCmd
{ {
pas::ESlideType x8_type = pas::ESlideType::Invalid; pas::ESlideType x8_type = pas::ESlideType::Invalid;
zeus::CVector3f xc_; zeus::CVector3f xc_dir;
public: public:
CBCSlideCmd() : CBodyStateCmd(EBodyStateCmd::Slide) {} CBCSlideCmd() : CBodyStateCmd(EBodyStateCmd::Slide) {}
CBCSlideCmd(pas::ESlideType type, const zeus::CVector3f& vec) CBCSlideCmd(pas::ESlideType type, const zeus::CVector3f& dir)
: CBodyStateCmd(EBodyStateCmd::Slide), x8_type(type), xc_(vec) {} : CBodyStateCmd(EBodyStateCmd::Slide), x8_type(type), xc_dir(dir) {}
pas::ESlideType GetSlideType() const { return x8_type; }
const zeus::CVector3f& GetSlideDirection() const { return xc_dir; }
}; };
class CBCScriptedCmd : public CBodyStateCmd class CBCScriptedCmd : public CBodyStateCmd
{ {
int x8_ = -1; s32 x8_anim = -1;
bool xc_24_ : 1; bool xc_24_loopAnim : 1;
bool xc_25_ : 1; bool xc_25_timedLoop : 1;
float x10_ = 0.f; float x10_loopDur = 0.f;
public: public:
CBCScriptedCmd() : CBodyStateCmd(EBodyStateCmd::Scripted) { xc_24_ = false; xc_25_ = false; } CBCScriptedCmd() : CBodyStateCmd(EBodyStateCmd::Scripted)
CBCScriptedCmd(int i, bool b1, bool b2, float f) : CBodyStateCmd(EBodyStateCmd::Scripted), { xc_24_loopAnim = false; xc_25_timedLoop = false; }
x8_(i), x10_(f) { xc_24_ = b1; xc_25_ = b2; } CBCScriptedCmd(int i, bool b1, bool b2, float f)
: CBodyStateCmd(EBodyStateCmd::Scripted),
x8_anim(i), x10_loopDur(f) { xc_24_loopAnim = b1; xc_25_timedLoop = b2; }
s32 GetAnimId() const { return x8_anim; }
bool IsLooped() const { return xc_24_loopAnim; }
bool GetUseLoopDuration() const { return xc_25_timedLoop; }
float GetLoopDuration() const { return x10_loopDur; }
}; };
class CBCCoverCmd : public CBodyStateCmd class CBCCoverCmd : public CBodyStateCmd
{ {
pas::ECoverDirection x8_dir = pas::ECoverDirection::Invalid; pas::ECoverDirection x8_dir = pas::ECoverDirection::Invalid;
zeus::CVector3f xc_; zeus::CVector3f xc_targetPos;
zeus::CVector3f x18_; zeus::CVector3f x18_alignDir;
public: public:
CBCCoverCmd() : CBodyStateCmd(EBodyStateCmd::Cover) {} CBCCoverCmd() : CBodyStateCmd(EBodyStateCmd::Cover) {}
CBCCoverCmd(pas::ECoverDirection dir, const zeus::CVector3f& v1, const zeus::CVector3f& v2) : CBCCoverCmd(pas::ECoverDirection dir, const zeus::CVector3f& v1, const zeus::CVector3f& v2) :
CBodyStateCmd(EBodyStateCmd::Cover), x8_dir(dir), xc_(v1), x18_(v2) {} CBodyStateCmd(EBodyStateCmd::Cover), x8_dir(dir), xc_targetPos(v1), x18_alignDir(v2) {}
pas::ECoverDirection GetDirection() const { return x8_dir; }
const zeus::CVector3f& GetTarget() const { return xc_targetPos; }
const zeus::CVector3f& GetAlignDirection() const { return x18_alignDir; }
}; };
class CBCWallHangCmd : public CBodyStateCmd class CBCWallHangCmd : public CBodyStateCmd
{ {
TUniqueId x8_uid = kInvalidUniqueId; TUniqueId x8_wpId = kInvalidUniqueId;
public: public:
CBCWallHangCmd() : CBodyStateCmd(EBodyStateCmd::WallHang) {} CBCWallHangCmd() : CBodyStateCmd(EBodyStateCmd::WallHang) {}
CBCWallHangCmd(TUniqueId uid) : CBCWallHangCmd(TUniqueId uid) :
CBodyStateCmd(EBodyStateCmd::WallHang), x8_uid(uid) {} CBodyStateCmd(EBodyStateCmd::WallHang), x8_wpId(uid) {}
TUniqueId GetTarget() const { return x8_wpId; }
}; };
class CBCAdditiveAimCmd : public CBodyStateCmd class CBCAdditiveAimCmd : public CBodyStateCmd
@ -202,11 +253,13 @@ public:
class CBCLoopAttackCmd : public CBodyStateCmd class CBCLoopAttackCmd : public CBodyStateCmd
{ {
pas::ELoopAttackType x8_type = pas::ELoopAttackType::Invalid; pas::ELoopAttackType x8_type = pas::ELoopAttackType::Invalid;
u32 xc_ = 0; u32 xc_waitForAnimOver = 0;
public: public:
CBCLoopAttackCmd() : CBodyStateCmd(EBodyStateCmd::LoopAttack) {} CBCLoopAttackCmd() : CBodyStateCmd(EBodyStateCmd::LoopAttack) {}
CBCLoopAttackCmd(pas::ELoopAttackType type) CBCLoopAttackCmd(pas::ELoopAttackType type)
: CBodyStateCmd(EBodyStateCmd::LoopAttack), x8_type(type) {} : CBodyStateCmd(EBodyStateCmd::LoopAttack), x8_type(type) {}
pas::ELoopAttackType GetAttackType() const { return x8_type; }
bool WaitForAnimOver() const { return xc_waitForAnimOver == 1; }
}; };
class CBCTauntCmd : public CBodyStateCmd class CBCTauntCmd : public CBodyStateCmd
@ -216,32 +269,44 @@ public:
CBCTauntCmd() : CBodyStateCmd(EBodyStateCmd::Taunt) {} CBCTauntCmd() : CBodyStateCmd(EBodyStateCmd::Taunt) {}
CBCTauntCmd(pas::ETauntType type) CBCTauntCmd(pas::ETauntType type)
: CBodyStateCmd(EBodyStateCmd::Taunt), x8_type(type) {} : CBodyStateCmd(EBodyStateCmd::Taunt), x8_type(type) {}
pas::ETauntType GetTauntType() const { return x8_type; }
}; };
class CBCLocomotionCmd class CBCLocomotionCmd
{ {
zeus::CVector3f x0_move;
zeus::CVector3f xc_face;
float x18_weight;
public: public:
CBCLocomotionCmd(const zeus::CVector3f& v1, const zeus::CVector3f& v2, float f)
: x0_move(v1), xc_face(v2), x18_weight(f) {}
const zeus::CVector3f& GetMoveVector() const { return x0_move; }
const zeus::CVector3f& GetFaceVector() const { return xc_face; }
float GetWeight() const { return x18_weight; }
};
enum class ESteeringBlendMode
{
Normal,
FullSpeed,
Clamped
}; };
class CBodyStateCmdMgr class CBodyStateCmdMgr
{ {
public: zeus::CVector3f x0_move;
enum class ESteeringBlendMode zeus::CVector3f xc_face;
{ zeus::CVector3f x18_target;
}; zeus::CVector3f x24_additiveTarget;
private: ESteeringBlendMode x30_steeringMode = ESteeringBlendMode::Normal;
zeus::CVector3f x0_; float x34_steeringSpeedMin = 0.f;
zeus::CVector3f xc_; float x38_steeringSpeedMax = 1.f;
zeus::CVector3f x18_; float x3c_steeringSpeed = 0.f;
zeus::CVector3f x24_;
u32 x30_ = 0;
float x34_steeringSpeedMin;
float x38_steeringSpeedMax;
rstl::reserved_vector<CBodyStateCmd*, 28> x40_commandTable; rstl::reserved_vector<CBodyStateCmd*, 28> x40_commandTable;
u32 xb4_deliveredCmdMask = 0; u32 xb4_deliveredCmdMask = 0;
CBCGetupCmd xb8_getup; CBCGetupCmd xb8_getup;
CBCStepCmd xc4_step; CBCStepCmd xc4_step;
CBodyStateCmd xd4_ = {EBodyStateCmd::Two}; CBodyStateCmd xd4_ = {EBodyStateCmd::Die};
CBCKnockDownCmd xdc_knockDown; CBCKnockDownCmd xdc_knockDown;
CBCKnockBackCmd xf4_knockBack; CBCKnockBackCmd xf4_knockBack;
CBCMeleeAttackCmd x10c_meleeAttack; CBCMeleeAttackCmd x10c_meleeAttack;
@ -249,9 +314,9 @@ private:
CBCLoopAttackCmd x144_loopAttack; CBCLoopAttackCmd x144_loopAttack;
CBCLoopReactionCmd x154_loopReaction; CBCLoopReactionCmd x154_loopReaction;
CBCLoopHitReactionCmd x160_loopHitReaction; CBCLoopHitReactionCmd x160_loopHitReaction;
CBodyStateCmd x16c_ = {EBodyStateCmd::Ten}; CBodyStateCmd x16c_ = {EBodyStateCmd::ExitState};
CBodyStateCmd x174_ = {EBodyStateCmd::Eleven}; CBodyStateCmd x174_ = {EBodyStateCmd::LeanFromCover};
CBodyStateCmd x17c_ = {EBodyStateCmd::Twelve}; CBodyStateCmd x17c_ = {EBodyStateCmd::NextState};
CBodyStateCmd x184_ = {EBodyStateCmd::Thirteen}; CBodyStateCmd x184_ = {EBodyStateCmd::Thirteen};
CBCGenerateCmd x18c_generate; CBCGenerateCmd x18c_generate;
CBCHurledCmd x1ac_hurled; CBCHurledCmd x1ac_hurled;
@ -261,7 +326,7 @@ private:
CBCScriptedCmd x21c_scripted; CBCScriptedCmd x21c_scripted;
CBCCoverCmd x230_cover; CBCCoverCmd x230_cover;
CBCWallHangCmd x254_wallHang; CBCWallHangCmd x254_wallHang;
CBodyStateCmd x260_ = {EBodyStateCmd::TwentyTwo}; CBodyStateCmd x260_ = {EBodyStateCmd::Locomotion};
CBodyStateCmd x268_ = {EBodyStateCmd::TwentyThree}; CBodyStateCmd x268_ = {EBodyStateCmd::TwentyThree};
CBCAdditiveAimCmd x270_additiveAim; CBCAdditiveAimCmd x270_additiveAim;
CBCAdditiveFlinchCmd x278_additiveFlinch; CBCAdditiveFlinchCmd x278_additiveFlinch;
@ -376,20 +441,25 @@ public:
DeliverCmd(EBodyStateCmd::AdditiveReaction); DeliverCmd(EBodyStateCmd::AdditiveReaction);
} }
void DeliverCmd(const CBCLocomotionCmd& cmd); void DeliverCmd(const CBCLocomotionCmd& cmd);
void DeliverTargetVector(const zeus::CVector3f&); void DeliverTargetVector(const zeus::CVector3f& t) { x18_target = t; }
void DeliverAdditiveTargetVector(const zeus::CVector3f&); void DeliverAdditiveTargetVector(const zeus::CVector3f& t) { x24_additiveTarget = t; }
void SetSteeringBlendSpeed(float); void SetSteeringBlendSpeed(float s) { x3c_steeringSpeed = s; }
void SetSteeringBlendMode(ESteeringBlendMode); void SetSteeringBlendMode(ESteeringBlendMode m) { x30_steeringMode = m; }
void SetSteeringSpeedRange(float, float); void SetSteeringSpeedRange(float rmin, float rmax)
{ x34_steeringSpeedMin = rmin; x38_steeringSpeedMax = rmax; }
void BlendSteeringCmds(); void BlendSteeringCmds();
void Reset(); void Reset();
void ClearLocomtionCmds(); void ClearLocomotionCmds();
void GetCmd(EBodyStateCmd); const CBodyStateCmd* GetCmd(EBodyStateCmd cmd) const
zeus::CVector3f GetTargetVector() const; {
void GetFaceVector() const; if (xb4_deliveredCmdMask & (1 << int(cmd)))
void GetMoveVector() const; return x40_commandTable[int(cmd)];
s32 GetNumSteerCmds() const; return nullptr;
zeus::CVector3f GetAdditiveTargetVector() const; }
const zeus::CVector3f& GetMoveVector() const { return x0_move; }
const zeus::CVector3f& GetFaceVector() const { return xc_face; }
const zeus::CVector3f& GetTargetVector() const { return x18_target; }
const zeus::CVector3f& GetAdditiveTargetVector() const { return x24_additiveTarget; }
}; };
} }

View File

@ -0,0 +1,416 @@
#include "CBodyStateInfo.hpp"
#include "World/CActor.hpp"
#include "CBodyController.hpp"
namespace urde
{
CBodyStateInfo::CBodyStateInfo(CActor& actor, EBodyType type)
{
x34_24_changeLocoAtEndOfAnimOnly = false;
const CPASDatabase& pasDatabase =
actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase();
for (int i=0 ; i<pasDatabase.GetNumAnimStates() ; ++i)
{
const CPASAnimState* state = pasDatabase.GetAnimStateByIndex(i);
std::unique_ptr<CBodyState> bs;
switch (type)
{
case EBodyType::BiPedal:
bs = SetupBiPedalBodyStates(state->GetStateId(), actor);
break;
case EBodyType::Restricted:
default:
bs = SetupRestrictedBodyStates(state->GetStateId(), actor);
break;
case EBodyType::Flyer:
bs = SetupFlyerBodyStates(state->GetStateId(), actor);
break;
case EBodyType::Pitchable:
bs = SetupPitchableBodyStates(state->GetStateId(), actor);
break;
case EBodyType::WallWalker:
bs = SetupWallWalkerBodyStates(state->GetStateId(), actor);
break;
case EBodyType::NewFlyer:
bs = SetupNewFlyerBodyStates(state->GetStateId(), actor);
break;
case EBodyType::RestrictedFlyer:
bs = SetupRestrictedFlyerBodyStates(state->GetStateId(), actor);
break;
}
if (bs)
x0_stateMap[state->GetStateId()] = std::move(bs);
}
x1c_additiveStates.reserve(4);
x1c_additiveStates.push_back({21, std::make_unique<CABSIdle>()});
x1c_additiveStates.push_back({22, std::make_unique<CABSAim>()});
x1c_additiveStates.push_back({23, std::make_unique<CABSFlinch>()});
x1c_additiveStates.push_back({24, std::make_unique<CABSReaction>()});
}
std::unique_ptr<CBodyState> CBodyStateInfo::SetupRestrictedFlyerBodyStates(int stateId, CActor& actor)
{
switch (stateId)
{
case 0:
return std::make_unique<CBSFall>();
case 1:
return std::make_unique<CBSGetup>();
case 2:
return std::make_unique<CBSLieOnGround>(actor);
case 3:
return std::make_unique<CBSStep>();
case 4:
return std::make_unique<CBSDie>();
case 5:
return std::make_unique<CBSRestrictedFlyerLocomotion>(actor);
case 6:
return std::make_unique<CBSKnockBack>();
case 7:
return std::make_unique<CBSAttack>();
case 18:
return std::make_unique<CBSProjectileAttack>();
case 9:
return std::make_unique<CBSLoopAttack>();
case 8:
return std::make_unique<CBSTurn>();
case 10:
return std::make_unique<CBSLoopReaction>();
case 11:
return std::make_unique<CBSGroundHit>();
case 12:
return std::make_unique<CBSGenerate>();
case 13:
return std::make_unique<CBSJump>();
case 14:
return std::make_unique<CBSHurled>();
case 15:
return std::make_unique<CBSSlide>();
case 16:
return std::make_unique<CBSTaunt>();
case 17:
return std::make_unique<CBSScripted>();
default:
return {};
}
}
std::unique_ptr<CBodyState> CBodyStateInfo::SetupNewFlyerBodyStates(int stateId, CActor& actor)
{
switch (stateId)
{
case 0:
return std::make_unique<CBSFall>();
case 1:
return std::make_unique<CBSGetup>();
case 2:
return std::make_unique<CBSLieOnGround>(actor);
case 3:
return std::make_unique<CBSStep>();
case 4:
return std::make_unique<CBSDie>();
case 5:
return std::make_unique<CBSNewFlyerLocomotion>(actor);
case 6:
return std::make_unique<CBSKnockBack>();
case 7:
return std::make_unique<CBSAttack>();
case 18:
return std::make_unique<CBSProjectileAttack>();
case 9:
return std::make_unique<CBSLoopAttack>();
case 8:
return std::make_unique<CBSTurn>();
case 10:
return std::make_unique<CBSLoopReaction>();
case 11:
return std::make_unique<CBSGroundHit>();
case 12:
return std::make_unique<CBSGenerate>();
case 13:
return std::make_unique<CBSJump>();
case 14:
return std::make_unique<CBSHurled>();
case 15:
return std::make_unique<CBSSlide>();
case 16:
return std::make_unique<CBSTaunt>();
case 17:
return std::make_unique<CBSScripted>();
default:
return {};
}
}
std::unique_ptr<CBodyState> CBodyStateInfo::SetupWallWalkerBodyStates(int stateId, CActor& actor)
{
switch (stateId)
{
case 0:
return std::make_unique<CBSFall>();
case 1:
return std::make_unique<CBSGetup>();
case 2:
return std::make_unique<CBSLieOnGround>(actor);
case 3:
return std::make_unique<CBSStep>();
case 4:
return std::make_unique<CBSDie>();
case 5:
return std::make_unique<CBSWallWalkerLocomotion>(actor);
case 6:
return std::make_unique<CBSKnockBack>();
case 7:
return std::make_unique<CBSAttack>();
case 18:
return std::make_unique<CBSProjectileAttack>();
case 9:
return std::make_unique<CBSLoopAttack>();
case 8:
return std::make_unique<CBSFlyerTurn>();
case 10:
return std::make_unique<CBSLoopReaction>();
case 11:
return std::make_unique<CBSGroundHit>();
case 12:
return std::make_unique<CBSGenerate>();
case 13:
return std::make_unique<CBSJump>();
case 14:
return std::make_unique<CBSHurled>();
case 15:
return std::make_unique<CBSSlide>();
case 16:
return std::make_unique<CBSTaunt>();
case 17:
return std::make_unique<CBSScripted>();
default:
return {};
}
}
std::unique_ptr<CBodyState> CBodyStateInfo::SetupPitchableBodyStates(int stateId, CActor& actor)
{
switch (stateId)
{
case 0:
return std::make_unique<CBSFall>();
case 1:
return std::make_unique<CBSGetup>();
case 2:
return std::make_unique<CBSLieOnGround>(actor);
case 3:
return std::make_unique<CBSStep>();
case 4:
return std::make_unique<CBSDie>();
case 5:
return std::make_unique<CBSFlyerLocomotion>(actor, true);
case 6:
return std::make_unique<CBSKnockBack>();
case 7:
return std::make_unique<CBSAttack>();
case 18:
return std::make_unique<CBSProjectileAttack>();
case 9:
return std::make_unique<CBSLoopAttack>();
case 8:
return std::make_unique<CBSFlyerTurn>();
case 10:
return std::make_unique<CBSLoopReaction>();
case 11:
return std::make_unique<CBSGroundHit>();
case 12:
return std::make_unique<CBSGenerate>();
case 13:
return std::make_unique<CBSJump>();
case 14:
return std::make_unique<CBSHurled>();
case 15:
return std::make_unique<CBSSlide>();
case 16:
return std::make_unique<CBSTaunt>();
case 17:
return std::make_unique<CBSScripted>();
default:
return {};
}
}
std::unique_ptr<CBodyState> CBodyStateInfo::SetupFlyerBodyStates(int stateId, CActor& actor)
{
switch (stateId)
{
case 0:
return std::make_unique<CBSFall>();
case 1:
return std::make_unique<CBSGetup>();
case 2:
return std::make_unique<CBSLieOnGround>(actor);
case 3:
return std::make_unique<CBSStep>();
case 4:
return std::make_unique<CBSDie>();
case 5:
return std::make_unique<CBSFlyerLocomotion>(actor, false);
case 6:
return std::make_unique<CBSKnockBack>();
case 7:
return std::make_unique<CBSAttack>();
case 18:
return std::make_unique<CBSProjectileAttack>();
case 9:
return std::make_unique<CBSLoopAttack>();
case 8:
return std::make_unique<CBSFlyerTurn>();
case 10:
return std::make_unique<CBSLoopReaction>();
case 11:
return std::make_unique<CBSGroundHit>();
case 12:
return std::make_unique<CBSGenerate>();
case 13:
return std::make_unique<CBSJump>();
case 14:
return std::make_unique<CBSHurled>();
case 15:
return std::make_unique<CBSSlide>();
case 16:
return std::make_unique<CBSTaunt>();
case 17:
return std::make_unique<CBSScripted>();
default:
return {};
}
}
std::unique_ptr<CBodyState> CBodyStateInfo::SetupRestrictedBodyStates(int stateId, CActor& actor)
{
switch (stateId)
{
case 0:
return std::make_unique<CBSFall>();
case 1:
return std::make_unique<CBSGetup>();
case 2:
return std::make_unique<CBSLieOnGround>(actor);
case 3:
return std::make_unique<CBSStep>();
case 4:
return std::make_unique<CBSDie>();
case 5:
return std::make_unique<CBSRestrictedLocomotion>(actor);
case 6:
return std::make_unique<CBSKnockBack>();
case 7:
return std::make_unique<CBSAttack>();
case 18:
return std::make_unique<CBSProjectileAttack>();
case 9:
return std::make_unique<CBSLoopAttack>();
case 8:
return std::make_unique<CBSTurn>();
case 10:
return std::make_unique<CBSLoopReaction>();
case 11:
return std::make_unique<CBSGroundHit>();
case 12:
return std::make_unique<CBSGenerate>();
case 13:
return std::make_unique<CBSJump>();
case 14:
return std::make_unique<CBSHurled>();
case 15:
return std::make_unique<CBSSlide>();
case 16:
return std::make_unique<CBSTaunt>();
case 17:
return std::make_unique<CBSScripted>();
case 19:
return std::make_unique<CBSCover>();
default:
return {};
}
}
std::unique_ptr<CBodyState> CBodyStateInfo::SetupBiPedalBodyStates(int stateId, CActor& actor)
{
switch (stateId)
{
case 0:
return std::make_unique<CBSFall>();
case 1:
return std::make_unique<CBSGetup>();
case 2:
return std::make_unique<CBSLieOnGround>(actor);
case 3:
return std::make_unique<CBSStep>();
case 4:
return std::make_unique<CBSDie>();
case 5:
return std::make_unique<CBSBiPedLocomotion>(actor);
case 6:
return std::make_unique<CBSKnockBack>();
case 7:
return std::make_unique<CBSAttack>();
case 18:
return std::make_unique<CBSProjectileAttack>();
case 9:
return std::make_unique<CBSLoopAttack>();
case 8:
return std::make_unique<CBSTurn>();
case 10:
return std::make_unique<CBSLoopReaction>();
case 11:
return std::make_unique<CBSGroundHit>();
case 12:
return std::make_unique<CBSGenerate>();
case 13:
return std::make_unique<CBSJump>();
case 14:
return std::make_unique<CBSHurled>();
case 15:
return std::make_unique<CBSSlide>();
case 16:
return std::make_unique<CBSTaunt>();
case 17:
return std::make_unique<CBSScripted>();
case 19:
return std::make_unique<CBSCover>();
case 20:
return std::make_unique<CBSWallHang>();
default:
return {};
}
}
float CBodyStateInfo::GetLocomotionSpeed(pas::ELocomotionAnim anim) const
{
auto search = x0_stateMap.find(5);
if (search != x0_stateMap.cend() && search->second && x18_bodyController)
{
const CBSLocomotion& bs = static_cast<const CBSLocomotion&>(*search->second);
return bs.GetLocomotionSpeed(x18_bodyController->GetLocomotionType(), anim);
}
return 0.f;
}
float CBodyStateInfo::GetMaxSpeed() const
{
float ret = GetLocomotionSpeed(pas::ELocomotionAnim::Run);
if (std::fabs(ret) < 0.00001f)
{
for (int i=0 ; i<8 ; ++i)
{
float tmp = GetLocomotionSpeed(pas::ELocomotionAnim(i));
if (tmp > ret)
ret = tmp;
}
}
return ret;
}
}

View File

@ -0,0 +1,41 @@
#ifndef __URDE_CBODYSTATEINFO_HPP__
#define __URDE_CBODYSTATEINFO_HPP__
#include "RetroTypes.hpp"
#include "CharacterCommon.hpp"
#include "CBodyState.hpp"
#include "CAdditiveBodyState.hpp"
namespace urde
{
class CActor;
class CBodyStateInfo
{
friend class CBodyController;
std::map<int, std::unique_ptr<CBodyState>> x0_stateMap;
int x14_ = -1;
CBodyController* x18_bodyController = nullptr;
std::vector<std::pair<int, std::unique_ptr<CAdditiveBodyState>>> x1c_additiveStates;
u32 x2c_ = 0x15;
float x30_maxPitch = 0.f;
bool x34_24_changeLocoAtEndOfAnimOnly;
std::unique_ptr<CBodyState> SetupRestrictedFlyerBodyStates(int stateId, CActor& actor);
std::unique_ptr<CBodyState> SetupNewFlyerBodyStates(int stateId, CActor& actor);
std::unique_ptr<CBodyState> SetupWallWalkerBodyStates(int stateId, CActor& actor);
std::unique_ptr<CBodyState> SetupPitchableBodyStates(int stateId, CActor& actor);
std::unique_ptr<CBodyState> SetupFlyerBodyStates(int stateId, CActor& actor);
std::unique_ptr<CBodyState> SetupRestrictedBodyStates(int stateId, CActor& actor);
std::unique_ptr<CBodyState> SetupBiPedalBodyStates(int stateId, CActor& actor);
public:
CBodyStateInfo(CActor& actor, EBodyType type);
float GetLocomotionSpeed(pas::ELocomotionAnim anim) const;
float GetMaxSpeed() const;
float GetMaximumPitch() const { return x30_maxPitch; }
bool GetLocoAnimChangeAtEndOfAnimOnly() const { return x34_24_changeLocoAtEndOfAnimOnly; }
void SetLocoAnimChangeAtEndOfAnimOnly(bool s) { x34_24_changeLocoAtEndOfAnimOnly = s; }
};
}
#endif // __URDE_CBODYSTATEINFO_HPP__

View File

@ -80,7 +80,7 @@ bool CCharAnimTime::operator !=(const CCharAnimTime& other) const
return !(*this == other); return !(*this == other);
} }
bool CCharAnimTime::operator>=(const CCharAnimTime& other) bool CCharAnimTime::operator>=(const CCharAnimTime& other) const
{ {
if (*this == other) if (*this == other)
return true; return true;
@ -88,7 +88,7 @@ bool CCharAnimTime::operator>=(const CCharAnimTime& other)
return (*this > other); return (*this > other);
} }
bool CCharAnimTime::operator<=(const CCharAnimTime& other) bool CCharAnimTime::operator<=(const CCharAnimTime& other) const
{ {
if (*this == other) if (*this == other)
return true; return true;
@ -162,7 +162,7 @@ CCharAnimTime& CCharAnimTime::operator+=(const CCharAnimTime& other)
return *this; return *this;
} }
CCharAnimTime CCharAnimTime::operator+(const CCharAnimTime& other) CCharAnimTime CCharAnimTime::operator+(const CCharAnimTime& other) const
{ {
if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) if (x4_type == EType::Infinity && other.x4_type == EType::Infinity)
{ {
@ -216,7 +216,7 @@ CCharAnimTime& CCharAnimTime::operator-=(const CCharAnimTime& other)
return *this; return *this;
} }
CCharAnimTime CCharAnimTime::operator-(const CCharAnimTime& other) CCharAnimTime CCharAnimTime::operator-(const CCharAnimTime& other) const
{ {
if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) if (x4_type == EType::Infinity && other.x4_type == EType::Infinity)
{ {
@ -266,7 +266,7 @@ CCharAnimTime CCharAnimTime::operator-(const CCharAnimTime& other)
return ret; return ret;
} }
CCharAnimTime CCharAnimTime::operator*(const CCharAnimTime& other) CCharAnimTime CCharAnimTime::operator*(const CCharAnimTime& other) const
{ {
if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) if (x4_type == EType::Infinity && other.x4_type == EType::Infinity)
{ {
@ -313,7 +313,7 @@ CCharAnimTime CCharAnimTime::operator*(const CCharAnimTime& other)
return ret; return ret;
} }
CCharAnimTime CCharAnimTime::operator*(const float& other) CCharAnimTime CCharAnimTime::operator*(const float& other) const
{ {
CCharAnimTime ret; CCharAnimTime ret;
if (other == 0.f) if (other == 0.f)
@ -331,7 +331,7 @@ CCharAnimTime CCharAnimTime::operator*(const float& other)
return ret; return ret;
} }
float CCharAnimTime::operator/(const CCharAnimTime& other) float CCharAnimTime::operator/(const CCharAnimTime& other) const
{ {
if (other.EqualsZero()) if (other.EqualsZero())
return 0.f; return 0.f;

View File

@ -36,25 +36,26 @@ public:
} }
static CCharAnimTime Infinity(); static CCharAnimTime Infinity();
operator float() const {return x0_time;} float GetSeconds() const { return x0_time; }
bool EqualsZero() const; bool EqualsZero() const;
bool EpsilonZero() const; bool EpsilonZero() const;
bool GreaterThanZero() const; bool GreaterThanZero() const;
bool operator ==(const CCharAnimTime& other) const; bool operator ==(const CCharAnimTime& other) const;
bool operator !=(const CCharAnimTime& other) const; bool operator !=(const CCharAnimTime& other) const;
bool operator>=(const CCharAnimTime& other); bool operator>=(const CCharAnimTime& other) const;
bool operator<=(const CCharAnimTime& other); bool operator<=(const CCharAnimTime& other) const;
bool operator >(const CCharAnimTime& other) const; bool operator >(const CCharAnimTime& other) const;
bool operator <(const CCharAnimTime& other) const; bool operator <(const CCharAnimTime& other) const;
CCharAnimTime& operator*=(const CCharAnimTime& other); CCharAnimTime& operator*=(const CCharAnimTime& other);
CCharAnimTime& operator+=(const CCharAnimTime& other); CCharAnimTime& operator+=(const CCharAnimTime& other);
CCharAnimTime operator+(const CCharAnimTime& other); CCharAnimTime operator+(const CCharAnimTime& other) const;
CCharAnimTime& operator-=(const CCharAnimTime& other); CCharAnimTime& operator-=(const CCharAnimTime& other);
CCharAnimTime operator-(const CCharAnimTime& other); CCharAnimTime operator-(const CCharAnimTime& other) const;
CCharAnimTime operator*(const CCharAnimTime& other); CCharAnimTime operator*(const CCharAnimTime& other) const;
CCharAnimTime operator*(const float& other); CCharAnimTime operator*(const float& other) const;
float operator/(const CCharAnimTime& other); float operator/(const CCharAnimTime& other) const;
}; };
} }

View File

@ -280,7 +280,7 @@ float CFBStreamedCompression::CalculateAverageVelocity(const u8* chans)
transCompA = transCompB; transCompA = transCompB;
} }
return accumMag / GetAnimationDuration(); return accumMag / GetAnimationDuration().GetSeconds();
} }
} }

View File

@ -85,9 +85,11 @@ set(CHARACTER_SOURCES
CActorLights.hpp CActorLights.cpp CActorLights.hpp CActorLights.cpp
CAnimSysContext.hpp CAnimSysContext.hpp
CBodyState.hpp CBodyState.cpp CBodyState.hpp CBodyState.cpp
CAdditiveBodyState.hpp CAdditiveBodyState.cpp
CBodyStateCmdMgr.hpp CBodyStateCmdMgr.cpp CBodyStateCmdMgr.hpp CBodyStateCmdMgr.cpp
CBodyController.hpp CBodyController.cpp CBodyController.hpp CBodyController.cpp
CGroundMovement.hpp CGroundMovement.cpp CGroundMovement.hpp CGroundMovement.cpp
CSteeringBehaviors.hpp CSteeringBehaviors.cpp) CSteeringBehaviors.hpp CSteeringBehaviors.cpp
CBodyStateInfo.hpp CBodyStateInfo.cpp)
runtime_add_list(Character CHARACTER_SOURCES) runtime_add_list(Character CHARACTER_SOURCES)

View File

@ -17,6 +17,6 @@ std::shared_ptr<CAnimTreeNode> CMetaTransTrans::VGetTransitionTree(const std::we
const CAnimSysContext& animSys) const const CAnimSysContext& animSys) const
{ {
return std::make_shared<CAnimTreeTransition>(xc_, a, b, x4_animTime, xd_, x10_, return std::make_shared<CAnimTreeTransition>(xc_, a, b, x4_animTime, xd_, x10_,
CAnimTreeTransition::CreatePrimitiveName(a, b, x4_animTime)); CAnimTreeTransition::CreatePrimitiveName(a, b, x4_animTime.GetSeconds()));
} }
} }

View File

@ -13,6 +13,7 @@ class CPASAnimInfo
u32 x0_id; u32 x0_id;
rstl::reserved_vector<CPASAnimParm::UParmValue, 8> x4_parms; rstl::reserved_vector<CPASAnimParm::UParmValue, 8> x4_parms;
public: public:
CPASAnimInfo(u32 id) : x0_id(id) {}
CPASAnimInfo(u32 id, rstl::reserved_vector<CPASAnimParm::UParmValue, 8>&& parms); CPASAnimInfo(u32 id, rstl::reserved_vector<CPASAnimParm::UParmValue, 8>&& parms);
u32 GetAnimId() const { return x0_id; } u32 GetAnimId() const { return x0_id; }
CPASAnimParm::UParmValue GetAnimParmValue(u32 idx) const; CPASAnimParm::UParmValue GetAnimParmValue(u32 idx) const;

View File

@ -13,9 +13,15 @@ class CPASAnimParmData
public: public:
CPASAnimParmData() = default; CPASAnimParmData() = default;
CPASAnimParmData(s32 stateId, const CPASAnimParm& parm1, const CPASAnimParm& parm2, const CPASAnimParm& parm3, CPASAnimParmData(s32 stateId,
const CPASAnimParm& parm4, const CPASAnimParm& parm5, const CPASAnimParm& parm6, const CPASAnimParm& parm1 = CPASAnimParm::NoParameter(),
const CPASAnimParm& parm7, const CPASAnimParm& parm8); const CPASAnimParm& parm2 = CPASAnimParm::NoParameter(),
const CPASAnimParm& parm3 = CPASAnimParm::NoParameter(),
const CPASAnimParm& parm4 = CPASAnimParm::NoParameter(),
const CPASAnimParm& parm5 = CPASAnimParm::NoParameter(),
const CPASAnimParm& parm6 = CPASAnimParm::NoParameter(),
const CPASAnimParm& parm7 = CPASAnimParm::NoParameter(),
const CPASAnimParm& parm8 = CPASAnimParm::NoParameter());
s32 GetStateId() const { return x0_stateId; } s32 GetStateId() const { return x0_stateId; }
const rstl::reserved_vector<CPASAnimParm, 8>& GetAnimParmData() const { return x4_parms; } const rstl::reserved_vector<CPASAnimParm, 8>& GetAnimParmData() const { return x4_parms; }

View File

@ -60,16 +60,17 @@ CPASAnimState::CPASAnimState(int stateId)
: x0_id(stateId) : x0_id(stateId)
{} {}
CPASAnimParm CPASAnimState::GetAnimParmData(s32 idx, u32 id) const CPASAnimParm CPASAnimState::GetAnimParmData(s32 animId, u32 parmIdx) const
{ {
auto search = std::lower_bound(x14_anims.begin(), x14_anims.end(), id, CPASAnimInfo key(animId);
[](const CPASAnimInfo& item, const u32& testId) -> auto search = std::lower_bound(x14_anims.begin(), x14_anims.end(), key,
bool {return item.GetAnimId() < testId;}); [](const CPASAnimInfo& item, const CPASAnimInfo& testId) ->
if (search == x14_anims.end()) bool {return item.GetAnimId() < testId.GetAnimId();});
if (search == x14_anims.end() || search->GetAnimId() > animId)
return CPASAnimParm::NoParameter(); return CPASAnimParm::NoParameter();
CPASParmInfo parm = x4_parms.at(idx); CPASParmInfo parm = x4_parms.at(parmIdx);
return (*search).GetAnimParmData(idx, parm.GetParameterType()); return (*search).GetAnimParmData(parmIdx, parm.GetParameterType());
} }
s32 CPASAnimState::PickRandomAnimation(CRandom16& rand) const s32 CPASAnimState::PickRandomAnimation(CRandom16& rand) const
@ -208,7 +209,7 @@ float CPASAnimState::ComputePercentErrorWeight(u32 idx, const CPASAnimParm& parm
case CPASAnimParm::EParmType::Enum: case CPASAnimParm::EParmType::Enum:
{ {
const CPASParmInfo& info = x4_parms[idx]; const CPASParmInfo& info = x4_parms[idx];
range = info.GetWeightMaxValue().m_float - info.GetWeightMinValue().m_float; range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int;
val = std::fabs(parm.GetEnumValue() - parmVal.m_int); val = std::fabs(parm.GetEnumValue() - parmVal.m_int);
break; break;
} }

View File

@ -41,7 +41,7 @@ std::pair<float, s32> CPASDatabase::FindBestAnimation(const CPASAnimParmData& da
auto it = std::lower_bound(x0_states.cbegin(), x0_states.cend(), key, auto it = std::lower_bound(x0_states.cbegin(), x0_states.cend(), key,
[](const CPASAnimState& item, const CPASAnimState& test) -> bool {return item.GetStateId() < test.GetStateId();}); [](const CPASAnimState& item, const CPASAnimState& test) -> bool {return item.GetStateId() < test.GetStateId();});
if (it->GetStateId() < key.GetStateId() || it == x0_states.cend()) if (it == x0_states.cend() || it->GetStateId() > key.GetStateId())
return {0.f, -1}; return {0.f, -1};
return (*it).FindBestAnimation(data.GetAnimParmData(), rand, ignoreAnim); return (*it).FindBestAnimation(data.GetAnimParmData(), rand, ignoreAnim);

View File

@ -51,10 +51,10 @@ std::shared_ptr<IVaryingAnimationTimeScale> CLinearAnimationTimeScale::VClone()
CLinearAnimationTimeScale* ret = new CLinearAnimationTimeScale(); CLinearAnimationTimeScale* ret = new CLinearAnimationTimeScale();
float f30 = x4_ * xc_ + x8_; float f30 = x4_ * xc_ + x8_;
ret->x4_ = (x4_ * x10_ + x8_ - f30) / timeB; ret->x4_ = (x4_ * x10_ + x8_ - f30) / timeB.GetSeconds();
ret->x8_ = -((x4_ * x10_ + x8_ - f30) / (timeA - timeB) * timeB - f30); ret->x8_ = -((x4_ * x10_ + x8_ - f30) / (timeA - timeB).GetSeconds() * timeB.GetSeconds() - f30);
ret->xc_ = timeB; ret->xc_ = timeB.GetSeconds();
ret->x10_ = timeA; ret->x10_ = timeA.GetSeconds();
return std::shared_ptr<IVaryingAnimationTimeScale>(ret); return std::shared_ptr<IVaryingAnimationTimeScale>(ret);
} }
@ -68,10 +68,11 @@ CLinearAnimationTimeScale::VGetFunctionMirrored(const float& parm) const
CCharAnimTime timeB(2.f * parm - x10_); CCharAnimTime timeB(2.f * parm - x10_);
CLinearAnimationTimeScale* ret = new CLinearAnimationTimeScale(); CLinearAnimationTimeScale* ret = new CLinearAnimationTimeScale();
ret->x4_ = (-x4_ * 2.f * parm - xc_ + f27 - f31) / (timeA - timeB); ret->x4_ = (-x4_ * 2.f * parm - xc_ + f27 - f31) / (timeA - timeB).GetSeconds();
ret->x8_ = -(((-x4_ * 2.f * parm - xc_ + f27 - f31) / (timeA - timeB)) * timeB - f31); ret->x8_ = -(((-x4_ * 2.f * parm - xc_ + f27 - f31) /
ret->xc_ = timeB; (timeA - timeB).GetSeconds()) * timeB.GetSeconds() - f31);
ret->x10_ = timeA; ret->xc_ = timeB.GetSeconds();
ret->x10_ = timeA.GetSeconds();
return std::shared_ptr<IVaryingAnimationTimeScale>(ret); return std::shared_ptr<IVaryingAnimationTimeScale>(ret);
} }

View File

@ -7,23 +7,80 @@ namespace pas
{ {
enum class ELocomotionType enum class ELocomotionType
{ {
Invalid = -1,
Crouch,
Relaxed,
Lurk,
Combat,
Internal4,
Internal5,
Internal6,
Internal7,
Internal8,
Internal9,
Internal10,
Internal11,
Internal12,
Internal13,
Internal14
}; };
enum class ELocomotionAnim enum class ELocomotionAnim
{ {
Invalid = -1,
Idle,
Walk,
Run,
BackUp,
StrafeLeft,
StrafeRight,
StrafeUp,
StrafeDown
}; };
enum class EAnimationState enum class EAnimationState
{ {
Invalid = -1,
Fall,
Getup,
LieOnGround,
Step,
Death,
Locomotion,
KnockBack,
MeleeAttack,
Turn,
LoopAttack,
LoopReaction,
GroundHit,
Generate,
Jump,
Hurled,
Slide,
Taunt,
Scripted,
ProjectileAttack,
Cover,
WallHang
}; };
enum class EHurledType enum class EHurledState
{ {
Invalid = -1,
KnockIntoAir,
KnockLoop,
KnockDown,
StrikeWall,
StrikeWallFallLoop,
OutOfStrikeWall,
Six,
Seven
}; };
enum class EFallState enum class EFallState
{ {
Invalid = -1,
Zero
}; };
enum class EReactionType enum class EReactionType
@ -38,16 +95,31 @@ enum class EAdditiveReactionType
enum class EJumpType enum class EJumpType
{ {
Zero Normal,
One,
Ambush
};
enum class EJumpState
{
Invalid = -1,
IntoJump,
AmbushJump,
Loop,
OutOfJump,
WallBounceLeft,
WallBounceRight
}; };
enum class EStepDirection enum class EStepDirection
{ {
Invalid = -1, Invalid = -1,
Up = 0, Forward = 0,
Down = 1, Backward = 1,
Left = 2, Left = 2,
Right = 3 Right = 3,
Up = 4,
Down = 5
}; };
enum class EStepType enum class EStepType
@ -66,6 +138,14 @@ enum class EGetupType
Invalid = -1 Invalid = -1
}; };
enum class ELoopState
{
Invalid = -1,
Begin,
Loop,
End
};
enum class ELoopAttackType enum class ELoopAttackType
{ {
Invalid = -1 Invalid = -1
@ -86,25 +166,62 @@ enum class ETauntType
Invalid = -1 Invalid = -1
}; };
enum class ECoverState
{
Invalid = -1,
IntoCover,
Cover,
Lean,
OutOfCover
};
enum class ECoverDirection enum class ECoverDirection
{ {
Invalid = -1 Invalid = -1,
Left,
Right
};
enum class ETurnDirection
{
Invalid = -1,
Right,
Left
};
enum class EWallHangState
{
Invalid = -1,
IntoJump,
JumpArc,
JumpAirLoop,
IntoWallHang,
WallHang,
Five,
OutOfWallHang,
OutOfWallHangTurn,
DetachJumpLoop,
DetachOutOfJump
}; };
} }
enum class EBodyType enum class EBodyType
{ {
Zero, Invalid,
One, BiPedal,
Two, Restricted,
Three Flyer,
Pitchable,
RestrictedFlyer,
WallWalker,
NewFlyer
}; };
enum class EBodyStateCmd enum class EBodyStateCmd
{ {
Getup, Getup,
Step, Step,
Two, Die,
KnockDown, KnockDown,
KnockBack, KnockBack,
MeleeAttack, MeleeAttack,
@ -112,9 +229,9 @@ enum class EBodyStateCmd
LoopAttack, LoopAttack,
LoopReaction, LoopReaction,
LoopHitReaction, LoopHitReaction,
Ten, ExitState,
Eleven, LeanFromCover,
Twelve, NextState,
Thirteen, Thirteen,
Generate, Generate,
Hurled, Hurled,
@ -124,7 +241,7 @@ enum class EBodyStateCmd
Scripted, Scripted,
Cover, Cover,
WallHang, WallHang,
TwentyTwo, Locomotion,
TwentyThree, TwentyThree,
AdditiveAim, AdditiveAim,
AdditiveFlinch, AdditiveFlinch,

View File

@ -13,7 +13,7 @@ CBeetle::CBeetle(TUniqueId uid, const std::string& name, const CEntityInfo& info
const CDamageVulnerability&, const zeus::CVector3f&, float, float, float, const CDamageVulnerability&, const CDamageVulnerability&, const zeus::CVector3f&, float, float, float, const CDamageVulnerability&,
const CActorParameters& aParams, const rstl::optional_object<CStaticRes>) const CActorParameters& aParams, const rstl::optional_object<CStaticRes>)
: CPatterned(ECharacter::Beetle, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Ground, : CPatterned(ECharacter::Beetle, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Ground,
EColliderType::One, EBodyType::One, aParams, bool(flavor)) EColliderType::One, EBodyType::BiPedal, aParams, bool(flavor))
{ {
} }

View File

@ -26,7 +26,7 @@ CMetroid::CMetroid(TUniqueId uid, const std::string& name, EFlavorType flavor, c
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo,
const CActorParameters& aParms, const CMetroidData& metroidData) const CActorParameters& aParms, const CMetroidData& metroidData)
: CPatterned(ECharacter::Metroid, uid, name, flavor, info, xf, std::move(mData), pInfo, : CPatterned(ECharacter::Metroid, uid, name, flavor, info, xf, std::move(mData), pInfo,
EMovementType::Flyer, EColliderType::One, EBodyType::Three, aParms, true) EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, true)
{ {
} }

View File

@ -10,7 +10,7 @@ CMetroidBeta::CMetroidBeta(TUniqueId uid, const std::string& name, const CEntity
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo,
const CActorParameters& aParms, const CMetroidData& metroidData) const CActorParameters& aParms, const CMetroidData& metroidData)
: CPatterned(ECharacter::MetroidBeta, uid, name, EFlavorType::One, info, xf, std::move(mData), pInfo, : CPatterned(ECharacter::MetroidBeta, uid, name, EFlavorType::One, info, xf, std::move(mData), pInfo,
EMovementType::Flyer, EColliderType::One, EBodyType::Three, aParms, 2) EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, 2)
{ {
} }

View File

@ -12,7 +12,7 @@ CNewIntroBoss::CNewIntroBoss(TUniqueId uid, const std::string& name, const CEnti
const CActorParameters& actParms, float, u32, const CDamageInfo& dInfo, const CActorParameters& actParms, float, u32, const CDamageInfo& dInfo,
u32, u32, u32, u32) u32, u32, u32, u32)
: CPatterned(ECharacter::NewIntroBoss, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, : CPatterned(ECharacter::NewIntroBoss, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Flyer, EColliderType::One, EBodyType::Two, actParms, true) EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, true)
{ {
} }

View File

@ -10,7 +10,7 @@ CSpacePirate::CSpacePirate(TUniqueId uid, const std::string& name, const CEntity
CModelData&& mData, const CActorParameters& aParams, const CPatternedInfo& pInfo, CInputStream& in, CModelData&& mData, const CActorParameters& aParams, const CPatternedInfo& pInfo, CInputStream& in,
u32 propCount) u32 propCount)
: CPatterned(ECharacter::SpacePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Ground, : CPatterned(ECharacter::SpacePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Ground,
EColliderType::One, EBodyType::One, aParams, true) EColliderType::One, EBodyType::BiPedal, aParams, true)
{ {
} }

View File

@ -8,7 +8,7 @@ CThardusRockProjectile::CThardusRockProjectile(
const zeus::CTransform& xf, CModelData&& modelData, const CActorParameters& aParms, const zeus::CTransform& xf, CModelData&& modelData, const CActorParameters& aParms,
const CPatternedInfo& patternedInfo, const std::vector<CModelData>& mDataVec, u32) const CPatternedInfo& patternedInfo, const std::vector<CModelData>& mDataVec, u32)
: CPatterned(ECharacter::ThardusRockProjectile, uid, name, EFlavorType::Zero, info, xf, std::move(modelData), : CPatterned(ECharacter::ThardusRockProjectile, uid, name, EFlavorType::Zero, info, xf, std::move(modelData),
patternedInfo, EMovementType::Flyer, EColliderType::One, EBodyType::Three, aParms, true) patternedInfo, EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, true)
{ {
} }

View File

@ -11,7 +11,7 @@ CWarWasp::CWarWasp(TUniqueId uid, const std::string& name, const CEntityInfo& in
CPatterned::EColliderType collider, const CDamageInfo& dInfo1, const CActorParameters& actorParms, CPatterned::EColliderType collider, const CDamageInfo& dInfo1, const CActorParameters& actorParms,
ResId weapon, const CDamageInfo& dInfo2, ResId particle, u32 w3) ResId weapon, const CDamageInfo& dInfo2, ResId particle, u32 w3)
: CPatterned(ECharacter::WarWasp, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, collider, : CPatterned(ECharacter::WarWasp, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, collider,
EBodyType::Three, actorParms, false) EBodyType::Flyer, actorParms, false)
{ {
} }

View File

@ -504,4 +504,11 @@ void CActor::SetCalculateLighting(bool c)
4, 4, false, false, false, 0.1f); 4, 4, false, false, false, 0.1f);
xe4_31_lightsDirty = c; xe4_31_lightsDirty = c;
} }
float CActor::GetAverageAnimVelocity(int anim) const
{
if (HasModelData() && GetModelData()->HasAnimData())
return GetModelData()->GetAnimationData()->GetAverageVelocity(anim);
return 0.f;
}
} }

View File

@ -174,6 +174,7 @@ public:
const CHealthInfo* GetHealthInfo() const { return const_cast<CActor*>(this)->HealthInfo(); } const CHealthInfo* GetHealthInfo() const { return const_cast<CActor*>(this)->HealthInfo(); }
bool GetDoTargetDistanceTest() const { return xe7_30_doTargetDistanceTest; } bool GetDoTargetDistanceTest() const { return xe7_30_doTargetDistanceTest; }
void SetCalculateLighting(bool c); void SetCalculateLighting(bool c);
float GetAverageAnimVelocity(int anim) const;
}; };
} }

View File

@ -70,6 +70,17 @@ public:
}; };
private: private:
union
{
struct
{
bool x328_24_ : 1;
bool x328_25_ : 1;
bool x328_26_ : 1;
bool x328_27_onGround : 1;
};
u32 _dummy = 0;
};
ECharacter x34c_character; ECharacter x34c_character;
public: public:
CPatterned(ECharacter character, TUniqueId uid, const std::string& name, EFlavorType flavor, const CEntityInfo& info, CPatterned(ECharacter character, TUniqueId uid, const std::string& name, EFlavorType flavor, const CEntityInfo& info,
@ -97,6 +108,11 @@ public:
return static_cast<const T*>(patterned.GetPtr()); return static_cast<const T*>(patterned.GetPtr());
return nullptr; return nullptr;
} }
bool GetX328_26() const { return x328_26_; }
virtual bool IsOnGround() const { return x328_27_onGround; }
virtual float GetGravityConstant() const { return 24.525002f; }
}; };
} }

View File

@ -159,6 +159,8 @@ public:
void SetVelocityWR(const zeus::CVector3f& vel); void SetVelocityWR(const zeus::CVector3f& vel);
void SetVelocityOR(const zeus::CVector3f& vel); void SetVelocityOR(const zeus::CVector3f& vel);
void SetMomentumWR(const zeus::CVector3f& m) { x150_momentum = m; } void SetMomentumWR(const zeus::CVector3f& m) { x150_momentum = m; }
void SetConstantForce(const zeus::CVector3f& f) { xfc_constantForce = f; }
void SetAngularMomentum(const zeus::CAxisAngle& m) { x108_angularMomentum = m; }
const zeus::CVector3f& GetMomentum() const { return x150_momentum; } const zeus::CVector3f& GetMomentum() const { return x150_momentum; }
const zeus::CVector3f& GetVelocity() const { return x138_velocity; } const zeus::CVector3f& GetVelocity() const { return x138_velocity; }
zeus::CVector3f GetTotalForcesWR() const; zeus::CVector3f GetTotalForcesWR() const;

View File

@ -8,6 +8,7 @@ namespace urde
class CScriptWaypoint : public CActor class CScriptWaypoint : public CActor
{ {
u16 xfa_jumpFlags;
public: public:
CScriptWaypoint(TUniqueId, const std::string&, const CEntityInfo&, CScriptWaypoint(TUniqueId, const std::string&, const CEntityInfo&,
const zeus::CTransform&, bool, float, float, const zeus::CTransform&, bool, float, float,

@ -1 +1 @@
Subproject commit c35ccdd3cd7517e4e277d02e336997b519d00162 Subproject commit 34bdfdcad75e16e877e1962478ff195372df82a3