mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-28 22:13:21 +00:00
Base GetColliding script functions on collisions detected by the movement solver
This commit is contained in:
parent
6b35ee68e1
commit
467220e6d7
@ -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…
x
Reference in New Issue
Block a user