diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index c0a907f70..6e97905b8 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -756,6 +756,11 @@ namespace MWRender mWater->removeEmitter(ptr); } + void RenderingManager::emitWaterRipple(const osg::Vec3f &pos) + { + mWater->emitRipple(pos); + } + void RenderingManager::updateProjectionMatrix() { double aspect = mViewer->getCamera()->getViewport()->aspectRatio(); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index a0ea14cb4..4d223aeb8 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -138,6 +138,7 @@ namespace MWRender void addWaterRippleEmitter(const MWWorld::Ptr& ptr); void removeWaterRippleEmitter(const MWWorld::Ptr& ptr); + void emitWaterRipple(const osg::Vec3f& pos); void updatePlayerPtr(const MWWorld::Ptr &ptr); diff --git a/apps/openmw/mwrender/ripplesimulation.cpp b/apps/openmw/mwrender/ripplesimulation.cpp index 55b732613..766e20fc4 100644 --- a/apps/openmw/mwrender/ripplesimulation.cpp +++ b/apps/openmw/mwrender/ripplesimulation.cpp @@ -139,9 +139,7 @@ void RippleSimulation::update(float dt) if (mParticleSystem->numParticles()-mParticleSystem->numDeadParticles() > 500) continue; // TODO: remove the oldest particle to make room? - osgParticle::Particle* p = mParticleSystem->createParticle(NULL); - p->setPosition(currentPos); - p->setAngle(osg::Vec3f(0,0, Misc::Rng::rollProbability() * osg::PI * 2 - osg::PI)); + emitRipple(currentPos); } } } @@ -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) { mParticleNode->setPosition(osg::Vec3f(0,0,height)); diff --git a/apps/openmw/mwrender/ripplesimulation.hpp b/apps/openmw/mwrender/ripplesimulation.hpp index 17d5fea15..7d412f454 100644 --- a/apps/openmw/mwrender/ripplesimulation.hpp +++ b/apps/openmw/mwrender/ripplesimulation.hpp @@ -52,6 +52,8 @@ namespace MWRender void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr); 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 void setWaterHeight(float height); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 1afb74bd7..9823d79df 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -731,6 +731,11 @@ void Water::updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr) mSimulation->updateEmitterPtr(old, ptr); } +void Water::emitRipple(const osg::Vec3f &pos) +{ + mSimulation->emitRipple(pos); +} + void Water::removeCell(const MWWorld::CellStore *store) { mSimulation->removeCell(store); diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 551184c11..b26782873 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -91,6 +91,8 @@ namespace MWRender void addEmitter (const MWWorld::Ptr& ptr, float scale = 1.f, float force = 1.f); void removeEmitter (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 clearRipples(); diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index 08ae6f2b0..e188afc5d 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -25,6 +25,7 @@ #include "../mwrender/effectmanager.hpp" #include "../mwrender/animation.hpp" #include "../mwrender/vismask.hpp" +#include "../mwrender/renderingmanager.hpp" #include "../mwsound/sound.hpp" @@ -34,9 +35,11 @@ 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) , mResourceSystem(resourceSystem) + , mRendering(rendering) , mPhysics(physics) { @@ -225,32 +228,38 @@ namespace MWWorld // TODO: use a proper btRigidBody / btGhostObject? 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); - - // Try to get a Ptr to the bow that was used. It might no longer exist. - MWWorld::Ptr bow = projectileRef.getPtr(); - if (!caster.isEmpty()) + if (result.mHit) { - 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; + MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mId); + + // 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::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()) - caster = result.mHitObject; - - MWMechanics::projectileHit(caster, result.mHitObject, bow, projectileRef.getPtr(), result.mHitPos, it->mAttackStrength); + if (underwater) + mRendering->emitWaterRipple(newPos); mParent->removeChild(it->mNode); - it = mProjectiles.erase(it); continue; } - else - ++it; + + ++it; } } diff --git a/apps/openmw/mwworld/projectilemanager.hpp b/apps/openmw/mwworld/projectilemanager.hpp index 22fc4784c..87878ef2a 100644 --- a/apps/openmw/mwworld/projectilemanager.hpp +++ b/apps/openmw/mwworld/projectilemanager.hpp @@ -36,6 +36,7 @@ namespace Resource namespace MWRender { class EffectAnimationTime; + class RenderingManager; } namespace MWWorld @@ -45,7 +46,7 @@ namespace MWWorld { public: 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. void launchMagicBolt (const std::string& model, const std::string &sound, const std::string &spellId, @@ -67,6 +68,7 @@ namespace MWWorld private: osg::ref_ptr mParent; Resource::ResourceSystem* mResourceSystem; + MWRender::RenderingManager* mRendering; MWPhysics::PhysicsSystem* mPhysics; 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 update (State& state, float duration); + + void operator=(const ProjectileManager&); + ProjectileManager(const ProjectileManager&); }; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 22485ed92..a2c8b6bd9 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -163,8 +163,8 @@ namespace MWWorld mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0) { mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode); - mProjectileManager.reset(new ProjectileManager(rootNode, resourceSystem, mPhysics)); mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem, &mFallback, resourcePath); + mProjectileManager.reset(new ProjectileManager(rootNode, resourceSystem, mRendering, mPhysics)); mEsm.resize(contentFiles.size()); Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();