#include "refidcollection.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "columns.hpp" #include "nestedcoladapterimp.hpp" #include "nestedtablewrapper.hpp" #include "refidadapter.hpp" #include "refidadapterimp.hpp" CSMWorld::RefIdColumn::RefIdColumn(int columnId, Display displayType, int flag, bool editable, bool userEditable) : NestableColumn(columnId, displayType, flag) , mEditable(editable) , mUserEditable(userEditable) { } bool CSMWorld::RefIdColumn::isEditable() const { return mEditable; } bool CSMWorld::RefIdColumn::isUserEditable() const { return mUserEditable; } const CSMWorld::RefIdAdapter& CSMWorld::RefIdCollection::findAdapter(UniversalId::Type type) const { std::map::const_iterator iter = mAdapters.find(type); if (iter == mAdapters.end()) throw std::logic_error("unsupported type in RefIdCollection"); return *iter->second; } CSMWorld::RefIdCollection::RefIdCollection() { BaseColumns baseColumns; mColumns.emplace_back( Columns::ColumnId_Id, ColumnBase::Display_Id, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false); baseColumns.mId = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Modification, ColumnBase::Display_RecordState, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, true, false); baseColumns.mModified = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_RecordType, ColumnBase::Display_RefRecordType, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false); baseColumns.mType = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Blocked, ColumnBase::Display_Boolean, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh); baseColumns.mBlocked = &mColumns.back(); ModelColumns modelColumns(baseColumns); mColumns.emplace_back(Columns::ColumnId_Persistent, ColumnBase::Display_Boolean); modelColumns.mPersistence = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Model, ColumnBase::Display_Mesh); modelColumns.mModel = &mColumns.back(); NameColumns nameColumns(modelColumns); // Only items that can be placed in a container have the 32 character limit, but enforce // that for all referenceable types for now. mColumns.emplace_back(Columns::ColumnId_Name, ColumnBase::Display_String32); nameColumns.mName = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Script, ColumnBase::Display_Script); nameColumns.mScript = &mColumns.back(); InventoryColumns inventoryColumns(nameColumns); mColumns.emplace_back(Columns::ColumnId_Icon, ColumnBase::Display_Icon); inventoryColumns.mIcon = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Weight, ColumnBase::Display_Float); inventoryColumns.mWeight = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_CoinValue, ColumnBase::Display_Integer); inventoryColumns.mValue = &mColumns.back(); IngredientColumns ingredientColumns(inventoryColumns); mColumns.emplace_back(Columns::ColumnId_EffectList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); ingredientColumns.mEffects = &mColumns.back(); std::map ingredientEffectsMap; ingredientEffectsMap.insert(std::make_pair(UniversalId::Type_Ingredient, new IngredEffectRefIdAdapter())); mNestedAdapters.emplace_back(&mColumns.back(), ingredientEffectsMap); mColumns.back().addColumn(new NestedChildColumn(Columns::ColumnId_EffectId, ColumnBase::Display_IngredEffectId)); mColumns.back().addColumn(new NestedChildColumn(Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill)); mColumns.back().addColumn(new NestedChildColumn(Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute)); // nested table PotionColumns potionColumns(inventoryColumns); mColumns.emplace_back(Columns::ColumnId_EffectList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); potionColumns.mEffects = &mColumns.back(); // see refidadapterimp.hpp std::map effectsMap; effectsMap.insert( std::make_pair(UniversalId::Type_Potion, new EffectsRefIdAdapter(UniversalId::Type_Potion))); mNestedAdapters.emplace_back(&mColumns.back(), effectsMap); mColumns.back().addColumn(new NestedChildColumn(Columns::ColumnId_EffectId, ColumnBase::Display_EffectId)); mColumns.back().addColumn(new NestedChildColumn(Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill)); mColumns.back().addColumn(new NestedChildColumn(Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute)); mColumns.back().addColumn(new NestedChildColumn(Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange)); mColumns.back().addColumn(new NestedChildColumn(Columns::ColumnId_EffectArea, ColumnBase::Display_String)); mColumns.back().addColumn( new NestedChildColumn(Columns::ColumnId_Duration, ColumnBase::Display_Integer)); // reuse from light mColumns.back().addColumn(new NestedChildColumn(Columns::ColumnId_MinMagnitude, ColumnBase::Display_Integer)); mColumns.back().addColumn(new NestedChildColumn(Columns::ColumnId_MaxMagnitude, ColumnBase::Display_Integer)); EnchantableColumns enchantableColumns(inventoryColumns); mColumns.emplace_back(Columns::ColumnId_Enchantment, ColumnBase::Display_Enchantment); enchantableColumns.mEnchantment = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_EnchantmentPoints, ColumnBase::Display_Integer); enchantableColumns.mEnchantmentPoints = &mColumns.back(); ToolColumns toolsColumns(inventoryColumns); mColumns.emplace_back(Columns::ColumnId_Quality, ColumnBase::Display_Float); toolsColumns.mQuality = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Charges, ColumnBase::Display_Integer); toolsColumns.mUses = &mColumns.back(); ActorColumns actorsColumns(nameColumns); mColumns.emplace_back(Columns::ColumnId_AiHello, ColumnBase::Display_UnsignedInteger16); actorsColumns.mHello = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_AiFlee, ColumnBase::Display_UnsignedInteger8); actorsColumns.mFlee = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_AiFight, ColumnBase::Display_UnsignedInteger8); actorsColumns.mFight = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_AiAlarm, ColumnBase::Display_UnsignedInteger8); actorsColumns.mAlarm = &mColumns.back(); // Nested table mColumns.emplace_back( Columns::ColumnId_ActorInventory, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); actorsColumns.mInventory = &mColumns.back(); std::map inventoryMap; inventoryMap.insert( std::make_pair(UniversalId::Type_Npc, new NestedInventoryRefIdAdapter(UniversalId::Type_Npc))); inventoryMap.insert(std::make_pair( UniversalId::Type_Creature, new NestedInventoryRefIdAdapter(UniversalId::Type_Creature))); mNestedAdapters.emplace_back(&mColumns.back(), inventoryMap); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_Referenceable)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer)); // Nested table mColumns.emplace_back(Columns::ColumnId_SpellList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); actorsColumns.mSpells = &mColumns.back(); std::map spellsMap; spellsMap.insert( std::make_pair(UniversalId::Type_Npc, new NestedSpellRefIdAdapter(UniversalId::Type_Npc))); spellsMap.insert(std::make_pair( UniversalId::Type_Creature, new NestedSpellRefIdAdapter(UniversalId::Type_Creature))); mNestedAdapters.emplace_back(&mColumns.back(), spellsMap); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_SpellId, CSMWorld::ColumnBase::Display_Spell)); // Nested table mColumns.emplace_back( Columns::ColumnId_NpcDestinations, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); actorsColumns.mDestinations = &mColumns.back(); std::map destMap; destMap.insert( std::make_pair(UniversalId::Type_Npc, new NestedTravelRefIdAdapter(UniversalId::Type_Npc))); destMap.insert(std::make_pair( UniversalId::Type_Creature, new NestedTravelRefIdAdapter(UniversalId::Type_Creature))); mNestedAdapters.emplace_back(&mColumns.back(), destMap); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_DestinationCell, CSMWorld::ColumnBase::Display_Cell)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_PosX, CSMWorld::ColumnBase::Display_Float)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_PosY, CSMWorld::ColumnBase::Display_Float)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_PosZ, CSMWorld::ColumnBase::Display_Float)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_RotX, CSMWorld::ColumnBase::Display_Double)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_RotY, CSMWorld::ColumnBase::Display_Double)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Double)); // Nested table mColumns.emplace_back(Columns::ColumnId_AiPackageList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); actorsColumns.mAiPackages = &mColumns.back(); std::map aiMap; aiMap.insert(std::make_pair(UniversalId::Type_Npc, new ActorAiRefIdAdapter(UniversalId::Type_Npc))); aiMap.insert( std::make_pair(UniversalId::Type_Creature, new ActorAiRefIdAdapter(UniversalId::Type_Creature))); mNestedAdapters.emplace_back(&mColumns.back(), aiMap); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_AiPackageType, CSMWorld::ColumnBase::Display_AiPackageType)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AiWanderDist, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AiDuration, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AiWanderToD, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle1, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle2, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle3, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle4, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle5, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle6, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle7, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Idle8, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AiWanderRepeat, CSMWorld::ColumnBase::Display_Boolean)); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_AiActivateName, CSMWorld::ColumnBase::Display_String32)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AiTargetId, CSMWorld::ColumnBase::Display_String32)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AiTargetCell, CSMWorld::ColumnBase::Display_String)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_PosX, CSMWorld::ColumnBase::Display_Float)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_PosY, CSMWorld::ColumnBase::Display_Float)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_PosZ, CSMWorld::ColumnBase::Display_Float)); static const struct { int mName; unsigned int mFlag; } sServiceTable[] = { { Columns::ColumnId_BuysWeapons, ESM::NPC::Weapon }, { Columns::ColumnId_BuysArmor, ESM::NPC::Armor }, { Columns::ColumnId_BuysClothing, ESM::NPC::Clothing }, { Columns::ColumnId_BuysBooks, ESM::NPC::Books }, { Columns::ColumnId_BuysIngredients, ESM::NPC::Ingredients }, { Columns::ColumnId_BuysLockpicks, ESM::NPC::Picks }, { Columns::ColumnId_BuysProbes, ESM::NPC::Probes }, { Columns::ColumnId_BuysLights, ESM::NPC::Lights }, { Columns::ColumnId_BuysApparati, ESM::NPC::Apparatus }, { Columns::ColumnId_BuysRepairItems, ESM::NPC::RepairItem }, { Columns::ColumnId_BuysMiscItems, ESM::NPC::Misc }, { Columns::ColumnId_BuysPotions, ESM::NPC::Potions }, { Columns::ColumnId_BuysMagicItems, ESM::NPC::MagicItems }, { Columns::ColumnId_SellsSpells, ESM::NPC::Spells }, { Columns::ColumnId_Trainer, ESM::NPC::Training }, { Columns::ColumnId_Spellmaking, ESM::NPC::Spellmaking }, { Columns::ColumnId_EnchantingService, ESM::NPC::Enchanting }, { Columns::ColumnId_RepairService, ESM::NPC::Repair }, { -1, 0 } }; for (int i = 0; sServiceTable[i].mName != -1; ++i) { mColumns.emplace_back(sServiceTable[i].mName, ColumnBase::Display_Boolean); actorsColumns.mServices.insert(std::make_pair(&mColumns.back(), sServiceTable[i].mFlag)); } mColumns.emplace_back(Columns::ColumnId_AutoCalc, ColumnBase::Display_Boolean, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh); const RefIdColumn* autoCalc = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_ApparatusType, ColumnBase::Display_ApparatusType); const RefIdColumn* apparatusType = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_ArmorType, ColumnBase::Display_ArmorType); const RefIdColumn* armorType = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Health, ColumnBase::Display_Integer); const RefIdColumn* health = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_ArmorValue, ColumnBase::Display_Integer); const RefIdColumn* armor = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_BookType, ColumnBase::Display_BookType); const RefIdColumn* bookType = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Skill, ColumnBase::Display_SkillId); const RefIdColumn* skill = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Text, ColumnBase::Display_LongString); const RefIdColumn* text = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_ClothingType, ColumnBase::Display_ClothingType); const RefIdColumn* clothingType = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_WeightCapacity, ColumnBase::Display_Float); const RefIdColumn* weightCapacity = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_OrganicContainer, ColumnBase::Display_Boolean); const RefIdColumn* organic = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Respawn, ColumnBase::Display_Boolean); const RefIdColumn* respawn = &mColumns.back(); // Nested table mColumns.emplace_back( Columns::ColumnId_ContainerContent, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); const RefIdColumn* content = &mColumns.back(); std::map contMap; contMap.insert(std::make_pair( UniversalId::Type_Container, new NestedInventoryRefIdAdapter(UniversalId::Type_Container))); mNestedAdapters.emplace_back(&mColumns.back(), contMap); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_Referenceable)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer)); CreatureColumns creatureColumns(actorsColumns); mColumns.emplace_back(Columns::ColumnId_CreatureType, ColumnBase::Display_CreatureType); creatureColumns.mType = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Scale, ColumnBase::Display_Float); creatureColumns.mScale = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_ParentCreature, ColumnBase::Display_Creature); creatureColumns.mOriginal = &mColumns.back(); static const struct { int mName; unsigned int mFlag; } sCreatureFlagTable[] = { { Columns::ColumnId_Biped, ESM::Creature::Bipedal }, { Columns::ColumnId_HasWeapon, ESM::Creature::Weapon }, { Columns::ColumnId_Swims, ESM::Creature::Swims }, { Columns::ColumnId_Flies, ESM::Creature::Flies }, { Columns::ColumnId_Walks, ESM::Creature::Walks }, { Columns::ColumnId_Essential, ESM::Creature::Essential }, { -1, 0 } }; // for re-use in NPC records const RefIdColumn* essential = nullptr; for (int i = 0; sCreatureFlagTable[i].mName != -1; ++i) { mColumns.emplace_back(sCreatureFlagTable[i].mName, ColumnBase::Display_Boolean); creatureColumns.mFlags.insert(std::make_pair(&mColumns.back(), sCreatureFlagTable[i].mFlag)); switch (sCreatureFlagTable[i].mFlag) { case ESM::Creature::Essential: essential = &mColumns.back(); break; } } mColumns.emplace_back(Columns::ColumnId_BloodType, ColumnBase::Display_BloodType); // For re-use in NPC records. const RefIdColumn* bloodType = &mColumns.back(); creatureColumns.mBloodType = bloodType; creatureColumns.mFlags.insert(std::make_pair(respawn, ESM::Creature::Respawn)); // Nested table mColumns.emplace_back( Columns::ColumnId_CreatureAttributes, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); creatureColumns.mAttributes = &mColumns.back(); std::map creaAttrMap; creaAttrMap.insert(std::make_pair(UniversalId::Type_Creature, new CreatureAttributesRefIdAdapter())); mNestedAdapters.emplace_back(&mColumns.back(), creaAttrMap); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_Attribute, CSMWorld::ColumnBase::Display_Attribute, false, false)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_AttributeValue, CSMWorld::ColumnBase::Display_Integer)); // Nested table mColumns.emplace_back( Columns::ColumnId_CreatureAttack, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); creatureColumns.mAttacks = &mColumns.back(); std::map attackMap; attackMap.insert(std::make_pair(UniversalId::Type_Creature, new CreatureAttackRefIdAdapter())); mNestedAdapters.emplace_back(&mColumns.back(), attackMap); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_CreatureAttack, CSMWorld::ColumnBase::Display_Integer, false, false)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_MinAttack, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_MaxAttack, CSMWorld::ColumnBase::Display_Integer)); // Nested list mColumns.emplace_back(Columns::ColumnId_CreatureMisc, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List); creatureColumns.mMisc = &mColumns.back(); std::map creaMiscMap; creaMiscMap.insert(std::make_pair(UniversalId::Type_Creature, new CreatureMiscRefIdAdapter())); mNestedAdapters.emplace_back(&mColumns.back(), creaMiscMap); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Level, CSMWorld::ColumnBase::Display_Integer, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Health, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Mana, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Fatigue, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_SoulPoints, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_CombatState, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_MagicState, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_StealthState, CSMWorld::ColumnBase::Display_Integer)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Gold, CSMWorld::ColumnBase::Display_Integer)); mColumns.emplace_back(Columns::ColumnId_OpenSound, ColumnBase::Display_Sound); const RefIdColumn* openSound = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_CloseSound, ColumnBase::Display_Sound); const RefIdColumn* closeSound = &mColumns.back(); LightColumns lightColumns(inventoryColumns); mColumns.emplace_back(Columns::ColumnId_Duration, ColumnBase::Display_Integer); lightColumns.mTime = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Radius, ColumnBase::Display_Integer); lightColumns.mRadius = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Colour, ColumnBase::Display_Colour); lightColumns.mColor = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Sound, ColumnBase::Display_Sound); lightColumns.mSound = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_EmitterType, ColumnBase::Display_EmitterType); lightColumns.mEmitterType = &mColumns.back(); static const struct { int mName; unsigned int mFlag; } sLightFlagTable[] = { { Columns::ColumnId_Dynamic, ESM::Light::Dynamic }, { Columns::ColumnId_Portable, ESM::Light::Carry }, { Columns::ColumnId_NegativeLight, ESM::Light::Negative }, { Columns::ColumnId_Fire, ESM::Light::Fire }, { Columns::ColumnId_OffByDefault, ESM::Light::OffDefault }, { -1, 0 } }; for (int i = 0; sLightFlagTable[i].mName != -1; ++i) { mColumns.emplace_back(sLightFlagTable[i].mName, ColumnBase::Display_Boolean); lightColumns.mFlags.insert(std::make_pair(&mColumns.back(), sLightFlagTable[i].mFlag)); } mColumns.emplace_back(Columns::ColumnId_IsKey, ColumnBase::Display_Boolean); const RefIdColumn* key = &mColumns.back(); NpcColumns npcColumns(actorsColumns); mColumns.emplace_back(Columns::ColumnId_Race, ColumnBase::Display_Race); npcColumns.mRace = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Class, ColumnBase::Display_Class); npcColumns.mClass = &mColumns.back(); // NAME32 enforced in IdCompletionDelegate::createEditor() mColumns.emplace_back(Columns::ColumnId_Faction, ColumnBase::Display_Faction); npcColumns.mFaction = &mColumns.back(); mColumns.emplace_back(Columns::Columnid_Hair, ColumnBase::Display_BodyPart); npcColumns.mHair = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Head, ColumnBase::Display_BodyPart); npcColumns.mHead = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_Gender, ColumnBase::Display_GenderNpc); npcColumns.mGender = &mColumns.back(); npcColumns.mFlags.insert(std::make_pair(essential, ESM::NPC::Essential)); npcColumns.mFlags.insert(std::make_pair(respawn, ESM::NPC::Respawn)); npcColumns.mFlags.insert(std::make_pair(autoCalc, ESM::NPC::Autocalc)); // Re-used from Creature records. npcColumns.mBloodType = bloodType; // Need a way to add a table of stats and values (rather than adding a long list of // entries in the dialogue subview) E.g. attributes+stats(health, mana, fatigue), skills // These needs to be driven from the autocalculated setting. // Nested table mColumns.emplace_back(Columns::ColumnId_NpcAttributes, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); npcColumns.mAttributes = &mColumns.back(); std::map attrMap; attrMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcAttributesRefIdAdapter())); mNestedAdapters.emplace_back(&mColumns.back(), attrMap); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_Attribute, CSMWorld::ColumnBase::Display_Attribute, false, false)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_UnsignedInteger8)); // Nested table mColumns.emplace_back(Columns::ColumnId_NpcSkills, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); npcColumns.mSkills = &mColumns.back(); std::map skillsMap; skillsMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcSkillsRefIdAdapter())); mNestedAdapters.emplace_back(&mColumns.back(), skillsMap); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_Skill, CSMWorld::ColumnBase::Display_SkillId, false, false)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_UnsignedInteger8)); // Nested list mColumns.emplace_back(Columns::ColumnId_NpcMisc, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List); npcColumns.mMisc = &mColumns.back(); std::map miscMap; miscMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcMiscRefIdAdapter())); mNestedAdapters.emplace_back(&mColumns.back(), miscMap); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Level, CSMWorld::ColumnBase::Display_SignedInteger16)); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_Health, CSMWorld::ColumnBase::Display_UnsignedInteger16)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Mana, CSMWorld::ColumnBase::Display_UnsignedInteger16)); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_Fatigue, CSMWorld::ColumnBase::Display_UnsignedInteger16)); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_NpcDisposition, CSMWorld::ColumnBase::Display_UnsignedInteger8)); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_NpcReputation, CSMWorld::ColumnBase::Display_UnsignedInteger8)); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_NpcRank, CSMWorld::ColumnBase::Display_UnsignedInteger8)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_Gold, CSMWorld::ColumnBase::Display_Integer)); WeaponColumns weaponColumns(enchantableColumns); mColumns.emplace_back(Columns::ColumnId_WeaponType, ColumnBase::Display_WeaponType); weaponColumns.mType = &mColumns.back(); weaponColumns.mHealth = health; mColumns.emplace_back(Columns::ColumnId_WeaponSpeed, ColumnBase::Display_Float); weaponColumns.mSpeed = &mColumns.back(); mColumns.emplace_back(Columns::ColumnId_WeaponReach, ColumnBase::Display_Float); weaponColumns.mReach = &mColumns.back(); for (int i = 0; i < 3; ++i) { const RefIdColumn** column = i == 0 ? weaponColumns.mChop : (i == 1 ? weaponColumns.mSlash : weaponColumns.mThrust); for (int j = 0; j < 2; ++j) { mColumns.emplace_back(Columns::ColumnId_MinChop + i * 2 + j, ColumnBase::Display_Integer); column[j] = &mColumns.back(); } } static const struct { int mName; unsigned int mFlag; } sWeaponFlagTable[] = { { Columns::ColumnId_Magical, ESM::Weapon::Magical }, { Columns::ColumnId_Silver, ESM::Weapon::Silver }, { -1, 0 } }; for (int i = 0; sWeaponFlagTable[i].mName != -1; ++i) { mColumns.emplace_back(sWeaponFlagTable[i].mName, ColumnBase::Display_Boolean); weaponColumns.mFlags.insert(std::make_pair(&mColumns.back(), sWeaponFlagTable[i].mFlag)); } // Nested table mColumns.emplace_back(Columns::ColumnId_PartRefList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); const RefIdColumn* partRef = &mColumns.back(); std::map partMap; partMap.insert( std::make_pair(UniversalId::Type_Armor, new BodyPartRefIdAdapter(UniversalId::Type_Armor))); partMap.insert(std::make_pair( UniversalId::Type_Clothing, new BodyPartRefIdAdapter(UniversalId::Type_Clothing))); mNestedAdapters.emplace_back(&mColumns.back(), partMap); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_PartRefType, CSMWorld::ColumnBase::Display_PartRefType)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_PartRefMale, CSMWorld::ColumnBase::Display_BodyPart)); mColumns.back().addColumn(new RefIdColumn(Columns::ColumnId_PartRefFemale, CSMWorld::ColumnBase::Display_BodyPart)); LevListColumns creatureLevListColumns(baseColumns); LevListColumns itemLevListColumns(baseColumns); std::map creatureLevListMap, itemLevListMap; creatureLevListMap.insert(std::make_pair(UniversalId::Type_CreatureLevelledList, new NestedLevListRefIdAdapter(UniversalId::Type_CreatureLevelledList))); itemLevListMap.insert(std::make_pair(UniversalId::Type_ItemLevelledList, new NestedLevListRefIdAdapter(UniversalId::Type_ItemLevelledList))); // Levelled creature nested table mColumns.emplace_back(Columns::ColumnId_LevelledList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); creatureLevListColumns.mLevList = &mColumns.back(); mNestedAdapters.emplace_back(&mColumns.back(), creatureLevListMap); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_LevelledCreatureId, CSMWorld::ColumnBase::Display_Referenceable)); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_LevelledItemLevel, CSMWorld::ColumnBase::Display_Integer)); // Levelled item nested table mColumns.emplace_back(Columns::ColumnId_LevelledList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue); itemLevListColumns.mLevList = &mColumns.back(); mNestedAdapters.emplace_back(&mColumns.back(), itemLevListMap); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_LevelledItemId, CSMWorld::ColumnBase::Display_Referenceable)); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_LevelledItemLevel, CSMWorld::ColumnBase::Display_Integer)); // Shared levelled list nested list mColumns.emplace_back(Columns::ColumnId_LevelledList, ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List); creatureLevListColumns.mNestedListLevList = &mColumns.back(); itemLevListColumns.mNestedListLevList = &mColumns.back(); std::map nestedListLevListMap; nestedListLevListMap.insert(std::make_pair(UniversalId::Type_CreatureLevelledList, new NestedListLevListRefIdAdapter(UniversalId::Type_CreatureLevelledList))); nestedListLevListMap.insert(std::make_pair(UniversalId::Type_ItemLevelledList, new NestedListLevListRefIdAdapter(UniversalId::Type_ItemLevelledList))); mNestedAdapters.emplace_back(&mColumns.back(), nestedListLevListMap); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_LevelledItemTypeEach, CSMWorld::ColumnBase::Display_Boolean)); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_LevelledItemType, CSMWorld::ColumnBase::Display_Boolean)); mColumns.back().addColumn( new RefIdColumn(Columns::ColumnId_LevelledItemChanceNone, CSMWorld::ColumnBase::Display_UnsignedInteger8)); mAdapters.insert(std::make_pair( UniversalId::Type_Activator, new NameRefIdAdapter(UniversalId::Type_Activator, nameColumns))); mAdapters.insert(std::make_pair(UniversalId::Type_Potion, new PotionRefIdAdapter(potionColumns, autoCalc))); mAdapters.insert(std::make_pair(UniversalId::Type_Apparatus, new ApparatusRefIdAdapter(inventoryColumns, apparatusType, toolsColumns.mQuality))); mAdapters.insert(std::make_pair( UniversalId::Type_Armor, new ArmorRefIdAdapter(enchantableColumns, armorType, health, armor, partRef))); mAdapters.insert( std::make_pair(UniversalId::Type_Book, new BookRefIdAdapter(enchantableColumns, bookType, skill, text))); mAdapters.insert(std::make_pair( UniversalId::Type_Clothing, new ClothingRefIdAdapter(enchantableColumns, clothingType, partRef))); mAdapters.insert(std::make_pair(UniversalId::Type_Container, new ContainerRefIdAdapter(nameColumns, weightCapacity, organic, respawn, content))); mAdapters.insert(std::make_pair(UniversalId::Type_Creature, new CreatureRefIdAdapter(creatureColumns))); mAdapters.insert(std::make_pair(UniversalId::Type_Door, new DoorRefIdAdapter(nameColumns, openSound, closeSound))); mAdapters.insert(std::make_pair(UniversalId::Type_Ingredient, new IngredientRefIdAdapter(ingredientColumns))); mAdapters.insert(std::make_pair(UniversalId::Type_CreatureLevelledList, new LevelledListRefIdAdapter( UniversalId::Type_CreatureLevelledList, creatureLevListColumns))); mAdapters.insert(std::make_pair(UniversalId::Type_ItemLevelledList, new LevelledListRefIdAdapter(UniversalId::Type_ItemLevelledList, itemLevListColumns))); mAdapters.insert(std::make_pair(UniversalId::Type_Light, new LightRefIdAdapter(lightColumns))); mAdapters.insert(std::make_pair( UniversalId::Type_Lockpick, new ToolRefIdAdapter(UniversalId::Type_Lockpick, toolsColumns))); mAdapters.insert(std::make_pair(UniversalId::Type_Miscellaneous, new MiscRefIdAdapter(inventoryColumns, key))); mAdapters.insert(std::make_pair(UniversalId::Type_Npc, new NpcRefIdAdapter(npcColumns))); mAdapters.insert(std::make_pair( UniversalId::Type_Probe, new ToolRefIdAdapter(UniversalId::Type_Probe, toolsColumns))); mAdapters.insert(std::make_pair( UniversalId::Type_Repair, new ToolRefIdAdapter(UniversalId::Type_Repair, toolsColumns))); mAdapters.insert(std::make_pair( UniversalId::Type_Static, new ModelRefIdAdapter(UniversalId::Type_Static, modelColumns))); mAdapters.insert(std::make_pair(UniversalId::Type_Weapon, new WeaponRefIdAdapter(weaponColumns))); } CSMWorld::RefIdCollection::~RefIdCollection() { for (std::map::iterator iter(mAdapters.begin()); iter != mAdapters.end(); ++iter) delete iter->second; for (std::vector>>::iterator iter( mNestedAdapters.begin()); iter != mNestedAdapters.end(); ++iter) { for (std::map::iterator it((iter->second).begin()); it != (iter->second).end(); ++it) delete it->second; } } int CSMWorld::RefIdCollection::getSize() const { return mData.getSize(); } ESM::RefId CSMWorld::RefIdCollection::getId(int index) const { return ESM::RefId::stringRefId(getData(index, 0).toString().toUtf8().constData()); } int CSMWorld::RefIdCollection::getIndex(const ESM::RefId& id) const { int index = searchId(id); if (index == -1) throw std::runtime_error("invalid ID: " + id.getRefIdString()); return index; } int CSMWorld::RefIdCollection::getColumns() const { return mColumns.size(); } const CSMWorld::ColumnBase& CSMWorld::RefIdCollection::getColumn(int column) const { return mColumns.at(column); } QVariant CSMWorld::RefIdCollection::getData(int index, int column) const { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(index); const RefIdAdapter& adaptor = findAdapter(localIndex.second); return adaptor.getData(&mColumns.at(column), mData, localIndex.first); } QVariant CSMWorld::RefIdCollection::getNestedData(int row, int column, int subRow, int subColumn) const { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row); const CSMWorld::NestedRefIdAdapterBase& nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); return nestedAdapter.getNestedData(&mColumns.at(column), mData, localIndex.first, subRow, subColumn); } void CSMWorld::RefIdCollection::setData(int index, int column, const QVariant& data) { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(index); const RefIdAdapter& adaptor = findAdapter(localIndex.second); adaptor.setData(&mColumns.at(column), mData, localIndex.first, data); } void CSMWorld::RefIdCollection::setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn) { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row); const CSMWorld::NestedRefIdAdapterBase& nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); nestedAdapter.setNestedData(&mColumns.at(column), mData, localIndex.first, data, subRow, subColumn); } void CSMWorld::RefIdCollection::removeRows(int index, int count) { mData.erase(index, count); } void CSMWorld::RefIdCollection::removeNestedRows(int row, int column, int subRow) { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row); const CSMWorld::NestedRefIdAdapterBase& nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); nestedAdapter.removeNestedRow(&mColumns.at(column), mData, localIndex.first, subRow); } void CSMWorld::RefIdCollection::appendBlankRecord(const ESM::RefId& id, UniversalId::Type type) { mData.appendRecord(type, id, false); } int CSMWorld::RefIdCollection::searchId(std::string_view id) const { RefIdData::LocalIndex localIndex = mData.searchId(ESM::RefId::stringRefId(id)); if (localIndex.first == -1) return -1; return mData.localToGlobalIndex(localIndex); } int CSMWorld::RefIdCollection::searchId(const ESM::RefId& id) const { return searchId(id.getRefIdString()); } void CSMWorld::RefIdCollection::replace(int index, std::unique_ptr record) { mData.getRecord(mData.globalToLocalIndex(index)).assign(*record.release()); } void CSMWorld::RefIdCollection::cloneRecord( const ESM::RefId& origin, const ESM::RefId& destination, const CSMWorld::UniversalId::Type type) { std::unique_ptr newRecord = mData.getRecord(mData.searchId(origin)).modifiedCopy(); mAdapters.find(type)->second->setId(*newRecord, destination.getRefIdString()); mData.insertRecord(std::move(newRecord), type, destination); } bool CSMWorld::RefIdCollection::touchRecord(const ESM::RefId& id) { throw std::runtime_error("RefIdCollection::touchRecord is unimplemented"); return false; } void CSMWorld::RefIdCollection::appendRecord(std::unique_ptr record, UniversalId::Type type) { auto id = findAdapter(type).getId(*record.get()); int index = mData.getAppendIndex(type); mData.appendRecord(type, id, false); mData.getRecord(mData.globalToLocalIndex(index)).assign(*record.release()); } const CSMWorld::RecordBase& CSMWorld::RefIdCollection::getRecord(const ESM::RefId& id) const { return mData.getRecord(mData.searchId(id)); } const CSMWorld::RecordBase& CSMWorld::RefIdCollection::getRecord(int index) const { return mData.getRecord(mData.globalToLocalIndex(index)); } void CSMWorld::RefIdCollection::load(ESM::ESMReader& reader, bool base, UniversalId::Type type) { mData.load(reader, base, type); } int CSMWorld::RefIdCollection::getAppendIndex(const ESM::RefId& id, UniversalId::Type type) const { return mData.getAppendIndex(type); } std::vector CSMWorld::RefIdCollection::getIds(bool listDeleted) const { return mData.getIds(listDeleted); } bool CSMWorld::RefIdCollection::reorderRows(int baseIndex, const std::vector& newOrder) { return false; } void CSMWorld::RefIdCollection::save(int index, ESM::ESMWriter& writer) const { mData.save(index, writer); } const CSMWorld::RefIdData& CSMWorld::RefIdCollection::getDataSet() const { return mData; } int CSMWorld::RefIdCollection::getNestedRowsCount(int row, int column) const { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row); const CSMWorld::NestedRefIdAdapterBase& nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); return nestedAdapter.getNestedRowsCount(&mColumns.at(column), mData, localIndex.first); } int CSMWorld::RefIdCollection::getNestedColumnsCount(int row, int column) const { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row); const CSMWorld::NestedRefIdAdapterBase& nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); return nestedAdapter.getNestedColumnsCount(&mColumns.at(column), mData); } CSMWorld::NestableColumn* CSMWorld::RefIdCollection::getNestableColumn(int column) { return &mColumns.at(column); } void CSMWorld::RefIdCollection::addNestedRow(int row, int col, int position) { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row); const CSMWorld::NestedRefIdAdapterBase& nestedAdapter = getNestedAdapter(mColumns.at(col), localIndex.second); nestedAdapter.addNestedRow(&mColumns.at(col), mData, localIndex.first, position); } void CSMWorld::RefIdCollection::setNestedTable(int row, int column, const CSMWorld::NestedTableWrapperBase& nestedTable) { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row); const CSMWorld::NestedRefIdAdapterBase& nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); nestedAdapter.setNestedTable(&mColumns.at(column), mData, localIndex.first, nestedTable); } CSMWorld::NestedTableWrapperBase* CSMWorld::RefIdCollection::nestedTable(int row, int column) const { RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row); const CSMWorld::NestedRefIdAdapterBase& nestedAdapter = getNestedAdapter(mColumns.at(column), localIndex.second); return nestedAdapter.nestedTable(&mColumns.at(column), mData, localIndex.first); } const CSMWorld::NestedRefIdAdapterBase& CSMWorld::RefIdCollection::getNestedAdapter( const CSMWorld::ColumnBase& column, UniversalId::Type type) const { for (std::vector>>::const_iterator iter(mNestedAdapters.begin()); iter != mNestedAdapters.end(); ++iter) { if ((iter->first) == &column) { std::map::const_iterator it = (iter->second).find(type); if (it == (iter->second).end()) throw std::runtime_error("No such type in the nestedadapters"); return *it->second; } } throw std::runtime_error("No such column in the nestedadapters"); } void CSMWorld::RefIdCollection::copyTo(int index, RefIdCollection& target) const { mData.copyTo(index, target.mData); }