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> unknown7;
Value<atUint32> unknown8;
Value<atUint32> unknown9;
Value<atUint32> jumpFlags; // 0x2: single, 0x4: double
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<CParticlePOINode, 20> CAnimData::g_ParticlePOINodes;
rstl::reserved_vector<CSoundPOINode, 20> CAnimData::g_SoundPOINodes;
rstl::reserved_vector<CInt32POINode, 16> CAnimData::g_TransientInt32POINodes;
void CAnimData::FreeCache()
{
@ -73,6 +74,7 @@ CAnimData::CAnimData(ResId id,
g_Int32POINodes.resize(16);
g_ParticlePOINodes.resize(20);
g_SoundPOINodes.resize(20);
g_TransientInt32POINodes.resize(16);
x108_aabb = xd8_modelData->GetModel()->GetAABB();
x120_particleDB.CacheParticleDesc(xc_charInfo.GetParticleResData());
@ -127,7 +129,7 @@ SAdvancementDeltas CAnimData::AdvanceAdditiveAnims(float dt)
std::shared_ptr<CAnimTreeNode>& anim = additive.second.GetAnim();
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);
x20c_passedBoolCount += anim->GetBoolPOIList(time, g_BoolPOINodes.data(), 8, x20c_passedBoolCount, 0);
@ -143,7 +145,7 @@ SAdvancementDeltas CAnimData::AdvanceAdditiveAnims(float dt)
else
{
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);
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;
}
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)
@ -291,13 +309,193 @@ void CAnimData::SetPlaybackRate(float 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,
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
@ -330,12 +528,12 @@ bool CAnimData::IsAnimTimeRemaining(float rem, const std::string& name) const
{
if (!x1f8_animRoot)
return false;
return float(x1f8_animRoot->VGetTimeRemaining()) <= rem;
return x1f8_animRoot->VGetTimeRemaining().GetSeconds() <= rem;
}
float CAnimData::GetAnimTimeRemaining(const std::string& name) const
{
float rem = x1f8_animRoot->VGetTimeRemaining();
float rem = x1f8_animRoot->VGetTimeRemaining().GetSeconds();
if (x200_speedScale)
return rem / x200_speedScale;
return rem;
@ -373,7 +571,7 @@ float CAnimData::GetAnimationDuration(int animIn) const
}
}
durAccum += dur;
durAccum += dur.GetSeconds();
}
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
{
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);
if (parms.x4_animB != -1)
if (parms.GetSecondAnimationId() != -1)
{
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);
}
}
void CAnimData::SetAnimation(const CAnimPlaybackParms& parms, bool noTrans)
{
if (parms.x0_animA == x40c_playbackParms.x0_animA ||
(parms.x4_animB == x40c_playbackParms.x4_animB &&
parms.x8_blendWeight == x40c_playbackParms.x8_blendWeight &&
parms.x8_blendWeight != 1.f) ||
parms.x4_animB == -1)
if (parms.GetAnimationId() == x40c_playbackParms.GetAnimationId() ||
(parms.GetSecondAnimationId() == x40c_playbackParms.GetSecondAnimationId() &&
parms.GetBlendFactor() == x40c_playbackParms.GetBlendFactor() &&
parms.GetBlendFactor() != 1.f) ||
parms.GetSecondAnimationId() == -1)
{
if (x220_29_animationJustStarted)
return;
}
x40c_playbackParms.x0_animA = parms.x0_animA;
x40c_playbackParms.x4_animB = parms.x4_animB;
x40c_playbackParms.x8_blendWeight = parms.x8_blendWeight;
x40c_playbackParms.SetAnimationId(parms.GetAnimationId());
x40c_playbackParms.SetSecondAnimationId(parms.GetSecondAnimationId());
x40c_playbackParms.SetBlendFactor(parms.GetBlendFactor());
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();
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 =
x100_animMgr->GetAnimationTree(animIdxA, CMetaAnimTreeBuildOrders::NoSpecialOrders());
std::shared_ptr<CAnimTreeNode> treeB =
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,
parms.x8_blendWeight));
parms.GetBlendFactor()));
}
else
{
@ -548,7 +746,7 @@ void CAnimData::SetAnimation(const CAnimPlaybackParms& parms, bool noTrans)
else
x1f8_animRoot = blendNode;
x220_24_animating = parms.xc_animating;
x220_24_animating = parms.GetIsPlayAnimation();
CalcPlaybackAlignmentParms(parms, blendNode);
ResetPOILists();
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);
AdvanceAnim(time, offsetPost, quatPost);
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())
{
x220_24_animating = false;
@ -703,7 +901,7 @@ void CAnimData::AdvanceAnim(CCharAnimTime& time, zeus::CVector3f& offset, zeus::
offset += results.x8_deltas.x0_posDelta;
if (x220_26_)
offset += x1dc_alignPos * time;
offset += x1dc_alignPos * time.GetSeconds();
zeus::CQuaternion rot = results.x8_deltas.xc_rotDelta * x1e8_alignRot;
quat = quat * rot;
@ -771,8 +969,8 @@ float CAnimData::GetAverageVelocity(int animIn) const
}
}
velAccum += dur * avgVel;
durAccum += dur;
velAccum += dur.GetSeconds() * avgVel;
durAccum += dur.GetSeconds();
}
if (durAccum > 0.f)

View File

@ -139,6 +139,7 @@ class CAnimData
static rstl::reserved_vector<CInt32POINode, 16> g_Int32POINodes;
static rstl::reserved_vector<CParticlePOINode, 20> g_ParticlePOINodes;
static rstl::reserved_vector<CSoundPOINode, 20> g_SoundPOINodes;
static rstl::reserved_vector<CInt32POINode, 16> g_TransientInt32POINodes;
int m_drawInstCount;
@ -184,6 +185,7 @@ public:
float GetAnimationDuration(int) const;
bool GetIsLoop() const {return x220_25_loop;}
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;}
std::shared_ptr<CAnimSysContext> GetAnimSysContext() const;
std::shared_ptr<CAnimationManager> GetAnimationManager() const;

View File

@ -2,27 +2,42 @@
#define __CANIMPLAYBACKPARMS_HPP__
#include "RetroTypes.hpp"
#include "zeus/CQuaternion.hpp"
namespace urde
{
class CAnimPlaybackParms
{
friend class CAnimData;
s32 x0_animA = -1;
s32 x4_animB = -1;
float x8_blendWeight = 1.f;
bool xc_animating = true;
s32 x10_ = 0;
s32 x14_ = 0;
bool x18_ = false;
s32 x1c_ = 0;
s32 x20_ = 0;
s32 x24_ = 0;
s32 x10_ = 0;
const zeus::CVector3f* x14_targetPos = nullptr;
bool x18_useLocator = false;
const zeus::CQuaternion* x1c_deltaOrient = nullptr;
const zeus::CTransform* x20_objectXf = nullptr;
const zeus::CVector3f* x24_objectScale = nullptr;
public:
CAnimPlaybackParms() = default;
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)
accum += frameVel;
}
x60_averageVelocity = accum / x0_duration;
x60_averageVelocity = accum / x0_duration.GetSeconds();
}
CAnimSource::CAnimSource(CInputStream& in, IObjectStore& store)
@ -146,10 +146,10 @@ void CAnimSource::GetSegStatementSet(const CSegIdList& list,
const CCharAnimTime& time) const
{
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)
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 rotFloatsPerFrame = x40_data.xc_rotPerFrame * 4;
@ -209,10 +209,10 @@ zeus::CQuaternion CAnimSource::GetRotation(const CSegId& seg, const CCharAnimTim
if (rotIdx != 0xff)
{
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)
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 float* frameDataA =
@ -240,10 +240,10 @@ zeus::CVector3f CAnimSource::GetOffset(const CSegId& seg, const CCharAnimTime& t
return {};
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)
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 rotFloatsPerFrame = x40_data.xc_rotPerFrame * 4;

View File

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

View File

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

View File

@ -3,13 +3,15 @@
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)
, 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 {};
}
@ -22,13 +24,16 @@ CCharAnimTime CAnimTreeTimeScale::GetRealLifeTime(const CCharAnimTime& time) con
if (x28_ > CCharAnimTime())
{
if (tmp < CCharAnimTime(x28_ * x20_))
return x18_timeScale->VTimeScaleIntegral(x20_, x20_ + tmp);
return x18_timeScale->VTimeScaleIntegral(x20_.GetSeconds(),
(x20_ + tmp).GetSeconds());
else
{
CCharAnimTime integral = x18_timeScale->VTimeScaleIntegral(x20_, x28_);
CCharAnimTime integral =
x18_timeScale->VTimeScaleIntegral(x20_.GetSeconds(), x28_.GetSeconds());
if (integral > tmp)
return x18_timeScale->VFindUpperLimit(x20_, tmp) * x20_;
return x18_timeScale->VFindUpperLimit(x20_.GetSeconds(), tmp.GetSeconds()) *
x20_.GetSeconds();
else
return integral + (integral * tmp);
}

View File

@ -71,7 +71,7 @@ void CAnimTreeTransition::SetBlendingWeight(float w)
float CAnimTreeTransition::VGetBlendingWeight() const
{
if (x24_.GreaterThanZero())
return (1.f / x24_) * x2c_;
return (1.f / x24_.GetSeconds()) * x2c_.GetSeconds();
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 "zeus/CQuaternion.hpp"
#include "CharacterCommon.hpp"
#include "CBodyStateCmdMgr.hpp"
#include "CBodyStateInfo.hpp"
namespace urde
{
@ -14,26 +16,60 @@ class CFinalInput;
class CPASAnimParmData;
class CRandom16;
class CStateManager;
class CPASDatabase;
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:
CBodyController(CActor&, float, EBodyType);
CBodyController(CActor& owner, float f1, EBodyType bodyType);
void GetCurrentStateId() const;
void GetComandMgr();
void SetDoDeathAnims(bool);
CBodyStateCmdMgr& GetCommandMgr() { return x4_cmdMgr; }
const CBodyStateCmdMgr& GetCommandMgr() const { return x4_cmdMgr; }
void SetDoDeathAnims(bool d) { x300_28_playDeathAnims = d; }
bool IsElectrocuting() const;
bool IsOnFire() const;
bool IsFrozen() const;
void GetBodyStateInfo() const;
const CBodyStateInfo& GetBodyStateInfo() const { return x2a4_bodyStateInfo; }
bool GetIsActive() const;
void BodyStateInfo();
float GetTurnSpeed() const;
pas::ELocomotionType GetLocomotionType() const;
void GetOwner();
bool IsAnimationOver() const;
void EnableAnimation(bool);
bool ShouldPlayDeathAnims() const;
void GetCurrentAnimId() const;
pas::ELocomotionType GetLocomotionType() const { return x2ec_locomotionType; }
CActor& GetOwner() const { return x0_actor; }
bool IsAnimationOver() const { return x300_24_animationOver; }
void EnableAnimation(bool e);
bool ShouldPlayDeathAnims() const { return x300_28_playDeathAnims; }
s32 GetCurrentAnimId() const { return x2f8_curAnim; }
void Activate(CStateManager&);
void GetCurrentAdditiveState();
void SetState(pas::EAnimationState);
@ -47,15 +83,15 @@ public:
void SetAdditiveState(pas::EAnimationState);
void SetTurnSpeed(float);
void SetCurrentAnimation(const CAnimPlaybackParms&, bool, bool);
void GetAnimTimeRemaining() const;
float GetAnimTimeRemaining() const;
void SetPlaybackRate(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 FaceDirection3D(const zeus::CVector3f&, float);
void FaceDirection3D(const zeus::CVector3f&, const zeus::CVector3f&, float);
void HasBodyInfo(CActor&);
void ProcessInput(const CFinalInput&);
void GetPASDatabase() const;
const CPASDatabase& GetPASDatabase() const;
void PlayBestAnimation(const CPASAnimParmData&, CRandom16&);
void LoopBestAnimation(const CPASAnimParmData&, CRandom16&);
void Freeze(float, float, float);
@ -67,9 +103,9 @@ public:
void DouseElectrocuting();
void UpdateFrozenInfo(float, CStateManager&);
void GetCurrentAdditiveStateId() const;
EBodyType GetBodyType() const;
EBodyType GetBodyType() const { return x2f4_bodyType; }
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
#define CBODYSTATE_HPP
#include "RetroTypes.hpp"
#include "CharacterCommon.hpp"
#include "CBodyStateCmdMgr.hpp"
namespace urde
{
class CBodyController;
class CStateManager;
class CActor;
class CBodyState
{
public:
virtual bool IsInAir(const CBodyController&) const { return false; }
virtual bool IsDead() const { return false; }
virtual bool IsDying() const { return false; }
virtual bool IsMoving() const { return false; }
virtual bool ApplyGravity() const { return true; }
virtual bool ApplyHeadTracking() const { return true; }
virtual bool ApplyAnimationDeltas() const { return true; }
virtual bool CanShoot() const { return false; }
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;
};
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:
virtual bool CanShoot() const { return false; }
virtual void Start(CBodyController &, CStateManager &) {}
virtual void UpdateBody(float, CBodyController &, CStateManager&);
virtual void Shutdown(CBodyController&) {}
bool CanShoot() const { return false; }
void Start(CBodyController& bc, CStateManager & mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
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
{
float x4_remTime = 0.f;
bool x8_isDead = false;
public:
bool IsDead() const { return x8_isDead; }
void Start(CBodyController &, CStateManager &) {}
void UpdateBody(float, CBodyController &, CStateManager&) {}
void Shutdown(CBodyController &) {}
bool IsDying() const { return true; }
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
};
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:
void Start(CBodyController &, CStateManager &) {}
void UpdateBody(float, CBodyController &, CStateManager&) {}
void Shutdown(CBodyController &) {}
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController& bc);
};
class CBSGetup : public CBodyState
{
pas::EFallState x4_fallState = pas::EFallState::Invalid;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public:
void Start(CBodyController &, CStateManager &) {}
void UpdateBody(float, CBodyController &, CStateManager&) {}
void Shutdown(CBodyController &) {}
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController& bc);
};
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:
bool IsMoving() const { return true; }
void Start(CBodyController &, CStateManager &) {}
void UpdateBody(float, CBodyController &, CStateManager&) {}
void Shutdown(CBodyController &) {}
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
};
class CBSLieOnGround : public CBodyState
{
bool x4_24_hasGroundHit : 1;
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public:
void Start(CBodyController &, CStateManager &) {}
void UpdateBody(float, CBodyController &, CStateManager&) {}
void Shutdown(CBodyController &) {}
CBSLieOnGround(CActor& actor);
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController& bc);
};
class CBSStep : public CBodyState
{
pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
public:
bool IsMoving() const { return true; }
bool CanShoot() const { return true; }
void Start(CBodyController &, CStateManager &) {}
void UpdateBody(float, CBodyController &, CStateManager&) {}
void Shutdown(CBodyController &) {}
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
};
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:
virtual bool CanShoot() const { return true; }
virtual void Start(CBodyController &, CStateManager &) {}
virtual void UpdateBody(float, CBodyController &, CStateManager&) {}
virtual void Shutdown(CBodyController &) {}
virtual void GetBodyStateTransition(float, CBodyController&);
bool CanShoot() const { return true; }
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController&) {}
virtual pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc);
};
class CBSFlyerTurn : public CBSTurn
{
public:
virtual void Start(CBodyController &, CStateManager &) {}
virtual void UpdateBody(float, CBodyController &, CStateManager&) {}
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
};
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:
virtual bool CanShoot() const { return true; }
virtual void Start(CBodyController &, CStateManager &) {}
virtual void UpdateBody(float, CBodyController &, CStateManager&);
virtual void Shutdown(CBodyController&) {}
CBSLoopAttack() { xc_24_waitForAnimOver = false; xc_25_advance = false; }
bool CanShoot() const { return true; }
void Start(CBodyController& bc, CStateManager& mgr);
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
{
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:
virtual bool IsMoving() const = 0;
virtual bool CanShoot() const { return true; }
virtual void Start(CBodyController &, CStateManager &) {}
virtual void UpdateBody(float, CBodyController &, CStateManager&) {}
virtual void Shutdown() const {}
virtual bool IsPitchable() const { return true; }
virtual float GetLocomotionSpeed(pas::ELocomotionType, pas::ELocomotionAnim) = 0;
virtual void ApplyLocomotionPysics(float, CBodyController&) {}
virtual void UpdateLocomotionAnimation(float, const CBodyController& )=0;
virtual void GetBodyStateTransition(float, CBodyState&) {}
bool IsMoving() const = 0;
bool CanShoot() const { return true; }
void Start(CBodyController& bc, CStateManager& mgr);
pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr);
void Shutdown(CBodyController& bc);
virtual bool IsPitchable() const { return false; }
virtual float GetLocomotionSpeed(pas::ELocomotionType type, pas::ELocomotionAnim anim) const = 0;
virtual float ApplyLocomotionPhysics(float dt, CBodyController& bc);
virtual float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init) = 0;
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

View File

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

View File

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

View File

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

View File

@ -85,9 +85,11 @@ set(CHARACTER_SOURCES
CActorLights.hpp CActorLights.cpp
CAnimSysContext.hpp
CBodyState.hpp CBodyState.cpp
CAdditiveBodyState.hpp CAdditiveBodyState.cpp
CBodyStateCmdMgr.hpp CBodyStateCmdMgr.cpp
CBodyController.hpp CBodyController.cpp
CGroundMovement.hpp CGroundMovement.cpp
CSteeringBehaviors.hpp CSteeringBehaviors.cpp)
CSteeringBehaviors.hpp CSteeringBehaviors.cpp
CBodyStateInfo.hpp CBodyStateInfo.cpp)
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
{
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,8 +13,9 @@ class CPASAnimInfo
u32 x0_id;
rstl::reserved_vector<CPASAnimParm::UParmValue, 8> x4_parms;
public:
CPASAnimInfo(u32 id) : x0_id(id) {}
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 GetAnimParmData(u32, CPASAnimParm::EParmType) const;
};

View File

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

View File

@ -60,16 +60,17 @@ CPASAnimState::CPASAnimState(int 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,
[](const CPASAnimInfo& item, const u32& testId) ->
bool {return item.GetAnimId() < testId;});
if (search == x14_anims.end())
CPASAnimInfo key(animId);
auto search = std::lower_bound(x14_anims.begin(), x14_anims.end(), key,
[](const CPASAnimInfo& item, const CPASAnimInfo& testId) ->
bool {return item.GetAnimId() < testId.GetAnimId();});
if (search == x14_anims.end() || search->GetAnimId() > animId)
return CPASAnimParm::NoParameter();
CPASParmInfo parm = x4_parms.at(idx);
return (*search).GetAnimParmData(idx, parm.GetParameterType());
CPASParmInfo parm = x4_parms.at(parmIdx);
return (*search).GetAnimParmData(parmIdx, parm.GetParameterType());
}
s32 CPASAnimState::PickRandomAnimation(CRandom16& rand) const
@ -208,7 +209,7 @@ float CPASAnimState::ComputePercentErrorWeight(u32 idx, const CPASAnimParm& parm
case CPASAnimParm::EParmType::Enum:
{
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);
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,
[](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 (*it).FindBestAnimation(data.GetAnimParmData(), rand, ignoreAnim);

View File

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

View File

@ -7,23 +7,80 @@ namespace pas
{
enum class ELocomotionType
{
Invalid = -1,
Crouch,
Relaxed,
Lurk,
Combat,
Internal4,
Internal5,
Internal6,
Internal7,
Internal8,
Internal9,
Internal10,
Internal11,
Internal12,
Internal13,
Internal14
};
enum class ELocomotionAnim
{
Invalid = -1,
Idle,
Walk,
Run,
BackUp,
StrafeLeft,
StrafeRight,
StrafeUp,
StrafeDown
};
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
{
Invalid = -1,
Zero
};
enum class EReactionType
@ -38,16 +95,31 @@ enum class EAdditiveReactionType
enum class EJumpType
{
Zero
Normal,
One,
Ambush
};
enum class EJumpState
{
Invalid = -1,
IntoJump,
AmbushJump,
Loop,
OutOfJump,
WallBounceLeft,
WallBounceRight
};
enum class EStepDirection
{
Invalid = -1,
Up = 0,
Down = 1,
Forward = 0,
Backward = 1,
Left = 2,
Right = 3
Right = 3,
Up = 4,
Down = 5
};
enum class EStepType
@ -66,6 +138,14 @@ enum class EGetupType
Invalid = -1
};
enum class ELoopState
{
Invalid = -1,
Begin,
Loop,
End
};
enum class ELoopAttackType
{
Invalid = -1
@ -86,25 +166,62 @@ enum class ETauntType
Invalid = -1
};
enum class ECoverState
{
Invalid = -1,
IntoCover,
Cover,
Lean,
OutOfCover
};
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
{
Zero,
One,
Two,
Three
Invalid,
BiPedal,
Restricted,
Flyer,
Pitchable,
RestrictedFlyer,
WallWalker,
NewFlyer
};
enum class EBodyStateCmd
{
Getup,
Step,
Two,
Die,
KnockDown,
KnockBack,
MeleeAttack,
@ -112,9 +229,9 @@ enum class EBodyStateCmd
LoopAttack,
LoopReaction,
LoopHitReaction,
Ten,
Eleven,
Twelve,
ExitState,
LeanFromCover,
NextState,
Thirteen,
Generate,
Hurled,
@ -124,7 +241,7 @@ enum class EBodyStateCmd
Scripted,
Cover,
WallHang,
TwentyTwo,
Locomotion,
TwentyThree,
AdditiveAim,
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 CActorParameters& aParams, const rstl::optional_object<CStaticRes>)
: 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 CActorParameters& aParms, const CMetroidData& metroidData)
: 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 CActorParameters& aParms, const CMetroidData& metroidData)
: 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,
u32, u32, u32, u32)
: 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,
u32 propCount)
: 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 CPatternedInfo& patternedInfo, const std::vector<CModelData>& mDataVec, u32)
: 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,
ResId weapon, const CDamageInfo& dInfo2, ResId particle, u32 w3)
: 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);
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(); }
bool GetDoTargetDistanceTest() const { return xe7_30_doTargetDistanceTest; }
void SetCalculateLighting(bool c);
float GetAverageAnimVelocity(int anim) const;
};
}

View File

@ -70,6 +70,17 @@ public:
};
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;
public:
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 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 SetVelocityOR(const zeus::CVector3f& vel);
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& GetVelocity() const { return x138_velocity; }
zeus::CVector3f GetTotalForcesWR() const;

View File

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

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