Esempio n. 1
0
void GamePadDevice::resetAxisDirection(const int axis,
                                       Input::AxisDirection direction)
{
    // ignore this while in menus
    if (StateManager::get()->getGameState() != GUIEngine::GAME) return;

    AbstractKart* pk = getPlayer()->getKart();
    if (!pk)
    {
        Log::error("Binding", "Trying to reset axis for an unknown player.");
        return;
    }

    for(int n=PA_BEFORE_FIRST+1; n<PA_COUNT; n++)
    {
        const Binding& bind = m_configuration->getBinding(n);
        if(bind.getType() == Input::IT_STICKMOTION &&
           bind.getId() == axis &&
           bind.getDirection()== direction &&
           pk->getController() != NULL)
        {
            ((PlayerController*)(pk->getController()))
                                                  ->action((PlayerAction)n, 0);
            return;
        }
    }

}   // resetAxisDirection
Esempio n. 2
0
// ----------------------------------------------------------------------------
void addAttachment(Attachment::AttachmentType type)
{
    World* world = World::getWorld();
    if (world == NULL) return;
    for (unsigned int i = 0; i < world->getNumKarts(); i++)
    {
        AbstractKart *kart = world->getKart(i);
        if (!kart->getController()->isLocalPlayerController())
            continue;
        if (type == Attachment::ATTACH_ANVIL)
        {
            kart->getAttachment()
                ->set(type, kart->getKartProperties()->getAnvilDuration());
            kart->adjustSpeed(kart->getKartProperties()->getAnvilSpeedFactor());
            kart->updateWeight();
        }
        else if (type == Attachment::ATTACH_PARACHUTE)
        {
            kart->getAttachment()
                ->set(type, kart->getKartProperties()->getParachuteDuration());
        }
        else if (type == Attachment::ATTACH_BOMB)
        {
            kart->getAttachment()
                ->set(type, stk_config->m_bomb_time);
        }
    }

}   // addAttachment
Esempio n. 3
0
void addAttachment(Attachment::AttachmentType type)
{
    World* world = World::getWorld();
        if (world == NULL) return;
        for(unsigned int i = 0; i < world->getNumKarts(); i++)
        {
        AbstractKart *kart = world->getKart(i);
        if (kart->getController()->isPlayerController()) {
            if (type == Attachment::ATTACH_ANVIL)
            {
                kart->getAttachment()
                    ->set(type, stk_config->m_anvil_time);
                kart->adjustSpeed(stk_config->m_anvil_speed_factor);
                kart->updateWeight();
            }
            else if (type == Attachment::ATTACH_PARACHUTE)
            {
                kart->getAttachment()
                        ->set(type, stk_config->m_parachute_time);
            }
            else if (type == Attachment::ATTACH_BOMB)
            {
                kart->getAttachment()
                        ->set(type, stk_config->m_bomb_time);
            }
        }
        }

}
Esempio n. 4
0
void GamePadDevice::resetAxisDirection(const int axis, 
                                       Input::AxisDirection direction, 
                                       StateManager::ActivePlayer* player)
{
    // ignore this while in menus
    if (StateManager::get()->getGameState() != GUIEngine::GAME) return;

    AbstractKart* pk = player->getKart();
    if (pk == NULL)
    {
        fprintf(stderr, "Error, trying to reset axis for an unknown player\n");
        return;
    }
    
    for(int n=0; n<PA_COUNT; n++)
    {
        Binding& bind = m_configuration->getBinding(n);
        if(bind.getType() == Input::IT_STICKMOTION &&
           bind.getId() == axis &&
           bind.getDirection()== direction)
        {
            ((PlayerController*)(pk->getController()))
                                                  ->action((PlayerAction)n, 0);
            return;
        }
    }

}   // resetAxisDirection
/** Receives a kart control message. 
 *  \param kart_id_offset is the global id of the first kart on the host from 
 *         which this packet was received.
 */
KartControlMessage::KartControlMessage(ENetPacket* pkt, int kart_id_offset,
                                       int num_local_players)
                  : Message(pkt, MT_KART_CONTROL)
{
    // FIXME: This probably does not work anymore - it assume that
    // num_local_Players is the number of all local karts, while it might
    // only be the number of all network karts.
    for(int i=kart_id_offset; i<kart_id_offset+num_local_players; i++)
    {
        KartControl kc(this);
        AbstractKart *kart = World::getWorld()->getKart(i);
        if(kart->getController()->isNetworkController())
        {
            ((NetworkKart*)kart)->setControl(kc);
        }
    }
};   // KartControlMessage
Esempio n. 6
0
/** Remove (eliminate) a kart from the race */
void World::eliminateKart(int kart_id, bool notify_of_elimination)
{
    AbstractKart *kart = m_karts[kart_id];
    if (kart->isGhostKart()) return;

    // Display a message about the eliminated kart in the race guia
    if (notify_of_elimination)
    {
        for(unsigned int i=0; i<Camera::getNumCameras(); i++)
        {
            Camera *camera = Camera::getCamera(i);
            if(camera->getKart()==kart)
                m_race_gui->addMessage(_("You have been eliminated!"), kart,
                                       2.0f);
            else
                m_race_gui->addMessage(_("'%s' has been eliminated.",
                                       kart->getName()),
                                       camera->getKart(),
                                       2.0f);
        }  // for i < number of cameras
    }   // if notify_of_elimination

    if(kart->getController()->isLocalPlayerController())
    {
        for(unsigned int i=0; i<Camera::getNumCameras(); i++)
        {
            // Change the camera so that it will be attached to the leader
            // and facing backwards.
            Camera *camera = Camera::getCamera(i);
            if(camera->getKart()==kart)
                camera->setMode(Camera::CM_LEADER_MODE);
        }
        m_eliminated_players++;
    }

    // The kart can't be really removed from the m_kart array, since otherwise
    // a race can't be restarted. So it's only marked to be eliminated (and
    // ignored in all loops). Important:world->getCurrentNumKarts() returns
    // the number of karts still racing. This value can not be used for loops
    // over all karts, use race_manager->getNumKarts() instead!
    kart->eliminate();
    m_eliminated_karts++;

}   // eliminateKart
/** Remove (eliminate) a kart from the race */
void World::eliminateKart(int kart_number, bool notify_of_elimination)
{
    AbstractKart *kart = m_karts[kart_number];
    
    // Display a message about the eliminated kart in the race gui
    if (notify_of_elimination)
    {
        for (KartList::iterator i = m_karts.begin(); i != m_karts.end();  i++ )
        {
            if(!(*i)->getCamera()) continue;
            if(*i==kart)
            {
                m_race_gui->addMessage(_("You have been eliminated!"), *i, 
                                       2.0f);
            }
            else
            {
                m_race_gui->addMessage(_("'%s' has been eliminated.",
                                       core::stringw(kart->getName())), *i, 
                                       2.0f);
            }
        }   // for i in kart
    }
    
    if(kart->getController()->isPlayerController())
    {
        // Change the camera so that it will be attached to the leader
        // and facing backwards.
        Camera* camera=kart->getCamera();
        camera->setMode(Camera::CM_LEADER_MODE);
        m_eliminated_players++;
    }

    // The kart can't be really removed from the m_kart array, since otherwise
    // a race can't be restarted. So it's only marked to be eliminated (and
    // ignored in all loops). Important:world->getCurrentNumKarts() returns
    // the number of karts still racing. This value can not be used for loops
    // over all karts, use race_manager->getNumKarts() instead!
    kart->eliminate();
    m_eliminated_karts++;

}   // eliminateKart
Esempio n. 8
0
/** Ends the race early and places still active player karts at the back.
 *  The race immediately goes to the result stage, estimating the time for the
 *  karts still in the race. Still active player karts get a penalty in time
 *  as well as being placed at the back. Players that already finished keep
 *  their position.
 *
 *  End time for the punished players is calculated as follows
 *  end_time = current_time + (estimated_time - current_time)
 *                          + (estimated_time_for_last - current_time)
 *           = estimated_time + estimated_time_for_last - current_time
 *  This will put them at the end at all times. The further you (and the last in
 *  the race) are from the finish line, the harsher the punishment will be.
 */
void StandardRace::endRaceEarly()
{
    const unsigned int kart_amount = (unsigned int)m_karts.size();
    std::vector<int> active_players;
    // Required for debugging purposes
    beginSetKartPositions();
    for (unsigned int i = 1; i <= kart_amount; i++)
    {
        int kartid = m_position_index[i-1];
        AbstractKart* kart = m_karts[kartid];
        if (kart->hasFinishedRace())
        {
            // Have to do this to keep endSetKartPosition happy
            setKartPosition(kartid, kart->getPosition());
            continue;
        }

        if (kart->getController()->isPlayerController())
        {
            // Keep active players apart for now
            active_players.push_back(kartid);
        }
        else
        {
            // AI karts finish
            setKartPosition(kartid, i - (unsigned int) active_players.size());
            kart->finishedRace(estimateFinishTimeForKart(kart));
        }
    } // i <= kart_amount
    // Now make the active players finish
    for (unsigned int i = 0; i < active_players.size(); i++)
    {
        int kartid = active_players[i];
        int position = getNumKarts() - (int) active_players.size() + 1 + i;
        setKartPosition(kartid, position);
        m_karts[kartid]->eliminate();
    } // Finish the active players
    endSetKartPositions();
    setPhase(RESULT_DISPLAY_PHASE);
    if (!isNetworkWorld() || NetworkConfig::get()->isServer())
        terminateRace();
} // endRaceEarly
Esempio n. 9
0
/** Is called by check structures if a kart starts a new lap.
 *  \param kart_index Index of the kart.
 */
void LinearWorld::newLap(unsigned int kart_index)
{
    KartInfo &kart_info = m_kart_info[kart_index];
    AbstractKart *kart  = m_karts[kart_index];

    // Reset reset-after-lap achievements
    StateManager::ActivePlayer *c = kart->getController()->getPlayer();
    PlayerProfile *p = PlayerManager::getCurrentPlayer();
    if (c && c->getConstProfile() == p)
    {
        p->getAchievementsStatus()->onLapEnd();
    }

    // Only update the kart controller if a kart that has already finished
    // the race crosses the start line again. This avoids 'fastest lap'
    // messages if the end controller does a fastest lap, but especially
    // allows the end controller to switch end cameras
    if(kart->hasFinishedRace())
    {
        kart->getController()->newLap(kart_info.m_race_lap);
        return;
    }

    const int lap_count = race_manager->getNumLaps();

    // Only increase the lap counter and set the new time if the
    // kart hasn't already finished the race (otherwise the race_gui
    // will begin another countdown).
    if(kart_info.m_race_lap+1 <= lap_count)
    {
        assert(kart->getWorldKartId()==kart_index);
        kart_info.m_time_at_last_lap=getTime();
        kart_info.m_race_lap++;
        m_kart_info[kart_index].m_overall_distance =
              m_kart_info[kart_index].m_race_lap * m_track->getTrackLength()
            + getDistanceDownTrackForKart(kart->getWorldKartId());
    }
    // Last lap message (kart_index's assert in previous block already)
    if (raceHasLaps() && kart_info.m_race_lap+1 == lap_count)
    {
        m_race_gui->addMessage(_("Final lap!"), kart,
                               3.0f, video::SColor(255, 210, 100, 50), true);
        if(!m_last_lap_sfx_played && lap_count > 1)
        {
            if (UserConfigParams::m_music)
            {
                m_last_lap_sfx->play();
                m_last_lap_sfx_played = true;
                m_last_lap_sfx_playing = true;

                // In case that no music is defined
                if(music_manager->getCurrentMusic() &&
                    music_manager->getMasterMusicVolume() > 0.2f)
                {
                    music_manager->setTemporaryVolume(0.2f);
                }
            }
            else
            {
                m_last_lap_sfx_played = true;
                m_last_lap_sfx_playing = false;
            }
        }
    }
    else if (raceHasLaps() && kart_info.m_race_lap > 0 &&
             kart_info.m_race_lap+1 < lap_count)
    {
        m_race_gui->addMessage(_("Lap %i", kart_info.m_race_lap+1),
                               kart, 3.0f, video::SColor(255, 210, 100, 50),
                               true);
    }

    // The race positions must be updated here: consider the situation where
    // the first kart does not cross the finish line in its last lap, instead
    // it passes it, the kart reverses and crosses the finishing line
    // backwards. Just before crossing the finishing line the kart will be on
    // the last lap, but with a distance along the track close to zero.
    // Therefore its position will be wrong. If the race position gets updated
    // after increasing the number of laps (but before tagging the kart to have
    // finished the race) the position will be correct (since the kart now
    // has one additional lap it will be ahead of the other karts).
    // Without this call the incorrect position for this kart would remain
    // (since a kart that has finished the race does not get its position
    // changed anymore), potentially resulting in a duplicated race position
    // (since the first kart does not have position 1, no other kart can get
    // position 1, so one rank will be duplicated).
    // Similarly the situation can happen if the distance along track should
    // go back to zero before actually crossing the finishing line. While this
    // should not happen, it could potentially be caused by floating point
    // errors. In this case the call to updateRacePosition will avoid
    // duplicated race positions as well.
    updateRacePosition();

    // Race finished
    if(kart_info.m_race_lap >= race_manager->getNumLaps() && raceHasLaps())
    {
        kart->finishedRace(getTime());
    }
    float time_per_lap;
    if (kart_info.m_race_lap == 1) // just completed first lap
    {
        time_per_lap=getTime();
    }
    else //completing subsequent laps
    {
        time_per_lap=getTime() - kart_info.m_lap_start_time;
    }

    // if new fastest lap
    if(time_per_lap < m_fastest_lap && raceHasLaps() &&
        kart_info.m_race_lap>0)
    {
        m_fastest_lap = time_per_lap;

        std::string s = StringUtils::timeToString(time_per_lap);

        // Store the temporary string because clang would mess this up
        // (remove the stringw before the wchar_t* is used).
        const core::stringw &kart_name = kart->getName();

        //I18N: as in "fastest lap: 60 seconds by Wilber"
        irr::core::stringw m_fastest_lap_message =
            _C("fastest_lap", "%s by %s", s.c_str(), kart_name);

        m_race_gui->addMessage(m_fastest_lap_message, NULL,
                               3.0f, video::SColor(255, 255, 255, 255), false);

        m_race_gui->addMessage(_("New fastest lap"), NULL,
                               3.0f, video::SColor(255, 255, 255, 255), false);

    } // end if new fastest lap

    kart_info.m_lap_start_time = getTime();
    kart->getController()->newLap(kart_info.m_race_lap);
}   // newLap
Esempio n. 10
0
bool handleContextMenuAction(s32 cmd_id)
{

    World *world = World::getWorld();
    Physics *physics = world ? world->getPhysics() : NULL;
    switch(cmd_id)
    {
    case DEBUG_GRAPHICS_RELOAD_SHADERS:
            Log::info("Debug", "Reloading shaders...");
            ShaderBase::updateShaders();
            break;
    case DEBUG_GRAPHICS_RESET:
        if (physics)
            physics->setDebugMode(IrrDebugDrawer::DM_NONE);

        irr_driver->resetDebugModes();
        break;
    case DEBUG_GRAPHICS_WIREFRAME:
        if (physics)
            physics->setDebugMode(IrrDebugDrawer::DM_NONE);

        irr_driver->resetDebugModes();
        irr_driver->toggleWireframe();
        break;
    case DEBUG_GRAPHICS_MIPMAP_VIZ:
        if (physics)
            physics->setDebugMode(IrrDebugDrawer::DM_NONE);

        irr_driver->resetDebugModes();
        irr_driver->toggleMipVisualization();
        break;
    case DEBUG_GRAPHICS_NORMALS_VIZ:
        if (physics)
            physics->setDebugMode(IrrDebugDrawer::DM_NONE);

        irr_driver->resetDebugModes();
        irr_driver->toggleNormals();
        break;
    case DEBUG_GRAPHICS_SSAO_VIZ:
        if (physics)
            physics->setDebugMode(IrrDebugDrawer::DM_NONE);

        irr_driver->resetDebugModes();
        irr_driver->toggleSSAOViz();
        break;
    case DEBUG_GRAPHICS_RSM_VIZ:
        if (physics)
            physics->setDebugMode(IrrDebugDrawer::DM_NONE);

        irr_driver->resetDebugModes();
        irr_driver->toggleRSM();
        break;
    case DEBUG_GRAPHICS_RH_VIZ:
        if (physics)
            physics->setDebugMode(IrrDebugDrawer::DM_NONE);

        irr_driver->resetDebugModes();
        irr_driver->toggleRH();
        break;
    case DEBUG_GRAPHICS_GI_VIZ:
        if (physics)
            physics->setDebugMode(IrrDebugDrawer::DM_NONE);

        irr_driver->resetDebugModes();
        irr_driver->toggleGI();
        break;
    case DEBUG_GRAPHICS_SHADOW_VIZ:
        if (physics)
            physics->setDebugMode(IrrDebugDrawer::DM_NONE);

        irr_driver->resetDebugModes();
        irr_driver->toggleShadowViz();
        break;
    case DEBUG_GRAPHICS_LIGHT_VIZ:
        if (physics)
            physics->setDebugMode(IrrDebugDrawer::DM_NONE);

        irr_driver->resetDebugModes();
        irr_driver->toggleLightViz();
        break;
    case DEBUG_GRAPHICS_DISTORT_VIZ:
        if (physics)
            physics->setDebugMode(IrrDebugDrawer::DM_NONE);

        irr_driver->resetDebugModes();
        irr_driver->toggleDistortViz();
        break;
    case DEBUG_GRAPHICS_BULLET_1:
        irr_driver->resetDebugModes();

        if (!world) return false;
        physics->setDebugMode(IrrDebugDrawer::DM_KARTS_PHYSICS);
        break;
    case DEBUG_GRAPHICS_BULLET_2:
    {
        irr_driver->resetDebugModes();

        if (!world) return false;
        Physics *physics = world->getPhysics();
        physics->setDebugMode(IrrDebugDrawer::DM_NO_KARTS_GRAPHICS);
        break;
    }
    case DEBUG_GRAPHICS_BOUNDING_BOXES_VIZ:
        irr_driver->resetDebugModes();
        irr_driver->toggleBoundingBoxesViz();
        break;
    case DEBUG_PROFILER:
        UserConfigParams::m_profiler_enabled =
            !UserConfigParams::m_profiler_enabled;
        break;
    case DEBUG_PROFILER_GENERATE_REPORT:
        profiler.setCaptureReport(!profiler.getCaptureReport());
        break;
    case DEBUG_THROTTLE_FPS:
        main_loop->setThrottleFPS(false);
        break;
    case DEBUG_FONT_DUMP_GLYPH_PAGE:
        font_manager->getFont<BoldFace>()->dumpGlyphPage("bold");
        font_manager->getFont<DigitFace>()->dumpGlyphPage("digit");
        font_manager->getFont<RegularFace>()->dumpGlyphPage("regular");
    case DEBUG_FONT_RELOAD:
        font_manager->getFont<BoldFace>()->reset();
        font_manager->getFont<DigitFace>()->reset();
        font_manager->getFont<RegularFace>()->reset();
        break;
    case DEBUG_FPS:
        UserConfigParams::m_display_fps =
            !UserConfigParams::m_display_fps;
        break;
    case DEBUG_SAVE_REPLAY:
        ReplayRecorder::get()->save();
        break;
    case DEBUG_SAVE_HISTORY:
        history->Save();
        break;
    case DEBUG_POWERUP_BOWLING:
        addPowerup(PowerupManager::POWERUP_BOWLING);
        break;
    case DEBUG_POWERUP_BUBBLEGUM:
        addPowerup(PowerupManager::POWERUP_BUBBLEGUM);
        break;
    case DEBUG_POWERUP_CAKE:
        addPowerup(PowerupManager::POWERUP_CAKE);
        break;
    case DEBUG_POWERUP_PARACHUTE:
        addPowerup(PowerupManager::POWERUP_PARACHUTE);
        break;
    case DEBUG_POWERUP_PLUNGER:
        addPowerup(PowerupManager::POWERUP_PLUNGER);
        break;
    case DEBUG_POWERUP_RUBBERBALL:
        addPowerup(PowerupManager::POWERUP_RUBBERBALL);
        break;
    case DEBUG_POWERUP_SWATTER:
        addPowerup(PowerupManager::POWERUP_SWATTER);
        break;
    case DEBUG_POWERUP_SWITCH:
        addPowerup(PowerupManager::POWERUP_SWITCH);
        break;
    case DEBUG_POWERUP_ZIPPER:
        addPowerup(PowerupManager::POWERUP_ZIPPER);
        break;
    case DEBUG_POWERUP_NITRO:
    {
        if (!world) return false;
        const unsigned int num_local_players =
            race_manager->getNumLocalPlayers();
        for (unsigned int i = 0; i < num_local_players; i++)
        {
            AbstractKart* kart = world->getLocalPlayerKart(i);
            kart->setEnergy(100.0f);
        }
        break;
    }
    case DEBUG_ATTACHMENT_ANVIL:
        addAttachment(Attachment::ATTACH_ANVIL);
        break;
    case DEBUG_ATTACHMENT_BOMB:
        addAttachment(Attachment::ATTACH_BOMB);
        break;
    case DEBUG_ATTACHMENT_PARACHUTE:
        addAttachment(Attachment::ATTACH_PARACHUTE);
        break;
    case DEBUG_GUI_TOGGLE:
    {
        if (!world) return false;
        RaceGUIBase* gui = world->getRaceGUI();
        if (gui != NULL) gui->m_enabled = !gui->m_enabled;
        break;
    }
    case DEBUG_GUI_HIDE_KARTS:
        if (!world) return false;
        for (unsigned int n = 0; n<world->getNumKarts(); n++)
        {
            AbstractKart* kart = world->getKart(n);
            if (kart->getController()->isPlayerController())
                kart->getNode()->setVisible(false);
        }
        break;
    case DEBUG_GUI_CAM_TOP:
        CameraDebug::setDebugType(CameraDebug::CM_DEBUG_TOP_OF_KART);
        Camera::changeCamera(0, Camera::CM_TYPE_DEBUG);
        irr_driver->getDevice()->getCursorControl()->setVisible(true);
        break;
    case DEBUG_GUI_CAM_WHEEL:
        CameraDebug::setDebugType(CameraDebug::CM_DEBUG_GROUND);
        Camera::changeCamera(0, Camera::CM_TYPE_DEBUG);
        irr_driver->getDevice()->getCursorControl()->setVisible(true);
        break;
    case DEBUG_GUI_CAM_BEHIND_KART:
        CameraDebug::setDebugType(CameraDebug::CM_DEBUG_BEHIND_KART);
        Camera::changeCamera(0, Camera::CM_TYPE_DEBUG);
        irr_driver->getDevice()->getCursorControl()->setVisible(true);
        break;
    case DEBUG_GUI_CAM_SIDE_OF_KART:
        CameraDebug::setDebugType(CameraDebug::CM_DEBUG_SIDE_OF_KART);
        Camera::changeCamera(0, Camera::CM_TYPE_DEBUG);
        irr_driver->getDevice()->getCursorControl()->setVisible(true);
        break;
    case DEBUG_GUI_CAM_FREE:
    {
        Camera *camera = Camera::getActiveCamera();
        Camera::changeCamera(camera->getIndex(), Camera::CM_TYPE_FPS);
        irr_driver->getDevice()->getCursorControl()->setVisible(false);
        // Reset camera rotation
        CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
        if(cam)
        {
            cam->setDirection(vector3df(0, 0, 1));
            cam->setUpVector(vector3df(0, 1, 0));
        }
        break;
    }
    case DEBUG_GUI_CAM_NORMAL:
    {
        Camera *camera = Camera::getActiveCamera();
        Camera::changeCamera(camera->getIndex(), Camera::CM_TYPE_NORMAL);
        irr_driver->getDevice()->getCursorControl()->setVisible(true);
        break;
    }
    case DEBUG_GUI_CAM_SMOOTH:
    {
        CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
        if(cam)
        {
            cam->setSmoothMovement(!cam->getSmoothMovement());
        }
        break;
    }
    case DEBUG_GUI_CAM_ATTACH:
    {
        CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
        if(cam)
        {
            cam->setAttachedFpsCam(!cam->getAttachedFpsCam());
        }
        break;
    }
    case DEBUG_VIEW_KART_ONE:
        changeCameraTarget(1);
        break;
    case DEBUG_VIEW_KART_TWO:
        changeCameraTarget(2);
        break;
    case DEBUG_VIEW_KART_THREE:
        changeCameraTarget(3);
        break;
    case DEBUG_VIEW_KART_FOUR:
        changeCameraTarget(4);
        break;
    case DEBUG_VIEW_KART_FIVE:
        changeCameraTarget(5);
        break;
    case DEBUG_VIEW_KART_SIX:
        changeCameraTarget(6);
        break;
    case DEBUG_VIEW_KART_SEVEN:
        changeCameraTarget(7);
        break;
    case DEBUG_VIEW_KART_EIGHT:
        changeCameraTarget(8);
        break;
    case DEBUG_PRINT_START_POS:
        if (!world) return false;
        for (unsigned int i = 0; i<world->getNumKarts(); i++)
        {
            AbstractKart *kart = world->getKart(i);
            Log::warn(kart->getIdent().c_str(),
                "<start position=\"%d\" x=\"%f\" y=\"%f\" z=\"%f\" h=\"%f\"/>",
                i, kart->getXYZ().getX(), kart->getXYZ().getY(),
                kart->getXYZ().getZ(), kart->getHeading()*RAD_TO_DEGREE
                );
        }
        break;
    case DEBUG_VISUAL_VALUES:
    {
#if !defined(__APPLE__)
        DebugSliderDialog *dsd = new DebugSliderDialog();
        dsd->setSliderHook("red_slider", 0, 255,
            [](){ return int(irr_driver->getAmbientLight().r * 255.f); },
            [](int v){
            video::SColorf ambient = irr_driver->getAmbientLight();
            ambient.setColorComponentValue(0, v / 255.f);
            irr_driver->setAmbientLight(ambient); }
        );
        dsd->setSliderHook("green_slider", 0, 255,
            [](){ return int(irr_driver->getAmbientLight().g * 255.f); },
            [](int v){
            video::SColorf ambient = irr_driver->getAmbientLight();
            ambient.setColorComponentValue(1, v / 255.f);
            irr_driver->setAmbientLight(ambient); }
        );
        dsd->setSliderHook("blue_slider", 0, 255,
            [](){ return int(irr_driver->getAmbientLight().b * 255.f); },
            [](int v){
            video::SColorf ambient = irr_driver->getAmbientLight();
            ambient.setColorComponentValue(2, v / 255.f);
            irr_driver->setAmbientLight(ambient); }
        );
        dsd->setSliderHook("ssao_radius", 0, 100,
            [](){ return int(irr_driver->getSSAORadius() * 10.f); },
            [](int v){irr_driver->setSSAORadius(v / 10.f); }
        );
        dsd->setSliderHook("ssao_k", 0, 100,
            [](){ return int(irr_driver->getSSAOK() * 10.f); },
            [](int v){irr_driver->setSSAOK(v / 10.f); }
        );
        dsd->setSliderHook("ssao_sigma", 0, 100,
            [](){ return int(irr_driver->getSSAOSigma() * 10.f); },
            [](int v){irr_driver->setSSAOSigma(v / 10.f); }
        );
#endif
    }
    break;
    case DEBUG_ADJUST_LIGHTS:
    {
#if !defined(__APPLE__)
        // Some sliders use multipliers because the spinner widget
        // only supports integers
        DebugSliderDialog *dsd = new DebugSliderDialog();
        dsd->changeLabel("Red", "Red (x10)");
        dsd->setSliderHook("red_slider", 0, 100,
            []()
            {
                return int(findNearestLight()->getColor().X * 100);
            },
            [](int intensity)
            {
                LightNode* nearest = findNearestLight();
                core::vector3df color = nearest->getColor();
                nearest->setColor(intensity / 100.0f, color.Y, color.Z);
            }
        );
        dsd->changeLabel("Green", "Green (x10)");
        dsd->setSliderHook("green_slider", 0, 100,
            []()
            {
                return int(findNearestLight()->getColor().Y * 100);
            },
            [](int intensity)
            {
                LightNode* nearest = findNearestLight();
                core::vector3df color = nearest->getColor();
                nearest->setColor(color.X, intensity / 100.0f, color.Z);
            }
        );
        dsd->changeLabel("Blue", "Blue (x10)");
        dsd->setSliderHook("blue_slider", 0, 100,
            []()
            {
                return int(findNearestLight()->getColor().Z * 100);
            },
            [](int intensity)
            {
                LightNode* nearest = findNearestLight();
                core::vector3df color = nearest->getColor();
                nearest->setColor(color.X, color.Y, intensity / 100.0f);
            }
        );
        dsd->changeLabel("SSAO radius", "energy (x10)");
        dsd->setSliderHook("ssao_radius", 0, 100,
            []()     { return int(findNearestLight()->getEnergy() * 10);  },
            [](int v){        findNearestLight()->setEnergy(v / 10.0f); }
        );
        dsd->changeLabel("SSAO k", "radius");
        dsd->setSliderHook("ssao_k", 0, 100,
            []()     { return int(findNearestLight()->getRadius());  },
            [](int v){        findNearestLight()->setRadius(float(v)); }
        );
        dsd->changeLabel("SSAO Sigma", "[None]");
#endif
        break;
    }
    case DEBUG_SCRIPT_CONSOLE:
        new ScriptingConsole();
        break;
    }   // switch
    return false;
}
Esempio n. 11
0
// ----------------------------------------------------------------------------
bool GameEventsProtocol::notifyEvent(Event* event)
{
    // Avoid crash in case that we still receive race events when
    // the race is actually over.
    if (event->getType() != EVENT_TYPE_MESSAGE || !World::getWorld())
        return true;
    NetworkString &data = event->data();
    if (data.size() < 1) // for type
    {
        Log::warn("GameEventsProtocol", "Too short message.");
        return true;
    }
    uint8_t type = data.getUInt8();
    CaptureTheFlag* ctf = dynamic_cast<CaptureTheFlag*>(World::getWorld());
    FreeForAll* ffa = dynamic_cast<FreeForAll*>(World::getWorld());
    SoccerWorld* sw = dynamic_cast<SoccerWorld*>(World::getWorld());
    LinearWorld* lw = dynamic_cast<LinearWorld*>(World::getWorld());
    switch (type)
    {
    case GE_KART_FINISHED_RACE:
        kartFinishedRace(data);     break;
    case GE_RESET_BALL:
    {
        if (!sw)
            throw std::invalid_argument("No soccer world");
        sw->handleResetBallFromServer(data);
        break;
    }
    case GE_PLAYER_GOAL:
    {
        if (!sw)
            throw std::invalid_argument("No soccer world");
        sw->handlePlayerGoalFromServer(data);
        break;
    }
    case GE_BATTLE_KART_SCORE:
    {
        if (!ffa)
            throw std::invalid_argument("No free-for-all world");
        ffa->setKartScoreFromServer(data);
        break;
    }
    case GE_CTF_SCORED:
    {
        if (!ctf)
            throw std::invalid_argument("No CTF world");
        uint8_t kart_id = data.getUInt8();
        bool red_team_scored = data.getUInt8() == 1;
        int16_t new_kart_scores = data.getUInt16();
        int new_red_scores = data.getUInt8();
        int new_blue_scores = data.getUInt8();
        ctf->ctfScored(kart_id, red_team_scored, new_kart_scores,
            new_red_scores, new_blue_scores);
        break;
    }
    case GE_STARTUP_BOOST:
    {
        if (NetworkConfig::get()->isServer())
        {
            uint8_t kart_id = data.getUInt8();
            if (!event->getPeer()->availableKartID(kart_id))
            {
                Log::warn("GameProtocol", "Wrong kart id %d from %s.",
                    kart_id, event->getPeer()->getAddress().toString().c_str());
                return true;
            }
            float f = LobbyProtocol::get<ServerLobby>()
                ->getStartupBoostOrPenaltyForKart(
                event->getPeer()->getAveragePing(), kart_id);
            NetworkString *ns = getNetworkString();
            ns->setSynchronous(true);
            ns->addUInt8(GE_STARTUP_BOOST).addUInt8(kart_id).addFloat(f);
            sendMessageToPeers(ns, true);
            delete ns;
        }
        else
        {
            uint8_t kart_id = data.getUInt8();
            float boost = data.getFloat();
            AbstractKart* k = World::getWorld()->getKart(kart_id);
            if (boost < 0.0f)
            {
                PlayerController* pc =
                    dynamic_cast<PlayerController*>(k->getController());
                pc->displayPenaltyWarning();
            }
            else
                k->setStartupBoost(boost);
        }
        break;
    }
    case GE_CHECK_LINE:
    {
        if (!lw)
            throw std::invalid_argument("No linear world");
        if (NetworkConfig::get()->isClient())
            lw->updateCheckLinesClient(data);
        break;
    }
    default:
        Log::warn("GameEventsProtocol", "Unkown message type.");
        break;
    }
    return true;
}   // notifyEvent
Esempio n. 12
0
// -----------------------------------------------------------------------------
// Debug menu handling
bool onEvent(const SEvent &event)
{
    // Only activated in artist debug mode
    if(!UserConfigParams::m_artist_debug_mode)
        return true;    // keep handling the events

    if(event.EventType == EET_MOUSE_INPUT_EVENT)
    {
        // Create the menu (only one menu at a time)
        if(event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN && !g_debug_menu_visible)
        {
            // root menu
            gui::IGUIEnvironment* guienv = irr_driver->getGUI();
            IGUIContextMenu* mnu = guienv->addContextMenu(
                core::rect<s32>(event.MouseInput.X, event.MouseInput.Y, event.MouseInput.Y+100, event.MouseInput.Y+100),NULL);
            int graphicsMenuIndex = mnu->addItem(L"Graphics >",-1,true,true);
            
            // graphics menu
            IGUIContextMenu* sub = mnu->getSubMenu(graphicsMenuIndex);

            sub->addItem(L"Reload shaders", DEBUG_GRAPHICS_RELOAD_SHADERS );
            sub->addItem(L"Reset debug views", DEBUG_GRAPHICS_RESET );
            sub->addItem(L"Wireframe", DEBUG_GRAPHICS_WIREFRAME );
            sub->addItem(L"Mipmap viz", DEBUG_GRAPHICS_MIPMAP_VIZ );
            sub->addItem(L"Normals viz", DEBUG_GRAPHICS_NORMALS_VIZ );
            sub->addItem(L"SSAO viz", DEBUG_GRAPHICS_SSAO_VIZ );
            sub->addItem(L"RSM viz", DEBUG_GRAPHICS_RSM_VIZ);
            sub->addItem(L"RH viz", DEBUG_GRAPHICS_RH_VIZ);
            sub->addItem(L"GI viz", DEBUG_GRAPHICS_GI_VIZ);
            sub->addItem(L"Shadow viz", DEBUG_GRAPHICS_SHADOW_VIZ );
            sub->addItem(L"Light viz", DEBUG_GRAPHICS_LIGHT_VIZ );
            sub->addItem(L"Distort viz", DEBUG_GRAPHICS_DISTORT_VIZ );
            sub->addItem(L"Physics debug", DEBUG_GRAPHICS_BULLET_1);
            sub->addItem(L"Physics debug (no kart)", DEBUG_GRAPHICS_BULLET_2);

            mnu->addItem(L"Items >",-1,true,true);
            sub = mnu->getSubMenu(1);
            sub->addItem(L"Basketball", DEBUG_POWERUP_RUBBERBALL );
            sub->addItem(L"Bowling", DEBUG_POWERUP_BOWLING );
            sub->addItem(L"Bubblegum", DEBUG_POWERUP_BUBBLEGUM );
            sub->addItem(L"Cake", DEBUG_POWERUP_CAKE );
            sub->addItem(L"Parachute", DEBUG_POWERUP_PARACHUTE );
            sub->addItem(L"Plunger", DEBUG_POWERUP_PLUNGER );
            sub->addItem(L"Swatter", DEBUG_POWERUP_SWATTER );
            sub->addItem(L"Switch", DEBUG_POWERUP_SWITCH );
            sub->addItem(L"Zipper", DEBUG_POWERUP_ZIPPER );
            sub->addItem(L"Nitro", DEBUG_POWERUP_NITRO );
            
            mnu->addItem(L"Attachments >",-1,true, true);
            sub = mnu->getSubMenu(2);
            sub->addItem(L"Bomb", DEBUG_ATTACHMENT_BOMB);
            sub->addItem(L"Anvil", DEBUG_ATTACHMENT_ANVIL);
            sub->addItem(L"Parachute", DEBUG_ATTACHMENT_PARACHUTE);

            mnu->addItem(L"Adjust values", DEBUG_VISUAL_VALUES);

            mnu->addItem(L"Profiler",DEBUG_PROFILER);
            if (UserConfigParams::m_profiler_enabled)
                mnu->addItem(L"Toggle capture profiler report", DEBUG_PROFILER_GENERATE_REPORT);
            mnu->addItem(L"Do not limit FPS", DEBUG_THROTTLE_FPS);
            mnu->addItem(L"FPS",DEBUG_FPS);
            mnu->addItem(L"Save replay", DEBUG_SAVE_REPLAY);
            mnu->addItem(L"Save history", DEBUG_SAVE_HISTORY);
            mnu->addItem(L"Toggle GUI", DEBUG_TOGGLE_GUI);
            mnu->addItem(L"Hide karts", DEBUG_HIDE_KARTS);


            g_debug_menu_visible = true;
            irr_driver->showPointer();
        }

        // Let Irrlicht handle the event while the menu is visible - otherwise in a race the GUI events won't be generated
        if(g_debug_menu_visible)
            return false;
    }

    if (event.EventType == EET_GUI_EVENT)
    {
        if (event.GUIEvent.Caller != NULL && event.GUIEvent.Caller->getType() == EGUIET_CONTEXT_MENU )
        {
            IGUIContextMenu *menu = (IGUIContextMenu*)event.GUIEvent.Caller;
            s32 cmdID = menu->getItemCommandId(menu->getSelectedItem());

            if(event.GUIEvent.EventType == EGET_ELEMENT_CLOSED)
            {
                g_debug_menu_visible = false;
            }

            if (event.GUIEvent.EventType == gui::EGET_MENU_ITEM_SELECTED)
            {
                if(cmdID == DEBUG_GRAPHICS_RELOAD_SHADERS)
                {
                    Log::info("Debug", "Reloading shaders...");
                    irr_driver->updateShaders();
                }
                else if (cmdID == DEBUG_GRAPHICS_RESET)
                {
                    World* world = World::getWorld();
                    if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);

                    irr_driver->resetDebugModes();
                }
                else if (cmdID == DEBUG_GRAPHICS_WIREFRAME)
                {
                    World* world = World::getWorld();
                    if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);

                    irr_driver->resetDebugModes();
                    irr_driver->toggleWireframe();
                }
                else if (cmdID == DEBUG_GRAPHICS_MIPMAP_VIZ)
                {
                    World* world = World::getWorld();
                    if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);

                    irr_driver->resetDebugModes();
                    irr_driver->toggleMipVisualization();
                }
                else if (cmdID == DEBUG_GRAPHICS_NORMALS_VIZ)
                {
                    World* world = World::getWorld();
                    if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);

                    irr_driver->resetDebugModes();
                    irr_driver->toggleNormals();
                }
                else if (cmdID == DEBUG_GRAPHICS_SSAO_VIZ)
                {
                    World* world = World::getWorld();
                    if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);

                    irr_driver->resetDebugModes();
                    irr_driver->toggleSSAOViz();
                }
                else if (cmdID == DEBUG_GRAPHICS_RSM_VIZ)
                {
                    World* world = World::getWorld();
                    if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);

                    irr_driver->resetDebugModes();
                    irr_driver->toggleRSM();
                }
                else if (cmdID == DEBUG_GRAPHICS_RH_VIZ)
                {
                    World* world = World::getWorld();
                    if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);

                    irr_driver->resetDebugModes();
                    irr_driver->toggleRH();
                }
                else if (cmdID == DEBUG_GRAPHICS_GI_VIZ)
                {
                    World* world = World::getWorld();
                    if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);

                    irr_driver->resetDebugModes();
                    irr_driver->toggleGI();
                }
                else if (cmdID == DEBUG_GRAPHICS_SHADOW_VIZ)
                {
                    World* world = World::getWorld();
                    if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);

                    irr_driver->resetDebugModes();
                    irr_driver->toggleShadowViz();
                }
                else if (cmdID == DEBUG_GRAPHICS_LIGHT_VIZ)
                {
                    World* world = World::getWorld();
                    if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);

                    irr_driver->resetDebugModes();
                    irr_driver->toggleLightViz();
                }
                else if (cmdID == DEBUG_GRAPHICS_DISTORT_VIZ)
                {
                    World* world = World::getWorld();
                    if (world != NULL) world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NONE);

                    irr_driver->resetDebugModes();
                    irr_driver->toggleDistortViz();
                }
                else if (cmdID == DEBUG_GRAPHICS_BULLET_1)
                {
                    irr_driver->resetDebugModes();

                    World* world = World::getWorld();
                    if (world == NULL) return false;
                    world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_KARTS_PHYSICS);
                }
                else if (cmdID == DEBUG_GRAPHICS_BULLET_2)
                {
                    irr_driver->resetDebugModes();

                    World* world = World::getWorld();
                    if (world == NULL) return false;
                    world->getPhysics()->setDebugMode(IrrDebugDrawer::DM_NO_KARTS_GRAPHICS);
                }
                else if (cmdID == DEBUG_PROFILER)
                {
                    UserConfigParams::m_profiler_enabled =
                                            !UserConfigParams::m_profiler_enabled;
                }
                else if (cmdID == DEBUG_PROFILER_GENERATE_REPORT)
                {
                    profiler.setCaptureReport(!profiler.getCaptureReport());
                }
                else if (cmdID == DEBUG_THROTTLE_FPS)
                {
                    main_loop->setThrottleFPS(false);
                }
                else if (cmdID == DEBUG_FPS)
                {
                    UserConfigParams::m_display_fps =
                                        !UserConfigParams::m_display_fps;
                }
                else if (cmdID == DEBUG_SAVE_REPLAY)
                {
                    ReplayRecorder::get()->Save();
                }
                else if (cmdID == DEBUG_SAVE_HISTORY)
                {
                    history->Save();
                }
                else if (cmdID == DEBUG_POWERUP_BOWLING)
                {
                    addPowerup(PowerupManager::POWERUP_BOWLING);
                }
                else if (cmdID == DEBUG_POWERUP_BUBBLEGUM)
                {
                    addPowerup(PowerupManager::POWERUP_BUBBLEGUM);
                }
                else if (cmdID == DEBUG_POWERUP_CAKE)
                {
                    addPowerup(PowerupManager::POWERUP_CAKE);
                }
                else if (cmdID == DEBUG_POWERUP_PARACHUTE)
                {
                    addPowerup(PowerupManager::POWERUP_PARACHUTE);
                }
                else if (cmdID == DEBUG_POWERUP_PLUNGER)
                {
                    addPowerup(PowerupManager::POWERUP_PLUNGER);
                }
                else if (cmdID == DEBUG_POWERUP_RUBBERBALL)
                {
                    addPowerup(PowerupManager::POWERUP_RUBBERBALL);
                }
                else if (cmdID == DEBUG_POWERUP_SWATTER)
                {
                    addPowerup(PowerupManager::POWERUP_SWATTER);
                }
                else if (cmdID == DEBUG_POWERUP_SWITCH)
                {
                    addPowerup(PowerupManager::POWERUP_SWITCH);
                }
                else if (cmdID == DEBUG_POWERUP_ZIPPER)
                {
                    addPowerup(PowerupManager::POWERUP_ZIPPER);
                }
                else if (cmdID == DEBUG_POWERUP_NITRO)
                {
                    World* world = World::getWorld();
                    if (world == NULL) return false;
                    for(unsigned int i = 0; i < race_manager->getNumLocalPlayers(); i++)
                    {
                        AbstractKart* kart = world->getLocalPlayerKart(i);
                        kart->setEnergy(100.0f);
                    }
                }
                else if (cmdID == DEBUG_ATTACHMENT_ANVIL)
                {
                    addAttachment(Attachment::ATTACH_ANVIL);
                }
                else if (cmdID == DEBUG_ATTACHMENT_BOMB)
                {
                    addAttachment(Attachment::ATTACH_BOMB);
                }
                else if (cmdID == DEBUG_ATTACHMENT_PARACHUTE)
                {
                    addAttachment(Attachment::ATTACH_PARACHUTE);
                }
                else if (cmdID == DEBUG_TOGGLE_GUI)
                {
                    World* world = World::getWorld();
                    if (world == NULL) return false;
                    RaceGUIBase* gui = world->getRaceGUI();
                    if (gui != NULL) gui->m_enabled = !gui->m_enabled;
                }
                else if (cmdID == DEBUG_HIDE_KARTS)
                {
                    World* world = World::getWorld();
                    if (world == NULL) return false;
                    const int count = World::getWorld()->getNumKarts();
                    for (int n = 0; n<count; n++)
                    {
                        AbstractKart* kart = world->getKart(n);
                        if (kart->getController()->isPlayerController())
                            kart->getNode()->setVisible(false);
                    }
                }
                else if (cmdID == DEBUG_VISUAL_VALUES)
                {
#if !defined(__APPLE__)
                    DebugSliderDialog *dsd = new DebugSliderDialog();
                    dsd->setSliderHook( "red_slider", 0, 255, [](){ return irr_driver->getAmbientLight().r * 255.f; },
                        [](int v){
                            video::SColorf ambient = irr_driver->getAmbientLight();
                            ambient.setColorComponentValue(0, v / 255.f);
                            irr_driver->setAmbientLight(ambient); }
                    );
                    dsd->setSliderHook("green_slider", 0, 255, [](){ return irr_driver->getAmbientLight().g * 255.f; },
                        [](int v){
                        video::SColorf ambient = irr_driver->getAmbientLight();
                        ambient.setColorComponentValue(1, v / 255.f);
                        irr_driver->setAmbientLight(ambient); }
                    );
                    dsd->setSliderHook("blue_slider", 0, 255, [](){ return irr_driver->getAmbientLight().b * 255.f; },
                        [](int v){
                        video::SColorf ambient = irr_driver->getAmbientLight();
                        ambient.setColorComponentValue(2, v / 255.f);
                        irr_driver->setAmbientLight(ambient); }
                    );
                    dsd->setSliderHook("ssao_radius", 0, 100, [](){ return irr_driver->getSSAORadius() * 10.f; },
                        [](int v){irr_driver->setSSAORadius(v / 10.f); }
                    );
                    dsd->setSliderHook("ssao_k", 0, 100, [](){ return irr_driver->getSSAOK() * 10.f; },
                        [](int v){irr_driver->setSSAOK(v / 10.f); }
                    );
                    dsd->setSliderHook("ssao_sigma", 0, 100, [](){ return irr_driver->getSSAOSigma() * 10.f; },
                        [](int v){irr_driver->setSSAOSigma(v / 10.f); }
                    );
#endif
                }
            }

            return false;   // event has been handled
        }
    }
    return true;    // continue event handling
}
Esempio n. 13
0
/** Handles the conversion from some input to a GameAction and its distribution
 * to the currently active menu.
 * It also handles whether the game is currently sensing input. It does so by
 * suppressing the distribution of the input as a GameAction. Instead the
 * input is stored in 'm_sensed_input' and GA_SENSE_COMPLETE is distributed. If
 * however the input in question has resolved to GA_LEAVE this is treated as
 * an attempt of the user to cancel the sensing. In that case GA_SENSE_CANCEL
 * is distributed.
 *
 * Note: It is the obligation of the called menu to switch of the sense mode.
 *
 */
void InputManager::dispatchInput(Input::InputType type, int deviceID, 
                                 int button, 
                                 Input::AxisDirection axisDirection, int value)
{
    // Act different in input sensing mode.
    if (m_mode == INPUT_SENSE_KEYBOARD ||
        m_mode == INPUT_SENSE_GAMEPAD)
    {
        inputSensing(type, deviceID, button, axisDirection,  value);
        return;
    }
    
    // Abort demo mode if a key is pressed during the race in demo mode
    if(dynamic_cast<DemoWorld*>(World::getWorld()))
    {
        race_manager->exitRace();
        StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance());
        return;
    }

    StateManager::ActivePlayer*   player = NULL;
    PlayerAction    action;
    bool action_found = m_device_manager->translateInput(type, deviceID, 
                                                         button, axisDirection,
                                                         value, m_mode, 
                                                         &player, &action);

    // in menus, some keyboard keys are standard (before each player selected 
    // his device). So if a key could not be mapped to any known binding, 
    // fall back to check the defaults.
    if (!action_found && 
            StateManager::get()->getGameState() != GUIEngine::GAME && 
            type == Input::IT_KEYBOARD &&
            m_mode == MENU && m_device_manager->getAssignMode() == NO_ASSIGN)
    {
        action = PA_BEFORE_FIRST;

        if      (button == KEY_UP)     action = PA_MENU_UP;
        else if (button == KEY_DOWN)   action = PA_MENU_DOWN;
        else if (button == KEY_LEFT)   action = PA_MENU_LEFT;
        else if (button == KEY_RIGHT)  action = PA_MENU_RIGHT;
        else if (button == KEY_SPACE)  action = PA_MENU_SELECT;
        else if (button == KEY_RETURN) action = PA_MENU_SELECT;

        if (button == KEY_RETURN && GUIEngine::ModalDialog::isADialogActive())
        {
            GUIEngine::ModalDialog::onEnterPressed();
        }
        
        if (action != PA_BEFORE_FIRST)
        {
            action_found = true;
            player = NULL;
        }
    }
    
    // do something with the key if it matches a binding
    if (action_found)
    {
        // If we're in the kart menu awaiting new players, do special things
        // when a device presses fire or rescue
        if (m_device_manager->getAssignMode() == DETECT_NEW)
        {            
            // Player is unjoining
            if ((player != NULL) && (action == PA_RESCUE || 
                                     action == PA_MENU_CANCEL ) )
            {
                // returns true if the event was handled
                if (KartSelectionScreen::getInstance()->playerQuit( player ))
                {
                    return; // we're done here
                }
            }

            /* The way this is currently structured, any time an event is
               received from an input device that is not associated with a
               player and the device manager is in DETECT_NEW mode, the event
               is ignored, unless it is a PA_FIRE event (a player is joining)

               perhaps it will be good to let unassigned devices back out
               of the kart selection menu?
            */

            else if (player == NULL)
            {
                // New player is joining
                if (action == PA_FIRE || action == PA_MENU_SELECT)
                {
                    InputDevice *device = NULL;
                    if (type == Input::IT_KEYBOARD)
                    {
                        //std::cout << "==== New Player Joining with Key " << 
                        // button << " ====" << std::endl;
                        device = m_device_manager->getKeyboardFromBtnID(button);
                    }
                    else if (type == Input::IT_STICKBUTTON || 
                             type == Input::IT_STICKMOTION    )
                    {
                        device = m_device_manager->getGamePadFromIrrID(deviceID);
                    }

                    if (device != NULL)
                    {
                        KartSelectionScreen::getInstance()->playerJoin(device, 
                                                                       false );
                    }
                }
                return; // we're done here, ignore devices that aren't 
                        // associated with players
            }
        }

        // ... when in-game
        if (StateManager::get()->getGameState() == GUIEngine::GAME && 
             !GUIEngine::ModalDialog::isADialogActive()                  )
        {
            if (player == NULL)
            {
                // Prevent null pointer crash
                return;
            }

            // Find the corresponding PlayerKart from our ActivePlayer instance
            AbstractKart* pk = player->getKart();

            if (pk == NULL)
            {
                std::cerr <<
                    "Error, trying to process action for an unknown player\n";
                return;
            }
            
            Controller* controller = pk->getController();
            if (controller != NULL) controller->action(action, abs(value));
        }
        // ... when in menus
        else
        {

            // reset timer when released
            if (abs(value) == 0 &&  type == Input::IT_STICKBUTTON)
            {
                m_timer_in_use = false;
                m_timer = 0;
            }

            // When in master-only mode, we can safely assume that players 
            // are set up, contrarly to early menus where we accept every 
            // input because players are not set-up yet
            if (m_master_player_only && player == NULL)
            {
                if (type == Input::IT_STICKMOTION || 
                    type == Input::IT_STICKBUTTON)
                {
                    GamePadDevice* gp = 
                        getDeviceList()->getGamePadFromIrrID(deviceID);

                    if (gp != NULL &&
                        abs(value)>gp->m_deadzone)
                    {
                        //I18N: message shown when an input device is used but
                        // is not associated to any player
                        GUIEngine::showMessage(
                            _("Ignoring '%s', you needed to join earlier to play!",
                            irr::core::stringw(gp->m_name.c_str()).c_str())      );
                    }
                }
                return;
            }
            
            // menu input
            if (!m_timer_in_use)
            {
                if (abs(value) > Input::MAX_VALUE*2/3)
                {
                    m_timer_in_use = true;
                    m_timer = 0.25;
                }
                                
                // player may be NULL in early menus, before player setup has 
                // been performed
                int playerID = (player == NULL ? 0 : player->getID());
                
                // If only the master player can act, and this player is not 
                // the master, ignore his input
                if (m_device_manager->getAssignMode() == ASSIGN && 
                    m_master_player_only &&
                    playerID != PLAYER_ID_GAME_MASTER)
                {
                    //I18N: message shown when a player that isn't game master
                    //I18N: tries to modify options that only the game master 
                    //I18N: is allowed to
                    GUIEngine::showMessage(
                        _("Only the Game Master may act at this point!"));
                    return;
                }
                
                // all is good, pass the translated input event on to the 
                // event handler
                GUIEngine::EventHandler::get()
                    ->processGUIAction(action, deviceID, abs(value), type, 
                                       playerID);
            }
        }
    }
    else if (type == Input::IT_KEYBOARD)
    {
        // keyboard press not handled by device manager / bindings. 
        // Check static bindings...
        handleStaticAction( button, value );
    }
}   // input
Esempio n. 14
0
/** Updates the physics simulation and handles all collisions.
 *  \param dt Time step.
 */
void Physics::update(float dt)
{
    PROFILER_PUSH_CPU_MARKER("Physics", 0, 0, 0);

    m_physics_loop_active = true;
    // Bullet can report the same collision more than once (up to 4
    // contact points per collision). Additionally, more than one internal
    // substep might be taken, resulting in potentially even more
    // duplicates. To handle this, all collisions (i.e. pair of objects)
    // are stored in a vector, but only one entry per collision pair
    // of objects.
    m_all_collisions.clear();

    // Maximum of three substeps. This will work for framerate down to
    // 20 FPS (bullet default frequency is 60 HZ).
    m_dynamics_world->stepSimulation(dt, 3);

    // Now handle the actual collision. Note: flyables can not be removed
    // inside of this loop, since the same flyables might hit more than one
    // other object. So only a flag is set in the flyables, the actual
    // clean up is then done later in the projectile manager.
    std::vector<CollisionPair>::iterator p;
    for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
    {
        // Kart-kart collision
        // --------------------
        if(p->getUserPointer(0)->is(UserPointer::UP_KART))
        {
            KartKartCollision(p->getUserPointer(0)->getPointerKart(),
                              p->getContactPointCS(0),
                              p->getUserPointer(1)->getPointerKart(),
                              p->getContactPointCS(1)                );
            Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
            int kartid1 = p->getUserPointer(0)->getPointerKart()->getWorldKartId();
            int kartid2 = p->getUserPointer(1)->getPointerKart()->getWorldKartId();
            script_engine->runFunction("void onKartKartCollision(int, int)",
                [=](asIScriptContext* ctx) {
                    ctx->SetArgDWord(0, kartid1);
                    ctx->SetArgDWord(1, kartid2);
                });
            continue;
        }  // if kart-kart collision

        if(p->getUserPointer(0)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Kart hits physical object
            // -------------------------
            Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
            AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
            int kartId = kart->getWorldKartId();
            PhysicalObject* obj = p->getUserPointer(0)->getPointerPhysicalObject();
            std::string obj_id = obj->getID();
            std::string scripting_function = obj->getOnKartCollisionFunction();
            if (scripting_function.size() > 0)
            {
                script_engine->runFunction("void " + scripting_function + "(int, const string)",
                    [&](asIScriptContext* ctx) {
                        ctx->SetArgDWord(0, kartId);
                        ctx->SetArgObject(1, &obj_id);
                    });
            }
            if (obj->isCrashReset())
            {
                new RescueAnimation(kart);
            }
            else if (obj->isExplodeKartObject())
            {
                ExplosionAnimation::create(kart);
            }
            else if (obj->isFlattenKartObject())
            {
                const KartProperties* kp = kart->getKartProperties();
                kart->setSquash(kp->getSquashDuration() * kart->getPlayerDifficulty()->getSquashDuration(),
                    kp->getSquashSlowdown() * kart->getPlayerDifficulty()->getSquashSlowdown());
            }
            else if(obj->isSoccerBall() && 
                    race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
            {
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setLastKartTohitBall(kartId);
            }
            continue;
        }

        if (p->getUserPointer(0)->is(UserPointer::UP_ANIMATION))
        {
            // Kart hits animation
            ThreeDAnimation *anim=p->getUserPointer(0)->getPointerAnimation();
            if(anim->isCrashReset())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                new RescueAnimation(kart);
            }
            else if (anim->isExplodeKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                ExplosionAnimation::create(kart);
            }
            else if (anim->isFlattenKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                const KartProperties* kp = kart->getKartProperties();
                kart->setSquash(kp->getSquashDuration() * kart->getPlayerDifficulty()->getSquashDuration(),
                    kp->getSquashSlowdown() * kart->getPlayerDifficulty()->getSquashSlowdown());
            }
            continue;

        }
        // now the first object must be a projectile
        // =========================================
        if(p->getUserPointer(1)->is(UserPointer::UP_TRACK))
        {
            // Projectile hits track
            // ---------------------
            p->getUserPointer(0)->getPointerFlyable()->hitTrack();
        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Projectile hits physical object
            // -------------------------------
            Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine();
            Flyable* flyable = p->getUserPointer(0)->getPointerFlyable();
            PhysicalObject* obj = p->getUserPointer(1)->getPointerPhysicalObject();
            std::string obj_id = obj->getID();
            std::string scripting_function = obj->getOnItemCollisionFunction();
            if (scripting_function.size() > 0)
            {
                script_engine->runFunction("void " + scripting_function + "(int, int, const string)",
                        [&](asIScriptContext* ctx) {
                        ctx->SetArgDWord(0, (int)flyable->getType());
                        ctx->SetArgDWord(1, flyable->getOwnerId());
                        ctx->SetArgObject(2, &obj_id);
                    });
            }
            flyable->hit(NULL, obj);

            if (obj->isSoccerBall() && 
                race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
            {
                int kartId = p->getUserPointer(0)->getPointerFlyable()->getOwnerId();
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setLastKartTohitBall(kartId);
            }

        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_KART))
        {
            // Projectile hits kart
            // --------------------
            // Only explode a bowling ball if the target is
            // not invulnerable
            AbstractKart* target_kart = p->getUserPointer(1)->getPointerKart();
            PowerupManager::PowerupType type = p->getUserPointer(0)->getPointerFlyable()->getType();
            if(type != PowerupManager::POWERUP_BOWLING || !target_kart->isInvulnerable())
            {
                Flyable *f = p->getUserPointer(0)->getPointerFlyable();
                f->hit(target_kart);

                // Check for achievements
                AbstractKart * kart = World::getWorld()->getKart(f->getOwnerId());
                PlayerController *c = dynamic_cast<PlayerController*>(kart->getController());

                // Check that it's not a kart hitting itself (this can
                // happen at the time a flyable is shot - release too close
                // to the kart, and it's the current player. At this stage
                // only the current player can get achievements.
                if (target_kart != kart && c &&
                    c->getPlayer()->getConstProfile() == PlayerManager::getCurrentPlayer())
                {
                    // Compare the current value of hits with the 'hit' goal value
                    // (otherwise it would be compared with the kart id goal value,
                    // which doesn't exist.
                    PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_ARCH_ENEMY,
                                                       target_kart->getIdent(), 1, "hit");
                    if (type == PowerupManager::POWERUP_BOWLING)
                    {
                        PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_STRIKE,
                                                          "ball", 1);
                    }   // is bowling ball
                }   // if target_kart != kart && is a player kart and is current player
            }

        }
        else
        {
            // Projectile hits projectile
            // --------------------------
            p->getUserPointer(0)->getPointerFlyable()->hit(NULL);
            p->getUserPointer(1)->getPointerFlyable()->hit(NULL);
        }
    }  // for all p in m_all_collisions

    m_physics_loop_active = false;
    // Now remove the karts that were removed while the above loop
    // was active. Now we can safely call removeKart, since the loop
    // is finished and m_physics_world_active is not set anymore.
    for(unsigned int i=0; i<m_karts_to_delete.size(); i++)
        removeKart(m_karts_to_delete[i]);
    m_karts_to_delete.clear();

    PROFILER_POP_CPU_MARKER();
}   // update
Esempio n. 15
0
/** Updates the physics simulation and handles all collisions.
 *  \param ticks Number of physics steps to simulate.
 */
void Physics::update(int ticks)
{
    PROFILER_PUSH_CPU_MARKER("Physics", 0, 0, 0);

    m_physics_loop_active = true;
    // Bullet can report the same collision more than once (up to 4
    // contact points per collision). Additionally, more than one internal
    // substep might be taken, resulting in potentially even more
    // duplicates. To handle this, all collisions (i.e. pair of objects)
    // are stored in a vector, but only one entry per collision pair
    // of objects.
    m_all_collisions.clear();

    // Since the world update (which calls physics update) is called at the
    // fixed frequency necessary for the physics update, we need to do exactly
    // one physic step only.
    double start;
    if(UserConfigParams::m_physics_debug) start = StkTime::getRealTime();

    m_dynamics_world->stepSimulation(stk_config->ticks2Time(1), 1,
                                     stk_config->ticks2Time(1)      );
    if (UserConfigParams::m_physics_debug)
    {
        Log::verbose("Physics", "At %d physics duration %12.8f",
                     World::getWorld()->getTicksSinceStart(),
                     StkTime::getRealTime() - start);
    }

    // Now handle the actual collision. Note: flyables can not be removed
    // inside of this loop, since the same flyables might hit more than one
    // other object. So only a flag is set in the flyables, the actual
    // clean up is then done later in the projectile manager.
    std::vector<CollisionPair>::iterator p;
    for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p)
    {
        // Kart-kart collision
        // --------------------
        if(p->getUserPointer(0)->is(UserPointer::UP_KART))
        {
            KartKartCollision(p->getUserPointer(0)->getPointerKart(),
                              p->getContactPointCS(0),
                              p->getUserPointer(1)->getPointerKart(),
                              p->getContactPointCS(1)                );
            Scripting::ScriptEngine* script_engine =
                                            Scripting::ScriptEngine::getInstance();
            int kartid1 = p->getUserPointer(0)->getPointerKart()->getWorldKartId();
            int kartid2 = p->getUserPointer(1)->getPointerKart()->getWorldKartId();
            script_engine->runFunction(false, "void onKartKartCollision(int, int)",
                [=](asIScriptContext* ctx) {
                    ctx->SetArgDWord(0, kartid1);
                    ctx->SetArgDWord(1, kartid2);
                });
            continue;
        }  // if kart-kart collision

        if(p->getUserPointer(0)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Kart hits physical object
            // -------------------------
            Scripting::ScriptEngine* script_engine = Scripting::ScriptEngine::getInstance();
            AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
            int kartId = kart->getWorldKartId();
            PhysicalObject* obj = p->getUserPointer(0)->getPointerPhysicalObject();
            std::string obj_id = obj->getID();
            std::string scripting_function = obj->getOnKartCollisionFunction();

            TrackObject* to = obj->getTrackObject();
            TrackObject* library = to->getParentLibrary();
            std::string lib_id;
            std::string* lib_id_ptr = NULL;
            if (library != NULL)
                lib_id = library->getID();
            lib_id_ptr = &lib_id;

            if (scripting_function.size() > 0)
            {
                script_engine->runFunction(true, "void " + scripting_function + "(int, const string, const string)",
                    [&](asIScriptContext* ctx) {
                        ctx->SetArgDWord(0, kartId);
                        ctx->SetArgObject(1, lib_id_ptr);
                        ctx->SetArgObject(2, &obj_id);
                    });
            }
            if (obj->isCrashReset())
            {
                new RescueAnimation(kart);
            }
            else if (obj->isExplodeKartObject())
            {
                ExplosionAnimation::create(kart);
                if (kart->getKartAnimation() != NULL)
                {
                    World::getWorld()->kartHit(kart->getWorldKartId());
                }
            }
            else if (obj->isFlattenKartObject())
            {
                const KartProperties *kp = kart->getKartProperties();
                // Count squash only once from original state
                bool was_squashed = kart->isSquashed();
                if (kart->setSquash(kp->getSwatterSquashDuration(),
                    kp->getSwatterSquashSlowdown()) && !was_squashed)
                {
                    World::getWorld()->kartHit(kart->getWorldKartId());
                }
            }
            else if(obj->isSoccerBall() && 
                    race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
            {
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setBallHitter(kartId);
            }
            continue;
        }

        if (p->getUserPointer(0)->is(UserPointer::UP_ANIMATION))
        {
            // Kart hits animation
            ThreeDAnimation *anim=p->getUserPointer(0)->getPointerAnimation();
            if(anim->isCrashReset())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                new RescueAnimation(kart);
            }
            else if (anim->isExplodeKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                ExplosionAnimation::create(kart);
                if (kart->getKartAnimation() != NULL)
                {
                    World::getWorld()->kartHit(kart->getWorldKartId());
                }
            }
            else if (anim->isFlattenKartObject())
            {
                AbstractKart *kart = p->getUserPointer(1)->getPointerKart();
                const KartProperties *kp = kart->getKartProperties();

                // Count squash only once from original state
                bool was_squashed = kart->isSquashed();
                if (kart->setSquash(kp->getSwatterSquashDuration(),
                    kp->getSwatterSquashSlowdown()) && !was_squashed)
                {
                    World::getWorld()->kartHit(kart->getWorldKartId());
                }

            }
            continue;

        }
        // now the first object must be a projectile
        // =========================================
        if(p->getUserPointer(1)->is(UserPointer::UP_TRACK))
        {
            // Projectile hits track
            // ---------------------
            p->getUserPointer(0)->getPointerFlyable()->hitTrack();
        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_PHYSICAL_OBJECT))
        {
            // Projectile hits physical object
            // -------------------------------
            Scripting::ScriptEngine* script_engine = Scripting::ScriptEngine::getInstance();
            Flyable* flyable = p->getUserPointer(0)->getPointerFlyable();
            PhysicalObject* obj = p->getUserPointer(1)->getPointerPhysicalObject();
            std::string obj_id = obj->getID();
            std::string scripting_function = obj->getOnItemCollisionFunction();
            if (scripting_function.size() > 0)
            {
                script_engine->runFunction(true, "void " + scripting_function + "(int, int, const string)",
                        [&](asIScriptContext* ctx) {
                        ctx->SetArgDWord(0, (int)flyable->getType());
                        ctx->SetArgDWord(1, flyable->getOwnerId());
                        ctx->SetArgObject(2, &obj_id);
                    });
            }
            flyable->hit(NULL, obj);

            if (obj->isSoccerBall() && 
                race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
            {
                int kartId = p->getUserPointer(0)->getPointerFlyable()->getOwnerId();
                SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
                soccerWorld->setBallHitter(kartId);
            }

        }
        else if(p->getUserPointer(1)->is(UserPointer::UP_KART))
        {
            // Projectile hits kart
            // --------------------
            // Only explode a bowling ball if the target is
            // not invulnerable
            AbstractKart* target_kart = p->getUserPointer(1)->getPointerKart();
            PowerupManager::PowerupType type = p->getUserPointer(0)->getPointerFlyable()->getType();
            if(type != PowerupManager::POWERUP_BOWLING || !target_kart->isInvulnerable())
            {
                Flyable *f = p->getUserPointer(0)->getPointerFlyable();
                f->hit(target_kart);

                // Check for achievements
                AbstractKart * kart = World::getWorld()->getKart(f->getOwnerId());
                LocalPlayerController *lpc =
                    dynamic_cast<LocalPlayerController*>(kart->getController());

                // Check that it's not a kart hitting itself (this can
                // happen at the time a flyable is shot - release too close
                // to the kart, and it's the current player. At this stage
                // only the current player can get achievements.
                if (target_kart != kart && lpc && lpc->canGetAchievements())
                {
                    if (type == PowerupManager::POWERUP_BOWLING)
                    {
                        PlayerManager::increaseAchievement(AchievementsStatus::BOWLING_HIT, 1);
                        if (race_manager->isLinearRaceMode())
                            PlayerManager::increaseAchievement(AchievementsStatus::BOWLING_HIT_1RACE, 1);
                    }   // is bowling ball
                }   // if target_kart != kart && is a player kart and is current player
            }

        }
        else
        {
            // Projectile hits projectile
            // --------------------------
            p->getUserPointer(0)->getPointerFlyable()->hit(NULL);
            p->getUserPointer(1)->getPointerFlyable()->hit(NULL);
        }
    }  // for all p in m_all_collisions

    m_physics_loop_active = false;
    // Now remove the karts that were removed while the above loop
    // was active. Now we can safely call removeKart, since the loop
    // is finished and m_physics_world_active is not set anymore.
    for(unsigned int i=0; i<m_karts_to_delete.size(); i++)
        removeKart(m_karts_to_delete[i]);
    m_karts_to_delete.clear();

    PROFILER_POP_CPU_MARKER();
}   // update
Esempio n. 16
0
/** Draw players icons and their times (if defined in the current mode).
 *  Also takes care of icon looking different due to plumber, squashing, ...
 */
void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin)
{
    // For now, don't draw player icons when in soccer mode
    const RaceManager::MinorRaceModeType  minor_mode = race_manager->getMinorMode();
    if(minor_mode == RaceManager::MINOR_MODE_SOCCER)
        return;

    int x_base = 10;
    int y_base = 20;
    unsigned int y_space = UserConfigParams::m_height - bottom_margin - y_base;
    // Special case : when 3 players play, use 4th window to display such stuff
    if (race_manager->getNumLocalPlayers() == 3)
    {
        x_base = UserConfigParams::m_width/2 + x_base;
        y_base = UserConfigParams::m_height/2 + y_base;
        y_space = UserConfigParams::m_height - y_base;
    }

    // -2 because that's the spacing further on
    int ICON_PLAYER_WIDTH = y_space / race_manager->getNumberOfKarts() - 2;

    int icon_width_max = (int)(50*(UserConfigParams::m_width/800.0f));
    int icon_width_min = (int)(35*(UserConfigParams::m_height/600.0f));
    if (icon_width_min > icon_width_max)
    {
        int icon_width_tmp = icon_width_max;
        icon_width_max = icon_width_min;
        icon_width_min = icon_width_tmp;
    }

    // Make sure it fits within our boundaries
    if (ICON_PLAYER_WIDTH > icon_width_max) ICON_PLAYER_WIDTH = icon_width_max;
    if (ICON_PLAYER_WIDTH < icon_width_min) ICON_PLAYER_WIDTH = icon_width_min;

    // TODO: Is this absolute treshold necessary?
    if(UserConfigParams::m_height<600)
    {
        ICON_PLAYER_WIDTH = 35;
    }

    // Icon width for the AI karts
    int ICON_WIDTH = ICON_PLAYER_WIDTH * 4 / 5;

    WorldWithRank *world    = (WorldWithRank*)(World::getWorld());
    //initialize m_previous_icons_position
    if(m_previous_icons_position.size()==0)
    {
        for(unsigned int i=0; i<race_manager->getNumberOfKarts(); i++)
        {
            const AbstractKart *kart = world->getKart(i);
            int position = kart->getPosition();
            core::vector2d<s32> pos(x_base,y_base+(position-1)*(ICON_PLAYER_WIDTH+2));
            m_previous_icons_position.push_back(pos);
        }
    }

    int x;
    int y;
    float previous_distance=0.0;//no need to be far ahead, first kart won't try to overlap



    int previous_x=x_base;
    int previous_y=y_base-ICON_PLAYER_WIDTH-2;

    gui::ScalableFont* font = GUIEngine::getFont();
    const unsigned int kart_amount = world->getNumKarts();

    //where is the limit to hide last icons
    int y_icons_limit=UserConfigParams::m_height-bottom_margin-ICON_PLAYER_WIDTH;
    if (race_manager->getNumLocalPlayers() == 3)
        y_icons_limit=UserConfigParams::m_height-ICON_WIDTH;

    world->getKartsDisplayInfo(&m_kart_display_infos);

    for(int position = 1; position <= (int)kart_amount ; position++)
    {
        AbstractKart *kart = world->getKartAtPosition(position);

        if (kart->getPosition() == -1)//if position is not set
        {
            //we use karts ordered by id only
            //(needed for beginning of MINOR_MODE_3_STRIKES)
            kart= world->getKart(position-1);
        }

        if(kart->isEliminated()) continue;
        unsigned int kart_id = kart->getWorldKartId();

        KartIconDisplayInfo &info = m_kart_display_infos[kart_id];
        //x,y is the target position
        int lap = info.lap;

        // In battle mode mode there is no distance along track etc.
        if( minor_mode==RaceManager::MINOR_MODE_3_STRIKES ||
            minor_mode==RaceManager::MINOR_MODE_EASTER_EGG)
        {
            x = x_base;
            y = previous_y+ICON_PLAYER_WIDTH+2;
        }
        else
        {
            LinearWorld *linear_world = (LinearWorld*)(World::getWorld());

            float distance = linear_world->getDistanceDownTrackForKart(kart_id)
                           + linear_world->getTrack()->getTrackLength()*lap;
            if ((position>1) &&
                (previous_distance-distance<m_dist_show_overlap) &&
                (!kart->hasFinishedRace())                          )
            {
                //linear translation : form (0,ICON_PLAYER_WIDTH+2) to
                // (previous_x-x_base+(ICON_PLAYER_WIDTH+2)/2,0)
                x=(int)(x_base+(1-(previous_distance-distance)
                                /m_dist_show_overlap)
                        *(previous_x-x_base+(ICON_PLAYER_WIDTH+2)/2));
                y=(int)(previous_y+(previous_distance-distance)
                        /m_dist_show_overlap*(ICON_PLAYER_WIDTH+2));
            }
            else
            {
                x=x_base;
                y=previous_y+ICON_PLAYER_WIDTH+2;
            }
            previous_distance=distance;
        }   // not three-strike-battle


        previous_x=x;//save coord of the previous kart in list
        previous_y=y;

        //soft movement using previous position:
        x=(int)((x+m_previous_icons_position[kart_id].X*m_icons_inertia)
                /(m_icons_inertia+1));
        y=(int)((y+m_previous_icons_position[kart_id].Y*m_icons_inertia)
                /(m_icons_inertia+1));

        //save position for next time
        m_previous_icons_position[kart_id].X=x;
        m_previous_icons_position[kart_id].Y=y;

        if (y>y_icons_limit)
        {
            //there are too many icons, write "Top 9", to express that
            //there is not everybody shown
            core::recti pos_top;
            pos_top.UpperLeftCorner.Y  = y_base-22;
            pos_top.UpperLeftCorner.X  = x_base;

            static video::SColor color = video::SColor(255, 255, 255, 255);
            pos_top.LowerRightCorner   = pos_top.UpperLeftCorner;

            font->draw(StringUtils::insertValues( m_string_top, position-1 ), pos_top, color);

            break;
        }

        if (m_kart_display_infos[kart_id].m_text.size() > 0)
        {
            core::rect<s32> pos(x+ICON_PLAYER_WIDTH, y+5,
                                x+ICON_PLAYER_WIDTH, y+5);
            core::stringw s=info.m_text.c_str();

            font->draw(s.c_str(), pos, info.m_color, false, false, NULL,
                       true /* ignore RTL */);
        }

        if (info.special_title.size() > 0)
        {
            core::rect<s32> pos(x+ICON_PLAYER_WIDTH, y+5,
                                x+ICON_PLAYER_WIDTH, y+5);
            core::stringw s(info.special_title.c_str());
            font->draw(s.c_str(), pos, info.m_color, false, false, NULL,
                       true /* ignore RTL */);
        }

        // draw icon
        video::ITexture *icon =
        kart->getKartProperties()->getIconMaterial()->getTexture();
        int w =
        kart->getController()->isPlayerController() ? ICON_PLAYER_WIDTH
        : ICON_WIDTH;
        const core::rect<s32> pos(x, y, x+w, y+w);

        //to bring to light the player's icon: add a background
        if (kart->getController()->isPlayerController())
        {
            video::SColor colors[4];
            for (unsigned int i=0;i<4;i++)
            {
                colors[i]=kart->getKartProperties()->getColor();
                colors[i].setAlpha(
                                   100+(int)(100*cos(M_PI/2*i+World::getWorld()->getTime()*2)));
            }
            const core::rect<s32> rect(core::position2d<s32>(0,0),
                                       m_icons_frame->getTexture()->getOriginalSize());
            draw2DImage(
                                                      m_icons_frame->getTexture(), pos, rect,NULL, colors, true);
        }

        // Fixes crash bug, why are certain icons not showing up?
        if (icon  && !kart->getKartAnimation() && !kart->isSquashed())
        {
            const core::rect<s32> rect(core::position2d<s32>(0,0),
                                       icon->getOriginalSize());
            draw2DImage(icon, pos, rect,
                                                      NULL, NULL, true);
        }

        //draw status info - icon fade out in case of rescue/explode

        if (icon  && dynamic_cast<RescueAnimation*>(kart->getKartAnimation()))
        {
            //icon fades to the left
            float t = kart->getKartAnimation()->getAnimationTimer();
            float t_anim=100*sin(0.5f*M_PI*t);
            const core::rect<s32> rect1(core::position2d<s32>(0,0),
                                        icon->getOriginalSize());
            const core::rect<s32> pos1((int)(x-t_anim), y,
                                       (int)(x+w-t_anim), y+w);
            draw2DImage(icon, pos1, rect1,
                                                      NULL, NULL, true);
        }

        if (icon  && !kart->getKartAnimation() && kart->isSquashed() )
        {
            //syncs icon squash with kart squash
            const core::rect<s32> destRect(core::position2d<s32>(x,y+w/4),
                                           core::position2d<s32>(x+w,y+w*3/4));
            const core::rect<s32> sourceRect(core::position2d<s32>(0,0),
                                             icon->getOriginalSize());
            draw2DImage(icon, destRect,
                                                      sourceRect, NULL, NULL,
                                                      true);
        }

        if (icon  &&
            dynamic_cast<ExplosionAnimation*>(kart->getKartAnimation()) )
        {
            //exploses into 4 parts
            float t = kart->getKartAnimation()->getAnimationTimer();
            float t_anim=50.0f*sin(0.5f*M_PI*t);
            u16 icon_size_x=icon->getOriginalSize().Width;
            u16 icon_size_y=icon->getOriginalSize().Height;

            const core::rect<s32> rect1(0, 0, icon_size_x/2,icon_size_y/2);
            const core::rect<s32> pos1((int)(x-t_anim), (int)(y-t_anim),
                                       (int)(x+w/2-t_anim),
                                       (int)(y+w/2-t_anim));
            draw2DImage(icon, pos1, rect1,
                                                      NULL, NULL, true);

            const core::rect<s32> rect2(icon_size_x/2,0,
                                        icon_size_x,icon_size_y/2);
            const core::rect<s32> pos2((int)(x+w/2+t_anim),
                                       (int)(y-t_anim),
                                       (int)(x+w+t_anim),
                                       (int)(y+w/2-t_anim));
            draw2DImage(icon, pos2, rect2,
                                                      NULL, NULL, true);

            const core::rect<s32> rect3(0, icon_size_y/2, icon_size_x/2,icon_size_y);
            const core::rect<s32> pos3((int)(x-t_anim), (int)(y+w/2+t_anim),
                                       (int)(x+w/2-t_anim), (int)(y+w+t_anim));
            draw2DImage(icon, pos3, rect3, NULL, NULL, true);

            const core::rect<s32> rect4(icon_size_x/2,icon_size_y/2,icon_size_x,icon_size_y);
            const core::rect<s32> pos4((int)(x+w/2+t_anim), (int)(y+w/2+t_anim),
                                       (int)(x+w+t_anim), (int)(y+w+t_anim));
            draw2DImage(icon, pos4, rect4, NULL, NULL, true);
        }

        //Plunger
        if (kart->getBlockedByPlungerTime()>0)
        {
            video::ITexture *icon_plunger =
            powerup_manager->getIcon(PowerupManager::POWERUP_PLUNGER)->getTexture();
            if (icon_plunger != NULL)
            {
                const core::rect<s32> rect(core::position2d<s32>(0,0),
                                           icon_plunger->getOriginalSize());
                const core::rect<s32> pos1(x+10, y-10, x+w+10, y+w-10);
                draw2DImage(icon_plunger, pos1,
                                                          rect, NULL, NULL,
                                                          true);
            }
        }
        //attachment
        if (kart->getAttachment()->getType() != Attachment::ATTACH_NOTHING)
        {
            video::ITexture *icon_attachment =
            attachment_manager->getIcon(kart->getAttachment()->getType())
            ->getTexture();
            if (icon_attachment != NULL)
            {
                const core::rect<s32> rect(core::position2d<s32>(0,0),
                                           icon_attachment->getOriginalSize());
                const core::rect<s32> pos1(x-20, y-10, x+w-20, y+w-10);
                draw2DImage(icon_attachment,
                                                          pos1, rect, NULL,
                                                          NULL, true);
            }
        }

    } //next position
}   // drawGlobalPlayerIcons