actorid
Miroslav Puda 12 years ago
commit cd57523601

@ -23,7 +23,8 @@ opencs_units (model/world
opencs_units_noqt (model/world
universalid data record idcollection commands columnbase scriptcontext cell
universalid data record idcollection commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp
)
opencs_hdrs_noqt (model/world

@ -36,7 +36,12 @@ namespace CSMWorld
Display_Attribute,
Display_Boolean,
Display_SpellType,
Display_Script
Display_Script,
Display_ApparatusType,
Display_ArmorType,
Display_ClothingType,
Display_CreatureType,
Display_WeaponType
};
std::string mTitle;

@ -71,7 +71,7 @@ void CSMWorld::RevertCommand::redo()
void CSMWorld::RevertCommand::undo()
{
mModel.setRecord (*mOld);
mModel.setRecord (mId, *mOld);
}
CSMWorld::DeleteCommand::DeleteCommand (IdTable& model, const std::string& id, QUndoCommand *parent)
@ -104,5 +104,5 @@ void CSMWorld::DeleteCommand::redo()
void CSMWorld::DeleteCommand::undo()
{
mModel.setRecord (*mOld);
mModel.setRecord (mId, *mOld);
}

@ -140,6 +140,8 @@ CSMWorld::Data::Data()
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign);
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell);
addModel (new IdTable (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell);
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables,
UniversalId::Type_Referenceable);
}
CSMWorld::Data::~Data()
@ -268,6 +270,16 @@ CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells()
return mCells;
}
const CSMWorld::RefIdCollection& CSMWorld::Data::getReferenceables() const
{
return mReferenceables;
}
CSMWorld::RefIdCollection& CSMWorld::Data::getReferenceables()
{
return mReferenceables;
}
QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
{
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
@ -315,6 +327,30 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
case ESM::REC_SPEL: mSpells.load (reader, base); break;
case ESM::REC_CELL: mCells.load (reader, base); break;
case ESM::REC_ACTI: mReferenceables.load (reader, base, UniversalId::Type_Activator); break;
case ESM::REC_ALCH: mReferenceables.load (reader, base, UniversalId::Type_Potion); break;
case ESM::REC_APPA: mReferenceables.load (reader, base, UniversalId::Type_Apparatus); break;
case ESM::REC_ARMO: mReferenceables.load (reader, base, UniversalId::Type_Armor); break;
case ESM::REC_BOOK: mReferenceables.load (reader, base, UniversalId::Type_Book); break;
case ESM::REC_CLOT: mReferenceables.load (reader, base, UniversalId::Type_Clothing); break;
case ESM::REC_CONT: mReferenceables.load (reader, base, UniversalId::Type_Container); break;
case ESM::REC_CREA: mReferenceables.load (reader, base, UniversalId::Type_Creature); break;
case ESM::REC_DOOR: mReferenceables.load (reader, base, UniversalId::Type_Door); break;
case ESM::REC_INGR: mReferenceables.load (reader, base, UniversalId::Type_Ingredient); break;
case ESM::REC_LEVC:
mReferenceables.load (reader, base, UniversalId::Type_CreatureLevelledList); break;
case ESM::REC_LEVI:
mReferenceables.load (reader, base, UniversalId::Type_ItemLevelledList); break;
case ESM::REC_LIGH: mReferenceables.load (reader, base, UniversalId::Type_Light); break;
case ESM::REC_LOCK: mReferenceables.load (reader, base, UniversalId::Type_Lockpick); break;
case ESM::REC_MISC:
mReferenceables.load (reader, base, UniversalId::Type_Miscellaneous); break;
case ESM::REC_NPC_: mReferenceables.load (reader, base, UniversalId::Type_Npc); break;
case ESM::REC_PROB: mReferenceables.load (reader, base, UniversalId::Type_Probe); break;
case ESM::REC_REPA: mReferenceables.load (reader, base, UniversalId::Type_Repair); break;
case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break;
case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break;
default:
/// \todo throw an exception instead, once all records are implemented

@ -21,6 +21,7 @@
#include "idcollection.hpp"
#include "universalid.hpp"
#include "cell.hpp"
#include "refidcollection.hpp"
class QAbstractItemModel;
@ -40,6 +41,7 @@ namespace CSMWorld
IdCollection<ESM::BirthSign> mBirthsigns;
IdCollection<ESM::Spell> mSpells;
IdCollection<Cell> mCells;
RefIdCollection mReferenceables;
std::vector<QAbstractItemModel *> mModels;
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
@ -104,6 +106,10 @@ namespace CSMWorld
IdCollection<Cell>& getCells();
const RefIdCollection& getReferenceables() const;
RefIdCollection& getReferenceables();
QAbstractItemModel *getTableModel (const UniversalId& id);
///< If no table model is available for \a id, an exception is thrown.
///

@ -16,6 +16,7 @@
#include <components/misc/stringops.hpp>
#include "columnbase.hpp"
#include "universalid.hpp"
namespace CSMWorld
{
@ -45,15 +46,19 @@ namespace CSMWorld
virtual void setData (int index, int column, const QVariant& data) = 0;
virtual void merge() = 0;
// Not in use. Temporarily removed so that the implementation of RefIdCollection can continue without
// these functions for now.
// virtual void merge() = 0;
///< Merge modified into base.
virtual void purge() = 0;
// virtual void purge() = 0;
///< Remove records that are flagged as erased.
virtual void removeRows (int index, int count) = 0;
virtual void appendBlankRecord (const std::string& id) = 0;
virtual void appendBlankRecord (const std::string& id,
UniversalId::Type type = UniversalId::Type_None) = 0;
///< \param type Will be ignored, unless the collection supports multiple record types
virtual int searchId (const std::string& id) const = 0;
////< Search record with \a id.
@ -63,24 +68,47 @@ namespace CSMWorld
///< If the record type does not match, an exception is thrown.
///
/// \attention \a record must not change the ID.
///< \param type Will be ignored, unless the collection supports multiple record types
virtual void appendRecord (const RecordBase& record) = 0;
virtual void appendRecord (const RecordBase& record,
UniversalId::Type type = UniversalId::Type_None) = 0;
///< If the record type does not match, an exception is thrown.
virtual std::string getId (const RecordBase& record) const = 0;
///< Return ID for \a record.
///
/// \attention Throws an exception, if the type of \a record does not match.
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;
virtual void load (ESM::ESMReader& reader, bool base,
UniversalId::Type type = UniversalId::Type_None) = 0;
///< \param type Will be ignored, unless the collection supports multiple record types
virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const = 0;
///< \param type Will be ignored, unless the collection supports multiple record types
};
///< \brief Collection of ID-based records
///< \brief Access to ID field in records
template<typename ESXRecordT>
struct IdAccessor
{
std::string& getId (ESXRecordT& record);
const std::string getId (const ESXRecordT& record) const;
};
template<typename ESXRecordT>
std::string& IdAccessor<ESXRecordT>::getId (ESXRecordT& record)
{
return record.mId;
}
template<typename ESXRecordT>
const std::string IdAccessor<ESXRecordT>::getId (const ESXRecordT& record) const
{
return record.mId;
}
///< \brief Collection of ID-based records
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
class IdCollection : public IdCollectionBase
{
std::vector<Record<ESXRecordT> > mRecords;
@ -122,7 +150,9 @@ namespace CSMWorld
virtual void removeRows (int index, int count) ;
virtual void appendBlankRecord (const std::string& id);
virtual void appendBlankRecord (const std::string& id,
UniversalId::Type type = UniversalId::Type_None);
///< \param type Will be ignored, unless the collection supports multiple record types
virtual int searchId (const std::string& id) const;
////< Search record with \a id.
@ -133,38 +163,40 @@ namespace CSMWorld
///
/// \attention \a record must not change the ID.
virtual void appendRecord (const RecordBase& record);
virtual void appendRecord (const RecordBase& record,
UniversalId::Type type = UniversalId::Type_None);
///< If the record type does not match, an exception is thrown.
virtual std::string getId (const RecordBase& record) const;
///< Return ID for \a record.
///
/// \attention Throw san exception, if the type of \a record does not match.
///< \param type Will be ignored, unless the collection supports multiple record types
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);
virtual void load (ESM::ESMReader& reader, bool base,
UniversalId::Type type = UniversalId::Type_None);
///< \param type Will be ignored, unless the collection supports multiple record types
virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const;
///< \param type Will be ignored, unless the collection supports multiple record types
void addColumn (Column<ESXRecordT> *column);
};
template<typename ESXRecordT>
IdCollection<ESXRecordT>::IdCollection()
template<typename ESXRecordT, typename IdAccessorT>
IdCollection<ESXRecordT, IdAccessorT>::IdCollection()
{}
template<typename ESXRecordT>
IdCollection<ESXRecordT>::~IdCollection()
template<typename ESXRecordT, typename IdAccessorT>
IdCollection<ESXRecordT, IdAccessorT>::~IdCollection()
{
for (typename std::vector<Column<ESXRecordT> *>::iterator iter (mColumns.begin()); iter!=mColumns.end(); ++iter)
delete *iter;
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::add (const ESXRecordT& record)
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::add (const ESXRecordT& record)
{
std::string id = Misc::StringUtils::lowerCase(record.mId);
std::string id = Misc::StringUtils::lowerCase (IdAccessorT().getId (record));
std::map<std::string, int>::iterator iter = mIndex.find (id);
@ -183,20 +215,20 @@ namespace CSMWorld
}
}
template<typename ESXRecordT>
int IdCollection<ESXRecordT>::getSize() const
template<typename ESXRecordT, typename IdAccessorT>
int IdCollection<ESXRecordT, IdAccessorT>::getSize() const
{
return mRecords.size();
}
template<typename ESXRecordT>
std::string IdCollection<ESXRecordT>::getId (int index) const
template<typename ESXRecordT, typename IdAccessorT>
std::string IdCollection<ESXRecordT, IdAccessorT>::getId (int index) const
{
return mRecords.at (index).get().mId;
return IdAccessorT().getId (mRecords.at (index).get());
}
template<typename ESXRecordT>
int IdCollection<ESXRecordT>::getIndex (const std::string& id) const
template<typename ESXRecordT, typename IdAccessorT>
int IdCollection<ESXRecordT, IdAccessorT>::getIndex (const std::string& id) const
{
int index = searchId (id);
@ -206,38 +238,38 @@ namespace CSMWorld
return index;
}
template<typename ESXRecordT>
int IdCollection<ESXRecordT>::getColumns() const
template<typename ESXRecordT, typename IdAccessorT>
int IdCollection<ESXRecordT, IdAccessorT>::getColumns() const
{
return mColumns.size();
}
template<typename ESXRecordT>
QVariant IdCollection<ESXRecordT>::getData (int index, int column) const
template<typename ESXRecordT, typename IdAccessorT>
QVariant IdCollection<ESXRecordT, IdAccessorT>::getData (int index, int column) const
{
return mColumns.at (column)->get (mRecords.at (index));
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::setData (int index, int column, const QVariant& data)
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::setData (int index, int column, const QVariant& data)
{
return mColumns.at (column)->set (mRecords.at (index), data);
}
template<typename ESXRecordT>
const ColumnBase& IdCollection<ESXRecordT>::getColumn (int column) const
template<typename ESXRecordT, typename IdAccessorT>
const ColumnBase& IdCollection<ESXRecordT, IdAccessorT>::getColumn (int column) const
{
return *mColumns.at (column);
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::addColumn (Column<ESXRecordT> *column)
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::addColumn (Column<ESXRecordT> *column)
{
mColumns.push_back (column);
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::merge()
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::merge()
{
for (typename std::vector<Record<ESXRecordT> >::iterator iter (mRecords.begin()); iter!=mRecords.end(); ++iter)
iter->merge();
@ -245,16 +277,22 @@ namespace CSMWorld
purge();
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::purge()
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::purge()
{
mRecords.erase (std::remove_if (mRecords.begin(), mRecords.end(),
std::mem_fun_ref (&Record<ESXRecordT>::isErased) // I want lambda :(
), mRecords.end());
int i = 0;
while (i<static_cast<int> (mRecords.size()))
{
if (mRecords[i].isErased())
removeRows (i, 1);
else
++i;
}
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::removeRows (int index, int count)
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::removeRows (int index, int count)
{
mRecords.erase (mRecords.begin()+index, mRecords.begin()+index+count);
@ -278,17 +316,18 @@ namespace CSMWorld
}
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::appendBlankRecord (const std::string& id)
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::appendBlankRecord (const std::string& id,
UniversalId::Type type)
{
ESXRecordT record;
record.mId = id;
IdAccessorT().getId (record) = id;
record.blank();
add (record);
}
template<typename ESXRecordT>
int IdCollection<ESXRecordT>::searchId (const std::string& id) const
template<typename ESXRecordT, typename IdAccessorT>
int IdCollection<ESXRecordT, IdAccessorT>::searchId (const std::string& id) const
{
std::string id2 = Misc::StringUtils::lowerCase(id);
@ -300,28 +339,25 @@ namespace CSMWorld
return iter->second;
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::replace (int index, const RecordBase& record)
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::replace (int index, const RecordBase& record)
{
mRecords.at (index) = dynamic_cast<const Record<ESXRecordT>&> (record);
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::appendRecord (const RecordBase& record)
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::appendRecord (const RecordBase& record,
UniversalId::Type type)
{
mRecords.push_back (dynamic_cast<const Record<ESXRecordT>&> (record));
mIndex.insert (std::make_pair (Misc::StringUtils::lowerCase (getId (record)), mRecords.size()-1));
mIndex.insert (std::make_pair (Misc::StringUtils::lowerCase (IdAccessorT().getId (
dynamic_cast<const Record<ESXRecordT>&> (record).get())),
mRecords.size()-1));
}
template<typename ESXRecordT>
std::string IdCollection<ESXRecordT>::getId (const RecordBase& record) const
{
const Record<ESXRecordT>& record2 = dynamic_cast<const Record<ESXRecordT>&> (record);
return (record2.isModified() ? record2.mModified : record2.mBase).mId;
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::load (ESM::ESMReader& reader, bool base)
template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base,
UniversalId::Type type)
{
std::string id = reader.getHNOString ("NAME");
@ -351,10 +387,10 @@ namespace CSMWorld
else
{
ESXRecordT record;
record.mId = id;
IdAccessorT().getId (record) = id;
record.load (reader);
int index = searchId (record.mId);
int index = searchId (IdAccessorT().getId (record));
if (index==-1)
{
@ -378,15 +414,21 @@ namespace CSMWorld
}
}
template<typename ESXRecordT>
const Record<ESXRecordT>& IdCollection<ESXRecordT>::getRecord (const std::string& id) const
template<typename ESXRecordT, typename IdAccessorT>
int IdCollection<ESXRecordT, IdAccessorT>::getAppendIndex (UniversalId::Type type) const
{
return static_cast<int> (mRecords.size());
}
template<typename ESXRecordT, typename IdAccessorT>
const Record<ESXRecordT>& IdCollection<ESXRecordT, IdAccessorT>::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
template<typename ESXRecordT, typename IdAccessorT>
const Record<ESXRecordT>& IdCollection<ESXRecordT, IdAccessorT>::getRecord (int index) const
{
return mRecords.at (index);
}

@ -117,7 +117,7 @@ QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const
void CSMWorld::IdTable::addRecord (const std::string& id)
{
int index = mIdCollection->getSize();
int index = mIdCollection->getAppendIndex();
beginInsertRows (QModelIndex(), index, index);
@ -131,13 +131,13 @@ QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column)
return index (mIdCollection->getIndex (id), column);
}
void CSMWorld::IdTable::setRecord (const RecordBase& record)
void CSMWorld::IdTable::setRecord (const std::string& id, const RecordBase& record)
{
int index = mIdCollection->searchId (mIdCollection->getId (record));
int index = mIdCollection->searchId (id);
if (index==-1)
{
int index = mIdCollection->getSize();
int index = mIdCollection->getAppendIndex();
beginInsertRows (QModelIndex(), index, index);

@ -48,7 +48,7 @@ namespace CSMWorld
QModelIndex getModelIndex (const std::string& id, int column) const;
void setRecord (const RecordBase& record);
void setRecord (const std::string& id, const RecordBase& record);
///< Add record or overwrite existing recrod.
const RecordBase& getRecord (const std::string& id) const;

@ -22,6 +22,9 @@ namespace CSMWorld
virtual RecordBase *clone() const = 0;
virtual void assign (const RecordBase& record) = 0;
///< Will throw an exception if the types don't match.
bool isDeleted() const;
bool isErased() const;
@ -37,9 +40,14 @@ namespace CSMWorld
virtual RecordBase *clone() const;
virtual void assign (const RecordBase& record);
const ESXRecordT& get() const;
///< Throws an exception, if the record is deleted.
ESXRecordT& get();
///< Throws an exception, if the record is deleted.
const ESXRecordT& getBase() const;
///< Throws an exception, if the record is deleted. Returns modified, if there is no base.
@ -56,6 +64,12 @@ namespace CSMWorld
return new Record<ESXRecordT> (*this);
}
template <typename ESXRecordT>
void Record<ESXRecordT>::assign (const RecordBase& record)
{
*this = dynamic_cast<const Record<ESXRecordT>& > (record);
}
template <typename ESXRecordT>
const ESXRecordT& Record<ESXRecordT>::get() const
{
@ -65,6 +79,15 @@ namespace CSMWorld
return mState==State_BaseOnly || mState==State_Deleted ? mBase : mModified;
}
template <typename ESXRecordT>
ESXRecordT& Record<ESXRecordT>::get()
{
if (mState==State_Erased)
throw std::logic_error ("attempt to access a deleted record");
return mState==State_BaseOnly || mState==State_Deleted ? mBase : mModified;
}
template <typename ESXRecordT>
const ESXRecordT& Record<ESXRecordT>::getBase() const
{
@ -81,7 +104,9 @@ namespace CSMWorld
throw std::logic_error ("attempt to modify a deleted record");
mModified = modified;
mState = State_Modified;
if (mState!=State_ModifiedOnly)
mState = State_Modified;
}
template <typename ESXRecordT>

@ -0,0 +1,6 @@
#include "refidadapter.hpp"
CSMWorld::RefIdAdapter::RefIdAdapter() {}
CSMWorld::RefIdAdapter::~RefIdAdapter() {}

@ -0,0 +1,37 @@
#ifndef CSM_WOLRD_REFIDADAPTER_H
#define CSM_WOLRD_REFIDADAPTER_H
#include <string>
class QVariant;
namespace CSMWorld
{
class RefIdColumn;
class RefIdData;
class RecordBase;
class RefIdAdapter
{
// not implemented
RefIdAdapter (const RefIdAdapter&);
RefIdAdapter& operator= (const RefIdAdapter&);
public:
RefIdAdapter();
virtual ~RefIdAdapter();
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int idnex)
const = 0;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const = 0;
///< If the data type does not match an exception is thrown.
virtual std::string getId (const RecordBase& record) const = 0;
};
}
#endif

@ -0,0 +1,575 @@
#include "refidadapterimp.hpp"
CSMWorld::PotionRefIdAdapter::PotionRefIdAdapter (const InventoryColumns& columns,
const RefIdColumn *autoCalc)
: InventoryRefIdAdapter<ESM::Potion> (UniversalId::Type_Potion, columns),
mAutoCalc (autoCalc)
{}
QVariant CSMWorld::PotionRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Potion>& record = static_cast<const Record<ESM::Potion>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Potion)));
if (column==mAutoCalc)
return record.get().mData.mAutoCalc!=0;
return InventoryRefIdAdapter<ESM::Potion>::getData (column, data, index);
}
void CSMWorld::PotionRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Potion>& record = static_cast<Record<ESM::Potion>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Potion)));
if (column==mAutoCalc)
record.get().mData.mAutoCalc = value.toInt();
else
InventoryRefIdAdapter<ESM::Potion>::setData (column, data, index, value);
}
CSMWorld::ApparatusRefIdAdapter::ApparatusRefIdAdapter (const InventoryColumns& columns,
const RefIdColumn *type, const RefIdColumn *quality)
: InventoryRefIdAdapter<ESM::Apparatus> (UniversalId::Type_Apparatus, columns),
mType (type), mQuality (quality)
{}
QVariant CSMWorld::ApparatusRefIdAdapter::getData (const RefIdColumn *column,
const RefIdData& data, int index) const
{
const Record<ESM::Apparatus>& record = static_cast<const Record<ESM::Apparatus>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Apparatus)));
if (column==mType)
return record.get().mData.mType;
if (column==mQuality)
return record.get().mData.mQuality;
return InventoryRefIdAdapter<ESM::Apparatus>::getData (column, data, index);
}
void CSMWorld::ApparatusRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Apparatus>& record = static_cast<Record<ESM::Apparatus>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Apparatus)));
if (column==mType)
record.get().mData.mType = value.toInt();
else if (column==mQuality)
record.get().mData.mQuality = value.toFloat();
else
InventoryRefIdAdapter<ESM::Apparatus>::setData (column, data, index, value);
}
CSMWorld::ArmorRefIdAdapter::ArmorRefIdAdapter (const EnchantableColumns& columns,
const RefIdColumn *type, const RefIdColumn *health, const RefIdColumn *armor)
: EnchantableRefIdAdapter<ESM::Armor> (UniversalId::Type_Armor, columns),
mType (type), mHealth (health), mArmor (armor)
{}
QVariant CSMWorld::ArmorRefIdAdapter::getData (const RefIdColumn *column,
const RefIdData& data, int index) const
{
const Record<ESM::Armor>& record = static_cast<const Record<ESM::Armor>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Armor)));
if (column==mType)
return record.get().mData.mType;
if (column==mHealth)
return record.get().mData.mHealth;
if (column==mArmor)
return record.get().mData.mArmor;
return EnchantableRefIdAdapter<ESM::Armor>::getData (column, data, index);
}
void CSMWorld::ArmorRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Armor>& record = static_cast<Record<ESM::Armor>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Armor)));
if (column==mType)
record.get().mData.mType = value.toInt();
else if (column==mHealth)
record.get().mData.mHealth = value.toInt();
else if (column==mArmor)
record.get().mData.mArmor = value.toInt();
else
EnchantableRefIdAdapter<ESM::Armor>::setData (column, data, index, value);
}
CSMWorld::BookRefIdAdapter::BookRefIdAdapter (const EnchantableColumns& columns,
const RefIdColumn *scroll, const RefIdColumn *skill)
: EnchantableRefIdAdapter<ESM::Book> (UniversalId::Type_Book, columns),
mScroll (scroll), mSkill (skill)
{}
QVariant CSMWorld::BookRefIdAdapter::getData (const RefIdColumn *column,
const RefIdData& data, int index) const
{
const Record<ESM::Book>& record = static_cast<const Record<ESM::Book>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Book)));
if (column==mScroll)
return record.get().mData.mIsScroll!=0;
if (column==mSkill)
return record.get().mData.mSkillID;
return EnchantableRefIdAdapter<ESM::Book>::getData (column, data, index);
}
void CSMWorld::BookRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Book>& record = static_cast<Record<ESM::Book>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Book)));
if (column==mScroll)
record.get().mData.mIsScroll = value.toInt();
else if (column==mSkill)
record.get().mData.mSkillID = value.toInt();
else
EnchantableRefIdAdapter<ESM::Book>::setData (column, data, index, value);
}
CSMWorld::ClothingRefIdAdapter::ClothingRefIdAdapter (const EnchantableColumns& columns,
const RefIdColumn *type)
: EnchantableRefIdAdapter<ESM::Clothing> (UniversalId::Type_Clothing, columns), mType (type)
{}
QVariant CSMWorld::ClothingRefIdAdapter::getData (const RefIdColumn *column,
const RefIdData& data, int index) const
{
const Record<ESM::Clothing>& record = static_cast<const Record<ESM::Clothing>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Clothing)));
if (column==mType)
return record.get().mData.mType;
return EnchantableRefIdAdapter<ESM::Clothing>::getData (column, data, index);
}
void CSMWorld::ClothingRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Clothing>& record = static_cast<Record<ESM::Clothing>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Clothing)));
if (column==mType)
record.get().mData.mType = value.toInt();
else
EnchantableRefIdAdapter<ESM::Clothing>::setData (column, data, index, value);
}
CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& columns,
const RefIdColumn *weight, const RefIdColumn *organic, const RefIdColumn *respawn)
: NameRefIdAdapter<ESM::Container> (UniversalId::Type_Container, columns), mWeight (weight),
mOrganic (organic), mRespawn (respawn)
{}
QVariant CSMWorld::ContainerRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Container>& record = static_cast<const Record<ESM::Container>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container)));
if (column==mWeight)
return record.get().mWeight;
if (column==mOrganic)
return (record.get().mFlags & ESM::Container::Organic)!=0;
if (column==mRespawn)
return (record.get().mFlags & ESM::Container::Respawn)!=0;
return NameRefIdAdapter<ESM::Container>::getData (column, data, index);
}
void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Container>& record = static_cast<Record<ESM::Container>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container)));
if (column==mWeight)
record.get().mWeight = value.toFloat();
else if (column==mOrganic)
{
if (value.toInt())
record.get().mFlags |= ESM::Container::Organic;
else
record.get().mFlags &= ~ESM::Container::Organic;
}
else if (column==mRespawn)
{
if (value.toInt())
record.get().mFlags |= ESM::Container::Respawn;
else
record.get().mFlags &= ~ESM::Container::Respawn;
}
else
NameRefIdAdapter<ESM::Container>::setData (column, data, index, value);
}
CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns)
: ActorColumns (actorColumns)
{}
CSMWorld::CreatureRefIdAdapter::CreatureRefIdAdapter (const CreatureColumns& columns)
: ActorRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature, columns), mColumns (columns)
{}
QVariant CSMWorld::CreatureRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Creature>& record = static_cast<const Record<ESM::Creature>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
if (column==mColumns.mType)
return record.get().mData.mType;
if (column==mColumns.mSoul)
return record.get().mData.mSoul;
if (column==mColumns.mScale)
return record.get().mScale;
if (column==mColumns.mOriginal)
return QString::fromUtf8 (record.get().mOriginal.c_str());
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
return (record.get().mFlags & iter->second)!=0;
return ActorRefIdAdapter<ESM::Creature>::getData (column, data, index);
}
void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Creature>& record = static_cast<Record<ESM::Creature>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
if (column==mColumns.mType)
record.get().mData.mType = value.toInt();
else if (column==mColumns.mSoul)
record.get().mData.mSoul = value.toInt();
else if (column==mColumns.mScale)
record.get().mScale = value.toFloat();
else if (column==mColumns.mOriginal)
record.get().mOriginal = value.toString().toUtf8().constData();
else
{
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
{
if (value.toInt()!=0)
record.get().mFlags |= iter->second;
else
record.get().mFlags &= ~iter->second;
}
else
ActorRefIdAdapter<ESM::Creature>::setData (column, data, index, value);
}
}
CSMWorld::DoorRefIdAdapter::DoorRefIdAdapter (const NameColumns& columns,
const RefIdColumn *openSound, const RefIdColumn *closeSound)
: NameRefIdAdapter<ESM::Door> (UniversalId::Type_Door, columns), mOpenSound (openSound),
mCloseSound (closeSound)
{}
QVariant CSMWorld::DoorRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Door>& record = static_cast<const Record<ESM::Door>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Door)));
if (column==mOpenSound)
return QString::fromUtf8 (record.get().mOpenSound.c_str());
if (column==mCloseSound)
return QString::fromUtf8 (record.get().mCloseSound.c_str());
return NameRefIdAdapter<ESM::Door>::getData (column, data, index);
}
void CSMWorld::DoorRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Door>& record = static_cast<Record<ESM::Door>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Door)));
if (column==mOpenSound)
record.get().mOpenSound = value.toString().toUtf8().constData();
else if (column==mCloseSound)
record.get().mCloseSound = value.toString().toUtf8().constData();
else
NameRefIdAdapter<ESM::Door>::setData (column, data, index, value);
}
CSMWorld::LightColumns::LightColumns (const InventoryColumns& columns)
: InventoryColumns (columns) {}
CSMWorld::LightRefIdAdapter::LightRefIdAdapter (const LightColumns& columns)
: InventoryRefIdAdapter<ESM::Light> (UniversalId::Type_Light, columns), mColumns (columns)
{}
QVariant CSMWorld::LightRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Light>& record = static_cast<const Record<ESM::Light>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Light)));
if (column==mColumns.mTime)
return record.get().mData.mTime;
if (column==mColumns.mRadius)
return record.get().mData.mRadius;
if (column==mColumns.mColor)
return record.get().mData.mColor;
if (column==mColumns.mSound)
return QString::fromUtf8 (record.get().mSound.c_str());
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
return (record.get().mData.mFlags & iter->second)!=0;
return InventoryRefIdAdapter<ESM::Light>::getData (column, data, index);
}
void CSMWorld::LightRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Light>& record = static_cast<Record<ESM::Light>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Light)));
if (column==mColumns.mTime)
record.get().mData.mTime = value.toInt();
else if (column==mColumns.mRadius)
record.get().mData.mRadius = value.toInt();
else if (column==mColumns.mColor)
record.get().mData.mColor = value.toInt();
else if (column==mColumns.mSound)
record.get().mSound = value.toString().toUtf8().constData();
else
{
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
{
if (value.toInt()!=0)
record.get().mData.mFlags |= iter->second;
else
record.get().mData.mFlags &= ~iter->second;
}
else
InventoryRefIdAdapter<ESM::Light>::setData (column, data, index, value);
}
}
CSMWorld::MiscRefIdAdapter::MiscRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *key)
: InventoryRefIdAdapter<ESM::Miscellaneous> (UniversalId::Type_Miscellaneous, columns), mKey (key)
{}
QVariant CSMWorld::MiscRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Miscellaneous>& record = static_cast<const Record<ESM::Miscellaneous>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Miscellaneous)));
if (column==mKey)
return record.get().mData.mIsKey!=0;
return InventoryRefIdAdapter<ESM::Miscellaneous>::getData (column, data, index);
}
void CSMWorld::MiscRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Miscellaneous>& record = static_cast<Record<ESM::Miscellaneous>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Miscellaneous)));
if (column==mKey)
record.get().mData.mIsKey = value.toInt();
else
InventoryRefIdAdapter<ESM::Miscellaneous>::setData (column, data, index, value);
}
CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns) : ActorColumns (actorColumns) {}
CSMWorld::NpcRefIdAdapter::NpcRefIdAdapter (const NpcColumns& columns)
: ActorRefIdAdapter<ESM::NPC> (UniversalId::Type_Npc, columns), mColumns (columns)
{}
QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data, int index)
const
{
const Record<ESM::NPC>& record = static_cast<const Record<ESM::NPC>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
if (column==mColumns.mRace)
return QString::fromUtf8 (record.get().mRace.c_str());
if (column==mColumns.mClass)
return QString::fromUtf8 (record.get().mClass.c_str());
if (column==mColumns.mFaction)
return QString::fromUtf8 (record.get().mFaction.c_str());
if (column==mColumns.mHair)
return QString::fromUtf8 (record.get().mHair.c_str());
if (column==mColumns.mHead)
return QString::fromUtf8 (record.get().mHead.c_str());
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
return (record.get().mFlags & iter->second)!=0;
return ActorRefIdAdapter<ESM::NPC>::getData (column, data, index);
}
void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::NPC>& record = static_cast<Record<ESM::NPC>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
if (column==mColumns.mRace)
record.get().mRace = value.toString().toUtf8().constData();
else if (column==mColumns.mClass)
record.get().mClass = value.toString().toUtf8().constData();
else if (column==mColumns.mFaction)
record.get().mFaction = value.toString().toUtf8().constData();
else if (column==mColumns.mHair)
record.get().mHair = value.toString().toUtf8().constData();
else if (column==mColumns.mHead)
record.get().mHead = value.toString().toUtf8().constData();
else
{
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
{
if (value.toInt()!=0)
record.get().mFlags |= iter->second;
else
record.get().mFlags &= ~iter->second;
}
else
ActorRefIdAdapter<ESM::NPC>::setData (column, data, index, value);
}
}
CSMWorld::WeaponColumns::WeaponColumns (const EnchantableColumns& columns)
: EnchantableColumns (columns) {}
CSMWorld::WeaponRefIdAdapter::WeaponRefIdAdapter (const WeaponColumns& columns)
: EnchantableRefIdAdapter<ESM::Weapon> (UniversalId::Type_Weapon, columns), mColumns (columns)
{}
QVariant CSMWorld::WeaponRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Weapon>& record = static_cast<const Record<ESM::Weapon>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Weapon)));
if (column==mColumns.mType)
return record.get().mData.mType;
if (column==mColumns.mHealth)
return record.get().mData.mHealth;
if (column==mColumns.mSpeed)
return record.get().mData.mSpeed;
if (column==mColumns.mReach)
return record.get().mData.mReach;
for (int i=0; i<2; ++i)
{
if (column==mColumns.mChop[i])
return record.get().mData.mChop[i];
if (column==mColumns.mSlash[i])
return record.get().mData.mSlash[i];
if (column==mColumns.mThrust[i])
return record.get().mData.mThrust[i];
}
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
return (record.get().mData.mFlags & iter->second)!=0;
return EnchantableRefIdAdapter<ESM::Weapon>::getData (column, data, index);
}
void CSMWorld::WeaponRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Weapon>& record = static_cast<Record<ESM::Weapon>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Weapon)));
if (column==mColumns.mType)
record.get().mData.mType = value.toInt();
else if (column==mColumns.mHealth)
record.get().mData.mHealth = value.toInt();
else if (column==mColumns.mSpeed)
record.get().mData.mSpeed = value.toFloat();
else if (column==mColumns.mReach)
record.get().mData.mReach = value.toFloat();
else if (column==mColumns.mChop[0])
record.get().mData.mChop[0] = value.toInt();
else if (column==mColumns.mChop[1])
record.get().mData.mChop[1] = value.toInt();
else if (column==mColumns.mSlash[0])
record.get().mData.mSlash[0] = value.toInt();
else if (column==mColumns.mSlash[1])
record.get().mData.mSlash[1] = value.toInt();
else if (column==mColumns.mThrust[0])
record.get().mData.mThrust[0] = value.toInt();
else if (column==mColumns.mThrust[1])
record.get().mData.mThrust[1] = value.toInt();
else
{
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
{
if (value.toInt()!=0)
record.get().mData.mFlags |= iter->second;
else
record.get().mData.mFlags &= ~iter->second;
}
else
EnchantableRefIdAdapter<ESM::Weapon>::setData (column, data, index, value);
}
}

@ -0,0 +1,766 @@
#ifndef CSM_WOLRD_REFIDADAPTERIMP_H
#define CSM_WOLRD_REFIDADAPTERIMP_H
#include <map>
#include <QVariant>
#include <components/esm/loadalch.hpp>
#include <components/esm/loadappa.hpp>
#include "record.hpp"
#include "refiddata.hpp"
#include "universalid.hpp"
#include "refidadapter.hpp"
namespace CSMWorld
{
struct BaseColumns
{
const RefIdColumn *mId;
const RefIdColumn *mModified;
const RefIdColumn *mType;
};
/// \brief Base adapter for all refereceable record types
template<typename RecordT>
class BaseRefIdAdapter : public RefIdAdapter
{
UniversalId::Type mType;
BaseColumns mBase;
public:
BaseRefIdAdapter (UniversalId::Type type, const BaseColumns& base);
virtual std::string getId (const RecordBase& record) const;
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
UniversalId::Type getType() const;
};
template<typename RecordT>
BaseRefIdAdapter<RecordT>::BaseRefIdAdapter (UniversalId::Type type, const BaseColumns& base)
: mType (type), mBase (base)
{}
template<typename RecordT>
std::string BaseRefIdAdapter<RecordT>::getId (const RecordBase& record) const
{
return dynamic_cast<const Record<RecordT>&> (record).get().mId;
}
template<typename RecordT>
QVariant BaseRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, mType)));
if (column==mBase.mId)
return QString::fromUtf8 (record.get().mId.c_str());
if (column==mBase.mModified)
{
if (record.mState==Record<RecordT>::State_Erased)
return static_cast<int> (Record<RecordT>::State_Deleted);
return static_cast<int> (record.mState);
}
if (column==mBase.mType)
return static_cast<int> (mType);
return QVariant();
}
template<typename RecordT>
void BaseRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, mType)));
if (column==mBase.mModified)
record.mState = static_cast<RecordBase::State> (value.toInt());
}
template<typename RecordT>
UniversalId::Type BaseRefIdAdapter<RecordT>::getType() const
{
return mType;
}
struct ModelColumns : public BaseColumns
{
const RefIdColumn *mModel;
ModelColumns (const BaseColumns& base) : BaseColumns (base) {}
};
/// \brief Adapter for IDs with models (all but levelled lists)
template<typename RecordT>
class ModelRefIdAdapter : public BaseRefIdAdapter<RecordT>
{
ModelColumns mModel;
public:
ModelRefIdAdapter (UniversalId::Type type, const ModelColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
template<typename RecordT>
ModelRefIdAdapter<RecordT>::ModelRefIdAdapter (UniversalId::Type type, const ModelColumns& columns)
: BaseRefIdAdapter<RecordT> (type, columns), mModel (columns)
{}
template<typename RecordT>
QVariant ModelRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mModel.mModel)
return QString::fromUtf8 (record.get().mModel.c_str());
return BaseRefIdAdapter<RecordT>::getData (column, data, index);
}
template<typename RecordT>
void ModelRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mModel.mModel)
record.get().mModel = value.toString().toUtf8().constData();
else
BaseRefIdAdapter<RecordT>::setData (column, data, index, value);
}
struct NameColumns : public ModelColumns
{
const RefIdColumn *mName;
const RefIdColumn *mScript;
NameColumns (const ModelColumns& base) : ModelColumns (base) {}
};
/// \brief Adapter for IDs with names (all but levelled lists and statics)
template<typename RecordT>
class NameRefIdAdapter : public ModelRefIdAdapter<RecordT>
{
NameColumns mName;
public:
NameRefIdAdapter (UniversalId::Type type, const NameColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
template<typename RecordT>
NameRefIdAdapter<RecordT>::NameRefIdAdapter (UniversalId::Type type, const NameColumns& columns)
: ModelRefIdAdapter<RecordT> (type, columns), mName (columns)
{}
template<typename RecordT>
QVariant NameRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mName.mName)
return QString::fromUtf8 (record.get().mName.c_str());
if (column==mName.mScript)
return QString::fromUtf8 (record.get().mScript.c_str());
return ModelRefIdAdapter<RecordT>::getData (column, data, index);
}
template<typename RecordT>
void NameRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mName.mName)
record.get().mName = value.toString().toUtf8().constData();
else if (column==mName.mScript)
record.get().mScript = value.toString().toUtf8().constData();
else
ModelRefIdAdapter<RecordT>::setData (column, data, index, value);
}
struct InventoryColumns : public NameColumns
{
const RefIdColumn *mIcon;
const RefIdColumn *mWeight;
const RefIdColumn *mValue;
InventoryColumns (const NameColumns& base) : NameColumns (base) {}
};
/// \brief Adapter for IDs that can go into an inventory
template<typename RecordT>
class InventoryRefIdAdapter : public NameRefIdAdapter<RecordT>
{
InventoryColumns mInventory;
public:
InventoryRefIdAdapter (UniversalId::Type type, const InventoryColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
template<typename RecordT>
InventoryRefIdAdapter<RecordT>::InventoryRefIdAdapter (UniversalId::Type type,
const InventoryColumns& columns)
: NameRefIdAdapter<RecordT> (type, columns), mInventory (columns)
{}
template<typename RecordT>
QVariant InventoryRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mInventory.mIcon)
return QString::fromUtf8 (record.get().mIcon.c_str());
if (column==mInventory.mWeight)
return record.get().mData.mWeight;
if (column==mInventory.mValue)
return record.get().mData.mValue;
return NameRefIdAdapter<RecordT>::getData (column, data, index);
}
template<typename RecordT>
void InventoryRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mInventory.mIcon)
record.get().mIcon = value.toString().toUtf8().constData();
else if (column==mInventory.mWeight)
record.get().mData.mWeight = value.toFloat();
else if (column==mInventory.mValue)
record.get().mData.mValue = value.toInt();
else
NameRefIdAdapter<RecordT>::setData (column, data, index, value);
}
class PotionRefIdAdapter : public InventoryRefIdAdapter<ESM::Potion>
{
const RefIdColumn *mAutoCalc;
public:
PotionRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *autoCalc);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
struct EnchantableColumns : public InventoryColumns
{
const RefIdColumn *mEnchantment;
const RefIdColumn *mEnchantmentPoints;
EnchantableColumns (const InventoryColumns& base) : InventoryColumns (base) {}
};
/// \brief Adapter for enchantable IDs
template<typename RecordT>
class EnchantableRefIdAdapter : public InventoryRefIdAdapter<RecordT>
{
EnchantableColumns mEnchantable;
public:
EnchantableRefIdAdapter (UniversalId::Type type, const EnchantableColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
template<typename RecordT>
EnchantableRefIdAdapter<RecordT>::EnchantableRefIdAdapter (UniversalId::Type type,
const EnchantableColumns& columns)
: InventoryRefIdAdapter<RecordT> (type, columns), mEnchantable (columns)
{}
template<typename RecordT>
QVariant EnchantableRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mEnchantable.mEnchantment)
return QString::fromUtf8 (record.get().mEnchant.c_str());
if (column==mEnchantable.mEnchantmentPoints)
return static_cast<int> (record.get().mData.mEnchant);
return InventoryRefIdAdapter<RecordT>::getData (column, data, index);
}
template<typename RecordT>
void EnchantableRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data,
int index, const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mEnchantable.mEnchantment)
record.get().mEnchant = value.toString().toUtf8().constData();
else if (column==mEnchantable.mEnchantmentPoints)
record.get().mData.mEnchant = value.toInt();
else
InventoryRefIdAdapter<RecordT>::setData (column, data, index, value);
}
struct ToolColumns : public InventoryColumns
{
const RefIdColumn *mQuality;
const RefIdColumn *mUses;
ToolColumns (const InventoryColumns& base) : InventoryColumns (base) {}
};
/// \brief Adapter for tools with limited uses IDs (lockpick, repair, probes)
template<typename RecordT>
class ToolRefIdAdapter : public InventoryRefIdAdapter<RecordT>
{
ToolColumns mTools;
public:
ToolRefIdAdapter (UniversalId::Type type, const ToolColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
template<typename RecordT>
ToolRefIdAdapter<RecordT>::ToolRefIdAdapter (UniversalId::Type type, const ToolColumns& columns)
: InventoryRefIdAdapter<RecordT> (type, columns), mTools (columns)
{}
template<typename RecordT>
QVariant ToolRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mTools.mQuality)
return record.get().mData.mQuality;
if (column==mTools.mUses)
return record.get().mData.mUses;
return InventoryRefIdAdapter<RecordT>::getData (column, data, index);
}
template<typename RecordT>
void ToolRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data,
int index, const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mTools.mQuality)
record.get().mData.mQuality = value.toFloat();
else if (column==mTools.mUses)
record.get().mData.mUses = value.toInt();
else
InventoryRefIdAdapter<RecordT>::setData (column, data, index, value);
}
struct ActorColumns : public NameColumns
{
const RefIdColumn *mHasAi;
const RefIdColumn *mHello;
const RefIdColumn *mFlee;
const RefIdColumn *mFight;
const RefIdColumn *mAlarm;
std::map<const RefIdColumn *, unsigned int> mServices;
ActorColumns (const NameColumns& base) : NameColumns (base) {}
};
/// \brief Adapter for actor IDs (handles common AI functionality)
template<typename RecordT>
class ActorRefIdAdapter : public NameRefIdAdapter<RecordT>
{
ActorColumns mActors;
public:
ActorRefIdAdapter (UniversalId::Type type, const ActorColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
template<typename RecordT>
ActorRefIdAdapter<RecordT>::ActorRefIdAdapter (UniversalId::Type type,
const ActorColumns& columns)
: NameRefIdAdapter<RecordT> (type, columns), mActors (columns)
{}
template<typename RecordT>
QVariant ActorRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mActors.mHasAi)
return record.get().mHasAI!=0;
if (column==mActors.mHello)
return record.get().mAiData.mHello;
if (column==mActors.mFlee)
return record.get().mAiData.mFlee;
if (column==mActors.mFight)
return record.get().mAiData.mFight;
if (column==mActors.mAlarm)
return record.get().mAiData.mAlarm;
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mActors.mServices.find (column);
if (iter!=mActors.mServices.end())
return (record.get().mAiData.mServices & iter->second)!=0;
return NameRefIdAdapter<RecordT>::getData (column, data, index);
}
template<typename RecordT>
void ActorRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mActors.mHasAi)
record.get().mHasAI = value.toInt();
else if (column==mActors.mHello)
record.get().mAiData.mHello = value.toInt();
else if (column==mActors.mFlee)
record.get().mAiData.mFlee = value.toInt();
else if (column==mActors.mFight)
record.get().mAiData.mFight = value.toInt();
else if (column==mActors.mAlarm)
record.get().mAiData.mAlarm = value.toInt();
else
{
typename std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mActors.mServices.find (column);
if (iter!=mActors.mServices.end())
{
if (value.toInt()!=0)
record.get().mAiData.mServices |= iter->second;
else
record.get().mAiData.mServices &= ~iter->second;
}
else
NameRefIdAdapter<RecordT>::setData (column, data, index, value);
}
}
class ApparatusRefIdAdapter : public InventoryRefIdAdapter<ESM::Apparatus>
{
const RefIdColumn *mType;
const RefIdColumn *mQuality;
public:
ApparatusRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *type,
const RefIdColumn *quality);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
class ArmorRefIdAdapter : public EnchantableRefIdAdapter<ESM::Armor>
{
const RefIdColumn *mType;
const RefIdColumn *mHealth;
const RefIdColumn *mArmor;
public:
ArmorRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *type,
const RefIdColumn *health, const RefIdColumn *armor);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
class BookRefIdAdapter : public EnchantableRefIdAdapter<ESM::Book>
{
const RefIdColumn *mScroll;
const RefIdColumn *mSkill;
public:
BookRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *scroll,
const RefIdColumn *skill);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
class ClothingRefIdAdapter : public EnchantableRefIdAdapter<ESM::Clothing>
{
const RefIdColumn *mType;
public:
ClothingRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *type);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
class ContainerRefIdAdapter : public NameRefIdAdapter<ESM::Container>
{
const RefIdColumn *mWeight;
const RefIdColumn *mOrganic;
const RefIdColumn *mRespawn;
public:
ContainerRefIdAdapter (const NameColumns& columns, const RefIdColumn *weight,
const RefIdColumn *organic, const RefIdColumn *respawn);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
struct CreatureColumns : public ActorColumns
{
std::map<const RefIdColumn *, unsigned int> mFlags;
const RefIdColumn *mType;
const RefIdColumn *mSoul;
const RefIdColumn *mScale;
const RefIdColumn *mOriginal;
CreatureColumns (const ActorColumns& actorColumns);
};
class CreatureRefIdAdapter : public ActorRefIdAdapter<ESM::Creature>
{
CreatureColumns mColumns;
public:
CreatureRefIdAdapter (const CreatureColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
class DoorRefIdAdapter : public NameRefIdAdapter<ESM::Door>
{
const RefIdColumn *mOpenSound;
const RefIdColumn *mCloseSound;
public:
DoorRefIdAdapter (const NameColumns& columns, const RefIdColumn *openSound,
const RefIdColumn *closeSound);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
struct LightColumns : public InventoryColumns
{
const RefIdColumn *mTime;
const RefIdColumn *mRadius;
const RefIdColumn *mColor;
const RefIdColumn *mSound;
std::map<const RefIdColumn *, unsigned int> mFlags;
LightColumns (const InventoryColumns& columns);
};
class LightRefIdAdapter : public InventoryRefIdAdapter<ESM::Light>
{
LightColumns mColumns;
public:
LightRefIdAdapter (const LightColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
class MiscRefIdAdapter : public InventoryRefIdAdapter<ESM::Miscellaneous>
{
const RefIdColumn *mKey;
public:
MiscRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *key);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
struct NpcColumns : public ActorColumns
{
std::map<const RefIdColumn *, unsigned int> mFlags;
const RefIdColumn *mRace;
const RefIdColumn *mClass;
const RefIdColumn *mFaction;
const RefIdColumn *mHair;
const RefIdColumn *mHead;
NpcColumns (const ActorColumns& actorColumns);
};
class NpcRefIdAdapter : public ActorRefIdAdapter<ESM::NPC>
{
NpcColumns mColumns;
public:
NpcRefIdAdapter (const NpcColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
struct WeaponColumns : public EnchantableColumns
{
const RefIdColumn *mType;
const RefIdColumn *mHealth;
const RefIdColumn *mSpeed;
const RefIdColumn *mReach;
const RefIdColumn *mChop[2];
const RefIdColumn *mSlash[2];
const RefIdColumn *mThrust[2];
std::map<const RefIdColumn *, unsigned int> mFlags;
WeaponColumns (const EnchantableColumns& columns);
};
class WeaponRefIdAdapter : public EnchantableRefIdAdapter<ESM::Weapon>
{
WeaponColumns mColumns;
public:
WeaponRefIdAdapter (const WeaponColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
}
#endif

@ -0,0 +1,540 @@
#include "refidcollection.hpp"
#include <stdexcept>
#include "refidadapter.hpp"
#include "refidadapterimp.hpp"
CSMWorld::RefIdColumn::RefIdColumn (const std::string& title, Display displayType, int flag,
bool editable, bool userEditable)
: ColumnBase (title, displayType, flag), mEditable (editable), mUserEditable (userEditable)
{}
bool CSMWorld::RefIdColumn::isEditable() const
{
return mEditable;
}
bool CSMWorld::RefIdColumn::isUserEditable() const
{
return mUserEditable;
}
const CSMWorld::RefIdAdapter& CSMWorld::RefIdCollection::findAdaptor (UniversalId::Type type) const
{
std::map<UniversalId::Type, RefIdAdapter *>::const_iterator iter = mAdapters.find (type);
if (iter==mAdapters.end())
throw std::logic_error ("unsupported type in RefIdCollection");
return *iter->second;
}
CSMWorld::RefIdCollection::RefIdCollection()
{
BaseColumns baseColumns;
mColumns.push_back (RefIdColumn ("ID", ColumnBase::Display_String,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
baseColumns.mId = &mColumns.back();
mColumns.push_back (RefIdColumn ("*", ColumnBase::Display_Integer,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
baseColumns.mModified = &mColumns.back();
mColumns.push_back (RefIdColumn ("Type", ColumnBase::Display_Integer,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
baseColumns.mType = &mColumns.back();
ModelColumns modelColumns (baseColumns);
mColumns.push_back (RefIdColumn ("Model", ColumnBase::Display_String));
modelColumns.mModel = &mColumns.back();
NameColumns nameColumns (modelColumns);
mColumns.push_back (RefIdColumn ("Name", ColumnBase::Display_String));
nameColumns.mName = &mColumns.back();
mColumns.push_back (RefIdColumn ("Script", ColumnBase::Display_String));
nameColumns.mScript = &mColumns.back();
InventoryColumns inventoryColumns (nameColumns);
mColumns.push_back (RefIdColumn ("Icon", ColumnBase::Display_String));
inventoryColumns.mIcon = &mColumns.back();
mColumns.push_back (RefIdColumn ("Weight", ColumnBase::Display_Float));
inventoryColumns.mWeight = &mColumns.back();
mColumns.push_back (RefIdColumn ("Value", ColumnBase::Display_Integer));
inventoryColumns.mValue = &mColumns.back();
EnchantableColumns enchantableColumns (inventoryColumns);
mColumns.push_back (RefIdColumn ("Enchantment", ColumnBase::Display_String));
enchantableColumns.mEnchantment = &mColumns.back();
mColumns.push_back (RefIdColumn ("Enchantment Points", ColumnBase::Display_Integer));
enchantableColumns.mEnchantmentPoints = &mColumns.back();
ToolColumns toolsColumns (inventoryColumns);
mColumns.push_back (RefIdColumn ("Quality", ColumnBase::Display_Float));
toolsColumns.mQuality = &mColumns.back();
mColumns.push_back (RefIdColumn ("Uses", ColumnBase::Display_Integer));
toolsColumns.mUses = &mColumns.back();
ActorColumns actorsColumns (nameColumns);
mColumns.push_back (RefIdColumn ("AI", ColumnBase::Display_Boolean));
actorsColumns.mHasAi = &mColumns.back();
mColumns.push_back (RefIdColumn ("AI Hello", ColumnBase::Display_Integer));
actorsColumns.mHello = &mColumns.back();
mColumns.push_back (RefIdColumn ("AI Flee", ColumnBase::Display_Integer));
actorsColumns.mFlee = &mColumns.back();
mColumns.push_back (RefIdColumn ("AI Fight", ColumnBase::Display_Integer));
actorsColumns.mFight = &mColumns.back();
mColumns.push_back (RefIdColumn ("AI Alarm", ColumnBase::Display_Integer));
actorsColumns.mAlarm = &mColumns.back();
static const struct
{
const char *mName;
unsigned int mFlag;
} sServiceTable[] =
{
{ "Buys Weapons", ESM::NPC::Weapon},
{ "Buys Armor", ESM::NPC::Armor},
{ "Buys Clothing", ESM::NPC::Clothing},
{ "Buys Books", ESM::NPC::Books},
{ "Buys Ingredients", ESM::NPC::Ingredients},
{ "Buys Lockpicks", ESM::NPC::Picks},
{ "Buys Probes", ESM::NPC::Probes},
{ "Buys Lights", ESM::NPC::Lights},
{ "Buys Apparati", ESM::NPC::Apparatus},
{ "Buys Repair Items", ESM::NPC::RepairItem},
{ "Buys Misc Items", ESM::NPC::Misc},
{ "Buys Potions", ESM::NPC::Potions},
{ "Buys Magic Items", ESM::NPC::MagicItems},
{ "Sells Spells", ESM::NPC::Spells},
{ "Trainer", ESM::NPC::Training},
{ "Spellmaking", ESM::NPC::Spellmaking},
{ "Enchanting Service", ESM::NPC::Enchanting},
{ "Repair Serivce", ESM::NPC::Repair},
{ 0, 0 }
};
for (int i=0; sServiceTable[i].mName; ++i)
{
mColumns.push_back (RefIdColumn (sServiceTable[i].mName, ColumnBase::Display_Boolean));
actorsColumns.mServices.insert (std::make_pair (&mColumns.back(), sServiceTable[i].mFlag));
}
mColumns.push_back (RefIdColumn ("Auto Calc", ColumnBase::Display_Boolean));
const RefIdColumn *autoCalc = &mColumns.back();
mColumns.push_back (RefIdColumn ("Apparatus Type", ColumnBase::Display_ApparatusType));
const RefIdColumn *apparatusType = &mColumns.back();
mColumns.push_back (RefIdColumn ("Armor Type", ColumnBase::Display_ArmorType));
const RefIdColumn *armorType = &mColumns.back();
mColumns.push_back (RefIdColumn ("Health", ColumnBase::Display_Integer));
const RefIdColumn *health = &mColumns.back();
mColumns.push_back (RefIdColumn ("Armor Value", ColumnBase::Display_Integer));
const RefIdColumn *armor = &mColumns.back();
mColumns.push_back (RefIdColumn ("Scroll", ColumnBase::Display_Boolean));
const RefIdColumn *scroll = &mColumns.back();
mColumns.push_back (RefIdColumn ("Attribute", ColumnBase::Display_Attribute));
const RefIdColumn *attribute = &mColumns.back();
mColumns.push_back (RefIdColumn ("Clothing Type", ColumnBase::Display_ClothingType));
const RefIdColumn *clothingType = &mColumns.back();
mColumns.push_back (RefIdColumn ("Weight Capacity", ColumnBase::Display_Float));
const RefIdColumn *weightCapacity = &mColumns.back();
mColumns.push_back (RefIdColumn ("Organic Container", ColumnBase::Display_Boolean));
const RefIdColumn *organic = &mColumns.back();
mColumns.push_back (RefIdColumn ("Respawn", ColumnBase::Display_Boolean));
const RefIdColumn *respawn = &mColumns.back();
CreatureColumns creatureColumns (actorsColumns);
mColumns.push_back (RefIdColumn ("Creature Type", ColumnBase::Display_CreatureType));
creatureColumns.mType = &mColumns.back();
mColumns.push_back (RefIdColumn ("Soul Points", ColumnBase::Display_Integer));
creatureColumns.mSoul = &mColumns.back();
mColumns.push_back (RefIdColumn ("Scale", ColumnBase::Display_Float));
creatureColumns.mScale = &mColumns.back();
mColumns.push_back (RefIdColumn ("Original Creature", ColumnBase::Display_String));
creatureColumns.mOriginal = &mColumns.back();
static const struct
{
const char *mName;
unsigned int mFlag;
} sCreatureFlagTable[] =
{
{ "Biped", ESM::Creature::Biped },
{ "Has Weapon", ESM::Creature::Weapon },
{ "No Movement", ESM::Creature::None },
{ "Swims", ESM::Creature::Swims },
{ "Flies", ESM::Creature::Flies },
{ "Walks", ESM::Creature::Walks },
{ "Essential", ESM::Creature::Essential },
{ "Skeleton Blood", ESM::Creature::Skeleton },
{ "Metal Blood", ESM::Creature::Metal },
{ 0, 0 }
};
// for re-use in NPC records
const RefIdColumn *essential = 0;
const RefIdColumn *skeletonBlood = 0;
const RefIdColumn *metalBlood = 0;
for (int i=0; sCreatureFlagTable[i].mName; ++i)
{
mColumns.push_back (RefIdColumn (sCreatureFlagTable[i].mName, ColumnBase::Display_Boolean));
creatureColumns.mFlags.insert (std::make_pair (&mColumns.back(), sCreatureFlagTable[i].mFlag));
switch (sCreatureFlagTable[i].mFlag)
{
case ESM::Creature::Essential: essential = &mColumns.back(); break;
case ESM::Creature::Skeleton: skeletonBlood = &mColumns.back(); break;
case ESM::Creature::Metal: metalBlood = &mColumns.back(); break;
}
}
creatureColumns.mFlags.insert (std::make_pair (respawn, ESM::Creature::Respawn));
mColumns.push_back (RefIdColumn ("Open Sound", ColumnBase::Display_String));
const RefIdColumn *openSound = &mColumns.back();
mColumns.push_back (RefIdColumn ("Close Sound", ColumnBase::Display_String));
const RefIdColumn *closeSound = &mColumns.back();
LightColumns lightColumns (inventoryColumns);
mColumns.push_back (RefIdColumn ("Duration", ColumnBase::Display_Integer));
lightColumns.mTime = &mColumns.back();
mColumns.push_back (RefIdColumn ("Radius", ColumnBase::Display_Integer));
lightColumns.mRadius = &mColumns.back();
mColumns.push_back (RefIdColumn ("Colour", ColumnBase::Display_Integer));
lightColumns.mColor = &mColumns.back();
mColumns.push_back (RefIdColumn ("Sound", ColumnBase::Display_String));
lightColumns.mSound = &mColumns.back();
static const struct
{
const char *mName;
unsigned int mFlag;
} sLightFlagTable[] =
{
{ "Dynamic", ESM::Light::Dynamic },
{ "Portable", ESM::Light::Carry },
{ "Negative Light", ESM::Light::Negative },
{ "Flickering", ESM::Light::Flicker },
{ "Slow Flickering", ESM::Light::Flicker },
{ "Pulsing", ESM::Light::Pulse },
{ "Slow Pulsing", ESM::Light::PulseSlow },
{ "Fire", ESM::Light::Fire },
{ "Off by default", ESM::Light::OffDefault },
{ 0, 0 }
};
for (int i=0; sLightFlagTable[i].mName; ++i)
{
mColumns.push_back (RefIdColumn (sLightFlagTable[i].mName, ColumnBase::Display_Boolean));
lightColumns.mFlags.insert (std::make_pair (&mColumns.back(), sLightFlagTable[i].mFlag));
}
mColumns.push_back (RefIdColumn ("Key", ColumnBase::Display_Boolean));
const RefIdColumn *key = &mColumns.back();
NpcColumns npcColumns (actorsColumns);
mColumns.push_back (RefIdColumn ("Race", ColumnBase::Display_String));
npcColumns.mRace = &mColumns.back();
mColumns.push_back (RefIdColumn ("Class", ColumnBase::Display_String));
npcColumns.mClass = &mColumns.back();
mColumns.push_back (RefIdColumn ("Faction", ColumnBase::Display_String));
npcColumns.mFaction = &mColumns.back();
mColumns.push_back (RefIdColumn ("Hair", ColumnBase::Display_String));
npcColumns.mHair = &mColumns.back();
mColumns.push_back (RefIdColumn ("Head", ColumnBase::Display_String));
npcColumns.mHead = &mColumns.back();
mColumns.push_back (RefIdColumn ("Female", ColumnBase::Display_Boolean));
npcColumns.mFlags.insert (std::make_pair (&mColumns.back(), ESM::NPC::Female));
npcColumns.mFlags.insert (std::make_pair (essential, ESM::NPC::Essential));
npcColumns.mFlags.insert (std::make_pair (respawn, ESM::NPC::Respawn));
npcColumns.mFlags.insert (std::make_pair (autoCalc, ESM::NPC::Autocalc));
npcColumns.mFlags.insert (std::make_pair (skeletonBlood, ESM::NPC::Skeleton));
npcColumns.mFlags.insert (std::make_pair (metalBlood, ESM::NPC::Metal));
WeaponColumns weaponColumns (enchantableColumns);
mColumns.push_back (RefIdColumn ("Weapon Type", ColumnBase::Display_WeaponType));
weaponColumns.mType = &mColumns.back();
weaponColumns.mHealth = health;
mColumns.push_back (RefIdColumn ("Weapon Speed", ColumnBase::Display_Float));
weaponColumns.mSpeed = &mColumns.back();
mColumns.push_back (RefIdColumn ("Weapon Reach", ColumnBase::Display_Float));
weaponColumns.mReach = &mColumns.back();
for (int i=0; i<2; ++i)
{
std::string suffix = i==0 ? "Min " : "Max ";
mColumns.push_back (RefIdColumn ("Chop" + suffix, ColumnBase::Display_Integer));
weaponColumns.mChop[i] = &mColumns.back();
mColumns.push_back (RefIdColumn ("Slash" + suffix, ColumnBase::Display_Integer));
weaponColumns.mSlash[i] = &mColumns.back();
mColumns.push_back (RefIdColumn ("Thrust" + suffix, ColumnBase::Display_Integer));
weaponColumns.mThrust[i] = &mColumns.back();
}
static const struct
{
const char *mName;
unsigned int mFlag;
} sWeaponFlagTable[] =
{
{ "Magical", ESM::Weapon::Magical },
{ "Silver", ESM::Weapon::Silver },
{ 0, 0 }
};
for (int i=0; sWeaponFlagTable[i].mName; ++i)
{
mColumns.push_back (RefIdColumn (sWeaponFlagTable[i].mName, ColumnBase::Display_Boolean));
weaponColumns.mFlags.insert (std::make_pair (&mColumns.back(), sWeaponFlagTable[i].mFlag));
}
mAdapters.insert (std::make_pair (UniversalId::Type_Activator,
new NameRefIdAdapter<ESM::Activator> (UniversalId::Type_Activator, nameColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Potion,
new PotionRefIdAdapter (inventoryColumns, autoCalc)));
mAdapters.insert (std::make_pair (UniversalId::Type_Apparatus,
new ApparatusRefIdAdapter (inventoryColumns, apparatusType, toolsColumns.mQuality)));
mAdapters.insert (std::make_pair (UniversalId::Type_Armor,
new ArmorRefIdAdapter (enchantableColumns, armorType, health, armor)));
mAdapters.insert (std::make_pair (UniversalId::Type_Book,
new BookRefIdAdapter (enchantableColumns, scroll, attribute)));
mAdapters.insert (std::make_pair (UniversalId::Type_Clothing,
new ClothingRefIdAdapter (enchantableColumns, clothingType)));
mAdapters.insert (std::make_pair (UniversalId::Type_Container,
new ContainerRefIdAdapter (nameColumns, weightCapacity, organic, respawn)));
mAdapters.insert (std::make_pair (UniversalId::Type_Creature,
new CreatureRefIdAdapter (creatureColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Door,
new DoorRefIdAdapter (nameColumns, openSound, closeSound)));
mAdapters.insert (std::make_pair (UniversalId::Type_Ingredient,
new InventoryRefIdAdapter<ESM::Ingredient> (UniversalId::Type_Ingredient, inventoryColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_CreatureLevelledList,
new BaseRefIdAdapter<ESM::CreatureLevList> (
UniversalId::Type_CreatureLevelledList, baseColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_ItemLevelledList,
new BaseRefIdAdapter<ESM::ItemLevList> (UniversalId::Type_ItemLevelledList, baseColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Light,
new LightRefIdAdapter (lightColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Lockpick,
new ToolRefIdAdapter<ESM::Lockpick> (UniversalId::Type_Lockpick, toolsColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Miscellaneous,
new MiscRefIdAdapter (inventoryColumns, key)));
mAdapters.insert (std::make_pair (UniversalId::Type_Npc,
new NpcRefIdAdapter (npcColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Probe,
new ToolRefIdAdapter<ESM::Probe> (UniversalId::Type_Probe, toolsColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Repair,
new ToolRefIdAdapter<ESM::Repair> (UniversalId::Type_Repair, toolsColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Static,
new ModelRefIdAdapter<ESM::Static> (UniversalId::Type_Static, modelColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Weapon,
new WeaponRefIdAdapter (weaponColumns)));
}
CSMWorld::RefIdCollection::~RefIdCollection()
{
for (std::map<UniversalId::Type, RefIdAdapter *>::iterator iter (mAdapters.begin());
iter!=mAdapters.end(); ++iter)
delete iter->second;
}
int CSMWorld::RefIdCollection::getSize() const
{
return mData.getSize();
}
std::string CSMWorld::RefIdCollection::getId (int index) const
{
return getData (index, 0).toString().toUtf8().constData();
}
int CSMWorld::RefIdCollection::getIndex (const std::string& id) const
{
int index = searchId (id);
if (index==-1)
throw std::runtime_error ("invalid ID: " + id);
return index;
}
int CSMWorld::RefIdCollection::getColumns() const
{
return mColumns.size();
}
const CSMWorld::ColumnBase& CSMWorld::RefIdCollection::getColumn (int column) const
{
return mColumns.at (column);
}
QVariant CSMWorld::RefIdCollection::getData (int index, int column) const
{
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
const RefIdAdapter& adaptor = findAdaptor (localIndex.second);
return adaptor.getData (&mColumns.at (column), mData, localIndex.first);
}
void CSMWorld::RefIdCollection::setData (int index, int column, const QVariant& data)
{
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
const RefIdAdapter& adaptor = findAdaptor (localIndex.second);
adaptor.setData (&mColumns.at (column), mData, localIndex.first, data);
}
void CSMWorld::RefIdCollection::removeRows (int index, int count)
{
mData.erase (index, count);
}
void CSMWorld::RefIdCollection::appendBlankRecord (const std::string& id, UniversalId::Type type)
{
mData.appendRecord (type, id);
}
int CSMWorld::RefIdCollection::searchId (const std::string& id) const
{
RefIdData::LocalIndex localIndex = mData.searchId (id);
if (localIndex.first==-1)
return -1;
return mData.localToGlobalIndex (localIndex);
}
void CSMWorld::RefIdCollection::replace (int index, const RecordBase& record)
{
mData.getRecord (mData.globalToLocalIndex (index)).assign (record);
}
void CSMWorld::RefIdCollection::appendRecord (const RecordBase& record,
UniversalId::Type type)
{
std::string id = findAdaptor (type).getId (record);
int index = mData.getAppendIndex (type);
mData.appendRecord (type, id);
mData.getRecord (mData.globalToLocalIndex (index)).assign (record);
}
const CSMWorld::RecordBase& CSMWorld::RefIdCollection::getRecord (const std::string& id) const
{
return mData.getRecord (mData.searchId (id));
}
const CSMWorld::RecordBase& CSMWorld::RefIdCollection::getRecord (int index) const
{
return mData.getRecord (mData.globalToLocalIndex (index));
}
void CSMWorld::RefIdCollection::load (ESM::ESMReader& reader, bool base, UniversalId::Type type)
{
std::string id = reader.getHNOString ("NAME");
int index = searchId (id);
if (reader.isNextSub ("DELE"))
{
reader.skipRecord();
if (index==-1)
{
// deleting a record that does not exist
// ignore it for now
/// \todo report the problem to the user
}
else if (base)
{
mData.erase (index, 1);
}
else
{
mData.getRecord (mData.globalToLocalIndex (index)).mState = RecordBase::State_Deleted;
}
}
else
{
if (index==-1)
{
// new record
int index = mData.getAppendIndex (type);
mData.appendRecord (type, id);
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
mData.load (localIndex, reader, base);
mData.getRecord (localIndex).mState =
base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
}
else
{
// old record
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
if (!base)
if (mData.getRecord (localIndex).mState==RecordBase::State_Erased)
throw std::logic_error ("attempt to access a deleted record");
mData.load (localIndex, reader, base);
if (!base)
mData.getRecord (localIndex).mState = RecordBase::State_Modified;
}
}
}
int CSMWorld::RefIdCollection::getAppendIndex (UniversalId::Type type) const
{
return mData.getAppendIndex (type);
}

@ -0,0 +1,95 @@
#ifndef CSM_WOLRD_REFIDCOLLECTION_H
#define CSM_WOLRD_REFIDCOLLECTION_H
#include <vector>
#include <map>
#include <deque>
#include "columnbase.hpp"
#include "idcollection.hpp"
#include "refiddata.hpp"
namespace CSMWorld
{
class RefIdAdapter;
class RefIdColumn : public ColumnBase
{
bool mEditable;
bool mUserEditable;
public:
RefIdColumn (const std::string& title, Display displayType,
int flag = Flag_Table | Flag_Dialogue, bool editable = true,
bool userEditable = true);
virtual bool isEditable() const;
virtual bool isUserEditable() const;
};
class RefIdCollection : public IdCollectionBase
{
private:
RefIdData mData;
std::deque<RefIdColumn> mColumns;
std::map<UniversalId::Type, RefIdAdapter *> mAdapters;
private:
const RefIdAdapter& findAdaptor (UniversalId::Type) const;
///< Throws an exception if no adaptor for \a Type can be found.
public:
RefIdCollection();
virtual ~RefIdCollection();
virtual int getSize() const;
virtual std::string getId (int index) const;
virtual int getIndex (const std::string& id) const;
virtual int getColumns() const;
virtual const ColumnBase& getColumn (int column) const;
virtual QVariant getData (int index, int column) const;
virtual void setData (int index, int column, const QVariant& data);
virtual void removeRows (int index, int count);
virtual void appendBlankRecord (const std::string& id, UniversalId::Type type);
///< \param type Will be ignored, unless the collection supports multiple record types
virtual int searchId (const std::string& id) const;
////< Search record with \a id.
/// \return index of record (if found) or -1 (not found)
virtual void replace (int index, const RecordBase& record);
///< If the record type does not match, an exception is thrown.
///
/// \attention \a record must not change the ID.
virtual void appendRecord (const RecordBase& record, UniversalId::Type type);
///< If the record type does not match, an exception is thrown.
///
///< \param type Will be ignored, unless the collection supports multiple record types
virtual const RecordBase& getRecord (const std::string& id) const;
virtual const RecordBase& getRecord (int index) const;
virtual void load (ESM::ESMReader& reader, bool base, UniversalId::Type type);
virtual int getAppendIndex (UniversalId::Type type) const;
///< \param type Will be ignored, unless the collection supports multiple record types
};
}
#endif

@ -0,0 +1,198 @@
#include "refiddata.hpp"
#include <cassert>
#include <components/misc/stringops.hpp>
CSMWorld::RefIdDataContainerBase::~RefIdDataContainerBase() {}
CSMWorld::RefIdData::RefIdData()
{
mRecordContainers.insert (std::make_pair (UniversalId::Type_Activator, &mActivators));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Potion, &mPotions));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Apparatus, &mApparati));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Armor, &mArmors));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Book, &mBooks));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Clothing, &mClothing));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Container, &mContainers));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Creature, &mCreatures));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Door, &mDoors));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Ingredient, &mIngredients));
mRecordContainers.insert (std::make_pair (UniversalId::Type_CreatureLevelledList,
&mCreatureLevelledLists));
mRecordContainers.insert (std::make_pair (UniversalId::Type_ItemLevelledList, &mItemLevelledLists));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Light, &mLights));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Lockpick, &mLockpicks));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Miscellaneous, &mMiscellaneous));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Npc, &mNpcs));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Probe, &mProbes));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Repair, &mRepairs));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Static, &mStatics));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Weapon, &mWeapons));
}
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::globalToLocalIndex (int index) const
{
for (std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter (
mRecordContainers.begin()); iter!=mRecordContainers.end(); ++iter)
{
if (index<iter->second->getSize())
return LocalIndex (index, iter->first);
index -= iter->second->getSize();
}
throw std::runtime_error ("RefIdData index out of range");
}
int CSMWorld::RefIdData::localToGlobalIndex (const LocalIndex& index)
const
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator end =
mRecordContainers.find (index.second);
if (end==mRecordContainers.end())
throw std::logic_error ("invalid local index type");
int globalIndex = index.first;
for (std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter (
mRecordContainers.begin()); iter!=end; ++iter)
globalIndex += iter->second->getSize();
return globalIndex;
}
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId (
const std::string& id) const
{
std::string id2 = Misc::StringUtils::lowerCase (id);
std::map<std::string, std::pair<int, UniversalId::Type> >::const_iterator iter = mIndex.find (id2);
if (iter==mIndex.end())
return std::make_pair (-1, CSMWorld::UniversalId::Type_None);
return iter->second;
}
void CSMWorld::RefIdData::erase (int index, int count)
{
LocalIndex localIndex = globalToLocalIndex (index);
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter =
mRecordContainers.find (localIndex.second);
while (count>0 && iter!=mRecordContainers.end())
{
int size = iter->second->getSize();
if (localIndex.first+count>size)
{
erase (localIndex, size-localIndex.first);
count -= size-localIndex.first;
++iter;
if (iter==mRecordContainers.end())
throw std::runtime_error ("invalid count value for erase operation");
localIndex.first = 0;
localIndex.second = iter->first;
}
else
{
erase (localIndex, count);
count = 0;
}
}
}
const CSMWorld::RecordBase& CSMWorld::RefIdData::getRecord (const LocalIndex& index) const
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter =
mRecordContainers.find (index.second);
if (iter==mRecordContainers.end())
throw std::logic_error ("invalid local index type");
return iter->second->getRecord (index.first);
}
CSMWorld::RecordBase& CSMWorld::RefIdData::getRecord (const LocalIndex& index)
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
mRecordContainers.find (index.second);
if (iter==mRecordContainers.end())
throw std::logic_error ("invalid local index type");
return iter->second->getRecord (index.first);
}
void CSMWorld::RefIdData::appendRecord (UniversalId::Type type, const std::string& id)
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
mRecordContainers.find (type);
if (iter==mRecordContainers.end())
throw std::logic_error ("invalid local index type");
iter->second->appendRecord (id);
mIndex.insert (std::make_pair (Misc::StringUtils::lowerCase (id),
LocalIndex (iter->second->getSize()-1, type)));
}
int CSMWorld::RefIdData::getAppendIndex (UniversalId::Type type) const
{
int index = 0;
for (std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter (
mRecordContainers.begin()); iter!=mRecordContainers.end(); ++iter)
{
index += iter->second->getSize();
if (type==iter->first)
break;
}
return index;
}
void CSMWorld::RefIdData::load (const LocalIndex& index, ESM::ESMReader& reader, bool base)
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
mRecordContainers.find (index.second);
if (iter==mRecordContainers.end())
throw std::logic_error ("invalid local index type");
iter->second->load (index.first, reader, base);
}
void CSMWorld::RefIdData::erase (const LocalIndex& index, int count)
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
mRecordContainers.find (index.second);
if (iter==mRecordContainers.end())
throw std::logic_error ("invalid local index type");
for (int i=index.first; i<index.first+count; ++i)
{
std::map<std::string, LocalIndex>::iterator result =
mIndex.find (Misc::StringUtils::lowerCase (iter->second->getId (i)));
if (result!=mIndex.end())
mIndex.erase (result);
}
iter->second->erase (index.first, count);
}
int CSMWorld::RefIdData::getSize() const
{
return mIndex.size();
}

@ -0,0 +1,188 @@
#ifndef CSM_WOLRD_REFIDDATA_H
#define CSM_WOLRD_REFIDDATA_H
#include <vector>
#include <map>
#include <components/esm/loadacti.hpp>
#include <components/esm/loadalch.hpp>
#include <components/esm/loadappa.hpp>
#include <components/esm/loadarmo.hpp>
#include <components/esm/loadbook.hpp>
#include <components/esm/loadclot.hpp>
#include <components/esm/loadcont.hpp>
#include <components/esm/loadcrea.hpp>
#include <components/esm/loaddoor.hpp>
#include <components/esm/loadingr.hpp>
#include <components/esm/loadlevlist.hpp>
#include <components/esm/loadligh.hpp>
#include <components/esm/loadlock.hpp>
#include <components/esm/loadprob.hpp>
#include <components/esm/loadrepa.hpp>
#include <components/esm/loadstat.hpp>
#include <components/esm/loadweap.hpp>
#include <components/esm/loadnpc.hpp>
#include <components/esm/loadmisc.hpp>
#include "record.hpp"
#include "universalid.hpp"
namespace ESM
{
class ESMReader;
}
namespace CSMWorld
{
struct RefIdDataContainerBase
{
virtual ~RefIdDataContainerBase();
virtual int getSize() const = 0;
virtual const RecordBase& getRecord (int index) const = 0;
virtual RecordBase& getRecord (int index)= 0;
virtual void appendRecord (const std::string& id) = 0;
virtual void load (int index, ESM::ESMReader& reader, bool base) = 0;
virtual void erase (int index, int count) = 0;
virtual std::string getId (int index) const = 0;
};
template<typename RecordT>
struct RefIdDataContainer : public RefIdDataContainerBase
{
std::vector<Record<RecordT> > mContainer;
virtual int getSize() const;
virtual const RecordBase& getRecord (int index) const;
virtual RecordBase& getRecord (int index);
virtual void appendRecord (const std::string& id);
virtual void load (int index, ESM::ESMReader& reader, bool base);
virtual void erase (int index, int count);
virtual std::string getId (int index) const;
};
template<typename RecordT>
int RefIdDataContainer<RecordT>::getSize() const
{
return static_cast<int> (mContainer.size());
}
template<typename RecordT>
const RecordBase& RefIdDataContainer<RecordT>::getRecord (int index) const
{
return mContainer.at (index);
}
template<typename RecordT>
RecordBase& RefIdDataContainer<RecordT>::getRecord (int index)
{
return mContainer.at (index);
}
template<typename RecordT>
void RefIdDataContainer<RecordT>::appendRecord (const std::string& id)
{
Record<RecordT> record;
record.mModified.mId = id;
record.mModified.blank();
record.mState = RecordBase::State_ModifiedOnly;
mContainer.push_back (record);
}
template<typename RecordT>
void RefIdDataContainer<RecordT>::load (int index, ESM::ESMReader& reader, bool base)
{
(base ? mContainer.at (index).mBase : mContainer.at (index).mModified).load (reader);
}
template<typename RecordT>
void RefIdDataContainer<RecordT>::erase (int index, int count)
{
if (index<0 || index+count>=getSize())
throw std::runtime_error ("invalid RefIdDataContainer index");
mContainer.erase (mContainer.begin()+index, mContainer.begin()+index+count);
}
template<typename RecordT>
std::string RefIdDataContainer<RecordT>::getId (int index) const
{
return mContainer.at (index).get().mId;
}
class RefIdData
{
public:
typedef std::pair<int, UniversalId::Type> LocalIndex;
private:
RefIdDataContainer<ESM::Activator> mActivators;
RefIdDataContainer<ESM::Potion> mPotions;
RefIdDataContainer<ESM::Apparatus> mApparati;
RefIdDataContainer<ESM::Armor> mArmors;
RefIdDataContainer<ESM::Book> mBooks;
RefIdDataContainer<ESM::Clothing> mClothing;
RefIdDataContainer<ESM::Container> mContainers;
RefIdDataContainer<ESM::Creature> mCreatures;
RefIdDataContainer<ESM::Door> mDoors;
RefIdDataContainer<ESM::Ingredient> mIngredients;
RefIdDataContainer<ESM::CreatureLevList> mCreatureLevelledLists;
RefIdDataContainer<ESM::ItemLevList> mItemLevelledLists;
RefIdDataContainer<ESM::Light> mLights;
RefIdDataContainer<ESM::Lockpick> mLockpicks;
RefIdDataContainer<ESM::Miscellaneous> mMiscellaneous;
RefIdDataContainer<ESM::NPC> mNpcs;
RefIdDataContainer<ESM::Probe> mProbes;
RefIdDataContainer<ESM::Repair> mRepairs;
RefIdDataContainer<ESM::Static> mStatics;
RefIdDataContainer<ESM::Weapon> mWeapons;
std::map<std::string, LocalIndex> mIndex;
std::map<UniversalId::Type, RefIdDataContainerBase *> mRecordContainers;
void erase (const LocalIndex& index, int count);
///< Must not spill over into another type.
public:
RefIdData();
LocalIndex globalToLocalIndex (int index) const;
int localToGlobalIndex (const LocalIndex& index) const;
LocalIndex searchId (const std::string& id) const;
void erase (int index, int count);
const RecordBase& getRecord (const LocalIndex& index) const;
RecordBase& getRecord (const LocalIndex& index);
void appendRecord (UniversalId::Type type, const std::string& id);
int getAppendIndex (UniversalId::Type type) const;
void load (const LocalIndex& index, ESM::ESMReader& reader, bool base);
int getSize() const;
};
}
#endif

@ -29,6 +29,8 @@ namespace
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables,
"Referenceables" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
};
@ -47,6 +49,30 @@ namespace
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Activator, "Activator" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Potion, "Potion" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Apparatus, "Apparatus" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Armor, "Armor" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Book, "Book" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Clothing, "Clothing" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Container, "Container" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Creature, "Creature" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Door, "Door" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Ingredient, "Ingredient" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_CreatureLevelledList,
"Creature Levelled List" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_ItemLevelledList,
"Item Levelled List" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Light, "Light" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Lockpick, "Lockpick" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Miscellaneous,
"Miscellaneous" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Npc, "NPC" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Probe, "Probe" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Repair, "Repair" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Static, "Static" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Weapon, "Weapon" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
};

@ -57,7 +57,30 @@ namespace CSMWorld
Type_Spells,
Type_Spell,
Type_Cells,
Type_Cell
Type_Cell,
Type_Referenceables,
Type_Referenceable,
Type_Activator,
Type_Potion,
Type_Apparatus,
Type_Armor,
Type_Book,
Type_Clothing,
Type_Container,
Type_Creature,
Type_Door,
Type_Ingredient,
Type_CreatureLevelledList,
Type_ItemLevelledList,
Type_Light,
Type_Lockpick,
Type_Miscellaneous,
Type_Npc,
Type_Probe,
Type_Repair,
Type_Static,
Type_Weapon
};
private:

@ -131,6 +131,11 @@ void CSVDoc::View::setupWorldMenu()
QAction *cells = new QAction (tr ("Cells"), this);
connect (cells, SIGNAL (triggered()), this, SLOT (addCellsSubView()));
world->addAction (cells);
QAction *referenceables = new QAction (tr ("Referenceables"), this);
connect (referenceables, SIGNAL (triggered()), this, SLOT (addReferenceablesSubView()));
world->addAction (referenceables);
}
void CSVDoc::View::setupUi()
@ -336,6 +341,11 @@ void CSVDoc::View::addCellsSubView()
addSubView (CSMWorld::UniversalId::Type_Cells);
}
void CSVDoc::View::addReferenceablesSubView()
{
addSubView (CSMWorld::UniversalId::Type_Referenceables);
}
void CSVDoc::View::abortOperation (int type)
{
mDocument->abortOperation (type);

@ -138,6 +138,8 @@ namespace CSVDoc
void addCellsSubView();
void addReferenceablesSubView();
void showUserSettings();
};
}

@ -57,6 +57,35 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
"Spell", "Ability", "Blight", "Disease", "Curse", "Power", 0
};
static const char *sApparatusTypes[] =
{
"Mortar & Pestle", "Albemic", "Calcinator", "Retort", 0
};
static const char *sArmorTypes[] =
{
"Helmet", "Cuirass", "Left Pauldron", "Right Pauldron", "Greaves", "Boots", "Left Gauntlet",
"Right Gauntlet", "Shield", "Left Bracer", "Right Bracer", 0
};
static const char *sClothingTypes[] =
{
"Pants", "Shoes", "Shirt", "Belt", "Robe", "Right Glove", "Left Glove", "Skirt", "Ring",
"Amulet", 0
};
static const char *sCreatureTypes[] =
{
"Creature", "Deadra", "Undead", "Humanoid", 0
};
static const char *sWeaponTypes[] =
{
"Short Blade 1H", "Long Blade 1H", "Long Blade 2H", "Blunt 1H", "Blunt 2H Close",
"Blunt 2H Wide", "Spear 2H", "Axe 1H", "Axe 2H", "Bow", "Crossbow", "Thrown", "Arrow",
"Bolt", 0
};
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType,
@ -73,6 +102,21 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
mDelegateFactories->add (CSMWorld::ColumnBase::Display_SpellType,
new CSVWorld::EnumDelegateFactory (sSpellTypes));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_ApparatusType,
new CSVWorld::EnumDelegateFactory (sApparatusTypes));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_ArmorType,
new CSVWorld::EnumDelegateFactory (sArmorTypes));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_ClothingType,
new CSVWorld::EnumDelegateFactory (sClothingTypes));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_CreatureType,
new CSVWorld::EnumDelegateFactory (sCreatureTypes));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_WeaponType,
new CSVWorld::EnumDelegateFactory (sWeaponTypes));
}
CSVDoc::ViewManager::~ViewManager()

@ -44,6 +44,9 @@ CSVWorld::EnumDelegate::EnumDelegate (const std::vector<std::pair<int, QString>
QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
if (!index.data().isValid())
return 0;
QComboBox *comboBox = new QComboBox (parent);
for (std::vector<std::pair<int, QString> >::const_iterator iter (mValues.begin());
@ -73,20 +76,23 @@ void CSVWorld::EnumDelegate::setEditorData (QWidget *editor, const QModelIndex&
void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
QStyleOptionViewItemV4 option2 (option);
if (index.data().isValid())
{
QStyleOptionViewItemV4 option2 (option);
int value = index.data().toInt();
int value = index.data().toInt();
for (std::vector<std::pair<int, QString> >::const_iterator iter (mValues.begin());
iter!=mValues.end(); ++iter)
if (iter->first==value)
{
option2.text = iter->second;
for (std::vector<std::pair<int, QString> >::const_iterator iter (mValues.begin());
iter!=mValues.end(); ++iter)
if (iter->first==value)
{
option2.text = iter->second;
QApplication::style()->drawControl (QStyle::CE_ItemViewItem, &option2, painter);
QApplication::style()->drawControl (QStyle::CE_ItemViewItem, &option2, painter);
break;
}
break;
}
}
}

@ -27,6 +27,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CSMWorld::UniversalId::Type_Birthsigns,
CSMWorld::UniversalId::Type_Spells,
CSMWorld::UniversalId::Type_Cells,
CSMWorld::UniversalId::Type_Referenceables,
CSMWorld::UniversalId::Type_None // end marker
};

@ -116,6 +116,16 @@ void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemMode
///< \todo provide some kind of feedback to the user, indicating that editing is currently not possible.
}
QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
if (!index.data().isValid())
return 0;
return QStyledItemDelegate::createEditor (parent, option, index);
}
void CSVWorld::CommandDelegate::setEditLock (bool locked)
{
mEditLock = locked;

@ -99,6 +99,9 @@ namespace CSVWorld
virtual void setModelData (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const;
virtual QWidget *createEditor (QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const;
void setEditLock (bool locked);
bool isEditLocked() const;

@ -67,7 +67,7 @@ add_openmw_dir (mwclass
add_openmw_dir (mwmechanics
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow
aiescort aiactivate repair enchanting pathfinding
aiescort aiactivate repair enchanting pathfinding security
)
add_openmw_dir (mwbase

@ -233,6 +233,7 @@ namespace MWGui
{
// transfer everything into the player's inventory
ItemModel* playerModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getModel();
mModel->update();
for (size_t i=0; i<mModel->getItemCount(); ++i)
{
if (i==0)
@ -257,7 +258,6 @@ namespace MWGui
{
onTakeAllButtonClicked(mTakeButton);
/// \todo if corpse is non-disposable: messagebox #{sDisposeCorpseFail}
if (MWWorld::Class::get(mPtr).isPersistent(mPtr))
MWBase::Environment::get().getWindowManager()->messageBox("#{sDisposeCorpseFail}");
else

@ -241,6 +241,10 @@ namespace MWInput
case A_ToggleHUD:
mWindows.toggleHud();
break;
case A_Use:
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
mPlayer.use();
break;
}
}
}
@ -803,6 +807,7 @@ namespace MWInput
{
std::map<int, std::string> descriptions;
descriptions[A_Use] = "sUse";
descriptions[A_Activate] = "sActivate";
descriptions[A_MoveBackward] = "sBack";
descriptions[A_MoveForward] = "sForward";
@ -865,6 +870,7 @@ namespace MWInput
ret.push_back(A_AlwaysRun);
ret.push_back(A_Sneak);
ret.push_back(A_Activate);
ret.push_back(A_Use);
ret.push_back(A_ToggleWeapon);
ret.push_back(A_ToggleSpell);
ret.push_back(A_AutoMove);

@ -0,0 +1,108 @@
#include "security.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "npcstats.hpp"
#include "creaturestats.hpp"
namespace MWMechanics
{
Security::Security(const MWWorld::Ptr &actor)
{
CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor);
NpcStats& npcStats = MWWorld::Class::get(actor).getNpcStats(actor);
mAgility = creatureStats.getAttribute(ESM::Attribute::Agility).getModified();
mLuck = creatureStats.getAttribute(ESM::Attribute::Luck).getModified();
mSecuritySkill = npcStats.getSkill(ESM::Skill::Security).getModified();
mFatigueTerm = creatureStats.getFatigueTerm();
}
void Security::pickLock(const MWWorld::Ptr &lock, const MWWorld::Ptr &lockpick,
std::string& resultMessage, std::string& resultSound)
{
if (lock.getCellRef().mLockLevel <= 0)
return;
int lockStrength = lock.getCellRef().mLockLevel;
float pickQuality = lockpick.get<ESM::Lockpick>()->mBase->mData.mQuality;
float fPickLockMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fPickLockMult")->getFloat();
float x = 0.2 * mAgility + 0.1 * mLuck + mSecuritySkill;
x *= pickQuality * mFatigueTerm;
x += fPickLockMult * lockStrength;
resultSound = "Open Lock Fail";
if (x <= 0)
resultMessage = "#{sLockImpossible}";
else
{
int roll = static_cast<float> (std::rand()) / RAND_MAX * 100;
if (roll <= x)
{
MWWorld::Class::get(lock).unlock(lock);
resultMessage = "#{sLockSuccess}";
resultSound = "Open Lock";
MWWorld::Class::get(mActor).skillUsageSucceeded(mActor, ESM::Skill::Security, 1);
}
else
resultMessage = "#{sLockFail}";
}
if (lockpick.getCellRef().mCharge == -1)
lockpick.getCellRef().mCharge = lockpick.get<ESM::Lockpick>()->mBase->mData.mUses;
--lockpick.getCellRef().mCharge;
if (!lockpick.getCellRef().mCharge)
lockpick.getRefData().setCount(0);
}
void Security::probeTrap(const MWWorld::Ptr &trap, const MWWorld::Ptr &probe,
std::string& resultMessage, std::string& resultSound)
{
if (trap.getCellRef().mTrap == "")
return;
float probeQuality = probe.get<ESM::Probe>()->mBase->mData.mQuality;
const ESM::Spell* trapSpell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(trap.getCellRef().mTrap);
float trapSpellPoints = trapSpell->mData.mCost;
float fTrapCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fTrapCostMult")->getFloat();
float x = 0.2 * mAgility + 0.1 * mLuck + mSecuritySkill;
x += fTrapCostMult * trapSpellPoints;
x *= probeQuality * mFatigueTerm;
resultSound = "Disarm Trap Fail";
if (x <= 0)
resultMessage = "#{sTrapImpossible}";
else
{
int roll = static_cast<float> (std::rand()) / RAND_MAX * 100;
if (roll <= x)
{
trap.getCellRef().mTrap = "";
resultSound = "Disarm Trap";
resultMessage = "#{sTrapSuccess}";
MWWorld::Class::get(mActor).skillUsageSucceeded(mActor, ESM::Skill::Security, 0);
}
else
resultMessage = "#{sTrapFail}";
}
if (probe.getCellRef().mCharge == -1)
probe.getCellRef().mCharge = probe.get<ESM::Probe>()->mBase->mData.mUses;
--probe.getCellRef().mCharge;
if (!probe.getCellRef().mCharge)
probe.getRefData().setCount(0);
}
}

@ -0,0 +1,27 @@
#ifndef MWMECHANICS_SECURITY_H
#define MWMECHANICS_SECURITY_H
#include "../mwworld/ptr.hpp"
namespace MWMechanics
{
/// @brief implementation of Security skill
class Security
{
public:
Security (const MWWorld::Ptr& actor);
void pickLock (const MWWorld::Ptr& lock, const MWWorld::Ptr& lockpick,
std::string& resultMessage, std::string& resultSound);
void probeTrap (const MWWorld::Ptr& trap, const MWWorld::Ptr& probe,
std::string& resultMessage, std::string& resultSound);
private:
float mAgility, mLuck, mSecuritySkill, mFatigueTerm;
MWWorld::Ptr mActor;
};
}
#endif

@ -728,4 +728,12 @@ void Animation::showWeapons(bool showWeapon)
{
}
bool Animation::isPriorityActive(int priority) const
{
for (AnimStateMap::const_iterator it = mStates.begin(); it != mStates.end(); ++it)
if (it->second.mPriority == priority)
return true;
return false;
}
}

@ -148,6 +148,9 @@ public:
bool hasAnimation(const std::string &anim);
bool isPriorityActive (int priority) const;
///< Is there an animation playing with the given priority?
// Specifies the axis' to accumulate on. Non-accumulated axis will just
// move visually, but not affect the actual movement. Each x/y/z value
// should be on the scale of 0 to 1.

@ -193,6 +193,7 @@ namespace MWRender
mNode->setOrientation (Ogre::Quaternion::IDENTITY);
mRenderTarget->update();
mSelectionBuffer->update();
}
@ -203,8 +204,8 @@ namespace MWRender
void InventoryPreview::onSetup ()
{
if (!mSelectionBuffer)
mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, 0);
delete mSelectionBuffer;
mSelectionBuffer = new OEngine::Render::SelectionBuffer(mCamera, 512, 1024, 0);
mAnimation->showWeapons(true);

@ -73,8 +73,6 @@ namespace MWRender
int getSlotSelected(int posX, int posY);
void setNpcAnimation (NpcAnimation* anim);
private:
OEngine::Render::SelectionBuffer* mSelectionBuffer;

@ -197,11 +197,11 @@ void LocalMap::render(const float x, const float y,
const float zlow, const float zhigh,
const float xw, const float yw, const std::string& texture)
{
//mCellCamera->setFarClipDistance( (zhigh-zlow) * 1.1 );
mCellCamera->setFarClipDistance(0); // infinite
mCellCamera->setFarClipDistance( (zhigh-zlow) + 2000 );
mCellCamera->setNearClipDistance(50);
mCellCamera->setOrthoWindow(xw, yw);
mCameraNode->setPosition(Vector3(x, y, zhigh+100000));
mCameraNode->setPosition(Vector3(x, y, zhigh+1000));
// disable fog (only necessary for fixed function, the shader based
// materials already do this through local_map material configuration)

@ -128,8 +128,6 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
assert(viewMode != VM_HeadOnly);
mViewMode = viewMode;
Ogre::SceneNode *node = mInsert->getParentSceneNode();
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
const ESM::Race *race = store.get<ESM::Race>().find(mNpc->mRace);
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;

@ -235,8 +235,8 @@ void RenderingManager::toggleWater()
void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store)
{
sh::Factory::getInstance().unloadUnreferencedMaterials();
mObjects.buildStaticGeometry (*store);
sh::Factory::getInstance().unloadUnreferencedMaterials();
mDebugging->cellAdded(store);
if (store->mCell->isExterior())
mTerrainManager->cellAdded(store);

@ -640,7 +640,7 @@ Ogre::SceneNode* SkyManager::getSunNode()
void SkyManager::setGlareEnabled (bool enabled)
{
if (!mCreated)
if (!mCreated || !mEnabled)
return;
mSunGlare->setVisible (mSunEnabled && enabled);
}

@ -2,11 +2,19 @@
#include "player.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/ptr.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwmechanics/movement.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/character.hpp"
#include "../mwmechanics/security.hpp"
#include "../mwrender/animation.hpp"
#include "class.hpp"
@ -133,6 +141,49 @@ namespace MWWorld
MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[1] = roll;
}
void Player::use()
{
MWWorld::InventoryStore& store = MWWorld::Class::get(getPlayer()).getInventoryStore(getPlayer());
MWWorld::ContainerStoreIterator equipped = store.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if (getDrawState() == MWMechanics::DrawState_Weapon)
{
if (equipped != store.end())
{
MWWorld::Ptr item = *equipped;
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(getPlayer());
MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getFacedObject();
if (anim->isPriorityActive(MWMechanics::Priority_Weapon))
return;
std::string resultMessage, resultSound;
if (item.getTypeName() == typeid(ESM::Lockpick).name())
{
if (!target.isEmpty())
MWMechanics::Security(getPlayer()).pickLock(target, item, resultMessage, resultSound);
anim->play("pickprobe", MWMechanics::Priority_Weapon, MWRender::Animation::Group_UpperBody, true, "start", "stop", 0.0, 0);
}
else if (item.getTypeName() == typeid(ESM::Probe).name())
{
if (!target.isEmpty())
MWMechanics::Security(getPlayer()).probeTrap(target, item, resultMessage, resultSound);
anim->play("pickprobe", MWMechanics::Priority_Weapon, MWRender::Animation::Group_UpperBody, true, "start", "stop", 0.0, 0);
}
if (!resultMessage.empty())
MWBase::Environment::get().getWindowManager()->messageBox(resultMessage);
if (!resultSound.empty())
MWBase::Environment::get().getSoundManager()->playSound(resultSound,1,1);
// tool used up?
if (!item.getRefData().getCount())
MWBase::Environment::get().getWindowManager()->setSelectedWeapon(MWWorld::Ptr());
}
}
}
MWMechanics::DrawState_ Player::getDrawState()
{
MWWorld::Ptr ptr = getPlayer();

@ -58,6 +58,9 @@ namespace MWWorld
void setForwardBackward (int value);
void setUpDown(int value);
void use ();
///< Use item equipped on right hand, or fists
void setRunState(bool run);
void setSneak(bool sneak);

@ -5,6 +5,12 @@
namespace ESM
{
void AIData::blank()
{
mHello = mU1 = mFight = mFlee = mAlarm = mU2 = mU3 = mU4 = 0;
mServices = 0;
}
void AIPackageList::load(ESMReader &esm)
{
while (esm.hasMoreSubs()) {

@ -19,6 +19,9 @@ namespace ESM
// These are probabilities
char mHello, mU1, mFight, mFlee, mAlarm, mU2, mU3, mU4;
int mServices; // See the Services enum
void blank();
///< Set record to default state (does not touch the ID).
}; // 12 bytes
struct AIWander

@ -17,4 +17,11 @@ void Activator::save(ESMWriter &esm)
esm.writeHNCString("FNAM", mName);
esm.writeHNOCString("SCRI", mScript);
}
void Activator::blank()
{
mName.clear();
mScript.clear();
mModel.clear();
}
}

@ -15,6 +15,9 @@ struct Activator
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}

@ -23,4 +23,16 @@ void Potion::save(ESMWriter &esm)
esm.writeHNT("ALDT", mData, 12);
mEffects.save(esm);
}
void Potion::blank()
{
mData.mWeight = 0;
mData.mValue = 0;
mData.mAutoCalc = 0;
mName.clear();
mModel.clear();
mIcon.clear();
mScript.clear();
mEffects.mList.clear();
}
}

@ -30,6 +30,10 @@ struct Potion
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

@ -36,4 +36,16 @@ void Apparatus::save(ESMWriter &esm)
esm.writeHNOCString("SCRI", mScript);
esm.writeHNCString("ITEX", mIcon);
}
void Apparatus::blank()
{
mData.mType = 0;
mData.mQuality = 0;
mData.mWeight = 0;
mData.mValue = 0;
mModel.clear();
mIcon.clear();
mScript.clear();
mName.clear();
}
}

@ -36,6 +36,9 @@ struct Apparatus
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

@ -50,4 +50,19 @@ void Armor::save(ESMWriter &esm)
esm.writeHNOCString("ENAM", mEnchant);
}
void Armor::blank()
{
mData.mType = 0;
mData.mWeight = 0;
mData.mValue = 0;
mData.mHealth = 0;
mData.mEnchant = 0;
mData.mArmor = 0;
mParts.mParts.clear();
mName.clear();
mModel.clear();
mIcon.clear();
mScript.clear();
mEnchant.clear();
}
}

@ -90,6 +90,9 @@ struct Armor
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

@ -27,4 +27,18 @@ void Book::save(ESMWriter &esm)
esm.writeHNOCString("ENAM", mEnchant);
}
void Book::blank()
{
mData.mWeight = 0;
mData.mValue = 0;
mData.mIsScroll = 0;
mData.mSkillID = 0;
mData.mEnchant = 0;
mName.clear();
mModel.clear();
mIcon.clear();
mScript.clear();
mEnchant.clear();
mText.clear();
}
}

@ -26,6 +26,9 @@ struct Book
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

@ -16,7 +16,7 @@ void Clothing::load(ESMReader &esm)
mIcon = esm.getHNOString("ITEX");
mParts.load(esm);
mEnchant = esm.getHNOString("ENAM");
}
@ -28,10 +28,24 @@ void Clothing::save(ESMWriter &esm)
esm.writeHNOCString("SCRI", mScript);
esm.writeHNOCString("ITEX", mIcon);
mParts.save(esm);
esm.writeHNOCString("ENAM", mEnchant);
}
void Clothing::blank()
{
mData.mType = 0;
mData.mWeight = 0;
mData.mValue = 0;
mData.mEnchant = 0;
mParts.mParts.clear();
mName.clear();
mModel.clear();
mIcon.clear();
mIcon.clear();
mEnchant.clear();
mScript.clear();
}
}

@ -46,6 +46,9 @@ struct Clothing
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

@ -53,4 +53,13 @@ void Container::save(ESMWriter &esm)
mInventory.save(esm);
}
void Container::blank()
{
mName.clear();
mModel.clear();
mScript.clear();
mWeight = 0;
mFlags = 0;
mInventory.mList.clear();
}
}

@ -47,6 +47,9 @@ struct Container
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

@ -55,4 +55,28 @@ void Creature::save(ESMWriter &esm)
mAiPackage.save(esm);
}
void Creature::blank()
{
mData.mType = 0;
mData.mLevel = 0;
mData.mStrength = mData.mIntelligence = mData.mWillpower = mData.mAgility =
mData.mSpeed = mData.mEndurance = mData.mPersonality = mData.mLuck = 0;
mData.mHealth = mData.mMana = mData.mFatigue = 0;
mData.mSoul = 0;
mData.mCombat = mData.mMagic = mData.mStealth = 0;
for (int i=0; i<6; ++i) mData.mAttack[i] = 0;
mData.mGold = 0;
mFlags = 0;
mScale = 0;
mModel.clear();
mName.clear();
mScript.clear();
mOriginal.clear();
mInventory.mList.clear();
mSpells.mList.clear();
mHasAI = false;
mAiData.blank();
mAiData.mServices = 0;
mAiPackage.mList.clear();
}
}

@ -87,6 +87,9 @@ struct Creature
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}

@ -24,4 +24,12 @@ void Door::save(ESMWriter &esm)
esm.writeHNOCString("ANAM", mCloseSound);
}
void Door::blank()
{
mName.clear();
mModel.clear();
mScript.clear();
mOpenSound.clear();
mCloseSound.clear();
}
}

@ -15,6 +15,9 @@ struct Door
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

@ -24,7 +24,7 @@ void Ingredient::load(ESMReader &esm)
{
mData.mAttributes[i] = -1;
}
// is this relevant in cycle from 0 to 4?
if (mData.mEffectID[i] != 89 &&
mData.mEffectID[i] != 26 &&
@ -46,4 +46,20 @@ void Ingredient::save(ESMWriter &esm)
esm.writeHNOCString("ITEX", mIcon);
}
void Ingredient::blank()
{
mData.mWeight = 0;
mData.mValue = 0;
for (int i=0; i<4; ++i)
{
mData.mEffectID[i] = 0;
mData.mSkills[i] = 0;
mData.mAttributes[i] = 0;
}
mName.clear();
mModel.clear();
mIcon.clear();
mScript.clear();
}
}

@ -29,6 +29,9 @@ struct Ingredient
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

@ -38,7 +38,7 @@ void LeveledListBase::save(ESMWriter &esm)
esm.writeHNT("DATA", mFlags);
esm.writeHNT("NNAM", mChanceNone);
esm.writeHNT<int>("INDX", mList.size());
for (std::vector<LevelItem>::iterator it = mList.begin(); it != mList.end(); ++it)
{
esm.writeHNCString(mRecName, it->mId);
@ -46,4 +46,10 @@ void LeveledListBase::save(ESMWriter &esm)
}
}
void LeveledListBase::blank()
{
mFlags = 0;
mChanceNone = 0;
mList.clear();
}
}

@ -15,7 +15,7 @@ class ESMWriter;
* to implement it once.
*
* We should later implement the ability to merge leveled lists from
* several files.
* several files.
*/
struct LeveledListBase
@ -52,6 +52,9 @@ struct LeveledListBase
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
struct CreatureLevList: LeveledListBase

@ -26,4 +26,18 @@ void Light::save(ESMWriter &esm)
esm.writeHNOCString("SNAM", mSound);
}
void Light::blank()
{
mData.mWeight = 0;
mData.mValue = 0;
mData.mTime = 0;
mData.mRadius = 0;
mData.mColor = 0;
mData.mFlags = 0;
mSound.clear();
mScript.clear();
mModel.clear();
mIcon.clear();
mName.clear();
}
}

@ -45,6 +45,9 @@ struct Light
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

@ -21,11 +21,21 @@ void Lockpick::save(ESMWriter &esm)
{
esm.writeHNCString("MODL", mModel);
esm.writeHNCString("FNAM", mName);
esm.writeHNT("LKDT", mData, 16);
esm.writeHNOString("SCRI", mScript);
esm.writeHNOCString("ITEX", mIcon);
}
void Lockpick::blank()
{
mData.mWeight = 0;
mData.mValue = 0;
mData.mQuality = 0;
mData.mUses = 0;
mName.clear();
mModel.clear();
mIcon.clear();
mScript.clear();
}
}

@ -25,6 +25,9 @@ struct Lockpick
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}

@ -23,4 +23,14 @@ void Miscellaneous::save(ESMWriter &esm)
esm.writeHNOCString("ITEX", mIcon);
}
void Miscellaneous::blank()
{
mData.mWeight = 0;
mData.mValue = 0;
mData.mIsKey = 0;
mName.clear();
mModel.clear();
mIcon.clear();
mScript.clear();
}
}

@ -30,6 +30,9 @@ struct Miscellaneous
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

@ -58,7 +58,7 @@ void NPC::load(ESMReader &esm)
mTransport.push_back(dodt);
} else if (esm.retSubName() == 0x4d414e44) { // DNAM struct
mTransport.back().mCellName = esm.getHString();
}
}
}
mAiPackage.load(esm);
esm.skipRecord();
@ -73,14 +73,14 @@ void NPC::save(ESMWriter &esm)
esm.writeHNCString("BNAM", mHead);
esm.writeHNCString("KNAM", mHair);
esm.writeHNOCString("SCRI", mScript);
if (mNpdtType == 52)
esm.writeHNT("NPDT", mNpdt52, 52);
else if (mNpdtType == 12)
esm.writeHNT("NPDT", mNpdt12, 12);
esm.writeHNT("FLAG", mFlags);
mInventory.save(esm);
mSpells.save(esm);
if (mHasAI) {
@ -95,4 +95,53 @@ void NPC::save(ESMWriter &esm)
mAiPackage.save(esm);
}
bool NPC::isMale() const {
return (mFlags & Female) == 0;
}
void NPC::setIsMale(bool value) {
mFlags |= Female;
if (value) {
mFlags ^= Female;
}
}
void NPC::blank()
{
mNpdtType = 0;
mNpdt52.mLevel = 0;
mNpdt52.mStrength = mNpdt52.mIntelligence = mNpdt52.mWillpower = mNpdt52.mAgility =
mNpdt52.mSpeed = mNpdt52.mEndurance = mNpdt52.mPersonality = mNpdt52.mLuck = 0;
for (int i=0; i<27; ++i) mNpdt52.mSkills[i] = 0;
mNpdt52.mReputation = 0;
mNpdt52.mHealth = mNpdt52.mMana = mNpdt52.mFatigue = 0;
mNpdt52.mDisposition = 0;
mNpdt52.mFactionID = 0;
mNpdt52.mRank = 0;
mNpdt52.mUnknown = 0;
mNpdt52.mGold = 0;
mNpdt12.mLevel = 0;
mNpdt12.mDisposition = 0;
mNpdt12.mReputation = 0;
mNpdt12.mRank = 0;
mNpdt12.mUnknown1 = 0;
mNpdt12.mUnknown2 = 0;
mNpdt12.mUnknown3 = 0;
mNpdt12.mGold = 0;
mFlags = 0;
mInventory.mList.clear();
mSpells.mList.clear();
mAiData.blank();
mHasAI = false;
mTransport.clear();
mAiPackage.mList.clear();
mName.clear();
mModel.clear();
mRace.clear();
mClass.clear();
mFaction.clear();
mScript.clear();
mHair.clear();
mHead.clear();
}
}

@ -116,20 +116,15 @@ struct NPC
// body parts
std::string mHair, mHead;
// Implementation moved to load_impl.cpp
void load(ESMReader &esm);
void save(ESMWriter &esm);
bool isMale() const {
return (mFlags & Female) == 0;
}
bool isMale() const;
void setIsMale(bool value) {
mFlags |= Female;
if (value) {
mFlags ^= Female;
}
}
void setIsMale(bool value);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

@ -21,10 +21,21 @@ void Probe::save(ESMWriter &esm)
{
esm.writeHNCString("MODL", mModel);
esm.writeHNCString("FNAM", mName);
esm.writeHNT("PBDT", mData, 16);
esm.writeHNOString("SCRI", mScript);
esm.writeHNOCString("ITEX", mIcon);
}
void Probe::blank()
{
mData.mWeight = 0;
mData.mValue = 0;
mData.mQuality = 0;
mData.mUses = 0;
mName.clear();
mModel.clear();
mIcon.clear();
mScript.clear();
}
}

@ -25,6 +25,9 @@ struct Probe
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}

@ -27,5 +27,15 @@ void Repair::save(ESMWriter &esm)
esm.writeHNOCString("ITEX", mIcon);
}
void Repair::blank()
{
mData.mWeight = 0;
mData.mValue = 0;
mData.mQuality = 0;
mData.mUses = 0;
mName.clear();
mModel.clear();
mIcon.clear();
mScript.clear();
}
}

@ -25,6 +25,9 @@ struct Repair
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}

@ -15,4 +15,8 @@ void Static::save(ESMWriter &esm)
esm.writeHNCString("MODL", mModel);
}
void Static::blank()
{
mModel.clear();
}
}

@ -26,6 +26,9 @@ struct Static
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

@ -25,4 +25,24 @@ void Weapon::save(ESMWriter &esm)
esm.writeHNOCString("ENAM", mEnchant);
}
void Weapon::blank()
{
mData.mWeight = 0;
mData.mValue = 0;
mData.mType = 0;
mData.mHealth = 0;
mData.mSpeed = 0;
mData.mReach = 0;
mData.mEnchant = 0;
mData.mChop[0] = mData.mChop[1] = 0;
mData.mSlash[0] = mData.mSlash[1] = 0;
mData.mThrust[0] = mData.mThrust[1] = 0;
mData.mFlags = 0;
mName.clear();
mModel.clear();
mIcon.clear();
mEnchant.clear();
mScript.clear();
}
}

@ -60,6 +60,9 @@ struct Weapon
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

Loading…
Cancel
Save