|
|
|
@ -2892,10 +2892,34 @@ namespace MWWorld
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
|
|
|
|
|
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength)
|
|
|
|
|
void World::launchProjectile (MWWorld::Ptr& actor, MWWorld::Ptr& projectile,
|
|
|
|
|
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr& bow, float speed, float attackStrength)
|
|
|
|
|
{
|
|
|
|
|
mProjectileManager->launchProjectile(actor, projectile, worldPos, orient, bow, speed, attackStrength);
|
|
|
|
|
// An initial position of projectile can be outside shooter's collision box, so any object between shooter and launch position will be ignored.
|
|
|
|
|
// To avoid this issue, we should check for impact immediately before launch the projectile.
|
|
|
|
|
// So we cast a 1-yard-length ray from shooter to launch position and check if there are collisions in this area.
|
|
|
|
|
// TODO: as a better solutuon we should handle projectiles during physics update, not during world update.
|
|
|
|
|
const osg::Vec3f sourcePos = worldPos + orient * osg::Vec3f(0,-1,0) * 64.f;
|
|
|
|
|
|
|
|
|
|
// Early out if the launch position is underwater
|
|
|
|
|
bool underwater = MWBase::Environment::get().getWorld()->isUnderwater(MWMechanics::getPlayer().getCell(), worldPos);
|
|
|
|
|
if (underwater)
|
|
|
|
|
{
|
|
|
|
|
mRendering->emitWaterRipple(worldPos);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For AI actors, get combat targets to use in the ray cast. Only those targets will return a positive hit result.
|
|
|
|
|
std::vector<MWWorld::Ptr> targetActors;
|
|
|
|
|
if (!actor.isEmpty() && actor.getClass().isActor() && actor != MWMechanics::getPlayer())
|
|
|
|
|
actor.getClass().getCreatureStats(actor).getAiSequence().getCombatTargets(targetActors);
|
|
|
|
|
|
|
|
|
|
// Check for impact, if yes, handle hit, if not, launch projectile
|
|
|
|
|
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(sourcePos, worldPos, actor, targetActors, 0xff, MWPhysics::CollisionType_Projectile);
|
|
|
|
|
if (result.mHit)
|
|
|
|
|
MWMechanics::projectileHit(actor, result.mHitObject, bow, projectile, result.mHitPos, attackStrength);
|
|
|
|
|
else
|
|
|
|
|
mProjectileManager->launchProjectile(actor, projectile, worldPos, orient, bow, speed, attackStrength);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void World::launchMagicBolt (const std::string &spellId, const MWWorld::Ptr& caster, const osg::Vec3f& fallbackDirection)
|
|
|
|
|