|
@@ -332,6 +332,54 @@ bool AchievementDatabase::mobexists( uint32 mob_id ){
|
|
|
return (it != this->achievement_mobs.end()) ? true : false;
|
|
|
}
|
|
|
|
|
|
+const std::string AchievementLevelDatabase::getDefaultLocation(){
|
|
|
+ return std::string(db_path) + "/achievement_level_db.yml";
|
|
|
+}
|
|
|
+
|
|
|
+uint64 AchievementLevelDatabase::parseBodyNode( const YAML::Node &node ){
|
|
|
+ if( !this->nodesExist( node, { "Level", "Points" } ) ){
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ uint16 level;
|
|
|
+
|
|
|
+ if( !this->asUInt16( node, "Level", level ) ){
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if( level == 0 ){
|
|
|
+ this->invalidWarning( node, "Invalid achievement level %hu (minimum value: 1), skipping.\n", level );
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Make it zero based
|
|
|
+ level -= 1;
|
|
|
+
|
|
|
+ std::shared_ptr<s_achievement_level> ptr = this->find( level );
|
|
|
+ bool exists = ptr != nullptr;
|
|
|
+
|
|
|
+ if( !exists ){
|
|
|
+ ptr = std::make_shared<s_achievement_level>();
|
|
|
+ ptr->level = level;
|
|
|
+ }
|
|
|
+
|
|
|
+ uint16 points;
|
|
|
+
|
|
|
+ if (!this->asUInt16(node, "Points", points)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ ptr->points = points;
|
|
|
+
|
|
|
+ if( !exists ){
|
|
|
+ this->put( level, ptr );
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+AchievementLevelDatabase achievement_level_db;
|
|
|
+
|
|
|
/**
|
|
|
* Add an achievement to the player's log
|
|
|
* @param sd: Player data
|
|
@@ -711,33 +759,57 @@ int *achievement_level(struct map_session_data *sd, bool flag)
|
|
|
{
|
|
|
nullpo_retr(nullptr, sd);
|
|
|
|
|
|
- static int info[2];
|
|
|
- int old_level = sd->achievement_data.level;
|
|
|
- const int score_table[MAX_ACHIEVEMENT_RANK] = { 18, 31, 49, 73, 135, 104, 140, 178, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000 }; //! TODO: Figure out the EXP required to level up from 8-20
|
|
|
-
|
|
|
sd->achievement_data.total_score = 0;
|
|
|
- sd->achievement_data.level = 0;
|
|
|
|
|
|
for (int i = 0; i < sd->achievement_data.count; i++) { // Recount total score
|
|
|
if (sd->achievement_data.achievements[i].completed > 0)
|
|
|
sd->achievement_data.total_score += sd->achievement_data.achievements[i].score;
|
|
|
}
|
|
|
|
|
|
- int i, temp_score = sd->achievement_data.total_score;
|
|
|
+ int left_score, right_score, old_level = sd->achievement_data.level;
|
|
|
+
|
|
|
+ for( sd->achievement_data.level = 0; /* Break condition's inside the loop */; sd->achievement_data.level++ ){
|
|
|
+ std::shared_ptr<s_achievement_level> level = achievement_level_db.find( sd->achievement_data.level );
|
|
|
|
|
|
- for (i = 0; i < MAX_ACHIEVEMENT_RANK && temp_score > score_table[i]; i++) { // Determine rollover and TNL EXP
|
|
|
- temp_score -= score_table[i];
|
|
|
- sd->achievement_data.level++;
|
|
|
+ if( sd->achievement_data.total_score > level->points ){
|
|
|
+ std::shared_ptr<s_achievement_level> next_level = achievement_level_db.find( sd->achievement_data.level + 1 );
|
|
|
+
|
|
|
+ // Check if there is another level
|
|
|
+ if( next_level == nullptr ){
|
|
|
+ std::shared_ptr<s_achievement_level> level = achievement_level_db.find( sd->achievement_data.level );
|
|
|
+
|
|
|
+ left_score = sd->achievement_data.total_score - level->points;
|
|
|
+ right_score = 0;
|
|
|
+
|
|
|
+ // Increase the level for client side display
|
|
|
+ sd->achievement_data.level++;
|
|
|
+ break;
|
|
|
+ }else{
|
|
|
+ // Enough points for this level, check the next one
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if( sd->achievement_data.level == 0 ){
|
|
|
+ left_score = sd->achievement_data.total_score;
|
|
|
+ right_score = level->points;
|
|
|
+ break;
|
|
|
+ }else{
|
|
|
+ std::shared_ptr<s_achievement_level> previous_level = achievement_level_db.find( sd->achievement_data.level - 1 );
|
|
|
+
|
|
|
+ left_score = sd->achievement_data.total_score - previous_level->points;
|
|
|
+ right_score = level->points - previous_level->points;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- info[0] = temp_score; // Left number
|
|
|
- info[1] = score_table[i]; // Right number
|
|
|
+ static int info[2];
|
|
|
+
|
|
|
+ info[0] = left_score; // Left number
|
|
|
+ info[1] = right_score; // Right number
|
|
|
|
|
|
if (flag && old_level != sd->achievement_data.level) { // Give AG_GOAL_ACHIEVE
|
|
|
- int achievement_id = 240000 + sd->achievement_data.level;
|
|
|
-
|
|
|
- if (achievement_add(sd, achievement_id))
|
|
|
- achievement_update_achievement(sd, achievement_id, true);
|
|
|
+ achievement_update_objective( sd, AG_GOAL_ACHIEVE, 0 );
|
|
|
}
|
|
|
|
|
|
return info;
|
|
@@ -951,7 +1023,6 @@ void achievement_update_objective(struct map_session_data *sd, enum e_achievemen
|
|
|
|
|
|
switch(group) {
|
|
|
case AG_CHAT: //! TODO: Not sure how this works officially
|
|
|
- case AG_GOAL_ACHIEVE:
|
|
|
// These have no objective use.
|
|
|
break;
|
|
|
default:
|
|
@@ -986,6 +1057,8 @@ void achievement_read_db(void)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ achievement_level_db.load();
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1014,6 +1087,7 @@ void do_init_achievement(void)
|
|
|
*/
|
|
|
void do_final_achievement(void){
|
|
|
achievement_db.clear();
|
|
|
+ achievement_level_db.clear();
|
|
|
}
|
|
|
|
|
|
/**
|