1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-26 09:35:28 +00:00

Merge branch 'explosion_at_impact' into 'master'

Bring arrow behaviour in line with vanilla (#6233 and other change)

See merge request OpenMW/openmw!1188
This commit is contained in:
psi29a 2021-09-27 19:00:53 +00:00
commit 2cee222e73
7 changed files with 29 additions and 44 deletions

View File

@ -624,7 +624,7 @@ namespace MWPhysics
mTaskScheduler->convexSweepTest(projectile->getConvexShape(), from_, to_, resultCallback);
const auto newpos = projectile->isActive() ? position : Misc::Convert::toOsg(resultCallback.m_hitPointWorld);
const auto newpos = projectile->isActive() ? position : Misc::Convert::toOsg(projectile->getHitPosition());
projectile->setPosition(newpos);
mTaskScheduler->updateSingleAabb(foundProjectile->second);
}
@ -686,7 +686,7 @@ namespace MWPhysics
mActors.emplace(ptr.mRef, std::move(actor));
}
int PhysicsSystem::addProjectile (const MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius, bool canTraverseWater)
int PhysicsSystem::addProjectile (const MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius)
{
osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance = mShapeManager->getInstance(mesh);
assert(shapeInstance);
@ -694,7 +694,7 @@ namespace MWPhysics
mProjectileId++;
auto projectile = std::make_shared<Projectile>(caster, position, radius, canTraverseWater, mTaskScheduler.get(), this);
auto projectile = std::make_shared<Projectile>(caster, position, radius, mTaskScheduler.get(), this);
mProjectiles.emplace(mProjectileId, std::move(projectile));
return mProjectileId;

View File

@ -131,7 +131,7 @@ namespace MWPhysics
void addObject (const MWWorld::Ptr& ptr, const std::string& mesh, osg::Quat rotation, int collisionType = CollisionType_World, bool skipAnimated = false);
void addActor (const MWWorld::Ptr& ptr, const std::string& mesh);
int addProjectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius, bool canTraverseWater);
int addProjectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius);
void setCaster(int projectileId, const MWWorld::Ptr& caster);
void updateProjectile(const int projectileId, const osg::Vec3f &position) const;
void removeProjectile(const int projectileId);

View File

@ -15,12 +15,10 @@
namespace MWPhysics
{
Projectile::Projectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, float radius, bool canCrossWaterSurface, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem)
: mCanCrossWaterSurface(canCrossWaterSurface)
, mCrossedWaterSurface(false)
Projectile::Projectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, float radius, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem)
: mHitWater(false)
, mActive(true)
, mHitTarget(nullptr)
, mWaterHitPosition(std::nullopt)
, mPhysics(physicssystem)
, mTaskScheduler(scheduler)
{
@ -75,11 +73,6 @@ osg::Vec3f Projectile::getPosition() const
return mPosition;
}
bool Projectile::canTraverseWater() const
{
return mCanCrossWaterSurface;
}
void Projectile::hit(const btCollisionObject* target, btVector3 pos, btVector3 normal)
{
bool active = true;
@ -143,17 +136,4 @@ bool Projectile::isValidTarget(const btCollisionObject* target) const
[target](const btCollisionObject* actor) { return target == actor; });
}
std::optional<btVector3> Projectile::getWaterHitPosition()
{
return std::exchange(mWaterHitPosition, std::nullopt);
}
void Projectile::setWaterHitPosition(btVector3 pos)
{
if (mCrossedWaterSurface)
return;
mCrossedWaterSurface = true;
mWaterHitPosition = pos;
}
}

View File

@ -4,7 +4,6 @@
#include <atomic>
#include <memory>
#include <mutex>
#include <optional>
#include <LinearMath/btVector3.h>
@ -32,7 +31,7 @@ namespace MWPhysics
class Projectile final : public PtrHolder
{
public:
Projectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, float radius, bool canCrossWaterSurface, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem);
Projectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, float radius, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem);
~Projectile() override;
btConvexShape* getConvexShape() const { return mConvexShape; }
@ -56,15 +55,25 @@ namespace MWPhysics
return mCasterColObj;
}
bool canTraverseWater() const;
void setHitWater()
{
mHitWater = true;
}
bool getHitWater() const
{
return mHitWater;
}
void hit(const btCollisionObject* target, btVector3 pos, btVector3 normal);
void setValidTargets(const std::vector<MWWorld::Ptr>& targets);
bool isValidTarget(const btCollisionObject* target) const;
std::optional<btVector3> getWaterHitPosition();
void setWaterHitPosition(btVector3 pos);
btVector3 getHitPosition() const
{
return mHitPosition;
}
private:
@ -72,13 +81,11 @@ namespace MWPhysics
btConvexShape* mConvexShape;
bool mTransformUpdatePending;
bool mCanCrossWaterSurface;
bool mCrossedWaterSurface;
bool mHitWater;
std::atomic<bool> mActive;
MWWorld::Ptr mCaster;
const btCollisionObject* mCasterColObj;
const btCollisionObject* mHitTarget;
std::optional<btVector3> mWaterHitPosition;
osg::Vec3f mPosition;
btVector3 mHitPosition;
btVector3 mHitNormal;

View File

@ -49,9 +49,7 @@ namespace MWPhysics
}
case CollisionType_Water:
{
mProjectile->setWaterHitPosition(m_hitPointWorld);
if (mProjectile->canTraverseWater())
return 1.f;
mProjectile->setHitWater();
break;
}
}

View File

@ -317,7 +317,7 @@ namespace MWWorld
// in case there are multiple effects, the model is a dummy without geometry. Use the second effect for physics shape
if (state.mIdMagic.size() > 1)
model = "meshes\\" + MWBase::Environment::get().getWorld()->getStore().get<ESM::Weapon>().find(state.mIdMagic[1])->mModel;
state.mProjectileId = mPhysics->addProjectile(caster, pos, model, true, false);
state.mProjectileId = mPhysics->addProjectile(caster, pos, model, true);
state.mToDelete = false;
mMagicBolts.push_back(state);
}
@ -342,7 +342,7 @@ namespace MWWorld
if (!ptr.getClass().getEnchantment(ptr).empty())
SceneUtil::addEnchantedGlow(state.mNode, mResourceSystem, ptr.getClass().getEnchantmentColor(ptr));
state.mProjectileId = mPhysics->addProjectile(actor, pos, model, false, true);
state.mProjectileId = mPhysics->addProjectile(actor, pos, model, false);
state.mToDelete = false;
mProjectiles.push_back(state);
}
@ -493,9 +493,6 @@ namespace MWWorld
auto* projectile = mPhysics->getProjectile(projectileState.mProjectileId);
if (const auto hitWaterPos = projectile->getWaterHitPosition())
mRendering->emitWaterRipple(Misc::Convert::toOsg(*hitWaterPos));
const auto pos = projectile->getPosition();
projectileState.mNode->setPosition(pos);
@ -519,6 +516,8 @@ namespace MWWorld
if (invIt != inv.end() && Misc::StringUtils::ciEqual(invIt->getCellRef().getRefId(), projectileState.mBowId))
bow = *invIt;
}
if (projectile->getHitWater())
mRendering->emitWaterRipple(pos);
MWMechanics::projectileHit(caster, target, bow, projectileRef.getPtr(), pos, projectileState.mAttackStrength);
projectileState.mToDelete = true;
@ -663,7 +662,7 @@ namespace MWWorld
int weaponType = ptr.get<ESM::Weapon>()->mBase->mData.mType;
state.mThrown = MWMechanics::getWeaponType(weaponType)->mWeaponClass == ESM::WeaponType::Thrown;
state.mProjectileId = mPhysics->addProjectile(state.getCaster(), osg::Vec3f(esm.mPosition), model, false, true);
state.mProjectileId = mPhysics->addProjectile(state.getCaster(), osg::Vec3f(esm.mPosition), model, false);
}
catch(...)
{
@ -716,7 +715,7 @@ namespace MWWorld
osg::Vec4 lightDiffuseColor = getMagicBoltLightDiffuseColor(state.mEffects);
createModel(state, model, osg::Vec3f(esm.mPosition), osg::Quat(esm.mOrientation), true, true, lightDiffuseColor, texture);
state.mProjectileId = mPhysics->addProjectile(state.getCaster(), osg::Vec3f(esm.mPosition), model, true, false);
state.mProjectileId = mPhysics->addProjectile(state.getCaster(), osg::Vec3f(esm.mPosition), model, true);
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
for (const std::string &soundid : state.mSoundIds)

View File

@ -3125,6 +3125,7 @@ namespace MWWorld
bool underwater = MWBase::Environment::get().getWorld()->isUnderwater(MWMechanics::getPlayer().getCell(), worldPos);
if (underwater)
{
MWMechanics::projectileHit(actor, Ptr(), bow, projectile, worldPos, attackStrength);
mRendering->emitWaterRipple(worldPos);
return;
}