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.)
This commit is contained in:
MAtahualpa 2017-02-15 23:06:36 +01:00
parent f10edb71cc
commit d4972ab166
7 changed files with 73 additions and 15 deletions

View file

@ -132,6 +132,7 @@ namespace CSMWorld
Display_String32, Display_String32,
Display_LongString256, Display_LongString256,
Display_BookType, Display_BookType,
Display_BloodType,
Display_EffectSkill, // must display at least one, unlike Display_Skill Display_EffectSkill, // must display at least one, unlike Display_Skill
Display_EffectAttribute, // must display at least one, unlike Display_Attribute Display_EffectAttribute, // must display at least one, unlike Display_Attribute

View file

@ -112,8 +112,8 @@ namespace CSMWorld
{ ColumnId_Flies, "Flies" }, { ColumnId_Flies, "Flies" },
{ ColumnId_Walks, "Walks" }, { ColumnId_Walks, "Walks" },
{ ColumnId_Essential, "Essential" }, { ColumnId_Essential, "Essential" },
{ ColumnId_SkeletonBlood, "Skeleton Blood" }, { ColumnId_BloodType, "Blood Type" },
{ ColumnId_MetalBlood, "Metal Blood" },
{ ColumnId_OpenSound, "Open Sound" }, { ColumnId_OpenSound, "Open Sound" },
{ ColumnId_CloseSound, "Close Sound" }, { ColumnId_CloseSound, "Close Sound" },
{ ColumnId_Duration, "Duration" }, { ColumnId_Duration, "Duration" },
@ -558,6 +558,11 @@ namespace
"Book", "Scroll", 0 "Book", "Scroll", 0
}; };
static const char *sBloodType[] =
{
"Default (Red)", "Skeleton Blood (White)", "Metal Blood (Golden)", 0
};
const char **getEnumNames (CSMWorld::Columns::ColumnId column) const char **getEnumNames (CSMWorld::Columns::ColumnId column)
{ {
switch (column) switch (column)
@ -588,6 +593,7 @@ namespace
case CSMWorld::Columns::ColumnId_InfoCondFunc: return CSMWorld::ConstInfoSelectWrapper::FunctionEnumStrings; case CSMWorld::Columns::ColumnId_InfoCondFunc: return CSMWorld::ConstInfoSelectWrapper::FunctionEnumStrings;
case CSMWorld::Columns::ColumnId_InfoCondComp: return CSMWorld::ConstInfoSelectWrapper::RelationEnumStrings; case CSMWorld::Columns::ColumnId_InfoCondComp: return CSMWorld::ConstInfoSelectWrapper::RelationEnumStrings;
case CSMWorld::Columns::ColumnId_BookType: return sBookType; case CSMWorld::Columns::ColumnId_BookType: return sBookType;
case CSMWorld::Columns::ColumnId_BloodType: return sBloodType;
default: return 0; default: return 0;
} }

View file

@ -107,8 +107,8 @@ namespace CSMWorld
ColumnId_Flies = 92, ColumnId_Flies = 92,
ColumnId_Walks = 93, ColumnId_Walks = 93,
ColumnId_Essential = 94, ColumnId_Essential = 94,
ColumnId_SkeletonBlood = 95, ColumnId_BloodType = 95,
ColumnId_MetalBlood = 96, // unused
ColumnId_OpenSound = 97, ColumnId_OpenSound = 97,
ColumnId_CloseSound = 98, ColumnId_CloseSound = 98,
ColumnId_Duration = 99, ColumnId_Duration = 99,

View file

@ -458,7 +458,8 @@ CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns)
mOriginal(NULL), mOriginal(NULL),
mAttributes(NULL), mAttributes(NULL),
mAttacks(NULL), mAttacks(NULL),
mMisc(NULL) mMisc(NULL),
mBloodType(NULL)
{} {}
CSMWorld::CreatureRefIdAdapter::CreatureRefIdAdapter (const CreatureColumns& columns) CSMWorld::CreatureRefIdAdapter::CreatureRefIdAdapter (const CreatureColumns& columns)
@ -489,6 +490,19 @@ QVariant CSMWorld::CreatureRefIdAdapter::getData (const RefIdColumn *column, con
if (column==mColumns.mMisc) if (column==mColumns.mMisc)
return QVariant::fromValue(ColumnBase::TableEdit_Full); 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 RefIdColumn *, unsigned int>::const_iterator iter = std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column); mColumns.mFlags.find (column);
@ -512,6 +526,17 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa
creature.mScale = value.toFloat(); creature.mScale = value.toFloat();
else if (column==mColumns.mOriginal) else if (column==mColumns.mOriginal)
creature.mOriginal = value.toString().toUtf8().constData(); 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 else
{ {
std::map<const RefIdColumn *, unsigned int>::const_iterator iter = std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
@ -696,7 +721,8 @@ CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns)
mHead(NULL), mHead(NULL),
mAttributes(NULL), mAttributes(NULL),
mSkills(NULL), mSkills(NULL),
mMisc(NULL) mMisc(NULL),
mBloodType(NULL)
{} {}
CSMWorld::NpcRefIdAdapter::NpcRefIdAdapter (const NpcColumns& columns) CSMWorld::NpcRefIdAdapter::NpcRefIdAdapter (const NpcColumns& columns)
@ -735,6 +761,19 @@ QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const Re
if (column==mColumns.mMisc) if (column==mColumns.mMisc)
return QVariant::fromValue(ColumnBase::TableEdit_Full); 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 RefIdColumn *, unsigned int>::const_iterator iter = std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column); mColumns.mFlags.find (column);
@ -762,6 +801,17 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d
npc.mHair = value.toString().toUtf8().constData(); npc.mHair = value.toString().toUtf8().constData();
else if (column==mColumns.mHead) else if (column==mColumns.mHead)
npc.mHead = value.toString().toUtf8().constData(); 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 else
{ {
std::map<const RefIdColumn *, unsigned int>::const_iterator iter = std::map<const RefIdColumn *, unsigned int>::const_iterator iter =

View file

@ -757,6 +757,7 @@ namespace CSMWorld
const RefIdColumn *mAttributes; const RefIdColumn *mAttributes;
const RefIdColumn *mAttacks; const RefIdColumn *mAttacks;
const RefIdColumn *mMisc; const RefIdColumn *mMisc;
const RefIdColumn *mBloodType;
CreatureColumns (const ActorColumns& actorColumns); CreatureColumns (const ActorColumns& actorColumns);
}; };
@ -849,6 +850,7 @@ namespace CSMWorld
const RefIdColumn *mAttributes; // depends on npc type const RefIdColumn *mAttributes; // depends on npc type
const RefIdColumn *mSkills; // depends on npc type const RefIdColumn *mSkills; // depends on npc type
const RefIdColumn *mMisc; // may depend on npc type, e.g. FactionID const RefIdColumn *mMisc; // may depend on npc type, e.g. FactionID
const RefIdColumn *mBloodType;
NpcColumns (const ActorColumns& actorColumns); NpcColumns (const ActorColumns& actorColumns);
}; };

View file

@ -346,15 +346,11 @@ CSMWorld::RefIdCollection::RefIdCollection()
{ Columns::ColumnId_Flies, ESM::Creature::Flies }, { Columns::ColumnId_Flies, ESM::Creature::Flies },
{ Columns::ColumnId_Walks, ESM::Creature::Walks }, { Columns::ColumnId_Walks, ESM::Creature::Walks },
{ Columns::ColumnId_Essential, ESM::Creature::Essential }, { Columns::ColumnId_Essential, ESM::Creature::Essential },
{ Columns::ColumnId_SkeletonBlood, ESM::Creature::Skeleton },
{ Columns::ColumnId_MetalBlood, ESM::Creature::Metal },
{ -1, 0 } { -1, 0 }
}; };
// for re-use in NPC records // for re-use in NPC records
const RefIdColumn *essential = 0; const RefIdColumn *essential = 0;
const RefIdColumn *skeletonBlood = 0;
const RefIdColumn *metalBlood = 0;
for (int i=0; sCreatureFlagTable[i].mName!=-1; ++i) for (int i=0; sCreatureFlagTable[i].mName!=-1; ++i)
{ {
@ -364,11 +360,14 @@ CSMWorld::RefIdCollection::RefIdCollection()
switch (sCreatureFlagTable[i].mFlag) switch (sCreatureFlagTable[i].mFlag)
{ {
case ESM::Creature::Essential: essential = &mColumns.back(); break; 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)); creatureColumns.mFlags.insert (std::make_pair (respawn, ESM::Creature::Respawn));
// Nested table // 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 (autoCalc, ESM::NPC::Autocalc));
npcColumns.mFlags.insert (std::make_pair (skeletonBlood, ESM::NPC::Skeleton)); // Re-used from Creature records.
npcColumns.mBloodType = bloodType;
npcColumns.mFlags.insert (std::make_pair (metalBlood, ESM::NPC::Metal));
// Need a way to add a table of stats and values (rather than adding a long list of // 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 // entries in the dialogue subview) E.g. attributes+stats(health, mana, fatigue), skills

View file

@ -108,6 +108,7 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
{ CSMWorld::ColumnBase::Display_EffectSkill, CSMWorld::Columns::ColumnId_Skill, false }, { CSMWorld::ColumnBase::Display_EffectSkill, CSMWorld::Columns::ColumnId_Skill, false },
{ CSMWorld::ColumnBase::Display_EffectAttribute, CSMWorld::Columns::ColumnId_Attribute, false }, { CSMWorld::ColumnBase::Display_EffectAttribute, CSMWorld::Columns::ColumnId_Attribute, false },
{ CSMWorld::ColumnBase::Display_BookType, CSMWorld::Columns::ColumnId_BookType, 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<sizeof (sMapping)/sizeof (Mapping); ++i) for (std::size_t i=0; i<sizeof (sMapping)/sizeof (Mapping); ++i)