1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-15 22:49:55 +00:00
openmw-tes3mp/apps/openmw/mwrender/weaponanimation.cpp

228 lines
7.3 KiB
C++
Raw Normal View History

2014-03-12 10:30:44 +00:00
#include "weaponanimation.hpp"
2015-05-31 16:53:16 +00:00
#include <osg/MatrixTransform>
2015-05-30 23:07:43 +00:00
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
2014-03-12 10:30:44 +00:00
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"
2014-03-12 10:30:44 +00:00
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/esmstore.hpp"
#include "../mwmechanics/creaturestats.hpp"
2015-01-31 21:28:23 +00:00
#include "../mwmechanics/combat.hpp"
#include "../mwmechanics/weapontype.hpp"
2014-03-12 10:30:44 +00:00
#include "animation.hpp"
2015-05-31 16:53:16 +00:00
#include "rotatecontroller.hpp"
2014-03-12 10:30:44 +00:00
namespace MWRender
{
2015-05-30 23:07:43 +00:00
float WeaponAnimationTime::getValue(osg::NodeVisitor*)
2014-03-12 10:30:44 +00:00
{
if (mWeaponGroup.empty())
return 0;
2015-05-30 23:07:43 +00:00
2014-03-12 10:30:44 +00:00
float current = mAnimation->getCurrentTime(mWeaponGroup);
if (current == -1)
return 0;
return current - mStartTime;
}
void WeaponAnimationTime::setGroup(const std::string &group, bool relativeTime)
2014-03-12 10:30:44 +00:00
{
mWeaponGroup = group;
mRelativeTime = relativeTime;
if (mRelativeTime)
mStartTime = mAnimation->getStartTime(mWeaponGroup);
else
mStartTime = 0;
2014-03-12 10:30:44 +00:00
}
void WeaponAnimationTime::updateStartTime()
{
setGroup(mWeaponGroup, mRelativeTime);
2014-03-12 10:30:44 +00:00
}
2015-05-30 23:07:43 +00:00
WeaponAnimation::WeaponAnimation()
: mPitchFactor(0)
{
}
2015-05-31 16:53:16 +00:00
WeaponAnimation::~WeaponAnimation()
{
}
2014-03-12 10:30:44 +00:00
void WeaponAnimation::attachArrow(MWWorld::Ptr actor)
{
const MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor);
MWWorld::ConstContainerStoreIterator weaponSlot = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if (weaponSlot == inv.end())
return;
if (weaponSlot->getTypeName() != typeid(ESM::Weapon).name())
return;
int type = weaponSlot->get<ESM::Weapon>()->mBase->mData.mType;
ESM::WeaponType::Class weapclass = MWMechanics::getWeaponType(type)->mWeaponClass;
if (weapclass == ESM::WeaponType::Thrown)
{
std::string soundid = weaponSlot->getClass().getUpSoundId(*weaponSlot);
if(!soundid.empty())
{
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
sndMgr->playSound3D(actor, soundid, 1.0f, 1.0f);
}
2014-03-12 10:30:44 +00:00
showWeapon(true);
}
else if (weapclass == ESM::WeaponType::Ranged)
2014-03-12 10:30:44 +00:00
{
2015-05-30 23:07:43 +00:00
osg::Group* parent = getArrowBone();
if (!parent)
return;
2014-03-12 10:30:44 +00:00
MWWorld::ConstContainerStoreIterator ammo = inv.getSlot(MWWorld::InventoryStore::Slot_Ammunition);
2014-03-12 10:30:44 +00:00
if (ammo == inv.end())
return;
std::string model = ammo->getClass().getModel(*ammo);
2016-02-09 17:33:02 +00:00
osg::ref_ptr<osg::Node> arrow = getResourceSystem()->getSceneManager()->getInstance(model, parent);
2015-05-30 23:07:43 +00:00
mAmmunition = PartHolderPtr(new PartHolder(arrow));
2014-03-12 10:30:44 +00:00
}
}
void WeaponAnimation::detachArrow(MWWorld::Ptr actor)
{
mAmmunition.reset();
}
void WeaponAnimation::releaseArrow(MWWorld::Ptr actor, float attackStrength)
2014-03-12 10:30:44 +00:00
{
MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor);
MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
if (weapon == inv.end())
return;
if (weapon->getTypeName() != typeid(ESM::Weapon).name())
return;
2014-03-12 10:30:44 +00:00
// The orientation of the launched projectile. Always the same as the actor orientation, even if the ArrowBone's orientation dictates otherwise.
2015-05-30 23:07:43 +00:00
osg::Quat orient = osg::Quat(actor.getRefData().getPosition().rot[0], osg::Vec3f(-1,0,0))
* osg::Quat(actor.getRefData().getPosition().rot[2], osg::Vec3f(0,0,-1));
2014-03-12 10:30:44 +00:00
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
MWMechanics::applyFatigueLoss(actor, *weapon, attackStrength);
2014-03-12 10:30:44 +00:00
if (MWMechanics::getWeaponType(weapon->get<ESM::Weapon>()->mBase->mData.mType)->mWeaponClass == ESM::WeaponType::Thrown)
2014-03-12 10:30:44 +00:00
{
// Thrown weapons get detached now
2015-05-30 23:07:43 +00:00
osg::Node* weaponNode = getWeaponNode();
if (!weaponNode)
return;
osg::NodePathList nodepaths = weaponNode->getParentalNodePaths();
if (nodepaths.empty())
2015-05-30 23:07:43 +00:00
return;
osg::Vec3f launchPos = osg::computeLocalToWorld(nodepaths[0]).getTrans();
2014-03-12 10:30:44 +00:00
2018-08-29 15:38:12 +00:00
float fThrownWeaponMinSpeed = gmst.find("fThrownWeaponMinSpeed")->mValue.getFloat();
float fThrownWeaponMaxSpeed = gmst.find("fThrownWeaponMaxSpeed")->mValue.getFloat();
float speed = fThrownWeaponMinSpeed + (fThrownWeaponMaxSpeed - fThrownWeaponMinSpeed) * attackStrength;
2014-03-12 10:30:44 +00:00
MWWorld::Ptr weaponPtr = *weapon;
MWBase::Environment::get().getWorld()->launchProjectile(actor, weaponPtr, launchPos, orient, weaponPtr, speed, attackStrength);
2014-03-12 10:30:44 +00:00
showWeapon(false);
inv.remove(*weapon, 1, actor);
}
else
{
// With bows and crossbows only the used arrow/bolt gets detached
MWWorld::ContainerStoreIterator ammo = inv.getSlot(MWWorld::InventoryStore::Slot_Ammunition);
if (ammo == inv.end())
return;
2015-05-30 23:07:43 +00:00
if (!mAmmunition)
2015-01-04 00:33:36 +00:00
return;
2015-05-30 23:07:43 +00:00
osg::ref_ptr<osg::Node> ammoNode = mAmmunition->getNode();
osg::NodePathList nodepaths = ammoNode->getParentalNodePaths();
if (nodepaths.empty())
2015-05-30 23:07:43 +00:00
return;
osg::Vec3f launchPos = osg::computeLocalToWorld(nodepaths[0]).getTrans();
2014-03-12 10:30:44 +00:00
2018-08-29 15:38:12 +00:00
float fProjectileMinSpeed = gmst.find("fProjectileMinSpeed")->mValue.getFloat();
float fProjectileMaxSpeed = gmst.find("fProjectileMaxSpeed")->mValue.getFloat();
float speed = fProjectileMinSpeed + (fProjectileMaxSpeed - fProjectileMinSpeed) * attackStrength;
2014-03-12 10:30:44 +00:00
MWWorld::Ptr weaponPtr = *weapon;
MWWorld::Ptr ammoPtr = *ammo;
MWBase::Environment::get().getWorld()->launchProjectile(actor, ammoPtr, launchPos, orient, weaponPtr, speed, attackStrength);
2014-03-12 10:30:44 +00:00
inv.remove(ammoPtr, 1, actor);
2015-05-30 23:07:43 +00:00
mAmmunition.reset();
2014-03-12 10:30:44 +00:00
}
}
2015-05-31 16:53:16 +00:00
void WeaponAnimation::addControllers(const std::map<std::string, osg::ref_ptr<osg::MatrixTransform> >& nodes,
std::vector<std::pair<osg::ref_ptr<osg::Node>, osg::ref_ptr<osg::NodeCallback>>> &map, osg::Node* objectRoot)
2014-03-12 10:30:44 +00:00
{
2015-05-31 16:53:16 +00:00
for (int i=0; i<2; ++i)
{
2018-10-09 06:21:12 +00:00
mSpineControllers[i] = nullptr;
2014-03-12 10:30:44 +00:00
2015-05-31 16:53:16 +00:00
std::map<std::string, osg::ref_ptr<osg::MatrixTransform> >::const_iterator found = nodes.find(i == 0 ? "bip01 spine1" : "bip01 spine2");
if (found != nodes.end())
{
osg::Node* node = found->second;
mSpineControllers[i] = new RotateController(objectRoot);
node->addUpdateCallback(mSpineControllers[i]);
map.emplace_back(node, mSpineControllers[i]);
2015-05-31 16:53:16 +00:00
}
}
}
2015-05-31 16:53:16 +00:00
void WeaponAnimation::deleteControllers()
{
for (int i=0; i<2; ++i)
2018-10-09 06:21:12 +00:00
mSpineControllers[i] = nullptr;
2015-05-31 16:53:16 +00:00
}
2015-05-31 16:53:16 +00:00
void WeaponAnimation::configureControllers(float characterPitchRadians)
{
if (mPitchFactor == 0.f || characterPitchRadians == 0.f)
{
setControllerEnabled(false);
2015-05-31 16:53:16 +00:00
return;
}
float pitch = characterPitchRadians * mPitchFactor;
osg::Quat rotate (pitch/2, osg::Vec3f(-1,0,0));
setControllerRotate(rotate);
setControllerEnabled(true);
}
void WeaponAnimation::setControllerRotate(const osg::Quat& rotate)
{
2015-05-31 16:53:16 +00:00
for (int i=0; i<2; ++i)
if (mSpineControllers[i])
mSpineControllers[i]->setRotate(rotate);
}
void WeaponAnimation::setControllerEnabled(bool enabled)
{
for (int i=0; i<2; ++i)
if (mSpineControllers[i])
mSpineControllers[i]->setEnabled(enabled);
2014-03-12 10:30:44 +00:00
}
}