Browse Source

Updated Achievement EXP to official values (#4326)

* Added the official values for the AG_GOAL_ACHIEVE.
* Refactored the leveling logic for Achievements to account for the new values.
* Moved achievement EXP to a database file.
* Added AchievementLevel player variable to allow for easy tracking in the achievement condition checks.
* Cleaned up player GUI EXP progression.
* Added a check to not save achievements that made no changes.
* Added first login achievement.
Thanks to @Lemongrass3110!
Aleos 5 years ago
parent
commit
783009d642

+ 40 - 0
db/achievement_level_db.yml

@@ -0,0 +1,40 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2019 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Achievement Level Database
+###########################################################################
+#
+# Achievement Level Settings
+#
+###########################################################################
+# Level - Achievement Level
+###########################################################################
+# Points - Required total scoring points to reach this level.
+###########################################################################
+
+Header:
+  Type: ACHIEVEMENT_LEVEL_DB
+  Version: 1
+
+Footer:
+  Imports:
+  - Path: db/pre-re/achievement_level_db.yml
+    Mode: Prerenewal
+  - Path: db/re/achievement_level_db.yml
+    Mode: Renewal
+  - Path: db/import/achievement_level_db.yml

+ 32 - 0
db/import-tmpl/achievement_level_db.yml

@@ -0,0 +1,32 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2019 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Import Achievement Level Database
+###########################################################################
+#
+# Achievement Level Settings
+#
+###########################################################################
+# Level - Achievement Level
+###########################################################################
+# Points - Required total scoring points to reach this level.
+###########################################################################
+
+Header:
+  Type: ACHIEVEMENT_LEVEL_DB
+  Version: 1

+ 22 - 1
db/pre-re/achievement_db.yml

@@ -2520,11 +2520,13 @@ Body:
     Score: 20
   - ID: 240000
     Group: "AG_GOAL_LEVEL"
-    Name: "Complete challenges after first introduction"
+    Name: "First Login after the introduction of Achievement Tasks"
     Score: 10
+    Condition: " true "
   - ID: 240001
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 1"
+    Condition: " AchievementLevel >= 1 "
     Reward:
       ItemID: 644
       Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
@@ -2532,6 +2534,7 @@ Body:
   - ID: 240002
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 2"
+    Condition: " AchievementLevel >= 2 "
     Dependent:
       - Id: 240001
     Reward:
@@ -2541,6 +2544,7 @@ Body:
   - ID: 240003
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 3"
+    Condition: " AchievementLevel >= 3 "
     Dependent:
       - Id: 240002
     Reward:
@@ -2550,6 +2554,7 @@ Body:
   - ID: 240004
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 4"
+    Condition: " AchievementLevel >= 4 "
     Dependent:
       - Id: 240003
     Reward:
@@ -2559,6 +2564,7 @@ Body:
   - ID: 240005
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 5"
+    Condition: " AchievementLevel >= 5 "
     Dependent:
       - Id: 240004
     Reward:
@@ -2568,6 +2574,7 @@ Body:
   - ID: 240006
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 6"
+    Condition: " AchievementLevel >= 6 "
     Dependent:
       - Id: 240005
     Reward:
@@ -2577,6 +2584,7 @@ Body:
   - ID: 240007
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 7"
+    Condition: " AchievementLevel >= 7 "
     Dependent:
       - Id: 240006
     Reward:
@@ -2586,6 +2594,7 @@ Body:
   - ID: 240008
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 8"
+    Condition: " AchievementLevel >= 8 "
     Dependent:
       - Id: 240007
     Reward:
@@ -2595,6 +2604,7 @@ Body:
   - ID: 240009
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 9"
+    Condition: " AchievementLevel >= 9 "
     Dependent:
       - Id: 240008
     Reward:
@@ -2604,6 +2614,7 @@ Body:
   - ID: 240010
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 10"
+    Condition: " AchievementLevel >= 10 "
     Dependent:
       - Id: 240009
     Reward:
@@ -2614,6 +2625,7 @@ Body:
   - ID: 240011
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 11"
+    Condition: " AchievementLevel >= 11 "
     Dependent:
       - Id: 240010
     Reward:
@@ -2623,6 +2635,7 @@ Body:
   - ID: 240012
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 12"
+    Condition: " AchievementLevel >= 12 "
     Dependent:
       - Id: 240011
     Reward:
@@ -2632,6 +2645,7 @@ Body:
   - ID: 240013
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 13"
+    Condition: " AchievementLevel >= 13 "
     Dependent:
       - Id: 240012
     Reward:
@@ -2641,6 +2655,7 @@ Body:
   - ID: 240014
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 14"
+    Condition: " AchievementLevel >= 14 "
     Dependent:
       - Id: 240013
     Reward:
@@ -2650,6 +2665,7 @@ Body:
   - ID: 240015
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 15"
+    Condition: " AchievementLevel >= 15 "
     Dependent:
       - Id: 240014
     Reward:
@@ -2659,6 +2675,7 @@ Body:
   - ID: 240016
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 16"
+    Condition: " AchievementLevel >= 16 "
     Dependent:
       - Id: 240015
     Reward:
@@ -2668,6 +2685,7 @@ Body:
   - ID: 240017
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 17"
+    Condition: " AchievementLevel >= 17 "
     Dependent:
       - Id: 240016
     Reward:
@@ -2677,6 +2695,7 @@ Body:
   - ID: 240018
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 18"
+    Condition: " AchievementLevel >= 18 "
     Dependent:
       - Id: 240017
     Reward:
@@ -2686,6 +2705,7 @@ Body:
   - ID: 240019
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 19"
+    Condition: " AchievementLevel >= 19 "
     Dependent:
       - Id: 240018
     Reward:
@@ -2695,6 +2715,7 @@ Body:
   - ID: 240020
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 20"
+    Condition: " AchievementLevel >= 20 "
     Dependent:
       - Id: 240019
     Reward:

+ 74 - 0
db/pre-re/achievement_level_db.yml

@@ -0,0 +1,74 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2019 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Pre-Renewal Achievement Level Database
+###########################################################################
+#
+# Achievement Level Settings
+#
+###########################################################################
+# Level - Achievement Level
+###########################################################################
+# Points - Required total scoring points to reach this level.
+###########################################################################
+
+Header:
+  Type: ACHIEVEMENT_LEVEL_DB
+  Version: 1
+
+Body:
+  - Level: 1
+    Points: 18
+  - Level: 2
+    Points: 49
+  - Level: 3
+    Points: 98
+  - Level: 4
+    Points: 171
+  - Level: 5
+    Points: 306
+  - Level: 6
+    Points: 410
+  - Level: 7
+    Points: 550
+  - Level: 8
+    Points: 728
+  - Level: 9
+    Points: 942
+  - Level: 10
+    Points: 1247
+  - Level: 11
+    Points: 1504
+  - Level: 12
+    Points: 1804
+  - Level: 13
+    Points: 2152
+  - Level: 14
+    Points: 2550
+  - Level: 15
+    Points: 3070
+  - Level: 16
+    Points: 3522
+  - Level: 17
+    Points: 4030
+  - Level: 18
+    Points: 4592
+  - Level: 19
+    Points: 5210
+  - Level: 20
+    Points: 5980

+ 22 - 1
db/re/achievement_db.yml

@@ -2520,11 +2520,13 @@ Body:
     Score: 20
   - ID: 240000
     Group: "AG_GOAL_LEVEL"
-    Name: "Complete challenges after first introduction"
+    Name: "First Login after the introduction of Achievement Tasks"
     Score: 10
+    Condition: " true "
   - ID: 240001
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 1"
+    Condition: " AchievementLevel >= 1 "
     Reward:
       ItemID: 644
       Script: " specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,30000,10; "
@@ -2532,6 +2534,7 @@ Body:
   - ID: 240002
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 2"
+    Condition: " AchievementLevel >= 2 "
     Dependent:
       - Id: 240001
     Reward:
@@ -2541,6 +2544,7 @@ Body:
   - ID: 240003
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 3"
+    Condition: " AchievementLevel >= 3 "
     Dependent:
       - Id: 240002
     Reward:
@@ -2550,6 +2554,7 @@ Body:
   - ID: 240004
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 4"
+    Condition: " AchievementLevel >= 4 "
     Dependent:
       - Id: 240003
     Reward:
@@ -2559,6 +2564,7 @@ Body:
   - ID: 240005
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 5"
+    Condition: " AchievementLevel >= 5 "
     Dependent:
       - Id: 240004
     Reward:
@@ -2568,6 +2574,7 @@ Body:
   - ID: 240006
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 6"
+    Condition: " AchievementLevel >= 6 "
     Dependent:
       - Id: 240005
     Reward:
@@ -2577,6 +2584,7 @@ Body:
   - ID: 240007
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 7"
+    Condition: " AchievementLevel >= 7 "
     Dependent:
       - Id: 240006
     Reward:
@@ -2586,6 +2594,7 @@ Body:
   - ID: 240008
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 8"
+    Condition: " AchievementLevel >= 8 "
     Dependent:
       - Id: 240007
     Reward:
@@ -2595,6 +2604,7 @@ Body:
   - ID: 240009
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 9"
+    Condition: " AchievementLevel >= 9 "
     Dependent:
       - Id: 240008
     Reward:
@@ -2604,6 +2614,7 @@ Body:
   - ID: 240010
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 10"
+    Condition: " AchievementLevel >= 10 "
     Dependent:
       - Id: 240009
     Reward:
@@ -2614,6 +2625,7 @@ Body:
   - ID: 240011
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 11"
+    Condition: " AchievementLevel >= 11 "
     Dependent:
       - Id: 240010
     Reward:
@@ -2623,6 +2635,7 @@ Body:
   - ID: 240012
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 12"
+    Condition: " AchievementLevel >= 12 "
     Dependent:
       - Id: 240011
     Reward:
@@ -2632,6 +2645,7 @@ Body:
   - ID: 240013
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 13"
+    Condition: " AchievementLevel >= 13 "
     Dependent:
       - Id: 240012
     Reward:
@@ -2641,6 +2655,7 @@ Body:
   - ID: 240014
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 14"
+    Condition: " AchievementLevel >= 14 "
     Dependent:
       - Id: 240013
     Reward:
@@ -2650,6 +2665,7 @@ Body:
   - ID: 240015
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 15"
+    Condition: " AchievementLevel >= 15 "
     Dependent:
       - Id: 240014
     Reward:
@@ -2659,6 +2675,7 @@ Body:
   - ID: 240016
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 16"
+    Condition: " AchievementLevel >= 16 "
     Dependent:
       - Id: 240015
     Reward:
@@ -2668,6 +2685,7 @@ Body:
   - ID: 240017
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 17"
+    Condition: " AchievementLevel >= 17 "
     Dependent:
       - Id: 240016
     Reward:
@@ -2677,6 +2695,7 @@ Body:
   - ID: 240018
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 18"
+    Condition: " AchievementLevel >= 18 "
     Dependent:
       - Id: 240017
     Reward:
@@ -2686,6 +2705,7 @@ Body:
   - ID: 240019
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 19"
+    Condition: " AchievementLevel >= 19 "
     Dependent:
       - Id: 240018
     Reward:
@@ -2695,6 +2715,7 @@ Body:
   - ID: 240020
     Group: "AG_GOAL_ACHIEVE"
     Name: "Reaching Level 20"
+    Condition: " AchievementLevel >= 20 "
     Dependent:
       - Id: 240019
     Reward:

+ 74 - 0
db/re/achievement_level_db.yml

@@ -0,0 +1,74 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2019 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Renewal Achievement Level Database
+###########################################################################
+#
+# Achievement Level Settings
+#
+###########################################################################
+# Level - Achievement Level
+###########################################################################
+# Points - Required total scoring points to reach this level.
+###########################################################################
+
+Header:
+  Type: ACHIEVEMENT_LEVEL_DB
+  Version: 1
+
+Body:
+  - Level: 1
+    Points: 18
+  - Level: 2
+    Points: 49
+  - Level: 3
+    Points: 98
+  - Level: 4
+    Points: 171
+  - Level: 5
+    Points: 306
+  - Level: 6
+    Points: 410
+  - Level: 7
+    Points: 550
+  - Level: 8
+    Points: 728
+  - Level: 9
+    Points: 942
+  - Level: 10
+    Points: 1247
+  - Level: 11
+    Points: 1504
+  - Level: 12
+    Points: 1804
+  - Level: 13
+    Points: 2152
+  - Level: 14
+    Points: 2550
+  - Level: 15
+    Points: 3070
+  - Level: 16
+    Points: 3522
+  - Level: 17
+    Points: 4030
+  - Level: 18
+    Points: 4592
+  - Level: 19
+    Points: 5210
+  - Level: 20
+    Points: 5980

+ 7 - 0
src/char/int_achievement.cpp

@@ -113,6 +113,13 @@ bool mapif_achievement_add(uint32 char_id, struct achievement* ad)
 	StringBuf buf;
 	int i;
 
+	ARR_FIND( 0, MAX_ACHIEVEMENT_OBJECTIVES, i, ad->count[i] != 0 );
+
+	if( i == MAX_ACHIEVEMENT_OBJECTIVES && ad->completed == 0 && ad->rewarded == 0 ){
+		// Do not save
+		return true;
+	}
+
 	StringBuf_Init(&buf);
 	StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `id`, `completed`, `rewarded`", schema_config.achievement_table);
 	for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; ++i)

+ 0 - 1
src/common/mmo.hpp

@@ -152,7 +152,6 @@
 #define EL_CLASS_MAX (EL_CLASS_BASE+MAX_ELEMENTAL_CLASS-1)
 
 //Achievement System
-#define MAX_ACHIEVEMENT_RANK 20 /// Maximum achievement level
 #define MAX_ACHIEVEMENT_OBJECTIVES 10 /// Maximum different objectives in achievement_db.yml
 #define MAX_ACHIEVEMENT_DEPENDENTS 20 /// Maximum different dependents in achievement_db.yml
 #define ACHIEVEMENT_NAME_LENGTH 50 /// Max Achievement Name length

+ 90 - 16
src/map/achievement.cpp

@@ -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();
 }
 
 /**

+ 17 - 0
src/map/achievement.hpp

@@ -112,6 +112,23 @@ public:
 
 extern AchievementDatabase achievement_db;
 
+struct s_achievement_level{
+	uint16 level;
+	uint16 points;
+};
+
+class AchievementLevelDatabase : public TypesafeYamlDatabase<uint16, s_achievement_level>{
+public:
+	AchievementLevelDatabase() : TypesafeYamlDatabase( "ACHIEVEMENT_LEVEL_DB", 1 ){
+
+	}
+
+	const std::string getDefaultLocation();
+	uint64 parseBodyNode( const YAML::Node& node );
+};
+
+extern AchievementLevelDatabase achievement_level_db;
+
 void achievement_get_reward(struct map_session_data *sd, int achievement_id, time_t rewarded);
 struct achievement *achievement_add(struct map_session_data *sd, int achievement_id);
 bool achievement_remove(struct map_session_data *sd, int achievement_id);

+ 10 - 4
src/map/intif.cpp

@@ -2179,11 +2179,17 @@ void intif_parse_achievements(int fd)
 				memmove(&sd->achievement_data.achievements[k], &sd->achievement_data.achievements[sd->achievement_data.incompleteCount], sizeof(struct achievement) * (num_received - k));
 			sd->achievement_data.achievements = (struct achievement *)aRealloc(sd->achievement_data.achievements, sizeof(struct achievement) * sd->achievement_data.count);
 		}
-		achievement_level(sd, false); // Calculate level info but don't give any AG_GOAL_ACHIEVE achievements
-		achievement_get_titles(sd->status.char_id); // Populate the title list for completed achievements
-		clif_achievement_update(sd, NULL, 0);
-		clif_achievement_list_all(sd);
 	}
+
+	// Check all conditions and counters on login
+	for( int group = AG_NONE + 1; group < AG_MAX; group++ ){
+		achievement_update_objective( sd, static_cast<e_achievement_group>( group ), 0 );
+	}
+
+	achievement_level(sd, false); // Calculate level info but don't give any AG_GOAL_ACHIEVE achievements
+	achievement_get_titles(sd->status.char_id); // Populate the title list for completed achievements
+	clif_achievement_update(sd, NULL, 0);
+	clif_achievement_list_all(sd);
 }
 
 /**

+ 1 - 0
src/map/map-server.vcxproj

@@ -292,6 +292,7 @@
     <Copy SourceFiles="$(SolutionDir)conf\msg_conf\import-tmpl\map_msg_tha_conf.txt" DestinationFolder="$(SolutionDir)conf\msg_conf\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)conf\msg_conf\import\map_msg_tha_conf.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\abra_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\abra_db.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\achievement_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\achievement_db.yml')" />
+    <Copy SourceFiles="$(SolutionDir)db\import-tmpl\achievement_level_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\achievement_level_db.yml')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\attendance.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\attendance.yml')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\attr_fix.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\attr_fix.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\castle_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\castle_db.txt')" />

+ 1 - 0
src/map/map.hpp

@@ -438,6 +438,7 @@ enum _sp {
 	SP_ROULETTE_GOLD = 130,
 	SP_CASHPOINTS, SP_KAFRAPOINTS,
 	SP_PCDIECOUNTER, SP_COOKMASTERY,
+	SP_ACHIEVEMENT_LEVEL,
 
 	// Mercenaries
 	SP_MERCFLEE=165, SP_MERCKILLS=189, SP_MERCFAITH=190,

+ 1 - 0
src/map/pc.cpp

@@ -8418,6 +8418,7 @@ int pc_readparam(struct map_session_data* sd,int type)
 		case SP_ROULETTE_GOLD:   val = sd->roulette_point.gold; break;
 		case SP_PCDIECOUNTER:    val = sd->die_counter; break;
 		case SP_COOKMASTERY:     val = sd->cook_mastery; break;
+		case SP_ACHIEVEMENT_LEVEL: val = sd->achievement_data.level; break;
 		case SP_CRITICAL:        val = sd->battle_status.cri/10; break;
 		case SP_ASPD:            val = (2000-sd->battle_status.amotion)/10; break;
 		case SP_BASE_ATK:

+ 1 - 0
src/map/pc.hpp

@@ -49,6 +49,7 @@ enum sc_type : int16;
 #define TKMISSIONCOUNT_VAR "TK_MISSION_COUNT"
 #define ATTENDANCE_DATE_VAR "#AttendanceDate"
 #define ATTENDANCE_COUNT_VAR "#AttendanceCounter"
+#define ACHIEVEMENTLEVEL "AchievementLevel"
 
 //Update this max as necessary. 55 is the value needed for Super Baby currently
 //Raised to 85 since Expanded Super Baby needs it.

+ 1 - 0
src/map/script_constants.hpp

@@ -526,6 +526,7 @@
 	export_parameter(KAFRAPOINT_VAR, SP_KAFRAPOINTS);
 	export_parameter(PCDIECOUNTER_VAR, SP_PCDIECOUNTER);
 	export_parameter(COOKMASTERY_VAR, SP_COOKMASTERY);
+	export_parameter(ACHIEVEMENTLEVEL, SP_ACHIEVEMENT_LEVEL);
 
 	export_constant2("bMaxHP",SP_MAXHP);
 	export_constant2("bMaxSP",SP_MAXSP);