Merge branch 'master' of https://github.com/zinnschlag/openmw
commit
cd57523601
@ -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
|
@ -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
|
Loading…
Reference in New Issue