Пример #1
0
    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;
        }
    }
Пример #2
0
    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;
        }
    }