mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 11:49:56 +00:00
dab8b328c4
Replaces the four emitter check boxes in Light records with an "Emitter Type" combo box. Related issue: - Fixes #3752: Editor: Replace emitter check boxes in Light records with "Emitter Type" combo box (https://bugs.openmw.org/issues/3752) Tests: The changes were successfully tested in OpenMW-CS by manipulating several Light records. Please note that this fix also prevents users from erroneously assigning two or more emitter types at the same time. (I don't know which one would prevail in that case.)
1574 lines
56 KiB
C++
1574 lines
56 KiB
C++
#include "refidadapterimp.hpp"
|
|
|
|
#include <cassert>
|
|
#include <stdexcept>
|
|
#include <utility>
|
|
|
|
#include <components/esm/loadcont.hpp>
|
|
#include <components/esm/loadmgef.hpp>
|
|
|
|
#include "nestedtablewrapper.hpp"
|
|
|
|
CSMWorld::PotionColumns::PotionColumns (const InventoryColumns& columns)
|
|
: InventoryColumns (columns) {}
|
|
|
|
CSMWorld::PotionRefIdAdapter::PotionRefIdAdapter (const PotionColumns& columns,
|
|
const RefIdColumn *autoCalc)
|
|
: InventoryRefIdAdapter<ESM::Potion> (UniversalId::Type_Potion, columns),
|
|
mColumns(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;
|
|
|
|
// to show nested tables in dialogue subview, see IdTree::hasChildren()
|
|
if (column==mColumns.mEffects)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
|
|
|
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)));
|
|
|
|
ESM::Potion potion = record.get();
|
|
|
|
if (column==mAutoCalc)
|
|
potion.mData.mAutoCalc = value.toInt();
|
|
else
|
|
{
|
|
InventoryRefIdAdapter<ESM::Potion>::setData (column, data, index, value);
|
|
|
|
return;
|
|
}
|
|
|
|
record.setModified(potion);
|
|
}
|
|
|
|
|
|
CSMWorld::IngredientColumns::IngredientColumns (const InventoryColumns& columns)
|
|
: InventoryColumns (columns) {}
|
|
|
|
CSMWorld::IngredientRefIdAdapter::IngredientRefIdAdapter (const IngredientColumns& columns)
|
|
: InventoryRefIdAdapter<ESM::Ingredient> (UniversalId::Type_Ingredient, columns),
|
|
mColumns(columns)
|
|
{}
|
|
|
|
QVariant CSMWorld::IngredientRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
|
|
int index) const
|
|
{
|
|
if (column==mColumns.mEffects)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
|
|
|
return InventoryRefIdAdapter<ESM::Ingredient>::getData (column, data, index);
|
|
}
|
|
|
|
void CSMWorld::IngredientRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
|
|
const QVariant& value) const
|
|
{
|
|
InventoryRefIdAdapter<ESM::Ingredient>::setData (column, data, index, value);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
CSMWorld::IngredEffectRefIdAdapter::IngredEffectRefIdAdapter()
|
|
: mType(UniversalId::Type_Ingredient)
|
|
{}
|
|
|
|
CSMWorld::IngredEffectRefIdAdapter::~IngredEffectRefIdAdapter()
|
|
{}
|
|
|
|
void CSMWorld::IngredEffectRefIdAdapter::addNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int position) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void CSMWorld::IngredEffectRefIdAdapter::removeNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int rowToRemove) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void CSMWorld::IngredEffectRefIdAdapter::setNestedTable (const RefIdColumn* column,
|
|
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
Record<ESM::Ingredient>& record =
|
|
static_cast<Record<ESM::Ingredient>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
|
|
ESM::Ingredient ingredient = record.get();
|
|
|
|
ingredient.mData =
|
|
static_cast<const NestedTableWrapper<std::vector<ESM::Ingredient::IRDTstruct> >&>(nestedTable).mNestedTable.at(0);
|
|
|
|
record.setModified (ingredient);
|
|
}
|
|
|
|
CSMWorld::NestedTableWrapperBase* CSMWorld::IngredEffectRefIdAdapter::nestedTable (const RefIdColumn* column,
|
|
const RefIdData& data, int index) const
|
|
{
|
|
const Record<ESM::Ingredient>& record =
|
|
static_cast<const Record<ESM::Ingredient>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
|
|
|
|
// return the whole struct
|
|
std::vector<ESM::Ingredient::IRDTstruct> wrap;
|
|
wrap.push_back(record.get().mData);
|
|
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<ESM::Ingredient::IRDTstruct> >(wrap);
|
|
}
|
|
|
|
QVariant CSMWorld::IngredEffectRefIdAdapter::getNestedData (const RefIdColumn *column,
|
|
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
|
|
{
|
|
const Record<ESM::Ingredient>& record =
|
|
static_cast<const Record<ESM::Ingredient>&> (data.getRecord (RefIdData::LocalIndex (index, mType)));
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= 4)
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return record.get().mData.mEffectID[subRowIndex];
|
|
case 1:
|
|
{
|
|
switch (record.get().mData.mEffectID[subRowIndex])
|
|
{
|
|
case ESM::MagicEffect::DrainSkill:
|
|
case ESM::MagicEffect::DamageSkill:
|
|
case ESM::MagicEffect::RestoreSkill:
|
|
case ESM::MagicEffect::FortifySkill:
|
|
case ESM::MagicEffect::AbsorbSkill:
|
|
return record.get().mData.mSkills[subRowIndex];
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
case 2:
|
|
{
|
|
switch (record.get().mData.mEffectID[subRowIndex])
|
|
{
|
|
case ESM::MagicEffect::DrainAttribute:
|
|
case ESM::MagicEffect::DamageAttribute:
|
|
case ESM::MagicEffect::RestoreAttribute:
|
|
case ESM::MagicEffect::FortifyAttribute:
|
|
case ESM::MagicEffect::AbsorbAttribute:
|
|
return record.get().mData.mAttributes[subRowIndex];
|
|
default:
|
|
return QVariant();
|
|
}
|
|
}
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
}
|
|
|
|
void CSMWorld::IngredEffectRefIdAdapter::setNestedData (const RefIdColumn *column,
|
|
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
Record<ESM::Ingredient>& record =
|
|
static_cast<Record<ESM::Ingredient>&> (data.getRecord (RefIdData::LocalIndex (row, mType)));
|
|
ESM::Ingredient ingredient = record.get();
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= 4)
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
switch(subColIndex)
|
|
{
|
|
case 0: ingredient.mData.mEffectID[subRowIndex] = value.toInt(); break;
|
|
case 1: ingredient.mData.mSkills[subRowIndex] = value.toInt(); break;
|
|
case 2: ingredient.mData.mAttributes[subRowIndex] = value.toInt(); break;
|
|
default:
|
|
throw std::runtime_error("Trying to access non-existing column in the nested table!");
|
|
}
|
|
|
|
record.setModified (ingredient);
|
|
}
|
|
|
|
int CSMWorld::IngredEffectRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
|
{
|
|
return 3; // effect, skill, attribute
|
|
}
|
|
|
|
int CSMWorld::IngredEffectRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
|
{
|
|
return 4; // up to 4 effects
|
|
}
|
|
|
|
|
|
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)));
|
|
|
|
ESM::Apparatus apparatus = record.get();
|
|
|
|
if (column==mType)
|
|
apparatus.mData.mType = value.toInt();
|
|
else if (column==mQuality)
|
|
apparatus.mData.mQuality = value.toFloat();
|
|
else
|
|
{
|
|
InventoryRefIdAdapter<ESM::Apparatus>::setData (column, data, index, value);
|
|
|
|
return;
|
|
}
|
|
record.setModified(apparatus);
|
|
}
|
|
|
|
|
|
CSMWorld::ArmorRefIdAdapter::ArmorRefIdAdapter (const EnchantableColumns& columns,
|
|
const RefIdColumn *type, const RefIdColumn *health, const RefIdColumn *armor,
|
|
const RefIdColumn *partRef)
|
|
: EnchantableRefIdAdapter<ESM::Armor> (UniversalId::Type_Armor, columns),
|
|
mType (type), mHealth (health), mArmor (armor), mPartRef(partRef)
|
|
{}
|
|
|
|
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;
|
|
|
|
if (column==mPartRef)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
|
|
|
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)));
|
|
|
|
ESM::Armor armor = record.get();
|
|
|
|
if (column==mType)
|
|
armor.mData.mType = value.toInt();
|
|
else if (column==mHealth)
|
|
armor.mData.mHealth = value.toInt();
|
|
else if (column==mArmor)
|
|
armor.mData.mArmor = value.toInt();
|
|
else
|
|
{
|
|
EnchantableRefIdAdapter<ESM::Armor>::setData (column, data, index, value);
|
|
|
|
return;
|
|
}
|
|
|
|
record.setModified(armor);
|
|
}
|
|
|
|
CSMWorld::BookRefIdAdapter::BookRefIdAdapter (const EnchantableColumns& columns,
|
|
const RefIdColumn *bookType, const RefIdColumn *skill, const RefIdColumn *text)
|
|
: EnchantableRefIdAdapter<ESM::Book> (UniversalId::Type_Book, columns),
|
|
mBookType (bookType), mSkill (skill), mText (text)
|
|
{}
|
|
|
|
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==mBookType)
|
|
return record.get().mData.mIsScroll;
|
|
|
|
if (column==mSkill)
|
|
return record.get().mData.mSkillId;
|
|
|
|
if (column==mText)
|
|
return QString::fromUtf8 (record.get().mText.c_str());
|
|
|
|
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)));
|
|
|
|
ESM::Book book = record.get();
|
|
|
|
if (column==mBookType)
|
|
book.mData.mIsScroll = value.toInt();
|
|
else if (column==mSkill)
|
|
book.mData.mSkillId = value.toInt();
|
|
else if (column==mText)
|
|
book.mText = value.toString().toUtf8().data();
|
|
else
|
|
{
|
|
EnchantableRefIdAdapter<ESM::Book>::setData (column, data, index, value);
|
|
|
|
return;
|
|
}
|
|
|
|
record.setModified(book);
|
|
}
|
|
|
|
CSMWorld::ClothingRefIdAdapter::ClothingRefIdAdapter (const EnchantableColumns& columns,
|
|
const RefIdColumn *type, const RefIdColumn *partRef)
|
|
: EnchantableRefIdAdapter<ESM::Clothing> (UniversalId::Type_Clothing, columns), mType (type),
|
|
mPartRef(partRef)
|
|
{}
|
|
|
|
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;
|
|
|
|
if (column==mPartRef)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
|
|
|
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)));
|
|
|
|
ESM::Clothing clothing = record.get();
|
|
|
|
if (column==mType)
|
|
clothing.mData.mType = value.toInt();
|
|
else
|
|
{
|
|
EnchantableRefIdAdapter<ESM::Clothing>::setData (column, data, index, value);
|
|
|
|
return;
|
|
}
|
|
|
|
record.setModified(clothing);
|
|
}
|
|
|
|
CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& columns,
|
|
const RefIdColumn *weight, const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content)
|
|
: NameRefIdAdapter<ESM::Container> (UniversalId::Type_Container, columns), mWeight (weight),
|
|
mOrganic (organic), mRespawn (respawn), mContent(content)
|
|
{}
|
|
|
|
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;
|
|
|
|
if (column==mContent)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
|
|
|
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)));
|
|
|
|
ESM::Container container = record.get();
|
|
|
|
if (column==mWeight)
|
|
container.mWeight = value.toFloat();
|
|
else if (column==mOrganic)
|
|
{
|
|
if (value.toInt())
|
|
container.mFlags |= ESM::Container::Organic;
|
|
else
|
|
container.mFlags &= ~ESM::Container::Organic;
|
|
}
|
|
else if (column==mRespawn)
|
|
{
|
|
if (value.toInt())
|
|
container.mFlags |= ESM::Container::Respawn;
|
|
else
|
|
container.mFlags &= ~ESM::Container::Respawn;
|
|
}
|
|
else
|
|
{
|
|
NameRefIdAdapter<ESM::Container>::setData (column, data, index, value);
|
|
|
|
return;
|
|
}
|
|
|
|
record.setModified(container);
|
|
}
|
|
|
|
CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns)
|
|
: ActorColumns (actorColumns),
|
|
mType(NULL),
|
|
mScale(NULL),
|
|
mOriginal(NULL),
|
|
mAttributes(NULL),
|
|
mAttacks(NULL),
|
|
mMisc(NULL),
|
|
mBloodType(NULL)
|
|
{}
|
|
|
|
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.mScale)
|
|
return record.get().mScale;
|
|
|
|
if (column==mColumns.mOriginal)
|
|
return QString::fromUtf8 (record.get().mOriginal.c_str());
|
|
|
|
if (column==mColumns.mAttributes)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
|
|
|
if (column==mColumns.mAttacks)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
|
|
|
if (column==mColumns.mMisc)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
|
|
|
if (column == mColumns.mBloodType)
|
|
{
|
|
int mask = ESM::Creature::Skeleton | ESM::Creature::Metal;
|
|
|
|
if ((record.get().mFlags & mask) == ESM::Creature::Skeleton)
|
|
return 1;
|
|
|
|
if ((record.get().mFlags & mask) == ESM::Creature::Metal)
|
|
return 2;
|
|
|
|
return 0;
|
|
}
|
|
|
|
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)));
|
|
|
|
ESM::Creature creature = record.get();
|
|
|
|
if (column==mColumns.mType)
|
|
creature.mData.mType = value.toInt();
|
|
else if (column==mColumns.mScale)
|
|
creature.mScale = value.toFloat();
|
|
else if (column==mColumns.mOriginal)
|
|
creature.mOriginal = value.toString().toUtf8().constData();
|
|
else if (column == mColumns.mBloodType)
|
|
{
|
|
int mask = ~(ESM::Creature::Skeleton | ESM::Creature::Metal);
|
|
|
|
if (value.toInt() == 1)
|
|
creature.mFlags = (creature.mFlags & mask) | ESM::Creature::Skeleton;
|
|
else if (value.toInt() == 2)
|
|
creature.mFlags = (creature.mFlags & mask) | ESM::Creature::Metal;
|
|
else
|
|
creature.mFlags = creature.mFlags & mask;
|
|
}
|
|
else
|
|
{
|
|
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
|
mColumns.mFlags.find (column);
|
|
|
|
if (iter!=mColumns.mFlags.end())
|
|
{
|
|
if (value.toInt()!=0)
|
|
creature.mFlags |= iter->second;
|
|
else
|
|
creature.mFlags &= ~iter->second;
|
|
}
|
|
else
|
|
{
|
|
ActorRefIdAdapter<ESM::Creature>::setData (column, data, index, value);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
record.setModified(creature);
|
|
}
|
|
|
|
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)));
|
|
|
|
ESM::Door door = record.get();
|
|
|
|
if (column==mOpenSound)
|
|
door.mOpenSound = value.toString().toUtf8().constData();
|
|
else if (column==mCloseSound)
|
|
door.mCloseSound = value.toString().toUtf8().constData();
|
|
else
|
|
{
|
|
NameRefIdAdapter<ESM::Door>::setData (column, data, index, value);
|
|
|
|
return;
|
|
}
|
|
|
|
record.setModified(door);
|
|
}
|
|
|
|
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());
|
|
|
|
if (column == mColumns.mEmitterType)
|
|
{
|
|
int mask = ESM::Light::Flicker | ESM::Light::FlickerSlow | ESM::Light::Pulse | ESM::Light::PulseSlow;
|
|
|
|
if ((record.get().mData.mFlags & mask) == ESM::Light::Flicker)
|
|
return 1;
|
|
|
|
if ((record.get().mData.mFlags & mask) == ESM::Light::FlickerSlow)
|
|
return 2;
|
|
|
|
if ((record.get().mData.mFlags & mask) == ESM::Light::Pulse)
|
|
return 3;
|
|
|
|
if ((record.get().mData.mFlags & mask) == ESM::Light::PulseSlow)
|
|
return 4;
|
|
|
|
return 0;
|
|
}
|
|
|
|
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)));
|
|
|
|
ESM::Light light = record.get();
|
|
|
|
if (column==mColumns.mTime)
|
|
light.mData.mTime = value.toInt();
|
|
else if (column==mColumns.mRadius)
|
|
light.mData.mRadius = value.toInt();
|
|
else if (column==mColumns.mColor)
|
|
light.mData.mColor = value.toInt();
|
|
else if (column==mColumns.mSound)
|
|
light.mSound = value.toString().toUtf8().constData();
|
|
else if (column == mColumns.mEmitterType)
|
|
{
|
|
int mask = ~(ESM::Light::Flicker | ESM::Light::FlickerSlow | ESM::Light::Pulse | ESM::Light::PulseSlow);
|
|
|
|
if (value.toInt() == 0)
|
|
light.mData.mFlags = light.mData.mFlags & mask;
|
|
else if (value.toInt() == 1)
|
|
light.mData.mFlags = (light.mData.mFlags & mask) | ESM::Light::Flicker;
|
|
else if (value.toInt() == 2)
|
|
light.mData.mFlags = (light.mData.mFlags & mask) | ESM::Light::FlickerSlow;
|
|
else if (value.toInt() == 3)
|
|
light.mData.mFlags = (light.mData.mFlags & mask) | ESM::Light::Pulse;
|
|
else
|
|
light.mData.mFlags = (light.mData.mFlags & mask) | ESM::Light::PulseSlow;
|
|
}
|
|
else
|
|
{
|
|
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
|
mColumns.mFlags.find (column);
|
|
|
|
if (iter!=mColumns.mFlags.end())
|
|
{
|
|
if (value.toInt()!=0)
|
|
light.mData.mFlags |= iter->second;
|
|
else
|
|
light.mData.mFlags &= ~iter->second;
|
|
}
|
|
else
|
|
{
|
|
InventoryRefIdAdapter<ESM::Light>::setData (column, data, index, value);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
record.setModified (light);
|
|
}
|
|
|
|
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)));
|
|
|
|
ESM::Miscellaneous misc = record.get();
|
|
|
|
if (column==mKey)
|
|
misc.mData.mIsKey = value.toInt();
|
|
else
|
|
{
|
|
InventoryRefIdAdapter<ESM::Miscellaneous>::setData (column, data, index, value);
|
|
|
|
return;
|
|
}
|
|
|
|
record.setModified(misc);
|
|
}
|
|
|
|
CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns)
|
|
: ActorColumns (actorColumns),
|
|
mRace(NULL),
|
|
mClass(NULL),
|
|
mFaction(NULL),
|
|
mHair(NULL),
|
|
mHead(NULL),
|
|
mAttributes(NULL),
|
|
mSkills(NULL),
|
|
mMisc(NULL),
|
|
mBloodType(NULL)
|
|
{}
|
|
|
|
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());
|
|
|
|
if (column==mColumns.mAttributes || column==mColumns.mSkills)
|
|
{
|
|
if ((record.get().mFlags & ESM::NPC::Autocalc) != 0)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_None);
|
|
else
|
|
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
|
}
|
|
|
|
if (column==mColumns.mMisc)
|
|
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
|
|
|
if (column == mColumns.mBloodType)
|
|
{
|
|
int mask = ESM::NPC::Skeleton | ESM::NPC::Metal;
|
|
|
|
if ((record.get().mFlags & mask) == ESM::NPC::Skeleton)
|
|
return 1;
|
|
|
|
if ((record.get().mFlags & mask) == ESM::NPC::Metal)
|
|
return 2;
|
|
|
|
return 0;
|
|
}
|
|
|
|
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)));
|
|
|
|
ESM::NPC npc = record.get();
|
|
|
|
if (column==mColumns.mRace)
|
|
npc.mRace = value.toString().toUtf8().constData();
|
|
else if (column==mColumns.mClass)
|
|
npc.mClass = value.toString().toUtf8().constData();
|
|
else if (column==mColumns.mFaction)
|
|
npc.mFaction = value.toString().toUtf8().constData();
|
|
else if (column==mColumns.mHair)
|
|
npc.mHair = value.toString().toUtf8().constData();
|
|
else if (column==mColumns.mHead)
|
|
npc.mHead = value.toString().toUtf8().constData();
|
|
else if (column == mColumns.mBloodType)
|
|
{
|
|
int mask = ~(ESM::NPC::Skeleton | ESM::NPC::Metal);
|
|
|
|
if (value.toInt() == 1)
|
|
npc.mFlags = (npc.mFlags & mask) | ESM::NPC::Skeleton;
|
|
else if (value.toInt() == 2)
|
|
npc.mFlags = (npc.mFlags & mask) | ESM::NPC::Metal;
|
|
else
|
|
npc.mFlags = npc.mFlags & mask;
|
|
}
|
|
else
|
|
{
|
|
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
|
|
mColumns.mFlags.find (column);
|
|
|
|
if (iter!=mColumns.mFlags.end())
|
|
{
|
|
if (value.toInt()!=0)
|
|
npc.mFlags |= iter->second;
|
|
else
|
|
npc.mFlags &= ~iter->second;
|
|
|
|
if (iter->second == ESM::NPC::Autocalc)
|
|
npc.mNpdtType = (value.toInt() != 0) ? ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS
|
|
: ESM::NPC::NPC_DEFAULT;
|
|
}
|
|
else
|
|
{
|
|
ActorRefIdAdapter<ESM::NPC>::setData (column, data, index, value);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
record.setModified (npc);
|
|
}
|
|
|
|
CSMWorld::NpcAttributesRefIdAdapter::NpcAttributesRefIdAdapter ()
|
|
{}
|
|
|
|
void CSMWorld::NpcAttributesRefIdAdapter::addNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int position) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void CSMWorld::NpcAttributesRefIdAdapter::removeNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int rowToRemove) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void CSMWorld::NpcAttributesRefIdAdapter::setNestedTable (const RefIdColumn* column,
|
|
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
Record<ESM::NPC>& record =
|
|
static_cast<Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
|
|
ESM::NPC npc = record.get();
|
|
|
|
// store the whole struct
|
|
npc.mNpdt52 =
|
|
static_cast<const NestedTableWrapper<std::vector<ESM::NPC::NPDTstruct52> > &>(nestedTable).mNestedTable.at(0);
|
|
|
|
record.setModified (npc);
|
|
}
|
|
|
|
CSMWorld::NestedTableWrapperBase* CSMWorld::NpcAttributesRefIdAdapter::nestedTable (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)));
|
|
|
|
// return the whole struct
|
|
std::vector<ESM::NPC::NPDTstruct52> wrap;
|
|
wrap.push_back(record.get().mNpdt52);
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<ESM::NPC::NPDTstruct52> >(wrap);
|
|
}
|
|
|
|
QVariant CSMWorld::NpcAttributesRefIdAdapter::getNestedData (const RefIdColumn *column,
|
|
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
|
|
{
|
|
const Record<ESM::NPC>& record =
|
|
static_cast<const Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
|
|
|
|
const ESM::NPC::NPDTstruct52& npcStruct = record.get().mNpdt52;
|
|
|
|
if (subColIndex == 0)
|
|
return subRowIndex;
|
|
else if (subColIndex == 1)
|
|
switch (subRowIndex)
|
|
{
|
|
case 0: return static_cast<int>(npcStruct.mStrength);
|
|
case 1: return static_cast<int>(npcStruct.mIntelligence);
|
|
case 2: return static_cast<int>(npcStruct.mWillpower);
|
|
case 3: return static_cast<int>(npcStruct.mAgility);
|
|
case 4: return static_cast<int>(npcStruct.mSpeed);
|
|
case 5: return static_cast<int>(npcStruct.mEndurance);
|
|
case 6: return static_cast<int>(npcStruct.mPersonality);
|
|
case 7: return static_cast<int>(npcStruct.mLuck);
|
|
default: return QVariant(); // throw an exception here?
|
|
}
|
|
else
|
|
return QVariant(); // throw an exception here?
|
|
}
|
|
|
|
void CSMWorld::NpcAttributesRefIdAdapter::setNestedData (const RefIdColumn *column,
|
|
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
Record<ESM::NPC>& record =
|
|
static_cast<Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Npc)));
|
|
ESM::NPC npc = record.get();
|
|
ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt52;
|
|
|
|
if (subColIndex == 1)
|
|
switch(subRowIndex)
|
|
{
|
|
case 0: npcStruct.mStrength = static_cast<unsigned char>(value.toInt()); break;
|
|
case 1: npcStruct.mIntelligence = static_cast<unsigned char>(value.toInt()); break;
|
|
case 2: npcStruct.mWillpower = static_cast<unsigned char>(value.toInt()); break;
|
|
case 3: npcStruct.mAgility = static_cast<unsigned char>(value.toInt()); break;
|
|
case 4: npcStruct.mSpeed = static_cast<unsigned char>(value.toInt()); break;
|
|
case 5: npcStruct.mEndurance = static_cast<unsigned char>(value.toInt()); break;
|
|
case 6: npcStruct.mPersonality = static_cast<unsigned char>(value.toInt()); break;
|
|
case 7: npcStruct.mLuck = static_cast<unsigned char>(value.toInt()); break;
|
|
default: return; // throw an exception here?
|
|
}
|
|
else
|
|
return; // throw an exception here?
|
|
|
|
record.setModified (npc);
|
|
}
|
|
|
|
int CSMWorld::NpcAttributesRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
int CSMWorld::NpcAttributesRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
|
{
|
|
// There are 8 attributes
|
|
return 8;
|
|
}
|
|
|
|
CSMWorld::NpcSkillsRefIdAdapter::NpcSkillsRefIdAdapter ()
|
|
{}
|
|
|
|
void CSMWorld::NpcSkillsRefIdAdapter::addNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int position) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void CSMWorld::NpcSkillsRefIdAdapter::removeNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int rowToRemove) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void CSMWorld::NpcSkillsRefIdAdapter::setNestedTable (const RefIdColumn* column,
|
|
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
Record<ESM::NPC>& record =
|
|
static_cast<Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
|
|
ESM::NPC npc = record.get();
|
|
|
|
// store the whole struct
|
|
npc.mNpdt52 =
|
|
static_cast<const NestedTableWrapper<std::vector<ESM::NPC::NPDTstruct52> > &>(nestedTable).mNestedTable.at(0);
|
|
|
|
record.setModified (npc);
|
|
}
|
|
|
|
CSMWorld::NestedTableWrapperBase* CSMWorld::NpcSkillsRefIdAdapter::nestedTable (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)));
|
|
|
|
// return the whole struct
|
|
std::vector<ESM::NPC::NPDTstruct52> wrap;
|
|
wrap.push_back(record.get().mNpdt52);
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<ESM::NPC::NPDTstruct52> >(wrap);
|
|
}
|
|
|
|
QVariant CSMWorld::NpcSkillsRefIdAdapter::getNestedData (const RefIdColumn *column,
|
|
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
|
|
{
|
|
const Record<ESM::NPC>& record =
|
|
static_cast<const Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
|
|
|
|
const ESM::NPC::NPDTstruct52& npcStruct = record.get().mNpdt52;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= ESM::Skill::Length)
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
if (subColIndex == 0)
|
|
return subRowIndex;
|
|
else if (subColIndex == 1)
|
|
return static_cast<int>(npcStruct.mSkills[subRowIndex]);
|
|
else
|
|
return QVariant(); // throw an exception here?
|
|
}
|
|
|
|
void CSMWorld::NpcSkillsRefIdAdapter::setNestedData (const RefIdColumn *column,
|
|
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
Record<ESM::NPC>& record =
|
|
static_cast<Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Npc)));
|
|
ESM::NPC npc = record.get();
|
|
ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt52;
|
|
|
|
if (subRowIndex < 0 || subRowIndex >= ESM::Skill::Length)
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
if (subColIndex == 1)
|
|
npcStruct.mSkills[subRowIndex] = static_cast<unsigned char>(value.toInt());
|
|
else
|
|
return; // throw an exception here?
|
|
|
|
record.setModified (npc);
|
|
}
|
|
|
|
int CSMWorld::NpcSkillsRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
int CSMWorld::NpcSkillsRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
|
{
|
|
// There are 27 skills
|
|
return ESM::Skill::Length;
|
|
}
|
|
|
|
CSMWorld::NpcMiscRefIdAdapter::NpcMiscRefIdAdapter ()
|
|
{}
|
|
|
|
CSMWorld::NpcMiscRefIdAdapter::~NpcMiscRefIdAdapter()
|
|
{}
|
|
|
|
void CSMWorld::NpcMiscRefIdAdapter::addNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int position) const
|
|
{
|
|
throw std::logic_error ("cannot add a row to a fixed table");
|
|
}
|
|
|
|
void CSMWorld::NpcMiscRefIdAdapter::removeNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int rowToRemove) const
|
|
{
|
|
throw std::logic_error ("cannot remove a row to a fixed table");
|
|
}
|
|
|
|
void CSMWorld::NpcMiscRefIdAdapter::setNestedTable (const RefIdColumn* column,
|
|
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
throw std::logic_error ("table operation not supported");
|
|
}
|
|
|
|
CSMWorld::NestedTableWrapperBase* CSMWorld::NpcMiscRefIdAdapter::nestedTable (const RefIdColumn* column,
|
|
const RefIdData& data, int index) const
|
|
{
|
|
throw std::logic_error ("table operation not supported");
|
|
}
|
|
|
|
QVariant CSMWorld::NpcMiscRefIdAdapter::getNestedData (const RefIdColumn *column,
|
|
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
|
|
{
|
|
const Record<ESM::NPC>& record =
|
|
static_cast<const Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
|
|
|
|
bool autoCalc = (record.get().mFlags & ESM::NPC::Autocalc) != 0;
|
|
|
|
if (autoCalc)
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return static_cast<int>(record.get().mNpdt12.mLevel);
|
|
case 1: return QVariant(QVariant::UserType);
|
|
case 2: return QVariant(QVariant::UserType);
|
|
case 3: return QVariant(QVariant::UserType);
|
|
case 4: return QVariant(QVariant::UserType);
|
|
case 5: return static_cast<int>(record.get().mNpdt12.mDisposition);
|
|
case 6: return static_cast<int>(record.get().mNpdt12.mReputation);
|
|
case 7: return static_cast<int>(record.get().mNpdt12.mRank);
|
|
case 8: return record.get().mNpdt12.mGold;
|
|
case 9: return record.get().mPersistent == true;
|
|
default: return QVariant(); // throw an exception here?
|
|
}
|
|
else
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return static_cast<int>(record.get().mNpdt52.mLevel);
|
|
case 1: return static_cast<int>(record.get().mNpdt52.mFactionID);
|
|
case 2: return static_cast<int>(record.get().mNpdt52.mHealth);
|
|
case 3: return static_cast<int>(record.get().mNpdt52.mMana);
|
|
case 4: return static_cast<int>(record.get().mNpdt52.mFatigue);
|
|
case 5: return static_cast<int>(record.get().mNpdt52.mDisposition);
|
|
case 6: return static_cast<int>(record.get().mNpdt52.mReputation);
|
|
case 7: return static_cast<int>(record.get().mNpdt52.mRank);
|
|
case 8: return record.get().mNpdt52.mGold;
|
|
case 9: return record.get().mPersistent == true;
|
|
default: return QVariant(); // throw an exception here?
|
|
}
|
|
}
|
|
|
|
void CSMWorld::NpcMiscRefIdAdapter::setNestedData (const RefIdColumn *column,
|
|
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
Record<ESM::NPC>& record =
|
|
static_cast<Record<ESM::NPC>&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Npc)));
|
|
ESM::NPC npc = record.get();
|
|
|
|
bool autoCalc = (record.get().mFlags & ESM::NPC::Autocalc) != 0;
|
|
|
|
if (autoCalc)
|
|
switch(subColIndex)
|
|
{
|
|
case 0: npc.mNpdt12.mLevel = static_cast<short>(value.toInt()); break;
|
|
case 1: return;
|
|
case 2: return;
|
|
case 3: return;
|
|
case 4: return;
|
|
case 5: npc.mNpdt12.mDisposition = static_cast<signed char>(value.toInt()); break;
|
|
case 6: npc.mNpdt12.mReputation = static_cast<signed char>(value.toInt()); break;
|
|
case 7: npc.mNpdt12.mRank = static_cast<signed char>(value.toInt()); break;
|
|
case 8: npc.mNpdt12.mGold = value.toInt(); break;
|
|
case 9: npc.mPersistent = value.toBool(); break;
|
|
default: return; // throw an exception here?
|
|
}
|
|
else
|
|
switch(subColIndex)
|
|
{
|
|
case 0: npc.mNpdt52.mLevel = static_cast<short>(value.toInt()); break;
|
|
case 1: npc.mNpdt52.mFactionID = static_cast<char>(value.toInt()); break;
|
|
case 2: npc.mNpdt52.mHealth = static_cast<unsigned short>(value.toInt()); break;
|
|
case 3: npc.mNpdt52.mMana = static_cast<unsigned short>(value.toInt()); break;
|
|
case 4: npc.mNpdt52.mFatigue = static_cast<unsigned short>(value.toInt()); break;
|
|
case 5: npc.mNpdt52.mDisposition = static_cast<signed char>(value.toInt()); break;
|
|
case 6: npc.mNpdt52.mReputation = static_cast<signed char>(value.toInt()); break;
|
|
case 7: npc.mNpdt52.mRank = static_cast<signed char>(value.toInt()); break;
|
|
case 8: npc.mNpdt52.mGold = value.toInt(); break;
|
|
case 9: npc.mPersistent = value.toBool(); break;
|
|
default: return; // throw an exception here?
|
|
}
|
|
|
|
record.setModified (npc);
|
|
}
|
|
|
|
int CSMWorld::NpcMiscRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
|
{
|
|
return 10; // Level, FactionID, Health, Mana, Fatigue, Disposition, Reputation, Rank, Gold, Persist
|
|
}
|
|
|
|
int CSMWorld::NpcMiscRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
|
{
|
|
return 1; // fixed at size 1
|
|
}
|
|
|
|
CSMWorld::CreatureAttributesRefIdAdapter::CreatureAttributesRefIdAdapter()
|
|
{}
|
|
|
|
void CSMWorld::CreatureAttributesRefIdAdapter::addNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int position) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void CSMWorld::CreatureAttributesRefIdAdapter::removeNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int rowToRemove) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void CSMWorld::CreatureAttributesRefIdAdapter::setNestedTable (const RefIdColumn* column,
|
|
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
Record<ESM::Creature>& record =
|
|
static_cast<Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
|
ESM::Creature creature = record.get();
|
|
|
|
// store the whole struct
|
|
creature.mData =
|
|
static_cast<const NestedTableWrapper<std::vector<ESM::Creature::NPDTstruct> > &>(nestedTable).mNestedTable.at(0);
|
|
|
|
record.setModified (creature);
|
|
}
|
|
|
|
CSMWorld::NestedTableWrapperBase* CSMWorld::CreatureAttributesRefIdAdapter::nestedTable (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)));
|
|
|
|
// return the whole struct
|
|
std::vector<ESM::Creature::NPDTstruct> wrap;
|
|
wrap.push_back(record.get().mData);
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<ESM::Creature::NPDTstruct> >(wrap);
|
|
}
|
|
|
|
QVariant CSMWorld::CreatureAttributesRefIdAdapter::getNestedData (const RefIdColumn *column,
|
|
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
|
|
{
|
|
const Record<ESM::Creature>& record =
|
|
static_cast<const Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
|
|
|
const ESM::Creature& creature = record.get();
|
|
|
|
if (subColIndex == 0)
|
|
return subRowIndex;
|
|
else if (subColIndex == 1)
|
|
switch (subRowIndex)
|
|
{
|
|
case 0: return creature.mData.mStrength;
|
|
case 1: return creature.mData.mIntelligence;
|
|
case 2: return creature.mData.mWillpower;
|
|
case 3: return creature.mData.mAgility;
|
|
case 4: return creature.mData.mSpeed;
|
|
case 5: return creature.mData.mEndurance;
|
|
case 6: return creature.mData.mPersonality;
|
|
case 7: return creature.mData.mLuck;
|
|
default: return QVariant(); // throw an exception here?
|
|
}
|
|
else
|
|
return QVariant(); // throw an exception here?
|
|
}
|
|
|
|
void CSMWorld::CreatureAttributesRefIdAdapter::setNestedData (const RefIdColumn *column,
|
|
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
Record<ESM::Creature>& record =
|
|
static_cast<Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Creature)));
|
|
ESM::Creature creature = record.get();
|
|
|
|
if (subColIndex == 1)
|
|
switch(subRowIndex)
|
|
{
|
|
case 0: creature.mData.mStrength = value.toInt(); break;
|
|
case 1: creature.mData.mIntelligence = value.toInt(); break;
|
|
case 2: creature.mData.mWillpower = value.toInt(); break;
|
|
case 3: creature.mData.mAgility = value.toInt(); break;
|
|
case 4: creature.mData.mSpeed = value.toInt(); break;
|
|
case 5: creature.mData.mEndurance = value.toInt(); break;
|
|
case 6: creature.mData.mPersonality = value.toInt(); break;
|
|
case 7: creature.mData.mLuck = value.toInt(); break;
|
|
default: return; // throw an exception here?
|
|
}
|
|
else
|
|
return; // throw an exception here?
|
|
|
|
record.setModified (creature);
|
|
}
|
|
|
|
int CSMWorld::CreatureAttributesRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
int CSMWorld::CreatureAttributesRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
|
{
|
|
// There are 8 attributes
|
|
return 8;
|
|
}
|
|
|
|
CSMWorld::CreatureAttackRefIdAdapter::CreatureAttackRefIdAdapter()
|
|
{}
|
|
|
|
void CSMWorld::CreatureAttackRefIdAdapter::addNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int position) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void CSMWorld::CreatureAttackRefIdAdapter::removeNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int rowToRemove) const
|
|
{
|
|
// Do nothing, this table cannot be changed by the user
|
|
}
|
|
|
|
void CSMWorld::CreatureAttackRefIdAdapter::setNestedTable (const RefIdColumn* column,
|
|
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
Record<ESM::Creature>& record =
|
|
static_cast<Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
|
ESM::Creature creature = record.get();
|
|
|
|
// store the whole struct
|
|
creature.mData =
|
|
static_cast<const NestedTableWrapper<std::vector<ESM::Creature::NPDTstruct> > &>(nestedTable).mNestedTable.at(0);
|
|
|
|
record.setModified (creature);
|
|
}
|
|
|
|
CSMWorld::NestedTableWrapperBase* CSMWorld::CreatureAttackRefIdAdapter::nestedTable (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)));
|
|
|
|
// return the whole struct
|
|
std::vector<ESM::Creature::NPDTstruct> wrap;
|
|
wrap.push_back(record.get().mData);
|
|
// deleted by dtor of NestedTableStoring
|
|
return new NestedTableWrapper<std::vector<ESM::Creature::NPDTstruct> >(wrap);
|
|
}
|
|
|
|
QVariant CSMWorld::CreatureAttackRefIdAdapter::getNestedData (const RefIdColumn *column,
|
|
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
|
|
{
|
|
const Record<ESM::Creature>& record =
|
|
static_cast<const Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
|
|
|
const ESM::Creature& creature = record.get();
|
|
|
|
if (subRowIndex < 0 || subRowIndex > 2 || subColIndex < 0 || subColIndex > 2)
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
if (subColIndex == 0)
|
|
return subRowIndex + 1;
|
|
else if (subColIndex < 3) // 1 or 2
|
|
return creature.mData.mAttack[(subRowIndex * 2) + (subColIndex - 1)];
|
|
else
|
|
return QVariant(); // throw an exception here?
|
|
}
|
|
|
|
void CSMWorld::CreatureAttackRefIdAdapter::setNestedData (const RefIdColumn *column,
|
|
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
Record<ESM::Creature>& record =
|
|
static_cast<Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Creature)));
|
|
ESM::Creature creature = record.get();
|
|
|
|
if (subRowIndex < 0 || subRowIndex > 2)
|
|
throw std::runtime_error ("index out of range");
|
|
|
|
if (subColIndex == 1 || subColIndex == 2)
|
|
creature.mData.mAttack[(subRowIndex * 2) + (subColIndex - 1)] = value.toInt();
|
|
else
|
|
return; // throw an exception here?
|
|
|
|
record.setModified (creature);
|
|
}
|
|
|
|
int CSMWorld::CreatureAttackRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
|
{
|
|
return 3;
|
|
}
|
|
|
|
int CSMWorld::CreatureAttackRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
|
{
|
|
// There are 3 attacks
|
|
return 3;
|
|
}
|
|
|
|
CSMWorld::CreatureMiscRefIdAdapter::CreatureMiscRefIdAdapter()
|
|
{}
|
|
|
|
CSMWorld::CreatureMiscRefIdAdapter::~CreatureMiscRefIdAdapter()
|
|
{}
|
|
|
|
void CSMWorld::CreatureMiscRefIdAdapter::addNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int position) const
|
|
{
|
|
throw std::logic_error ("cannot add a row to a fixed table");
|
|
}
|
|
|
|
void CSMWorld::CreatureMiscRefIdAdapter::removeNestedRow (const RefIdColumn *column,
|
|
RefIdData& data, int index, int rowToRemove) const
|
|
{
|
|
throw std::logic_error ("cannot remove a row to a fixed table");
|
|
}
|
|
|
|
void CSMWorld::CreatureMiscRefIdAdapter::setNestedTable (const RefIdColumn* column,
|
|
RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const
|
|
{
|
|
throw std::logic_error ("table operation not supported");
|
|
}
|
|
|
|
CSMWorld::NestedTableWrapperBase* CSMWorld::CreatureMiscRefIdAdapter::nestedTable (const RefIdColumn* column,
|
|
const RefIdData& data, int index) const
|
|
{
|
|
throw std::logic_error ("table operation not supported");
|
|
}
|
|
|
|
QVariant CSMWorld::CreatureMiscRefIdAdapter::getNestedData (const RefIdColumn *column,
|
|
const RefIdData& data, int index, int subRowIndex, int subColIndex) const
|
|
{
|
|
const Record<ESM::Creature>& record =
|
|
static_cast<const Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
|
|
|
const ESM::Creature& creature = record.get();
|
|
|
|
switch (subColIndex)
|
|
{
|
|
case 0: return creature.mData.mLevel;
|
|
case 1: return creature.mData.mHealth;
|
|
case 2: return creature.mData.mMana;
|
|
case 3: return creature.mData.mFatigue;
|
|
case 4: return creature.mData.mSoul;
|
|
case 5: return creature.mData.mCombat;
|
|
case 6: return creature.mData.mMagic;
|
|
case 7: return creature.mData.mStealth;
|
|
case 8: return creature.mData.mGold;
|
|
default: return QVariant(); // throw an exception here?
|
|
}
|
|
}
|
|
|
|
void CSMWorld::CreatureMiscRefIdAdapter::setNestedData (const RefIdColumn *column,
|
|
RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const
|
|
{
|
|
Record<ESM::Creature>& record =
|
|
static_cast<Record<ESM::Creature>&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Creature)));
|
|
ESM::Creature creature = record.get();
|
|
|
|
switch(subColIndex)
|
|
{
|
|
case 0: creature.mData.mLevel = value.toInt(); break;
|
|
case 1: creature.mData.mHealth = value.toInt(); break;
|
|
case 2: creature.mData.mMana = value.toInt(); break;
|
|
case 3: creature.mData.mFatigue = value.toInt(); break;
|
|
case 4: creature.mData.mSoul = value.toInt(); break;
|
|
case 5: creature.mData.mCombat = value.toInt(); break;
|
|
case 6: creature.mData.mMagic = value.toInt(); break;
|
|
case 7: creature.mData.mStealth = value.toInt(); break;
|
|
case 8: creature.mData.mGold = value.toInt(); break;
|
|
default: return; // throw an exception here?
|
|
}
|
|
|
|
record.setModified (creature);
|
|
}
|
|
|
|
int CSMWorld::CreatureMiscRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
|
{
|
|
return 9; // Level, Health, Mana, Fatigue, Soul, Combat, Magic, Steath, Gold
|
|
}
|
|
|
|
int CSMWorld::CreatureMiscRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const
|
|
{
|
|
return 1; // fixed at size 1
|
|
}
|
|
|
|
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)));
|
|
|
|
ESM::Weapon weapon = record.get();
|
|
|
|
if (column==mColumns.mType)
|
|
weapon.mData.mType = value.toInt();
|
|
else if (column==mColumns.mHealth)
|
|
weapon.mData.mHealth = value.toInt();
|
|
else if (column==mColumns.mSpeed)
|
|
weapon.mData.mSpeed = value.toFloat();
|
|
else if (column==mColumns.mReach)
|
|
weapon.mData.mReach = value.toFloat();
|
|
else if (column==mColumns.mChop[0])
|
|
weapon.mData.mChop[0] = value.toInt();
|
|
else if (column==mColumns.mChop[1])
|
|
weapon.mData.mChop[1] = value.toInt();
|
|
else if (column==mColumns.mSlash[0])
|
|
weapon.mData.mSlash[0] = value.toInt();
|
|
else if (column==mColumns.mSlash[1])
|
|
weapon.mData.mSlash[1] = value.toInt();
|
|
else if (column==mColumns.mThrust[0])
|
|
weapon.mData.mThrust[0] = value.toInt();
|
|
else if (column==mColumns.mThrust[1])
|
|
weapon.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)
|
|
weapon.mData.mFlags |= iter->second;
|
|
else
|
|
weapon.mData.mFlags &= ~iter->second;
|
|
}
|
|
else
|
|
{
|
|
EnchantableRefIdAdapter<ESM::Weapon>::setData (column, data, index, value);
|
|
return; // Don't overwrite changes made by base class
|
|
}
|
|
}
|
|
|
|
record.setModified(weapon);
|
|
}
|