mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-29 18:32:36 +00:00
Merge branch 'bumpbump' into 'master'
Base GetColliding script functions on collisions detected by the movement solver Closes #7053 See merge request OpenMW/openmw!3794
This commit is contained in:
commit
bd84200d4e
@ -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 #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 #7053: Running into objects doesn't trigger GetCollidingPC
|
||||
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 #7077: OpenMW fails to load certain particle effects in .osgt format
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "collisiontype.hpp"
|
||||
#include "constants.hpp"
|
||||
#include "contacttestwrapper.h"
|
||||
#include "object.hpp"
|
||||
#include "physicssystem.hpp"
|
||||
#include "projectile.hpp"
|
||||
#include "projectileconvexcallback.hpp"
|
||||
@ -243,11 +244,20 @@ namespace MWPhysics
|
||||
float hitHeight = tracer.mHitPoint.z() - tracer.mEndPos.z() + actor.mHalfExtentsZ;
|
||||
osg::Vec3f oldPosition = newPosition;
|
||||
bool usedStepLogic = false;
|
||||
if (hitHeight < Constants::sStepSizeUp && !isActor(tracer.mHitObject))
|
||||
if (!isActor(tracer.mHitObject))
|
||||
{
|
||||
// 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);
|
||||
if (hitHeight < Constants::sStepSizeUp)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
|
@ -23,6 +23,7 @@ namespace MWPhysics
|
||||
, mPosition(ptr.getRefData().getPosition().asVec3())
|
||||
, mRotation(rotation)
|
||||
, mTaskScheduler(scheduler)
|
||||
, mCollidedWith(ScriptedCollisionType_None)
|
||||
{
|
||||
mCollisionObject = BulletHelpers::makeCollisionObject(mShapeInstance->mCollisionShape.get(),
|
||||
Misc::Convert::toBullet(mPosition), Misc::Convert::toBullet(rotation));
|
||||
@ -166,4 +167,20 @@ namespace MWPhysics
|
||||
}
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
@ -38,6 +46,9 @@ namespace MWPhysics
|
||||
/// @brief update object shape
|
||||
/// @return true if shape changed
|
||||
bool animateCollisionShapes();
|
||||
bool collidedWith(ScriptedCollisionType type) const;
|
||||
void addCollision(ScriptedCollisionType type);
|
||||
void resetCollisions();
|
||||
|
||||
private:
|
||||
osg::ref_ptr<Resource::BulletShapeInstance> mShapeInstance;
|
||||
@ -50,6 +61,7 @@ namespace MWPhysics
|
||||
bool mTransformUpdatePending = false;
|
||||
mutable std::mutex mPositionMutex;
|
||||
PhysicsTaskScheduler* mTaskScheduler;
|
||||
char mCollidedWith;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -673,12 +673,13 @@ namespace MWPhysics
|
||||
// Slow fall reduces fall speed by a factor of (effect magnitude / 200)
|
||||
const float slowFall
|
||||
= 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()
|
||||
|| (!godmode && stats.getMagicEffects().getOrDefault(ESM::MagicEffect::Paralyze).getModifier() > 0);
|
||||
|
||||
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 (willSimulate)
|
||||
@ -708,6 +709,8 @@ namespace MWPhysics
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
for (auto& [_, object] : mObjects)
|
||||
object->resetCollisions();
|
||||
|
||||
#ifndef BT_NO_PROFILE
|
||||
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);
|
||||
return (std::find(collisions.begin(), collisions.end(), actor) != collisions.end());
|
||||
auto found = mObjects.find(object.mRef);
|
||||
if (found != mObjects.end())
|
||||
return found->second->collidedWith(type);
|
||||
return false;
|
||||
}
|
||||
|
||||
void PhysicsSystem::getActorsCollidingWith(const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr>& out) const
|
||||
@ -890,7 +895,8 @@ namespace MWPhysics
|
||||
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()
|
||||
, mStandingOn(nullptr)
|
||||
, mIsOnGround(actor.getOnGround())
|
||||
@ -917,6 +923,7 @@ namespace MWPhysics
|
||||
, mIsAquatic(actor.getPtr().getClass().isPureWaterCreature(actor.getPtr()))
|
||||
, mWaterCollision(waterCollision)
|
||||
, mSkipCollisionDetection(!actor.getCollisionMode())
|
||||
, mIsPlayer(isPlayer)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,7 @@ namespace MWPhysics
|
||||
class Actor;
|
||||
class PhysicsTaskScheduler;
|
||||
class Projectile;
|
||||
enum ScriptedCollisionType : char;
|
||||
|
||||
using ActorMap = std::unordered_map<const MWWorld::LiveCellRefBase*, std::shared_ptr<Actor>>;
|
||||
|
||||
@ -79,7 +80,7 @@ namespace MWPhysics
|
||||
|
||||
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 mInertia;
|
||||
const btCollisionObject* mStandingOn;
|
||||
@ -102,6 +103,7 @@ namespace MWPhysics
|
||||
const bool mIsAquatic;
|
||||
const bool mWaterCollision;
|
||||
const bool mSkipCollisionDetection;
|
||||
const bool mIsPlayer;
|
||||
};
|
||||
|
||||
struct ProjectileFrameData
|
||||
@ -258,9 +260,8 @@ namespace MWPhysics
|
||||
/// 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;
|
||||
|
||||
/// Return true if \a actor has collided with \a object in this frame.
|
||||
/// This will detect running into objects, but will not detect climbing stairs, stepping up a small object, etc.
|
||||
bool isActorCollidingWith(const MWWorld::Ptr& actor, const MWWorld::ConstPtr& object) const;
|
||||
/// Return true if an object of the given type has collided with this object
|
||||
bool isObjectCollidingWith(const MWWorld::ConstPtr& object, ScriptedCollisionType type) const;
|
||||
|
||||
/// 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;
|
||||
|
@ -2429,15 +2429,12 @@ namespace MWWorld
|
||||
|
||||
bool World::getPlayerCollidingWith(const MWWorld::ConstPtr& object)
|
||||
{
|
||||
MWWorld::Ptr player = getPlayerPtr();
|
||||
return mPhysics->isActorCollidingWith(player, object);
|
||||
return mPhysics->isObjectCollidingWith(object, MWPhysics::ScriptedCollisionType_Player);
|
||||
}
|
||||
|
||||
bool World::getActorCollidingWith(const MWWorld::ConstPtr& object)
|
||||
{
|
||||
std::vector<MWWorld::Ptr> actors;
|
||||
mPhysics->getActorsCollidingWith(object, actors);
|
||||
return !actors.empty();
|
||||
return mPhysics->isObjectCollidingWith(object, MWPhysics::ScriptedCollisionType_Actor);
|
||||
}
|
||||
|
||||
void World::hurtStandingActors(const ConstPtr& object, float healthPerSecond)
|
||||
|
Loading…
x
Reference in New Issue
Block a user