mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-13 12:40:04 +00:00
Projectiles interact with the water surface (Fixes #2986)
This commit is contained in:
parent
4a9b37aa53
commit
3f93af4181
@ -756,6 +756,11 @@ namespace MWRender
|
|||||||
mWater->removeEmitter(ptr);
|
mWater->removeEmitter(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingManager::emitWaterRipple(const osg::Vec3f &pos)
|
||||||
|
{
|
||||||
|
mWater->emitRipple(pos);
|
||||||
|
}
|
||||||
|
|
||||||
void RenderingManager::updateProjectionMatrix()
|
void RenderingManager::updateProjectionMatrix()
|
||||||
{
|
{
|
||||||
double aspect = mViewer->getCamera()->getViewport()->aspectRatio();
|
double aspect = mViewer->getCamera()->getViewport()->aspectRatio();
|
||||||
|
@ -138,6 +138,7 @@ namespace MWRender
|
|||||||
|
|
||||||
void addWaterRippleEmitter(const MWWorld::Ptr& ptr);
|
void addWaterRippleEmitter(const MWWorld::Ptr& ptr);
|
||||||
void removeWaterRippleEmitter(const MWWorld::Ptr& ptr);
|
void removeWaterRippleEmitter(const MWWorld::Ptr& ptr);
|
||||||
|
void emitWaterRipple(const osg::Vec3f& pos);
|
||||||
|
|
||||||
void updatePlayerPtr(const MWWorld::Ptr &ptr);
|
void updatePlayerPtr(const MWWorld::Ptr &ptr);
|
||||||
|
|
||||||
|
@ -139,9 +139,7 @@ void RippleSimulation::update(float dt)
|
|||||||
if (mParticleSystem->numParticles()-mParticleSystem->numDeadParticles() > 500)
|
if (mParticleSystem->numParticles()-mParticleSystem->numDeadParticles() > 500)
|
||||||
continue; // TODO: remove the oldest particle to make room?
|
continue; // TODO: remove the oldest particle to make room?
|
||||||
|
|
||||||
osgParticle::Particle* p = mParticleSystem->createParticle(NULL);
|
emitRipple(currentPos);
|
||||||
p->setPosition(currentPos);
|
|
||||||
p->setAngle(osg::Vec3f(0,0, Misc::Rng::rollProbability() * osg::PI * 2 - osg::PI));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,6 +192,16 @@ void RippleSimulation::removeCell(const MWWorld::CellStore *store)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RippleSimulation::emitRipple(const osg::Vec3f &pos)
|
||||||
|
{
|
||||||
|
if (std::abs(pos.z() - mParticleNode->getPosition().z()) < 20)
|
||||||
|
{
|
||||||
|
osgParticle::Particle* p = mParticleSystem->createParticle(NULL);
|
||||||
|
p->setPosition(osg::Vec3f(pos.x(), pos.y(), 0.f));
|
||||||
|
p->setAngle(osg::Vec3f(0,0, Misc::Rng::rollProbability() * osg::PI * 2 - osg::PI));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RippleSimulation::setWaterHeight(float height)
|
void RippleSimulation::setWaterHeight(float height)
|
||||||
{
|
{
|
||||||
mParticleNode->setPosition(osg::Vec3f(0,0,height));
|
mParticleNode->setPosition(osg::Vec3f(0,0,height));
|
||||||
|
@ -52,6 +52,8 @@ namespace MWRender
|
|||||||
void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr);
|
void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr);
|
||||||
void removeCell(const MWWorld::CellStore* store);
|
void removeCell(const MWWorld::CellStore* store);
|
||||||
|
|
||||||
|
void emitRipple(const osg::Vec3f& pos);
|
||||||
|
|
||||||
/// Change the height of the water surface, thus moving all ripples with it
|
/// Change the height of the water surface, thus moving all ripples with it
|
||||||
void setWaterHeight(float height);
|
void setWaterHeight(float height);
|
||||||
|
|
||||||
|
@ -731,6 +731,11 @@ void Water::updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr)
|
|||||||
mSimulation->updateEmitterPtr(old, ptr);
|
mSimulation->updateEmitterPtr(old, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Water::emitRipple(const osg::Vec3f &pos)
|
||||||
|
{
|
||||||
|
mSimulation->emitRipple(pos);
|
||||||
|
}
|
||||||
|
|
||||||
void Water::removeCell(const MWWorld::CellStore *store)
|
void Water::removeCell(const MWWorld::CellStore *store)
|
||||||
{
|
{
|
||||||
mSimulation->removeCell(store);
|
mSimulation->removeCell(store);
|
||||||
|
@ -91,6 +91,8 @@ namespace MWRender
|
|||||||
void addEmitter (const MWWorld::Ptr& ptr, float scale = 1.f, float force = 1.f);
|
void addEmitter (const MWWorld::Ptr& ptr, float scale = 1.f, float force = 1.f);
|
||||||
void removeEmitter (const MWWorld::Ptr& ptr);
|
void removeEmitter (const MWWorld::Ptr& ptr);
|
||||||
void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr);
|
void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr);
|
||||||
|
void emitRipple(const osg::Vec3f& pos);
|
||||||
|
|
||||||
void removeCell(const MWWorld::CellStore* store); ///< remove all emitters in this cell
|
void removeCell(const MWWorld::CellStore* store); ///< remove all emitters in this cell
|
||||||
|
|
||||||
void clearRipples();
|
void clearRipples();
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "../mwrender/effectmanager.hpp"
|
#include "../mwrender/effectmanager.hpp"
|
||||||
#include "../mwrender/animation.hpp"
|
#include "../mwrender/animation.hpp"
|
||||||
#include "../mwrender/vismask.hpp"
|
#include "../mwrender/vismask.hpp"
|
||||||
|
#include "../mwrender/renderingmanager.hpp"
|
||||||
|
|
||||||
#include "../mwsound/sound.hpp"
|
#include "../mwsound/sound.hpp"
|
||||||
|
|
||||||
@ -34,9 +35,11 @@
|
|||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
|
||||||
ProjectileManager::ProjectileManager(osg::Group* parent, Resource::ResourceSystem* resourceSystem, MWPhysics::PhysicsSystem* physics)
|
ProjectileManager::ProjectileManager(osg::Group* parent, Resource::ResourceSystem* resourceSystem,
|
||||||
|
MWRender::RenderingManager* rendering, MWPhysics::PhysicsSystem* physics)
|
||||||
: mParent(parent)
|
: mParent(parent)
|
||||||
, mResourceSystem(resourceSystem)
|
, mResourceSystem(resourceSystem)
|
||||||
|
, mRendering(rendering)
|
||||||
, mPhysics(physics)
|
, mPhysics(physics)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -225,32 +228,38 @@ namespace MWWorld
|
|||||||
// TODO: use a proper btRigidBody / btGhostObject?
|
// TODO: use a proper btRigidBody / btGhostObject?
|
||||||
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(pos, newPos, caster, 0xff, MWPhysics::CollisionType_Projectile);
|
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(pos, newPos, caster, 0xff, MWPhysics::CollisionType_Projectile);
|
||||||
|
|
||||||
if (result.mHit)
|
bool underwater = MWBase::Environment::get().getWorld()->isUnderwater(MWMechanics::getPlayer().getCell(), newPos);
|
||||||
|
if (result.mHit || underwater)
|
||||||
{
|
{
|
||||||
MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mId);
|
if (result.mHit)
|
||||||
|
|
||||||
// Try to get a Ptr to the bow that was used. It might no longer exist.
|
|
||||||
MWWorld::Ptr bow = projectileRef.getPtr();
|
|
||||||
if (!caster.isEmpty())
|
|
||||||
{
|
{
|
||||||
MWWorld::InventoryStore& inv = caster.getClass().getInventoryStore(caster);
|
MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mId);
|
||||||
MWWorld::ContainerStoreIterator invIt = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
|
||||||
if (invIt != inv.end() && Misc::StringUtils::ciEqual(invIt->getCellRef().getRefId(), it->mBowId))
|
// Try to get a Ptr to the bow that was used. It might no longer exist.
|
||||||
bow = *invIt;
|
MWWorld::Ptr bow = projectileRef.getPtr();
|
||||||
|
if (!caster.isEmpty())
|
||||||
|
{
|
||||||
|
MWWorld::InventoryStore& inv = caster.getClass().getInventoryStore(caster);
|
||||||
|
MWWorld::ContainerStoreIterator invIt = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
|
if (invIt != inv.end() && Misc::StringUtils::ciEqual(invIt->getCellRef().getRefId(), it->mBowId))
|
||||||
|
bow = *invIt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caster.isEmpty())
|
||||||
|
caster = result.mHitObject;
|
||||||
|
|
||||||
|
MWMechanics::projectileHit(caster, result.mHitObject, bow, projectileRef.getPtr(), result.mHitPos, it->mAttackStrength);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caster.isEmpty())
|
if (underwater)
|
||||||
caster = result.mHitObject;
|
mRendering->emitWaterRipple(newPos);
|
||||||
|
|
||||||
MWMechanics::projectileHit(caster, result.mHitObject, bow, projectileRef.getPtr(), result.mHitPos, it->mAttackStrength);
|
|
||||||
|
|
||||||
mParent->removeChild(it->mNode);
|
mParent->removeChild(it->mNode);
|
||||||
|
|
||||||
it = mProjectiles.erase(it);
|
it = mProjectiles.erase(it);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ namespace Resource
|
|||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
class EffectAnimationTime;
|
class EffectAnimationTime;
|
||||||
|
class RenderingManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
@ -45,7 +46,7 @@ namespace MWWorld
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProjectileManager (osg::Group* parent, Resource::ResourceSystem* resourceSystem,
|
ProjectileManager (osg::Group* parent, Resource::ResourceSystem* resourceSystem,
|
||||||
MWPhysics::PhysicsSystem* physics);
|
MWRender::RenderingManager* rendering, MWPhysics::PhysicsSystem* physics);
|
||||||
|
|
||||||
/// If caster is an actor, the actor's facing orientation is used. Otherwise fallbackDirection is used.
|
/// If caster is an actor, the actor's facing orientation is used. Otherwise fallbackDirection is used.
|
||||||
void launchMagicBolt (const std::string& model, const std::string &sound, const std::string &spellId,
|
void launchMagicBolt (const std::string& model, const std::string &sound, const std::string &spellId,
|
||||||
@ -67,6 +68,7 @@ namespace MWWorld
|
|||||||
private:
|
private:
|
||||||
osg::ref_ptr<osg::Group> mParent;
|
osg::ref_ptr<osg::Group> mParent;
|
||||||
Resource::ResourceSystem* mResourceSystem;
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
|
MWRender::RenderingManager* mRendering;
|
||||||
MWPhysics::PhysicsSystem* mPhysics;
|
MWPhysics::PhysicsSystem* mPhysics;
|
||||||
|
|
||||||
struct State
|
struct State
|
||||||
@ -120,6 +122,9 @@ namespace MWWorld
|
|||||||
|
|
||||||
void createModel (State& state, const std::string& model, const osg::Vec3f& pos, const osg::Quat& orient);
|
void createModel (State& state, const std::string& model, const osg::Vec3f& pos, const osg::Quat& orient);
|
||||||
void update (State& state, float duration);
|
void update (State& state, float duration);
|
||||||
|
|
||||||
|
void operator=(const ProjectileManager&);
|
||||||
|
ProjectileManager(const ProjectileManager&);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -163,8 +163,8 @@ namespace MWWorld
|
|||||||
mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0)
|
mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0)
|
||||||
{
|
{
|
||||||
mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode);
|
mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode);
|
||||||
mProjectileManager.reset(new ProjectileManager(rootNode, resourceSystem, mPhysics));
|
|
||||||
mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem, &mFallback, resourcePath);
|
mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem, &mFallback, resourcePath);
|
||||||
|
mProjectileManager.reset(new ProjectileManager(rootNode, resourceSystem, mRendering, mPhysics));
|
||||||
|
|
||||||
mEsm.resize(contentFiles.size());
|
mEsm.resize(contentFiles.size());
|
||||||
Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user