mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-15 21:19:57 +00:00
29556a1802
A Warning indicates a potential problem in the content file(s) that the user told OpenMW to load. E.g. this might cause an object to not display at all or as intended, however the rest of the game will run fine. An Error, however, is more likely to be a bug with the engine itself - it means that basic assumptions have been violated and the engine might not run correctly anymore. The above mostly applies to errors/warnings during game-play; startup issues are handled differently: when a file is completely invalid/corrupted to the point that the engine can not start, that might cause messages that are worded as Error due to the severity of the issue but are not necessarily the engine's fault. Hopefully, being a little more consistent here will alleviate confusion among users as to when a log message should be reported and to whom.
208 lines
5.9 KiB
C++
208 lines
5.9 KiB
C++
#include "creatureanimation.hpp"
|
|
|
|
#include <iostream>
|
|
|
|
#include <osg/MatrixTransform>
|
|
|
|
#include <components/esm/loadcrea.hpp>
|
|
|
|
#include <components/resource/resourcesystem.hpp>
|
|
#include <components/resource/scenemanager.hpp>
|
|
#include <components/sceneutil/attach.hpp>
|
|
#include <components/sceneutil/visitor.hpp>
|
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
|
#include <components/sceneutil/skeleton.hpp>
|
|
|
|
#include <components/misc/stringops.hpp>
|
|
|
|
#include "../mwbase/world.hpp"
|
|
|
|
#include "../mwworld/class.hpp"
|
|
|
|
namespace MWRender
|
|
{
|
|
|
|
CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr,
|
|
const std::string& model, Resource::ResourceSystem* resourceSystem)
|
|
: ActorAnimation(ptr, osg::ref_ptr<osg::Group>(ptr.getRefData().getBaseNode()), resourceSystem)
|
|
{
|
|
MWWorld::LiveCellRef<ESM::Creature> *ref = mPtr.get<ESM::Creature>();
|
|
|
|
if(!model.empty())
|
|
{
|
|
setObjectRoot(model, false, false, true);
|
|
|
|
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
|
addAnimSource("meshes\\xbase_anim.nif");
|
|
addAnimSource(model);
|
|
}
|
|
}
|
|
|
|
|
|
CreatureWeaponAnimation::CreatureWeaponAnimation(const MWWorld::Ptr &ptr, const std::string& model, Resource::ResourceSystem* resourceSystem)
|
|
: ActorAnimation(ptr, osg::ref_ptr<osg::Group>(ptr.getRefData().getBaseNode()), resourceSystem)
|
|
, mShowWeapons(false)
|
|
, mShowCarriedLeft(false)
|
|
{
|
|
MWWorld::LiveCellRef<ESM::Creature> *ref = mPtr.get<ESM::Creature>();
|
|
|
|
if(!model.empty())
|
|
{
|
|
setObjectRoot(model, true, false, true);
|
|
|
|
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
|
addAnimSource("meshes\\xbase_anim.nif");
|
|
addAnimSource(model);
|
|
|
|
mPtr.getClass().getInventoryStore(mPtr).setInvListener(this, mPtr);
|
|
|
|
updateParts();
|
|
}
|
|
|
|
mWeaponAnimationTime = boost::shared_ptr<WeaponAnimationTime>(new WeaponAnimationTime(this));
|
|
}
|
|
|
|
void CreatureWeaponAnimation::showWeapons(bool showWeapon)
|
|
{
|
|
if (showWeapon != mShowWeapons)
|
|
{
|
|
mShowWeapons = showWeapon;
|
|
updateParts();
|
|
}
|
|
}
|
|
|
|
void CreatureWeaponAnimation::showCarriedLeft(bool show)
|
|
{
|
|
if (show != mShowCarriedLeft)
|
|
{
|
|
mShowCarriedLeft = show;
|
|
updateParts();
|
|
}
|
|
}
|
|
|
|
void CreatureWeaponAnimation::updateParts()
|
|
{
|
|
mAmmunition.reset();
|
|
mWeapon.reset();
|
|
mShield.reset();
|
|
|
|
if (mShowWeapons)
|
|
updatePart(mWeapon, MWWorld::InventoryStore::Slot_CarriedRight);
|
|
if (mShowCarriedLeft)
|
|
updatePart(mShield, MWWorld::InventoryStore::Slot_CarriedLeft);
|
|
}
|
|
|
|
void CreatureWeaponAnimation::updatePart(PartHolderPtr& scene, int slot)
|
|
{
|
|
if (!mObjectRoot)
|
|
return;
|
|
|
|
const MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr);
|
|
MWWorld::ConstContainerStoreIterator it = inv.getSlot(slot);
|
|
|
|
if (it == inv.end())
|
|
{
|
|
scene.reset();
|
|
return;
|
|
}
|
|
MWWorld::ConstPtr item = *it;
|
|
|
|
std::string bonename;
|
|
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
|
|
bonename = "Weapon Bone";
|
|
else
|
|
bonename = "Shield Bone";
|
|
|
|
try
|
|
{
|
|
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->getInstance(item.getClass().getModel(item));
|
|
|
|
const NodeMap& nodeMap = getNodeMap();
|
|
NodeMap::const_iterator found = getNodeMap().find(Misc::StringUtils::lowerCase(bonename));
|
|
if (found == nodeMap.end())
|
|
throw std::runtime_error("Can't find attachment node " + bonename);
|
|
osg::ref_ptr<osg::Node> attached = SceneUtil::attach(node, mObjectRoot, bonename, found->second.get());
|
|
|
|
scene.reset(new PartHolder(attached));
|
|
|
|
if (!item.getClass().getEnchantment(item).empty())
|
|
addGlow(attached, getEnchantmentColor(item));
|
|
|
|
// Crossbows start out with a bolt attached
|
|
// FIXME: code duplicated from NpcAnimation
|
|
if (slot == MWWorld::InventoryStore::Slot_CarriedRight &&
|
|
item.getTypeName() == typeid(ESM::Weapon).name() &&
|
|
item.get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow)
|
|
{
|
|
MWWorld::ConstContainerStoreIterator ammo = inv.getSlot(MWWorld::InventoryStore::Slot_Ammunition);
|
|
if (ammo != inv.end() && ammo->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::Bolt)
|
|
attachArrow();
|
|
else
|
|
mAmmunition.reset();
|
|
}
|
|
else
|
|
mAmmunition.reset();
|
|
|
|
boost::shared_ptr<SceneUtil::ControllerSource> source;
|
|
|
|
if (slot == MWWorld::InventoryStore::Slot_CarriedRight)
|
|
source = mWeaponAnimationTime;
|
|
else
|
|
source.reset(new NullAnimationTime);
|
|
|
|
SceneUtil::AssignControllerSourcesVisitor assignVisitor(source);
|
|
attached->accept(assignVisitor);
|
|
}
|
|
catch (std::exception& e)
|
|
{
|
|
std::cerr << "Can not add creature part: " << e.what() << std::endl;
|
|
}
|
|
}
|
|
|
|
void CreatureWeaponAnimation::attachArrow()
|
|
{
|
|
WeaponAnimation::attachArrow(mPtr);
|
|
}
|
|
|
|
void CreatureWeaponAnimation::releaseArrow(float attackStrength)
|
|
{
|
|
WeaponAnimation::releaseArrow(mPtr, attackStrength);
|
|
}
|
|
|
|
osg::Group *CreatureWeaponAnimation::getArrowBone()
|
|
{
|
|
if (!mWeapon)
|
|
return NULL;
|
|
|
|
SceneUtil::FindByNameVisitor findVisitor ("ArrowBone");
|
|
mWeapon->getNode()->accept(findVisitor);
|
|
|
|
return findVisitor.mFoundNode;
|
|
}
|
|
|
|
osg::Node *CreatureWeaponAnimation::getWeaponNode()
|
|
{
|
|
return mWeapon ? mWeapon->getNode().get() : NULL;
|
|
}
|
|
|
|
Resource::ResourceSystem *CreatureWeaponAnimation::getResourceSystem()
|
|
{
|
|
return mResourceSystem;
|
|
}
|
|
|
|
void CreatureWeaponAnimation::addControllers()
|
|
{
|
|
Animation::addControllers();
|
|
WeaponAnimation::addControllers(mNodeMap, mActiveControllers, mObjectRoot.get());
|
|
}
|
|
|
|
osg::Vec3f CreatureWeaponAnimation::runAnimation(float duration)
|
|
{
|
|
osg::Vec3f ret = Animation::runAnimation(duration);
|
|
|
|
WeaponAnimation::configureControllers(mPtr.getRefData().getPosition().rot[0]);
|
|
|
|
return ret;
|
|
}
|
|
|
|
}
|