CPASAnimState fixes

This commit is contained in:
Jack Andersen 2017-07-06 11:06:56 -10:00
parent bfb16a3a0d
commit 778b37e0f8
9 changed files with 166 additions and 143 deletions

View File

@ -11,26 +11,26 @@ namespace DNAMP1
void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::read(athena::io::IStreamReader& reader) void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::read(athena::io::IStreamReader& reader)
{ {
parmType = reader.readUint32Big(); parmType = reader.readUint32Big();
unk1 = reader.readUint32Big(); weightFunction = reader.readUint32Big();
unk2 = reader.readFloatBig(); weight = reader.readFloatBig();
switch (DataType(parmType)) switch (DataType(parmType))
{ {
case DataType::Int32: case DataType::Int32:
parmVals[0].int32 = reader.readInt32Big(); range[0].int32 = reader.readInt32Big();
parmVals[1].int32 = reader.readInt32Big(); range[1].int32 = reader.readInt32Big();
break; break;
case DataType::UInt32: case DataType::UInt32:
case DataType::Enum: case DataType::Enum:
parmVals[0].uint32 = reader.readUint32Big(); range[0].uint32 = reader.readUint32Big();
parmVals[1].uint32 = reader.readUint32Big(); range[1].uint32 = reader.readUint32Big();
break; break;
case DataType::Float: case DataType::Float:
parmVals[0].float32 = reader.readFloatBig(); range[0].float32 = reader.readFloatBig();
parmVals[1].float32 = reader.readFloatBig(); range[1].float32 = reader.readFloatBig();
break; break;
case DataType::Bool: case DataType::Bool:
parmVals[0].bool1 = reader.readBool(); range[0].bool1 = reader.readBool();
parmVals[1].bool1 = reader.readBool(); range[1].bool1 = reader.readBool();
break; break;
} }
} }
@ -38,26 +38,26 @@ void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::read(a
void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::write(athena::io::IStreamWriter& writer) const void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::write(athena::io::IStreamWriter& writer) const
{ {
writer.writeUint32Big(parmType); writer.writeUint32Big(parmType);
writer.writeUint32Big(unk1); writer.writeUint32Big(weightFunction);
writer.writeFloatBig(unk2); writer.writeFloatBig(weight);
switch (DataType(parmType)) switch (DataType(parmType))
{ {
case DataType::Int32: case DataType::Int32:
writer.writeInt32Big(parmVals[0].int32); writer.writeInt32Big(range[0].int32);
writer.writeInt32Big(parmVals[1].int32); writer.writeInt32Big(range[1].int32);
break; break;
case DataType::UInt32: case DataType::UInt32:
case DataType::Enum: case DataType::Enum:
writer.writeUint32Big(parmVals[0].uint32); writer.writeUint32Big(range[0].uint32);
writer.writeUint32Big(parmVals[0].uint32); writer.writeUint32Big(range[0].uint32);
break; break;
case DataType::Float: case DataType::Float:
writer.writeFloatBig(parmVals[0].float32); writer.writeFloatBig(range[0].float32);
writer.writeFloatBig(parmVals[0].float32); writer.writeFloatBig(range[0].float32);
break; break;
case DataType::Bool: case DataType::Bool:
writer.writeBool(parmVals[0].bool1); writer.writeBool(range[0].bool1);
writer.writeBool(parmVals[0].bool1); writer.writeBool(range[0].bool1);
break; break;
} }
} }
@ -83,29 +83,29 @@ size_t ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::bina
void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::read(athena::io::YAMLDocReader& reader) void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::read(athena::io::YAMLDocReader& reader)
{ {
parmType = reader.readUint32("parmType"); parmType = reader.readUint32("parmType");
unk1 = reader.readUint32("unk1"); weightFunction = reader.readUint32("weightFunction");
unk2 = reader.readFloat("unk2"); weight = reader.readFloat("weight");
size_t parmValCount; size_t parmValCount;
if (auto v = reader.enterSubVector("parmVals", parmValCount)) if (auto v = reader.enterSubVector("range", parmValCount))
{ {
switch (DataType(parmType)) switch (DataType(parmType))
{ {
case DataType::Int32: case DataType::Int32:
parmVals[0].int32 = reader.readInt32(nullptr); range[0].int32 = reader.readInt32(nullptr);
parmVals[1].int32 = reader.readInt32(nullptr); range[1].int32 = reader.readInt32(nullptr);
break; break;
case DataType::UInt32: case DataType::UInt32:
case DataType::Enum: case DataType::Enum:
parmVals[0].uint32 = reader.readUint32(nullptr); range[0].uint32 = reader.readUint32(nullptr);
parmVals[1].uint32 = reader.readUint32(nullptr); range[1].uint32 = reader.readUint32(nullptr);
break; break;
case DataType::Float: case DataType::Float:
parmVals[0].float32 = reader.readFloat(nullptr); range[0].float32 = reader.readFloat(nullptr);
parmVals[1].float32 = reader.readFloat(nullptr); range[1].float32 = reader.readFloat(nullptr);
break; break;
case DataType::Bool: case DataType::Bool:
parmVals[0].bool1 = reader.readBool(nullptr); range[0].bool1 = reader.readBool(nullptr);
parmVals[1].bool1 = reader.readBool(nullptr); range[1].bool1 = reader.readBool(nullptr);
break; break;
default: break; default: break;
} }
@ -115,28 +115,28 @@ void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::read(a
void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::write(athena::io::YAMLDocWriter& writer) const void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::write(athena::io::YAMLDocWriter& writer) const
{ {
writer.writeUint32("parmType", parmType); writer.writeUint32("parmType", parmType);
writer.writeUint32("unk1", unk1); writer.writeUint32("weightFunction", weightFunction);
writer.writeFloat("unk2", unk2); writer.writeFloat("weight", weight);
if (auto v = writer.enterSubVector("parmVals")) if (auto v = writer.enterSubVector("range"))
{ {
switch (DataType(parmType)) switch (DataType(parmType))
{ {
case DataType::Int32: case DataType::Int32:
writer.writeInt32(nullptr, parmVals[0].int32); writer.writeInt32(nullptr, range[0].int32);
writer.writeInt32(nullptr, parmVals[1].int32); writer.writeInt32(nullptr, range[1].int32);
break; break;
case DataType::UInt32: case DataType::UInt32:
case DataType::Enum: case DataType::Enum:
writer.writeUint32(nullptr, parmVals[0].uint32); writer.writeUint32(nullptr, range[0].uint32);
writer.writeUint32(nullptr, parmVals[0].uint32); writer.writeUint32(nullptr, range[0].uint32);
break; break;
case DataType::Float: case DataType::Float:
writer.writeFloat(nullptr, parmVals[0].float32); writer.writeFloat(nullptr, range[0].float32);
writer.writeFloat(nullptr, parmVals[0].float32); writer.writeFloat(nullptr, range[0].float32);
break; break;
case DataType::Bool: case DataType::Bool:
writer.writeBool(nullptr, parmVals[0].bool1); writer.writeBool(nullptr, range[0].bool1);
writer.writeBool(nullptr, parmVals[0].bool1); writer.writeBool(nullptr, range[0].bool1);
break; break;
} }
} }

View File

@ -89,9 +89,9 @@ struct ANCS : BigYAML
}; };
atUint32 parmType; atUint32 parmType;
atUint32 unk1; atUint32 weightFunction;
float unk2; float weight;
Parm parmVals[2]; Parm range[2];
}; };
std::vector<ParmInfo> parmInfos; std::vector<ParmInfo> parmInfos;

View File

@ -42,7 +42,7 @@ public:
class CBCStepCmd : public CBodyStateCmd class CBCStepCmd : public CBodyStateCmd
{ {
pas::EStepDirection x8_dir = pas::EStepDirection::Invalid; pas::EStepDirection x8_dir = pas::EStepDirection::Invalid;
pas::EStepType xc_type = pas::EStepType::Zero; pas::EStepType xc_type = pas::EStepType::Normal;
public: public:
CBCStepCmd() : CBodyStateCmd(EBodyStateCmd::Step) {} CBCStepCmd() : CBodyStateCmd(EBodyStateCmd::Step) {}
CBCStepCmd(pas::EStepDirection dir, pas::EStepType type) CBCStepCmd(pas::EStepDirection dir, pas::EStepType type)

View File

@ -18,14 +18,4 @@ CPASAnimParmData::CPASAnimParmData(s32 stateId, const CPASAnimParm& parm1, const
x4_parms.push_back(parm8); x4_parms.push_back(parm8);
} }
s32 CPASAnimParmData::GetStateId()
{
return x0_stateId;
}
const rstl::reserved_vector<CPASAnimParm, 8>& CPASAnimParmData::GetAnimParmData() const
{
return x4_parms;
}
} }

View File

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

View File

@ -56,6 +56,10 @@ CPASAnimState::CPASAnimState(CInputStream& in)
} }
} }
CPASAnimState::CPASAnimState(int stateId)
: x0_id(stateId)
{}
CPASAnimParm CPASAnimState::GetAnimParmData(s32 idx, u32 id) const CPASAnimParm CPASAnimState::GetAnimParmData(s32 idx, u32 id) const
{ {
auto search = std::lower_bound(x14_anims.begin(), x14_anims.end(), id, auto search = std::lower_bound(x14_anims.begin(), x14_anims.end(), id,
@ -86,79 +90,83 @@ s32 CPASAnimState::PickRandomAnimation(CRandom16& rand) const
} }
std::pair<float, s32> CPASAnimState::FindBestAnimation(const rstl::reserved_vector<CPASAnimParm, 8>& parms, std::pair<float, s32> CPASAnimState::FindBestAnimation(const rstl::reserved_vector<CPASAnimParm, 8>& parms,
CRandom16& rand, s32 anim) const CRandom16& rand, s32 ignoreAnim) const
{ {
const_cast<std::vector<s32>*>(&x24_selectionCache)->clear(); const_cast<std::vector<s32>*>(&x24_selectionCache)->clear();
float weight = -1.f; float weight = -1.f;
if (x14_anims.size() != 0)
{
for (const CPASAnimInfo& info : x14_anims) for (const CPASAnimInfo& info : x14_anims)
{ {
if (info.GetAnimId() == ignoreAnim)
continue;
float calcWeight = 1.f; float calcWeight = 1.f;
if (x4_parms.size() > 0) if (x4_parms.size() > 0)
calcWeight = 0.f; calcWeight = 0.f;
u32 unweightedCount = 0; u32 unweightedCount = 0;
u32 i = 0;
for (; i<x4_parms.size() ; ++i) for (u32 i=0 ; i<x4_parms.size() ; ++i)
{ {
CPASAnimParm::UParmValue val = info.GetAnimParmValue(i); CPASAnimParm::UParmValue val = info.GetAnimParmValue(i);
const CPASParmInfo& parmInfo = x4_parms[i]; const CPASParmInfo& parmInfo = x4_parms[i];
float parmWeight = parmInfo.GetParameterWeight(); float parmWeight = parmInfo.GetParameterWeight();
float computedWeight; float computedWeight = 0.f;
if (parmInfo.GetWeightFunction() == CPASParmInfo::EWeightFunction::AngularPercent) switch (parmInfo.GetWeightFunction())
{
case CPASParmInfo::EWeightFunction::AngularPercent:
computedWeight = ComputeAngularPercentErrorWeight(i, parms[i], val); computedWeight = ComputeAngularPercentErrorWeight(i, parms[i], val);
else if (parmInfo.GetWeightFunction() == CPASParmInfo::EWeightFunction::ExactMatch) break;
case CPASParmInfo::EWeightFunction::ExactMatch:
computedWeight = ComputeExactMatchWeight(i, parms[i], val); computedWeight = ComputeExactMatchWeight(i, parms[i], val);
else if (parmInfo.GetWeightFunction() == CPASParmInfo::EWeightFunction::PercentError) break;
case CPASParmInfo::EWeightFunction::PercentError:
computedWeight = ComputePercentErrorWeight(i, parms[i], val); computedWeight = ComputePercentErrorWeight(i, parms[i], val);
else if (parmInfo.GetWeightFunction() == CPASParmInfo::EWeightFunction::NoWeight) break;
case CPASParmInfo::EWeightFunction::NoWeight:
unweightedCount++; unweightedCount++;
break;
default: break;
}
calcWeight = parmWeight * calcWeight + computedWeight; calcWeight += parmWeight * computedWeight;
} }
if (unweightedCount == x4_parms.size()) if (unweightedCount == x4_parms.size())
calcWeight = 1.0f; calcWeight = 1.0f;
if (calcWeight < weight) if (calcWeight > weight)
continue; {
const_cast<std::vector<s32>*>(&x24_selectionCache)->clear();
auto search = std::find(x24_selectionCache.cbegin(), x24_selectionCache.cend(), const_cast<std::vector<s32>*>(&x24_selectionCache)->push_back(info.GetAnimId());
info.GetAnimId()); weight = calcWeight;
}
if (search == x24_selectionCache.cend()) else if (weight == calcWeight)
{
const_cast<std::vector<s32>*>(&x24_selectionCache)->push_back(info.GetAnimId()); const_cast<std::vector<s32>*>(&x24_selectionCache)->push_back(info.GetAnimId());
weight = calcWeight; weight = calcWeight;
} }
} }
return {weight, PickRandomAnimation(rand)}; return {weight, PickRandomAnimation(rand)};
} }
float CPASAnimState::ComputeExactMatchWeight(u32, const CPASAnimParm& parm, CPASAnimParm::UParmValue parmVal) const float CPASAnimState::ComputeExactMatchWeight(u32, const CPASAnimParm& parm, CPASAnimParm::UParmValue parmVal) const
{ {
if (parm.GetParameterType() == CPASAnimParm::EParmType::Int32) switch (parm.GetParameterType())
{ {
case CPASAnimParm::EParmType::Int32:
return (parm.GetInt32Value() == parmVal.m_int ? 1.f : 0.f); return (parm.GetInt32Value() == parmVal.m_int ? 1.f : 0.f);
} case CPASAnimParm::EParmType::UInt32:
else if (parm.GetParameterType() == CPASAnimParm::EParmType::UInt32)
{
return (parm.GetUint32Value() == parmVal.m_uint ? 1.f : 0.f); return (parm.GetUint32Value() == parmVal.m_uint ? 1.f : 0.f);
} case CPASAnimParm::EParmType::Float:
else if (parm.GetParameterType() == CPASAnimParm::EParmType::Float)
{
return ((parmVal.m_float - parm.GetReal32Value()) < FLT_EPSILON ? 1.f : 0.f); return ((parmVal.m_float - parm.GetReal32Value()) < FLT_EPSILON ? 1.f : 0.f);
} case CPASAnimParm::EParmType::Bool:
else if (parm.GetParameterType() == CPASAnimParm::EParmType::Bool)
{
return (parm.GetBoolValue() == parmVal.m_bool ? 1.f : 0.f); return (parm.GetBoolValue() == parmVal.m_bool ? 1.f : 0.f);
} case CPASAnimParm::EParmType::Enum:
else if (parm.GetParameterType() == CPASAnimParm::EParmType::Enum)
{
return (parm.GetEnumValue() == parmVal.m_int ? 1.f : 0.f); return (parm.GetEnumValue() == parmVal.m_int ? 1.f : 0.f);
default: break;
} }
return 0.f; return 0.f;
@ -169,33 +177,42 @@ float CPASAnimState::ComputePercentErrorWeight(u32 idx, const CPASAnimParm& parm
float range = 0.f; float range = 0.f;
float val = 0.f; float val = 0.f;
if (parm.GetParameterType() == CPASAnimParm::EParmType::Int32) switch (parm.GetParameterType())
{
case CPASAnimParm::EParmType::Int32:
{ {
const CPASParmInfo& info = x4_parms[idx]; const CPASParmInfo& info = x4_parms[idx];
range = float(info.GetWeightMinValue().m_int - info.GetWeightMaxValue().m_int); range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int;
val = float(std::abs(parmVal.m_int - parm.GetInt32Value())); val = std::fabs(parm.GetInt32Value() - parmVal.m_int);
break;
} }
else if (parm.GetParameterType() == CPASAnimParm::EParmType::UInt32) case CPASAnimParm::EParmType::UInt32:
{ {
const CPASParmInfo& info = x4_parms[idx]; const CPASParmInfo& info = x4_parms[idx];
range = float(info.GetWeightMinValue().m_uint - info.GetWeightMaxValue().m_uint); range = info.GetWeightMaxValue().m_uint - info.GetWeightMinValue().m_uint;
val = float(std::abs(int(parmVal.m_uint) - int(parm.GetUint32Value()))); val = std::fabs(int(parmVal.m_uint) - int(parm.GetUint32Value()));
break;
} }
else if (parm.GetParameterType() == CPASAnimParm::EParmType::Float) case CPASAnimParm::EParmType::Float:
{ {
const CPASParmInfo& info = x4_parms[idx]; const CPASParmInfo& info = x4_parms[idx];
range = float(info.GetWeightMinValue().m_float - info.GetWeightMaxValue().m_float); range = info.GetWeightMaxValue().m_float - info.GetWeightMinValue().m_float;
val = float(std::fabs(parmVal.m_float - parm.GetReal32Value())); val = std::fabs(parm.GetReal32Value() - parmVal.m_float);
break;
} }
else if (parm.GetParameterType() == CPASAnimParm::EParmType::Bool) case CPASAnimParm::EParmType::Bool:
{ {
val = parm.GetBoolValue() ? 1.f : 0.f; val = parm.GetBoolValue() == parmVal.m_bool ? 0.f : 1.f;
break;
} }
else if (parm.GetParameterType() == CPASAnimParm::EParmType::Enum) case CPASAnimParm::EParmType::Enum:
{ {
const CPASParmInfo& info = x4_parms[idx]; const CPASParmInfo& info = x4_parms[idx];
range = float(info.GetWeightMinValue().m_float - info.GetWeightMaxValue().m_float); range = info.GetWeightMaxValue().m_float - info.GetWeightMinValue().m_float;
val = float(std::fabs(parmVal.m_float - parm.GetReal32Value())); val = std::fabs(parm.GetEnumValue() - parmVal.m_int);
break;
}
default: break;
} }
if (range > FLT_EPSILON) if (range > FLT_EPSILON)
@ -209,33 +226,42 @@ float CPASAnimState::ComputeAngularPercentErrorWeight(u32 idx, const CPASAnimPar
float range = 0.f; float range = 0.f;
float val = 0.f; float val = 0.f;
if (parm.GetParameterType() == CPASAnimParm::EParmType::Int32) switch (parm.GetParameterType())
{
case CPASAnimParm::EParmType::Int32:
{ {
const CPASParmInfo& info = x4_parms[idx]; const CPASParmInfo& info = x4_parms[idx];
range = float(info.GetWeightMinValue().m_int - info.GetWeightMaxValue().m_int); range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int;
val = float(std::abs(parmVal.m_int - parm.GetInt32Value())); val = std::fabs(parmVal.m_int - parm.GetInt32Value());
break;
} }
else if (parm.GetParameterType() == CPASAnimParm::EParmType::UInt32) case CPASAnimParm::EParmType::UInt32:
{ {
const CPASParmInfo& info = x4_parms[idx]; const CPASParmInfo& info = x4_parms[idx];
range = float(info.GetWeightMinValue().m_uint - info.GetWeightMaxValue().m_uint); range = info.GetWeightMaxValue().m_uint - info.GetWeightMinValue().m_uint;
val = float(std::abs(int(parmVal.m_uint) - int(parm.GetUint32Value()))); val = std::fabs(int(parmVal.m_uint) - int(parm.GetUint32Value()));
break;
} }
else if (parm.GetParameterType() == CPASAnimParm::EParmType::Float) case CPASAnimParm::EParmType::Float:
{ {
const CPASParmInfo& info = x4_parms[idx]; const CPASParmInfo& info = x4_parms[idx];
range = float(info.GetWeightMinValue().m_float - info.GetWeightMaxValue().m_float); range = info.GetWeightMaxValue().m_float - info.GetWeightMinValue().m_float;
val = float(std::fabs(parmVal.m_float - parm.GetReal32Value())); val = std::fabs(parm.GetReal32Value() - parmVal.m_float);
break;
} }
else if (parm.GetParameterType() == CPASAnimParm::EParmType::Bool) case CPASAnimParm::EParmType::Bool:
{ {
val = parm.GetBoolValue() ? 1.f : 0.f; val = parm.GetBoolValue() == parmVal.m_bool ? 0.f : 1.f;
break;
} }
else if (parm.GetParameterType() == CPASAnimParm::EParmType::Enum) case CPASAnimParm::EParmType::Enum:
{ {
const CPASParmInfo& info = x4_parms[idx]; const CPASParmInfo& info = x4_parms[idx];
range = float(info.GetWeightMinValue().m_float - info.GetWeightMaxValue().m_float); range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int + 1;
val = float(std::fabs(parmVal.m_float - parm.GetReal32Value())); val = std::fabs(parm.GetEnumValue() - parmVal.m_int);
break;
}
default: break;
} }
if (range > FLT_EPSILON) if (range > FLT_EPSILON)

View File

@ -17,6 +17,7 @@ class CPASAnimState
std::vector<s32> x24_selectionCache; std::vector<s32> x24_selectionCache;
public: public:
CPASAnimState(CInputStream& in); CPASAnimState(CInputStream& in);
CPASAnimState(int stateId);
s32 GetStateId() const {return x0_id;} s32 GetStateId() const {return x0_id;}
s32 GetNumAnims() const { return x14_anims.size(); } s32 GetNumAnims() const { return x14_anims.size(); }
CPASAnimParm GetAnimParmData(s32, u32) const; CPASAnimParm GetAnimParmData(s32, u32) const;

View File

@ -29,21 +29,22 @@ CPASDatabase::CPASDatabase(CInputStream& in)
SetDefaultState(defaultState); SetDefaultState(defaultState);
} }
std::pair<float, s32> CPASDatabase::FindBestAnimation(const CPASAnimParmData& data, s32 id) const std::pair<float, s32> CPASDatabase::FindBestAnimation(const CPASAnimParmData& data, s32 ignoreAnim) const
{ {
CRandom16 rnd(4660); CRandom16 rnd(4660);
return FindBestAnimation(data, rnd, id); return FindBestAnimation(data, rnd, ignoreAnim);
} }
std::pair<float, s32> CPASDatabase::FindBestAnimation(const CPASAnimParmData& data, CRandom16& rand, s32 id) const std::pair<float, s32> CPASDatabase::FindBestAnimation(const CPASAnimParmData& data, CRandom16& rand, s32 ignoreAnim) const
{ {
auto it = std::lower_bound(x0_states.cbegin(), x0_states.cend(), id, CPASAnimState key(data.GetStateId());
[](const CPASAnimState& item, const int& test) -> bool {return item.GetStateId() < test;}); 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 == x0_states.cend()) if (it->GetStateId() < key.GetStateId() || it == x0_states.cend())
return {0.f, -1}; return {0.f, -1};
return (*it).FindBestAnimation(data.GetAnimParmData(), rand, id); return (*it).FindBestAnimation(data.GetAnimParmData(), rand, ignoreAnim);
} }
} }

View File

@ -43,12 +43,17 @@ enum class EJumpType
enum class EStepDirection enum class EStepDirection
{ {
Invalid = -1 Invalid = -1,
Up = 0,
Down = 1,
Left = 2,
Right = 3
}; };
enum class EStepType enum class EStepType
{ {
Zero Normal = 0,
Dodge = 1
}; };
enum class ESeverity enum class ESeverity