diff --git a/apps/openmw/mwphysics/closestnotmeconvexresultcallback.cpp b/apps/openmw/mwphysics/closestnotmeconvexresultcallback.cpp index bbffe16a8e..8f72422765 100644 --- a/apps/openmw/mwphysics/closestnotmeconvexresultcallback.cpp +++ b/apps/openmw/mwphysics/closestnotmeconvexresultcallback.cpp @@ -25,13 +25,17 @@ namespace MWPhysics if (convexResult.m_hitCollisionObject->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Projectile) { - Projectile* projectileHolder = static_cast(convexResult.m_hitCollisionObject->getUserPointer()); + auto* projectileHolder = static_cast(convexResult.m_hitCollisionObject->getUserPointer()); if (!projectileHolder->isActive()) return btScalar(1); - PtrHolder* targetHolder = static_cast(mMe->getUserPointer()); + auto* targetHolder = static_cast(mMe->getUserPointer()); const MWWorld::Ptr target = targetHolder->getPtr(); - projectileHolder->hit(target, convexResult.m_hitPointLocal, convexResult.m_hitNormalLocal); - return btScalar(1); + // do nothing if we hit the caster. Sometimes the launching origin is inside of caster collision shape + if (projectileHolder->getCaster() != target) + { + projectileHolder->hit(target, convexResult.m_hitPointLocal, convexResult.m_hitNormalLocal); + return btScalar(1); + } } btVector3 hitNormalWorld; diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 7da2a69643..324b1db2d7 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -661,10 +661,10 @@ namespace MWPhysics mActors.emplace(ptr, std::move(actor)); } - int PhysicsSystem::addProjectile (const osg::Vec3f& position) + int PhysicsSystem::addProjectile (const MWWorld::Ptr& caster, const osg::Vec3f& position) { mProjectileId++; - auto projectile = std::make_shared(mProjectileId, position, mTaskScheduler.get(), this); + auto projectile = std::make_shared(mProjectileId, caster, position, mTaskScheduler.get(), this); mProjectiles.emplace(mProjectileId, std::move(projectile)); return mProjectileId; diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index 6721a2d918..b33d829a46 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -128,7 +128,7 @@ namespace MWPhysics void addObject (const MWWorld::Ptr& ptr, const std::string& mesh, int collisionType = CollisionType_World); void addActor (const MWWorld::Ptr& ptr, const std::string& mesh); - int addProjectile(const osg::Vec3f& position); + int addProjectile(const MWWorld::Ptr& caster, const osg::Vec3f& position); void updateProjectile(const int projectileId, const osg::Vec3f &position); void removeProjectile(const int projectileId); diff --git a/apps/openmw/mwphysics/projectile.cpp b/apps/openmw/mwphysics/projectile.cpp index cbc5b19814..5f5bc778ba 100644 --- a/apps/openmw/mwphysics/projectile.cpp +++ b/apps/openmw/mwphysics/projectile.cpp @@ -18,8 +18,9 @@ namespace MWPhysics { -Projectile::Projectile(int projectileId, const osg::Vec3f& position, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem) +Projectile::Projectile(int projectileId, const MWWorld::Ptr& caster, const osg::Vec3f& position, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem) : mActive(true) + , mCaster(caster) , mPhysics(physicssystem) , mTaskScheduler(scheduler) , mProjectileId(projectileId) diff --git a/apps/openmw/mwphysics/projectile.hpp b/apps/openmw/mwphysics/projectile.hpp index 6e8aba60b8..ed0fdce150 100644 --- a/apps/openmw/mwphysics/projectile.hpp +++ b/apps/openmw/mwphysics/projectile.hpp @@ -32,7 +32,7 @@ namespace MWPhysics class Projectile final : public PtrHolder { public: - Projectile(const int projectileId, const osg::Vec3f& position, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem); + Projectile(const int projectileId, const MWWorld::Ptr& caster, const osg::Vec3f& position, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem); ~Projectile() override; btConvexShape* getConvexShape() const { return mConvexShape; } @@ -62,6 +62,8 @@ namespace MWPhysics return mHitTarget; } + MWWorld::Ptr getCaster() const { return mCaster; } + osg::Vec3f getHitPos() const { assert(!mActive); @@ -80,6 +82,7 @@ namespace MWPhysics btTransform mLocalTransform; bool mTransformUpdatePending; std::atomic mActive; + MWWorld::Ptr mCaster; MWWorld::Ptr mHitTarget; btVector3 mHitPosition; btVector3 mHitNormal; diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index 626c57ac32..dba4289a23 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -316,7 +316,7 @@ namespace MWWorld state.mSounds.push_back(sound); } - state.mProjectileId = mPhysics->addProjectile(pos); + state.mProjectileId = mPhysics->addProjectile(caster, pos); state.mToDelete = false; mMagicBolts.push_back(state); } @@ -340,7 +340,7 @@ namespace MWWorld if (!ptr.getClass().getEnchantment(ptr).empty()) SceneUtil::addEnchantedGlow(state.mNode, mResourceSystem, ptr.getClass().getEnchantmentColor(ptr)); - state.mProjectileId = mPhysics->addProjectile(pos); + state.mProjectileId = mPhysics->addProjectile(actor, pos); state.mToDelete = false; mProjectiles.push_back(state); } @@ -546,7 +546,8 @@ namespace MWWorld const auto target = projectile->getTarget(); const auto pos = projectile->getHitPos(); MWWorld::Ptr caster = projectileState.getCaster(); - if (caster == target || !isValidTarget(caster, target)) + assert(target != caster); + if (!isValidTarget(caster, target)) { projectile->activate(); continue; @@ -581,7 +582,8 @@ namespace MWWorld const auto target = projectile->getTarget(); const auto pos = projectile->getHitPos(); MWWorld::Ptr caster = magicBoltState.getCaster(); - if (caster == target || !isValidTarget(caster, target)) + assert(target != caster); + if (!isValidTarget(caster, target)) { projectile->activate(); continue; @@ -724,7 +726,7 @@ namespace MWWorld int weaponType = ptr.get()->mBase->mData.mType; state.mThrown = MWMechanics::getWeaponType(weaponType)->mWeaponClass == ESM::WeaponType::Thrown; - state.mProjectileId = mPhysics->addProjectile(osg::Vec3f(esm.mPosition)); + state.mProjectileId = mPhysics->addProjectile(state.getCaster(), osg::Vec3f(esm.mPosition)); } catch(...) { @@ -769,7 +771,7 @@ namespace MWWorld MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), state.mIdMagic.at(0)); MWWorld::Ptr ptr = ref.getPtr(); model = ptr.getClass().getModel(ptr); - state.mProjectileId = mPhysics->addProjectile(osg::Vec3f(esm.mPosition)); + state.mProjectileId = mPhysics->addProjectile(state.getCaster(), osg::Vec3f(esm.mPosition)); } catch(...) {