Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629#include "refidadapterimp.hpp"
#include <stdexcept>
#include <apps/opencs/model/world/columnbase.hpp>#include <apps/opencs/model/world/disabletag.hpp>#include <apps/opencs/model/world/record.hpp>#include <apps/opencs/model/world/refiddata.hpp>#include <apps/opencs/model/world/universalid.hpp>
#include <components/esm/attr.hpp>#include <components/esm3/loadcont.hpp>#include <components/esm3/loadmgef.hpp>#include <components/esm3/loadskil.hpp>
#include "idcollection.hpp"#include "nestedtablewrapper.hpp"
CSMWorld::PotionColumns::PotionColumns(const InventoryColumns& columns) : InventoryColumns(columns) , mEffects(nullptr){}
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.mFlags & ESM::Potion::Autocalc;
// 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.mFlags = value.toBool(); else { InventoryRefIdAdapter<ESM::Potion>::setData(column, data, index, value);
return; }
record.setModified(potion);}
CSMWorld::IngredientColumns::IngredientColumns(const InventoryColumns& columns) : InventoryColumns(columns) , mEffects(nullptr){}
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;}
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");
ESM::RefId effectId = record.get().mData.mEffectID[subRowIndex]; bool targetSkill = false, targetAttribute = false; if (!effectId.empty()) { int recordIndex = mMagicEffects.searchId(effectId); if (recordIndex != -1) { const ESM::MagicEffect& mgef = mMagicEffects.getRecord(recordIndex).get(); targetSkill = mgef.mData.mFlags & ESM::MagicEffect::TargetSkill; targetAttribute = mgef.mData.mFlags & ESM::MagicEffect::TargetAttribute; } }
switch (subColIndex) { case 0: return ESM::MagicEffect::refIdToIndex(effectId); case 1: { if (targetSkill) return ESM::Skill::refIdToIndex(record.get().mData.mSkills[subRowIndex]); else return QVariant(); } case 2: { if (targetAttribute) return ESM::Attribute::refIdToIndex(record.get().mData.mAttributes[subRowIndex]); else 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");
ESM::RefId effectId = ESM::MagicEffect::indexToRefId(value.toInt()); bool targetSkill = false, targetAttribute = false;
switch (subColIndex) { case 0: ingredient.mData.mEffectID[subRowIndex] = effectId; if (!effectId.empty()) { int recordIndex = mMagicEffects.searchId(effectId); if (recordIndex != -1) { const ESM::MagicEffect& mgef = mMagicEffects.getRecord(recordIndex).get(); targetSkill = mgef.mData.mFlags & ESM::MagicEffect::TargetSkill; targetAttribute = mgef.mData.mFlags & ESM::MagicEffect::TargetAttribute; } }
if (!targetSkill) ingredient.mData.mSkills[subRowIndex] = ESM::RefId(); if (!targetAttribute) ingredient.mData.mAttributes[subRowIndex] = ESM::RefId(); break; case 1: ingredient.mData.mSkills[subRowIndex] = ESM::Skill::indexToRefId(value.toInt()); break; case 2: ingredient.mData.mAttributes[subRowIndex] = ESM::Attribute::indexToRefId(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 ESM::Skill::refIdToIndex(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 = ESM::Skill::indexToRefId(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(nullptr) , mScale(nullptr) , mOriginal(nullptr) , mAttributes(nullptr) , mAttacks(nullptr) , mMisc(nullptr) , mBloodType(nullptr){}
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.getRefIdString().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) return record.get().mBloodType;
{ 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; }
{ std::map<const RefIdColumn*, unsigned int>::const_iterator iter = mColumns.mServices.find(column); if (iter != mColumns.mServices.end() && iter->second == ESM::NPC::Training) return QVariant(); }
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 = ESM::RefId::stringRefId(value.toString().toUtf8().constData()); else if (column == mColumns.mBloodType) creature.mBloodType = 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) 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.getRefIdString().c_str());
if (column == mCloseSound) return QString::fromUtf8(record.get().mCloseSound.getRefIdString().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 = ESM::RefId::stringRefId(value.toString().toUtf8().constData()); else if (column == mCloseSound) door.mCloseSound = ESM::RefId::stringRefId(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) , mTime(nullptr) , mRadius(nullptr) , mColor(nullptr) , mSound(nullptr) , mEmitterType(nullptr){}
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.getRefIdString().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 = ESM::RefId::stringRefId(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 bool(record.get().mData.mFlags & ESM::Miscellaneous::Key);
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.mFlags = value.toInt(); else { InventoryRefIdAdapter<ESM::Miscellaneous>::setData(column, data, index, value);
return; }
record.setModified(misc);}
CSMWorld::NpcColumns::NpcColumns(const ActorColumns& actorColumns) : ActorColumns(actorColumns) , mRace(nullptr) , mClass(nullptr) , mFaction(nullptr) , mHair(nullptr) , mHead(nullptr) , mAttributes(nullptr) , mSkills(nullptr) , mMisc(nullptr) , mBloodType(nullptr) , mGender(nullptr){}
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.getRefIdString().c_str());
if (column == mColumns.mClass) return QString::fromUtf8(record.get().mClass.getRefIdString().c_str());
if (column == mColumns.mFaction) return QString::fromUtf8(record.get().mFaction.getRefIdString().c_str());
if (column == mColumns.mHair) return QString::fromUtf8(record.get().mHair.getRefIdString().c_str());
if (column == mColumns.mHead) return QString::fromUtf8(record.get().mHead.getRefIdString().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) return record.get().mBloodType;
if (column == mColumns.mGender) { // Implemented this way to allow additional gender types in the future. if ((record.get().mFlags & ESM::NPC::Female) == ESM::NPC::Female) return 1;
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 = ESM::RefId::stringRefId(value.toString().toUtf8().constData()); else if (column == mColumns.mClass) npc.mClass = ESM::RefId::stringRefId(value.toString().toUtf8().constData()); else if (column == mColumns.mFaction) npc.mFaction = ESM::RefId::stringRefId(value.toString().toUtf8().constData()); else if (column == mColumns.mHair) npc.mHair = ESM::RefId::stringRefId(value.toString().toUtf8().constData()); else if (column == mColumns.mHead) npc.mHead = ESM::RefId::stringRefId(value.toString().toUtf8().constData()); else if (column == mColumns.mBloodType) npc.mBloodType = value.toInt(); else if (column == mColumns.mGender) { // Implemented this way to allow additional gender types in the future. if (value.toInt() == 1) npc.mFlags = (npc.mFlags & ~ESM::NPC::Female) | ESM::NPC::Female; else npc.mFlags = npc.mFlags & ~ESM::NPC::Female; } 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);}
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.mNpdt = 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().mNpdt); // 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().mNpdt;
if (subColIndex == 0) return subRowIndex; else if (subColIndex == 1) { const ESM::RefId attribute = ESM::Attribute::indexToRefId(subRowIndex); if (!attribute.empty()) return static_cast<int>(npcStruct.getAttribute(attribute)); } 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.mNpdt;
const ESM::RefId attribute = ESM::Attribute::indexToRefId(subRowIndex); if (subColIndex == 1 && !attribute.empty()) npcStruct.mAttributes[attribute] = static_cast<unsigned char>(value.toInt()); 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{ return ESM::Attribute::Length;}
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.mNpdt = 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().mNpdt); // 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().mNpdt;
const ESM::RefId skill = ESM::Skill::indexToRefId(subRowIndex); if (skill.empty()) throw std::runtime_error("index out of range");
if (subColIndex == 0) return subRowIndex; else if (subColIndex == 1) return static_cast<int>(npcStruct.getSkill(skill)); 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.mNpdt;
const ESM::RefId skill = ESM::Skill::indexToRefId(subRowIndex); if (skill.empty()) throw std::runtime_error("index out of range");
if (subColIndex == 1) npcStruct.mSkills[skill] = 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;}
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().mNpdt.mLevel); case 1: return CSMWorld::DisableTag::getVariant(); case 2: return CSMWorld::DisableTag::getVariant(); case 3: return CSMWorld::DisableTag::getVariant(); case 4: return static_cast<int>(record.get().mNpdt.mDisposition); case 5: return static_cast<int>(record.get().mNpdt.mReputation); case 6: return static_cast<int>(record.get().mNpdt.mRank); case 7: return record.get().mNpdt.mGold; default: return QVariant(); // throw an exception here? } else switch (subColIndex) { case 0: return static_cast<int>(record.get().mNpdt.mLevel); case 1: return static_cast<int>(record.get().mNpdt.mHealth); case 2: return static_cast<int>(record.get().mNpdt.mMana); case 3: return static_cast<int>(record.get().mNpdt.mFatigue); case 4: return static_cast<int>(record.get().mNpdt.mDisposition); case 5: return static_cast<int>(record.get().mNpdt.mReputation); case 6: return static_cast<int>(record.get().mNpdt.mRank); case 7: return record.get().mNpdt.mGold; 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.mNpdt.mLevel = static_cast<short>(value.toInt()); break; case 1: return; case 2: return; case 3: return; case 4: npc.mNpdt.mDisposition = static_cast<signed char>(value.toInt()); break; case 5: npc.mNpdt.mReputation = static_cast<signed char>(value.toInt()); break; case 6: npc.mNpdt.mRank = static_cast<signed char>(value.toInt()); break; case 7: npc.mNpdt.mGold = value.toInt(); break; default: return; // throw an exception here? } else switch (subColIndex) { case 0: npc.mNpdt.mLevel = static_cast<short>(value.toInt()); break; case 1: npc.mNpdt.mHealth = static_cast<unsigned short>(value.toInt()); break; case 2: npc.mNpdt.mMana = static_cast<unsigned short>(value.toInt()); break; case 3: npc.mNpdt.mFatigue = static_cast<unsigned short>(value.toInt()); break; case 4: npc.mNpdt.mDisposition = static_cast<signed char>(value.toInt()); break; case 5: npc.mNpdt.mReputation = static_cast<signed char>(value.toInt()); break; case 6: npc.mNpdt.mRank = static_cast<signed char>(value.toInt()); break; case 7: npc.mNpdt.mGold = value.toInt(); break; default: return; // throw an exception here? }
record.setModified(npc);}
int CSMWorld::NpcMiscRefIdAdapter::getNestedColumnsCount(const RefIdColumn* column, const RefIdData& data) const{ return 8; // Level, Health, Mana, Fatigue, Disposition, Reputation, Rank, Gold}
int CSMWorld::NpcMiscRefIdAdapter::getNestedRowsCount(const RefIdColumn* column, const RefIdData& data, int index) const{ return 1; // fixed at size 1}
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) { const ESM::RefId attribute = ESM::Attribute::indexToRefId(subRowIndex); if (!attribute.empty()) return creature.mData.getAttribute(attribute); } 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)));
const ESM::RefId attribute = ESM::Attribute::indexToRefId(subRowIndex); if (subColIndex == 1 && !attribute.empty()) { ESM::Creature creature = record.get(); creature.mData.mAttributes[attribute] = value.toInt(); record.setModified(creature); } // throw an exception here?}
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{ return ESM::Attribute::Length;}
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) throw std::runtime_error("index out of range");
if (subColIndex == 0) return subRowIndex + 1; else if (subColIndex == 1 || subColIndex == 2) return creature.mData.mAttack[(subRowIndex * 2) + (subColIndex - 1)]; else throw std::runtime_error("index out of range");}
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;}
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) , mType(nullptr) , mHealth(nullptr) , mSpeed(nullptr) , mReach(nullptr) , mChop{ nullptr } , mSlash{ nullptr } , mThrust{ nullptr }{}
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 ESM::Weapon::refIdToIndex(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 = ESM::Weapon::indexToRefId(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);}