Use shield body part model for creatures (bug #5250)

pull/2662/head
capostrophic 4 years ago
parent 2bed25a5e8
commit bbe5adb860

@ -191,6 +191,7 @@
Bug #5239: OpenMW-CS does not support non-ASCII characters in path names
Bug #5241: On-self absorb spells cannot be detected
Bug #5242: ExplodeSpell behavior differs from Cast behavior
Bug #5250: Creatures display shield ground mesh instead of shield body part
Feature #1774: Handle AvoidNode
Feature #2229: Improve pathfinding AI
Feature #3025: Analogue gamepad movement controls

@ -27,6 +27,7 @@
#include "../mwworld/ptr.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwmechanics/actorutil.hpp"
#include "../mwmechanics/weapontype.hpp"
@ -87,6 +88,31 @@ PartHolderPtr ActorAnimation::attachMesh(const std::string& model, const std::st
std::string ActorAnimation::getShieldMesh(MWWorld::ConstPtr shield) const
{
std::string mesh = shield.getClass().getModel(shield);
const ESM::Armor *armor = shield.get<ESM::Armor>()->mBase;
const std::vector<ESM::PartReference>& bodyparts = armor->mParts.mParts;
if (!bodyparts.empty())
{
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
// Try to get shield model from bodyparts first, with ground model as fallback
for (const auto& part : bodyparts)
{
// Assume all creatures use the male mesh.
if (part.mPart != ESM::PRT_Shield || part.mMale.empty())
continue;
const ESM::BodyPart *bodypart = partStore.search(part.mMale);
if (bodypart && bodypart->mData.mType == ESM::BodyPart::MT_Armor && !bodypart->mModel.empty())
{
mesh = "meshes\\" + bodypart->mModel;
break;
}
}
}
if (mesh.empty())
return mesh;
std::string holsteredName = mesh;
holsteredName = holsteredName.replace(holsteredName.size()-4, 4, "_sh.nif");
if(mResourceSystem->getVFS()->exists(holsteredName))

@ -13,11 +13,13 @@
#include <components/misc/stringops.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwmechanics/weapontype.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"
namespace MWRender
{
@ -114,6 +116,7 @@ void CreatureWeaponAnimation::updatePart(PartHolderPtr& scene, int slot)
MWWorld::ConstPtr item = *it;
std::string bonename;
std::string itemModel = item.getClass().getModel(item);
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
{
if(item.getTypeName() == typeid(ESM::Weapon).name())
@ -132,11 +135,30 @@ void CreatureWeaponAnimation::updatePart(PartHolderPtr& scene, int slot)
bonename = "Weapon Bone";
}
else
{
bonename = "Shield Bone";
if (item.getTypeName() == typeid(ESM::Armor).name())
{
// Shield body part model should be used if possible.
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
for (const auto& part : item.get<ESM::Armor>()->mBase->mParts.mParts)
{
// Assume all creatures use the male mesh.
if (part.mPart != ESM::PRT_Shield || part.mMale.empty())
continue;
const ESM::BodyPart *bodypart = store.get<ESM::BodyPart>().search(part.mMale);
if (bodypart && bodypart->mData.mType == ESM::BodyPart::MT_Armor && !bodypart->mModel.empty())
{
itemModel = "meshes\\" + bodypart->mModel;
break;
}
}
}
}
try
{
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(item.getClass().getModel(item));
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(itemModel);
const NodeMap& nodeMap = getNodeMap();
NodeMap::const_iterator found = nodeMap.find(Misc::StringUtils::lowerCase(bonename));

@ -518,14 +518,14 @@ std::string NpcAnimation::getShieldMesh(MWWorld::ConstPtr shield) const
{
std::string mesh = shield.getClass().getModel(shield);
const ESM::Armor *armor = shield.get<ESM::Armor>()->mBase;
std::vector<ESM::PartReference> bodyparts = armor->mParts.mParts;
const std::vector<ESM::PartReference>& bodyparts = armor->mParts.mParts;
if (!bodyparts.empty())
{
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
// For NPCs try to get shield model from bodyparts first, with ground model as fallback
for (auto & part : bodyparts)
// Try to get shield model from bodyparts first, with ground model as fallback
for (const auto& part : bodyparts)
{
if (part.mPart != ESM::PRT_Shield)
continue;
@ -538,16 +538,21 @@ std::string NpcAnimation::getShieldMesh(MWWorld::ConstPtr shield) const
if (!bodypartName.empty())
{
const ESM::BodyPart *bodypart = 0;
bodypart = partStore.search(bodypartName);
const ESM::BodyPart *bodypart = partStore.search(bodypartName);
if (bodypart == nullptr || bodypart->mData.mType != ESM::BodyPart::MT_Armor)
return "";
return std::string();
else if (!bodypart->mModel.empty())
{
mesh = "meshes\\" + bodypart->mModel;
break;
}
}
}
}
if (mesh.empty())
return std::string();
std::string holsteredName = mesh;
holsteredName = holsteredName.replace(holsteredName.size()-4, 4, "_sh.nif");
if(mResourceSystem->getVFS()->exists(holsteredName))

Loading…
Cancel
Save