From 58957a3fbb5f4ff77c996f6ca9a09c46831e4006 Mon Sep 17 00:00:00 2001 From: Flakebi Date: Wed, 4 Feb 2015 12:32:15 +0100 Subject: [PATCH 01/40] Use camera position for LoD instead of the kart position --- src/graphics/lod_node.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/graphics/lod_node.cpp b/src/graphics/lod_node.cpp index 8f94368c2..062010c74 100644 --- a/src/graphics/lod_node.cpp +++ b/src/graphics/lod_node.cpp @@ -77,12 +77,7 @@ int LODNode::getLevel() Camera* camera = Camera::getActiveCamera(); if (camera == NULL) return (int)m_detail.size() - 1; - AbstractKart* kart = camera->getKart(); - // use kart position and not camera position when a kart is available, - // because for some effects the camera will be moved to various locations - // (for instance shadows), so using camera position for LOD may result - // in objects being culled when they shouldn't - const Vec3 &pos = (kart != NULL ? kart->getFrontXYZ() : camera->getCameraSceneNode()->getAbsolutePosition()); + const Vec3 &pos = camera->getCameraSceneNode()->getAbsolutePosition(); const int dist = (int)((m_nodes[0]->getAbsolutePosition()).getDistanceFromSQ(pos.toIrrVector() )); From e9d78326fb6cc2222a46cd2bf1b2c90a4f30ec0a Mon Sep 17 00:00:00 2001 From: Flakebi Date: Sun, 29 Mar 2015 04:16:24 +0200 Subject: [PATCH 02/40] Properly ignore the leader in the ftl scoreboard --- src/states_screens/race_result_gui.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index 80f5cbbbc..c74beb7e0 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -434,13 +434,11 @@ void RaceResultGUI::determineTableLayout() m_font->setMonospaceDigits(true); WorldWithRank *rank_world = (WorldWithRank*)World::getWorld(); - unsigned int first_position = 1; - if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER) - first_position = 2; - // Use only the karts that are supposed to be displayed (and // ignore e.g. the leader in a FTL race). - unsigned int num_karts =race_manager->getNumberOfKarts()-first_position+1; + unsigned int num_karts = race_manager->getNumberOfKarts(); + if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_FOLLOW_LEADER) + num_karts--; // In FTL races the leader kart is not displayed m_all_row_infos.resize(num_karts); @@ -452,14 +450,21 @@ void RaceResultGUI::determineTableLayout() m_width_kart_name = 0; float max_finish_time = 0; - - for(unsigned int position=first_position; - position<=race_manager->getNumberOfKarts(); position++) + for (unsigned int sourcePos = 1, destPos = 0; + destPos < num_karts; sourcePos++, destPos++) { - const AbstractKart *kart = rank_world->getKartAtPosition(position); + const AbstractKart *kart = rank_world->getKartAtPosition(sourcePos); + + // Don't take the leader + if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_FOLLOW_LEADER && + kart == rank_world->getKart(0)) + { + destPos--; + continue; + } // Save a pointer to the current row_info entry - RowInfo *ri = &(m_all_row_infos[position-first_position]); + RowInfo *ri = &(m_all_row_infos[destPos]); ri->m_is_player_kart = kart->getController()->isPlayerController(); ri->m_kart_name = translations->fribidize(kart->getName()); ri->m_player = ri->m_is_player_kart From cd256061e1a830afdcba0bbdffd74eb5912884d5 Mon Sep 17 00:00:00 2001 From: hiker Date: Sun, 26 Jul 2015 00:26:43 +1000 Subject: [PATCH 03/40] Fix #2248 (crash when taking screenshot). The assert was not appropriate (avoiding the call to clearAllMessages would have been quite ugly). --- src/states_screens/race_result_gui.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/states_screens/race_result_gui.hpp b/src/states_screens/race_result_gui.hpp index ea6e309bf..2c2a0d0d3 100644 --- a/src/states_screens/race_result_gui.hpp +++ b/src/states_screens/race_result_gui.hpp @@ -249,9 +249,6 @@ public: bool important=true, bool big_font=false) { } - /** Should not be called anymore. */ - virtual void clearAllMessages() {assert(false); } - void nextPhase(); /** Show no highscore */ From c8909b91975bb19d2f51e974214d91d28ab01025 Mon Sep 17 00:00:00 2001 From: hiker Date: Sun, 26 Jul 2015 00:30:09 +1000 Subject: [PATCH 04/40] Fixed missing display of points for non-winners in a FTL GP (partly fix for #2249). --- src/states_screens/race_result_gui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index 2cd63e88d..9ca797439 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -842,7 +842,8 @@ void RaceResultGUI::determineGPLayout() ri->m_y_pos = (float)(m_top+rank*m_distance_between_rows); int p = race_manager->getKartPrevScore(kart_id); ri->m_current_displayed_points = (float)p; - if (kart->isEliminated()) + if (kart->isEliminated() && + race_manager->getMinorMode()!=RaceManager::MINOR_MODE_FOLLOW_LEADER) { ri->m_new_points = 0; } From a9aa37ea9729283e71e6eb443f7ac65b522b7c27 Mon Sep 17 00:00:00 2001 From: hiker Date: Sun, 26 Jul 2015 00:31:15 +1000 Subject: [PATCH 05/40] Minor code style fixes. --- src/states_screens/race_result_gui.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index 9ca797439..52656fd69 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -450,21 +450,21 @@ void RaceResultGUI::determineTableLayout() m_width_kart_name = 0; float max_finish_time = 0; - for (unsigned int sourcePos = 1, destPos = 0; - destPos < num_karts; sourcePos++, destPos++) + for (unsigned int source_pos = 1, dest_pos = 0; + dest_pos < num_karts; source_pos++, dest_pos++) { - const AbstractKart *kart = rank_world->getKartAtPosition(sourcePos); + const AbstractKart *kart = rank_world->getKartAtPosition(source_pos); // Don't take the leader if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_FOLLOW_LEADER && kart == rank_world->getKart(0)) { - destPos--; + dest_pos--; continue; } // Save a pointer to the current row_info entry - RowInfo *ri = &(m_all_row_infos[destPos]); + RowInfo *ri = &(m_all_row_infos[dest_pos]); ri->m_is_player_kart = kart->getController()->isPlayerController(); ri->m_kart_name = translations->fribidize(kart->getName()); ri->m_player = ri->m_is_player_kart From d9e806f6102a736150359b74b28e5767614e53dd Mon Sep 17 00:00:00 2001 From: hiker Date: Sun, 26 Jul 2015 00:32:11 +1000 Subject: [PATCH 06/40] Changed unsigned int to int (dest_pos can become negative, and while de-facto it still works with unsigned, it's just bad style :) ). --- src/states_screens/race_result_gui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index 52656fd69..23a9f49dd 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -450,8 +450,8 @@ void RaceResultGUI::determineTableLayout() m_width_kart_name = 0; float max_finish_time = 0; - for (unsigned int source_pos = 1, dest_pos = 0; - dest_pos < num_karts; source_pos++, dest_pos++) + for (int source_pos = 1, dest_pos = 0; + dest_pos < num_karts; source_pos++, dest_pos++) { const AbstractKart *kart = rank_world->getKartAtPosition(source_pos); From fcc3e75a99d19e91774aa0e40032802344fda430 Mon Sep 17 00:00:00 2001 From: Tobias Markus Date: Sun, 26 Jul 2015 16:40:45 +0200 Subject: [PATCH 07/40] Fix crash when loading story mode --- src/tracks/track_object_presentation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracks/track_object_presentation.cpp b/src/tracks/track_object_presentation.cpp index 1c05723f6..c808afa29 100644 --- a/src/tracks/track_object_presentation.cpp +++ b/src/tracks/track_object_presentation.cpp @@ -940,7 +940,7 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger( std::string trigger_type; xml_node.get("trigger-type", &trigger_type); - if (trigger_type == "point") + if (trigger_type == "point" || trigger_type.empty()) { m_type = TRIGGER_TYPE_POINT; } From 51fe38f76ead624cd369bfe8548e2efe9bb6bf3d Mon Sep 17 00:00:00 2001 From: Marianne Gagnon Date: Sun, 26 Jul 2015 19:05:05 -0400 Subject: [PATCH 08/40] Use instead of , apparently fixes OSX compilation. Closes #2253 --- src/items/flyable.cpp | 2 +- src/karts/kart.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/items/flyable.cpp b/src/items/flyable.cpp index bafaff023..eb3cbdcd9 100644 --- a/src/items/flyable.cpp +++ b/src/items/flyable.cpp @@ -21,7 +21,7 @@ #include "items/flyable.hpp" -#include +#include #include #include diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index c94d76b66..e075e59e8 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -73,7 +73,7 @@ #include // for min and max #include -#include +#include #if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__) From 95b86ea9140578794c05e0b6eae1fdad41e84197 Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 27 Jul 2015 09:56:58 +1000 Subject: [PATCH 09/40] Fixed #2247. --- src/physics/btKart.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index 812c3bf46..58bb22640 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -447,7 +447,8 @@ void btKart::updateVehicle( btScalar step ) btVector3 kart_up = getChassisWorldTransform().getBasis().getColumn(1); btVector3 terrain_up(0,1,0); btVector3 axis = kart_up.cross(terrain_up); - axis.normalize(); + if(!axis.fuzzyZero()) + axis.normalize(); // To avoid the kart going backwards/forwards (or rolling sideways), // set the pitch/roll to 0 before applying the 'straightening' impulse. From 5c66273712d355c5e543086fcf2cb31f11f1cfee Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 27 Jul 2015 16:41:46 +1000 Subject: [PATCH 10/40] Fixed compiler warning. --- src/states_screens/race_result_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index 23a9f49dd..e8ff10d5e 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -451,7 +451,7 @@ void RaceResultGUI::determineTableLayout() float max_finish_time = 0; for (int source_pos = 1, dest_pos = 0; - dest_pos < num_karts; source_pos++, dest_pos++) + dest_pos < (int)num_karts; source_pos++, dest_pos++) { const AbstractKart *kart = rank_world->getKartAtPosition(source_pos); From 5efb44a4307ad922a3fee6a4fc80c2f09c2d71f9 Mon Sep 17 00:00:00 2001 From: hiker Date: Tue, 28 Jul 2015 09:39:00 +1000 Subject: [PATCH 11/40] Fixed scores in FTL GPs. All score handling is now done by the World, not race manager (which removes if tests). --- src/modes/follow_the_leader.cpp | 49 +++++++++++++++++++++++++- src/modes/follow_the_leader.hpp | 11 +++--- src/modes/world_with_rank.cpp | 12 +++++++ src/modes/world_with_rank.hpp | 6 ++++ src/race/race_manager.cpp | 13 +++++-- src/race/race_manager.hpp | 6 ---- src/states_screens/race_result_gui.cpp | 18 ++++++---- 7 files changed, 96 insertions(+), 19 deletions(-) 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()); } } From 3f468b254cf1eabbad3b8f386287412178c3ac67 Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 29 Jul 2015 07:59:46 +1000 Subject: [PATCH 12/40] Removed unused/duplicated code, use World::setKartPosition instead of Kart::setPosition (since this will keep an index array up-to-date). --- src/modes/follow_the_leader.cpp | 71 +++++++++++++-------------------- 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/src/modes/follow_the_leader.cpp b/src/modes/follow_the_leader.cpp index cf2acb188..bcee90fa7 100644 --- a/src/modes/follow_the_leader.cpp +++ b/src/modes/follow_the_leader.cpp @@ -186,43 +186,6 @@ void FollowTheLeaderRace::countdownReachedZero() music_manager->switchToFastMusic(); } - if (isRaceOver()) - { - // Handle special FTL situation: the leader is kart number 3 when - // the last kart gets eliminated. In this case kart on position 1 - // is eliminated, and the kart formerly on position 2 is on - // position 1, the leader now position 2. In this case the kart - // on position 1 would get more points for this victory. So if - // this is the case, change the position - if(m_karts[0]->getPosition()!=1) - { - // Adjust the position of all still driving karts that - // are ahead of the leader by +1, and move the leader - // to position 1. - for (unsigned int i=1; ihasFinishedRace() && - !m_karts[i]->isEliminated() && - m_karts[i]->getPosition()getPosition()) - { - m_karts[i]->setPosition(m_karts[i]->getPosition()+1); - } - } - m_karts[0]->setPosition(1); - } - - // Mark all still racing karts to be finished. - for (unsigned int n=0; nisEliminated() && - !m_karts[n]->hasFinishedRace()) - { - m_karts[n]->finishedRace(getTime()); - } - } - } - // End of race is detected from World::updateWorld() - } // countdownReachedZero //----------------------------------------------------------------------------- @@ -260,23 +223,43 @@ 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++) + // Handle special FTL situations: the leader is kart number 3 when + // the last kart gets eliminated. In this case kart on position 1 + // is eliminated, and the kart formerly on position 2 is on + // position 1, the leader now position 2, but the point distribution + // depends on the 'first' (non-leader) kart to be on position 2. + // That situation can also occur during the delay after eliminating + // the last kart before the race result is shown. + // To avoid this problem, adjust the position of any kart that is + // ahead of the leader. + beginSetKartPositions(); + for (unsigned int i = 0; i < getNumKarts(); 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); + setKartPosition(i, 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); + } // i < number of karts + setKartPosition(/*kart id*/0, /*position*/1); + endSetKartPositions(); + + // Mark all still racing karts to be finished. + for (unsigned int n = 0; n < m_karts.size(); n++) + { + if (!m_karts[n]->isEliminated() && + !m_karts[n]->hasFinishedRace()) + { + m_karts[n]->finishedRace(getTime()); + } + } + + World::terminateRace(); } // terminateRace From 6ada5a06661f16d1fb97fcf72d2d67abd3bfdd2c Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 29 Jul 2015 08:12:23 +1000 Subject: [PATCH 13/40] Revert "Properly ignore the leader in the ftl scoreboard" (this patch only fixed the problem that happens when a non-leader is number one. By now the code has fixed that it is guaranteed that the leader is always number one, so this patch is not necessary anymore, and it complicates the loop). This reverts commit e9d78326fb6cc2222a46cd2bf1b2c90a4f30ec0a. Conflicts: src/states_screens/race_result_gui.cpp --- src/states_screens/race_result_gui.cpp | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index c171f2e0c..774a723a3 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -434,11 +434,13 @@ void RaceResultGUI::determineTableLayout() m_font->setMonospaceDigits(true); WorldWithRank *rank_world = (WorldWithRank*)World::getWorld(); + unsigned int first_position = 1; + if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER) + first_position = 2; + // Use only the karts that are supposed to be displayed (and // ignore e.g. the leader in a FTL race). - unsigned int num_karts = race_manager->getNumberOfKarts(); - if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_FOLLOW_LEADER) - num_karts--; + unsigned int num_karts =race_manager->getNumberOfKarts()-first_position+1; // In FTL races the leader kart is not displayed m_all_row_infos.resize(num_karts); @@ -450,21 +452,13 @@ void RaceResultGUI::determineTableLayout() m_width_kart_name = 0; float max_finish_time = 0; - for (int source_pos = 1, dest_pos = 0; - dest_pos < (int)num_karts; source_pos++, dest_pos++) + for(unsigned int position=first_position; + position<=race_manager->getNumberOfKarts(); position++) { - const AbstractKart *kart = rank_world->getKartAtPosition(source_pos); - - // Don't take the leader - if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_FOLLOW_LEADER && - kart == rank_world->getKart(0)) - { - dest_pos--; - continue; - } + const AbstractKart *kart = rank_world->getKartAtPosition(position); // Save a pointer to the current row_info entry - RowInfo *ri = &(m_all_row_infos[dest_pos]); + RowInfo *ri = &(m_all_row_infos[position-first_position]); ri->m_is_player_kart = kart->getController()->isPlayerController(); ri->m_kart_name = translations->fribidize(kart->getName()); ri->m_player = ri->m_is_player_kart From d27ba5f6fe63aadc24be4e70658bcb3e6aba6f23 Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 29 Jul 2015 08:58:42 +1000 Subject: [PATCH 14/40] Fix #2249 (show points and points increasing in a FTL GP). --- src/states_screens/race_result_gui.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index 774a723a3..c26c65c0b 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -766,15 +766,20 @@ void RaceResultGUI::renderGlobal(float dt) { WorldWithRank *wwr = dynamic_cast(World::getWorld()); assert(wwr); + int most_points; + if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_FOLLOW_LEADER) + most_points = wwr->getScoreForPosition(2); + else + most_points = wwr->getScoreForPosition(1); ri->m_current_displayed_points += - dt*wwr->getScoreForPosition(1) / m_time_for_points; + dt*most_points / 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; } ri->m_new_points -= - dt*wwr->getScoreForPosition(1) / m_time_for_points; + dt*most_points / m_time_for_points; if (ri->m_new_points < 0) ri->m_new_points = 0; break; From 280ddf967d4f6af407f529319fc1a9e56bca3a0a Mon Sep 17 00:00:00 2001 From: Marianne Gagnon Date: Tue, 28 Jul 2015 19:17:37 -0400 Subject: [PATCH 15/40] Add missing character to the font, fixes #2226 --- data/fonts/StkFont.xml | Bin 53004 -> 53096 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/fonts/StkFont.xml b/data/fonts/StkFont.xml index 8653367f0899c14bacc17132796764a57e273382..9b5fa0851d3e4d2e19c623764add7b389d8e9d9f 100644 GIT binary patch delta 29 lcmeB~$NXX*^9Hlh$pyz)CfgkpVEV#3*{w8WvrFlTNC3bz466VD delta 18 acmaDckGW?a^9Hlh$rptAHZLeW5eWcL{s?~n From b18d0275fdafae9a44ba4c0a634b403813f29c29 Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 29 Jul 2015 17:27:43 +1000 Subject: [PATCH 16/40] Display a finish (survival) time in FTL result screen. --- src/modes/follow_the_leader.cpp | 35 +++++++++++++------------- src/modes/follow_the_leader.hpp | 3 +++ src/states_screens/race_result_gui.cpp | 30 +++++++++++----------- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/modes/follow_the_leader.cpp b/src/modes/follow_the_leader.cpp index bcee90fa7..00ca1e942 100644 --- a/src/modes/follow_the_leader.cpp +++ b/src/modes/follow_the_leader.cpp @@ -53,6 +53,7 @@ FollowTheLeaderRace::FollowTheLeaderRace() : LinearWorld() */ void FollowTheLeaderRace::init() { + m_last_eliminated_time = 0; 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 @@ -114,6 +115,7 @@ float FollowTheLeaderRace::getClockStartTime() */ void FollowTheLeaderRace::countdownReachedZero() { + m_last_eliminated_time += m_leader_intervals[0]; if(m_leader_intervals.size()>1) m_leader_intervals.erase(m_leader_intervals.begin()); WorldStatus::setTime(m_leader_intervals[0]); @@ -162,7 +164,7 @@ void FollowTheLeaderRace::countdownReachedZero() updateRacePosition(); } // Time doesn't make any sense in FTL (and it is not displayed) - kart->finishedRace(-1.0f); + kart->finishedRace(m_last_eliminated_time); // Move any camera for this kart to the leader, facing backwards, // so that the eliminated player has something to watch. @@ -229,34 +231,31 @@ void FollowTheLeaderRace::terminateRace() // position 1, the leader now position 2, but the point distribution // depends on the 'first' (non-leader) kart to be on position 2. // That situation can also occur during the delay after eliminating - // the last kart before the race result is shown. - // To avoid this problem, adjust the position of any kart that is - // ahead of the leader. + // the last kart before the race result is shown (when the leader + // is overtaken during that time). To avoid this problem, adjust the + // position of any kart that is ahead of the leader. beginSetKartPositions(); for (unsigned int i = 0; i < getNumKarts(); i++) { - if (!m_karts[i]->hasFinishedRace() && !m_karts[i]->isEliminated()) + if (!m_karts[i]->hasFinishedRace() && !m_karts[i]->isEliminated() && + m_karts[i]->getPosition() < pos_leader) { - if (m_karts[i]->getPosition() < pos_leader) - { - setKartPosition(i, m_karts[i]->getPosition() + 1); - } - // Update the estimated finishing time for all karts that haven't - // finished yet. - m_karts[i]->finishedRace(0.0f); + setKartPosition(i, m_karts[i]->getPosition() + 1); } } // i < number of karts setKartPosition(/*kart id*/0, /*position*/1); endSetKartPositions(); // Mark all still racing karts to be finished. - for (unsigned int n = 0; n < m_karts.size(); n++) + for (int i = m_karts.size(); i>0; i--) { - if (!m_karts[n]->isEliminated() && - !m_karts[n]->hasFinishedRace()) - { - m_karts[n]->finishedRace(getTime()); - } + AbstractKart *kart = getKartAtPosition(i); + if (kart->isEliminated() || kart->hasFinishedRace()) + continue; + m_last_eliminated_time += m_leader_intervals[0]; + if (m_leader_intervals.size() > 1) + m_leader_intervals.erase(m_leader_intervals.begin()); + kart->finishedRace(m_last_eliminated_time); } diff --git a/src/modes/follow_the_leader.hpp b/src/modes/follow_the_leader.hpp index 998daf65d..939f54129 100644 --- a/src/modes/follow_the_leader.hpp +++ b/src/modes/follow_the_leader.hpp @@ -33,6 +33,9 @@ private: /** A timer used before terminating the race. */ float m_is_over_delay; + /** Time the last kart was eliminated. It is used to assign each + * kart a 'finish' time (i.e. how long they lasted). */ + float m_last_eliminated_time; public: FollowTheLeaderRace(); diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index c26c65c0b..b744e4b3c 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -468,7 +468,9 @@ void RaceResultGUI::determineTableLayout() kart->getKartProperties()->getIconMaterial()->getTexture(); ri->m_kart_icon = icon; - if (kart->isEliminated()) + // FTL karts will get a time assigned, they are not shown as eliminated + if (kart->isEliminated() && + race_manager->getMinorMode()!=RaceManager::MINOR_MODE_FOLLOW_LEADER) { ri->m_finish_time_string = core::stringw(_("Eliminated")); } @@ -830,16 +832,19 @@ void RaceResultGUI::determineGPLayout() ri->m_player = ri->m_is_player_kart ? kart->getController()->getPlayer() : NULL; - if (!kart->isEliminated()) + // In FTL karts do have a time, which is shown even when the kart + // is eliminated + if (kart->isEliminated() && + race_manager->getMinorMode()!=RaceManager::MINOR_MODE_FOLLOW_LEADER) + { + ri->m_finish_time_string = core::stringw(_("Eliminated")); + } + else { float time = race_manager->getOverallTime(kart_id); ri->m_finish_time_string = StringUtils::timeToString(time).c_str(); } - else - { - ri->m_finish_time_string = core::stringw(_("Eliminated")); - } ri->m_start_at = m_time_between_rows * rank; ri->m_x_pos = (float)UserConfigParams::m_width; ri->m_y_pos = (float)(m_top+rank*m_distance_between_rows); @@ -916,15 +921,10 @@ void RaceResultGUI::displayOneEntry(unsigned int x, unsigned int y, current_x += m_width_kart_name + m_width_column_space; - // Draw the time except in FTL mode - // -------------------------------- - if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_FOLLOW_LEADER) - { - core::recti dest_rect = core::recti(current_x, y, current_x+100, y+10); - m_font->draw(ri->m_finish_time_string, dest_rect, color, false, false, - NULL, true /* ignoreRTL */); - current_x += m_width_finish_time + m_width_column_space; - } + core::recti dest_rect = core::recti(current_x, y, current_x + 100, y + 10); + m_font->draw(ri->m_finish_time_string, dest_rect, color, false, false, + NULL, true /* ignoreRTL */); + current_x += m_width_finish_time + m_width_column_space; // Only display points in GP mode and when the GP results are displayed. // ===================================================================== From 3687eb79d6a7de6b09e58a59fbd042ae4af1d0f5 Mon Sep 17 00:00:00 2001 From: Marianne Gagnon Date: Wed, 29 Jul 2015 18:51:03 -0400 Subject: [PATCH 17/40] Apply modified version of patch from Benau to fix chinese word wrapping. See #2110 --- lib/irrlicht/source/Irrlicht/CGUIStaticText.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/irrlicht/source/Irrlicht/CGUIStaticText.cpp b/lib/irrlicht/source/Irrlicht/CGUIStaticText.cpp index ea934d3e1..095dd64a0 100644 --- a/lib/irrlicht/source/Irrlicht/CGUIStaticText.cpp +++ b/lib/irrlicht/source/Irrlicht/CGUIStaticText.cpp @@ -11,6 +11,9 @@ #include "IVideoDriver.h" #include "rect.h" +#define CJK_START 12287 +#define CJK_END 40960 + namespace irr { namespace gui @@ -360,6 +363,20 @@ void CGUIStaticText::breakText() { // part of a word word += c; + + //Check for CJK, show them first if out of range of displaying area + if (Text[i] > CJK_START && Text[i] < CJK_END) + { + const s32 cjklgth = font->getDimension(word.c_str()).Width; + if (cjklgth > (elWidth - 23)) + { + BrokenText.push_back(line); + length = cjklgth; + line = word; + word = L""; + whitespace = L""; + } + } } if ( isWhitespace || i == (size-1)) From 738e7bc78078d4da993a3e235e3a4003027a496f Mon Sep 17 00:00:00 2001 From: Marianne Gagnon Date: Wed, 29 Jul 2015 18:55:40 -0400 Subject: [PATCH 18/40] Fix inverted if condition in input options screen, fixes #2255 --- src/states_screens/options_screen_input2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/states_screens/options_screen_input2.cpp b/src/states_screens/options_screen_input2.cpp index 55a7c535c..3832765d2 100644 --- a/src/states_screens/options_screen_input2.cpp +++ b/src/states_screens/options_screen_input2.cpp @@ -89,7 +89,7 @@ void OptionsScreenInput2::init() ButtonWidget* delete_button = getWidget("delete"); - if (m_config->isKeyboard()) + if (!m_config->isKeyboard()) { core::stringw label = (m_config->isEnabled() ? //I18N: button to disable a gamepad configuration From 7799e9835dfc056df5bf4a2ddd747e5bf638bdbd Mon Sep 17 00:00:00 2001 From: hiker Date: Thu, 30 Jul 2015 17:12:48 +1000 Subject: [PATCH 19/40] Added a getStartTransform function to World. Use this to change the start position of the non-leader karts in a FTL race, so that those karts now start at the end of all start positions, and not directly behind the leader. --- src/modes/cutscene_world.cpp | 5 ----- src/modes/follow_the_leader.cpp | 14 +++++++++++++- src/modes/follow_the_leader.hpp | 9 +++++++-- src/modes/profile_world.cpp | 2 +- src/modes/soccer_world.cpp | 6 +++--- src/modes/three_strikes_battle.cpp | 2 +- src/modes/world.cpp | 12 ++++++++++-- src/modes/world.hpp | 1 + src/modes/world_with_rank.cpp | 2 +- src/tracks/track.cpp | 9 ++++++++- src/tracks/track.hpp | 2 +- 11 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/modes/cutscene_world.cpp b/src/modes/cutscene_world.cpp index a10ec95af..e3f12e79d 100644 --- a/src/modes/cutscene_world.cpp +++ b/src/modes/cutscene_world.cpp @@ -77,13 +77,8 @@ void CutsceneWorld::init() m_duration = -1.0f; - //const btTransform &s = getTrack()->getStartTransform(0); - //const Vec3 &v = s.getOrigin(); Camera* stk_cam = Camera::createCamera(NULL); m_camera = stk_cam->getCameraSceneNode(); - //m_camera = irr_driver->getSceneManager() - // ->addCameraSceneNode(NULL, core::vector3df(0.0f, 0.0f, 0.0f), - // core::vector3df(0.0f, 0.0f, 0.0f)); m_camera->setFOV(0.61f); m_camera->bindTargetAndRotation(true); // no "look-at" diff --git a/src/modes/follow_the_leader.cpp b/src/modes/follow_the_leader.cpp index 00ca1e942..7b29a8653 100644 --- a/src/modes/follow_the_leader.cpp +++ b/src/modes/follow_the_leader.cpp @@ -101,11 +101,23 @@ int FollowTheLeaderRace::getScoreForPosition(int p) return m_score_for_position[p - 2]; } // getScoreForPosition +//----------------------------------------------------------------------------- +const btTransform &FollowTheLeaderRace::getStartTransform(int index) +{ + if (index == 0) // Leader start position + return m_track->getStartTransform(index); + + // Otherwise the karts will start at the rear starting positions + int start_index = stk_config->m_max_karts + - race_manager->getNumberOfKarts() + index; + return m_track->getStartTransform(start_index); +} // getStartTransform + //----------------------------------------------------------------------------- /** 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. */ -float FollowTheLeaderRace::getClockStartTime() +float FollowTheLeaderRace::getClockStartTime() const { return m_leader_intervals[0]; } // getClockStartTime diff --git a/src/modes/follow_the_leader.hpp b/src/modes/follow_the_leader.hpp index 939f54129..da5fe1f6d 100644 --- a/src/modes/follow_the_leader.hpp +++ b/src/modes/follow_the_leader.hpp @@ -48,14 +48,19 @@ public: // overriding World methods virtual void reset() OVERRIDE; virtual const std::string& getIdent() const OVERRIDE; - virtual float getClockStartTime(); - virtual bool useFastMusicNearEnd() const OVERRIDE { return false; } + virtual const btTransform &getStartTransform(int index); + virtual float getClockStartTime() const; virtual void getKartsDisplayInfo( std::vector *info) OVERRIDE; virtual void init() OVERRIDE; virtual void terminateRace() OVERRIDE; virtual bool isRaceOver() OVERRIDE; + // ------------------------------------------------------------------------ + /** Returns if this type of race has laps. */ virtual bool raceHasLaps() OVERRIDE { return false; } + // ------------------------------------------------------------------------ + /** Returns if faster music should be used at the end. */ + virtual bool useFastMusicNearEnd() const OVERRIDE { return false; } }; // FollowTheLeader diff --git a/src/modes/profile_world.cpp b/src/modes/profile_world.cpp index 0fef5edc7..7015a7b13 100644 --- a/src/modes/profile_world.cpp +++ b/src/modes/profile_world.cpp @@ -108,7 +108,7 @@ AbstractKart *ProfileWorld::createKart(const std::string &kart_ident, int index, RaceManager::KartType type, const PlayerDifficulty *difficulty) { - btTransform init_pos = m_track->getStartTransform(index); + btTransform init_pos = getStartTransform(index); Kart *new_kart = new KartWithStats(kart_ident, /*world kart id*/ index, diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp index dcba80e8c..0fc8f553c 100644 --- a/src/modes/soccer_world.cpp +++ b/src/modes/soccer_world.cpp @@ -336,7 +336,7 @@ void SoccerWorld::moveKartAfterRescue(AbstractKart* kart) { // no need for the overhead to compute exact distance with sqrt(), // so using the 'manhattan' heuristic which will do fine enough. - const btTransform &s = world->getTrack()->getStartTransform(n); + const btTransform &s = getStartTransform(n); const Vec3 &v=s.getOrigin(); float accumulatedDistance = .0f; bool spawnPointClear = true; @@ -368,7 +368,7 @@ void SoccerWorld::moveKartAfterRescue(AbstractKart* kart) } assert(furthest_id_found != -1); - const btTransform &s = world->getTrack()->getStartTransform(furthest_id_found); + const btTransform &s = getStartTransform(furthest_id_found); const Vec3 &xyz = s.getOrigin(); kart->setXYZ(xyz); kart->setRotation(s.getRotation()); @@ -481,7 +481,7 @@ AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index, if(index % 2 != 0) posIndex += 1; } - btTransform init_pos = m_track->getStartTransform(posIndex); + btTransform init_pos = getStartTransform(posIndex); AbstractKart *new_kart = new Kart(kart_ident, index, position, init_pos, difficulty); diff --git a/src/modes/three_strikes_battle.cpp b/src/modes/three_strikes_battle.cpp index aa95da191..d24555bf8 100644 --- a/src/modes/three_strikes_battle.cpp +++ b/src/modes/three_strikes_battle.cpp @@ -497,7 +497,7 @@ unsigned int ThreeStrikesBattle::getRescuePositionIndex(AbstractKart *kart) for(int n=0; ngetStartTransform(n); + const btTransform &s = getStartTransform(n); const Vec3 &v=s.getOrigin(); float accumulated_distance = .0f; bool spawn_point_clear = true; diff --git a/src/modes/world.cpp b/src/modes/world.cpp index f636fe2f2..4224b1763 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -305,9 +305,9 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index, const PlayerDifficulty *difficulty) { int position = index+1; - btTransform init_pos = m_track->getStartTransform(index); + btTransform init_pos = getStartTransform(index); AbstractKart *new_kart = new Kart(kart_ident, index, position, init_pos, - difficulty); + difficulty); new_kart->init(race_manager->getKartType(index)); Controller *controller = NULL; switch(kart_type) @@ -337,6 +337,14 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index, return new_kart; } // createKart +//----------------------------------------------------------------------------- +/** Returns the start coordinates for a kart with a given index. + * \param index Index of kart ranging from 0 to kart_num-1. */ +const btTransform &World::getStartTransform(int index) +{ + return m_track->getStartTransform(index); +} // getStartTransform + //----------------------------------------------------------------------------- /** Creates an AI controller for the kart. * \param kart The kart to be controlled by an AI. diff --git a/src/modes/world.hpp b/src/modes/world.hpp index fef41591b..94c6ccb39 100644 --- a/src/modes/world.hpp +++ b/src/modes/world.hpp @@ -294,6 +294,7 @@ public: PhysicalObject *object); AbstractKart* getPlayerKart(unsigned int player) const; AbstractKart* getLocalPlayerKart(unsigned int n) const; + virtual const btTransform &getStartTransform(int index); // ------------------------------------------------------------------------ /** Returns a pointer to the race gui. */ RaceGUIBase *getRaceGUI() const { return m_race_gui;} diff --git a/src/modes/world_with_rank.cpp b/src/modes/world_with_rank.cpp index e34a4fe91..9482d1f95 100644 --- a/src/modes/world_with_rank.cpp +++ b/src/modes/world_with_rank.cpp @@ -149,7 +149,7 @@ unsigned int WorldWithRank::getRescuePositionIndex(AbstractKart *kart) for (int n=0; ngetStartTransform(n); + const btTransform &s = getStartTransform(n); const Vec3 &v = s.getOrigin(); float abs_distance = (v - kart->getXYZ()).length(); diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 89b3aa614..9880be647 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -1736,7 +1736,14 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) if (!m_is_arena && !m_is_soccer && !m_is_cutscene) { - m_start_transforms.resize(race_manager->getNumberOfKarts()); + if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_FOLLOW_LEADER) + { + // In a FTL race the non-leader karts are placed at the end of the + // field, so we need all start positions. + m_start_transforms.resize(stk_config->m_max_karts); + } + else + m_start_transforms.resize(race_manager->getNumberOfKarts()); QuadGraph::get()->setDefaultStartPositions(&m_start_transforms, karts_per_row, forwards_distance, diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 23b88e997..5ac4daa79 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -523,7 +523,7 @@ public: // ------------------------------------------------------------------------ /** Returns the start coordinates for a kart with a given index. * \param index Index of kart ranging from 0 to kart_num-1. */ - btTransform getStartTransform (unsigned int index) const + const btTransform& getStartTransform (unsigned int index) const { if (index >= m_start_transforms.size()) Log::fatal("Track", "No start position for kart %i.", index); From bf858dd3ff84c43fde59b2aa5055e75257f871bb Mon Sep 17 00:00:00 2001 From: hiker Date: Thu, 30 Jul 2015 17:14:18 +1000 Subject: [PATCH 20/40] Fixed compiler warning. --- src/guiengine/widgets/icon_button_widget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guiengine/widgets/icon_button_widget.cpp b/src/guiengine/widgets/icon_button_widget.cpp index 587527738..9093ec7e6 100644 --- a/src/guiengine/widgets/icon_button_widget.cpp +++ b/src/guiengine/widgets/icon_button_widget.cpp @@ -182,7 +182,7 @@ void IconButtonWidget::add() x1 += diff; x2 += diff; } - else if (x2 > irr_driver->getActualScreenSize().Width) + else if (x2 > (int)irr_driver->getActualScreenSize().Width) { int diff = x2 - irr_driver->getActualScreenSize().Width; x2 -= diff; From a9761e30da60abc1576182cf9863f480c23106e8 Mon Sep 17 00:00:00 2001 From: Tobias Markus Date: Thu, 30 Jul 2015 18:46:01 +0200 Subject: [PATCH 21/40] Fix various issues reported by coverity --- src/states_screens/options_screen_audio.cpp | 3 ++- src/states_screens/options_screen_input.cpp | 3 ++- src/states_screens/options_screen_input2.cpp | 4 ++-- src/states_screens/options_screen_ui.cpp | 3 ++- src/states_screens/options_screen_video.cpp | 3 ++- src/states_screens/user_screen.cpp | 3 ++- 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/states_screens/options_screen_audio.cpp b/src/states_screens/options_screen_audio.cpp index 734c12a2d..799bab896 100644 --- a/src/states_screens/options_screen_audio.cpp +++ b/src/states_screens/options_screen_audio.cpp @@ -59,7 +59,8 @@ void OptionsScreenAudio::init() { Screen::init(); RibbonWidget* ribbon = this->getWidget("options_choice"); - if (ribbon != NULL) ribbon->select( "tab_audio", PLAYER_ID_GAME_MASTER ); + assert(ribbon != NULL); + ribbon->select( "tab_audio", PLAYER_ID_GAME_MASTER ); ribbon->getRibbonChildren()[0].setTooltip( _("Graphics") ); ribbon->getRibbonChildren()[2].setTooltip( _("User Interface") ); diff --git a/src/states_screens/options_screen_input.cpp b/src/states_screens/options_screen_input.cpp index 98aec63d1..7b8e970b6 100644 --- a/src/states_screens/options_screen_input.cpp +++ b/src/states_screens/options_screen_input.cpp @@ -133,7 +133,8 @@ void OptionsScreenInput::init() { Screen::init(); RibbonWidget* tabBar = this->getWidget("options_choice"); - if (tabBar != NULL) tabBar->select( "tab_controls", PLAYER_ID_GAME_MASTER ); + assert(tabBar != NULL); + tabBar->select( "tab_controls", PLAYER_ID_GAME_MASTER ); tabBar->getRibbonChildren()[0].setTooltip( _("Graphics") ); tabBar->getRibbonChildren()[1].setTooltip( _("Audio") ); diff --git a/src/states_screens/options_screen_input2.cpp b/src/states_screens/options_screen_input2.cpp index 3832765d2..363860e07 100644 --- a/src/states_screens/options_screen_input2.cpp +++ b/src/states_screens/options_screen_input2.cpp @@ -79,8 +79,8 @@ void OptionsScreenInput2::init() { Screen::init(); RibbonWidget* tabBar = getWidget("options_choice"); - if (tabBar != NULL) tabBar->select( "tab_controls", - PLAYER_ID_GAME_MASTER ); + assert(tabBar != NULL); + tabBar->select( "tab_controls", PLAYER_ID_GAME_MASTER ); tabBar->getRibbonChildren()[0].setTooltip( _("Graphics") ); tabBar->getRibbonChildren()[1].setTooltip( _("Audio") ); diff --git a/src/states_screens/options_screen_ui.cpp b/src/states_screens/options_screen_ui.cpp index 2358035d4..8d301eeaf 100644 --- a/src/states_screens/options_screen_ui.cpp +++ b/src/states_screens/options_screen_ui.cpp @@ -112,7 +112,8 @@ void OptionsScreenUI::init() { Screen::init(); RibbonWidget* ribbon = getWidget("options_choice"); - if (ribbon != NULL) ribbon->select( "tab_ui", PLAYER_ID_GAME_MASTER ); + assert(ribbon != NULL); + ribbon->select( "tab_ui", PLAYER_ID_GAME_MASTER ); ribbon->getRibbonChildren()[0].setTooltip( _("Graphics") ); ribbon->getRibbonChildren()[1].setTooltip( _("Audio") ); diff --git a/src/states_screens/options_screen_video.cpp b/src/states_screens/options_screen_video.cpp index 5981a9cce..6939a9e15 100644 --- a/src/states_screens/options_screen_video.cpp +++ b/src/states_screens/options_screen_video.cpp @@ -159,7 +159,8 @@ void OptionsScreenVideo::init() { Screen::init(); RibbonWidget* ribbon = getWidget("options_choice"); - if (ribbon != NULL) ribbon->select( "tab_video", PLAYER_ID_GAME_MASTER ); + assert(ribbon != NULL); + ribbon->select( "tab_video", PLAYER_ID_GAME_MASTER ); ribbon->getRibbonChildren()[1].setTooltip( _("Audio") ); ribbon->getRibbonChildren()[2].setTooltip( _("User Interface") ); diff --git a/src/states_screens/user_screen.cpp b/src/states_screens/user_screen.cpp index 7c7e7d3c0..64e846f4f 100644 --- a/src/states_screens/user_screen.cpp +++ b/src/states_screens/user_screen.cpp @@ -631,7 +631,8 @@ void BaseUserScreen::unloaded() void TabbedUserScreen::init() { RibbonWidget* tab_bar = getWidget("options_choice"); - if (tab_bar) tab_bar->select("tab_players", PLAYER_ID_GAME_MASTER); + assert(tab_bar != NULL); + tab_bar->select("tab_players", PLAYER_ID_GAME_MASTER); tab_bar->getRibbonChildren()[0].setTooltip( _("Graphics") ); tab_bar->getRibbonChildren()[1].setTooltip( _("Audio") ); tab_bar->getRibbonChildren()[2].setTooltip( _("User Interface") ); From 25c1880c183c0cb18ef4ae5bad7014e1a5d3f333 Mon Sep 17 00:00:00 2001 From: hiker Date: Fri, 31 Jul 2015 07:49:54 +1000 Subject: [PATCH 22/40] Fixed rescue in soccer mode (which would previously used World's moveKartAfterRescue, not its own custom function). --- src/modes/world.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modes/world.hpp b/src/modes/world.hpp index 94c6ccb39..69e5bf538 100644 --- a/src/modes/world.hpp +++ b/src/modes/world.hpp @@ -231,7 +231,7 @@ public: /** Returns the bullet transformation for the specified rescue index. */ virtual btTransform getRescueTransform(unsigned int index) const = 0; // ------------------------------------------------------------------------ - void moveKartAfterRescue(AbstractKart* kart); + virtual void moveKartAfterRescue(AbstractKart* kart); // ------------------------------------------------------------------------ /** Called when it is needed to know whether this kind of race involves * counting laps. */ From 431853b451ee8e91ab6c207cd476509b6835957f Mon Sep 17 00:00:00 2001 From: hiker Date: Fri, 31 Jul 2015 15:45:25 +1000 Subject: [PATCH 23/40] Removed some unused code, added better error message in case stk_config.xml could not be found. --- src/io/file_manager.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/io/file_manager.cpp b/src/io/file_manager.cpp index ef193ae13..1ddf9271c 100644 --- a/src/io/file_manager.cpp +++ b/src/io/file_manager.cpp @@ -181,14 +181,22 @@ FileManager::FileManager() { #ifdef SUPERTUXKART_DATADIR root_dir = SUPERTUXKART_DATADIR"/data/"; - if(root_dir.size()==0 || root_dir[root_dir.size()-1]!='/') - root_dir+='/'; - #else root_dir = "/usr/local/share/games/supertuxkart/"; #endif } + if (!m_file_system->existFile((root_dir + "stk_config.xml").c_str())) + { + Log::error("FileManager", "Could not file stk_config.xml in any " + "standard location (esp. ../data)."); + Log::error("FileManager", + "Last location checked '%s'.", root_dir.c_str()); + Log::fatal("FileManager", + "Set $SUPERTUXKART_DATADIR to point to the data directory."); + // fatal will exit the application + } + addRootDirs(root_dir); if( fileExists(root_dir+"../../stk-assets")) addRootDirs(root_dir+"../../stk-assets"); From a81366c4140ec5610c9d8fbfaf4b1b23720980e5 Mon Sep 17 00:00:00 2001 From: hiker Date: Fri, 31 Jul 2015 16:27:52 +1000 Subject: [PATCH 24/40] Removed rescue-code duplication in battle mode and soccer mode. --- src/modes/overworld.cpp | 31 +++++++++++ src/modes/overworld.hpp | 1 + src/modes/soccer_world.cpp | 82 ------------------------------ src/modes/soccer_world.hpp | 3 +- src/modes/three_strikes_battle.cpp | 50 ------------------ src/modes/three_strikes_battle.hpp | 1 - src/modes/world_with_rank.cpp | 51 +++++++++++++------ 7 files changed, 68 insertions(+), 151 deletions(-) diff --git a/src/modes/overworld.cpp b/src/modes/overworld.cpp index 0f5166caa..ba7e7df2d 100644 --- a/src/modes/overworld.cpp +++ b/src/modes/overworld.cpp @@ -160,6 +160,37 @@ void OverWorld::update(float dt) } } // update +// ---------------------------------------------------------------------------- +/** Finds the starting position which is closest to the kart. + * \param kart The kart for which a rescue position needs to be determined. + */ +unsigned int OverWorld::getRescuePositionIndex(AbstractKart *kart) +{ + // find closest point to drop kart on + const int start_spots_amount = getNumberOfRescuePositions(); + assert(start_spots_amount > 0); + + int closest_id = -1; + float closest_distance = 999999999.0f; + + for (int n=0; ngetXYZ()).length(); + + if (abs_distance < closest_distance) + { + closest_distance = abs_distance; + closest_id = n; + } + } + + assert(closest_id != -1); + return closest_id; +} // getRescuePositionIndex + //----------------------------------------------------------------------------- /** This function is not used in the overworld race gui. */ diff --git a/src/modes/overworld.hpp b/src/modes/overworld.hpp index 4001f0faa..62d510994 100644 --- a/src/modes/overworld.hpp +++ b/src/modes/overworld.hpp @@ -48,6 +48,7 @@ public: static void enterOverWorld(); virtual void update(float delta) OVERRIDE; + unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE; virtual void getKartsDisplayInfo( std::vector *info) OVERRIDE; // ------------------------------------------------------------------------ diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp index 0fc8f553c..2b18d14f6 100644 --- a/src/modes/soccer_world.cpp +++ b/src/modes/soccer_world.cpp @@ -315,88 +315,6 @@ void SoccerWorld::getKartsDisplayInfo( */ } // getKartsDisplayInfo -//----------------------------------------------------------------------------- -/** Moves a kart to its rescue position. - * \param kart The kart that was rescued. - */ -void SoccerWorld::moveKartAfterRescue(AbstractKart* kart) -{ - // find closest point to drop kart on - World *world = World::getWorld(); - const int start_spots_amount = world->getTrack()->getNumberOfStartPositions(); - assert(start_spots_amount > 0); - - float largest_accumulated_distance_found = -1; - int furthest_id_found = -1; - - const float kart_x = kart->getXYZ().getX(); - const float kart_z = kart->getXYZ().getZ(); - - for(int n=0; ngetKart(k); - const float currentKart_x = currentKart->getXYZ().getX(); - const float currentKartk_z = currentKart->getXYZ().getZ(); - - if(kart_x!=currentKart_x && kart_z !=currentKartk_z) - { - float absDistance = fabs(currentKart_x - v.getX()) + - fabs(currentKartk_z - v.getZ()); - if(absDistance < CLEAR_SPAWN_RANGE) - { - spawnPointClear = false; - break; - } - accumulatedDistance += absDistance; - } - } - - if(largest_accumulated_distance_found < accumulatedDistance && spawnPointClear) - { - furthest_id_found = n; - largest_accumulated_distance_found = accumulatedDistance; - } - } - - assert(furthest_id_found != -1); - const btTransform &s = getStartTransform(furthest_id_found); - const Vec3 &xyz = s.getOrigin(); - kart->setXYZ(xyz); - kart->setRotation(s.getRotation()); - - //position kart from same height as in World::resetAllKarts - btTransform pos; - pos.setOrigin(kart->getXYZ()+btVector3(0, 0.5f*kart->getKartHeight(), 0.0f)); - pos.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 0 /* angle */) ); - - kart->getBody()->setCenterOfMassTransform(pos); - - //project kart to surface of track - bool kart_over_ground = m_track->findGround(kart); - - if (kart_over_ground) - { - //add vertical offset so that the kart starts off above the track - float vertical_offset = kart->getKartProperties()->getVertRescueOffset() * - kart->getKartHeight(); - kart->getBody()->translate(btVector3(0, vertical_offset, 0)); - } - else - { - Log::warn("[SoccerWorld]", " Invalid position after rescue for kart %s on track %s.", - kart->getIdent().c_str(), m_track->getIdent().c_str()); - } -} // moveKartAfterRescue - //----------------------------------------------------------------------------- /** Set position and team for the karts */ void SoccerWorld::initKartList() diff --git a/src/modes/soccer_world.hpp b/src/modes/soccer_world.hpp index d33f1dd74..8d896d47c 100644 --- a/src/modes/soccer_world.hpp +++ b/src/modes/soccer_world.hpp @@ -76,8 +76,7 @@ public: virtual void getKartsDisplayInfo( std::vector *info); int getScore(unsigned int i); - virtual bool raceHasLaps(){ return false; } - virtual void moveKartAfterRescue(AbstractKart* kart); + virtual bool raceHasLaps() { return false; } virtual const std::string& getIdent() const; diff --git a/src/modes/three_strikes_battle.cpp b/src/modes/three_strikes_battle.cpp index d24555bf8..6fa48f882 100644 --- a/src/modes/three_strikes_battle.cpp +++ b/src/modes/three_strikes_battle.cpp @@ -477,53 +477,3 @@ void ThreeStrikesBattle::getKartsDisplayInfo( } } // getKartsDisplayInfo -//----------------------------------------------------------------------------- -/** Determines the rescue position for a kart. The rescue position is the - * start position which is has the biggest accumulated distance to all other - * karts, and which has no other kart very close. The latter avoids dropping - * a kart on top of another kart. - * \param kart The kart that is going to be rescued. - * \returns The index of the start position to which the rescued kart - * should be moved to. - */ - -unsigned int ThreeStrikesBattle::getRescuePositionIndex(AbstractKart *kart) -{ - const int start_spots_amount = getTrack()->getNumberOfStartPositions(); - assert(start_spots_amount > 0); - - float largest_accumulated_distance_found = -1; - int furthest_id_found = -1; - - for(int n=0; ngetWorldKartId()==k) continue; - float abs_distance2 = (getKart(k)->getXYZ()-v).length2_2d(); - const float CLEAR_SPAWN_RANGE2 = 5*5; - if( abs_distance2 < CLEAR_SPAWN_RANGE2) - { - spawn_point_clear = false; - break; - } - accumulated_distance += sqrt(abs_distance2); - } - - if(accumulated_distance > largest_accumulated_distance_found && - spawn_point_clear) - { - furthest_id_found = n; - largest_accumulated_distance_found = accumulated_distance; - } - } - - assert(furthest_id_found != -1); - return furthest_id_found; -} // getRescuePositionIndex - diff --git a/src/modes/three_strikes_battle.hpp b/src/modes/three_strikes_battle.hpp index 46a18674c..fe09b9340 100644 --- a/src/modes/three_strikes_battle.hpp +++ b/src/modes/three_strikes_battle.hpp @@ -97,7 +97,6 @@ public: virtual void getKartsDisplayInfo( std::vector *info); virtual bool raceHasLaps(){ return false; } - virtual unsigned int getRescuePositionIndex(AbstractKart *kart); virtual const std::string& getIdent() const; diff --git a/src/modes/world_with_rank.cpp b/src/modes/world_with_rank.cpp index 9482d1f95..f24ef58c3 100644 --- a/src/modes/world_with_rank.cpp +++ b/src/modes/world_with_rank.cpp @@ -134,35 +134,54 @@ unsigned int WorldWithRank::getNumberOfRescuePositions() const return getTrack()->getNumberOfStartPositions(); } // getNumberOfRescuePositions -// ---------------------------------------------------------------------------- -/** Finds the starting position which is closest to the kart. - * \param kart The kart for which a rescue position needs to be determined. +//----------------------------------------------------------------------------- +/** Determines the rescue position for a kart. The rescue position is the + * start position which is has the biggest accumulated distance to all other + * karts, and which has no other kart very close. The latter avoids dropping + * a kart on top of another kart. This is the method used + * \param kart The kart that is going to be rescued. + * \returns The index of the start position to which the rescued kart + * should be moved to. */ + unsigned int WorldWithRank::getRescuePositionIndex(AbstractKart *kart) { - // find closest point to drop kart on - const int start_spots_amount = getNumberOfRescuePositions(); + const int start_spots_amount = getTrack()->getNumberOfStartPositions(); assert(start_spots_amount > 0); - int closest_id = -1; - float closest_distance = 999999999.0f; + float largest_accumulated_distance_found = -1; + int furthest_id_found = -1; - for (int n=0; ngetXYZ()).length(); - - if (abs_distance < closest_distance) + for(unsigned int k=0; kgetWorldKartId()==k) continue; + float abs_distance2 = (getKart(k)->getXYZ()-v).length2_2d(); + const float CLEAR_SPAWN_RANGE2 = 5*5; + if( abs_distance2 < CLEAR_SPAWN_RANGE2) + { + spawn_point_clear = false; + break; + } + accumulated_distance += sqrt(abs_distance2); + } + + if(accumulated_distance > largest_accumulated_distance_found && + spawn_point_clear) + { + furthest_id_found = n; + largest_accumulated_distance_found = accumulated_distance; } } - assert(closest_id != -1); - return closest_id; + assert(furthest_id_found != -1); + return furthest_id_found; } // getRescuePositionIndex // ---------------------------------------------------------------------------- From 78c592e4e5b816d02afea137e7f4021fd852db1e Mon Sep 17 00:00:00 2001 From: hiker Date: Fri, 31 Jul 2015 22:06:21 +1000 Subject: [PATCH 25/40] Added a file with a 'unique filename' with version number which is used by STK to detect that stk is reading the right data files (and therefore avoids #2073, in which stk finds the wrong data directory). --- data/supertuxkart.git | 2 ++ src/io/file_manager.cpp | 29 ++++++++++++++++------------- src/io/file_manager.hpp | 8 ++++++++ src/main.cpp | 2 +- 4 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 data/supertuxkart.git diff --git a/data/supertuxkart.git b/data/supertuxkart.git new file mode 100644 index 000000000..b37a12b9c --- /dev/null +++ b/data/supertuxkart.git @@ -0,0 +1,2 @@ +This file is only here to help STK finding the right directory, +and to avoid problems with other directories called 'data'. diff --git a/src/io/file_manager.cpp b/src/io/file_manager.cpp index 1ddf9271c..e969b87b9 100644 --- a/src/io/file_manager.cpp +++ b/src/io/file_manager.cpp @@ -142,7 +142,7 @@ FileManager::FileManager() m_file_system = irr::io::createFileSystem(); - irr::io::path exe_path; + std::string exe_path; // Search for the root directory // ============================= @@ -151,8 +151,11 @@ FileManager::FileManager() // This is esp. useful for Visual Studio, since it's not necessary // to define the working directory when debugging, it works automatically. std::string root_dir; - if(m_file_system->existFile(CommandLine::getExecName().c_str())) - exe_path = m_file_system->getFileDir(CommandLine::getExecName().c_str()); + const std::string version = std::string("supertuxkart.") + STK_VERSION; + if (fileExists(CommandLine::getExecName())) + { + exe_path = StringUtils::getPath(CommandLine::getExecName()); + } if(exe_path.size()==0 || exe_path[exe_path.size()-1]!='/') exe_path += "/"; if ( getenv ( "SUPERTUXKART_DATADIR" ) != NULL ) @@ -160,19 +163,19 @@ FileManager::FileManager() #ifdef __APPLE__ else if( macSetBundlePathIfRelevant( root_dir ) ) { root_dir = root_dir + "data/"; } #endif - else if(m_file_system->existFile("data/stk_config.xml")) + else if(fileExists("data/", version)) root_dir = "data/" ; - else if(m_file_system->existFile("../data/stk_config.xml")) + else if(fileExists("../data/", version)) root_dir = "../data/" ; - else if(m_file_system->existFile("../../data/stk_config.xml")) + else if(fileExists("../../data/", version)) root_dir = "../../data/" ; // Test for old style build environment, with executable in root of stk - else if(m_file_system->existFile(exe_path+"data/stk_config.xml")) + else if(fileExists(exe_path+"data/"+version)) root_dir = (exe_path+"data/").c_str(); // Check for windows cmake style: bld/Debug/bin/supertuxkart.exe - else if (m_file_system->existFile(exe_path + "../../../data/stk_config.xml")) - root_dir = (exe_path + "../../../data/").c_str(); - else if (m_file_system->existFile(exe_path + "../data/stk_config.xml")) + else if (fileExists(exe_path + "../../../data/"+version)) + root_dir = exe_path + "../../../data/"; + else if (fileExists(exe_path + "../data/"+version)) { root_dir = exe_path.c_str(); root_dir += "../data/"; @@ -186,10 +189,10 @@ FileManager::FileManager() #endif } - if (!m_file_system->existFile((root_dir + "stk_config.xml").c_str())) + if (!m_file_system->existFile((root_dir + version).c_str())) { - Log::error("FileManager", "Could not file stk_config.xml in any " - "standard location (esp. ../data)."); + Log::error("FileManager", "Could not file '%s'in any " + "standard location (esp. ../data).", version.c_str()); Log::error("FileManager", "Last location checked '%s'.", root_dir.c_str()); Log::fatal("FileManager", diff --git a/src/io/file_manager.hpp b/src/io/file_manager.hpp index 1c0e7a6b6..0231365e0 100644 --- a/src/io/file_manager.hpp +++ b/src/io/file_manager.hpp @@ -134,6 +134,14 @@ public: std::string searchTexture(const std::string& fname) const; std::string getUserConfigFile(const std::string& fname) const; bool fileExists(const std::string& path) const; + // ------------------------------------------------------------------------ + /** Convenience function to save some typing in the + * file manager constructor. */ + bool fileExists(const char *prefix, const std::string& path) const + { + return fileExists(std::string(prefix) + path); + } + // ------------------------------------------------------------------------ void listFiles (std::set& result, const std::string& dir, bool make_full_path=false) const; diff --git a/src/main.cpp b/src/main.cpp index 3c6975a2e..9d6e1088c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1078,7 +1078,7 @@ int handleCmdLine() void initUserConfig() { file_manager = new FileManager(); - user_config = new UserConfig(); // needs file_manager + user_config = new UserConfig(); // needs file_manager user_config->loadConfig(); // Some parts of the file manager needs user config (paths for models // depend on artist debug flag). So init the rest of the file manager From 2f902f769d29867ef33e1521f8016b575c373144 Mon Sep 17 00:00:00 2001 From: hiker Date: Sat, 1 Aug 2015 22:02:00 +1000 Subject: [PATCH 26/40] Fixed minor memory leak. --- src/states_screens/dialogs/addons_loading.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/states_screens/dialogs/addons_loading.cpp b/src/states_screens/dialogs/addons_loading.cpp index 723460fba..3f0f0d8ec 100644 --- a/src/states_screens/dialogs/addons_loading.cpp +++ b/src/states_screens/dialogs/addons_loading.cpp @@ -331,12 +331,15 @@ void AddonsLoading::stopDownload() // (and not uninstalling an installed one): if(m_download_request) { - // In case of a cancel we can't free the memory, since - // network_http will potentially update the request. So in - // order to avoid a memory leak, we let network_http free - // the request. - //m_download_request->setManageMemory(true); + // In case of a cancel we can't free the memory, since the + // request manager thread is potentially working on this request. So + // in order to avoid a memory leak, we let the request manager + // free the data. This is thread safe since freeing the data is done + // when the request manager handles the result queue - and this is + // done by the main thread (i.e. this thread). + m_download_request->setManageMemory(true); m_download_request->cancel(); + m_download_request = NULL; }; } // startDownload From 085627364cb91b5038e208a819e3120bcdbdcd59 Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 3 Aug 2015 07:53:21 +1000 Subject: [PATCH 27/40] Fix #2162 (switch kart when loading a GP). --- src/config/saved_grand_prix.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config/saved_grand_prix.cpp b/src/config/saved_grand_prix.cpp index 779204f45..7f87262f7 100644 --- a/src/config/saved_grand_prix.cpp +++ b/src/config/saved_grand_prix.cpp @@ -173,9 +173,10 @@ void SavedGrandPrix::loadKarts(std::vector & kart_list) { if(kart_list[x].m_local_player_id == m_karts[i].m_local_player_id) { + kart_list[x].m_ident = m_karts[i].m_ident; kart_list[x].m_score = m_karts[i].m_score; kart_list[x].m_overall_time = m_karts[i].m_overall_time; - } // if kart_list[x].m_local_player_id == m_karts[i].,_local + } // if kart_list[x].m_local_player_id == m_karts[i].local } // for x } // if m_local_player_id == -1 } // for i From a852cf94fb8d562765c91c06450b1c4c1a7beff4 Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 3 Aug 2015 15:10:36 +1000 Subject: [PATCH 28/40] Don't save random GPs (which can not be continued anyway), and allow only one saved data set (for each GP and difficulty). Previously saved 'random' GPs (which can't be continued anyway) are deleted now, cleaning up the config.xml file. --- src/race/race_manager.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/race/race_manager.cpp b/src/race/race_manager.cpp index 056624d22..450d43e95 100644 --- a/src/race/race_manager.cpp +++ b/src/race/race_manager.cpp @@ -546,7 +546,7 @@ void RaceManager::saveGP() m_saved_gp->setKarts(m_kart_status); m_saved_gp->setNextTrack(m_track_number); } - else + else if (m_grand_prix.getId() != "random") { m_saved_gp = new SavedGrandPrix( StateManager::get()->getActivePlayerProfile(0)->getUniqueID(), @@ -556,12 +556,30 @@ void RaceManager::saveGP() m_track_number, m_grand_prix.getReverseType(), m_kart_status); - + + // If a new GP is saved, delete any other saved data for this + // GP at the same difficulty (even if #karts is different, otherwise + // the user has to remember the number of AI karts, with no indication + // on which ones are saved). + for (unsigned int i = 0; + i < UserConfigParams::m_saved_grand_prix_list.size();) + { + // Delete other save files (and random GP, which should never + // have been saved in the first place) + const SavedGrandPrix &sgp = UserConfigParams::m_saved_grand_prix_list[i]; + if (sgp.getGPID() == "random" || + (sgp.getGPID() == m_saved_gp->getGPID() && + sgp.getDifficulty() == m_saved_gp->getDifficulty()) ) + { + UserConfigParams::m_saved_grand_prix_list.erase(i); + } + else i++; + } UserConfigParams::m_saved_grand_prix_list.push_back(m_saved_gp); } user_config->saveConfig(); -} +} // saveGP //----------------------------------------------------------------------------- From 8d0cad3cb8705bad0418a2ddb562719e6e8e80e4 Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 3 Aug 2015 15:44:44 +1000 Subject: [PATCH 29/40] Use proper call instead of hard coded constant. --- src/race/race_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/race/race_manager.cpp b/src/race/race_manager.cpp index 450d43e95..924a1c98d 100644 --- a/src/race/race_manager.cpp +++ b/src/race/race_manager.cpp @@ -546,7 +546,7 @@ void RaceManager::saveGP() m_saved_gp->setKarts(m_kart_status); m_saved_gp->setNextTrack(m_track_number); } - else if (m_grand_prix.getId() != "random") + else if(!m_grand_prix.isRandomGP()) { m_saved_gp = new SavedGrandPrix( StateManager::get()->getActivePlayerProfile(0)->getUniqueID(), From 6f11156c0434ccb46baab010dd83c284e967d40e Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 3 Aug 2015 22:02:13 +1000 Subject: [PATCH 30/40] Fixed crash if a player kart in a saved GP is deleted. --- src/config/saved_grand_prix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/saved_grand_prix.cpp b/src/config/saved_grand_prix.cpp index 7f87262f7..98f57a729 100644 --- a/src/config/saved_grand_prix.cpp +++ b/src/config/saved_grand_prix.cpp @@ -173,7 +173,7 @@ void SavedGrandPrix::loadKarts(std::vector & kart_list) { if(kart_list[x].m_local_player_id == m_karts[i].m_local_player_id) { - kart_list[x].m_ident = m_karts[i].m_ident; + if(kp) kart_list[x].m_ident = m_karts[i].m_ident; kart_list[x].m_score = m_karts[i].m_score; kart_list[x].m_overall_time = m_karts[i].m_overall_time; } // if kart_list[x].m_local_player_id == m_karts[i].local From 340dec329c3a726814cec23a52ea71be4cdd9c62 Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 3 Aug 2015 23:25:11 +1000 Subject: [PATCH 31/40] Support to mirror a texture around U or V axis if a track is driven in reverse. --- src/graphics/material.cpp | 27 +++++++++++++-------------- src/graphics/material.hpp | 8 ++++++++ src/tracks/track.cpp | 12 ++++++++++++ 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/graphics/material.cpp b/src/graphics/material.cpp index 5501fd6b4..e0de3cd7c 100644 --- a/src/graphics/material.cpp +++ b/src/graphics/material.cpp @@ -84,21 +84,19 @@ Material::Material(const XMLNode *node, bool deprecated) std::string s; - //node->get("adjust-image", &s ); - //if(s=="premultiply") - // m_adjust_image = ADJ_PREMUL; - //else if (s=="divide") - // m_adjust_image = ADJ_DIV; - //else if (s=="" || s=="none") - // m_adjust_image = ADJ_NONE; - //else - // Log::warn("material", - // "Incorrect adjust-image specification: '%s' - ignored.", - // s.c_str()); - - node->get("high-adhesion", &m_high_tire_adhesion); - node->get("reset", &m_drive_reset ); + node->get("high-adhesion", &m_high_tire_adhesion ); + node->get("reset", &m_drive_reset ); + s = ""; + node->get("mirror-axis", &s); + if (s == "u") + s = "U"; + else if (s == "v") + s = "V"; + if (s != "U" && s != "V") + m_mirror_axis_when_reverse = ' '; + else + m_mirror_axis_when_reverse = s[0]; // backwards compatibility bool crash_reset = false; node->get("crash-reset", &crash_reset ); @@ -433,6 +431,7 @@ void Material::init() m_surface = false; m_ignore = false; m_drive_reset = false; + m_mirror_axis_when_reverse = ' '; m_collision_reaction = NORMAL; m_disable_z_write = false; m_water_shader_speed_1 = 6.6667f; diff --git a/src/graphics/material.hpp b/src/graphics/material.hpp index 692adfb57..2fa7cb2ac 100644 --- a/src/graphics/material.hpp +++ b/src/graphics/material.hpp @@ -156,6 +156,11 @@ private: bool m_fog; + /** Either ' ' (no mirroring), 'U' or 'V' if a texture needs to be + * mirrored when driving in reverse. Typically used for arrows indicating + * the direction. */ + char m_mirror_axis_when_reverse; + ParticleKind* m_particles_effects[EMIT_KINDS_COUNT]; /** For normal maps */ @@ -373,6 +378,9 @@ public: // ------------------------------------------------------------------------ ShaderType getShaderType() const { return m_shader_type; } // ------------------------------------------------------------------------ + /** True if this texture should have the U coordinates mirrored. */ + char getMirrorAxisInReverse() const { return m_mirror_axis_when_reverse; } + // ------------------------------------------------------------------------ } ; diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 9880be647..dc6e9538b 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -885,6 +885,18 @@ void Track::convertTrackToBullet(scene::ISceneNode *node) if (mb->getVertexType() == video::EVT_STANDARD) { irr::video::S3DVertex* mbVertices=(video::S3DVertex*)mb->getVertices(); + if (race_manager->getReverseTrack() && + material->getMirrorAxisInReverse() != ' ') + { + for (unsigned int i = 0; i < mb->getVertexCount(); i++) + { + core::vector2df &tc = mb->getTCoords(i); + if (material->getMirrorAxisInReverse() == 'V') + tc.Y = 1 - tc.Y; + else + tc.X = 1 - tc.X; + } + } // reverse track and texture needs mirroring for (unsigned int matrix_index = 0; matrix_index < matrices.size(); matrix_index++) { for (unsigned int j = 0; j < mb->getIndexCount(); j += 3) From 2a56cc6241de30d5e8619a031ef8b82be469ff32 Mon Sep 17 00:00:00 2001 From: hiker Date: Tue, 4 Aug 2015 09:45:38 +1000 Subject: [PATCH 32/40] Fix 2192 (key names like "Left" are not translatable). --- src/input/binding.cpp | 220 ++++++++++++++++++++++++++++-------------- 1 file changed, 147 insertions(+), 73 deletions(-) diff --git a/src/input/binding.cpp b/src/input/binding.cpp index 083a6b3ae..deda31cc3 100644 --- a/src/input/binding.cpp +++ b/src/input/binding.cpp @@ -110,45 +110,85 @@ irr::core::stringw Binding::getAsString() const case 221: s="]"; break; case 222: s="'"; break; #endif - case irr::KEY_LBUTTON : s = "left mouse button"; break; - case irr::KEY_RBUTTON : s = "right mouse button"; break; - case irr::KEY_CANCEL : s = "cancel"; break; - case irr::KEY_MBUTTON : s = "middle mouse button"; break; - case irr::KEY_XBUTTON1 : s = "X1 mouse button"; break; - case irr::KEY_XBUTTON2 : s = "X2 mouse button"; break; - case irr::KEY_BACK : s = "backspace"; break; - case irr::KEY_TAB : s = "tab"; break; - case irr::KEY_CLEAR : s = "clear"; break; - case irr::KEY_RETURN : s = "return"; break; - case irr::KEY_SHIFT : s = "shift"; break; - case irr::KEY_CONTROL : s = "control"; break; - case irr::KEY_MENU : s = "alt/menu"; break; - case irr::KEY_PAUSE : s = "pause"; break; - case irr::KEY_CAPITAL : s = "caps lock"; break; - case irr::KEY_KANA : s = "kana"; break; - case irr::KEY_JUNJA : s = "junja"; break; - case irr::KEY_FINAL : s = "final"; break; - case irr::KEY_ESCAPE : s = "escape"; break; - case irr::KEY_CONVERT : s = "convert"; break; - case irr::KEY_NONCONVERT : s = "nonconvert"; break; - case irr::KEY_ACCEPT : s = "accept"; break; - case irr::KEY_MODECHANGE : s = "modechange"; break; - case irr::KEY_SPACE : s = "space"; break; - case irr::KEY_PRIOR : s = "page up"; break; - case irr::KEY_NEXT : s = "page down"; break; - case irr::KEY_END : s = "end"; break; - case irr::KEY_HOME : s = "home"; break; - case irr::KEY_LEFT : s = "left"; break; - case irr::KEY_UP : s = "up"; break; - case irr::KEY_RIGHT : s = "right"; break; - case irr::KEY_DOWN : s = "down"; break; - case irr::KEY_SELECT : s = "select"; break; - case irr::KEY_PRINT : s = "print"; break; - case irr::KEY_EXECUT : s = "exec"; break; - case irr::KEY_SNAPSHOT : s = "print screen"; break; - case irr::KEY_INSERT : s = "insert"; break; - case irr::KEY_DELETE : s = "delete"; break; - case irr::KEY_HELP : s = "help"; break; + //I18N: input configuration screen: mouse button + case irr::KEY_LBUTTON : s = _("Left Mouse Button"); break; + //I18N: input configuration screen: mouse button + case irr::KEY_RBUTTON : s = _("Right Mouse Button"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_CANCEL : s = _("Cancel"); break; + //I18N: input configuration screen: mouse button + case irr::KEY_MBUTTON : s = _("Middle Mouse Button"); break; + //I18N: input configuration screen: mouse button + case irr::KEY_XBUTTON1 : s = _("X1 Mouse Button"); break; + //I18N: input configuration screen: mouse button + case irr::KEY_XBUTTON2 : s = _("X2 Mouse Button"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_BACK : s = _("Backspace"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_TAB : s = _("Tab"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_CLEAR : s = _("Clear"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_RETURN : s = _("Return"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_SHIFT : s = _("Shift"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_CONTROL : s = _("Control"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_MENU : s = _("Alt/Menu"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_PAUSE : s = _("Pause"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_CAPITAL : s = _("Caps Lock"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_KANA : s = _("Kana"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_JUNJA : s = _("Junja"); break; + //I18N: input configuration screen: keyboard key + //I18N: input configuration screen: keyboard key + case irr::KEY_FINAL : s = _("Final"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_ESCAPE : s = _("Escape"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_CONVERT : s = _("Convert"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NONCONVERT : s = _("Nonconvert"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_ACCEPT : s = _("Accept"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_MODECHANGE : s = _("Modechange"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_SPACE : s = _("Space"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_PRIOR : s = _("Page Up"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NEXT : s = _("Page Down"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_END : s = _("End"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_HOME : s = _("Home"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_LEFT : s = _("Left"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_UP : s = _("Up"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_RIGHT : s = _("Right"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_DOWN : s = _("Down"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_SELECT : s = _("Select"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_PRINT : s = _("Print"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_EXECUT : s = _("Exec"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_SNAPSHOT : s = _("Print Screen"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_INSERT : s = _("Insert"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_DELETE : s = _("Delete"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_HELP : s = _("Help"); break; case irr::KEY_KEY_0 : s = "0"; break; case irr::KEY_KEY_1 : s = "1"; break; case irr::KEY_KEY_2 : s = "2"; break; @@ -185,26 +225,44 @@ irr::core::stringw Binding::getAsString() const case irr::KEY_KEY_X : s = "X"; break; case irr::KEY_KEY_Y : s = "Y"; break; case irr::KEY_KEY_Z : s = "Z"; break; - case irr::KEY_LWIN : s = "Left Logo"; break; - case irr::KEY_RWIN : s = "Right Logo"; break; - case irr::KEY_APPS : s = "apps"; break; - case irr::KEY_SLEEP : s = "sleep"; break; - case irr::KEY_NUMPAD0 : s = "numpad 0"; break; - case irr::KEY_NUMPAD1 : s = "numpad 1"; break; - case irr::KEY_NUMPAD2 : s = "numpad 2"; break; - case irr::KEY_NUMPAD3 : s = "numpad 3"; break; - case irr::KEY_NUMPAD4 : s = "numpad 4"; break; - case irr::KEY_NUMPAD5 : s = "numpad 5"; break; - case irr::KEY_NUMPAD6 : s = "numpad 6"; break; - case irr::KEY_NUMPAD7 : s = "numpad 7"; break; - case irr::KEY_NUMPAD8 : s = "numpad 8"; break; - case irr::KEY_NUMPAD9 : s = "numpad 9"; break; + //I18N: input configuration screen: keyboard key + case irr::KEY_LWIN : s = _("Left Logo"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_RWIN : s = _("Right Logo"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_APPS : s = _("Apps"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_SLEEP : s = _("Sleep"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NUMPAD0 : s = _("Numpad 0"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NUMPAD1 : s = _("Numpad 1"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NUMPAD2 : s = _("Numpad 2"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NUMPAD3 : s = _("Numpad 3"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NUMPAD4 : s = _("Numpad 4"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NUMPAD5 : s = _("Numpad 5"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NUMPAD6 : s = _("Numpad 6"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NUMPAD7 : s = _("Numpad 7"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NUMPAD8 : s = _("Numpad 8"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NUMPAD9 : s = _("Numpad 9"); break; case irr::KEY_MULTIPLY : s = "*"; break; case irr::KEY_ADD : s = "+"; break; - case irr::KEY_SEPARATOR : s = "separator"; break; - case irr::KEY_SUBTRACT : s = "- (subtract)"; break; - case irr::KEY_DECIMAL : s = "decimal"; break; - case irr::KEY_DIVIDE : s = "/ (divide)"; break; + //I18N: input configuration screen: keyboard key + case irr::KEY_SEPARATOR : s = _("Separator"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_SUBTRACT : s = _("- (Subtract)"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_DECIMAL : s = _("Decimal"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_DIVIDE : s = _("/ (Divide)"); break; case irr::KEY_F1 : s = "F1"; break; case irr::KEY_F2 : s = "F2"; break; case irr::KEY_F3 : s = "F3"; break; @@ -229,26 +287,42 @@ irr::core::stringw Binding::getAsString() const case irr::KEY_F22 : s = "F22"; break; case irr::KEY_F23 : s = "F23"; break; case irr::KEY_F24 : s = "F24"; break; - case irr::KEY_NUMLOCK : s = "num lock"; break; - case irr::KEY_SCROLL : s = "scroll lock"; break; - case irr::KEY_LSHIFT : s = "left shift"; break; - case irr::KEY_RSHIFT : s = "right shift"; break; - case irr::KEY_LCONTROL : s = "left control"; break; - case irr::KEY_RCONTROL : s = "right control"; break; - case irr::KEY_LMENU : s = "left menu"; break; - case irr::KEY_RMENU : s = "right menu"; break; + //I18N: input configuration screen: keyboard key + case irr::KEY_NUMLOCK : s = _("Num Lock"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_SCROLL : s = _("Scroll Lock"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_LSHIFT : s = _("Left Shift"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_RSHIFT : s = _("Right Shift"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_LCONTROL : s = _("Left Control"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_RCONTROL : s = _("Right Control"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_LMENU : s = _("Left Menu"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_RMENU : s = _("Right Menu"); break; case irr::KEY_PLUS : s = "+"; break; case irr::KEY_COMMA : s = ","; break; case irr::KEY_MINUS : s = "-"; break; case irr::KEY_PERIOD : s = "."; break; - case irr::KEY_ATTN : s = "attn"; break; - case irr::KEY_CRSEL : s = "crsel"; break; - case irr::KEY_EXSEL : s = "exsel"; break; - case irr::KEY_EREOF : s = "ereof"; break; - case irr::KEY_PLAY : s = "play"; break; - case irr::KEY_ZOOM : s = "zoom"; break; - case irr::KEY_PA1 : s = "pa1"; break; - case irr::KEY_OEM_CLEAR : s = "oem clear"; break; + //I18N: input configuration screen: keyboard key + case irr::KEY_ATTN : s = _("Attn"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_CRSEL : s = _("Crsel"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_EXSEL : s = _("Exsel"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_EREOF : s = _("Ereof"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_PLAY : s = _("Play"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_ZOOM : s = _("Zoom"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_PA1 : s = _("Pa1"); break; + //I18N: input configuration screen: keyboard key + case irr::KEY_OEM_CLEAR : s = _("Oem Clear"); break; } break; From 4f4a1c0373b0a0dbf004409e54ae24c952729331 Mon Sep 17 00:00:00 2001 From: hiker Date: Tue, 4 Aug 2015 17:14:36 +1000 Subject: [PATCH 33/40] Added support for reverse mode in history files. --- src/race/history.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/race/history.cpp b/src/race/history.cpp index ec65911f8..eba50e42b 100644 --- a/src/race/history.cpp +++ b/src/race/history.cpp @@ -269,7 +269,17 @@ void History::Load() Log::fatal("History", "No difficulty found in history file."); race_manager->setDifficulty((RaceManager::Difficulty)n); + + // Optional (not supported in older history files): include reverse fgets(s, 1023, fd); + char r; + if (!sscanf(s, "reverse: %c", &r) != 1) + { + fgets(s, 1023, fd); + race_manager->setReverseTrack(r == 'y'); + } + + if(sscanf(s, "track: %1023s",s1)!=1) Log::warn("History", "Track not found in history file."); race_manager->setTrack(s1); From cdfa571855c197441203faef74738fb5a97cd857 Mon Sep 17 00:00:00 2001 From: konstin Date: Tue, 4 Aug 2015 11:15:29 +0200 Subject: [PATCH 34/40] remove patch file --- src/karts/patch | 71 ------------------------------------------------- 1 file changed, 71 deletions(-) delete mode 100644 src/karts/patch diff --git a/src/karts/patch b/src/karts/patch deleted file mode 100644 index 92c80793c..000000000 --- a/src/karts/patch +++ /dev/null @@ -1,71 +0,0 @@ -diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp -index de14bbe..47bbee9 100644 ---- a/src/karts/kart.cpp -+++ b/src/karts/kart.cpp -@@ -2476,11 +2476,12 @@ void Kart::kartIsInRestNow() - for(int i=0; igetNumWheels(); i++) - { - const btWheelInfo &wi = m_vehicle->getWheelInfo(i); -- f += wi.m_chassisConnectionPointCS.getY() -- - wi.m_raycastInfo.m_suspensionLength - wi.m_wheelsRadius; -+ f += wi.m_raycastInfo.m_suspensionLength; - } -+ m_terrain_info->update(getTrans()); - m_graphical_y_offset = f/m_vehicle->getNumWheels() - + getKartProperties()->getGraphicalYOffset(); -+ m_graphical_y_offset = m_kart_model->getLowestPoint() - (getXYZ().getY() - m_terrain_info->getHoT()); - - m_kart_model->setDefaultSuspension(); - } // kartIsInRestNow -@@ -2595,11 +2596,6 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz, - } // for igetWheelInfo(0); - -- // Determine the shadow position from the terrain Y position. This -- // leaves the shadow on the ground even if the kart is jumping because -- // of skidding (shadows are disabled when wheel are not on the track). -- m_shadow->update(m_terrain_info->getHoT() - getXYZ().getY() -- -m_skidding->getGraphicalJumpOffset()); - // Recompute the default average suspension length, see - // kartIsInRestNow() how to get from y-offset to susp. len. - float av_sus_len = -m_graphical_y_offset -@@ -2628,6 +2624,9 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz, - + lean_height - - m_kart_model->getLowestPoint()); - -+ center_shift.setY(m_skidding->getGraphicalJumpOffset() -+ + lean_height -+ +m_graphical_y_offset); - center_shift = getTrans().getBasis() * center_shift; - - Moveable::updateGraphics(dt, center_shift, -@@ -2637,6 +2636,14 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz, - // how much the wheels need to rotate. - m_kart_model->update(dt, m_speed*dt, getSteerPercent(), m_speed); - -+ // Determine the shadow position from the terrain Y position. This -+ // leaves the shadow on the ground even if the kart is jumping because -+ // of skidding (shadows are disabled when wheel are not on the track). -+ m_shadow->update( m_terrain_info->getHoT() - getXYZ().getY() -+ - m_skidding->getGraphicalJumpOffset() -+ - m_graphical_y_offset -+ - m_kart_model->getLowestPoint()); -+ - #ifdef XX - // cheap wheelie effect - if (m_controls.m_nitro) -diff --git a/src/karts/kart_model.cpp b/src/karts/kart_model.cpp -index 65879d3..36b03b7 100644 ---- a/src/karts/kart_model.cpp -+++ b/src/karts/kart_model.cpp -@@ -813,7 +813,9 @@ void KartModel::update(float dt, float distance, float steer, float speed) - core::vector3df pos = m_wheel_graphics_position[i].toIrrVector(); - - const btWheelInfo &wi = m_kart->getVehicle()->getWheelInfo(i); -- pos.Y = -wi.m_raycastInfo.m_suspensionLength + m_wheel_graphics_radius[i] + getLowestPoint(); -+ pos.Y += m_default_physics_suspension[i] -+ - wi.m_raycastInfo.m_suspensionLength -+ - getLowestPoint(); - m_wheel_node[i]->setPosition(pos); - - // Now calculate the new rotation: (old + change) mod 360 From 93a5a91628b6d85de66b2478635493bbbf289bad Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 5 Aug 2015 08:07:58 +1000 Subject: [PATCH 35/40] Fix #2152 (star effect not showing in graphics level 1). --- src/karts/explosion_animation.cpp | 7 ++----- src/karts/kart.cpp | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/karts/explosion_animation.cpp b/src/karts/explosion_animation.cpp index 81799dd8d..8105b2eba 100644 --- a/src/karts/explosion_animation.cpp +++ b/src/karts/explosion_animation.cpp @@ -109,11 +109,8 @@ ExplosionAnimation::ExplosionAnimation(AbstractKart *kart, float t = m_kart->getKartProperties()->getExplosionInvulnerabilityTime() * m_kart->getPlayerDifficulty()->getExplosionInvulnerabilityTime(); m_kart->setInvulnerableTime(t); - if ( UserConfigParams::m_graphical_effects ) - { - m_kart->showStarEffect(t); - } - + m_kart->showStarEffect(t); + m_kart->getAttachment()->clear(); }; // ExplosionAnimation diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index e075e59e8..6012a0a0b 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -1077,11 +1077,8 @@ void Kart::update(float dt) m_max_speed->getCurrentMaxSpeed()); #endif - if ( UserConfigParams::m_graphical_effects ) - { - // update star effect (call will do nothing if stars are not activated) - m_stars_effect->update(dt); - } + // update star effect (call will do nothing if stars are not activated) + m_stars_effect->update(dt); if(m_squash_time>=0) { From 9e75d28eebd3c6186ef8724654eaea2fbf563e9f Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 5 Aug 2015 08:15:31 +1000 Subject: [PATCH 36/40] Write the reverse flag into history files. --- src/race/history.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/race/history.cpp b/src/race/history.cpp index eba50e42b..e3a512a9b 100644 --- a/src/race/history.cpp +++ b/src/race/history.cpp @@ -182,6 +182,8 @@ void History::Save() fprintf(fd, "numkarts: %d\n", num_karts); fprintf(fd, "numplayers: %d\n", race_manager->getNumPlayers()); fprintf(fd, "difficulty: %d\n", race_manager->getDifficulty()); + fprintf(fd, "reverse: %c\n", race_manager->getReverseTrack() ? 'y' : 'n'); + fprintf(fd, "track: %s\n", world->getTrack()->getIdent().c_str()); assert(num_karts > 0); From bd85f517798cf54796f0d4901c4f7f3d5963b354 Mon Sep 17 00:00:00 2001 From: Marianne Gagnon Date: Tue, 4 Aug 2015 19:26:12 -0400 Subject: [PATCH 37/40] Improve memory management in GP manager, fixes #2261 --- src/race/grand_prix_manager.cpp | 38 ++++++++++++++++++--------------- src/race/grand_prix_manager.hpp | 12 +++++++---- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/race/grand_prix_manager.cpp b/src/race/grand_prix_manager.cpp index 793874dc3..17d793fc7 100644 --- a/src/race/grand_prix_manager.cpp +++ b/src/race/grand_prix_manager.cpp @@ -39,8 +39,6 @@ GrandPrixManager::GrandPrixManager() // ---------------------------------------------------------------------------- GrandPrixManager::~GrandPrixManager() { - for(unsigned int i=0; igetId() == s.str()) + if (m_gp_data[i].getId() == s.str()) { unique = false; break; @@ -139,25 +138,31 @@ std::string GrandPrixManager::generateId() bool GrandPrixManager::existsName(const irr::core::stringw& name) const { for (unsigned int i = 0; i < m_gp_data.size(); i++) - if (m_gp_data[i]->getName() == name) + if (m_gp_data[i].getName() == name) return true; return false; } // existsName // ---------------------------------------------------------------------------- -GrandPrixData* GrandPrixManager::getGrandPrix(const std::string& s) const +const GrandPrixData* GrandPrixManager::getGrandPrix(const std::string& s) const { - return editGrandPrix(s); + for (unsigned int i = 0; igetId() == s) - return m_gp_data[i]; + if (m_gp_data[i].getId() == s) + return m_gp_data.get(i); } // for i in m_gp_data return NULL; @@ -166,13 +171,12 @@ GrandPrixData* GrandPrixManager::editGrandPrix(const std::string& s) const // ---------------------------------------------------------------------------- void GrandPrixManager::checkConsistency() { - for(unsigned int i=0; i= 0; i--) { - if(!m_gp_data[i]->checkConsistency()) + if (!m_gp_data[i].checkConsistency()) { // delete this GP, since a track is missing - delete *(m_gp_data.erase(m_gp_data.begin()+i)); - i--; + m_gp_data.erase(i); } } } // checkConsistency diff --git a/src/race/grand_prix_manager.hpp b/src/race/grand_prix_manager.hpp index 4159b5213..25092149e 100644 --- a/src/race/grand_prix_manager.hpp +++ b/src/race/grand_prix_manager.hpp @@ -23,6 +23,7 @@ #include #include +#include "utils/ptr_vector.hpp" #include "irrlicht.h" class GrandPrixData; @@ -35,7 +36,7 @@ class GrandPrixManager private: static const char* SUFFIX; - std::vector m_gp_data; + PtrVector m_gp_data; /** Load all the grands prix from the 3 directories known */ void loadFiles(); @@ -51,20 +52,23 @@ public: GrandPrixManager(); ~GrandPrixManager(); void reload(); - GrandPrixData* getGrandPrix(const std::string& s) const; bool existsName(const irr::core::stringw& name) const; void checkConsistency(); // Methods for the gp editor - GrandPrixData* editGrandPrix(const std::string& s) const; + GrandPrixData* editGrandPrix(const std::string& s); GrandPrixData* createNewGP(const irr::core::stringw& newName); GrandPrixData* copy(const std::string& id, const irr::core::stringw& newName); void remove(const std::string& id); // ------------------------------------------------------------------------ + /** Returns a pointer to the data for the specified GP. + * \param i Index of the GP. */ + const GrandPrixData* getGrandPrix(const std::string& s) const; + // ------------------------------------------------------------------------ /** Returns a pointer to the data for the specified GP. * \param i Index of the GP. */ - GrandPrixData* getGrandPrix(const int i) const { return m_gp_data[i]; } + const GrandPrixData* getGrandPrix(const int i) const { return m_gp_data.get(i); } // ------------------------------------------------------------------------ /** Returns the number of GPs. */ unsigned int getNumberOfGrandPrix() const { return (int)m_gp_data.size(); } From c2feb458afcb9e4321c910fb4ace09c4ab20885f Mon Sep 17 00:00:00 2001 From: Marianne Gagnon Date: Tue, 4 Aug 2015 19:31:38 -0400 Subject: [PATCH 38/40] When restoring ribbon selection, consider that maybe the ribbon does not anymore contain as many items as previously. Fixes #2260 --- src/guiengine/widgets/ribbon_widget.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/guiengine/widgets/ribbon_widget.cpp b/src/guiengine/widgets/ribbon_widget.cpp index 6b04de7dd..6138c8d4d 100644 --- a/src/guiengine/widgets/ribbon_widget.cpp +++ b/src/guiengine/widgets/ribbon_widget.cpp @@ -560,7 +560,9 @@ EventPropagation RibbonWidget::focused(const int playerID) { if (m_selection[playerID] != -1) { - m_active_children.get(m_selection[playerID])->focused(playerID); + int selection = m_selection[playerID]; + if (selection < m_active_children.size()) + m_active_children.get(selection)->focused(playerID); } } From b44f0605dca450e6e42831ea3079b766284001c9 Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 5 Aug 2015 17:00:40 +1000 Subject: [PATCH 39/40] Try to bring karts quicker back on the ground when the kart is on its side, without overcompensating (and therefore shaking) when the kart is only slightly non-parallel to the ground when flying. --- data/stk_config.xml | 2 +- src/physics/btKart.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/data/stk_config.xml b/data/stk_config.xml index d4fd22725..0b9611b6e 100644 --- a/data/stk_config.xml +++ b/data/stk_config.xml @@ -426,7 +426,7 @@ chassis-angular-damping="0" downward-impulse-factor="5" track-connection-accel="2" - smooth-flying-impulse="25"/> + smooth-flying-impulse="250"/>