mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-29 03:26:38 +00:00 
			
		
		
		
	Base GetColliding script functions on collisions detected by the movement solver
This commit is contained in:
		
							parent
							
								
									6b35ee68e1
								
							
						
					
					
						commit
						467220e6d7
					
				
					 7 changed files with 64 additions and 19 deletions
				
			
		|  | @ -61,6 +61,7 @@ | ||||||
|     Bug #7034: Misc items defined in one content file are not treated as keys if another content file uses them as such |     Bug #7034: Misc items defined in one content file are not treated as keys if another content file uses them as such | ||||||
|     Bug #7042: Weapon follow animations that immediately follow the hit animations cause multiple hits |     Bug #7042: Weapon follow animations that immediately follow the hit animations cause multiple hits | ||||||
|     Bug #7044: Changing a class' services does not affect autocalculated NPCs |     Bug #7044: Changing a class' services does not affect autocalculated NPCs | ||||||
|  |     Bug #7053: Running into objects doesn't trigger GetCollidingPC | ||||||
|     Bug #7054: Quests aren't sorted by name |     Bug #7054: Quests aren't sorted by name | ||||||
|     Bug #7064: NPCs don't report crime if the player is casting offensive spells on them while sneaking |     Bug #7064: NPCs don't report crime if the player is casting offensive spells on them while sneaking | ||||||
|     Bug #7077: OpenMW fails to load certain particle effects in .osgt format |     Bug #7077: OpenMW fails to load certain particle effects in .osgt format | ||||||
|  |  | ||||||
|  | @ -15,6 +15,7 @@ | ||||||
| #include "collisiontype.hpp" | #include "collisiontype.hpp" | ||||||
| #include "constants.hpp" | #include "constants.hpp" | ||||||
| #include "contacttestwrapper.h" | #include "contacttestwrapper.h" | ||||||
|  | #include "object.hpp" | ||||||
| #include "physicssystem.hpp" | #include "physicssystem.hpp" | ||||||
| #include "projectile.hpp" | #include "projectile.hpp" | ||||||
| #include "projectileconvexcallback.hpp" | #include "projectileconvexcallback.hpp" | ||||||
|  | @ -243,11 +244,20 @@ namespace MWPhysics | ||||||
|             float hitHeight = tracer.mHitPoint.z() - tracer.mEndPos.z() + actor.mHalfExtentsZ; |             float hitHeight = tracer.mHitPoint.z() - tracer.mEndPos.z() + actor.mHalfExtentsZ; | ||||||
|             osg::Vec3f oldPosition = newPosition; |             osg::Vec3f oldPosition = newPosition; | ||||||
|             bool usedStepLogic = false; |             bool usedStepLogic = false; | ||||||
|             if (hitHeight < Constants::sStepSizeUp && !isActor(tracer.mHitObject)) |             if (!isActor(tracer.mHitObject)) | ||||||
|             { |             { | ||||||
|                 // Try to step up onto it.
 |                 if (hitHeight < Constants::sStepSizeUp) | ||||||
|                 // NOTE: this modifies newPosition and velocity on its own if successful
 |                 { | ||||||
|                 usedStepLogic = stepper.step(newPosition, velocity, remainingTime, seenGround, iterations == 0); |                     // Try to step up onto it.
 | ||||||
|  |                     // NOTE: this modifies newPosition and velocity on its own if successful
 | ||||||
|  |                     usedStepLogic = stepper.step(newPosition, velocity, remainingTime, seenGround, iterations == 0); | ||||||
|  |                 } | ||||||
|  |                 auto* ptrHolder = static_cast<PtrHolder*>(tracer.mHitObject->getUserPointer()); | ||||||
|  |                 if (Object* hitObject = dynamic_cast<Object*>(ptrHolder)) | ||||||
|  |                 { | ||||||
|  |                     hitObject->addCollision( | ||||||
|  |                         actor.mIsPlayer ? ScriptedCollisionType_Player : ScriptedCollisionType_Actor); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             if (usedStepLogic) |             if (usedStepLogic) | ||||||
|             { |             { | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ namespace MWPhysics | ||||||
|         , mPosition(ptr.getRefData().getPosition().asVec3()) |         , mPosition(ptr.getRefData().getPosition().asVec3()) | ||||||
|         , mRotation(rotation) |         , mRotation(rotation) | ||||||
|         , mTaskScheduler(scheduler) |         , mTaskScheduler(scheduler) | ||||||
|  |         , mCollidedWith(ScriptedCollisionType_None) | ||||||
|     { |     { | ||||||
|         mCollisionObject = BulletHelpers::makeCollisionObject(mShapeInstance->mCollisionShape.get(), |         mCollisionObject = BulletHelpers::makeCollisionObject(mShapeInstance->mCollisionShape.get(), | ||||||
|             Misc::Convert::toBullet(mPosition), Misc::Convert::toBullet(rotation)); |             Misc::Convert::toBullet(mPosition), Misc::Convert::toBullet(rotation)); | ||||||
|  | @ -166,4 +167,20 @@ namespace MWPhysics | ||||||
|         } |         } | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     bool Object::collidedWith(ScriptedCollisionType type) const | ||||||
|  |     { | ||||||
|  |         return mCollidedWith & type; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void Object::addCollision(ScriptedCollisionType type) | ||||||
|  |     { | ||||||
|  |         std::unique_lock<std::mutex> lock(mPositionMutex); | ||||||
|  |         mCollidedWith |= type; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void Object::resetCollisions() | ||||||
|  |     { | ||||||
|  |         mCollidedWith = ScriptedCollisionType_None; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -18,6 +18,14 @@ namespace MWPhysics | ||||||
| { | { | ||||||
|     class PhysicsTaskScheduler; |     class PhysicsTaskScheduler; | ||||||
| 
 | 
 | ||||||
|  |     enum ScriptedCollisionType : char | ||||||
|  |     { | ||||||
|  |         ScriptedCollisionType_None = 0, | ||||||
|  |         ScriptedCollisionType_Actor = 1, | ||||||
|  |         // Note that this isn't 3, colliding with a player doesn't count as colliding with an actor
 | ||||||
|  |         ScriptedCollisionType_Player = 2 | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     class Object final : public PtrHolder |     class Object final : public PtrHolder | ||||||
|     { |     { | ||||||
|     public: |     public: | ||||||
|  | @ -38,6 +46,9 @@ namespace MWPhysics | ||||||
|         /// @brief update object shape
 |         /// @brief update object shape
 | ||||||
|         /// @return true if shape changed
 |         /// @return true if shape changed
 | ||||||
|         bool animateCollisionShapes(); |         bool animateCollisionShapes(); | ||||||
|  |         bool collidedWith(ScriptedCollisionType type) const; | ||||||
|  |         void addCollision(ScriptedCollisionType type); | ||||||
|  |         void resetCollisions(); | ||||||
| 
 | 
 | ||||||
|     private: |     private: | ||||||
|         osg::ref_ptr<Resource::BulletShapeInstance> mShapeInstance; |         osg::ref_ptr<Resource::BulletShapeInstance> mShapeInstance; | ||||||
|  | @ -50,6 +61,7 @@ namespace MWPhysics | ||||||
|         bool mTransformUpdatePending = false; |         bool mTransformUpdatePending = false; | ||||||
|         mutable std::mutex mPositionMutex; |         mutable std::mutex mPositionMutex; | ||||||
|         PhysicsTaskScheduler* mTaskScheduler; |         PhysicsTaskScheduler* mTaskScheduler; | ||||||
|  |         char mCollidedWith; | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -673,12 +673,13 @@ namespace MWPhysics | ||||||
|             // Slow fall reduces fall speed by a factor of (effect magnitude / 200)
 |             // Slow fall reduces fall speed by a factor of (effect magnitude / 200)
 | ||||||
|             const float slowFall |             const float slowFall | ||||||
|                 = 1.f - std::clamp(effects.getOrDefault(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f, 0.f, 1.f); |                 = 1.f - std::clamp(effects.getOrDefault(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f, 0.f, 1.f); | ||||||
|             const bool godmode = ptr == world->getPlayerConstPtr() && world->getGodModeState(); |             const bool isPlayer = ptr == world->getPlayerConstPtr(); | ||||||
|  |             const bool godmode = isPlayer && world->getGodModeState(); | ||||||
|             const bool inert = stats.isDead() |             const bool inert = stats.isDead() | ||||||
|                 || (!godmode && stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Paralyze).getModifier() > 0); |                 || (!godmode && stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Paralyze).getModifier() > 0); | ||||||
| 
 | 
 | ||||||
|             simulations.emplace_back(ActorSimulation{ |             simulations.emplace_back(ActorSimulation{ | ||||||
|                 physicActor, ActorFrameData{ *physicActor, inert, waterCollision, slowFall, waterlevel } }); |                 physicActor, ActorFrameData{ *physicActor, inert, waterCollision, slowFall, waterlevel, isPlayer } }); | ||||||
| 
 | 
 | ||||||
|             // if the simulation will run, a jump request will be fulfilled. Update mechanics accordingly.
 |             // if the simulation will run, a jump request will be fulfilled. Update mechanics accordingly.
 | ||||||
|             if (willSimulate) |             if (willSimulate) | ||||||
|  | @ -708,6 +709,8 @@ namespace MWPhysics | ||||||
|                 changed = false; |                 changed = false; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |         for (auto& [_, object] : mObjects) | ||||||
|  |             object->resetCollisions(); | ||||||
| 
 | 
 | ||||||
| #ifndef BT_NO_PROFILE | #ifndef BT_NO_PROFILE | ||||||
|         CProfileManager::Reset(); |         CProfileManager::Reset(); | ||||||
|  | @ -782,10 +785,12 @@ namespace MWPhysics | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool PhysicsSystem::isActorCollidingWith(const MWWorld::Ptr& actor, const MWWorld::ConstPtr& object) const |     bool PhysicsSystem::isObjectCollidingWith(const MWWorld::ConstPtr& object, ScriptedCollisionType type) const | ||||||
|     { |     { | ||||||
|         std::vector<MWWorld::Ptr> collisions = getCollisions(object, CollisionType_World, CollisionType_Actor); |         auto found = mObjects.find(object.mRef); | ||||||
|         return (std::find(collisions.begin(), collisions.end(), actor) != collisions.end()); |         if (found != mObjects.end()) | ||||||
|  |             return found->second->collidedWith(type); | ||||||
|  |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void PhysicsSystem::getActorsCollidingWith(const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr>& out) const |     void PhysicsSystem::getActorsCollidingWith(const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr>& out) const | ||||||
|  | @ -890,7 +895,8 @@ namespace MWPhysics | ||||||
|             mDebugDrawer->addCollision(position, normal); |             mDebugDrawer->addCollision(position, normal); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ActorFrameData::ActorFrameData(Actor& actor, bool inert, bool waterCollision, float slowFall, float waterlevel) |     ActorFrameData::ActorFrameData( | ||||||
|  |         Actor& actor, bool inert, bool waterCollision, float slowFall, float waterlevel, bool isPlayer) | ||||||
|         : mPosition() |         : mPosition() | ||||||
|         , mStandingOn(nullptr) |         , mStandingOn(nullptr) | ||||||
|         , mIsOnGround(actor.getOnGround()) |         , mIsOnGround(actor.getOnGround()) | ||||||
|  | @ -917,6 +923,7 @@ namespace MWPhysics | ||||||
|         , mIsAquatic(actor.getPtr().getClass().isPureWaterCreature(actor.getPtr())) |         , mIsAquatic(actor.getPtr().getClass().isPureWaterCreature(actor.getPtr())) | ||||||
|         , mWaterCollision(waterCollision) |         , mWaterCollision(waterCollision) | ||||||
|         , mSkipCollisionDetection(!actor.getCollisionMode()) |         , mSkipCollisionDetection(!actor.getCollisionMode()) | ||||||
|  |         , mIsPlayer(isPlayer) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -56,6 +56,7 @@ namespace MWPhysics | ||||||
|     class Actor; |     class Actor; | ||||||
|     class PhysicsTaskScheduler; |     class PhysicsTaskScheduler; | ||||||
|     class Projectile; |     class Projectile; | ||||||
|  |     enum ScriptedCollisionType : char; | ||||||
| 
 | 
 | ||||||
|     using ActorMap = std::unordered_map<const MWWorld::LiveCellRefBase*, std::shared_ptr<Actor>>; |     using ActorMap = std::unordered_map<const MWWorld::LiveCellRefBase*, std::shared_ptr<Actor>>; | ||||||
| 
 | 
 | ||||||
|  | @ -79,7 +80,7 @@ namespace MWPhysics | ||||||
| 
 | 
 | ||||||
|     struct ActorFrameData |     struct ActorFrameData | ||||||
|     { |     { | ||||||
|         ActorFrameData(Actor& actor, bool inert, bool waterCollision, float slowFall, float waterlevel); |         ActorFrameData(Actor& actor, bool inert, bool waterCollision, float slowFall, float waterlevel, bool isPlayer); | ||||||
|         osg::Vec3f mPosition; |         osg::Vec3f mPosition; | ||||||
|         osg::Vec3f mInertia; |         osg::Vec3f mInertia; | ||||||
|         const btCollisionObject* mStandingOn; |         const btCollisionObject* mStandingOn; | ||||||
|  | @ -102,6 +103,7 @@ namespace MWPhysics | ||||||
|         const bool mIsAquatic; |         const bool mIsAquatic; | ||||||
|         const bool mWaterCollision; |         const bool mWaterCollision; | ||||||
|         const bool mSkipCollisionDetection; |         const bool mSkipCollisionDetection; | ||||||
|  |         const bool mIsPlayer; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     struct ProjectileFrameData |     struct ProjectileFrameData | ||||||
|  | @ -258,9 +260,8 @@ namespace MWPhysics | ||||||
|         /// Get the handle of all actors standing on \a object in this frame.
 |         /// Get the handle of all actors standing on \a object in this frame.
 | ||||||
|         void getActorsStandingOn(const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr>& out) const; |         void getActorsStandingOn(const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr>& out) const; | ||||||
| 
 | 
 | ||||||
|         /// Return true if \a actor has collided with \a object in this frame.
 |         /// Return true if an object of the given type has collided with this object
 | ||||||
|         /// This will detect running into objects, but will not detect climbing stairs, stepping up a small object, etc.
 |         bool isObjectCollidingWith(const MWWorld::ConstPtr& object, ScriptedCollisionType type) const; | ||||||
|         bool isActorCollidingWith(const MWWorld::Ptr& actor, const MWWorld::ConstPtr& object) const; |  | ||||||
| 
 | 
 | ||||||
|         /// Get the handle of all actors colliding with \a object in this frame.
 |         /// Get the handle of all actors colliding with \a object in this frame.
 | ||||||
|         void getActorsCollidingWith(const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr>& out) const; |         void getActorsCollidingWith(const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr>& out) const; | ||||||
|  |  | ||||||
|  | @ -2425,15 +2425,12 @@ namespace MWWorld | ||||||
| 
 | 
 | ||||||
|     bool World::getPlayerCollidingWith(const MWWorld::ConstPtr& object) |     bool World::getPlayerCollidingWith(const MWWorld::ConstPtr& object) | ||||||
|     { |     { | ||||||
|         MWWorld::Ptr player = getPlayerPtr(); |         return mPhysics->isObjectCollidingWith(object, MWPhysics::ScriptedCollisionType_Player); | ||||||
|         return mPhysics->isActorCollidingWith(player, object); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool World::getActorCollidingWith(const MWWorld::ConstPtr& object) |     bool World::getActorCollidingWith(const MWWorld::ConstPtr& object) | ||||||
|     { |     { | ||||||
|         std::vector<MWWorld::Ptr> actors; |         return mPhysics->isObjectCollidingWith(object, MWPhysics::ScriptedCollisionType_Actor); | ||||||
|         mPhysics->getActorsCollidingWith(object, actors); |  | ||||||
|         return !actors.empty(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void World::hurtStandingActors(const ConstPtr& object, float healthPerSecond) |     void World::hurtStandingActors(const ConstPtr& object, float healthPerSecond) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue