Add functionality to end a race early (#486).

* Only adding for standard races (normal race + time trial), didn't make as
  much sense elsewhere.
* Places still active players at the back of the final result and gives
  them penalty time.
* Add button to race pause dialog, temporarily using options_ui.png.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@11093 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
wardje
2012-04-07 21:58:11 +00:00
parent 0206f64ee9
commit 9eed9409e5
5 changed files with 88 additions and 9 deletions

View File

@@ -1,7 +1,7 @@
<stkgui>
<div x="5%" y="5%" width="90%" height="90%" layout="vertical-row" >
<header id="title" width="100%" text_align="center" text="Paused" proportion="3" />
<!-- FIXME: some play in proportions occur below because the text of an icon
@@ -12,25 +12,28 @@
<spacer width="20" height="50" />
<buttonbar id="choiceribbon" proportion="4" width="100%" align="center">
<icon-button id="newrace" width="128" height="128" icon="gui/main_race.png"
I18N="Race paused button" text="Setup New Race" word_wrap="true"/>
<icon-button id="restart" width="128" height="128" icon="gui/restart.png"
I18N="Race paused button" text="Restart Race" word_wrap="true"/>
<icon-button id="endrace" width="128" height="128" icon="gui/options_ui.png"
I18N="Race paused button" text="End Race" word_wrap="true"/>
<icon-button id="options" width="128" height="128" icon="gui/main_options.png"
I18N="Race paused button" text="Options" word_wrap="true"/>
<icon-button id="help" width="128" height="128" icon="gui/main_help.png"
I18N="Race paused button" text="Help" word_wrap="true"/>
<icon-button id="exit" width="128" height="128" icon="gui/main_quit.png"
I18N="Race paused button" text="Exit Race" word_wrap="true"/>
</buttonbar>
<spacer width="20" height="35" />
</div>
</stkgui>
</stkgui>

View File

@@ -20,6 +20,8 @@
#include "challenges/unlock_manager.hpp"
#include "config/user_config.hpp"
#include "items/powerup_manager.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/controller/controller.hpp"
//-----------------------------------------------------------------------------
StandardRace::StandardRace() : LinearWorld()
@@ -69,3 +71,59 @@ const std::string& StandardRace::getIdent() const
return IDENT_STD;
} // getIdent
//-----------------------------------------------------------------------------
/** Ends the race early and places still active player karts at the back.
* The race immediately goes to the result stage, estimating the time for the
* karts still in the race. Still active player karts get a penalty in time
* as well as being placed at the back. Players that already finished keep
* their position.
*/
void StandardRace::endRaceEarly()
{
const unsigned int kart_amount = m_karts.size();
// Estimate time for current last in race. Will be used to add to
// the time of the still active player karts. This way we ensure that
// when moving a player to the last spot, they will also have the worst
// time.
const float worst_time =
estimateFinishTimeForKart(getKartAtPosition(getNumKarts()));
std::vector<int> active_players;
// Required for debugging purposes
beginSetKartPositions();
for (unsigned int i = 1; i <= kart_amount; i++)
{
int kartid = m_position_index[i-1];
AbstractKart* kart = m_karts[kartid];
if (kart->hasFinishedRace())
{
// Have to do this to keep endSetKartPosition happy
setKartPosition(kartid, kart->getPosition());
continue;
}
if (kart->getController()->isPlayerController())
{
// Keep active players apart for now
active_players.push_back(kartid);
}
else
{
// AI karts finish
setKartPosition(kartid, i - active_players.size());
kart->finishedRace(estimateFinishTimeForKart(kart));
}
} // i < kart_amount
// Now make the active players finish
for (unsigned int i = 0; i < active_players.size(); i++)
{
int kartid = active_players[i];
int position = getNumKarts() - active_players.size() + 1 + i;
setKartPosition(kartid, position);
m_karts[kartid]->finishedRace(
estimateFinishTimeForKart(m_karts[kartid]) + worst_time
);
} // Finish the active players
endSetKartPositions();
m_phase = RESULT_DISPLAY_PHASE;
terminateRace();
} // endRaceEarly

View File

@@ -39,6 +39,8 @@ public:
virtual void getDefaultCollectibles(int *collectible_type, int *amount);
virtual bool haveBonusBoxes();
virtual const std::string& getIdent() const;
virtual void endRaceEarly();
};
#endif

View File

@@ -203,6 +203,7 @@ public:
virtual void unpause();
virtual void getDefaultCollectibles(int *collectible_type,
int *amount );
virtual void endRaceEarly() { return; }
// ------------------------------------------------------------------------
/** Called to determine whether this race mode uses bonus boxes. */

View File

@@ -74,6 +74,15 @@ void RacePausedDialog::loadedFromFile()
const bool success = choice_ribbon->deleteChild("restart");
assert(success);
}
// Remove "endrace" button for types not (yet?) implemented
if (race_manager->getMinorMode() != RaceManager::MINOR_MODE_NORMAL_RACE &&
race_manager->getMinorMode() != RaceManager::MINOR_MODE_TIME_TRIAL )
{
GUIEngine::RibbonWidget* choice_ribbon =
getWidget<GUIEngine::RibbonWidget>("choiceribbon");
const bool success = choice_ribbon->deleteChild("endrace");
assert(success);
}
}
// ----------------------------------------------------------------------------
@@ -144,6 +153,12 @@ GUIEngine::EventPropagation
StateManager::get()->resetAndSetStack( newStack );
return GUIEngine::EVENT_BLOCK;
}
else if (selection == "endrace")
{
ModalDialog::dismiss();
World::getWorld()->endRaceEarly();
return GUIEngine::EVENT_BLOCK;
}
}
return GUIEngine::EVENT_LET;
} // processEvent