Fixed Achievement Level progression (#4156)

* Fixes #4131.
* Changed the behavior of achievement experience to roll over remaining experience rather than check from the total amount.
* Cleaned up achievement level logic.
Thanks to @daisyanne1380 and @SeravySensei!
This commit is contained in:
Aleos 2019-07-19 10:25:28 -04:00 committed by GitHub
parent 68e98a87e5
commit ac46920e73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 48 deletions

View File

@ -691,54 +691,39 @@ int achievement_check_progress(struct map_session_data *sd, int achievement_id,
* Calculate a player's achievement level
* @param sd: Player to check achievement level
* @param flag: If the call should attempt to give the AG_GOAL_ACHIEVE achievement
* @return Player's achievement level or 0 on failure
* @return Rollover and TNL EXP or 0 on failure
*/
int *achievement_level(struct map_session_data *sd, bool flag)
{
nullpo_retr(nullptr, sd);
static int info[2];
int i, old_level;
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
nullpo_retr(0, sd);
sd->achievement_data.total_score = 0;
old_level = sd->achievement_data.level;
sd->achievement_data.level = 0;
for (i = 0; i < sd->achievement_data.count; i++) {
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;
}
info[0] = 0;
info[1] = 0;
int i, temp_score = sd->achievement_data.total_score;
for (i = 0; i < MAX_ACHIEVEMENT_RANK; i++) {
info[0] = info[1];
if (i < ARRAYLENGTH(score_table))
info[1] = score_table[i];
else {
info[0] = info[1];
info[1] = info[1] + 500;
}
if (sd->achievement_data.total_score < info[1])
break;
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 (i == MAX_ACHIEVEMENT_RANK)
i = 0;
info[0] = temp_score; // Left number
info[1] = score_table[i]; // Right number
info[1] = info[1] - info[0]; // Right number
info[0] = sd->achievement_data.total_score - info[0]; // Left number
sd->achievement_data.level = i;
if (flag == true && old_level != sd->achievement_data.level) {
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) ){
if (achievement_add(sd, achievement_id))
achievement_update_achievement(sd, achievement_id, true);
}
}
return info;

View File

@ -20300,14 +20300,11 @@ void clif_parse_sale_remove( int fd, struct map_session_data* sd ){
/// Author: Luxuri, Aleos
/**
* Sends all achievement data to the client (ZC_ALL_AG_LIST).
* Sends all achievement data to the client (ZC_ALL_ACH_LIST).
* 0a23 <packetType>.W <packetLength>.W <ACHCount>.L <ACHPoint>.L
*/
void clif_achievement_list_all(struct map_session_data *sd)
{
int i, j, len, fd, *info;
uint16 count = 0;
nullpo_retv(sd);
if (!battle_config.feature_achievement) {
@ -20315,14 +20312,14 @@ void clif_achievement_list_all(struct map_session_data *sd)
return;
}
fd = sd->fd;
count = sd->achievement_data.count; // All achievements should be sent to the client
len = (50 * count) + 22;
int count = sd->achievement_data.count; // All achievements should be sent to the client
if (len <= 22)
if (count == 0)
return;
info = achievement_level(sd, true);
int len = (50 * count) + 22;
int fd = sd->fd;
int *info = achievement_level(sd, true);
WFIFOHEAD(fd,len);
WFIFOW(fd, 0) = 0xa23;
@ -20333,10 +20330,10 @@ void clif_achievement_list_all(struct map_session_data *sd)
WFIFOL(fd, 14) = info[0]; // Achievement EXP (left number in bar)
WFIFOL(fd, 18) = info[1]; // Achievement EXP TNL (right number in bar)
for (i = 0; i < count; i++) {
for (int i = 0; i < count; i++) {
WFIFOL(fd, i * 50 + 22) = (uint32)sd->achievement_data.achievements[i].achievement_id;
WFIFOB(fd, i * 50 + 26) = (uint32)sd->achievement_data.achievements[i].completed > 0;
for (j = 0; j < MAX_ACHIEVEMENT_OBJECTIVES; j++)
for (int j = 0; j < MAX_ACHIEVEMENT_OBJECTIVES; j++)
WFIFOL(fd, (i * 50) + 27 + (j * 4)) = (uint32)sd->achievement_data.achievements[i].count[j];
WFIFOL(fd, i * 50 + 67) = (uint32)sd->achievement_data.achievements[i].completed;
WFIFOB(fd, i * 50 + 71) = sd->achievement_data.achievements[i].rewarded > 0;
@ -20345,13 +20342,11 @@ void clif_achievement_list_all(struct map_session_data *sd)
}
/**
* Sends a single achievement's data to the client (ZC_AG_UPDATE).
* Sends a single achievement's data to the client (ZC_ACH_UPDATE).
* 0a24 <packetType>.W <ACHPoint>.L
*/
void clif_achievement_update(struct map_session_data *sd, struct achievement *ach, int count)
{
int fd, i, *info;
nullpo_retv(sd);
if (!battle_config.feature_achievement) {
@ -20359,8 +20354,8 @@ void clif_achievement_update(struct map_session_data *sd, struct achievement *ac
return;
}
fd = sd->fd;
info = achievement_level(sd, true);
int fd = sd->fd;
int *info = achievement_level(sd, true);
WFIFOHEAD(fd, packet_len(0xa24));
WFIFOW(fd, 0) = 0xa24;
@ -20371,7 +20366,7 @@ void clif_achievement_update(struct map_session_data *sd, struct achievement *ac
if (ach) {
WFIFOL(fd, 16) = ach->achievement_id; // Achievement ID
WFIFOB(fd, 20) = ach->completed > 0; // Is it complete?
for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; i++)
for (int i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; i++)
WFIFOL(fd, 21 + (i * 4)) = (uint32)ach->count[i]; // 1~10 pre-reqs
WFIFOL(fd, 61) = (uint32)ach->completed; // Epoch time
WFIFOB(fd, 65) = ach->rewarded > 0; // Got reward?
@ -20381,7 +20376,7 @@ void clif_achievement_update(struct map_session_data *sd, struct achievement *ac
}
/**
* Checks if an achievement reward can be rewarded (CZ_REQ_AG_REWARD).
* Checks if an achievement reward can be rewarded (CZ_REQ_ACH_REWARD).
* 0a25 <packetType>.W <achievementID>.L
*/
void clif_parse_AchievementCheckReward(int fd, struct map_session_data *sd)
@ -20395,7 +20390,7 @@ void clif_parse_AchievementCheckReward(int fd, struct map_session_data *sd)
}
/**
* Returns the result of achievement_check_reward (ZC_REQ_AG_REWARD_ACK).
* Returns the result of achievement_check_reward (ZC_REQ_ACH_REWARD_ACK).
* 0a26 <packetType>.W <result>.W <achievementID>.L
*/
void clif_achievement_reward_ack(int fd, unsigned char result, int achievement_id)