From d4972ab166677cb30dbc918af59ddda6f0f252c8 Mon Sep 17 00:00:00 2001 From: MAtahualpa Date: Wed, 15 Feb 2017 23:06:36 +0100 Subject: [PATCH] Replace "Xyz blood" check boxes with a combo box (fixes #3751) Replaces the two "Xyz blood" check boxes in NPC and Creature records with a "Blood Type" combo box. Related issue: - Fixes #3751: OpenMW-CS: Replace "Xyz Blood" check boxes in NPC and Creature records with "Blood Type" combo box (https://bugs.openmw.org/issues/3751) Tests: The changes were successfully tested in OpenMW-CS by manipulating several NPC and Creature records. Please note that this fix also prevents users from erroneously assigning two blood types at the same time. (I don't know which one would prevail in that case.) --- apps/opencs/model/world/columnbase.hpp | 1 + apps/opencs/model/world/columns.cpp | 10 +++- apps/opencs/model/world/columns.hpp | 4 +- apps/opencs/model/world/refidadapterimp.cpp | 54 ++++++++++++++++++++- apps/opencs/model/world/refidadapterimp.hpp | 2 + apps/opencs/model/world/refidcollection.cpp | 16 +++--- apps/opencs/view/doc/viewmanager.cpp | 1 + 7 files changed, 73 insertions(+), 15 deletions(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 951af4b6a..19028de08 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -132,6 +132,7 @@ namespace CSMWorld Display_String32, Display_LongString256, Display_BookType, + Display_BloodType, Display_EffectSkill, // must display at least one, unlike Display_Skill Display_EffectAttribute, // must display at least one, unlike Display_Attribute diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 5c041894f..534d7da05 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -112,8 +112,8 @@ namespace CSMWorld { ColumnId_Flies, "Flies" }, { ColumnId_Walks, "Walks" }, { ColumnId_Essential, "Essential" }, - { ColumnId_SkeletonBlood, "Skeleton Blood" }, - { ColumnId_MetalBlood, "Metal Blood" }, + { ColumnId_BloodType, "Blood Type" }, + { ColumnId_OpenSound, "Open Sound" }, { ColumnId_CloseSound, "Close Sound" }, { ColumnId_Duration, "Duration" }, @@ -558,6 +558,11 @@ namespace "Book", "Scroll", 0 }; + static const char *sBloodType[] = + { + "Default (Red)", "Skeleton Blood (White)", "Metal Blood (Golden)", 0 + }; + const char **getEnumNames (CSMWorld::Columns::ColumnId column) { switch (column) @@ -588,6 +593,7 @@ namespace case CSMWorld::Columns::ColumnId_InfoCondFunc: return CSMWorld::ConstInfoSelectWrapper::FunctionEnumStrings; case CSMWorld::Columns::ColumnId_InfoCondComp: return CSMWorld::ConstInfoSelectWrapper::RelationEnumStrings; case CSMWorld::Columns::ColumnId_BookType: return sBookType; + case CSMWorld::Columns::ColumnId_BloodType: return sBloodType; default: return 0; } diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index c1586bf6c..2438d2de2 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -107,8 +107,8 @@ namespace CSMWorld ColumnId_Flies = 92, ColumnId_Walks = 93, ColumnId_Essential = 94, - ColumnId_SkeletonBlood = 95, - ColumnId_MetalBlood = 96, + ColumnId_BloodType = 95, + // unused ColumnId_OpenSound = 97, ColumnId_CloseSound = 98, ColumnId_Duration = 99, diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index fb19d943b..5e792e91f 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -458,7 +458,8 @@ CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns) mOriginal(NULL), mAttributes(NULL), mAttacks(NULL), - mMisc(NULL) + mMisc(NULL), + mBloodType(NULL) {} CSMWorld::CreatureRefIdAdapter::CreatureRefIdAdapter (const CreatureColumns& columns) @@ -489,6 +490,19 @@ QVariant CSMWorld::CreatureRefIdAdapter::getData (const RefIdColumn *column, con if (column==mColumns.mMisc) return QVariant::fromValue(ColumnBase::TableEdit_Full); + if (column == mColumns.mBloodType) + { + int mask = ESM::Creature::Flags::Skeleton | ESM::Creature::Flags::Metal; + + if ((record.get().mFlags & mask) == ESM::Creature::Flags::Skeleton) + return 1; + + if ((record.get().mFlags & mask) == ESM::Creature::Flags::Metal) + return 2; + + return 0; + } + std::map::const_iterator iter = mColumns.mFlags.find (column); @@ -512,6 +526,17 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa creature.mScale = value.toFloat(); else if (column==mColumns.mOriginal) creature.mOriginal = value.toString().toUtf8().constData(); + else if (column == mColumns.mBloodType) + { + int mask = !(ESM::Creature::Flags::Skeleton | ESM::Creature::Flags::Metal); + + if (value.toInt() == 1) + creature.mFlags = (creature.mFlags & mask) | ESM::Creature::Flags::Skeleton; + else if (value.toInt() == 2) + creature.mFlags = (creature.mFlags & mask) | ESM::Creature::Flags::Metal; + else + creature.mFlags = creature.mFlags & mask; + } else { std::map::const_iterator iter = @@ -696,7 +721,8 @@ CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns) mHead(NULL), mAttributes(NULL), mSkills(NULL), - mMisc(NULL) + mMisc(NULL), + mBloodType(NULL) {} CSMWorld::NpcRefIdAdapter::NpcRefIdAdapter (const NpcColumns& columns) @@ -735,6 +761,19 @@ QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const Re if (column==mColumns.mMisc) return QVariant::fromValue(ColumnBase::TableEdit_Full); + if (column == mColumns.mBloodType) + { + int mask = ESM::NPC::Flags::Skeleton | ESM::NPC::Flags::Metal; + + if ((record.get().mFlags & mask) == ESM::NPC::Flags::Skeleton) + return 1; + + if ((record.get().mFlags & mask) == ESM::NPC::Flags::Metal) + return 2; + + return 0; + } + std::map::const_iterator iter = mColumns.mFlags.find (column); @@ -762,6 +801,17 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d npc.mHair = value.toString().toUtf8().constData(); else if (column==mColumns.mHead) npc.mHead = value.toString().toUtf8().constData(); + else if (column == mColumns.mBloodType) + { + int mask = !(ESM::NPC::Flags::Skeleton | ESM::NPC::Flags::Metal); + + if (value.toInt() == 1) + npc.mFlags = (npc.mFlags & mask) | ESM::NPC::Flags::Skeleton; + else if (value.toInt() == 2) + npc.mFlags = (npc.mFlags & mask) | ESM::NPC::Flags::Metal; + else + npc.mFlags = npc.mFlags & mask; + } else { std::map::const_iterator iter = diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 390d1f1b4..b89b87ab1 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -757,6 +757,7 @@ namespace CSMWorld const RefIdColumn *mAttributes; const RefIdColumn *mAttacks; const RefIdColumn *mMisc; + const RefIdColumn *mBloodType; CreatureColumns (const ActorColumns& actorColumns); }; @@ -849,6 +850,7 @@ namespace CSMWorld const RefIdColumn *mAttributes; // depends on npc type const RefIdColumn *mSkills; // depends on npc type const RefIdColumn *mMisc; // may depend on npc type, e.g. FactionID + const RefIdColumn *mBloodType; NpcColumns (const ActorColumns& actorColumns); }; diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 150077fd8..a85ee5d25 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -346,15 +346,11 @@ CSMWorld::RefIdCollection::RefIdCollection() { Columns::ColumnId_Flies, ESM::Creature::Flies }, { Columns::ColumnId_Walks, ESM::Creature::Walks }, { Columns::ColumnId_Essential, ESM::Creature::Essential }, - { Columns::ColumnId_SkeletonBlood, ESM::Creature::Skeleton }, - { Columns::ColumnId_MetalBlood, ESM::Creature::Metal }, { -1, 0 } }; // for re-use in NPC records const RefIdColumn *essential = 0; - const RefIdColumn *skeletonBlood = 0; - const RefIdColumn *metalBlood = 0; for (int i=0; sCreatureFlagTable[i].mName!=-1; ++i) { @@ -364,11 +360,14 @@ CSMWorld::RefIdCollection::RefIdCollection() switch (sCreatureFlagTable[i].mFlag) { case ESM::Creature::Essential: essential = &mColumns.back(); break; - case ESM::Creature::Skeleton: skeletonBlood = &mColumns.back(); break; - case ESM::Creature::Metal: metalBlood = &mColumns.back(); break; } } + mColumns.push_back(RefIdColumn(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 @@ -497,9 +496,8 @@ CSMWorld::RefIdCollection::RefIdCollection() npcColumns.mFlags.insert (std::make_pair (autoCalc, ESM::NPC::Autocalc)); - npcColumns.mFlags.insert (std::make_pair (skeletonBlood, ESM::NPC::Skeleton)); - - npcColumns.mFlags.insert (std::make_pair (metalBlood, ESM::NPC::Metal)); + // 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 diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 12d52d3dd..b3a8d03d4 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -108,6 +108,7 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) { CSMWorld::ColumnBase::Display_EffectSkill, CSMWorld::Columns::ColumnId_Skill, false }, { CSMWorld::ColumnBase::Display_EffectAttribute, CSMWorld::Columns::ColumnId_Attribute, false }, { CSMWorld::ColumnBase::Display_BookType, CSMWorld::Columns::ColumnId_BookType, false}, + { CSMWorld::ColumnBase::Display_BloodType, CSMWorld::Columns::ColumnId_BloodType, false} }; for (std::size_t i=0; i