Implement OpenCS reference validation (Feature #831)

celladd
Kamil Bar 10 years ago
parent 75db4d6473
commit e1314d6211

@ -41,7 +41,7 @@ opencs_units (model/tools
opencs_units_noqt (model/tools
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
birthsigncheck spellcheck referenceablecheck scriptcheck bodypartcheck
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
)

@ -0,0 +1,103 @@
#include "referencecheck.hpp"
#include <boost/lexical_cast.hpp>
CSMTools::ReferenceCheckStage::ReferenceCheckStage(
const CSMWorld::RefCollection& references,
const CSMWorld::RefIdCollection& referencables,
const CSMWorld::IdCollection<CSMWorld::Cell>& cells,
const CSMWorld::IdCollection<ESM::Faction>& factions)
:
mReferences(references),
mReferencables(referencables),
mCells(cells),
mFactions(factions)
{
}
void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &messages)
{
const CSMWorld::Record<CSMWorld::CellRef>& record = mReferences.getRecord(stage);
if (record.isDeleted())
return;
const CSMWorld::CellRef& cellRef = record.get();
const CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Reference, cellRef.mId);
// Check for empty reference id
if (cellRef.mRefID.empty())
messages.push_back(std::make_pair(id, " is an empty reference"));
// Check for non existing referenced object
if (mReferencables.searchId(cellRef.mRefID) == -1)
messages.push_back(std::make_pair(id, " is referencing non existing object " + cellRef.mRefID));
// Check if referenced object is in valid cell
if (mCells.searchId(cellRef.mCell) == -1)
messages.push_back(std::make_pair(id, " is referencing object from non existing cell " + cellRef.mCell));
// If object have owner, check if that owner reference is valid
if (!cellRef.mOwner.empty() and mReferencables.searchId(cellRef.mOwner) == -1)
messages.push_back(std::make_pair(id, " has non existing owner " + cellRef.mOwner));
// If object have creature soul trapped, check if that creature reference is valid
if (!cellRef.mSoul.empty())
if (mReferencables.searchId(cellRef.mSoul) == -1)
messages.push_back(std::make_pair(id, " has non existing trapped soul " + cellRef.mSoul));
bool hasFaction = !cellRef.mFaction.empty();
// If object have faction, check if that faction reference is valid
if (hasFaction)
if (mFactions.searchId(cellRef.mFaction) == -1)
messages.push_back(std::make_pair(id, " has non existing faction " + cellRef.mFaction));
// Check item's faction rank
if (hasFaction && cellRef.mFactionRank < -1)
messages.push_back(std::make_pair(id, " has faction set but has invalid faction rank " + cellRef.mFactionRank));
else if (!hasFaction && cellRef.mFactionRank != -2)
messages.push_back(std::make_pair(id, " has invalid faction rank " + cellRef.mFactionRank));
// If door have destination cell, check if that reference is valid
if (!cellRef.mDestCell.empty())
if (mCells.searchId(cellRef.mDestCell) == -1)
messages.push_back(std::make_pair(id, " has non existing destination cell " + cellRef.mDestCell));
// Check if scale isn't negative
if (cellRef.mScale < 0)
{
std::string str = " has negative scale ";
str += boost::lexical_cast<std::string>(cellRef.mScale);
messages.push_back(std::make_pair(id, id.getId() + str));
}
// Check if charge isn't negative
if (cellRef.mChargeFloat < 0)
{
std::string str = " has negative charges ";
str += boost::lexical_cast<std::string>(cellRef.mChargeFloat);
messages.push_back(std::make_pair(id, id.getId() + str));
}
// Check if enchantement points aren't negative or are at full (-1)
if (cellRef.mEnchantmentCharge < 0 && cellRef.mEnchantmentCharge != -1)
{
std::string str = " has negative enchantment points ";
str += boost::lexical_cast<std::string>(cellRef.mEnchantmentCharge);
messages.push_back(std::make_pair(id, id.getId() + str));
}
// Check if gold value isn't negative
if (cellRef.mGoldValue < 0)
{
std::string str = " has negative gold value ";
str += cellRef.mGoldValue;
messages.push_back(std::make_pair(id, id.getId() + str));
}
}
int CSMTools::ReferenceCheckStage::setup()
{
return mReferences.getSize();
}

@ -0,0 +1,28 @@
#ifndef CSM_TOOLS_REFERENCECHECK_H
#define CSM_TOOLS_REFERENCECHECK_H
#include "../doc/state.hpp"
#include "../doc/document.hpp"
namespace CSMTools
{
class ReferenceCheckStage : public CSMDoc::Stage
{
public:
ReferenceCheckStage (const CSMWorld::RefCollection& references,
const CSMWorld::RefIdCollection& referencables,
const CSMWorld::IdCollection<CSMWorld::Cell>& cells,
const CSMWorld::IdCollection<ESM::Faction>& factions);
virtual void perform(int stage, CSMDoc::Messages& messages);
virtual int setup();
private:
const CSMWorld::RefCollection& mReferences;
const CSMWorld::RefIdCollection& mReferencables;
const CSMWorld::IdCollection<CSMWorld::Cell>& mCells;
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
};
}
#endif // CSM_TOOLS_REFERENCECHECK_H

@ -23,6 +23,7 @@
#include "referenceablecheck.hpp"
#include "scriptcheck.hpp"
#include "bodypartcheck.hpp"
#include "referencecheck.hpp"
CSMDoc::Operation *CSMTools::Tools::get (int type)
{
@ -82,6 +83,8 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions()));
mVerifier->appendStage (new ReferenceCheckStage(mData.getReferences(), mData.getReferenceables(), mData.getCells(), mData.getFactions()));
mVerifier->appendStage (new ScriptCheckStage (mDocument));
mVerifier->appendStage(

Loading…
Cancel
Save