diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 62747c9b0f..73faec59a3 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -38,7 +38,7 @@ opencs_units (model/tools opencs_units_noqt (model/tools mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck - birthsigncheck spellcheck referenceablecheck scriptcheck + birthsigncheck spellcheck referenceablecheck scriptcheck bodypartcheck ) diff --git a/apps/opencs/model/tools/bodypartcheck.cpp b/apps/opencs/model/tools/bodypartcheck.cpp new file mode 100644 index 0000000000..b2b6b915ff --- /dev/null +++ b/apps/opencs/model/tools/bodypartcheck.cpp @@ -0,0 +1,55 @@ +#include "bodypartcheck.hpp" + +CSMTools::BodyPartCheckStage::BodyPartCheckStage( + const CSMWorld::IdCollection &bodyParts, + const CSMWorld::Resources &meshes, + const CSMWorld::IdCollection &races ) : + mBodyParts(bodyParts), + mMeshes(meshes), + mRaces(races) +{ } + +int CSMTools::BodyPartCheckStage::setup() +{ + return mBodyParts.getSize(); +} + +void CSMTools::BodyPartCheckStage::perform ( int stage, Messages &messages ) +{ + const CSMWorld::Record &record = mBodyParts.getRecord(stage); + + if ( record.isDeleted() ) + return; + + const ESM::BodyPart &bodyPart = record.get(); + + CSMWorld::UniversalId id( CSMWorld::UniversalId::Type_BodyPart, bodyPart.mId ); + + // Check BYDT + + if ( bodyPart.mData.mPart < 0 || bodyPart.mData.mPart > 14 ) + messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range part value." )); + + if ( bodyPart.mData.mVampire < 0 ) + messages.push_back(std::make_pair( id, bodyPart.mId + " has negative vampire flag." )); + + if ( bodyPart.mData.mFlags < 0 || bodyPart.mData.mFlags > 2 ) + messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range flags value." )); + + if ( bodyPart.mData.mType < 0 || bodyPart.mData.mType > 2 ) + messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range type value." )); + + // Check MODL + + if ( bodyPart.mModel.empty() ) + messages.push_back(std::make_pair( id, bodyPart.mId + " has no model." )); + else if ( mMeshes.searchId( bodyPart.mModel ) == -1 ) + messages.push_back(std::make_pair( id, bodyPart.mId + " has unreferenced model." )); + + // Check FNAM + + if ( bodyPart.mRace.empty() ) + messages.push_back(std::make_pair( id, bodyPart.mId + " has no race." )); + else if ( mRaces.searchId( bodyPart.mRace ) == -1 ) + messages.push_back(std::make_pair( id, bodyPart.mId + " has invalid race." )); +} \ No newline at end of file diff --git a/apps/opencs/model/tools/bodypartcheck.hpp b/apps/opencs/model/tools/bodypartcheck.hpp new file mode 100644 index 0000000000..d72badfdf7 --- /dev/null +++ b/apps/opencs/model/tools/bodypartcheck.hpp @@ -0,0 +1,35 @@ +#ifndef CSM_TOOLS_BODYPARTCHECK_H +#define CSM_TOOLS_BODYPARTCHECK_H + +#include +#include + +#include "../world/resources.hpp" +#include "../world/idcollection.hpp" + +#include "../doc/stage.hpp" + +namespace CSMTools +{ + /// \brief VerifyStage: make sure that body part records are internally consistent + class BodyPartCheckStage : public CSMDoc::Stage + { + const CSMWorld::IdCollection &mBodyParts; + const CSMWorld::Resources &mMeshes; + const CSMWorld::IdCollection &mRaces; + + public: + BodyPartCheckStage( + const CSMWorld::IdCollection &bodyParts, + const CSMWorld::Resources &meshes, + const CSMWorld::IdCollection &races ); + + virtual int setup(); + ///< \return number of steps + + virtual void perform( int stage, Messages &messages ); + ///< Messages resulting from this tage will be appended to \a messages. + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index fcf98868a1..0f73acd16e 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -22,6 +22,7 @@ #include "spellcheck.hpp" #include "referenceablecheck.hpp" #include "scriptcheck.hpp" +#include "bodypartcheck.hpp" CSMDoc::Operation *CSMTools::Tools::get (int type) { @@ -79,9 +80,16 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier() mVerifier->appendStage (new SpellCheckStage (mData.getSpells())); - mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions())); + mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions())); mVerifier->appendStage (new ScriptCheckStage (mDocument)); + + mVerifier->appendStage( + new BodyPartCheckStage( + mData.getBodyParts(), + mData.getResources( + CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )), + mData.getRaces() )); } return mVerifier;