Esempio n. 1
0
/** Squash karts or items that are around the end position (determined using
 *  a joint) of the swatter.
 */
void Swatter::squashThingsAround()
{
    const KartProperties*  kp           = m_kart->getKartProperties();
    // Square of the minimum distance
    float                  min_dist2    = kp->getSwatterDistance2();
    const World*           world        = World::getWorld();

    // Get the node corresponding to the joint at the center of the swatter
    // (by swatter, I mean the thing hold in the hand, not the whole thing)
    scene::ISceneNode* swatter_node = m_scene_node->getJointNode("Swatter");
    assert(swatter_node);
    Vec3 swatter_pos = swatter_node->getAbsolutePosition();

    m_swat_sound->setPosition(swatter_pos);
    m_swat_sound->play();

    // Squash karts around
    for(unsigned int i=0; i<world->getNumKarts(); i++)
    {
        AbstractKart *kart = world->getKart(i);
        // TODO: isSwatterReady()
        if(kart->isEliminated() || kart==m_kart)
            continue;
        // don't swat an already hurt kart
        if (kart->isInvulnerable() || kart->isSquashed())
            continue;

        float dist2 = (kart->getXYZ()-swatter_pos).length2();

        if(dist2 >= min_dist2) continue;   // too far away, ignore this kart

        kart->setSquash(kp->getSquashDuration() * kart->getPlayerDifficulty()->getSquashDuration(),
            kp->getSquashSlowdown() * kart->getPlayerDifficulty()->getSquashSlowdown());

        if (kart->getAttachment()->getType()==Attachment::ATTACH_BOMB)
        {   // make bomb explode
            kart->getAttachment()->update(10000);
            HitEffect *he = new Explosion(m_kart->getXYZ(),  "explosion", "explosion.xml");
            if(m_kart->getController()->isPlayerController())
                he->setPlayerKartHit();
            projectile_manager->addHitEffect(he);
            ExplosionAnimation::create(kart);
        }   // if kart has bomb attached
        World::getWorld()->kartHit(kart->getWorldKartId());
    }   // for i < num_kartrs

    // TODO: squash items
}   // squashThingsAround
Esempio n. 2
0
//-----------------------------------------------------------------------------
void Attachment::update(float dt)
{
    if(m_type==ATTACH_NOTHING) return;
    m_time_left -=dt;
    
    
    bool is_shield = (m_type == ATTACH_BUBBLEGUM_SHIELD|| m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD);
    float m_wanted_node_scale = is_shield ? std::max(1.0f, m_kart->getHighestPoint()*1.1f) : 1.0f;
    
    if (m_node_scale < m_wanted_node_scale)
    {
        m_node_scale += dt*1.5f;
        if (m_node_scale > m_wanted_node_scale) m_node_scale = m_wanted_node_scale;
        m_node->setScale(core::vector3df(m_node_scale,m_node_scale,m_node_scale));
    }

    if(m_plugin)
    {
        bool discard = m_plugin->updateAndTestFinished(dt);
        if(discard)
        {
            clear();  // also removes the plugin
            return;
        }
    }

    switch (m_type)
    {
    case ATTACH_PARACHUTE:
        {
        // Partly handled in Kart::updatePhysics
        // Otherwise: disable if a certain percantage of
        // initial speed was lost
        // This percentage is based on the ratio of
        // initial_speed / initial_max_speed

        float f = m_initial_speed / stk_config->m_parachute_max_speed;
        if (f > 1.0f) f = 1.0f;   // cap fraction
        if (m_kart->getSpeed() <= m_initial_speed *
                                 (stk_config->m_parachute_lbound_fraction +
                                  f * (  stk_config->m_parachute_ubound_fraction
                                       - stk_config->m_parachute_lbound_fraction)))
        {
            m_time_left = -1;
        }
        }
        break;
    case ATTACH_ANVIL:     // handled in Kart::updatePhysics
    case ATTACH_NOTHING:   // Nothing to do, but complete all cases for switch
    case ATTACH_MAX:
        break;
    case ATTACH_SWATTER:
    case ATTACH_NOLOKS_SWATTER:
        // Everything is done in the plugin.
        break;
    case ATTACH_BOMB:

        if (m_bomb_sound) m_bomb_sound->position(m_kart->getXYZ());

        // Mesh animation frames are 1 to 61 frames (60 steps)
        // The idea is change second by second, counterclockwise 60 to 0 secs
        // If longer times needed, it should be a surprise "oh! bomb activated!"
        if(m_time_left <= (m_node->getEndFrame() - m_node->getStartFrame()-1))
        {
            m_node->setCurrentFrame(m_node->getEndFrame()
                                    - m_node->getStartFrame()-1-m_time_left);
        }
        if(m_time_left<=0.0)
        {
            HitEffect *he = new Explosion(m_kart->getXYZ(), "explosion", "explosion_bomb.xml");
            if(m_kart->getController()->isPlayerController())
                he->setPlayerKartHit();
            projectile_manager->addHitEffect(he);
            ExplosionAnimation::create(m_kart);

            if (m_bomb_sound)
            {
                m_bomb_sound->stop();
                sfx_manager->deleteSFX(m_bomb_sound);
                m_bomb_sound = NULL;
            }
        }
        break;
    case ATTACH_TINYTUX:
        // Nothing to do for tinytux, this is all handled in EmergencyAnimation
        break;
    case ATTACH_BUBBLEGUM_SHIELD:
    case ATTACH_NOLOK_BUBBLEGUM_SHIELD:
        if (m_time_left < 0)
        {
            m_time_left = 0.0f;
            if (m_bubble_explode_sound) sfx_manager->deleteSFX(m_bubble_explode_sound);
            m_bubble_explode_sound = sfx_manager->createSoundSource("bubblegum_explode");
            m_bubble_explode_sound->position(m_kart->getXYZ());
            m_bubble_explode_sound->play();
            
            // drop a small bubble gum
            Vec3 hit_point;
            Vec3 normal;
            const Material* material_hit;
            Vec3 pos = m_kart->getXYZ();
            Vec3 to=pos+Vec3(0, -10000, 0);
            World* world = World::getWorld();
            world->getTrack()->getTriangleMesh().castRay(pos, to, &hit_point,
                                                         &material_hit, &normal);
            // This can happen if the kart is 'over nothing' when dropping
            // the bubble gum
            if(material_hit)
            {
                normal.normalize();

                pos.setY(hit_point.getY()-0.05f);
                
                ItemManager::get()->newItem(Item::ITEM_BUBBLEGUM, pos, normal, m_kart);
            }
        }
        break;
    }   // switch

    // Detach attachment if its time is up.
    if ( m_time_left <= 0.0f)
        clear();
}   // update
Esempio n. 3
0
/** Randomly selects the new attachment. For a server process, the
*   attachment can be passed into this function.
*  \param item The item that was collected.
*  \param new_attachment Optional: only used on the clients, it
*                        specifies the new attachment to use
*/
void Attachment::hitBanana(Item *item, int new_attachment)
{
    const StateManager::ActivePlayer *const ap = m_kart->getController()
                                                       ->getPlayer();
    if(ap && ap->getConstProfile()==PlayerManager::getCurrentPlayer())
        PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_BANANA,
                                           "banana",1                      );
    //Bubble gum shield effect:
    if(m_type == ATTACH_BUBBLEGUM_SHIELD ||
       m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD)
    {
        m_time_left = 0.0f;
        return;
    }

    float leftover_time   = 0.0f;

    bool add_a_new_item = true;

    if (dynamic_cast<ThreeStrikesBattle*>(World::getWorld()) != NULL)
    {
        World::getWorld()->kartHit(m_kart->getWorldKartId());
        ExplosionAnimation::create(m_kart);
        return;
    }

    switch(getType())   // If there already is an attachment, make it worse :)
    {
    case ATTACH_BOMB:
        {
        add_a_new_item = false;
        HitEffect *he = new Explosion(m_kart->getXYZ(), "explosion", "explosion_bomb.xml");
        if(m_kart->getController()->isPlayerController())
            he->setPlayerKartHit();
        projectile_manager->addHitEffect(he);
        ExplosionAnimation::create(m_kart);
        clear();
        if(new_attachment==-1)
            new_attachment = m_random.get(3);
        // Disable the banana on which the kart just is for more than the
        // default time. This is necessary to avoid that a kart lands on the
        // same banana again once the explosion animation is finished, giving
        // the kart the same penalty twice.
        float f = std::max(item->getDisableTime(),
                         m_kart->getKartProperties()->getExplosionTime()+2.0f);
        item->setDisableTime(f);
        break;
        }
    case ATTACH_ANVIL:
        // if the kart already has an anvil, attach a new anvil,
        // and increase the overall time
        new_attachment = 2;
        leftover_time  = m_time_left;
        break;
    case ATTACH_PARACHUTE:
        new_attachment = 2;
        leftover_time  = m_time_left;
        break;
    default:
        // There is no attachment currently, but there will be one
        // so play the character sound ("Uh-Oh")
        m_kart->playCustomSFX(SFXManager::CUSTOM_ATTACH);

        if(new_attachment==-1)
            new_attachment = m_random.get(3);
    }   // switch

    if (add_a_new_item)
    {
        switch (new_attachment)
        {
        case 0:
            set( ATTACH_PARACHUTE,stk_config->m_parachute_time+leftover_time);
            m_initial_speed = m_kart->getSpeed();

            // if going very slowly or backwards,
            // braking won't remove parachute
            if(m_initial_speed <= 1.5) m_initial_speed = 1.5;
            break ;
        case 1:
            set( ATTACH_BOMB, stk_config->m_bomb_time+leftover_time);

            // if ( m_kart == m_kart[0] )
            //   sound -> playSfx ( SOUND_SHOOMF ) ;
            break ;
        case 2:
            set( ATTACH_ANVIL, stk_config->m_anvil_time+leftover_time);
            // if ( m_kart == m_kart[0] )
            //   sound -> playSfx ( SOUND_SHOOMF ) ;
            // Reduce speed once (see description above), all other changes are
            // handled in Kart::updatePhysics
            m_kart->adjustSpeed(stk_config->m_anvil_speed_factor);
            m_kart->updateWeight();
            break ;
        }   // switch
    }
}   // hitBanana
Esempio n. 4
0
//-----------------------------------------------------------------------------
void Attachment::update(float dt)
{
    if(m_type==ATTACH_NOTHING) return;
    m_time_left -=dt;

    if(m_plugin)
    {
        bool discard = m_plugin->updateAndTestFinished(dt);
        if(discard)
        {
            clear();  // also removes the plugin
            return;
        }
    }

    switch (m_type)
    {
    case ATTACH_PARACHUTE:
        // Partly handled in Kart::updatePhysics
        // Otherwise: disable if a certain percantage of
        // initial speed was lost
        if(m_kart->getSpeed() <= 
            m_initial_speed*stk_config->m_parachute_done_fraction)
        {
            m_time_left = -1;
        }
        break;
    case ATTACH_ANVIL:     // handled in Kart::updatePhysics
    case ATTACH_NOTHING:   // Nothing to do, but complete all cases for switch
    case ATTACH_MAX:
        break;
    case ATTACH_SWATTER:
    case ATTACH_NOLOKS_SWATTER:
        // Everything is done in the plugin.
        break;
    case ATTACH_BOMB:
            
        if (m_bomb_sound) m_bomb_sound->position(m_kart->getXYZ());

        // Mesh animation frames are 1 to 61 frames (60 steps)
        // The idea is change second by second, counterclockwise 60 to 0 secs
        // If longer times needed, it should be a surprise "oh! bomb activated!"
        if(m_time_left <= (m_node->getEndFrame() - m_node->getStartFrame()-1))
        {
            m_node->setCurrentFrame(m_node->getEndFrame() 
                                    - m_node->getStartFrame()-1-m_time_left);
        }
        if(m_time_left<=0.0)
        {
            HitEffect *he = new Explosion(m_kart->getXYZ(), "explosion");
            if(m_kart->getController()->isPlayerController())
                he->setPlayerKartHit();
            projectile_manager->addHitEffect(he);
            ExplosionAnimation::create(m_kart);
            
            if (m_bomb_sound)
            {
                m_bomb_sound->stop();
                sfx_manager->deleteSFX(m_bomb_sound);
                m_bomb_sound = NULL;
            }
        }
        break;
    case ATTACH_TINYTUX:
        // Nothing to do for tinytux, this is all handled in EmergencyAnimation
        break;
    }   // switch

    // Detach attachment if its time is up.
    if ( m_time_left <= 0.0f)
        clear();
}   // update