mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-06 23:15:35 +00:00
Use correct template flags for FONV and FO4 NPCs
This commit is contained in:
parent
bff4666b7b
commit
6c01ce2672
3 changed files with 53 additions and 26 deletions
|
@ -34,11 +34,26 @@ namespace MWClass
|
||||||
|
|
||||||
static const ESM4::Npc* chooseTemplate(const std::vector<const ESM4::Npc*>& recs, uint16_t flag)
|
static const ESM4::Npc* chooseTemplate(const std::vector<const ESM4::Npc*>& recs, uint16_t flag)
|
||||||
{
|
{
|
||||||
// In case of FO3 the function may return nullptr that will lead to "ESM4 NPC traits not found"
|
|
||||||
// exception and the NPC will not be added to the scene. But in any way it shouldn't cause a crash.
|
|
||||||
for (const auto* rec : recs)
|
for (const auto* rec : recs)
|
||||||
if (rec->mIsTES4 || rec->mIsFONV || !(rec->mBaseConfig.tes5.templateFlags & flag))
|
{
|
||||||
|
if (rec->mIsTES4)
|
||||||
return rec;
|
return rec;
|
||||||
|
else if (rec->mIsFONV)
|
||||||
|
{
|
||||||
|
// TODO: FO3 should use this branch as well. But it is not clear how to distinguish FO3 from
|
||||||
|
// TES5. Currently FO3 uses wrong template flags that can lead to "ESM4 NPC traits not found"
|
||||||
|
// exception the NPC will not be added to the scene. But in any way it shouldn't cause a crash.
|
||||||
|
if (!(rec->mBaseConfig.fo3.templateFlags & flag))
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
|
else if (rec->mIsFO4)
|
||||||
|
{
|
||||||
|
if (!(rec->mBaseConfig.fo4.templateFlags & flag))
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
|
else if (!(rec->mBaseConfig.tes5.templateFlags & flag))
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,8 +90,8 @@ namespace MWClass
|
||||||
const MWWorld::ESMStore* store = MWBase::Environment::get().getESMStore();
|
const MWWorld::ESMStore* store = MWBase::Environment::get().getESMStore();
|
||||||
auto npcRecs = withBaseTemplates<ESM4::LevelledNpc, ESM4::Npc>(ptr.get<ESM4::Npc>()->mBase);
|
auto npcRecs = withBaseTemplates<ESM4::LevelledNpc, ESM4::Npc>(ptr.get<ESM4::Npc>()->mBase);
|
||||||
|
|
||||||
data->mTraits = chooseTemplate(npcRecs, ESM4::Npc::TES5_UseTraits);
|
data->mTraits = chooseTemplate(npcRecs, ESM4::Npc::Template_UseTraits);
|
||||||
data->mBaseData = chooseTemplate(npcRecs, ESM4::Npc::TES5_UseBaseData);
|
data->mBaseData = chooseTemplate(npcRecs, ESM4::Npc::Template_UseBaseData);
|
||||||
|
|
||||||
if (!data->mTraits)
|
if (!data->mTraits)
|
||||||
throw std::runtime_error("ESM4 NPC traits not found");
|
throw std::runtime_error("ESM4 NPC traits not found");
|
||||||
|
@ -88,10 +103,13 @@ namespace MWClass
|
||||||
data->mIsFemale = data->mTraits->mBaseConfig.tes4.flags & ESM4::Npc::TES4_Female;
|
data->mIsFemale = data->mTraits->mBaseConfig.tes4.flags & ESM4::Npc::TES4_Female;
|
||||||
else if (data->mTraits->mIsFONV)
|
else if (data->mTraits->mIsFONV)
|
||||||
data->mIsFemale = data->mTraits->mBaseConfig.fo3.flags & ESM4::Npc::FO3_Female;
|
data->mIsFemale = data->mTraits->mBaseConfig.fo3.flags & ESM4::Npc::FO3_Female;
|
||||||
|
else if (data->mTraits->mIsFO4)
|
||||||
|
data->mIsFemale
|
||||||
|
= data->mTraits->mBaseConfig.fo4.flags & ESM4::Npc::TES5_Female; // FO4 flags are same as TES5
|
||||||
else
|
else
|
||||||
data->mIsFemale = data->mTraits->mBaseConfig.tes5.flags & ESM4::Npc::TES5_Female;
|
data->mIsFemale = data->mTraits->mBaseConfig.tes5.flags & ESM4::Npc::TES5_Female;
|
||||||
|
|
||||||
if (auto inv = chooseTemplate(npcRecs, ESM4::Npc::TES5_UseInventory))
|
if (auto inv = chooseTemplate(npcRecs, ESM4::Npc::Template_UseInventory))
|
||||||
{
|
{
|
||||||
for (const ESM4::InventoryItem& item : inv->mInventory)
|
for (const ESM4::InventoryItem& item : inv->mInventory)
|
||||||
{
|
{
|
||||||
|
|
|
@ -116,9 +116,11 @@ void ESM4::Npc::load(ESM4::Reader& reader)
|
||||||
{
|
{
|
||||||
switch (subHdr.dataSize)
|
switch (subHdr.dataSize)
|
||||||
{
|
{
|
||||||
|
case 20: // FO4
|
||||||
|
mIsFO4 = true;
|
||||||
|
[[fallthrough]];
|
||||||
case 16: // TES4
|
case 16: // TES4
|
||||||
case 24: // FO3/FNV, TES5
|
case 24: // FO3/FNV, TES5
|
||||||
case 20: // FO4
|
|
||||||
reader.get(&mBaseConfig, subHdr.dataSize);
|
reader.get(&mBaseConfig, subHdr.dataSize);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -78,6 +78,7 @@ namespace ESM4
|
||||||
FO3_NoRotateHead = 0x40000000
|
FO3_NoRotateHead = 0x40000000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// In FO4 flags seem to be the same.
|
||||||
enum ACBS_TES5
|
enum ACBS_TES5
|
||||||
{
|
{
|
||||||
TES5_Female = 0x00000001,
|
TES5_Female = 0x00000001,
|
||||||
|
@ -101,27 +102,32 @@ namespace ESM4
|
||||||
TES5_Invulnerable = 0x80000000
|
TES5_Invulnerable = 0x80000000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// All FO3+ games.
|
||||||
enum Template_Flags
|
enum Template_Flags
|
||||||
{
|
{
|
||||||
TES5_UseTraits = 0x0001, // Destructible Object; Traits tab, including race, gender, height, weight,
|
Template_UseTraits = 0x0001, // Destructible Object; Traits tab, including race, gender, height, weight,
|
||||||
// voice type, death item; Sounds tab; Animation tab; Character Gen tabs
|
// voice type, death item; Sounds tab; Animation tab; Character Gen tabs
|
||||||
TES5_UseStats = 0x0002, // Stats tab, including level, autocalc, skills, health/magicka/stamina,
|
Template_UseStats = 0x0002, // Stats tab, including level, autocalc, skills, health/magicka/stamina,
|
||||||
// speed, bleedout, class
|
// speed, bleedout, class
|
||||||
TES5_UseFactions = 0x0004, // both factions and assigned crime faction
|
Template_UseFactions = 0x0004, // both factions and assigned crime faction
|
||||||
TES5_UseSpellList = 0x0008, // both spells and perks
|
Template_UseSpellList = 0x0008, // both spells and perks
|
||||||
TES5_UseAIData = 0x0010, // AI Data tab, including aggression/confidence/morality, combat style and
|
Template_UseAIData = 0x0010, // AI Data tab, including aggression/confidence/morality, combat style and
|
||||||
// gift filter
|
// gift filter
|
||||||
TES5_UseAIPackage = 0x0020, // only the basic Packages listed on the AI Packages tab;
|
Template_UseAIPackage = 0x0020, // only the basic Packages listed on the AI Packages tab;
|
||||||
// rest of tab controlled by Def Pack List
|
// rest of tab controlled by Def Pack List
|
||||||
TES5_UseBaseData = 0x0080, // including name and short name, and flags for Essential, Protected,
|
Template_UseModel = 0x0040, // FO3, FONV; probably not used in TES5+
|
||||||
// Respawn, Summonable, Simple Actor, and Doesn't affect stealth meter
|
Template_UseBaseData = 0x0080, // including name and short name, and flags for Essential, Protected,
|
||||||
TES5_UseInventory = 0x0100, // Inventory tab, including all outfits and geared-up item
|
// Respawn, Summonable, Simple Actor, and Doesn't affect stealth meter
|
||||||
// -- but not death item
|
Template_UseInventory = 0x0100, // Inventory tab, including all outfits and geared-up item,
|
||||||
TES5_UseScript = 0x0200,
|
// but not death item
|
||||||
TES5_UseDefined = 0x0400, // Def Pack List (the dropdown-selected package lists on the AI Packages tab)
|
Template_UseScript = 0x0200,
|
||||||
TES5_UseAtkData = 0x0800, // Attack Data tab, including override from behavior graph race,
|
|
||||||
// events, and data)
|
// The following flags were added in TES5+:
|
||||||
TES5_UseKeywords = 0x1000
|
|
||||||
|
Template_UseDefined = 0x0400, // Def Pack List (the dropdown-selected package lists on the AI Packages tab)
|
||||||
|
Template_UseAtkData = 0x0800, // Attack Data tab, including override from behavior graph race,
|
||||||
|
// events, and data)
|
||||||
|
Template_UseKeywords = 0x1000
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
@ -172,6 +178,7 @@ namespace ESM4
|
||||||
|
|
||||||
bool mIsTES4;
|
bool mIsTES4;
|
||||||
bool mIsFONV;
|
bool mIsFONV;
|
||||||
|
bool mIsFO4 = false;
|
||||||
|
|
||||||
std::string mEditorId;
|
std::string mEditorId;
|
||||||
std::string mFullName;
|
std::string mFullName;
|
||||||
|
|
Loading…
Reference in a new issue