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);
|
||||
}
|
||||
|
||||
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…
x
Reference in New Issue
Block a user