diff --git a/conf/battle/monster.conf b/conf/battle/monster.conf index 012bb622bd..0c616db30d 100644 --- a/conf/battle/monster.conf +++ b/conf/battle/monster.conf @@ -276,3 +276,7 @@ boss_nopc_idleskill_rate: 100 // To switch it off, set it to 0. mob_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 diff --git a/src/map/achievement.cpp b/src/map/achievement.cpp index 66ea1fdf1f..2da72b96a8 100644 --- a/src/map/achievement.cpp +++ b/src/map/achievement.cpp @@ -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. */ diff --git a/src/map/achievement.hpp b/src/map/achievement.hpp index f0b3c215df..9a46e41b13 100644 --- a/src/map/achievement.hpp +++ b/src/map/achievement.hpp @@ -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); void achievement_get_titles(uint32 char_id); 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_db_reload(void); diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 701c6c588c..71b153f616 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -8951,6 +8951,7 @@ static const struct _battle_data { { "ping_timer_inverval", &battle_config.ping_timer_interval, 30, 0, 99999999, }, { "ping_time", &battle_config.ping_time, 20, 0, 99999999, }, { "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" }; diff --git a/src/map/battle.hpp b/src/map/battle.hpp index 4097bf19e5..a6ebe78a20 100644 --- a/src/map/battle.hpp +++ b/src/map/battle.hpp @@ -681,6 +681,7 @@ struct Battle_Config int ping_timer_interval; int ping_time; int show_skill_scale; + int achievement_mob_share; #include "../custom/battle_config_struct.inc" }; diff --git a/src/map/mob.cpp b/src/map/mob.cpp index 8f30e48437..c573f0aef5 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -3006,8 +3006,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) else if (sd->avail_quests) quest_update_objective(sd, md->mob_id); - if (achievement_db.mobexists(md->mob_id)) - achievement_update_objective(sd, AG_BATTLE, 1, md->mob_id); + if (achievement_db.mobexists(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 if (sd->md && src && (src->type == BL_PC || src->type == BL_MER) && mob_db(md->mob_id)->lv > sd->status.base_level / 2)