Merge branch 'skills' into next

actorid
Marc Zinnschlag 12 years ago
commit 1078386fd7

@ -35,7 +35,7 @@ opencs_units (model/tools
)
opencs_units_noqt (model/tools
stage verifier mandatoryid
stage verifier mandatoryid skillcheck
)

@ -198,6 +198,16 @@ void CSMDoc::Document::createBase()
}
/// \todo add GMSTs
for (int i=0; i<27; ++i)
{
ESM::Skill record;
record.mIndex = i;
record.mId = ESM::Skill::getIndexToId (record.mIndex);
record.blank();
getData().getSkills().add (record);
}
}
CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, bool new_)

@ -0,0 +1,37 @@
#include "skillcheck.hpp"
#include <sstream>
#include <components/esm/loadskil.hpp>
#include "../world/universalid.hpp"
CSMTools::SkillCheckStage::SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills)
: mSkills (skills)
{}
int CSMTools::SkillCheckStage::setup()
{
return mSkills.getSize();
}
void CSMTools::SkillCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Skill& skill = mSkills.getRecord (stage).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Skill, skill.mId);
for (int i=0; i<4; ++i)
if (skill.mData.mUseValue[i]<0)
{
std::ostringstream stream;
stream << id.toString() << "|Use value #" << i << " of " << skill.mId << " is negative";
messages.push_back (stream.str());
}
if (skill.mDescription.empty())
messages.push_back (id.toString() + "|" + skill.mId + " has an empty description");
}

@ -0,0 +1,29 @@
#ifndef CSM_TOOLS_SKILLCHECK_H
#define CSM_TOOLS_SKILLCHECK_H
#include <components/esm/loadskil.hpp>
#include "../world/idcollection.hpp"
#include "stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that skill records are internally consistent
class SkillCheckStage : public Stage
{
const CSMWorld::IdCollection<ESM::Skill>& mSkills;
public:
SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, std::vector<std::string>& messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

@ -12,6 +12,7 @@
#include "reportmodel.hpp"
#include "mandatoryid.hpp"
#include "skillcheck.hpp"
CSMTools::Operation *CSMTools::Tools::get (int type)
{
@ -51,6 +52,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier()
mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(),
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds));
mVerifier->appendStage (new SkillCheckStage (mData.getSkills()));
}
return mVerifier;

@ -31,7 +31,9 @@ namespace CSMWorld
Display_Float,
Display_Var,
Display_GmstVarType,
Display_GlobalVarType
Display_GlobalVarType,
Display_Specialisation,
Display_Attribute
};
std::string mTitle;

@ -1,6 +1,8 @@
#ifndef CSM_WOLRD_COLUMNS_H
#define CSM_WOLRD_COLUMNS_H
#include <boost/lexical_cast.hpp>
#include "columnbase.hpp"
namespace CSMWorld
@ -177,6 +179,112 @@ namespace CSMWorld
return true;
}
};
template<typename ESXRecordT>
struct DescriptionColumn : public Column<ESXRecordT>
{
DescriptionColumn() : Column<ESXRecordT> ("Description", ColumnBase::Display_String) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mDescription.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mDescription = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct SpecialisationColumn : public Column<ESXRecordT>
{
SpecialisationColumn() : Column<ESXRecordT> ("Specialisation", ColumnBase::Display_Specialisation) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mSpecialization;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mSpecialization = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct UseValueColumn : public Column<ESXRecordT>
{
int mIndex;
UseValueColumn (int index)
: Column<ESXRecordT> ("Use value #" + boost::lexical_cast<std::string> (index),
ColumnBase::Display_Float), mIndex (index)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mUseValue[mIndex];
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mUseValue[mIndex] = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct AttributeColumn : public Column<ESXRecordT>
{
AttributeColumn() : Column<ESXRecordT> ("Attribute", ColumnBase::Display_Attribute) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mAttribute;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mAttribute = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
}
#endif

@ -36,8 +36,17 @@ CSMWorld::Data::Data()
mGmsts.addColumn (new VarTypeColumn<ESM::GameSetting> (ColumnBase::Display_GmstVarType));
mGmsts.addColumn (new VarValueColumn<ESM::GameSetting>);
mSkills.addColumn (new StringIdColumn<ESM::Skill>);
mSkills.addColumn (new RecordStateColumn<ESM::Skill>);
mSkills.addColumn (new AttributeColumn<ESM::Skill>);
mSkills.addColumn (new SpecialisationColumn<ESM::Skill>);
for (int i=0; i<4; ++i)
mSkills.addColumn (new UseValueColumn<ESM::Skill> (i));
mSkills.addColumn (new DescriptionColumn<ESM::Skill>);
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill);
}
CSMWorld::Data::~Data()
@ -66,6 +75,16 @@ CSMWorld::IdCollection<ESM::GameSetting>& CSMWorld::Data::getGmsts()
return mGmsts;
}
const CSMWorld::IdCollection<ESM::Skill>& CSMWorld::Data::getSkills() const
{
return mSkills;
}
CSMWorld::IdCollection<ESM::Skill>& CSMWorld::Data::getSkills()
{
return mSkills;
}
QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
{
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
@ -102,7 +121,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
{
case ESM::REC_GLOB: mGlobals.load (reader, base); break;
case ESM::REC_GMST: mGmsts.load (reader, base); break;
case ESM::REC_SKIL: mSkills.load (reader, base); break;
default:

@ -8,6 +8,7 @@
#include <components/esm/loadglob.hpp>
#include <components/esm/loadgmst.hpp>
#include <components/esm/loadskil.hpp>
#include "idcollection.hpp"
#include "universalid.hpp"
@ -20,6 +21,7 @@ namespace CSMWorld
{
IdCollection<ESM::Global> mGlobals;
IdCollection<ESM::GameSetting> mGmsts;
IdCollection<ESM::Skill> mSkills;
std::vector<QAbstractItemModel *> mModels;
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
@ -44,6 +46,10 @@ namespace CSMWorld
IdCollection<ESM::GameSetting>& getGmsts();
const IdCollection<ESM::Skill>& getSkills() const;
IdCollection<ESM::Skill>& getSkills();
QAbstractItemModel *getTableModel (const UniversalId& id);
///< If no table model is available for \a id, an exception is thrown.
///

@ -74,6 +74,8 @@ namespace CSMWorld
virtual const RecordBase& getRecord (const std::string& id) const = 0;
virtual const RecordBase& getRecord (int index) const = 0;
virtual void load (ESM::ESMReader& reader, bool base) = 0;
};
@ -139,7 +141,9 @@ namespace CSMWorld
///
/// \attention Throw san exception, if the type of \a record does not match.
virtual const RecordBase& getRecord (const std::string& id) const;
virtual const Record<ESXRecordT>& getRecord (const std::string& id) const;
virtual const Record<ESXRecordT>& getRecord (int index) const;
virtual void load (ESM::ESMReader& reader, bool base);
@ -373,11 +377,18 @@ namespace CSMWorld
}
template<typename ESXRecordT>
const RecordBase& IdCollection<ESXRecordT>::getRecord (const std::string& id) const
const Record<ESXRecordT>& IdCollection<ESXRecordT>::getRecord (const std::string& id) const
{
int index = getIndex (id);
return mRecords.at (index);
}
template<typename ESXRecordT>
const Record<ESXRecordT>& IdCollection<ESXRecordT>::getRecord (int index) const
{
return mRecords.at (index);
}
}
#endif

@ -81,9 +81,7 @@ namespace CSMWorld
throw std::logic_error ("attempt to modify a deleted record");
mModified = modified;
if (mState!=State_ModifiedOnly)
mState = mBase==mModified ? State_BaseOnly : State_Modified;
mState = State_Modified;
}
template <typename ESXRecordT>

@ -19,6 +19,7 @@ namespace
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
};
@ -27,6 +28,7 @@ namespace
{
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
};
@ -43,7 +45,7 @@ CSMWorld::UniversalId::UniversalId (const std::string& universalId)
{
std::string::size_type index = universalId.find (':');
if (index==std::string::npos)
if (index!=std::string::npos)
{
std::string type = universalId.substr (0, index);

@ -37,8 +37,9 @@ namespace CSMWorld
Type_Global,
Type_VerificationResults,
Type_Gmsts,
Type_Gmst
Type_Gmst,
Type_Skills,
Type_Skill
};
private:

@ -86,6 +86,10 @@ void CSVDoc::View::setupWorldMenu()
connect (gmsts, SIGNAL (triggered()), this, SLOT (addGmstsSubView()));
world->addAction (gmsts);
QAction *skills = new QAction (tr ("Skills"), this);
connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView()));
world->addAction (skills);
mVerify = new QAction (tr ("&Verify"), this);
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify()));
world->addAction (mVerify);
@ -244,6 +248,11 @@ void CSVDoc::View::addGmstsSubView()
addSubView (CSMWorld::UniversalId::Type_Gmsts);
}
void CSVDoc::View::addSkillsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Skills);
}
void CSVDoc::View::abortOperation (int type)
{
mDocument->abortOperation (type);

@ -116,6 +116,7 @@ namespace CSVDoc
void addGmstsSubView();
void addSkillsSubView();
};
}

@ -38,6 +38,17 @@ void CSVDoc::ViewManager::updateIndices()
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
: mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false)
{
static const char *sSpecialisations[] =
{
"Combat", "Magic", "Stealth", 0
};
static const char *sAttributes[] =
{
"Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality",
"Luck", 0
};
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType,
@ -45,6 +56,12 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType,
new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_Specialisation,
new CSVWorld::EnumDelegateFactory (sSpecialisations));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_Attribute,
new CSVWorld::EnumDelegateFactory (sAttributes));
}
CSVDoc::ViewManager::~ViewManager()

@ -1,6 +1,7 @@
#include "enumdelegate.hpp"
#include <cassert>
#include <stdexcept>
#include <QComboBox>
@ -89,6 +90,16 @@ void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewIte
}
CSVWorld::EnumDelegateFactory::EnumDelegateFactory() {}
CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const char **names)
{
assert (names);
for (int i=0; names[i]; ++i)
add (i, names[i]);
}
CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
{

@ -45,6 +45,11 @@ namespace CSVWorld
public:
EnumDelegateFactory();
EnumDelegateFactory (const char **names);
///< \param names Array of char pointer with a 0-pointer as end mark
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.

@ -14,6 +14,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (CSMWorld::UniversalId::Type_Gmsts,
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (false));
manager.add (CSMWorld::UniversalId::Type_Skills,
new CSVDoc::SubViewFactoryWithCreateFlag<TableSubView> (false));
manager.add (CSMWorld::UniversalId::Type_Global,
new CSVDoc::SubViewFactoryWithCreateFlag<DialogueSubView> (true));
}

@ -1,5 +1,7 @@
#include "loadskil.hpp"
#include <sstream>
#include "esmreader.hpp"
#include "esmwriter.hpp"
@ -98,6 +100,10 @@ void Skill::load(ESMReader &esm)
esm.getHNT(mIndex, "INDX");
esm.getHNT(mData, "SKDT", 24);
mDescription = esm.getHNOString("DESC");
// create an ID from the index and the name (only used in the editor and likely to change in the
// future)
mId = getIndexToId (mIndex);
}
void Skill::save(ESMWriter &esm)
{
@ -105,4 +111,29 @@ void Skill::save(ESMWriter &esm)
esm.writeHNT("SKDT", mData, 24);
esm.writeHNOString("DESC", mDescription);
}
void Skill::blank()
{
mData.mAttribute = 0;
mData.mSpecialization = 0;
mData.mUseValue[0] = mData.mUseValue[1] = mData.mUseValue[2] = mData.mUseValue[3] = 1.0;
mDescription.clear();
}
std::string Skill::getIndexToId (int index)
{
std::ostringstream stream;
stream << "#";
if (index<10)
stream << "0";
stream << index;
if (index>=0 && index<Length)
stream << sSkillNameIds[index].substr (6);
return stream.str();
}
}

@ -19,6 +19,8 @@ class ESMWriter;
struct Skill
{
std::string mId;
struct SKDTstruct
{
int mAttribute; // see defs.hpp
@ -73,6 +75,11 @@ struct Skill
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID/index).
static std::string getIndexToId (int index);
};
}
#endif

Loading…
Cancel
Save