diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 675352d35c..0ab33065b7 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -2265,97 +2265,6 @@ namespace CSMWorld } }; - template - struct PathgridPointListColumn : public Column - { - PathgridPointListColumn () - : Column (Columns::ColumnId_PathgridPoints, - ColumnBase::Display_PathgridPointList, ColumnBase::Flag_Dialogue) - {} - - virtual QVariant get (const Record& record) const - { - return true; // required by IdTree::hasChildren() - } - - virtual bool isEditable() const - { - return true; - } - }; - - struct PathgridIndexColumn : public NestableColumn - { - PathgridIndexColumn() - : NestableColumn (Columns::ColumnId_PathgridIndex, - ColumnBase::Display_Integer, ColumnBase::Flag_Dialogue) - {} - - virtual bool isEditable() const - { - return false; - } - }; - - struct PathgridPointColumn : public NestableColumn - { - PathgridPointColumn(int index) - : NestableColumn (Columns::ColumnId_PathgridPosX+index, - ColumnBase::Display_Integer, ColumnBase::Flag_Dialogue) - {} - - virtual bool isEditable() const - { - return true; - } - }; - - template - struct PathgridEdgeListColumn : public Column - { - PathgridEdgeListColumn () - : Column (Columns::ColumnId_PathgridEdges, - ColumnBase::Display_PathgridEdgeList, ColumnBase::Flag_Dialogue) - {} - - virtual QVariant get (const Record& record) const - { - return true; // required by IdTree::hasChildren() - } - - virtual bool isEditable() const - { - return true; - } - - }; - - struct PathgridEdgeIndexColumn : public NestableColumn - { - PathgridEdgeIndexColumn() - : NestableColumn (Columns::ColumnId_PathgridEdgeIndex, - ColumnBase::Display_Integer, ColumnBase::Flag_Dialogue) - {} - - virtual bool isEditable() const - { - return false; - } - }; - - struct PathgridEdgeColumn : public NestableColumn - { - PathgridEdgeColumn (int index) - : NestableColumn (Columns::ColumnId_PathgridEdge0+index, - ColumnBase::Display_Integer, ColumnBase::Flag_Dialogue) - {} - - virtual bool isEditable() const - { - return true; - } - }; - template struct NestedParentColumn : public Column { @@ -2389,13 +2298,16 @@ namespace CSMWorld struct NestedIntegerColumn : public NestableColumn { - NestedIntegerColumn (Columns::ColumnId id) + bool mIsEditable; + + NestedIntegerColumn (Columns::ColumnId id, bool isEditable = true) : NestableColumn (id, ColumnBase::Display_Integer, ColumnBase::Flag_Dialogue) + , mIsEditable(isEditable) {} virtual bool isEditable() const { - return true; + return mIsEditable; } }; } diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index a2843d3e85..efe9a51167 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -241,6 +241,12 @@ namespace CSMWorld //{ ColumnId_FactionID, "Faction ID"}, { ColumnId_FactionReaction, "Reaction"}, + { ColumnId_EffectList, "Effects"}, + { ColumnId_EffectId, "ID"}, + { ColumnId_EffectAttribute, "Attrib"}, + { ColumnId_EffectRange, "Range"}, + { ColumnId_EffectArea, "Area"}, + { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, { ColumnId_UseValue3, "Use value 3" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index a1dc893932..6b3791042c 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -230,6 +230,12 @@ namespace CSMWorld //ColumnId_FactionID = 212, ColumnId_FactionReaction = 213, + ColumnId_EffectList = 214, + ColumnId_EffectId = 215, + ColumnId_EffectAttribute = 216, + ColumnId_EffectRange = 217, + ColumnId_EffectArea = 218, + // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. ColumnId_UseValue1 = 0x10000, diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 74b418b304..86cf3bb441 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -189,6 +189,27 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mSpells.addColumn (new FlagColumn (Columns::ColumnId_AutoCalc, 0x1)); mSpells.addColumn (new FlagColumn (Columns::ColumnId_StarterSpell, 0x2)); mSpells.addColumn (new FlagColumn (Columns::ColumnId_AlwaysSucceeds, 0x4)); + // Spell effects + NestedParentColumn *spellEffect = + new NestedParentColumn (Columns::ColumnId_EffectList); + mSpells.addColumn (spellEffect); + mSpells.addAdapter (std::make_pair(spellEffect, new EffectsListAdapter ())); + mSpells.getNestableColumn(mSpells.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_EffectId)); + mSpells.getNestableColumn(mSpells.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_Skill)); + mSpells.getNestableColumn(mSpells.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_EffectAttribute)); + mSpells.getNestableColumn(mSpells.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_EffectRange)); + mSpells.getNestableColumn(mSpells.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_EffectArea)); + mSpells.getNestableColumn(mSpells.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_Duration)); // reuse from light + mSpells.getNestableColumn(mSpells.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_MinRange)); // reuse from sound + mSpells.getNestableColumn(mSpells.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_MaxRange)); // reuse from sound mTopics.addColumn (new StringIdColumn); mTopics.addColumn (new RecordStateColumn); @@ -242,6 +263,27 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mEnchantments.addColumn (new CostColumn); mEnchantments.addColumn (new ChargesColumn2); mEnchantments.addColumn (new AutoCalcColumn); + // Enchantment effects + NestedParentColumn *enchantmentEffect = + new NestedParentColumn (Columns::ColumnId_EffectList); + mEnchantments.addColumn (enchantmentEffect); + mEnchantments.addAdapter (std::make_pair(enchantmentEffect, new EffectsListAdapter ())); + mEnchantments.getNestableColumn(mEnchantments.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_EffectId)); + mEnchantments.getNestableColumn(mEnchantments.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_Skill)); + mEnchantments.getNestableColumn(mEnchantments.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_EffectAttribute)); + mEnchantments.getNestableColumn(mEnchantments.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_EffectRange)); + mEnchantments.getNestableColumn(mEnchantments.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_EffectArea)); + mEnchantments.getNestableColumn(mEnchantments.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_Duration)); // reuse from light + mEnchantments.getNestableColumn(mEnchantments.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_MinRange)); // reuse from sound + mEnchantments.getNestableColumn(mEnchantments.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_MaxRange)); // reuse from sound mBodyParts.addColumn (new StringIdColumn); mBodyParts.addColumn (new RecordStateColumn); @@ -289,23 +331,32 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mPathgrids.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Pathgrid)); // new object deleted in dtor of Collection - PathgridPointListColumn *pointList = new PathgridPointListColumn (); + NestedParentColumn *pointList = + new NestedParentColumn (Columns::ColumnId_PathgridPoints); mPathgrids.addColumn (pointList); // new object deleted in dtor of SubCellCollection mPathgrids.addAdapter (std::make_pair(pointList, new PathgridPointListAdapter ())); // new objects deleted in dtor of NestableColumn // WARNING: The order of the columns below are assumed in PathgridPointListAdapter - mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn(new PathgridIndexColumn ()); - mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn(new PathgridPointColumn (0)); - mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn(new PathgridPointColumn (1)); - mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn(new PathgridPointColumn (2)); + mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_PathgridIndex, false)); + mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_PathgridPosX)); + mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_PathgridPosY)); + mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_PathgridPosZ)); - PathgridEdgeListColumn *edgeList = new PathgridEdgeListColumn (); + NestedParentColumn *edgeList = + new NestedParentColumn (Columns::ColumnId_PathgridEdges); mPathgrids.addColumn (edgeList); mPathgrids.addAdapter (std::make_pair(edgeList, new PathgridEdgeListAdapter ())); - mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn(new PathgridEdgeIndexColumn ()); - mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn(new PathgridEdgeColumn (0)); - mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn(new PathgridEdgeColumn (1)); + mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_PathgridEdgeIndex, false)); + mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_PathgridEdge0)); + mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn( + new NestedIntegerColumn (Columns::ColumnId_PathgridEdge1)); mStartScripts.addColumn (new StringIdColumn); mStartScripts.addColumn (new RecordStateColumn); @@ -373,13 +424,13 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc addModel (new IdTable (&mScripts), UniversalId::Type_Script); addModel (new IdTree (&mRegions, &mRegions), UniversalId::Type_Region); addModel (new IdTree (&mBirthsigns, &mBirthsigns), UniversalId::Type_Birthsign); - addModel (new IdTable (&mSpells), UniversalId::Type_Spell); + addModel (new IdTree (&mSpells, &mSpells), UniversalId::Type_Spell); addModel (new IdTable (&mTopics), UniversalId::Type_Topic); addModel (new IdTable (&mJournals), UniversalId::Type_Journal); addModel (new IdTable (&mTopicInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_TopicInfo); addModel (new IdTable (&mJournalInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_JournalInfo); addModel (new IdTable (&mCells, IdTable::Feature_ViewId), UniversalId::Type_Cell); - addModel (new IdTable (&mEnchantments), UniversalId::Type_Enchantment); + addModel (new IdTree (&mEnchantments, &mEnchantments), UniversalId::Type_Enchantment); addModel (new IdTable (&mBodyParts), UniversalId::Type_BodyPart); addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen); addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 2d2fd974c3..5ab69ac10d 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -75,10 +75,10 @@ namespace CSMWorld IdCollection mScripts; NestedIdCollection mRegions; NestedIdCollection mBirthsigns; - IdCollection mSpells; + NestedIdCollection mSpells; IdCollection mTopics; IdCollection mJournals; - IdCollection mEnchantments; + NestedIdCollection mEnchantments; IdCollection mBodyParts; IdCollection mMagicEffects; SubCellCollection mPathgrids; diff --git a/apps/opencs/model/world/idadapterimp.hpp b/apps/opencs/model/world/idadapterimp.hpp index c49435f1c8..219032dd3d 100644 --- a/apps/opencs/model/world/idadapterimp.hpp +++ b/apps/opencs/model/world/idadapterimp.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "idadapter.hpp" #include "nestedtablewrapper.hpp" @@ -583,6 +584,124 @@ namespace CSMWorld return static_cast(record.get().mPowers.mList.size()); } }; + + template + class EffectsListAdapter : public NestedIdAdapter + { + public: + EffectsListAdapter () {} + + virtual void addNestedRow(Record& record, int position) const + { + ESXRecordT magic = record.get(); + + std::vector& effectsList = magic.mEffects.mList; + + // blank row + ESM::ENAMstruct effect; + effect.mEffectID = 0; + effect.mSkill = 0; + effect.mAttribute = 0; + effect.mRange = 0; + effect.mArea = 0; + effect.mDuration = 0; + effect.mMagnMin = 0; + effect.mMagnMax = 0; + + effectsList.insert(effectsList.begin()+position, effect); + + record.setModified (magic); + } + + virtual void removeNestedRow(Record& record, int rowToRemove) const + { + ESXRecordT magic = record.get(); + + std::vector& effectsList = magic.mEffects.mList; + + if (rowToRemove < 0 || rowToRemove >= static_cast (effectsList.size())) + throw std::runtime_error ("index out of range"); + + effectsList.erase(effectsList.begin()+rowToRemove); + + record.setModified (magic); + } + + virtual void setNestedTable(Record& record, const NestedTableWrapperBase& nestedTable) const + { + record.get().mEffects.mList = + static_cast >&>(nestedTable).mNestedTable; + } + + virtual NestedTableWrapperBase* nestedTable(const Record& record) const + { + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(record.get().mEffects.mList); + } + + virtual QVariant getNestedData(const Record& record, int subRowIndex, int subColIndex) const + { + ESXRecordT magic = record.get(); + + std::vector& effectsList = magic.mEffects.mList; + + if (subRowIndex < 0 || subRowIndex >= static_cast (effectsList.size())) + throw std::runtime_error ("index out of range"); + + ESM::ENAMstruct effect = effectsList[subRowIndex]; + switch (subColIndex) + { + case 0: return effect.mEffectID; + case 1: return effect.mSkill; + case 2: return effect.mAttribute; + case 3: return effect.mRange; + case 4: return effect.mArea; + case 5: return effect.mDuration; + case 6: return effect.mMagnMin; + case 7: return effect.mMagnMax; + default: throw std::runtime_error("Magic Effects subcolumn index out of range"); + } + } + + virtual void setNestedData(Record& record, const QVariant& value, + int subRowIndex, int subColIndex) const + { + ESXRecordT magic = record.get(); + + std::vector& effectsList = magic.mEffects.mList; + + if (subRowIndex < 0 || subRowIndex >= static_cast (effectsList.size())) + throw std::runtime_error ("index out of range"); + + ESM::ENAMstruct effect = effectsList[subRowIndex]; + switch (subColIndex) + { + case 0: effect.mEffectID = static_cast(value.toInt()); break; + case 1: effect.mSkill = static_cast(value.toInt()); break; + case 2: effect.mAttribute = static_cast(value.toInt()); break; + case 3: effect.mRange = value.toInt(); break; + case 4: effect.mArea = value.toInt(); break; + case 5: effect.mDuration = value.toInt(); break; + case 6: effect.mMagnMin = value.toInt(); break; + case 7: effect.mMagnMax = value.toInt(); break; + default: throw std::runtime_error("Magic Effects subcolumn index out of range"); + } + + magic.mEffects.mList[subRowIndex] = effect; + + record.setModified (magic); + } + + virtual int getNestedColumnsCount(const Record& record) const + { + return 8; + } + + virtual int getNestedRowsCount(const Record& record) const + { + return static_cast(record.get().mEffects.mList.size()); + } + }; } #endif // CSM_WOLRD_IDADAPTERIMP_H