mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 06:53:52 +00:00
Use shield body part model for creatures (bug #5250)
This commit is contained in:
parent
2bed25a5e8
commit
bbe5adb860
4 changed files with 61 additions and 7 deletions
|
@ -191,6 +191,7 @@
|
||||||
Bug #5239: OpenMW-CS does not support non-ASCII characters in path names
|
Bug #5239: OpenMW-CS does not support non-ASCII characters in path names
|
||||||
Bug #5241: On-self absorb spells cannot be detected
|
Bug #5241: On-self absorb spells cannot be detected
|
||||||
Bug #5242: ExplodeSpell behavior differs from Cast behavior
|
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 #1774: Handle AvoidNode
|
||||||
Feature #2229: Improve pathfinding AI
|
Feature #2229: Improve pathfinding AI
|
||||||
Feature #3025: Analogue gamepad movement controls
|
Feature #3025: Analogue gamepad movement controls
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
#include "../mwmechanics/actorutil.hpp"
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
#include "../mwmechanics/weapontype.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 ActorAnimation::getShieldMesh(MWWorld::ConstPtr shield) const
|
||||||
{
|
{
|
||||||
std::string mesh = shield.getClass().getModel(shield);
|
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;
|
std::string holsteredName = mesh;
|
||||||
holsteredName = holsteredName.replace(holsteredName.size()-4, 4, "_sh.nif");
|
holsteredName = holsteredName.replace(holsteredName.size()-4, 4, "_sh.nif");
|
||||||
if(mResourceSystem->getVFS()->exists(holsteredName))
|
if(mResourceSystem->getVFS()->exists(holsteredName))
|
||||||
|
|
|
@ -13,11 +13,13 @@
|
||||||
|
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/weapontype.hpp"
|
#include "../mwmechanics/weapontype.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
@ -114,6 +116,7 @@ void CreatureWeaponAnimation::updatePart(PartHolderPtr& scene, int slot)
|
||||||
MWWorld::ConstPtr item = *it;
|
MWWorld::ConstPtr item = *it;
|
||||||
|
|
||||||
std::string bonename;
|
std::string bonename;
|
||||||
|
std::string itemModel = item.getClass().getModel(item);
|
||||||
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
|
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
|
||||||
{
|
{
|
||||||
if(item.getTypeName() == typeid(ESM::Weapon).name())
|
if(item.getTypeName() == typeid(ESM::Weapon).name())
|
||||||
|
@ -132,11 +135,30 @@ void CreatureWeaponAnimation::updatePart(PartHolderPtr& scene, int slot)
|
||||||
bonename = "Weapon Bone";
|
bonename = "Weapon Bone";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
bonename = "Shield Bone";
|
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
|
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();
|
const NodeMap& nodeMap = getNodeMap();
|
||||||
NodeMap::const_iterator found = nodeMap.find(Misc::StringUtils::lowerCase(bonename));
|
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);
|
std::string mesh = shield.getClass().getModel(shield);
|
||||||
const ESM::Armor *armor = shield.get<ESM::Armor>()->mBase;
|
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())
|
if (!bodyparts.empty())
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
|
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
|
// Try to get shield model from bodyparts first, with ground model as fallback
|
||||||
for (auto & part : bodyparts)
|
for (const auto& part : bodyparts)
|
||||||
{
|
{
|
||||||
if (part.mPart != ESM::PRT_Shield)
|
if (part.mPart != ESM::PRT_Shield)
|
||||||
continue;
|
continue;
|
||||||
|
@ -538,15 +538,20 @@ std::string NpcAnimation::getShieldMesh(MWWorld::ConstPtr shield) const
|
||||||
|
|
||||||
if (!bodypartName.empty())
|
if (!bodypartName.empty())
|
||||||
{
|
{
|
||||||
const ESM::BodyPart *bodypart = 0;
|
const ESM::BodyPart *bodypart = partStore.search(bodypartName);
|
||||||
bodypart = partStore.search(bodypartName);
|
|
||||||
if (bodypart == nullptr || bodypart->mData.mType != ESM::BodyPart::MT_Armor)
|
if (bodypart == nullptr || bodypart->mData.mType != ESM::BodyPart::MT_Armor)
|
||||||
return "";
|
return std::string();
|
||||||
else if (!bodypart->mModel.empty())
|
else if (!bodypart->mModel.empty())
|
||||||
|
{
|
||||||
mesh = "meshes\\" + bodypart->mModel;
|
mesh = "meshes\\" + bodypart->mModel;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh.empty())
|
||||||
|
return std::string();
|
||||||
|
|
||||||
std::string holsteredName = mesh;
|
std::string holsteredName = mesh;
|
||||||
holsteredName = holsteredName.replace(holsteredName.size()-4, 4, "_sh.nif");
|
holsteredName = holsteredName.replace(holsteredName.size()-4, 4, "_sh.nif");
|
||||||
|
|
Loading…
Reference in a new issue