mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 18:19:55 +00:00
Merge branch 'vanilla_projectile_47' into 'openmw-47'
#6233 / !1188 for 0.47 (Vanilla arrow behaviour) See merge request OpenMW/openmw!1238
This commit is contained in:
commit
81748f8e3d
7 changed files with 29 additions and 44 deletions
|
@ -620,7 +620,7 @@ namespace MWPhysics
|
|||
|
||||
mTaskScheduler->convexSweepTest(projectile->getConvexShape(), from_, to_, resultCallback);
|
||||
|
||||
const auto newpos = projectile->isActive() ? position : Misc::Convert::toOsg(resultCallback.m_hitPointWorld);
|
||||
const auto newpos = projectile->isActive() ? position : Misc::Convert::toOsg(projectile->getHitPosition());
|
||||
projectile->setPosition(newpos);
|
||||
mTaskScheduler->updateSingleAabb(foundProjectile->second);
|
||||
}
|
||||
|
@ -693,7 +693,7 @@ namespace MWPhysics
|
|||
mActors.emplace(ptr, std::move(actor));
|
||||
}
|
||||
|
||||
int PhysicsSystem::addProjectile (const MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius, bool canTraverseWater)
|
||||
int PhysicsSystem::addProjectile (const MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius)
|
||||
{
|
||||
osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance = mShapeManager->getInstance(mesh);
|
||||
assert(shapeInstance);
|
||||
|
@ -701,7 +701,7 @@ namespace MWPhysics
|
|||
|
||||
mProjectileId++;
|
||||
|
||||
auto projectile = std::make_shared<Projectile>(caster, position, radius, canTraverseWater, mTaskScheduler.get(), this);
|
||||
auto projectile = std::make_shared<Projectile>(caster, position, radius, mTaskScheduler.get(), this);
|
||||
mProjectiles.emplace(mProjectileId, std::move(projectile));
|
||||
|
||||
return mProjectileId;
|
||||
|
|
|
@ -125,7 +125,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 MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius, bool canTraverseWater);
|
||||
int addProjectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, const std::string& mesh, bool computeRadius);
|
||||
void setCaster(int projectileId, const MWWorld::Ptr& caster);
|
||||
void updateProjectile(const int projectileId, const osg::Vec3f &position) const;
|
||||
void removeProjectile(const int projectileId);
|
||||
|
|
|
@ -13,12 +13,10 @@
|
|||
|
||||
namespace MWPhysics
|
||||
{
|
||||
Projectile::Projectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, float radius, bool canCrossWaterSurface, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem)
|
||||
: mCanCrossWaterSurface(canCrossWaterSurface)
|
||||
, mCrossedWaterSurface(false)
|
||||
Projectile::Projectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, float radius, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem)
|
||||
: mHitWater(false)
|
||||
, mActive(true)
|
||||
, mCaster(caster)
|
||||
, mWaterHitPosition(std::nullopt)
|
||||
, mPhysics(physicssystem)
|
||||
, mTaskScheduler(scheduler)
|
||||
{
|
||||
|
@ -72,11 +70,6 @@ osg::Vec3f Projectile::getPosition() const
|
|||
return mPosition;
|
||||
}
|
||||
|
||||
bool Projectile::canTraverseWater() const
|
||||
{
|
||||
return mCanCrossWaterSurface;
|
||||
}
|
||||
|
||||
void Projectile::hit(MWWorld::Ptr target, btVector3 pos, btVector3 normal)
|
||||
{
|
||||
if (!mActive.load(std::memory_order_acquire))
|
||||
|
@ -127,17 +120,4 @@ bool Projectile::isValidTarget(const MWWorld::Ptr& target) const
|
|||
return validTarget;
|
||||
}
|
||||
|
||||
std::optional<btVector3> Projectile::getWaterHitPosition()
|
||||
{
|
||||
return std::exchange(mWaterHitPosition, std::nullopt);
|
||||
}
|
||||
|
||||
void Projectile::setWaterHitPosition(btVector3 pos)
|
||||
{
|
||||
if (mCrossedWaterSurface)
|
||||
return;
|
||||
mCrossedWaterSurface = true;
|
||||
mWaterHitPosition = pos;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
|
||||
#include <LinearMath/btVector3.h>
|
||||
|
||||
|
@ -32,7 +31,7 @@ namespace MWPhysics
|
|||
class Projectile final : public PtrHolder
|
||||
{
|
||||
public:
|
||||
Projectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, float radius, bool canCrossWaterSurface, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem);
|
||||
Projectile(const MWWorld::Ptr& caster, const osg::Vec3f& position, float radius, PhysicsTaskScheduler* scheduler, PhysicsSystem* physicssystem);
|
||||
~Projectile() override;
|
||||
|
||||
btConvexShape* getConvexShape() const { return mConvexShape; }
|
||||
|
@ -61,15 +60,25 @@ namespace MWPhysics
|
|||
MWWorld::Ptr getCaster() const;
|
||||
void setCaster(MWWorld::Ptr caster);
|
||||
|
||||
bool canTraverseWater() const;
|
||||
void setHitWater()
|
||||
{
|
||||
mHitWater = true;
|
||||
}
|
||||
|
||||
bool getHitWater() const
|
||||
{
|
||||
return mHitWater;
|
||||
}
|
||||
|
||||
void hit(MWWorld::Ptr target, btVector3 pos, btVector3 normal);
|
||||
|
||||
void setValidTargets(const std::vector<MWWorld::Ptr>& targets);
|
||||
bool isValidTarget(const MWWorld::Ptr& target) const;
|
||||
|
||||
std::optional<btVector3> getWaterHitPosition();
|
||||
void setWaterHitPosition(btVector3 pos);
|
||||
btVector3 getHitPosition() const
|
||||
{
|
||||
return mHitPosition;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
@ -78,12 +87,10 @@ namespace MWPhysics
|
|||
|
||||
std::unique_ptr<btCollisionObject> mCollisionObject;
|
||||
bool mTransformUpdatePending;
|
||||
bool mCanCrossWaterSurface;
|
||||
bool mCrossedWaterSurface;
|
||||
bool mHitWater;
|
||||
std::atomic<bool> mActive;
|
||||
MWWorld::Ptr mCaster;
|
||||
MWWorld::Ptr mHitTarget;
|
||||
std::optional<btVector3> mWaterHitPosition;
|
||||
osg::Vec3f mPosition;
|
||||
btVector3 mHitPosition;
|
||||
btVector3 mHitNormal;
|
||||
|
|
|
@ -47,9 +47,7 @@ namespace MWPhysics
|
|||
}
|
||||
case CollisionType_Water:
|
||||
{
|
||||
mProjectile->setWaterHitPosition(m_hitPointWorld);
|
||||
if (mProjectile->canTraverseWater())
|
||||
return 1.f;
|
||||
mProjectile->setHitWater();
|
||||
mProjectile->hit(MWWorld::Ptr(), m_hitPointWorld, m_hitNormalWorld);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -320,7 +320,7 @@ namespace MWWorld
|
|||
// in case there are multiple effects, the model is a dummy without geometry. Use the second effect for physics shape
|
||||
if (state.mIdMagic.size() > 1)
|
||||
model = "meshes\\" + MWBase::Environment::get().getWorld()->getStore().get<ESM::Weapon>().find(state.mIdMagic.at(1))->mModel;
|
||||
state.mProjectileId = mPhysics->addProjectile(caster, pos, model, true, false);
|
||||
state.mProjectileId = mPhysics->addProjectile(caster, pos, model, true);
|
||||
state.mToDelete = false;
|
||||
mMagicBolts.push_back(state);
|
||||
}
|
||||
|
@ -345,7 +345,7 @@ namespace MWWorld
|
|||
if (!ptr.getClass().getEnchantment(ptr).empty())
|
||||
SceneUtil::addEnchantedGlow(state.mNode, mResourceSystem, ptr.getClass().getEnchantmentColor(ptr));
|
||||
|
||||
state.mProjectileId = mPhysics->addProjectile(actor, pos, model, false, true);
|
||||
state.mProjectileId = mPhysics->addProjectile(actor, pos, model, false);
|
||||
state.mToDelete = false;
|
||||
mProjectiles.push_back(state);
|
||||
}
|
||||
|
@ -496,9 +496,6 @@ namespace MWWorld
|
|||
|
||||
auto* projectile = mPhysics->getProjectile(projectileState.mProjectileId);
|
||||
|
||||
if (const auto hitWaterPos = projectile->getWaterHitPosition())
|
||||
mRendering->emitWaterRipple(Misc::Convert::toOsg(*hitWaterPos));
|
||||
|
||||
const auto pos = projectile->getPosition();
|
||||
projectileState.mNode->setPosition(pos);
|
||||
|
||||
|
@ -522,6 +519,8 @@ namespace MWWorld
|
|||
if (invIt != inv.end() && Misc::StringUtils::ciEqual(invIt->getCellRef().getRefId(), projectileState.mBowId))
|
||||
bow = *invIt;
|
||||
}
|
||||
if (projectile->getHitWater())
|
||||
mRendering->emitWaterRipple(pos);
|
||||
|
||||
MWMechanics::projectileHit(caster, target, bow, projectileRef.getPtr(), pos, projectileState.mAttackStrength);
|
||||
cleanupProjectile(projectileState);
|
||||
|
@ -654,7 +653,7 @@ namespace MWWorld
|
|||
int weaponType = ptr.get<ESM::Weapon>()->mBase->mData.mType;
|
||||
state.mThrown = MWMechanics::getWeaponType(weaponType)->mWeaponClass == ESM::WeaponType::Thrown;
|
||||
|
||||
state.mProjectileId = mPhysics->addProjectile(state.getCaster(), osg::Vec3f(esm.mPosition), model, false, true);
|
||||
state.mProjectileId = mPhysics->addProjectile(state.getCaster(), osg::Vec3f(esm.mPosition), model, false);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
|
@ -707,7 +706,7 @@ namespace MWWorld
|
|||
|
||||
osg::Vec4 lightDiffuseColor = getMagicBoltLightDiffuseColor(state.mEffects);
|
||||
createModel(state, model, osg::Vec3f(esm.mPosition), osg::Quat(esm.mOrientation), true, true, lightDiffuseColor, texture);
|
||||
state.mProjectileId = mPhysics->addProjectile(state.getCaster(), osg::Vec3f(esm.mPosition), model, true, false);
|
||||
state.mProjectileId = mPhysics->addProjectile(state.getCaster(), osg::Vec3f(esm.mPosition), model, true);
|
||||
|
||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||
for (const std::string &soundid : state.mSoundIds)
|
||||
|
|
|
@ -3165,6 +3165,7 @@ namespace MWWorld
|
|||
bool underwater = MWBase::Environment::get().getWorld()->isUnderwater(MWMechanics::getPlayer().getCell(), worldPos);
|
||||
if (underwater)
|
||||
{
|
||||
MWMechanics::projectileHit(actor, Ptr(), bow, projectile, worldPos, attackStrength);
|
||||
mRendering->emitWaterRipple(worldPos);
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue