mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-15 19:19:55 +00:00
b39437dfb6
When an NPC fire a projectile, it should affect only its targeted actor. To this end, after a hit is detected the target is checked against the list of AI targets and reactivated if necessary. Problem occurs when the hit occurs as a result of a friendly actor going into the projectile (detected in ClosestNotMeConvexResultCallback): while the projectile is inside the friend's collision box, it is deactivated, just to be immediately reactivated. Effectively, the projectile does nothing until the actor moves out. Add a check inside the ClosestNotMeConvexResultCallback before declaring a hit. Since the necessary data is not safely accessible from the async thread, maintain a copy inside the Projectile class.
112 lines
2.4 KiB
C++
112 lines
2.4 KiB
C++
#ifndef OPENMW_MWPHYSICS_PROJECTILE_H
|
|
#define OPENMW_MWPHYSICS_PROJECTILE_H
|
|
|
|
#include <atomic>
|
|
#include <memory>
|
|
#include <mutex>
|
|
|
|
#include "components/misc/convert.hpp"
|
|
|
|
#include "ptrholder.hpp"
|
|
|
|
class btCollisionObject;
|
|
class btCollisionShape;
|
|
class btConvexShape;
|
|
class btVector3;
|
|
|
|
namespace osg
|
|
{
|
|
class Vec3f;
|
|
}
|
|
|
|
namespace Resource
|
|
{
|
|
class BulletShape;
|
|
}
|
|
|
|
namespace MWPhysics
|
|
{
|
|
class PhysicsTaskScheduler;
|
|
class PhysicsSystem;
|
|
|
|
class Projectile final : public PtrHolder
|
|
{
|
|
public:
|
|
Projectile(const int projectileId, const MWWorld::Ptr& caster, const osg::Vec3f& position, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem);
|
|
~Projectile() override;
|
|
|
|
btConvexShape* getConvexShape() const { return mConvexShape; }
|
|
|
|
void commitPositionChange();
|
|
|
|
void setPosition(const osg::Vec3f& position);
|
|
|
|
btCollisionObject* getCollisionObject() const
|
|
{
|
|
return mCollisionObject.get();
|
|
}
|
|
|
|
int getProjectileId() const
|
|
{
|
|
return mProjectileId;
|
|
}
|
|
|
|
bool isActive() const
|
|
{
|
|
return mActive.load(std::memory_order_acquire);
|
|
}
|
|
|
|
MWWorld::Ptr getTarget() const
|
|
{
|
|
assert(!mActive);
|
|
return mHitTarget;
|
|
}
|
|
|
|
MWWorld::Ptr getCaster() const;
|
|
void setCaster(MWWorld::Ptr caster);
|
|
|
|
osg::Vec3f getHitPos() const
|
|
{
|
|
assert(!mActive);
|
|
return Misc::Convert::toOsg(mHitPosition);
|
|
}
|
|
|
|
void hit(MWWorld::Ptr target, btVector3 pos, btVector3 normal);
|
|
void activate();
|
|
|
|
void setValidTargets(const std::vector<MWWorld::Ptr>& targets);
|
|
bool isValidTarget(const MWWorld::Ptr& target) const;
|
|
|
|
private:
|
|
|
|
std::unique_ptr<btCollisionShape> mShape;
|
|
btConvexShape* mConvexShape;
|
|
|
|
std::unique_ptr<btCollisionObject> mCollisionObject;
|
|
btTransform mLocalTransform;
|
|
bool mTransformUpdatePending;
|
|
std::atomic<bool> mActive;
|
|
MWWorld::Ptr mCaster;
|
|
MWWorld::Ptr mHitTarget;
|
|
btVector3 mHitPosition;
|
|
btVector3 mHitNormal;
|
|
|
|
std::vector<MWWorld::Ptr> mValidTargets;
|
|
|
|
mutable std::mutex mMutex;
|
|
|
|
osg::Vec3f mPosition;
|
|
|
|
PhysicsSystem *mPhysics;
|
|
PhysicsTaskScheduler *mTaskScheduler;
|
|
|
|
Projectile(const Projectile&);
|
|
Projectile& operator=(const Projectile&);
|
|
|
|
int mProjectileId;
|
|
};
|
|
|
|
}
|
|
|
|
|
|
#endif
|