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:
parent
68e98a87e5
commit
ac46920e73
@ -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;
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user