2008-09-27 15:43:57 -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.
|
|
|
|
|
|
|
|
#include "modes/linear_world.hpp"
|
2009-07-19 15:50:20 -04:00
|
|
|
#include "states_screens/race_gui.hpp"
|
2009-03-13 09:50:24 -04:00
|
|
|
|
2009-01-23 00:23:22 -05:00
|
|
|
#include <sstream>
|
|
|
|
|
2010-04-21 13:24:02 -04:00
|
|
|
#include "audio/music_manager.hpp"
|
2010-03-29 18:21:34 -04:00
|
|
|
#include "network/network_manager.hpp"
|
|
|
|
#include "race/history.hpp"
|
2009-01-22 17:27:13 -05:00
|
|
|
#include "tracks/track.hpp"
|
|
|
|
#include "utils/constants.hpp"
|
2009-07-08 08:34:39 -04:00
|
|
|
#include "utils/string_utils.hpp"
|
2009-01-23 00:23:22 -05:00
|
|
|
#include "utils/translation.hpp"
|
2008-09-27 15:43:57 -04:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
LinearWorld::LinearWorld() : World()
|
|
|
|
{
|
2009-01-15 18:05:50 -05:00
|
|
|
m_kart_display_info = NULL;
|
2008-12-15 18:37:25 -05:00
|
|
|
} // LinearWorld
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2008-11-07 21:07:54 -05:00
|
|
|
void LinearWorld::init()
|
|
|
|
{
|
|
|
|
World::init();
|
2010-02-10 17:59:17 -05:00
|
|
|
const unsigned int kart_amount = m_karts.size();
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2009-08-20 20:32:24 -04:00
|
|
|
m_kart_display_info = new RaceGUI::KartIconDisplayInfo[kart_amount];
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
for(unsigned int n=0; n<kart_amount; n++)
|
|
|
|
{
|
|
|
|
KartInfo info;
|
2009-05-21 23:23:48 -04:00
|
|
|
info.m_track_sector = QuadGraph::UNKNOWN_SECTOR;
|
2010-04-14 09:16:32 -04:00
|
|
|
info.m_last_valid_sector = 0;
|
2008-12-25 13:49:34 -05:00
|
|
|
info.m_last_valid_race_lap = -1;
|
2009-07-13 08:22:27 -04:00
|
|
|
info.m_lap_start_time = 0;
|
2010-02-10 17:59:17 -05:00
|
|
|
m_track->getQuadGraph().findRoadSector(m_karts[n]->getXYZ(),
|
2009-05-21 23:23:48 -04:00
|
|
|
&info.m_track_sector);
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
//If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of
|
|
|
|
//the road, so we have to use another function to find the sector.
|
2009-05-21 23:23:48 -04:00
|
|
|
info.m_on_road = info.m_track_sector != QuadGraph::UNKNOWN_SECTOR;
|
2008-12-21 19:33:25 -05:00
|
|
|
if (!info.m_on_road)
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
|
|
|
info.m_track_sector =
|
2010-02-10 17:59:17 -05:00
|
|
|
m_track->getQuadGraph().findOutOfRoadSector(m_karts[n]->getXYZ(),
|
2009-05-27 20:43:12 -04:00
|
|
|
QuadGraph::UNKNOWN_SECTOR );
|
2008-09-27 15:43:57 -04:00
|
|
|
}
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2009-05-21 23:23:48 -04:00
|
|
|
m_track->getQuadGraph().spatialToTrack(&info.m_curr_track_coords,
|
2010-02-10 17:59:17 -05:00
|
|
|
m_karts[n]->getXYZ(),
|
2009-05-21 23:23:48 -04:00
|
|
|
info.m_track_sector );
|
2008-12-15 18:37:25 -05:00
|
|
|
|
2009-09-09 23:25:42 -04:00
|
|
|
info.m_race_lap = -1;
|
2009-07-13 08:22:27 -04:00
|
|
|
info.m_lap_start_time = 0;
|
2008-09-27 15:43:57 -04:00
|
|
|
info.m_time_at_last_lap = 99999.9f;
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
m_kart_info.push_back(info);
|
2008-12-15 18:37:25 -05:00
|
|
|
} // next kart
|
|
|
|
|
|
|
|
} // init
|
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2008-09-30 16:38:11 -04:00
|
|
|
LinearWorld::~LinearWorld()
|
|
|
|
{
|
2009-01-15 18:05:50 -05:00
|
|
|
// In case that a track is not found, m_kart_display info was never
|
|
|
|
// initialised.
|
|
|
|
if(m_kart_display_info)
|
|
|
|
delete[] m_kart_display_info;
|
2008-12-15 18:37:25 -05:00
|
|
|
} // ~LinearWorld
|
|
|
|
|
2008-09-30 16:38:11 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2008-09-29 11:14:14 -04:00
|
|
|
void LinearWorld::restartRace()
|
|
|
|
{
|
|
|
|
World::restartRace();
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2010-02-10 17:59:17 -05:00
|
|
|
const unsigned int kart_amount = m_karts.size();
|
2010-02-14 19:54:28 -05:00
|
|
|
for(unsigned int i=0; i<kart_amount; i++)
|
2008-09-29 11:14:14 -04:00
|
|
|
{
|
2010-02-14 19:54:28 -05:00
|
|
|
KartInfo& info = m_kart_info[i];
|
2009-05-21 23:23:48 -04:00
|
|
|
info.m_track_sector = QuadGraph::UNKNOWN_SECTOR;
|
2010-04-14 09:16:32 -04:00
|
|
|
info.m_last_valid_sector = 0;
|
2009-07-13 08:22:27 -04:00
|
|
|
info.m_lap_start_time = 0;
|
2010-02-14 19:54:28 -05:00
|
|
|
m_track->getQuadGraph().findRoadSector(m_karts[i]->getXYZ(),
|
2009-05-21 23:23:48 -04:00
|
|
|
&info.m_track_sector);
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-29 11:14:14 -04:00
|
|
|
//If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of
|
|
|
|
//the road, so we have to use another function to find the sector.
|
2009-05-21 23:23:48 -04:00
|
|
|
info.m_on_road = info.m_track_sector != QuadGraph::UNKNOWN_SECTOR;
|
2008-12-21 19:33:25 -05:00
|
|
|
if (!info.m_on_road)
|
2008-09-29 11:14:14 -04:00
|
|
|
{
|
|
|
|
info.m_track_sector =
|
2010-02-14 19:54:28 -05:00
|
|
|
m_track->getQuadGraph().findOutOfRoadSector(m_karts[i]->getXYZ(),
|
2010-02-10 17:59:17 -05:00
|
|
|
QuadGraph::UNKNOWN_SECTOR );
|
2008-09-29 11:14:14 -04:00
|
|
|
}
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2009-05-21 23:23:48 -04:00
|
|
|
m_track->getQuadGraph().spatialToTrack(&info.m_curr_track_coords,
|
2010-02-14 19:54:28 -05:00
|
|
|
m_karts[i]->getXYZ(),
|
2009-05-21 23:23:48 -04:00
|
|
|
info.m_track_sector );
|
2009-09-09 23:25:42 -04:00
|
|
|
info.m_race_lap = -1;
|
2009-07-13 08:22:27 -04:00
|
|
|
info.m_lap_start_time = -0;
|
2008-09-29 11:14:14 -04:00
|
|
|
info.m_time_at_last_lap = 99999.9f;
|
2008-11-30 22:58:58 -05:00
|
|
|
} // next kart
|
2010-02-14 19:54:28 -05:00
|
|
|
|
|
|
|
// First all kart infos must be updated before the kart position can be
|
|
|
|
// recomputed, since otherwise 'new' (initialised) valued will be compared
|
|
|
|
// with old values.
|
2010-03-08 13:39:05 -05:00
|
|
|
updateRacePosition();
|
2010-03-07 11:52:20 -05:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
//FIXME: this could be defined somewhere in a central header so it can be used everywhere
|
|
|
|
#define assertExpr( ARG1, OP, ARG2 ) if (!(ARG1 OP ARG2)) \
|
|
|
|
{ \
|
|
|
|
std::cerr << "Failed assert " << #ARG1 << #OP << #ARG2 << " @ " << __FILE__ << ":" << __LINE__ \
|
|
|
|
<< "; values are (" << ARG1 << #OP << ARG2 << ")\n"; \
|
|
|
|
assert(false); \
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned int i=0; i<kart_amount; i++)
|
|
|
|
{
|
|
|
|
for (unsigned int j=i+1; j<kart_amount; j++)
|
|
|
|
{
|
|
|
|
assertExpr( m_karts[i]->getPosition(), !=, m_karts[j]->getPosition() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-11-30 22:58:58 -05:00
|
|
|
} // restartRace
|
2008-12-15 18:37:25 -05:00
|
|
|
|
2008-09-29 11:14:14 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-05-06 19:26:49 -04:00
|
|
|
/** General update function called once per frame. This updates the kart
|
|
|
|
* sectors, which are then used to determine the kart positions.
|
|
|
|
* \param dt Time step size.
|
|
|
|
*/
|
2008-09-27 15:43:57 -04:00
|
|
|
void LinearWorld::update(float delta)
|
2009-08-18 06:33:21 -04:00
|
|
|
{
|
2008-12-15 18:37:25 -05:00
|
|
|
// run generic parent stuff that applies to all modes. It
|
|
|
|
// especially updates the kart positions.
|
2008-09-27 15:43:57 -04:00
|
|
|
World::update(delta);
|
|
|
|
|
2010-02-10 06:40:33 -05:00
|
|
|
const unsigned int kart_amount = getNumKarts();
|
2008-12-15 01:35:17 -05:00
|
|
|
|
2008-12-15 18:37:25 -05:00
|
|
|
// Do stuff specific to this subtype of race.
|
|
|
|
// ------------------------------------------
|
2008-09-27 15:43:57 -04:00
|
|
|
for(unsigned int n=0; n<kart_amount; n++)
|
|
|
|
{
|
|
|
|
KartInfo& kart_info = m_kart_info[n];
|
2010-02-10 17:59:17 -05:00
|
|
|
Kart* kart = m_karts[n];
|
2008-12-21 02:43:41 -05:00
|
|
|
|
2010-02-17 06:59:51 -05:00
|
|
|
// Nothing to do for karts that are currently being rescued or eliminated
|
2010-04-22 09:21:35 -04:00
|
|
|
if(kart->playingEmergencyAnimation()) continue;
|
2008-12-21 02:43:41 -05:00
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
// ---------- deal with sector data ---------
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-29 21:54:09 -04:00
|
|
|
// update sector variables
|
2008-09-27 15:43:57 -04:00
|
|
|
int prev_sector = kart_info.m_track_sector;
|
2009-08-18 06:33:21 -04:00
|
|
|
m_track->getQuadGraph().findRoadSector(kart->getXYZ(),
|
2009-05-21 23:23:48 -04:00
|
|
|
&kart_info.m_track_sector);
|
2009-01-12 19:16:09 -05:00
|
|
|
|
2009-05-21 23:23:48 -04:00
|
|
|
kart_info.m_on_road = kart_info.m_track_sector != QuadGraph::UNKNOWN_SECTOR;
|
2009-05-27 20:43:12 -04:00
|
|
|
if(kart_info.m_on_road)
|
|
|
|
{
|
2009-09-09 23:25:42 -04:00
|
|
|
kart_info.m_last_valid_sector = kart_info.m_track_sector;
|
|
|
|
kart_info.m_last_valid_race_lap = kart_info.m_race_lap;
|
2009-05-27 20:43:12 -04:00
|
|
|
}
|
|
|
|
else
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
2008-12-21 19:33:25 -05:00
|
|
|
// Kart off road. Find the closest sector instead.
|
|
|
|
kart_info.m_track_sector =
|
2009-05-27 20:43:12 -04:00
|
|
|
m_track->getQuadGraph().findOutOfRoadSector(kart->getXYZ(), prev_sector );
|
2009-08-18 06:33:21 -04:00
|
|
|
}
|
|
|
|
|
2008-12-21 02:43:41 -05:00
|
|
|
// Update track coords (=progression)
|
2009-08-18 06:33:21 -04:00
|
|
|
m_track->getQuadGraph().spatialToTrack(&kart_info.m_curr_track_coords,
|
2009-05-21 23:23:48 -04:00
|
|
|
kart->getXYZ(),
|
|
|
|
kart_info.m_track_sector );
|
2008-12-21 02:43:41 -05:00
|
|
|
|
2008-12-15 18:37:25 -05:00
|
|
|
} // for n
|
|
|
|
|
|
|
|
// Update all positions. This must be done after _all_ karts have
|
|
|
|
// updated their position and laps etc, otherwise inconsistencies
|
|
|
|
// (like two karts at same position) can occur.
|
|
|
|
// ---------------------------------------------------------------
|
2010-03-08 13:39:05 -05:00
|
|
|
|
|
|
|
updateRacePosition();
|
|
|
|
|
|
|
|
for (unsigned int i=0; i<kart_amount; i++)
|
2008-12-15 18:37:25 -05:00
|
|
|
{
|
|
|
|
// ---------- update rank ------
|
2010-03-08 13:39:05 -05:00
|
|
|
if (m_karts[i]->hasFinishedRace() || m_karts[i]->isEliminated()) continue;
|
|
|
|
|
2010-02-17 06:59:51 -05:00
|
|
|
// During the last lap update the estimated finish time.
|
|
|
|
// This is used to play the faster music, and by the AI
|
2010-03-08 13:39:05 -05:00
|
|
|
if (m_kart_info[i].m_race_lap == race_manager->getNumLaps()-1)
|
|
|
|
{
|
2010-02-17 06:59:51 -05:00
|
|
|
m_kart_info[i].m_estimated_finish = estimateFinishTimeForKart(m_karts[i]);
|
2010-03-08 13:39:05 -05:00
|
|
|
}
|
2010-02-17 06:59:51 -05:00
|
|
|
checkForWrongDirection(i);
|
2008-12-15 18:37:25 -05:00
|
|
|
}
|
2010-03-08 13:39:05 -05:00
|
|
|
|
2008-12-15 18:37:25 -05:00
|
|
|
#ifdef DEBUG
|
2010-04-11 15:28:53 -04:00
|
|
|
// FIXME: Debug output in case that the double position error occurs again.
|
2008-12-15 18:37:25 -05:00
|
|
|
int pos_used[10];
|
|
|
|
for(int i=0; i<10; i++) pos_used[i]=-99;
|
|
|
|
for(unsigned int i=0; i<kart_amount; i++)
|
|
|
|
{
|
2010-02-10 17:59:17 -05:00
|
|
|
if(pos_used[m_karts[i]->getPosition()]!=-99)
|
2008-12-15 18:37:25 -05:00
|
|
|
{
|
|
|
|
for(unsigned int j =0; j<kart_amount; j++)
|
|
|
|
{
|
2010-04-06 20:26:47 -04:00
|
|
|
printf("kart id=%d, position=%d, finished=%d, laps=%d, distanceDownTrack=%f\n",
|
2010-02-10 17:59:17 -05:00
|
|
|
j, m_karts[j]->getPosition(),
|
|
|
|
m_karts[j]->hasFinishedRace(),
|
2008-12-15 18:37:25 -05:00
|
|
|
m_kart_info[j].m_race_lap,
|
2010-02-10 17:59:17 -05:00
|
|
|
getDistanceDownTrackForKart(m_karts[j]->getWorldKartId()));
|
2008-12-15 18:37:25 -05:00
|
|
|
}
|
|
|
|
}
|
2010-02-10 17:59:17 -05:00
|
|
|
pos_used[m_karts[i]->getPosition()]=i;
|
2008-12-15 18:37:25 -05:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
} // update
|
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2009-09-09 23:25:42 -04:00
|
|
|
/** Is called by check structures if a kart starts a new lap.
|
2009-07-07 20:44:55 -04:00
|
|
|
* \param kart_index Index of the kart.
|
|
|
|
*/
|
|
|
|
void LinearWorld::newLap(unsigned int kart_index)
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
2009-07-13 08:22:27 -04:00
|
|
|
KartInfo &kart_info = m_kart_info[kart_index];
|
2010-02-10 17:59:17 -05:00
|
|
|
Kart *kart = m_karts[kart_index];
|
2009-07-07 20:44:55 -04:00
|
|
|
// 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 <= race_manager->getNumLaps())
|
|
|
|
{
|
2009-09-09 23:25:42 -04:00
|
|
|
assert(kart->getWorldKartId()==kart_index);
|
|
|
|
setTimeAtLapForKart(getTime(), kart_index );
|
2009-07-07 20:44:55 -04:00
|
|
|
kart_info.m_race_lap++ ;
|
|
|
|
}
|
2009-12-23 11:58:10 -05:00
|
|
|
// Last lap message (kart_index's assert in previous block already)
|
|
|
|
if(kart_info.m_race_lap+1 == race_manager->getNumLaps())
|
|
|
|
{
|
2010-02-10 17:59:17 -05:00
|
|
|
m_race_gui->addMessage(_("Final lap!"), m_karts[kart_index],
|
2010-03-06 20:35:57 -05:00
|
|
|
3.0f, 40, video::SColor(255, 210, 100, 50), true);
|
2009-12-23 11:58:10 -05:00
|
|
|
}
|
2010-04-13 20:06:10 -04:00
|
|
|
|
|
|
|
// 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 updateRacePosion will avoid duplicated
|
|
|
|
// race positions as well.
|
|
|
|
updateRacePosition();
|
|
|
|
|
2009-07-07 20:44:55 -04:00
|
|
|
// Race finished
|
|
|
|
if(kart_info.m_race_lap >= race_manager->getNumLaps() && raceHasLaps())
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
2009-07-07 20:44:55 -04:00
|
|
|
// A client wait does not detect race finished by itself, it will
|
|
|
|
// receive a message from the server. So a client does not do
|
|
|
|
// anything here.
|
|
|
|
if(network_manager->getMode()!=NetworkManager::NW_CLIENT)
|
2010-02-14 19:54:28 -05:00
|
|
|
{
|
|
|
|
kart->finishedRace(getTime());
|
|
|
|
}
|
2009-07-07 20:44:55 -04:00
|
|
|
}
|
|
|
|
{
|
|
|
|
float time_per_lap;
|
|
|
|
if (kart_info.m_race_lap == 1) // just completed first lap
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
2009-07-07 20:44:55 -04:00
|
|
|
time_per_lap=getTime();
|
2008-09-27 15:43:57 -04:00
|
|
|
}
|
2009-07-07 20:44:55 -04:00
|
|
|
else //completing subsequent laps
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
2009-07-07 20:44:55 -04:00
|
|
|
time_per_lap=getTime() - kart_info.m_lap_start_time;
|
2008-09-27 15:43:57 -04:00
|
|
|
}
|
2009-07-07 20:44:55 -04:00
|
|
|
|
|
|
|
// if new fastest lap
|
2009-09-09 23:25:42 -04:00
|
|
|
if(time_per_lap < getFastestLapTime() && raceHasLaps() &&
|
|
|
|
kart_info.m_race_lap>0)
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
2009-07-07 20:44:55 -04:00
|
|
|
setFastestLap(kart, time_per_lap);
|
2009-08-18 06:33:21 -04:00
|
|
|
m_race_gui->addMessage(_("New fastest lap"), NULL,
|
2010-03-06 20:35:57 -05:00
|
|
|
2.0f, 40, video::SColor(255, 100, 210, 100), true);
|
2009-07-12 07:54:21 -04:00
|
|
|
std::string s = StringUtils::timeToString(time_per_lap);
|
|
|
|
|
2009-08-30 14:21:59 -04:00
|
|
|
irr::core::stringw m_fastest_lap_message;
|
2010-01-24 10:34:46 -05:00
|
|
|
//I18N: as in "fastest lap: 60 seconds by Wilber"
|
|
|
|
m_fastest_lap_message += StringUtils::insertValues(_("%s by %s"), s.c_str(), kart->getName().c_str()).c_str();
|
2009-12-23 11:58:10 -05:00
|
|
|
|
2009-08-30 14:21:59 -04:00
|
|
|
m_race_gui->addMessage(m_fastest_lap_message, NULL,
|
2009-07-15 23:24:17 -04:00
|
|
|
2.0f, 40, video::SColor(255, 100, 210, 100));
|
2009-07-07 20:44:55 -04:00
|
|
|
} // end if new fastest lap
|
2008-09-27 15:43:57 -04:00
|
|
|
}
|
2009-07-07 20:44:55 -04:00
|
|
|
kart_info.m_lap_start_time = getTime();
|
|
|
|
} // newLap
|
2008-12-15 18:37:25 -05:00
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int LinearWorld::getSectorForKart(const int kart_id) const
|
|
|
|
{
|
|
|
|
return m_kart_info[kart_id].m_track_sector;
|
2008-12-16 08:21:55 -05:00
|
|
|
} // getSectorForKart
|
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-02-23 08:27:01 -05:00
|
|
|
/** Returns the distance the kart has travelled along the track since
|
|
|
|
* crossing the start line..
|
|
|
|
* \param kart_id Index of the kart.
|
|
|
|
*/
|
2008-09-27 15:43:57 -04:00
|
|
|
float LinearWorld::getDistanceDownTrackForKart(const int kart_id) const
|
|
|
|
{
|
2010-02-23 08:27:01 -05:00
|
|
|
return m_kart_info[kart_id].m_curr_track_coords.getZ();
|
2008-12-16 08:21:55 -05:00
|
|
|
} // getDistanceDownTrackForKart
|
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-02-23 08:27:01 -05:00
|
|
|
/** Gets the distance of the kart from the center of the driveline. Positive
|
|
|
|
* is to the right of the center, negative values to the left.
|
|
|
|
* \param kart_id Index of kart.
|
|
|
|
*/
|
2008-09-27 15:43:57 -04:00
|
|
|
float LinearWorld::getDistanceToCenterForKart(const int kart_id) const
|
|
|
|
{
|
|
|
|
return m_kart_info[kart_id].m_curr_track_coords.getX();
|
2008-12-16 08:21:55 -05:00
|
|
|
} // getDistanceToCenterForKart
|
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int LinearWorld::getLapForKart(const int kart_id) const
|
|
|
|
{
|
|
|
|
return m_kart_info[kart_id].m_race_lap;
|
2008-12-16 08:21:55 -05:00
|
|
|
} // getLapForKart
|
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LinearWorld::setTimeAtLapForKart(float t, const int kart_id)
|
|
|
|
{
|
|
|
|
m_kart_info[kart_id].m_time_at_last_lap=t;
|
2008-12-16 08:21:55 -05:00
|
|
|
} // setTimeAtLapForKart
|
|
|
|
|
2008-12-08 18:23:33 -05:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/** Returns the estimated finishing time. Only valid during the last lap!
|
|
|
|
* \param kart_id Id of the kart.
|
|
|
|
*/
|
|
|
|
float LinearWorld::getEstimatedFinishTime(const int kart_id) const
|
|
|
|
{
|
|
|
|
assert(m_kart_info[kart_id].m_race_lap == race_manager->getNumLaps()-1);
|
|
|
|
return m_kart_info[kart_id].m_estimated_finish;
|
|
|
|
} // getEstimatedFinishTime
|
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
float LinearWorld::getTimeAtLapForKart(const int kart_id) const
|
|
|
|
{
|
|
|
|
return m_kart_info[kart_id].m_time_at_last_lap;
|
2008-12-16 08:21:55 -05:00
|
|
|
} // getTimeAtLapForKart
|
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2009-08-20 20:32:24 -04:00
|
|
|
RaceGUI::KartIconDisplayInfo* LinearWorld::getKartsDisplayInfo()
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
|
|
|
int laps_of_leader = -1;
|
|
|
|
float time_of_leader = -1;
|
|
|
|
// Find the best time for the lap. We can't simply use
|
|
|
|
// the time of the kart at position 1, since the kart
|
|
|
|
// might have been overtaken by now
|
2010-02-10 06:40:33 -05:00
|
|
|
const unsigned int kart_amount = getNumKarts();
|
2008-09-27 15:43:57 -04:00
|
|
|
for(unsigned int i = 0; i < kart_amount ; i++)
|
|
|
|
{
|
2009-08-20 20:32:24 -04:00
|
|
|
RaceGUI::KartIconDisplayInfo& rank_info = m_kart_display_info[i];
|
2010-02-10 17:59:17 -05:00
|
|
|
Kart* kart = m_karts[i];
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
// reset color
|
|
|
|
rank_info.r = 1.0;
|
|
|
|
rank_info.g = 1.0;
|
|
|
|
rank_info.b = 1.0;
|
|
|
|
rank_info.lap = -1;
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
if(kart->isEliminated()) continue;
|
|
|
|
const float lap_time = getTimeAtLapForKart(kart->getWorldKartId());
|
|
|
|
const int current_lap = getLapForKart( kart->getWorldKartId() );
|
|
|
|
rank_info.lap = current_lap;
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
if(current_lap > laps_of_leader)
|
|
|
|
{
|
|
|
|
// more laps than current leader --> new leader and new time computation
|
|
|
|
laps_of_leader = current_lap;
|
|
|
|
time_of_leader = lap_time;
|
|
|
|
} else if(current_lap == laps_of_leader)
|
|
|
|
{
|
|
|
|
// Same number of laps as leader: use fastest time
|
|
|
|
time_of_leader=std::min(time_of_leader,lap_time);
|
|
|
|
}
|
2008-09-30 21:15:34 -04:00
|
|
|
}
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-30 21:15:34 -04:00
|
|
|
// we now know the best time of the lap. fill the remaining bits of info
|
|
|
|
for(unsigned int i = 0; i < kart_amount ; i++)
|
2009-08-18 06:33:21 -04:00
|
|
|
{
|
2009-08-20 20:32:24 -04:00
|
|
|
RaceGUI::KartIconDisplayInfo& rank_info = m_kart_display_info[i];
|
2008-09-30 21:15:34 -04:00
|
|
|
KartInfo& kart_info = m_kart_info[i];
|
2010-02-10 17:59:17 -05:00
|
|
|
Kart* kart = m_karts[i];
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-30 21:15:34 -04:00
|
|
|
const int position = kart->getPosition();
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-30 20:46:00 -04:00
|
|
|
if(laps_of_leader>0 && // Don't compare times when crossing the start line first
|
2008-09-30 21:15:34 -04:00
|
|
|
(getTime() - getTimeAtLapForKart(kart->getWorldKartId())<5.0f || rank_info.lap != laps_of_leader) &&
|
2008-12-16 04:02:14 -05:00
|
|
|
raceHasLaps())
|
2008-09-27 15:43:57 -04:00
|
|
|
{ // Display for 5 seconds
|
2009-07-08 08:34:39 -04:00
|
|
|
std::string str;
|
2009-08-30 14:21:59 -04:00
|
|
|
if(position == 1)
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
2009-08-30 14:21:59 -04:00
|
|
|
str = " " + StringUtils::timeToString( getTimeAtLapForKart(kart->getWorldKartId()) );
|
2008-09-27 15:43:57 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float timeBehind;
|
2009-08-18 06:33:21 -04:00
|
|
|
timeBehind = (kart_info.m_race_lap==laps_of_leader
|
|
|
|
? getTimeAtLapForKart(kart->getWorldKartId())
|
2008-12-16 04:02:14 -05:00
|
|
|
: getTime())
|
|
|
|
- time_of_leader;
|
2009-08-30 14:21:59 -04:00
|
|
|
str = "+" + StringUtils::timeToString(timeBehind);
|
2008-09-27 15:43:57 -04:00
|
|
|
}
|
2010-03-31 19:49:42 -04:00
|
|
|
rank_info.m_text = irr::core::stringw(str.c_str());
|
2008-09-27 15:43:57 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-03-31 19:49:42 -04:00
|
|
|
rank_info.m_text = "";
|
2008-09-27 15:43:57 -04:00
|
|
|
}
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
int numLaps = race_manager->getNumLaps();
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
if(kart_info.m_race_lap>=numLaps)
|
|
|
|
{ // kart is finished, display in green
|
|
|
|
rank_info.g = rank_info.b = 0;
|
|
|
|
}
|
|
|
|
else if(kart_info.m_race_lap>=0 && numLaps>1)
|
|
|
|
{
|
|
|
|
rank_info.g = rank_info.b = 1.0f-(float)kart_info.m_race_lap/((float)numLaps-1.0f);
|
|
|
|
}
|
|
|
|
} // next kart
|
2009-08-18 06:33:21 -04:00
|
|
|
|
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
return m_kart_display_info;
|
2008-12-16 08:21:55 -05:00
|
|
|
} // getKartsDisplayInfo
|
|
|
|
|
2008-12-16 04:02:14 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
2010-02-10 06:40:33 -05:00
|
|
|
/** Sets up the mapping from kart position to kart index.
|
|
|
|
*/
|
2010-03-07 11:52:20 -05:00
|
|
|
void LinearWorld::raceResultOrder( int order[] )
|
2008-10-16 15:53:37 -04:00
|
|
|
{
|
2010-02-10 06:40:33 -05:00
|
|
|
const unsigned int NUM_KARTS = getNumKarts();
|
2010-03-07 11:52:20 -05:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
for (unsigned int i=0; i < NUM_KARTS; i++)
|
2008-10-16 15:53:37 -04:00
|
|
|
{
|
2010-03-07 11:52:20 -05:00
|
|
|
order[i] = -1;
|
|
|
|
}
|
2010-03-27 14:11:00 -04:00
|
|
|
|
|
|
|
bool positions_ok = true;
|
2010-03-07 11:52:20 -05:00
|
|
|
#endif
|
|
|
|
|
|
|
|
for (unsigned int i=0; i < NUM_KARTS; i++)
|
|
|
|
{
|
|
|
|
const int position = getKart(i)->getPosition()-1;
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
// sanity checks
|
|
|
|
if (order[position] != -1)
|
|
|
|
{
|
|
|
|
std::cerr << "== TWO KARTS ARE BEING GIVEN THE SAME POSITION!! ==\n";
|
|
|
|
for (unsigned int j=0; j < NUM_KARTS; j++)
|
|
|
|
{
|
|
|
|
if (order[j] == -1)
|
|
|
|
{
|
|
|
|
std::cout << " No kart is yet set at position " << j << std::endl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::cout << " Kart " << order[j] << " is at position " << j << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::cout << "Kart " << i << " is being given posiiton " << (getKart(i)->getPosition()-1)
|
|
|
|
<< ", but this position is already taken\n";
|
2010-03-27 14:11:00 -04:00
|
|
|
positions_ok = false;
|
2010-03-07 11:52:20 -05:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// actually assign the position
|
|
|
|
order[position] = i; // even for eliminated karts
|
2008-10-16 15:53:37 -04:00
|
|
|
}
|
2010-03-27 14:11:00 -04:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
2010-03-29 18:21:34 -04:00
|
|
|
if (!positions_ok) history->Save();
|
2010-03-27 14:11:00 -04:00
|
|
|
assert(positions_ok);
|
|
|
|
#endif
|
|
|
|
|
2008-12-16 08:21:55 -05:00
|
|
|
} // raceResultOrder
|
|
|
|
|
2008-09-27 16:49:11 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-02-07 16:57:10 -05:00
|
|
|
/** Estimate the arrival time of any karts that haven't arrived yet by using
|
|
|
|
* their average speed up to now and the distance still to race. This
|
|
|
|
* approach guarantees that the order of the karts won't change anymore
|
|
|
|
* (karts ahead will have a higher average speed and therefore finish the
|
|
|
|
* race earlier than karts further behind), so the position doesn't have to
|
|
|
|
* be updated to get the correct scoring.
|
|
|
|
* \param kart The kart for which to estimate the finishing times.
|
|
|
|
*/
|
2008-12-08 18:23:33 -05:00
|
|
|
float LinearWorld::estimateFinishTimeForKart(Kart* kart)
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
2008-12-08 18:23:33 -05:00
|
|
|
const KartInfo &kart_info = m_kart_info[kart->getWorldKartId()];
|
2008-12-16 04:02:14 -05:00
|
|
|
float distance_covered = kart_info.m_race_lap * m_track->getTrackLength()
|
2008-09-27 15:43:57 -04:00
|
|
|
+ getDistanceDownTrackForKart(kart->getWorldKartId());
|
|
|
|
// In case that a kart is rescued behind start line, or ...
|
|
|
|
if(distance_covered<0) distance_covered =1.0f;
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-12-16 04:02:14 -05:00
|
|
|
const float full_distance = race_manager->getNumLaps()*m_track->getTrackLength();
|
|
|
|
const float average_speed = distance_covered/getTime();
|
2009-08-18 06:33:21 -04:00
|
|
|
|
|
|
|
// Finish time is the time needed for the whole race with
|
2008-09-27 15:43:57 -04:00
|
|
|
// the average speed computed above.
|
2008-12-11 14:43:25 -05:00
|
|
|
return getTime() + (full_distance - distance_covered) / average_speed;
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2010-02-17 06:59:51 -05:00
|
|
|
} // estimateFinishTimeForKart
|
2008-12-21 19:21:43 -05:00
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2008-09-27 16:49:11 -04:00
|
|
|
/** Decide where to drop a rescued kart
|
|
|
|
*/
|
2010-04-22 09:21:35 -04:00
|
|
|
void LinearWorld::moveKartAfterRescue(Kart* kart)
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
|
|
|
KartInfo& info = m_kart_info[kart->getWorldKartId()];
|
2008-12-15 20:42:22 -05:00
|
|
|
|
2009-08-18 06:33:21 -04:00
|
|
|
// If the kart is off road, rescue it to the last valid track position
|
|
|
|
// instead of the current one (since the sector might be determined by
|
2008-12-15 20:42:22 -05:00
|
|
|
// being closest to it, which allows shortcuts like drive towards another
|
|
|
|
// part of the lap, press rescue, and be rescued to this other part of
|
|
|
|
// the track (example: math class, drive towards the left after start,
|
|
|
|
// when hitting the books, press rescue --> you are rescued to the
|
|
|
|
// end of the track).
|
|
|
|
if(!info.m_on_road)
|
2008-12-25 13:49:34 -05:00
|
|
|
{
|
2008-12-15 20:42:22 -05:00
|
|
|
info.m_track_sector = info.m_last_valid_sector;
|
2008-12-25 13:49:34 -05:00
|
|
|
}
|
2008-12-25 14:07:56 -05:00
|
|
|
info.m_race_lap = info.m_last_valid_race_lap;
|
2008-12-10 19:45:54 -05:00
|
|
|
// FIXME - removing 1 here makes it less likely to fall in a rescue loop since the kart
|
|
|
|
// moves back on each attempt. This is still a weak hack. Also some other code depends
|
|
|
|
// on 1 being substracted, like 'forceRescue'
|
2008-09-27 15:43:57 -04:00
|
|
|
if ( info.m_track_sector > 0 ) info.m_track_sector-- ;
|
2008-10-03 21:44:08 -04:00
|
|
|
info.m_last_valid_sector = info.m_track_sector;
|
|
|
|
if ( info.m_last_valid_sector > 0 ) info.m_last_valid_sector --;
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-12-16 04:02:14 -05:00
|
|
|
kart->setXYZ( m_track->trackToSpatial(info.m_track_sector) );
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2010-02-25 08:20:22 -05:00
|
|
|
btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f),
|
2009-05-18 00:08:00 -04:00
|
|
|
m_track->getAngle(info.m_track_sector) );
|
2008-09-27 15:43:57 -04:00
|
|
|
kart->setRotation(heading);
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2009-08-18 07:05:40 -04:00
|
|
|
// A certain epsilon is added here to the Z coordinate, in case
|
2008-09-27 16:32:07 -04:00
|
|
|
// that the drivelines are somewhat under the track. Otherwise, the
|
2009-08-18 07:05:40 -04:00
|
|
|
// kart might be placed a little bit under the track, triggering
|
|
|
|
// a rescue, ... (experimentally found value)
|
|
|
|
float epsilon = 0.5f * kart->getKartHeight();
|
|
|
|
|
2008-09-27 16:32:07 -04:00
|
|
|
btTransform pos;
|
2010-02-25 08:20:22 -05:00
|
|
|
pos.setOrigin(kart->getXYZ()+btVector3(0, kart->getKartHeight() + epsilon, 0));
|
|
|
|
pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f),
|
2009-05-18 00:08:00 -04:00
|
|
|
m_track->getAngle(info.m_track_sector)));
|
2008-09-27 16:32:07 -04:00
|
|
|
|
2010-04-22 09:21:35 -04:00
|
|
|
kart->getBody()->setCenterOfMassTransform(pos);
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2009-08-18 07:05:40 -04:00
|
|
|
//project kart to surface of track
|
|
|
|
bool kart_over_ground = m_physics->projectKartDownwards(kart);
|
|
|
|
|
|
|
|
if (kart_over_ground)
|
|
|
|
{
|
2009-08-19 10:07:15 -04:00
|
|
|
//add vertical offset so that the kart starts off above the track
|
2010-02-25 08:20:22 -05:00
|
|
|
float vertical_offset = kart->getKartProperties()->getVertRescueOffset() *
|
2009-08-19 10:07:15 -04:00
|
|
|
kart->getKartHeight();
|
2010-04-22 09:21:35 -04:00
|
|
|
kart->getBody()->translate(btVector3(0, vertical_offset, 0));
|
2009-08-18 07:05:40 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf(stderr, "WARNING: invalid position after rescue for kart %s on track %s.\n",
|
|
|
|
(kart->getIdent().c_str()), m_track->getIdent().c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-07 20:29:02 -05:00
|
|
|
} // moveKartAfterRescue
|
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
//-----------------------------------------------------------------------------
|
2010-03-08 13:39:05 -05:00
|
|
|
/** Find the position (rank) of every kart
|
2008-09-27 15:43:57 -04:00
|
|
|
*/
|
2010-03-08 13:39:05 -05:00
|
|
|
void LinearWorld::updateRacePosition()
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
2010-02-10 17:59:17 -05:00
|
|
|
const unsigned int kart_amount = m_karts.size();
|
2010-03-08 13:39:05 -05:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2010-03-11 21:16:11 -05:00
|
|
|
std::vector<bool> rank_used;
|
|
|
|
for (unsigned int n=0; n<=kart_amount; n++)
|
|
|
|
rank_used.push_back(false);
|
2010-03-08 13:39:05 -05:00
|
|
|
#endif
|
|
|
|
|
|
|
|
for (unsigned int i=0; i<kart_amount; i++)
|
2008-09-27 15:43:57 -04:00
|
|
|
{
|
2010-03-08 13:39:05 -05:00
|
|
|
Kart* kart = m_karts[i];
|
2010-03-15 07:25:01 -04:00
|
|
|
// Karts that are either eliminated or have finished the
|
|
|
|
// race already have their (final) position assigned. If
|
|
|
|
// these karts would get their rank updated, it could happen
|
|
|
|
// that a kart that finished first will be overtaken after
|
|
|
|
// crossing the finishing line and become second!
|
2010-04-11 15:28:53 -04:00
|
|
|
if(kart->isEliminated() || kart->hasFinishedRace())
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
rank_used[kart->getPosition()] = true;
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
2010-03-08 13:39:05 -05:00
|
|
|
KartInfo& kart_info = m_kart_info[i];
|
|
|
|
|
|
|
|
int p = 1 ;
|
|
|
|
|
|
|
|
const int my_id = kart->getWorldKartId();
|
|
|
|
const int my_laps = getLapForKart(my_id);
|
|
|
|
const float my_progression = getDistanceDownTrackForKart(my_id);
|
2010-04-11 15:44:52 -04:00
|
|
|
|
|
|
|
#if _DEBUG_PRINTS_LIKE_MAD_
|
|
|
|
std::cout << "counting karts ahead of " << kart->getIdent() << "\n";
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Count karts ahead of the current kart, i.e. kart that are already finished,
|
|
|
|
// have done more laps, or the same number of laps, but a greater distance.
|
2010-03-08 13:39:05 -05:00
|
|
|
for (unsigned int j = 0 ; j < kart_amount ; j++)
|
2008-12-15 18:37:25 -05:00
|
|
|
{
|
2010-03-08 13:39:05 -05:00
|
|
|
if(j == kart->getWorldKartId()) continue; // don't compare a kart with itself
|
|
|
|
|
|
|
|
//if(m_karts[j]->isEliminated()) continue; // dismiss eliminated karts
|
|
|
|
|
2010-04-11 15:44:52 -04:00
|
|
|
if(!kart->hasFinishedRace() && m_karts[j]->hasFinishedRace())
|
|
|
|
{
|
|
|
|
p++;
|
|
|
|
#if _DEBUG_PRINTS_LIKE_MAD_
|
|
|
|
std::cout << " " << p << " : " << m_karts[j]->getIdent() << " because he has finished.\n";
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
2010-03-08 13:39:05 -05:00
|
|
|
|
|
|
|
/* has done more or less lapses */
|
|
|
|
assert(j==m_karts[j]->getWorldKartId());
|
|
|
|
int other_laps = getLapForKart(j);
|
|
|
|
if (other_laps != my_laps)
|
|
|
|
{
|
2010-04-11 15:44:52 -04:00
|
|
|
if(other_laps > my_laps)
|
|
|
|
{
|
|
|
|
p++; // Other kart has more lapses
|
|
|
|
#if _DEBUG_PRINTS_LIKE_MAD_
|
|
|
|
std::cout << " " << p << " : " << m_karts[j]->getIdent() << " because he has more laps than me.\n";
|
|
|
|
#endif
|
|
|
|
}
|
2010-03-08 13:39:05 -05:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Now both karts have the same number of lapses. Test progression.
|
|
|
|
// A kart is ahead if it's driven further, or driven the same
|
|
|
|
// distance, but started further to the back.
|
|
|
|
float other_progression = getDistanceDownTrackForKart(j);
|
|
|
|
if(other_progression > my_progression ||
|
|
|
|
(other_progression == my_progression &&
|
|
|
|
m_karts[j]->getInitialPosition() > kart->getInitialPosition()) )
|
|
|
|
{
|
2010-04-11 15:44:52 -04:00
|
|
|
p++;
|
|
|
|
#if _DEBUG_PRINTS_LIKE_MAD_
|
|
|
|
std::cout << " " << p << " : " << m_karts[j]->getIdent() <<
|
|
|
|
" because he has is further within the track (my progression is " <<
|
|
|
|
my_progression << ", his progression is " << other_progression << ")\n";
|
|
|
|
#endif
|
2010-03-08 13:39:05 -05:00
|
|
|
}
|
|
|
|
} //next kart
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (rank_used[p])
|
|
|
|
{
|
|
|
|
std::cerr << "ERROR, same rank used twice!!\n";
|
|
|
|
|
|
|
|
std::cerr << "Info used to decide ranking :\n";
|
|
|
|
for (unsigned int d=0; d<kart_amount; d++)
|
|
|
|
{
|
|
|
|
std::cerr << " kart " << m_karts[d]->getIdent() << " has finished(" << m_karts[d]->hasFinishedRace()
|
|
|
|
<< "), is at lap (" << getLapForKart(d) << "), is at distance("
|
|
|
|
<< getDistanceDownTrackForKart(d) << "), is eliminated(" << m_karts[d]->isEliminated() << ")" << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cerr << "Used ranks:\n";
|
|
|
|
for (unsigned int d=1; d<=kart_amount; d++)
|
|
|
|
{
|
|
|
|
std::cerr << " rank " << d << " used : " << rank_used[d] << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cerr << "Who has each ranking so far :\n";
|
|
|
|
for (unsigned int d=0; d<i; d++)
|
|
|
|
{
|
|
|
|
std::cerr << " " << m_karts[d]->getIdent() << " has rank " << m_karts[d]->getPosition() << std::endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cerr << " --> And " << kart->getIdent() << " is being set at rank " << p << std::endl;
|
2010-04-11 15:28:53 -04:00
|
|
|
history->Save();
|
2010-03-08 13:39:05 -05:00
|
|
|
assert(false);
|
2008-12-15 18:37:25 -05:00
|
|
|
}
|
2010-03-08 13:39:05 -05:00
|
|
|
rank_used[p] = true;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
kart->setPosition(p);
|
|
|
|
// Switch on faster music if not already done so, if the
|
|
|
|
// first kart is doing its last lap, and if the estimated
|
|
|
|
// remaining time is less than 30 seconds.
|
|
|
|
if(!m_faster_music_active &&
|
|
|
|
kart_info.m_race_lap == race_manager->getNumLaps()-1 &&
|
|
|
|
p==1 &&
|
|
|
|
useFastMusicNearEnd() &&
|
|
|
|
kart_info.m_estimated_finish > 0 &&
|
|
|
|
kart_info.m_estimated_finish - getTime() < 30.0f )
|
2008-12-15 18:37:25 -05:00
|
|
|
{
|
2010-04-21 13:24:02 -04:00
|
|
|
music_manager->switchToFastMusic();
|
2010-03-08 13:39:05 -05:00
|
|
|
m_faster_music_active=true;
|
|
|
|
}
|
2010-03-11 21:16:11 -05:00
|
|
|
} // for i<kart_amount
|
2010-03-07 11:52:20 -05:00
|
|
|
|
2008-09-27 15:43:57 -04:00
|
|
|
} // updateRacePosition
|
2008-12-21 19:33:25 -05:00
|
|
|
|
2008-12-21 19:21:43 -05:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/** Checks if a kart is going in the wrong direction. This is done only for
|
|
|
|
* player karts to display a message to the player.
|
|
|
|
* \param i Kart id.
|
|
|
|
*/
|
|
|
|
void LinearWorld::checkForWrongDirection(unsigned int i)
|
|
|
|
{
|
2010-02-14 19:54:28 -05:00
|
|
|
if(!m_karts[i]->getController()->isPlayerController()) return;
|
2008-12-21 19:33:25 -05:00
|
|
|
if(!m_kart_info[i].m_on_road) return;
|
2008-12-21 19:21:43 -05:00
|
|
|
|
2010-02-10 17:59:17 -05:00
|
|
|
const Kart *kart=m_karts[i];
|
2009-05-18 00:08:00 -04:00
|
|
|
// If the kart can go in more than one directions from the current track
|
|
|
|
// don't do any reverse message handling, since it is likely that there
|
|
|
|
// will be one direction in which it isn't going backwards anyway.
|
|
|
|
if(m_track->getQuadGraph().getNumberOfSuccessors(m_kart_info[i].m_track_sector)>1)
|
|
|
|
return;
|
2009-08-18 06:33:21 -04:00
|
|
|
|
2008-12-21 19:21:43 -05:00
|
|
|
// check if the player is going in the wrong direction
|
2010-02-25 08:20:22 -05:00
|
|
|
float angle_diff = kart->getHeading() -
|
2009-05-18 00:08:00 -04:00
|
|
|
m_track->getAngle(m_kart_info[i].m_track_sector);
|
2008-12-21 19:21:43 -05:00
|
|
|
if(angle_diff > M_PI) angle_diff -= 2*M_PI;
|
|
|
|
else if (angle_diff < -M_PI) angle_diff += 2*M_PI;
|
|
|
|
// Display a warning message if the kart is going back way (unless
|
|
|
|
// the kart has already finished the race).
|
2009-07-02 20:51:31 -04:00
|
|
|
if (( angle_diff > DEGREE_TO_RAD* 120.0f ||
|
|
|
|
angle_diff < -DEGREE_TO_RAD*120.0f) &&
|
2008-12-21 19:21:43 -05:00
|
|
|
kart->getVelocityLC().getY() > 0.0f &&
|
|
|
|
!kart->hasFinishedRace() )
|
|
|
|
{
|
2009-07-12 07:54:21 -04:00
|
|
|
m_race_gui->addMessage(_("WRONG WAY!"), kart, -1.0f, 60);
|
2008-12-21 19:21:43 -05:00
|
|
|
} // if angle is too big
|
|
|
|
} // checkForWrongDirection
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|