From 778b37e0f83afc65357cb9c8582804bb13609bfd Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 6 Jul 2017 11:06:56 -1000 Subject: [PATCH] CPASAnimState fixes --- DataSpec/DNAMP1/ANCS.cpp | 84 ++++++------ DataSpec/DNAMP1/ANCS.hpp | 6 +- Runtime/Character/CBodyStateCmdMgr.hpp | 2 +- Runtime/Character/CPASAnimParmData.cpp | 10 -- Runtime/Character/CPASAnimParmData.hpp | 6 +- Runtime/Character/CPASAnimState.cpp | 176 ++++++++++++++----------- Runtime/Character/CPASAnimState.hpp | 1 + Runtime/Character/CPASDatabase.cpp | 15 ++- Runtime/Character/CharacterCommon.hpp | 9 +- 9 files changed, 166 insertions(+), 143 deletions(-) diff --git a/DataSpec/DNAMP1/ANCS.cpp b/DataSpec/DNAMP1/ANCS.cpp index a5d5b0ad0..c12a81bdc 100644 --- a/DataSpec/DNAMP1/ANCS.cpp +++ b/DataSpec/DNAMP1/ANCS.cpp @@ -11,26 +11,26 @@ namespace DNAMP1 void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::read(athena::io::IStreamReader& reader) { parmType = reader.readUint32Big(); - unk1 = reader.readUint32Big(); - unk2 = reader.readFloatBig(); + weightFunction = reader.readUint32Big(); + weight = reader.readFloatBig(); switch (DataType(parmType)) { case DataType::Int32: - parmVals[0].int32 = reader.readInt32Big(); - parmVals[1].int32 = reader.readInt32Big(); + range[0].int32 = reader.readInt32Big(); + range[1].int32 = reader.readInt32Big(); break; case DataType::UInt32: case DataType::Enum: - parmVals[0].uint32 = reader.readUint32Big(); - parmVals[1].uint32 = reader.readUint32Big(); + range[0].uint32 = reader.readUint32Big(); + range[1].uint32 = reader.readUint32Big(); break; case DataType::Float: - parmVals[0].float32 = reader.readFloatBig(); - parmVals[1].float32 = reader.readFloatBig(); + range[0].float32 = reader.readFloatBig(); + range[1].float32 = reader.readFloatBig(); break; case DataType::Bool: - parmVals[0].bool1 = reader.readBool(); - parmVals[1].bool1 = reader.readBool(); + range[0].bool1 = reader.readBool(); + range[1].bool1 = reader.readBool(); 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 { writer.writeUint32Big(parmType); - writer.writeUint32Big(unk1); - writer.writeFloatBig(unk2); + writer.writeUint32Big(weightFunction); + writer.writeFloatBig(weight); switch (DataType(parmType)) { case DataType::Int32: - writer.writeInt32Big(parmVals[0].int32); - writer.writeInt32Big(parmVals[1].int32); + writer.writeInt32Big(range[0].int32); + writer.writeInt32Big(range[1].int32); break; case DataType::UInt32: case DataType::Enum: - writer.writeUint32Big(parmVals[0].uint32); - writer.writeUint32Big(parmVals[0].uint32); + writer.writeUint32Big(range[0].uint32); + writer.writeUint32Big(range[0].uint32); break; case DataType::Float: - writer.writeFloatBig(parmVals[0].float32); - writer.writeFloatBig(parmVals[0].float32); + writer.writeFloatBig(range[0].float32); + writer.writeFloatBig(range[0].float32); break; case DataType::Bool: - writer.writeBool(parmVals[0].bool1); - writer.writeBool(parmVals[0].bool1); + writer.writeBool(range[0].bool1); + writer.writeBool(range[0].bool1); 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) { parmType = reader.readUint32("parmType"); - unk1 = reader.readUint32("unk1"); - unk2 = reader.readFloat("unk2"); + weightFunction = reader.readUint32("weightFunction"); + weight = reader.readFloat("weight"); size_t parmValCount; - if (auto v = reader.enterSubVector("parmVals", parmValCount)) + if (auto v = reader.enterSubVector("range", parmValCount)) { switch (DataType(parmType)) { case DataType::Int32: - parmVals[0].int32 = reader.readInt32(nullptr); - parmVals[1].int32 = reader.readInt32(nullptr); + range[0].int32 = reader.readInt32(nullptr); + range[1].int32 = reader.readInt32(nullptr); break; case DataType::UInt32: case DataType::Enum: - parmVals[0].uint32 = reader.readUint32(nullptr); - parmVals[1].uint32 = reader.readUint32(nullptr); + range[0].uint32 = reader.readUint32(nullptr); + range[1].uint32 = reader.readUint32(nullptr); break; case DataType::Float: - parmVals[0].float32 = reader.readFloat(nullptr); - parmVals[1].float32 = reader.readFloat(nullptr); + range[0].float32 = reader.readFloat(nullptr); + range[1].float32 = reader.readFloat(nullptr); break; case DataType::Bool: - parmVals[0].bool1 = reader.readBool(nullptr); - parmVals[1].bool1 = reader.readBool(nullptr); + range[0].bool1 = reader.readBool(nullptr); + range[1].bool1 = reader.readBool(nullptr); 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 { writer.writeUint32("parmType", parmType); - writer.writeUint32("unk1", unk1); - writer.writeFloat("unk2", unk2); - if (auto v = writer.enterSubVector("parmVals")) + writer.writeUint32("weightFunction", weightFunction); + writer.writeFloat("weight", weight); + if (auto v = writer.enterSubVector("range")) { switch (DataType(parmType)) { case DataType::Int32: - writer.writeInt32(nullptr, parmVals[0].int32); - writer.writeInt32(nullptr, parmVals[1].int32); + writer.writeInt32(nullptr, range[0].int32); + writer.writeInt32(nullptr, range[1].int32); break; case DataType::UInt32: case DataType::Enum: - writer.writeUint32(nullptr, parmVals[0].uint32); - writer.writeUint32(nullptr, parmVals[0].uint32); + writer.writeUint32(nullptr, range[0].uint32); + writer.writeUint32(nullptr, range[0].uint32); break; case DataType::Float: - writer.writeFloat(nullptr, parmVals[0].float32); - writer.writeFloat(nullptr, parmVals[0].float32); + writer.writeFloat(nullptr, range[0].float32); + writer.writeFloat(nullptr, range[0].float32); break; case DataType::Bool: - writer.writeBool(nullptr, parmVals[0].bool1); - writer.writeBool(nullptr, parmVals[0].bool1); + writer.writeBool(nullptr, range[0].bool1); + writer.writeBool(nullptr, range[0].bool1); break; } } diff --git a/DataSpec/DNAMP1/ANCS.hpp b/DataSpec/DNAMP1/ANCS.hpp index e398f17e3..6f5d21535 100644 --- a/DataSpec/DNAMP1/ANCS.hpp +++ b/DataSpec/DNAMP1/ANCS.hpp @@ -89,9 +89,9 @@ struct ANCS : BigYAML }; atUint32 parmType; - atUint32 unk1; - float unk2; - Parm parmVals[2]; + atUint32 weightFunction; + float weight; + Parm range[2]; }; std::vector parmInfos; diff --git a/Runtime/Character/CBodyStateCmdMgr.hpp b/Runtime/Character/CBodyStateCmdMgr.hpp index a75dbc142..bf03f909d 100644 --- a/Runtime/Character/CBodyStateCmdMgr.hpp +++ b/Runtime/Character/CBodyStateCmdMgr.hpp @@ -42,7 +42,7 @@ public: class CBCStepCmd : public CBodyStateCmd { pas::EStepDirection x8_dir = pas::EStepDirection::Invalid; - pas::EStepType xc_type = pas::EStepType::Zero; + pas::EStepType xc_type = pas::EStepType::Normal; public: CBCStepCmd() : CBodyStateCmd(EBodyStateCmd::Step) {} CBCStepCmd(pas::EStepDirection dir, pas::EStepType type) diff --git a/Runtime/Character/CPASAnimParmData.cpp b/Runtime/Character/CPASAnimParmData.cpp index 2a1edfea0..4a6df7227 100644 --- a/Runtime/Character/CPASAnimParmData.cpp +++ b/Runtime/Character/CPASAnimParmData.cpp @@ -18,14 +18,4 @@ CPASAnimParmData::CPASAnimParmData(s32 stateId, const CPASAnimParm& parm1, const x4_parms.push_back(parm8); } -s32 CPASAnimParmData::GetStateId() -{ - return x0_stateId; -} - -const rstl::reserved_vector& CPASAnimParmData::GetAnimParmData() const -{ - return x4_parms; -} - } diff --git a/Runtime/Character/CPASAnimParmData.hpp b/Runtime/Character/CPASAnimParmData.hpp index a7033a114..f6a77a4a7 100644 --- a/Runtime/Character/CPASAnimParmData.hpp +++ b/Runtime/Character/CPASAnimParmData.hpp @@ -11,14 +11,14 @@ class CPASAnimParmData rstl::reserved_vector x4_parms; public: - CPASAnimParmData() {} + 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); - s32 GetStateId(); - const rstl::reserved_vector& GetAnimParmData() const; + s32 GetStateId() const { return x0_stateId; } + const rstl::reserved_vector& GetAnimParmData() const { return x4_parms; } static inline CPASAnimParmData NoParameters(s32 stateId) { diff --git a/Runtime/Character/CPASAnimState.cpp b/Runtime/Character/CPASAnimState.cpp index 202531621..e031e3645 100644 --- a/Runtime/Character/CPASAnimState.cpp +++ b/Runtime/Character/CPASAnimState.cpp @@ -56,6 +56,10 @@ CPASAnimState::CPASAnimState(CInputStream& in) } } +CPASAnimState::CPASAnimState(int stateId) +: x0_id(stateId) +{} + CPASAnimParm CPASAnimState::GetAnimParmData(s32 idx, u32 id) const { auto search = std::lower_bound(x14_anims.begin(), x14_anims.end(), id, @@ -86,79 +90,83 @@ s32 CPASAnimState::PickRandomAnimation(CRandom16& rand) const } std::pair CPASAnimState::FindBestAnimation(const rstl::reserved_vector& parms, - CRandom16& rand, s32 anim) const + CRandom16& rand, s32 ignoreAnim) const { const_cast*>(&x24_selectionCache)->clear(); 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; + if (x4_parms.size() > 0) + calcWeight = 0.f; + + u32 unweightedCount = 0; + + for (u32 i=0 ; i 0) - calcWeight = 0.f; + CPASAnimParm::UParmValue val = info.GetAnimParmValue(i); + const CPASParmInfo& parmInfo = x4_parms[i]; + float parmWeight = parmInfo.GetParameterWeight(); - u32 unweightedCount = 0 ; - u32 i = 0; - - for (; i*>(&x24_selectionCache)->push_back(info.GetAnimId()); + if (calcWeight > weight) + { + const_cast*>(&x24_selectionCache)->clear(); + const_cast*>(&x24_selectionCache)->push_back(info.GetAnimId()); + weight = calcWeight; + } + else if (weight == calcWeight) + { + const_cast*>(&x24_selectionCache)->push_back(info.GetAnimId()); weight = calcWeight; } } + return {weight, PickRandomAnimation(rand)}; } 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); - } - else if (parm.GetParameterType() == CPASAnimParm::EParmType::UInt32) - { + case CPASAnimParm::EParmType::UInt32: return (parm.GetUint32Value() == parmVal.m_uint ? 1.f : 0.f); - } - else if (parm.GetParameterType() == CPASAnimParm::EParmType::Float) - { + case CPASAnimParm::EParmType::Float: return ((parmVal.m_float - parm.GetReal32Value()) < FLT_EPSILON ? 1.f : 0.f); - } - else if (parm.GetParameterType() == CPASAnimParm::EParmType::Bool) - { + case CPASAnimParm::EParmType::Bool: return (parm.GetBoolValue() == parmVal.m_bool ? 1.f : 0.f); - } - else if (parm.GetParameterType() == CPASAnimParm::EParmType::Enum) - { + case CPASAnimParm::EParmType::Enum: return (parm.GetEnumValue() == parmVal.m_int ? 1.f : 0.f); + default: break; } return 0.f; @@ -169,33 +177,42 @@ float CPASAnimState::ComputePercentErrorWeight(u32 idx, const CPASAnimParm& parm float range = 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]; - range = float(info.GetWeightMinValue().m_int - info.GetWeightMaxValue().m_int); - val = float(std::abs(parmVal.m_int - parm.GetInt32Value())); + range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int; + 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]; - range = float(info.GetWeightMinValue().m_uint - info.GetWeightMaxValue().m_uint); - val = float(std::abs(int(parmVal.m_uint) - int(parm.GetUint32Value()))); + range = info.GetWeightMaxValue().m_uint - info.GetWeightMinValue().m_uint; + 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]; - range = float(info.GetWeightMinValue().m_float - info.GetWeightMaxValue().m_float); - val = float(std::fabs(parmVal.m_float - parm.GetReal32Value())); + range = info.GetWeightMaxValue().m_float - info.GetWeightMinValue().m_float; + 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]; - range = float(info.GetWeightMinValue().m_float - info.GetWeightMaxValue().m_float); - val = float(std::fabs(parmVal.m_float - parm.GetReal32Value())); + range = info.GetWeightMaxValue().m_float - info.GetWeightMinValue().m_float; + val = std::fabs(parm.GetEnumValue() - parmVal.m_int); + break; + } + default: break; } if (range > FLT_EPSILON) @@ -209,33 +226,42 @@ float CPASAnimState::ComputeAngularPercentErrorWeight(u32 idx, const CPASAnimPar float range = 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]; - range = float(info.GetWeightMinValue().m_int - info.GetWeightMaxValue().m_int); - val = float(std::abs(parmVal.m_int - parm.GetInt32Value())); + range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int; + 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]; - range = float(info.GetWeightMinValue().m_uint - info.GetWeightMaxValue().m_uint); - val = float(std::abs(int(parmVal.m_uint) - int(parm.GetUint32Value()))); + range = info.GetWeightMaxValue().m_uint - info.GetWeightMinValue().m_uint; + 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]; - range = float(info.GetWeightMinValue().m_float - info.GetWeightMaxValue().m_float); - val = float(std::fabs(parmVal.m_float - parm.GetReal32Value())); + range = info.GetWeightMaxValue().m_float - info.GetWeightMinValue().m_float; + 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]; - range = float(info.GetWeightMinValue().m_float - info.GetWeightMaxValue().m_float); - val = float(std::fabs(parmVal.m_float - parm.GetReal32Value())); + range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int + 1; + val = std::fabs(parm.GetEnumValue() - parmVal.m_int); + break; + } + default: break; } if (range > FLT_EPSILON) diff --git a/Runtime/Character/CPASAnimState.hpp b/Runtime/Character/CPASAnimState.hpp index 9bce44218..787325fc1 100644 --- a/Runtime/Character/CPASAnimState.hpp +++ b/Runtime/Character/CPASAnimState.hpp @@ -17,6 +17,7 @@ class CPASAnimState std::vector x24_selectionCache; public: CPASAnimState(CInputStream& in); + CPASAnimState(int stateId); s32 GetStateId() const {return x0_id;} s32 GetNumAnims() const { return x14_anims.size(); } CPASAnimParm GetAnimParmData(s32, u32) const; diff --git a/Runtime/Character/CPASDatabase.cpp b/Runtime/Character/CPASDatabase.cpp index 270a7b323..0b041f457 100644 --- a/Runtime/Character/CPASDatabase.cpp +++ b/Runtime/Character/CPASDatabase.cpp @@ -29,21 +29,22 @@ CPASDatabase::CPASDatabase(CInputStream& in) SetDefaultState(defaultState); } -std::pair CPASDatabase::FindBestAnimation(const CPASAnimParmData& data, s32 id) const +std::pair CPASDatabase::FindBestAnimation(const CPASAnimParmData& data, s32 ignoreAnim) const { CRandom16 rnd(4660); - return FindBestAnimation(data, rnd, id); + return FindBestAnimation(data, rnd, ignoreAnim); } -std::pair CPASDatabase::FindBestAnimation(const CPASAnimParmData& data, CRandom16& rand, s32 id) const +std::pair CPASDatabase::FindBestAnimation(const CPASAnimParmData& data, CRandom16& rand, s32 ignoreAnim) const { - auto it = std::lower_bound(x0_states.cbegin(), x0_states.cend(), id, - [](const CPASAnimState& item, const int& test) -> bool {return item.GetStateId() < test;}); + CPASAnimState key(data.GetStateId()); + 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 (*it).FindBestAnimation(data.GetAnimParmData(), rand, id); + return (*it).FindBestAnimation(data.GetAnimParmData(), rand, ignoreAnim); } } diff --git a/Runtime/Character/CharacterCommon.hpp b/Runtime/Character/CharacterCommon.hpp index 40f609b0b..c51cf4f47 100644 --- a/Runtime/Character/CharacterCommon.hpp +++ b/Runtime/Character/CharacterCommon.hpp @@ -43,12 +43,17 @@ enum class EJumpType enum class EStepDirection { - Invalid = -1 + Invalid = -1, + Up = 0, + Down = 1, + Left = 2, + Right = 3 }; enum class EStepType { - Zero + Normal = 0, + Dodge = 1 }; enum class ESeverity