Adds support for sharing battle-type Achievements (#5021)

* Fixes #5018.
* Adds support for sharing battle-type Achievements when killing monsters.
* The behavior mimics Quest objectives.
* Adds a battle_config to easily toggle (off by default until confirmed on kRO).
Thanks to @MccloudBR's suggestion!
This commit is contained in:
Aleos 2020-06-12 13:02:50 -04:00 committed by GitHub
parent c875ebd5e2
commit 5647c875d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 2 deletions

View File

@ -276,3 +276,7 @@ boss_nopc_idleskill_rate: 100
// To switch it off, set it to 0. // To switch it off, set it to 0.
mob_nopc_move_rate: 100 mob_nopc_move_rate: 100
boss_nopc_move_rate: 100 boss_nopc_move_rate: 100
// When killing a monster, do AG_BATTLE type achievements trigger for everyone in the same party within the area?
// Area is limited to area_size battle config.
achievement_mob_share: no

View File

@ -1040,6 +1040,34 @@ void achievement_update_objective(struct map_session_data *sd, enum e_achievemen
} }
} }
/**
* Map iterator subroutine to update achievement objectives for a party after killing a monster.
* @see map_foreachinrange
* @param ap: Argument list, expecting:
* int Party ID
* int Mob ID
*/
int achievement_update_objective_sub(block_list *bl, va_list ap)
{
map_session_data *sd;
int mob_id, party_id;
nullpo_ret(bl);
nullpo_ret(sd = (map_session_data *)bl);
party_id = va_arg(ap, int);
mob_id = va_arg(ap, int);
if (sd->achievement_data.achievements == nullptr)
return 0;
if (sd->status.party_id != party_id)
return 0;
achievement_update_objective(sd, AG_BATTLE, 1, mob_id);
return 1;
}
/** /**
* Loads achievements from the achievement db. * Loads achievements from the achievement db.
*/ */

View File

@ -140,6 +140,7 @@ int *achievement_level(struct map_session_data *sd, bool flag);
bool achievement_check_condition(struct script_code* condition, struct map_session_data* sd); bool achievement_check_condition(struct script_code* condition, struct map_session_data* sd);
void achievement_get_titles(uint32 char_id); void achievement_get_titles(uint32 char_id);
void achievement_update_objective(struct map_session_data *sd, enum e_achievement_group group, uint8 arg_count, ...); void achievement_update_objective(struct map_session_data *sd, enum e_achievement_group group, uint8 arg_count, ...);
int achievement_update_objective_sub(block_list *bl, va_list ap);
void achievement_read_db(void); void achievement_read_db(void);
void achievement_db_reload(void); void achievement_db_reload(void);

View File

@ -8951,6 +8951,7 @@ static const struct _battle_data {
{ "ping_timer_inverval", &battle_config.ping_timer_interval, 30, 0, 99999999, }, { "ping_timer_inverval", &battle_config.ping_timer_interval, 30, 0, 99999999, },
{ "ping_time", &battle_config.ping_time, 20, 0, 99999999, }, { "ping_time", &battle_config.ping_time, 20, 0, 99999999, },
{ "show_skill_scale", &battle_config.show_skill_scale, 1, 0, 1, }, { "show_skill_scale", &battle_config.show_skill_scale, 1, 0, 1, },
{ "achievement_mob_share", &battle_config.achievement_mob_share, 0, 0, 1, },
#include "../custom/battle_config_init.inc" #include "../custom/battle_config_init.inc"
}; };

View File

@ -681,6 +681,7 @@ struct Battle_Config
int ping_timer_interval; int ping_timer_interval;
int ping_time; int ping_time;
int show_skill_scale; int show_skill_scale;
int achievement_mob_share;
#include "../custom/battle_config_struct.inc" #include "../custom/battle_config_struct.inc"
}; };

View File

@ -3006,8 +3006,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
else if (sd->avail_quests) else if (sd->avail_quests)
quest_update_objective(sd, md->mob_id); quest_update_objective(sd, md->mob_id);
if (achievement_db.mobexists(md->mob_id)) if (achievement_db.mobexists(md->mob_id)) {
achievement_update_objective(sd, AG_BATTLE, 1, md->mob_id); if (battle_config.achievement_mob_share > 0 && sd->status.party_id > 0)
map_foreachinallrange(achievement_update_objective_sub, &md->bl, AREA_SIZE, BL_PC, sd->status.party_id, md->mob_id);
else
achievement_update_objective(sd, AG_BATTLE, 1, md->mob_id);
}
// The master or Mercenary can increase the kill count // The master or Mercenary can increase the kill count
if (sd->md && src && (src->type == BL_PC || src->type == BL_MER) && mob_db(md->mob_id)->lv > sd->status.base_level / 2) if (sd->md && src && (src->type == BL_PC || src->type == BL_MER) && mob_db(md->mob_id)->lv > sd->status.base_level / 2)