Fixed item handling in battle modes by adding an additional 'position class'

to data/powerup.xml for battle modes. This makes it unnecessary that modes
can select which powerup are available, therefore this code was cleaned up.
Also added some minor code simplifications.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@5374 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2010-05-04 13:54:49 +00:00
parent d1ac9142a3
commit 56ebedd175
10 changed files with 109 additions and 76 deletions

View File

@ -25,11 +25,12 @@
<!-- Distribution of the items depending on position of the
kart. The order must correspond to powerup_manager.hpp -->
<!-- bubble cake bowl zipper plunger switch para anvil -->
<first w="1 0 0 0 0 1 0 0" />
<top33 w="1 1 1 1 1 1 1 0" />
<mid33 w="1 1 1 1 1 1 1 0" />
<end33 w="0 1 1 1 1 1 1 1" />
<last w="0 1 1 2 2 0 2 2" />
<first w="1 0 0 0 0 1 0 0" />
<top33 w="1 1 1 1 1 1 1 0" />
<mid33 w="1 1 1 1 1 1 1 0" />
<end33 w="0 1 1 1 1 1 1 1" />
<last w="0 1 1 2 2 0 2 2" />
<battle w="0 2 1 0 0 0 0 0" />
</powerup>

View File

@ -89,7 +89,7 @@ Plunger::Plunger(Kart *kart) : Flyable(kart, PowerupManager::POWERUP_PLUNGER)
// pulling back makes no sense in battle mode, since this mode is not a race.
// so in battle mode, always hide view
if( m_reverse_mode || race_manager->isBattleMode(race_manager->getMinorMode()) )
if( m_reverse_mode || race_manager->isBattleMode() )
m_rubber_band = NULL;
else
{
@ -151,7 +151,7 @@ void Plunger::hit(Kart *kart, PhysicalObject *obj)
// pulling back makes no sense in battle mode, since this mode is not a race.
// so in battle mode, always hide view
if( m_reverse_mode || race_manager->isBattleMode(race_manager->getMinorMode()) )
if( m_reverse_mode || race_manager->isBattleMode() )
{
if(kart) {
kart->blockViewWithPlunger();

View File

@ -289,8 +289,9 @@ void Powerup::use()
*/
void Powerup::hitBonusBox(int n, const Item &item, int add_info)
{
// Position can be -1 in case of a battle mode (which doesn't have
// positions), but this case is properly handled in getRandomPowerup.
int position = m_owner->getPosition();
assert(position != -1);
PowerupManager::PowerupType new_powerup =
powerup_manager->getRandomPowerup(position);

View File

@ -88,7 +88,7 @@ PowerupManager::PowerupType PowerupManager::getPowerupType(const std::string &na
} // getPowerupType
//-----------------------------------------------------------------------------
/** Loads all projectiles from the powerup.xml file.
/** Loads all powerups from the powerup.xml file.
*/
void PowerupManager::loadAllPowerups()
{
@ -104,14 +104,21 @@ void PowerupManager::loadAllPowerups()
if(type!=POWERUP_NOTHING)
LoadPowerup(type, *node);
}
loadWeights(*root, "first", POSITION_FIRST);
loadWeights(*root, "top33", POSITION_TOP33);
loadWeights(*root, "mid33", POSITION_MID33);
loadWeights(*root, "end33", POSITION_END33);
loadWeights(*root, "last" , POSITION_LAST );
loadWeights(*root, "first", POSITION_FIRST );
loadWeights(*root, "top33", POSITION_TOP33 );
loadWeights(*root, "mid33", POSITION_MID33 );
loadWeights(*root, "end33", POSITION_END33 );
loadWeights(*root, "last" , POSITION_LAST );
loadWeights(*root, "battle" , POSITION_BATTLE_MODE);
} // loadAllPowerups
//-----------------------------------------------------------------------------
/** Loads the data for one particular powerup. For bowling ball, plunger, and
* cake static members in the appropriate classes are called to store
* additional information for those objects.
* \param type The type of the powerup.
* \param node The XML node with the data for this powerup.
*/
void PowerupManager::LoadPowerup(PowerupType type, const XMLNode &node)
{
std::string icon_file("");
@ -222,6 +229,8 @@ void PowerupManager::updateWeightsForRace(unsigned int num_karts)
{
m_position_to_class.clear();
const World *world = World::getWorld();
// In battle mode no positions exist, so use only position 1
unsigned int end_position = (race_manager->isBattleMode()) ? 1 : num_karts;
for(unsigned int position =1; position <= num_karts; position++)
{
// Set up the mapping of position to position class:
@ -235,7 +244,6 @@ void PowerupManager::updateWeightsForRace(unsigned int num_karts)
for(unsigned int i= POWERUP_FIRST; i<=POWERUP_LAST; i++)
{
PowerupType type=(PowerupType)i;
if(!world->acceptPowerup(type)) continue;
unsigned int w =m_weights[pos_class][i-POWERUP_FIRST];
sum += w;
for(unsigned int i=0; i<w; i++)
@ -246,12 +254,18 @@ void PowerupManager::updateWeightsForRace(unsigned int num_karts)
} // updateWeightsForRace
// ----------------------------------------------------------------------------
/** Determines the position class for a
/** Determines the position class for a given position. If the race is a
* battle mode (in which case we don't have a position), always return
* 'POSITION_BATTLE_MODE' (and in this case only position 1 will be used
* for all karts).
* \param num_karts Number of karts in the race.
* \param position The position for which to determine the position class.
*/
PowerupManager::PositionClass
PowerupManager::convertPositionToClass(unsigned int num_karts,
unsigned int position)
{
if(race_manager->isBattleMode()) return POSITION_BATTLE_MODE;
if(position==1) return POSITION_FIRST;
if(position==num_karts) return POSITION_LAST;
@ -268,10 +282,19 @@ PowerupManager::PositionClass
} // convertPositionToClass
// ----------------------------------------------------------------------------
/** Returns a random powerup for a kart at a given position. If the race mode
* is a battle, the position is actually not used and a randomly selected
* item for POSITION_BATTLE_MODE is returned. This function takes the weights
* specified for all items into account by using a list which contains all
* items depending on the weights defined. See updateWeightsForRace()
* \param pos Position of the kart (1<=pos<=number of karts) - ignored in
* case of a battle mode.
*/
PowerupManager::PowerupType PowerupManager::getRandomPowerup(unsigned int pos)
{
// Positions start with 1, while the index starts with 0 - so subtract 1
PositionClass pos_class = m_position_to_class[pos-1];
PositionClass pos_class = race_manager->isBattleMode() ? POSITION_BATTLE_MODE
: m_position_to_class[pos-1];
int random = rand()%m_powerups_for_position[pos_class].size();
return m_powerups_for_position[pos_class][random];

View File

@ -82,12 +82,16 @@ public:
};
/** The different position classes, used to map a kart's position to a
* weight distribution for the different powerups. */
* weight distribution for the different powerups. The battle mode is
* listed as a separate 'position' - this way the same implementation
* as used for normal racing can be used to define which items are
* available in battle mode*/
enum PositionClass {POSITION_FIRST,
POSITION_TOP33,
POSITION_MID33,
POSITION_END33,
POSITION_LAST,
POSITION_BATTLE_MODE,
POSITION_COUNT};
private:

View File

@ -334,21 +334,3 @@ void ThreeStrikesBattle::raceResultOrder( int* order )
order[pos] = kart_id;
}
} // raceResultOrder
//-----------------------------------------------------------------------------
bool ThreeStrikesBattle::acceptPowerup(const PowerupManager::PowerupType type) const
{
// these powerups don't make much sense in battle mode
if (type == PowerupManager::POWERUP_PARACHUTE ||
type == PowerupManager::POWERUP_ANVIL ||
type == PowerupManager::POWERUP_BUBBLEGUM ||
type == PowerupManager::POWERUP_ZIPPER ||
type == PowerupManager::POWERUP_SWITCH ||
type == PowerupManager::POWERUP_PLUNGER)
{
return false;
}
return true;
} // acceptPowerup

View File

@ -70,7 +70,6 @@ public:
virtual RaceGUI::KartIconDisplayInfo* getKartsDisplayInfo();
virtual bool raceHasLaps(){ return false; }
virtual void moveKartAfterRescue(Kart* kart);
virtual bool acceptPowerup(const PowerupManager::PowerupType type) const;
virtual std::string getIdent() const;

View File

@ -220,13 +220,7 @@ public:
/** \return whether this world can generate/have highscores */
bool useHighScores() const { return m_use_highscores; }
/** called when a bonus box is hit, to determine which types of powerups are allowed
in each game mode. By default all are accepted, override in child classes to get
a different behaviour */
virtual bool acceptPowerup(const PowerupManager::PowerupType type) const
{ return true; }
/** Called by the code that draws the list of karts on the race GUI
* to know what needs to be drawn in the current mode
*/

View File

@ -89,8 +89,7 @@ public:
#define LINEAR_RACE(ID, COUNT_LAPSES) (1000+ID+100*COUNT_LAPSES)
#define BATTLE_ARENA(ID) (2000+ID)
/** Minor variants to the major types of race.
* Make sure to use the 'LINEAR_RACE/BATTLE_ARENA' macros
*/
* Make sure to use the 'LINEAR_RACE/BATTLE_ARENA' macros. */
enum MinorRaceModeType
{
MINOR_MODE_NONE = -1,
@ -102,6 +101,9 @@ public:
MINOR_MODE_3_STRIKES = BATTLE_ARENA(0)
};
/** Returns a string identifier for each minor race mode.
* \param mode Minor race mode.
*/
static const char* getIdentOf(const MinorRaceModeType mode)
{
switch (mode)
@ -112,8 +114,12 @@ public:
case MINOR_MODE_3_STRIKES: return STRIKES_IDENT;
default: assert(false); return NULL;
}
}
} // getIdentOf
// ------------------------------------------------------------------------
/** Returns the icon for a minor race mode.
* \param mode Minor race mode.
*/
static const char* getIconOf(const MinorRaceModeType mode)
{
switch (mode)
@ -124,7 +130,12 @@ public:
case MINOR_MODE_3_STRIKES: return "/gui/mode_3strikes.png";
default: assert(false); return NULL;
}
}
} // getIconOf
// ------------------------------------------------------------------------
/** Returns a (translated) name of a minor race mode.
* \param mode Minor race mode.
*/
static const wchar_t* getNameOf(const MinorRaceModeType mode)
{
switch (mode)
@ -141,6 +152,11 @@ public:
}
}
// ------------------------------------------------------------------------
/** Returns the minor mode id from a string identifier. This function is
* used from challenge_data, which reads the mode from a challenge file.
* \param name The name of the minor mode.
*/
static const MinorRaceModeType getModeIDFromInternalName(const char* name)
{
if (strcmp(name, IDENT_STD) == 0) return MINOR_MODE_NORMAL_RACE;
@ -155,7 +171,7 @@ public:
#undef LINEAR_RACE
#undef BATTLE_ARENA
/** Difficulty. */
/** Game difficulty. */
enum Difficulty { RD_EASY, RD_MEDIUM, RD_HARD };
/** Different kart types: A local player, a player connected via network,
@ -163,6 +179,9 @@ public:
* (currently not used). */
enum KartType { KT_PLAYER, KT_NETWORK_PLAYER, KT_AI, KT_LEADER, KT_GHOST };
private:
/** This data structure accumulates kart data and race result data from
* each race. */
struct KartStatus
{
std::string m_ident; // The .tkkf filename without the .tkkf
@ -188,9 +207,16 @@ private:
}; // KartStatus
/** The kart status data for each kart. */
std::vector<KartStatus> m_kart_status;
/** The selected difficulty. */
Difficulty m_difficulty;
/** The major mode (single race, GP). */
MajorRaceModeType m_major_mode;
/** The minor mode (race, time trial, ftl, battle mode). */
MinorRaceModeType m_minor_mode;
/** Stores remote kart information about all player karts. */
std::vector<RemoteKartInfo> m_player_karts;
@ -281,52 +307,55 @@ public:
void setRandomKartList(const std::vector<std::string>& rkl)
{ m_random_kart_list = rkl; }
void computeRandomKartList();
void setMirror() {/*FIXME*/}
void setReverse(){/*FIXME*/}
void startNew(); // start new race/GP/...
void next(); // start the next race or go back to the start screen
void rerunRace(); // Rerun the same race again
void exitRace(); // exit a race (and don't start the next one)
void startNew(); // start new race/GP/...
void next(); // start the next race or go back to the start screen
void rerunRace(); // Rerun the same race again
void exitRace(); // exit a race (and don't start the next one)
/** get information about given mode (returns true if 'mode' is of linear races type)
info is stored in its ID for conveniance, see the macros above for exact meaning
*/
static bool isLinearRaceMode(const MinorRaceModeType type)
* info is stored in its ID for conveniance, see the macros LINEAR_RACE and
* BATTLE_ARENA above for exact meaning.
*/
bool isLinearRaceMode()
{
const int id = (int)type;
const int id = (int)m_minor_mode;
if(id > 999 && id < 2000) return true;
else return false;
}
/** get information about given mode (returns true if 'mode' is of battle type)
info is stored in its ID for conveniance, see the macros above for exact meaning
*/
static bool isBattleMode(const MinorRaceModeType type)
// ------------------------------------------------------------------------
/** Returns true if the current mode is a battle mode. This uses the
* numerical id of the mode, see the macros LINEAR_RACE and BATTLE_ARENA
* above for exact meaning.
*/
bool isBattleMode()
{
const int id = (int)type;
const int id = (int)m_minor_mode;
if (id >= 2000) return true;
else return false;
}
/** get information about given mode (returns true if 'mode' requires lap counting)
info is stored in its ID for conveniance, see the macros above for exact meaning
// ------------------------------------------------------------------------
/** Returns true if the current mode has laps. If uses the numeric id based
* on the macros
*/
static bool modeHasLaps(const MinorRaceModeType type)
bool modeHasLaps()
{
if (isBattleMode(type)) return false;
const int id = (int)type;
if (isBattleMode()) return false;
const int id = (int)m_minor_mode;
const int answer = (id-1000)/100;
return answer!=0;
}
static bool modeHasHighscores(const MinorRaceModeType type)
// ------------------------------------------------------------------------
/** Returns true if the currently selected minor mode has highscores. */
bool modeHasHighscores()
{
//FIXME: this information is duplicated. RaceManager knows about it, and
// each World may set m_use_highscores to true or false. The reason
// for this duplication is that we might want to know whether to
// display highscores without creating a World.
return type != MINOR_MODE_3_STRIKES && type != MINOR_MODE_FOLLOW_LEADER;
return m_minor_mode != MINOR_MODE_3_STRIKES &&
m_minor_mode != MINOR_MODE_FOLLOW_LEADER;
}
};

View File

@ -45,8 +45,8 @@ using namespace GUIEngine;
TrackInfoDialog::TrackInfoDialog(const std::string& trackIdent, const irr::core::stringw& trackName,
ITexture* screenshot, const float w, const float h) : ModalDialog(w, h)
{
const bool has_laps = RaceManager::modeHasLaps (race_manager->getMinorMode());
const bool has_highscores = RaceManager::modeHasHighscores(race_manager->getMinorMode());
const bool has_laps = race_manager->modeHasLaps();
const bool has_highscores = race_manager->modeHasHighscores();
const int y1 = m_area.getHeight()/7;
const int y2 = m_area.getHeight()*5/7;