diff options
Diffstat (limited to 'src/map/mob.c')
-rw-r--r-- | src/map/mob.c | 104 |
1 files changed, 66 insertions, 38 deletions
diff --git a/src/map/mob.c b/src/map/mob.c index a9d6c8a51..56d07da92 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -479,7 +479,7 @@ static bool mob_ksprotected(struct block_list *src, struct block_list *target) // Message to KS if( DIFF_TICK(sd->ks_floodprotect_tick, tick) <= 0 ) { - sprintf(output, "[KS Warning!! - Owner : %s]", pl_sd->status.name); + sprintf(output, msg_sd(sd, 890), pl_sd->status.name); // [KS Warning!! - Owner : %s] clif_disp_onlyself(sd, output); sd->ks_floodprotect_tick = tick + 2000; @@ -488,7 +488,7 @@ static bool mob_ksprotected(struct block_list *src, struct block_list *target) // Message to Owner if( DIFF_TICK(pl_sd->ks_floodprotect_tick, tick) <= 0 ) { - sprintf(output, "[Watch out! %s is trying to KS you!]", sd->status.name); + sprintf(output, msg_sd(pl_sd, 891), sd->status.name); // [Watch out! %s is trying to KS you!] clif_disp_onlyself(pl_sd, output); pl_sd->ks_floodprotect_tick = tick + 2000; @@ -1297,6 +1297,27 @@ static int mob_warpchase_sub(struct block_list *bl, va_list ap) } return 0; } + +/** + * Checks if a monster is currently involved in battle, + * may it be due to aggression or being attacked. + * @param bl: monster's bl + * @return true if in battle, false otherwise + */ +static bool mob_is_in_battle_state(const struct mob_data *md) +{ + nullpo_retr(false, md); + switch (md->state.skillstate) { + case MSS_BERSERK: + case MSS_ANGRY: + case MSS_RUSH: + case MSS_FOLLOW: + return true; + default: + return false; + } +} + /*========================================== * Processing of slave monsters *------------------------------------------*/ @@ -1341,8 +1362,11 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) ) { short x = bl->x, y = bl->y; mob_stop_attack(md); - if(map->search_freecell(&md->bl, bl->m, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 1) - && unit->walktoxy(&md->bl, x, y, 0)) + const struct mob_data *m_md = BL_CCAST(BL_MOB, bl); + nullpo_retr(0, m_md); + if (map->search_freecell(&md->bl, bl->m, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 1) + && (battle_config.slave_chase_masters_chasetarget == 0 || !mob->is_in_battle_state(m_md)) + && unit->walktoxy(&md->bl, x, y, 0)) return 1; } } else if (bl->m != md->bl.m && map_flag_gvg(md->bl.m)) { @@ -1353,26 +1377,29 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) //Avoid attempting to lock the master's target too often to avoid unnecessary overload. [Skotlex] if (DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME && !md->target_id) { - struct unit_data *ud = unit->bl2ud(bl); + struct unit_data *ud = unit->bl2ud(bl); + struct mob_data *m_md = BL_CAST(BL_MOB, bl); + nullpo_retr(0, ud); + nullpo_retr(0, m_md); md->last_linktime = tick; - - if (ud) { - struct block_list *tbl=NULL; - if (ud->target && ud->state.attack_continue) - tbl=map->id2bl(ud->target); - else if (ud->skilltarget) { - tbl = map->id2bl(ud->skilltarget); - //Required check as skilltarget is not always an enemy. [Skotlex] - if (tbl && battle->check_target(&md->bl, tbl, BCT_ENEMY) <= 0) - tbl = NULL; - } - if (tbl && status->check_skilluse(&md->bl, tbl, 0, 0)) { - md->target_id=tbl->id; - md->min_chase=md->db->range3+distance_bl(&md->bl, tbl); - if(md->min_chase>MAX_MINCHASE) - md->min_chase=MAX_MINCHASE; - return 1; - } + struct block_list *tbl = NULL; + + if (battle_config.slave_chase_masters_chasetarget == 1 && m_md->target_id != 0) { // possibly chasing something + tbl = map->id2bl(m_md->target_id); + } else if (ud->target != 0 && ud->state.attack_continue != 0) { + tbl = map->id2bl(ud->target); + } else if (ud->skilltarget != 0) { + tbl = map->id2bl(ud->skilltarget); + //Required check as skilltarget is not always an enemy. [Skotlex] + if (tbl != NULL && battle->check_target(&md->bl, tbl, BCT_ENEMY) <= 0) + tbl = NULL; + } + if (tbl != NULL && status->check_skilluse(&md->bl, tbl, 0, 0) != 0) { + md->target_id = tbl->id; + md->min_chase = md->db->range3 + distance_bl(&md->bl, tbl); + if (md->min_chase > MAX_MINCHASE) + md->min_chase = MAX_MINCHASE; + return 1; } } return 0; @@ -1910,7 +1937,7 @@ static int mob_ai_hard(int tid, int64 tick, int id, intptr_t data) /** * Adds random options of a given options drop group into item. - * + * * @param item : item receiving random options * @param options : Random Option Drop Group to be used */ @@ -1918,7 +1945,7 @@ static void mob_setdropitem_options(struct item *item, struct optdrop_group *opt { nullpo_retv(item); nullpo_retv(options); - + for (int i = 0; i < options->optslot_count; i++) { if (rnd() % 10000 >= options->optslot_rate[i]) continue; @@ -1950,7 +1977,7 @@ static struct item_drop *mob_setdropitem(int nameid, struct optdrop_group *optio drop->item_data.nameid = nameid; drop->item_data.amount = qty; drop->item_data.identify = data ? itemdb->isidentified2(data) : itemdb->isidentified(nameid); - + // Set item options [KirieZ] if (options != NULL) mob->setdropitem_options(&drop->item_data, options); @@ -3934,7 +3961,7 @@ static bool mob_read_optdrops_option(struct config_setting_t *option, struct opt ShowWarning("mob_read_optdrops_option: Invalid option \"%s\" for option slot %d of %s group, skipping.\n", name, slot, group); return false; } - + int min = 0, max = 0, opt_rate = 0; if (config_setting_is_number(option)) { // OptionName: value @@ -3943,13 +3970,13 @@ static bool mob_read_optdrops_option(struct config_setting_t *option, struct opt // OptionName: [min, max] // OptionName: [min, max, rate] int slen = libconfig->setting_length(option); - + if (slen >= 2) { // [min, max,...] min = libconfig->setting_get_int_elem(option, 0); max = libconfig->setting_get_int_elem(option, 1); } - + if (slen == 3) { // [min, max, rate] opt_rate = libconfig->setting_get_int_elem(option, 2); @@ -3961,7 +3988,7 @@ static bool mob_read_optdrops_option(struct config_setting_t *option, struct opt if (max < min) max = min; - + entry->options[*idx].id = opt_id; entry->options[*idx].min = min; entry->options[*idx].max = max; @@ -3989,7 +4016,7 @@ static bool mob_read_optdrops_optslot(struct config_setting_t *optslot, int n, i nullpo_retr(false, group); Assert_retr(false, group_id >= 0 && group_id < mob->opt_drop_groups_count); Assert_retr(false, n >= 0 && n < MAX_ITEM_OPTIONS); - + // Structure: // { // Rate: chance of option 1 (int) @@ -4013,7 +4040,7 @@ static bool mob_read_optdrops_optslot(struct config_setting_t *optslot, int n, i struct optdrop_group_optslot *entry = &(mob->opt_drop_groups[group_id].optslot[n]); entry->options = aCalloc(sizeof(struct optdrop_group_option), count); - + int idx = 0; int i = 0; struct config_setting_t *opt = NULL; @@ -4025,7 +4052,7 @@ static bool mob_read_optdrops_optslot(struct config_setting_t *optslot, int n, i entry->option_count = idx; mob->opt_drop_groups[group_id].optslot_count++; mob->opt_drop_groups[group_id].optslot_rate[n] = drop_rate; - + // If there're empty rates, calculate them if (calc_rate == true) { for (int j = 0; j < idx; ++j) { @@ -4192,7 +4219,7 @@ static uint32 mob_read_db_mode_sub(struct mob_db *entry, struct config_setting_t /** * Process an entry of mob/mvp drops that contains a random option drop group. - * + * * @param entry : mob db entry being read (used in error messages) * @param item_name : AegisName of the item in this entry (used in error messages) * @param drop : drop data entry @@ -4215,7 +4242,7 @@ static struct optdrop_group *mob_read_db_drops_option(struct mob_db *entry, cons int i32; if (mob->get_const(libconfig->setting_get_elem(drop, 0), &i32) && i32 >= 0) *drop_rate = i32; - + const char *group_name = libconfig->setting_get_string_elem(drop, 1); if (group_name == NULL || *group_name == '\0') { ShowError("mob_read_db_optdrops: Missing option drop group name on item \"%s\" in monster %d, skipping.\n", item_name, entry->mob_id); @@ -4260,7 +4287,7 @@ static void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct config_setting i++; continue; } - + struct optdrop_group *drop_option = NULL; if (config_setting_is_number(drop)) { // Setting is a number, item doesn't contain options @@ -4340,7 +4367,7 @@ static void mob_read_db_drops_sub(struct mob_db *entry, struct config_setting_t // (Drop Rate, "Opt Drop Group") drop_option = mob->read_db_drops_option(entry, name, drop, &value); } - + if (value <= 0) { ShowWarning("mob_read_db: wrong drop chance %d for drop item %s in monster %d\n", value, name, entry->mob_id); i++; @@ -5668,7 +5695,7 @@ static void mob_destroy_drop_groups(void) { for (int i = 0; i < mob->opt_drop_groups_count; i++) { struct optdrop_group *group = &mob->opt_drop_groups[i]; - + for (int j = 0; j < group->optslot_count; j++) { aFree(group->optslot[j].options); } @@ -5803,6 +5830,7 @@ void mob_defaults(void) mob->ai_sub_hard_bg_ally = mob_ai_sub_hard_bg_ally; mob->ai_sub_hard_lootsearch = mob_ai_sub_hard_lootsearch; mob->warpchase_sub = mob_warpchase_sub; + mob->is_in_battle_state = mob_is_in_battle_state; mob->ai_sub_hard_slavemob = mob_ai_sub_hard_slavemob; mob->unlocktarget = mob_unlocktarget; mob->randomwalk = mob_randomwalk; |