void ProjectileManager::moveProjectiles(float duration) { for (std::vector<ProjectileState>::iterator it = mProjectiles.begin(); it != mProjectiles.end();) { // gravity constant - must be way lower than the gravity affecting actors, since we're not // simulating aerodynamics at all it->mVelocity -= osg::Vec3f(0, 0, 627.2f * 0.1f) * duration; osg::Vec3f pos(it->mNode->getPosition()); osg::Vec3f newPos = pos + it->mVelocity * duration; osg::Quat orient; orient.makeRotate(osg::Vec3f(0,1,0), it->mVelocity); it->mNode->setAttitude(orient); it->mNode->setPosition(newPos); update(*it, duration); MWWorld::Ptr caster = it->getCaster(); // Check for impact // TODO: use a proper btRigidBody / btGhostObject? MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(pos, newPos, caster, 0xff, MWPhysics::CollisionType_Projectile); bool underwater = MWBase::Environment::get().getWorld()->isUnderwater(MWMechanics::getPlayer().getCell(), newPos); if (result.mHit || underwater) { if (result.mHit) { MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mId); // Try to get a Ptr to the bow that was used. It might no longer exist. MWWorld::Ptr bow = projectileRef.getPtr(); if (!caster.isEmpty()) { MWWorld::InventoryStore& inv = caster.getClass().getInventoryStore(caster); MWWorld::ContainerStoreIterator invIt = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); if (invIt != inv.end() && Misc::StringUtils::ciEqual(invIt->getCellRef().getRefId(), it->mBowId)) bow = *invIt; } if (caster.isEmpty()) caster = result.mHitObject; MWMechanics::projectileHit(caster, result.mHitObject, bow, projectileRef.getPtr(), result.mHitPos, it->mAttackStrength); } if (underwater) mRendering->emitWaterRipple(newPos); mParent->removeChild(it->mNode); it = mProjectiles.erase(it); continue; } ++it; } }
void ProjectileManager::moveProjectiles(float duration) { for (std::vector<ProjectileState>::iterator it = mProjectiles.begin(); it != mProjectiles.end();) { // gravity constant - must be way lower than the gravity affecting actors, since we're not // simulating aerodynamics at all it->mVelocity -= Ogre::Vector3(0, 0, 627.2f * 0.1f) * duration; Ogre::Vector3 pos(it->mNode->getPosition()); Ogre::Vector3 newPos = pos + it->mVelocity * duration; Ogre::Quaternion orient = Ogre::Vector3::UNIT_Y.getRotationTo(it->mVelocity); it->mNode->setOrientation(orient); it->mNode->setPosition(newPos); update(it->mObject, duration); // Check for impact // TODO: use a proper btRigidBody / btGhostObject? btVector3 from(pos.x, pos.y, pos.z); btVector3 to(newPos.x, newPos.y, newPos.z); std::vector<std::pair<float, std::string> > collisions = mPhysEngine.rayTest2(from, to, OEngine::Physic::CollisionType_Projectile); bool hit=false; for (std::vector<std::pair<float, std::string> >::iterator cIt = collisions.begin(); cIt != collisions.end() && !hit; ++cIt) { MWWorld::Ptr obstacle = MWBase::Environment::get().getWorld()->searchPtrViaHandle(cIt->second); MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->mActorId); // Arrow intersects with player immediately after shooting :/ if (obstacle == caster) continue; MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mId); // Try to get a Ptr to the bow that was used. It might no longer exist. MWWorld::Ptr bow = projectileRef.getPtr(); if (!caster.isEmpty()) { MWWorld::InventoryStore& inv = caster.getClass().getInventoryStore(caster); MWWorld::ContainerStoreIterator invIt = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); if (invIt != inv.end() && Misc::StringUtils::ciEqual(invIt->getCellRef().getRefId(), it->mBowId)) bow = *invIt; } if (caster.isEmpty()) caster = obstacle; MWMechanics::projectileHit(caster, obstacle, bow, projectileRef.getPtr(), pos + (newPos - pos) * cIt->first); hit = true; } if (hit) { mSceneMgr->destroySceneNode(it->mNode); it = mProjectiles.erase(it); continue; } else ++it; } }