Projectiles interact with the water surface (Fixes #2986)

openmw-38
scrawl 9 years ago
parent 4a9b37aa53
commit 3f93af4181

@ -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();

@ -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);

@ -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));

@ -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);

@ -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);

@ -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();

@ -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;
}
}

@ -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<osg::Group> 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&);
};
}

@ -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();

Loading…
Cancel
Save