2008-09-21 21:52:28 -04:00
|
|
|
// SuperTuxKart - a fun racing game with go-kart
|
|
|
|
// Copyright (C) 2004 SuperTuxKart-Team
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License
|
|
|
|
// as published by the Free Software Foundation; either version 3
|
|
|
|
// of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
2010-02-08 07:59:03 -05:00
|
|
|
#include "modes/world_status.hpp"
|
2009-01-05 17:51:02 -05:00
|
|
|
|
2010-07-06 19:10:47 -04:00
|
|
|
#include "audio/music_manager.hpp"
|
2008-09-21 21:52:28 -04:00
|
|
|
#include "audio/sfx_manager.hpp"
|
|
|
|
#include "audio/sfx_base.hpp"
|
2009-06-11 06:00:43 -04:00
|
|
|
#include "config/stk_config.hpp"
|
2012-05-08 03:07:15 -04:00
|
|
|
#include "graphics/irr_driver.hpp"
|
2010-05-10 19:53:32 -04:00
|
|
|
#include "guiengine/modaldialog.hpp"
|
2012-03-19 16:21:11 -04:00
|
|
|
#include "karts/abstract_kart.hpp"
|
2010-07-06 19:10:47 -04:00
|
|
|
#include "modes/world.hpp"
|
|
|
|
#include "tracks/track.hpp"
|
2008-10-04 13:32:40 -04:00
|
|
|
#include "network/network_manager.hpp"
|
2008-09-21 21:52:28 -04:00
|
|
|
|
2012-05-08 03:07:15 -04:00
|
|
|
#include <irrlicht.h>
|
|
|
|
|
2008-09-21 21:52:28 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-02-08 07:59:03 -05:00
|
|
|
WorldStatus::WorldStatus()
|
2008-09-21 21:52:28 -04:00
|
|
|
{
|
2010-07-06 19:10:47 -04:00
|
|
|
m_clock_mode = CLOCK_CHRONO;
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2011-04-22 20:22:16 -04:00
|
|
|
m_prestart_sound = sfx_manager->createSoundSource("pre_start_race");
|
|
|
|
m_start_sound = sfx_manager->createSoundSource("start_race");
|
2010-07-06 19:10:47 -04:00
|
|
|
m_track_intro_sound = sfx_manager->createSoundSource("track_intro");
|
|
|
|
|
|
|
|
music_manager->stopMusic();
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2012-06-16 15:41:21 -04:00
|
|
|
m_play_racestart_sounds = true;
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2011-09-07 21:27:04 -04:00
|
|
|
IrrlichtDevice *device = irr_driver->getDevice();
|
|
|
|
if (device->getTimer()->isStopped()) device->getTimer()->start();
|
2010-02-08 07:59:03 -05:00
|
|
|
} // WorldStatus
|
2009-08-23 11:42:58 -04:00
|
|
|
|
2008-09-21 21:52:28 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-02-09 04:24:45 -05:00
|
|
|
/** Resets all status information, used when starting a new race.
|
|
|
|
*/
|
2010-02-08 07:59:03 -05:00
|
|
|
void WorldStatus::reset()
|
2008-09-21 21:52:28 -04:00
|
|
|
{
|
2010-02-09 04:24:45 -05:00
|
|
|
m_time = 0.0f;
|
2008-09-21 21:52:28 -04:00
|
|
|
m_auxiliary_timer = 0.0f;
|
2010-07-06 19:10:47 -04:00
|
|
|
// Using SETUP_PHASE will play the track into sfx first, and has no
|
|
|
|
// other side effects.
|
2011-07-05 17:22:50 -04:00
|
|
|
m_phase = UserConfigParams::m_race_now ? RACE_PHASE : SETUP_PHASE;
|
2010-06-06 23:31:41 -04:00
|
|
|
m_previous_phase = UNDEFINED_PHASE;
|
2010-07-06 19:10:47 -04:00
|
|
|
// Just in case that the game is reset during the intro phase
|
|
|
|
m_track_intro_sound->stop();
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2011-09-07 21:27:04 -04:00
|
|
|
IrrlichtDevice *device = irr_driver->getDevice();
|
|
|
|
if (device->getTimer()->isStopped()) device->getTimer()->start();
|
2009-08-23 11:42:58 -04:00
|
|
|
} // reset
|
|
|
|
|
2008-09-21 21:52:28 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-02-09 04:24:45 -05:00
|
|
|
/** Destructor of WorldStatus.
|
|
|
|
*/
|
2010-02-08 07:59:03 -05:00
|
|
|
WorldStatus::~WorldStatus()
|
2008-09-21 21:52:28 -04:00
|
|
|
{
|
|
|
|
sfx_manager->deleteSFX(m_prestart_sound);
|
|
|
|
sfx_manager->deleteSFX(m_start_sound);
|
2010-12-08 17:18:55 -05:00
|
|
|
sfx_manager->deleteSFX(m_track_intro_sound);
|
2011-09-07 21:27:04 -04:00
|
|
|
IrrlichtDevice *device = irr_driver->getDevice();
|
|
|
|
if (device->getTimer()->isStopped()) device->getTimer()->start();
|
2010-02-08 07:59:03 -05:00
|
|
|
} // ~WorldStatus
|
2009-08-23 11:42:58 -04:00
|
|
|
|
2008-09-21 21:52:28 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-02-09 04:24:45 -05:00
|
|
|
/** Sets the clock mode and the initial time of the world clock.
|
|
|
|
* \param mode The new clock mode.
|
|
|
|
* \param initial_time The new initial time for the world clock.
|
|
|
|
*/
|
2010-02-08 07:59:03 -05:00
|
|
|
void WorldStatus::setClockMode(const ClockType mode, const float initial_time)
|
2008-09-21 21:52:28 -04:00
|
|
|
{
|
2010-02-26 14:09:05 -05:00
|
|
|
m_clock_mode = mode;
|
2008-09-21 21:52:28 -04:00
|
|
|
m_time = initial_time;
|
2009-08-23 11:42:58 -04:00
|
|
|
} // setClockMode
|
|
|
|
|
2008-09-21 21:52:28 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-02-17 06:59:51 -05:00
|
|
|
/** Called when the race is finished, but it still leaves some time
|
|
|
|
* for an end of race animation, and potentially let some more AI karts
|
|
|
|
* finish the race.
|
2010-02-09 04:24:45 -05:00
|
|
|
*/
|
2010-02-17 06:59:51 -05:00
|
|
|
void WorldStatus::enterRaceOverState()
|
2008-09-21 21:52:28 -04:00
|
|
|
{
|
2010-07-22 18:49:56 -04:00
|
|
|
// Don't enter race over if it's already race over
|
2010-02-17 06:59:51 -05:00
|
|
|
if( m_phase == DELAY_FINISH_PHASE
|
2010-05-10 19:53:32 -04:00
|
|
|
|| m_phase == RESULT_DISPLAY_PHASE
|
2013-05-29 18:04:35 -04:00
|
|
|
|| m_phase == FINISH_PHASE )
|
2010-07-22 18:49:56 -04:00
|
|
|
return;
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2010-02-17 06:59:51 -05:00
|
|
|
m_phase = DELAY_FINISH_PHASE;
|
|
|
|
m_auxiliary_timer = 0.0f;
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2010-02-17 06:59:51 -05:00
|
|
|
} // enterRaceOverState
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/** Called when it's really over (delay over if any). This function must be
|
|
|
|
* called after all stats were updated from the different modes!
|
|
|
|
*/
|
|
|
|
void WorldStatus::terminateRace()
|
|
|
|
{
|
2008-10-04 13:32:40 -04:00
|
|
|
if(network_manager->getMode()==NetworkManager::NW_SERVER)
|
|
|
|
network_manager->sendRaceResults();
|
2010-02-17 06:59:51 -05:00
|
|
|
} // terminateRace
|
2009-08-23 11:42:58 -04:00
|
|
|
|
2008-09-21 21:52:28 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-02-09 04:24:45 -05:00
|
|
|
/** Updates all status information, called once per frame.
|
|
|
|
* \param dt Duration of time step.
|
|
|
|
*/
|
2010-02-08 07:59:03 -05:00
|
|
|
void WorldStatus::update(const float dt)
|
2008-09-21 21:52:28 -04:00
|
|
|
{
|
|
|
|
switch(m_phase)
|
|
|
|
{
|
|
|
|
// Note: setup phase must be a separate phase, since the race_manager
|
|
|
|
// checks the phase when updating the camera: in the very first time
|
|
|
|
// step dt is large (it includes loading time), so the camera might
|
|
|
|
// tilt way too much. A separate setup phase for the first frame
|
|
|
|
// simplifies this handling
|
|
|
|
case SETUP_PHASE:
|
2013-05-29 18:04:35 -04:00
|
|
|
m_auxiliary_timer = 0.0f;
|
2010-07-06 19:10:47 -04:00
|
|
|
m_phase = TRACK_INTRO_PHASE;
|
2012-06-16 15:41:21 -04:00
|
|
|
if (UserConfigParams::m_music && m_play_racestart_sounds)
|
|
|
|
{
|
2011-02-28 11:19:43 -05:00
|
|
|
m_track_intro_sound->play();
|
2012-06-16 15:41:21 -04:00
|
|
|
}
|
2010-07-06 19:10:47 -04:00
|
|
|
return;
|
|
|
|
case TRACK_INTRO_PHASE:
|
2011-07-07 21:22:43 -04:00
|
|
|
m_auxiliary_timer += dt;
|
|
|
|
// Work around a bug that occurred on linux once:
|
|
|
|
// the sfx_manager kept on reporting that it is playing,
|
|
|
|
// while it was not - so STK would never reach the ready
|
|
|
|
// ... phase. Since the sound effect is about 3 seconds
|
|
|
|
// long, we use the aux timer to force the next phase
|
|
|
|
// after 3.5 seconds.
|
|
|
|
if(m_track_intro_sound->getStatus()==SFXManager::SFX_PLAYING
|
2011-09-13 20:48:49 -04:00
|
|
|
&& m_auxiliary_timer<3.5f)
|
2010-07-06 19:10:47 -04:00
|
|
|
return;
|
2011-07-07 21:22:43 -04:00
|
|
|
m_auxiliary_timer = 0.0f;
|
2012-06-16 15:41:21 -04:00
|
|
|
if (m_play_racestart_sounds) m_prestart_sound->play();
|
2010-07-06 19:10:47 -04:00
|
|
|
m_phase = READY_PHASE;
|
|
|
|
for(unsigned int i=0; i<World::getWorld()->getNumKarts(); i++)
|
|
|
|
World::getWorld()->getKart(i)->startEngineSFX();
|
|
|
|
|
|
|
|
break;
|
2008-09-21 21:52:28 -04:00
|
|
|
case READY_PHASE:
|
|
|
|
if(m_auxiliary_timer>1.0)
|
|
|
|
{
|
2012-06-16 15:41:21 -04:00
|
|
|
if (m_play_racestart_sounds) m_prestart_sound->play();
|
2013-05-29 18:04:35 -04:00
|
|
|
m_phase=SET_PHASE;
|
2008-09-21 21:52:28 -04:00
|
|
|
}
|
|
|
|
m_auxiliary_timer += dt;
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2011-07-01 19:59:25 -04:00
|
|
|
// In artist debug mode, when without opponents, skip the ready/set/go counter faster
|
2013-01-16 21:20:12 -05:00
|
|
|
if (UserConfigParams::m_artist_debug_mode &&
|
|
|
|
race_manager->getNumberOfKarts() == 1 &&
|
|
|
|
race_manager->getTrackName() != "tutorial")
|
2011-07-01 19:59:25 -04:00
|
|
|
m_auxiliary_timer += dt*6;
|
2008-09-21 21:52:28 -04:00
|
|
|
return;
|
|
|
|
case SET_PHASE :
|
2013-05-29 18:04:35 -04:00
|
|
|
if(m_auxiliary_timer>2.0)
|
2008-09-21 21:52:28 -04:00
|
|
|
{
|
|
|
|
// set phase is over, go to the next one
|
2013-05-29 18:04:35 -04:00
|
|
|
m_phase=GO_PHASE;
|
2012-06-16 15:41:21 -04:00
|
|
|
if (m_play_racestart_sounds) m_start_sound->play();
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2011-05-10 21:47:27 -04:00
|
|
|
World::getWorld()->getTrack()->startMusic();
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2008-10-04 13:32:40 -04:00
|
|
|
// event
|
|
|
|
onGo();
|
2008-09-21 21:52:28 -04:00
|
|
|
}
|
|
|
|
m_auxiliary_timer += dt;
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2011-07-01 19:59:25 -04:00
|
|
|
// In artist debug mode, when without opponents, skip the ready/set/go counter faster
|
2013-01-16 21:20:12 -05:00
|
|
|
if (UserConfigParams::m_artist_debug_mode &&
|
|
|
|
race_manager->getNumberOfKarts() == 1 &&
|
|
|
|
race_manager->getTrackName() != "tutorial")
|
2011-07-01 19:59:25 -04:00
|
|
|
m_auxiliary_timer += dt*6;
|
2008-09-21 21:52:28 -04:00
|
|
|
return;
|
|
|
|
case GO_PHASE :
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2011-05-10 21:47:27 -04:00
|
|
|
if (m_auxiliary_timer>2.5f && music_manager->getCurrentMusic())
|
|
|
|
music_manager->startMusic(music_manager->getCurrentMusic());
|
2013-05-29 18:04:35 -04:00
|
|
|
|
|
|
|
if(m_auxiliary_timer>3.0f) // how long to display the 'go' message
|
2011-09-13 20:48:49 -04:00
|
|
|
{
|
2011-07-01 19:59:25 -04:00
|
|
|
m_phase=MUSIC_PHASE;
|
2011-09-13 20:48:49 -04:00
|
|
|
}
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2008-10-04 14:50:45 -04:00
|
|
|
m_auxiliary_timer += dt;
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2011-07-01 19:59:25 -04:00
|
|
|
// In artist debug mode, when without opponents, skip the ready/set/go counter faster
|
|
|
|
if (UserConfigParams::m_artist_debug_mode && race_manager->getNumberOfKarts() == 1)
|
|
|
|
m_auxiliary_timer += dt*6;
|
2008-10-04 14:50:45 -04:00
|
|
|
break;
|
|
|
|
case MUSIC_PHASE:
|
2008-10-06 09:40:11 -04:00
|
|
|
// how long to display the 'music' message
|
|
|
|
if(m_auxiliary_timer>stk_config->m_music_credit_time)
|
2013-05-29 18:04:35 -04:00
|
|
|
m_phase=RACE_PHASE;
|
2008-09-21 21:52:28 -04:00
|
|
|
m_auxiliary_timer += dt;
|
|
|
|
break;
|
2010-05-10 19:53:32 -04:00
|
|
|
case RACE_PHASE:
|
|
|
|
// Nothing to do for race phase, switch to delay finish phase
|
2013-05-29 18:04:35 -04:00
|
|
|
// happens when
|
2010-05-10 19:53:32 -04:00
|
|
|
break;
|
2008-09-21 21:52:28 -04:00
|
|
|
case DELAY_FINISH_PHASE :
|
|
|
|
{
|
|
|
|
m_auxiliary_timer += dt;
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2010-05-10 19:53:32 -04:00
|
|
|
// Change to next phase if delay is over
|
|
|
|
if(m_auxiliary_timer > stk_config->m_delay_finish_time)
|
|
|
|
{
|
2010-06-07 17:40:45 -04:00
|
|
|
m_phase = RESULT_DISPLAY_PHASE;
|
|
|
|
terminateRace();
|
2010-05-10 19:53:32 -04:00
|
|
|
}
|
|
|
|
break;
|
2008-09-21 21:52:28 -04:00
|
|
|
}
|
2013-05-29 18:04:35 -04:00
|
|
|
case RESULT_DISPLAY_PHASE :
|
2013-02-03 17:31:24 -05:00
|
|
|
{
|
2010-05-10 19:53:32 -04:00
|
|
|
break;
|
2013-02-03 17:31:24 -05:00
|
|
|
}
|
2008-09-21 21:52:28 -04:00
|
|
|
case FINISH_PHASE:
|
2010-05-10 19:53:32 -04:00
|
|
|
// Nothing to do here.
|
|
|
|
break;
|
|
|
|
default: break;
|
2008-09-21 21:52:28 -04:00
|
|
|
}
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2010-02-26 14:09:05 -05:00
|
|
|
switch(m_clock_mode)
|
2008-09-21 21:52:28 -04:00
|
|
|
{
|
2010-02-09 04:24:45 -05:00
|
|
|
case CLOCK_CHRONO:
|
2008-09-21 21:52:28 -04:00
|
|
|
m_time += dt;
|
|
|
|
break;
|
2010-02-09 04:24:45 -05:00
|
|
|
case CLOCK_COUNTDOWN:
|
2010-02-26 14:09:05 -05:00
|
|
|
// stop countdown when race is over
|
2010-05-10 19:53:32 -04:00
|
|
|
if (m_phase == RESULT_DISPLAY_PHASE || m_phase == FINISH_PHASE)
|
2010-02-26 14:09:05 -05:00
|
|
|
{
|
|
|
|
m_time = 0.0f;
|
|
|
|
break;
|
|
|
|
}
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2008-09-21 21:52:28 -04:00
|
|
|
m_time -= dt;
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2008-09-21 21:52:28 -04:00
|
|
|
if(m_time <= 0.0)
|
|
|
|
{
|
2008-10-04 13:32:40 -04:00
|
|
|
// event
|
|
|
|
countdownReachedZero();
|
2008-09-21 21:52:28 -04:00
|
|
|
}
|
2013-05-29 18:04:35 -04:00
|
|
|
|
2010-02-26 14:09:05 -05:00
|
|
|
break;
|
2008-09-21 21:52:28 -04:00
|
|
|
default: break;
|
|
|
|
}
|
2010-02-09 04:24:45 -05:00
|
|
|
} // update
|
|
|
|
|
2008-09-21 21:52:28 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-02-09 04:24:45 -05:00
|
|
|
/** Sets the time for the clock.
|
|
|
|
* \param time New time to set.
|
|
|
|
*/
|
2010-02-08 07:59:03 -05:00
|
|
|
void WorldStatus::setTime(const float time)
|
2008-09-21 21:52:28 -04:00
|
|
|
{
|
|
|
|
m_time = time;
|
2010-02-09 04:24:45 -05:00
|
|
|
} // setTime
|
|
|
|
|
2008-09-21 21:52:28 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-05-10 19:53:32 -04:00
|
|
|
/** Pauses the game and switches to the specified phase.
|
|
|
|
* \param phase Phase to switch to.
|
|
|
|
*/
|
|
|
|
void WorldStatus::pause(Phase phase)
|
2008-09-21 21:52:28 -04:00
|
|
|
{
|
2010-06-06 23:31:41 -04:00
|
|
|
assert(m_previous_phase==UNDEFINED_PHASE);
|
2008-09-21 21:52:28 -04:00
|
|
|
m_previous_phase = m_phase;
|
2010-05-10 19:53:32 -04:00
|
|
|
m_phase = phase;
|
2011-09-05 00:14:50 -04:00
|
|
|
IrrlichtDevice *device = irr_driver->getDevice();
|
2011-09-07 21:27:04 -04:00
|
|
|
if (!device->getTimer()->isStopped()) device->getTimer()->stop();
|
2010-02-09 04:24:45 -05:00
|
|
|
} // pause
|
|
|
|
|
2008-09-21 21:52:28 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-05-10 19:53:32 -04:00
|
|
|
/** Switches back from a pause state to the previous state.
|
|
|
|
*/
|
2010-02-08 07:59:03 -05:00
|
|
|
void WorldStatus::unpause()
|
2008-09-21 21:52:28 -04:00
|
|
|
{
|
2010-05-10 19:53:32 -04:00
|
|
|
m_phase = m_previous_phase;
|
|
|
|
// Set m_previous_phase so that we can use an assert
|
|
|
|
// in pause to detect incorrect pause/unpause sequences.
|
2010-06-06 23:31:41 -04:00
|
|
|
m_previous_phase = UNDEFINED_PHASE;
|
2011-09-05 00:14:50 -04:00
|
|
|
IrrlichtDevice *device = irr_driver->getDevice();
|
2011-09-07 21:27:04 -04:00
|
|
|
if (device->getTimer()->isStopped()) device->getTimer()->start();
|
2010-06-06 23:31:41 -04:00
|
|
|
} // unpause
|