示例#1
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