diff --git a/src/modes/follow_the_leader.cpp b/src/modes/follow_the_leader.cpp index 711e1d1ab..cf2acb188 100644 --- a/src/modes/follow_the_leader.cpp +++ b/src/modes/follow_the_leader.cpp @@ -54,8 +54,11 @@ FollowTheLeaderRace::FollowTheLeaderRace() : LinearWorld() void FollowTheLeaderRace::init() { LinearWorld::init(); + // WorldWithRank determines the score based on getNumKarts(), but since + // we ignore the leader, the points need to be based on number of karts -1 + stk_config->getAllScores(&m_score_for_position, getNumKarts() - 1); getKart(0)->setOnScreenText(_("Leader")); -} +} // init #if 0 #pragma mark - @@ -83,6 +86,20 @@ void FollowTheLeaderRace::reset() m_is_over_delay = 2.0f; } // reset +//----------------------------------------------------------------------------- +/** Returns the number of points for a kart at a specified position. + * \param p Position (starting with 1). + */ +int FollowTheLeaderRace::getScoreForPosition(int p) +{ + // Kart 0 (the leader) does not get any points + if (p == 1) return 0; + + assert(p-2 >= 0); + assert(p - 2 <(int) m_score_for_position.size()); + return m_score_for_position[p - 2]; +} // getScoreForPosition + //----------------------------------------------------------------------------- /** Returns the original time at which the countdown timer started. This is * used by the race_gui to display the music credits in FTL mode correctly. @@ -233,6 +250,36 @@ bool FollowTheLeaderRace::isRaceOver() } } // isRaceOver +//----------------------------------------------------------------------------- +/** Called at the end of a race. Updates highscores, pauses the game, and + * informs the unlock manager about the finished race. This function must + * be called after all other stats were updated from the different game + * modes. + */ +void FollowTheLeaderRace::terminateRace() +{ + int pos_leader = m_karts[0]->getPosition(); + + // Any kart that has overtaken the leader must be placed one position + // back, and the leader must be set to be number 1. + const unsigned int kart_amount = getNumKarts(); + for (unsigned int i = 0; i < kart_amount; i++) + { + if (!m_karts[i]->hasFinishedRace() && !m_karts[i]->isEliminated()) + { + if (m_karts[i]->getPosition() < pos_leader) + { + m_karts[i]->setPosition(m_karts[i]->getPosition() + 1); + } + // Update the estimated finishing time for all karts that haven't + // finished yet. + m_karts[i]->finishedRace(0.0f); + } + } // isetPosition(1); + World::terminateRace(); +} // terminateRace + //----------------------------------------------------------------------------- /** Returns the internal identifier for this kind of race. */ diff --git a/src/modes/follow_the_leader.hpp b/src/modes/follow_the_leader.hpp index ff29fc727..998daf65d 100644 --- a/src/modes/follow_the_leader.hpp +++ b/src/modes/follow_the_leader.hpp @@ -27,8 +27,11 @@ class FollowTheLeaderRace : public LinearWorld { private: - std::vector m_leader_intervals; // time till elimination in follow leader - float m_is_over_delay; //!< A timer used before terminating the race + // time till elimination in follow leader + std::vector m_leader_intervals; + + /** A timer used before terminating the race. */ + float m_is_over_delay; public: @@ -37,6 +40,7 @@ public: // clock events virtual void countdownReachedZero() OVERRIDE; + virtual int getScoreForPosition(int p) OVERRIDE; // overriding World methods virtual void reset() OVERRIDE; @@ -46,10 +50,9 @@ public: virtual void getKartsDisplayInfo( std::vector *info) OVERRIDE; virtual void init() OVERRIDE; - + virtual void terminateRace() OVERRIDE; virtual bool isRaceOver() OVERRIDE; virtual bool raceHasLaps() OVERRIDE { return false; } - }; // FollowTheLeader diff --git a/src/modes/world_with_rank.cpp b/src/modes/world_with_rank.cpp index bbad420c0..e34a4fe91 100644 --- a/src/modes/world_with_rank.cpp +++ b/src/modes/world_with_rank.cpp @@ -37,6 +37,8 @@ void WorldWithRank::init() m_position_used.resize(m_karts.size()); m_position_setting_initialised = false; #endif + stk_config->getAllScores(&m_score_for_position, getNumKarts()); + } // init //----------------------------------------------------------------------------- @@ -173,3 +175,13 @@ btTransform WorldWithRank::getRescueTransform(unsigned int rescue_pos) const return getTrack()->getStartTransform(rescue_pos); } // getRescueTransform +//----------------------------------------------------------------------------- +/** Returns the number of points for a kart at a specified position. + * \param p Position (starting with 1). + */ +int WorldWithRank::getScoreForPosition(int p) +{ + assert(p-1 >= 0); + assert(p - 1 <(int) m_score_for_position.size()); + return m_score_for_position[p - 1]; +} // getScoreForPosition diff --git a/src/modes/world_with_rank.hpp b/src/modes/world_with_rank.hpp index 0914f27d8..fd768bc46 100644 --- a/src/modes/world_with_rank.hpp +++ b/src/modes/world_with_rank.hpp @@ -43,6 +43,10 @@ protected: /** Whether to display the rank in the race GUI */ bool m_display_rank; + /** The points given to a kart on a given position (index is + * 0 based, so using race-position - 1. */ + std::vector m_score_for_position; + #ifdef DEBUG /** Used for debugging to help detect if the same kart position * is used more than once. */ @@ -70,6 +74,8 @@ public: unsigned int position); void endSetKartPositions(); AbstractKart* getKartAtPosition(unsigned int p) const; + virtual int getScoreForPosition(int p); + virtual unsigned int getNumberOfRescuePositions() const OVERRIDE; virtual unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE; diff --git a/src/race/race_manager.cpp b/src/race/race_manager.cpp index 17814d3e5..056624d22 100644 --- a/src/race/race_manager.cpp +++ b/src/race/race_manager.cpp @@ -416,7 +416,6 @@ void RaceManager::startNextRace() // Uncomment to debug audio leaks // sfx_manager->dump(); - stk_config->getAllScores(&m_score_for_position, m_num_karts); IrrlichtDevice* device = irr_driver->getDevice(); GUIEngine::renderLoading(); device->getVideoDriver()->endScene(); @@ -760,7 +759,17 @@ void RaceManager::kartFinishedRace(const AbstractKart *kart, float time) assert(pos-1 < (int)m_kart_status.size()); m_kart_status[id].m_last_score = m_kart_status[id].m_score; - m_kart_status[id].m_score += m_score_for_position[pos-1]; + + // In follow the leader mode, the winner is actually the kart with + // position 2, so adjust the points (#points for leader do not matter) + WorldWithRank *wwr = dynamic_cast(World::getWorld()); + if (wwr) + m_kart_status[id].m_score += wwr->getScoreForPosition(pos); + else + { + Log::error("RaceManager", "World with scores that is not a WorldWithRank??"); + } + m_kart_status[id].m_overall_time += time; m_kart_status[id].m_last_time = time; m_num_finished_karts ++; diff --git a/src/race/race_manager.hpp b/src/race/race_manager.hpp index c553bdab4..ea45be6e8 100644 --- a/src/race/race_manager.hpp +++ b/src/race/race_manager.hpp @@ -313,10 +313,6 @@ private: /** Whether a track should be reversed */ std::vector m_reverse_track; - /** The points given to a kart on a given position (index is - * 0 based, so using race-position - 1. */ - std::vector m_score_for_position; - /** The list of default AI karts to use. This is from the command line. */ std::vector m_default_ai_list; @@ -592,8 +588,6 @@ public: // ------------------------------------------------------------------------ float getTimeTarget() const { return m_time_target; } // ------------------------------------------------------------------------ - int getPositionScore(int p) const { return m_score_for_position[p-1]; } - // ------------------------------------------------------------------------ int getTrackNumber() const { return m_track_number; } // ------------------------------------------------------------------------ /** Returns the list of AI karts to use. Used for networking, and for diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index e8ff10d5e..c171f2e0c 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -769,18 +769,22 @@ void RaceResultGUI::renderGlobal(float dt) } break; case RR_INCREASE_POINTS: + { + WorldWithRank *wwr = dynamic_cast(World::getWorld()); + assert(wwr); ri->m_current_displayed_points += - dt*race_manager->getPositionScore(1)/m_time_for_points; - if(ri->m_current_displayed_points>ri->m_new_overall_points) + dt*wwr->getScoreForPosition(1) / m_time_for_points; + if (ri->m_current_displayed_points > ri->m_new_overall_points) { ri->m_current_displayed_points = - (float)ri->m_new_overall_points; + (float)ri->m_new_overall_points; } ri->m_new_points -= - dt*race_manager->getPositionScore(1)/m_time_for_points; - if(ri->m_new_points<0) + dt*wwr->getScoreForPosition(1) / m_time_for_points; + if (ri->m_new_points < 0) ri->m_new_points = 0; break; + } case RR_RESORT_TABLE: x = ri->m_x_pos - ri->m_radius*sin(m_timer/m_time_rotation*M_PI); @@ -849,8 +853,10 @@ void RaceResultGUI::determineGPLayout() } else { + WorldWithRank *wwr = dynamic_cast(World::getWorld()); + assert(wwr); ri->m_new_points = - (float)race_manager->getPositionScore(kart->getPosition()); + (float)wwr->getScoreForPosition(kart->getPosition()); } }