Reimplement Gold Driver and Unstoppable by gathering data in general counters. Also fix #3487
This commit is contained in:
parent
41ea4b1997
commit
70eb11de4f
@ -45,7 +45,6 @@
|
||||
<standard goal="1"/>
|
||||
<std_timetrial goal="1"/>
|
||||
<follow_leader goal="1"/>
|
||||
<opponents goal="3"/>
|
||||
</achievement>
|
||||
<achievement id="7" check-type="all-at-least" reset-type="race"
|
||||
name="Powerup Love" description="Use 10 or more powerups in a race.">
|
||||
|
@ -41,6 +41,10 @@ AchievementsStatus::AchievementsStatus()
|
||||
{
|
||||
m_valid = true;
|
||||
m_online = true;
|
||||
for (unsigned int i=0; i<ACHIEVE_DATA_NUM; i++)
|
||||
{
|
||||
m_variables[i].counter = 0;
|
||||
}
|
||||
} // AchievementsStatus
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -78,6 +82,29 @@ void AchievementsStatus::load(const XMLNode * input)
|
||||
achievement->load(xml_achievements[i]);
|
||||
} // for i in xml_achievements
|
||||
|
||||
// Load achievement data
|
||||
int data_version = -1;
|
||||
const XMLNode *n = input->getNode("data");
|
||||
if (n!=NULL)
|
||||
n->get("version", &data_version);
|
||||
if (data_version == DATA_VERSION)
|
||||
{
|
||||
std::vector<XMLNode*> xml_achievement_data;
|
||||
input->getNodes("var", xml_achievement_data);
|
||||
for (unsigned int i = 0; i < xml_achievement_data.size(); i++)
|
||||
{
|
||||
if (i>=ACHIEVE_DATA_NUM)
|
||||
{
|
||||
Log::warn("AchievementsStatus",
|
||||
"Found more saved achievement data "
|
||||
"than there should be. Discarding.");
|
||||
continue;
|
||||
}
|
||||
xml_achievement_data[i]->get("counter",&m_variables[i].counter);
|
||||
}
|
||||
}
|
||||
// If there is nothing valid to load ; we keep the init values
|
||||
|
||||
} // load
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -101,6 +128,11 @@ void AchievementsStatus::save(UTFWriter &out)
|
||||
if (i->second != NULL)
|
||||
i->second->save(out);
|
||||
}
|
||||
out << " <data version=\"1\"/>\n";
|
||||
for(int i=0;i<ACHIEVE_DATA_NUM;i++)
|
||||
{
|
||||
out << " <var counter=\"" << m_variables[i].counter << "\"/>\n";
|
||||
}
|
||||
out << " </achievements>\n";
|
||||
} // save
|
||||
|
||||
@ -157,6 +189,65 @@ void AchievementsStatus::sync(const std::vector<uint32_t> & achieved_ids)
|
||||
}
|
||||
} // sync
|
||||
|
||||
/* This function checks over achievements to update their goals
|
||||
FIXME It is currently hard-coded to specific achievements,
|
||||
until it can entirely supersedes the previous system and
|
||||
removes its complications. */
|
||||
void AchievementsStatus::updateAchievementsProgress(unsigned int achieve_data_id)
|
||||
{
|
||||
Achievement *gold_driver = PlayerManager::getCurrentAchievementsStatus()->getAchievement(AchievementInfo::ACHIEVE_GOLD_DRIVER);
|
||||
Achievement *unstoppable = PlayerManager::getCurrentAchievementsStatus()->getAchievement(AchievementInfo::ACHIEVE_UNSTOPPABLE);
|
||||
|
||||
if (!unstoppable->isAchieved())
|
||||
{
|
||||
unstoppable->reset();
|
||||
unstoppable->increase("wins", "wins", m_variables[ACHIEVE_CONS_WON_RACES].counter);
|
||||
}
|
||||
|
||||
if (!gold_driver->isAchieved())
|
||||
{
|
||||
gold_driver->reset();
|
||||
gold_driver->increase("standard", "standard", m_variables[ACHIEVE_WON_NORMAL_RACES].counter);
|
||||
gold_driver->increase("std_timetrial", "std_timetrial", m_variables[ACHIEVE_WON_TT_RACES].counter);
|
||||
gold_driver->increase("follow_leader", "follow_leader", m_variables[ACHIEVE_WON_FTL_RACES].counter);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AchievementsStatus::increaseDataVar(unsigned int achieve_data_id, int increase)
|
||||
{
|
||||
if (achieve_data_id<ACHIEVE_DATA_NUM)
|
||||
{
|
||||
m_variables[achieve_data_id].counter += increase;
|
||||
updateAchievementsProgress(achieve_data_id);
|
||||
if (m_variables[achieve_data_id].counter > 10000000)
|
||||
m_variables[achieve_data_id].counter = 10000000;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
{
|
||||
Log::error("Achievements", "Achievement data id %i don't match any variable.",
|
||||
achieve_data_id);
|
||||
}
|
||||
#endif
|
||||
} // increaseDataVar
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AchievementsStatus::resetDataVar(unsigned int achieve_data_id)
|
||||
{
|
||||
if (achieve_data_id<ACHIEVE_DATA_NUM)
|
||||
{
|
||||
m_variables[achieve_data_id].counter = 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
{
|
||||
Log::error("Achievements", "Achievement data id %i don't match any variable.",
|
||||
achieve_data_id);
|
||||
}
|
||||
#endif
|
||||
} // resetDataVar
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AchievementsStatus::onRaceEnd()
|
||||
{
|
||||
|
@ -40,10 +40,44 @@ class XMLNode;
|
||||
*/
|
||||
class AchievementsStatus
|
||||
{
|
||||
public :
|
||||
enum { // Won races values share the following properties :
|
||||
// 1. Only races with at least 3 AI count unless otherwise specified.
|
||||
ACHIEVE_WON_RACES = 0, // Normal, time-trial and FTL
|
||||
ACHIEVE_WON_NORMAL_RACES = 1, // Normal race only
|
||||
ACHIEVE_WON_TT_RACES = 2, // Time-trial race only
|
||||
ACHIEVE_WON_FTL_RACES = 3, // Follow-the-leader race only
|
||||
// Consecutive won race values :
|
||||
// 1. Ignore races with not enough AIs for incrementation
|
||||
// 2. Reset the counter in case of loss against any number of AIs
|
||||
ACHIEVE_CONS_WON_RACES = 4,
|
||||
// Won races in (at least) hard requires at least 5 AI opponents
|
||||
ACHIEVE_CONS_WON_RACES_HARD = 5,
|
||||
|
||||
ACHIEVE_DATA_NUM = 6
|
||||
};
|
||||
|
||||
private:
|
||||
std::map<uint32_t, Achievement *> m_achievements;
|
||||
bool m_online;
|
||||
bool m_valid;
|
||||
|
||||
// Variables used to track achievements progress,
|
||||
// one variable may be used by several achievements.
|
||||
// TODO
|
||||
// Currently this only uses an int counter.
|
||||
// Evaluate if additional data keeping (max achived ?) can be useful,
|
||||
// and either expand the struct or remove it.
|
||||
struct AchievementVariable
|
||||
{
|
||||
int counter;
|
||||
};
|
||||
|
||||
const int DATA_VERSION = 1;
|
||||
|
||||
// The tracked values are defined at compile time
|
||||
AchievementVariable m_variables[ACHIEVE_DATA_NUM];
|
||||
|
||||
bool m_online;
|
||||
bool m_valid;
|
||||
|
||||
class SyncAchievementsRequest : public Online::XMLRequest {
|
||||
virtual void callback ();
|
||||
@ -59,6 +93,9 @@ public :
|
||||
void save(UTFWriter &out);
|
||||
void add(Achievement *achievement);
|
||||
void sync(const std::vector<uint32_t> & achieved_ids);
|
||||
void updateAchievementsProgress(unsigned int achieve_data_id);
|
||||
void increaseDataVar(unsigned int achieve_data_id, int increase);
|
||||
void resetDataVar(unsigned int achieve_data_id);
|
||||
void onRaceEnd();
|
||||
void onLapEnd();
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -165,6 +165,30 @@ public:
|
||||
a->increase(key, goal_key.empty() ? key : goal_key, increase);
|
||||
|
||||
} // increaseAchievement
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** A handy shortcut to increase points for an achievement data of the
|
||||
* current player.
|
||||
* \param achievement_data_id The achievement data id
|
||||
* \param increase How much to increase the current value.
|
||||
*/
|
||||
static void increaseAchievement(unsigned int achievement_data_id,
|
||||
int increase = 1)
|
||||
{
|
||||
getCurrentAchievementsStatus()
|
||||
->increaseDataVar(achievement_data_id, increase);
|
||||
} // increaseAchievement
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Reset an achievement data for current player.
|
||||
* \param achievement_data_id The achievement data id
|
||||
*/
|
||||
static void resetAchievementData(unsigned int achievement_data_id)
|
||||
{
|
||||
getCurrentAchievementsStatus()
|
||||
->resetDataVar(achievement_data_id);
|
||||
} // resetAchievementData
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
}; // PlayerManager
|
||||
#endif
|
||||
|
@ -624,61 +624,43 @@ void World::terminateRace()
|
||||
"laps", race_manager->getNumLaps());
|
||||
}
|
||||
|
||||
Achievement *achiev = PlayerManager::getCurrentAchievementsStatus()->getAchievement(AchievementInfo::ACHIEVE_GOLD_DRIVER);
|
||||
if (achiev)
|
||||
// Increment won races counts
|
||||
if (race_manager->isLinearRaceMode())
|
||||
{
|
||||
std::string mode_name = getIdent(); // Get the race mode name
|
||||
int winner_position = 1;
|
||||
unsigned int opponents = achiev->getInfo()->getGoalValue("opponents"); // Get the required opponents number
|
||||
if (mode_name == IDENT_FTL)
|
||||
{
|
||||
winner_position = 2;
|
||||
opponents++;
|
||||
}
|
||||
for(unsigned int i = 0; i < kart_amount; i++)
|
||||
{
|
||||
// Retrieve the current player
|
||||
if (m_karts[i]->getController()->canGetAchievements())
|
||||
{
|
||||
int winner_position = 1;
|
||||
if (race_manager->isFollowMode()) winner_position = 2;//TODO : check this always work
|
||||
// Check if the player has won
|
||||
if (m_karts[i]->getPosition() == winner_position && kart_amount > opponents )
|
||||
if (m_karts[i]->getPosition() == winner_position && race_manager->getNumberOfAIKarts() >= 3)
|
||||
{
|
||||
// Update the achievement
|
||||
mode_name = StringUtils::toLowerCase(mode_name);
|
||||
if (achiev->getValue("opponents") <= 0)
|
||||
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_GOLD_DRIVER,
|
||||
"opponents", opponents);
|
||||
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_GOLD_DRIVER,
|
||||
mode_name, 1);
|
||||
}
|
||||
}
|
||||
} // for i < kart_amount
|
||||
} // if (achiev)
|
||||
PlayerManager::increaseAchievement(AchievementsStatus::ACHIEVE_WON_RACES,1);
|
||||
PlayerManager::increaseAchievement(AchievementsStatus::ACHIEVE_CONS_WON_RACES,1);
|
||||
if (race_manager->isTimeTrialMode())
|
||||
PlayerManager::increaseAchievement(AchievementsStatus::ACHIEVE_WON_TT_RACES,1);
|
||||
else if (race_manager->isFollowMode())
|
||||
PlayerManager::increaseAchievement(AchievementsStatus::ACHIEVE_WON_FTL_RACES,1);
|
||||
else // normal race
|
||||
PlayerManager::increaseAchievement(AchievementsStatus::ACHIEVE_WON_NORMAL_RACES,1);
|
||||
|
||||
Achievement *win = PlayerManager::getCurrentAchievementsStatus()->getAchievement(AchievementInfo::ACHIEVE_UNSTOPPABLE);
|
||||
//if achivement has been unlocked
|
||||
if (win->getValue("wins") < 5 )
|
||||
{
|
||||
for(unsigned int i = 0; i < kart_amount; i++)
|
||||
{
|
||||
// Retrieve the current player
|
||||
if (m_karts[i]->getController()->canGetAchievements())
|
||||
{
|
||||
// Check if the player has won
|
||||
if (m_karts[i]->getPosition() == 1 )
|
||||
{
|
||||
// Increase number of consecutive wins
|
||||
PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_UNSTOPPABLE,
|
||||
"wins", 1);
|
||||
if (race_manager->getNumberOfAIKarts() >= 5 &&
|
||||
(race_manager->getDifficulty() == RaceManager::DIFFICULTY_HARD ||
|
||||
race_manager->getDifficulty() == RaceManager::DIFFICULTY_BEST))
|
||||
PlayerManager::increaseAchievement(AchievementsStatus::ACHIEVE_CONS_WON_RACES_HARD,1);
|
||||
}
|
||||
else
|
||||
// Race lost, reset the consecutive wins counters
|
||||
else if (m_karts[i]->getPosition() > winner_position)
|
||||
{
|
||||
//Set number of consecutive wins to 0
|
||||
win->reset();
|
||||
PlayerManager::resetAchievementData(AchievementsStatus::ACHIEVE_CONS_WON_RACES);
|
||||
PlayerManager::resetAchievementData(AchievementsStatus::ACHIEVE_CONS_WON_RACES_HARD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // for i<kart_amount
|
||||
} // if isLinearRaceMode
|
||||
|
||||
PlayerManager::getCurrentPlayer()->raceFinished();
|
||||
|
||||
if (m_race_gui) m_race_gui->clearAllMessages();
|
||||
|
@ -514,6 +514,8 @@ public:
|
||||
* AI karts. */
|
||||
unsigned int getNumberOfKarts() const {return m_num_karts; }
|
||||
// ------------------------------------------------------------------------
|
||||
unsigned int getNumberOfAIKarts() const {return m_ai_kart_list.size(); }
|
||||
// ------------------------------------------------------------------------
|
||||
unsigned int getNumNonGhostKarts() const { return m_num_karts - m_num_ghost_karts; }
|
||||
// ------------------------------------------------------------------------
|
||||
MajorRaceModeType getMajorMode() const { return m_major_mode; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user