summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorskyleo <skyleo@skyleo.de>2019-10-15 02:15:21 +0200
committerskyleo <skyleo@skyleo.de>2019-10-18 22:52:13 +0200
commit9858bb5591f495b0e622391a00297366b972e09a (patch)
treeecbf09fe710a731d9a17a295934bdfb8281158b8
parentd026e28fd78f60dfa21da381f17f2a8cc9ae3d11 (diff)
downloadhercules-9858bb5591f495b0e622391a00297366b972e09a.tar.gz
hercules-9858bb5591f495b0e622391a00297366b972e09a.tar.bz2
hercules-9858bb5591f495b0e622391a00297366b972e09a.tar.xz
hercules-9858bb5591f495b0e622391a00297366b972e09a.zip
Make slave mobs react to master's chase target
This fixes slaves not chasing after master's chase target, when master was immobilized by an Ankle Snare for example midway.
-rw-r--r--conf/map/battle/monster.conf5
-rw-r--r--src/map/battle.c3
-rw-r--r--src/map/battle.h1
-rw-r--r--src/map/mob.c70
-rw-r--r--src/map/mob.h1
5 files changed, 58 insertions, 22 deletions
diff --git a/conf/map/battle/monster.conf b/conf/map/battle/monster.conf
index 8f969dc48..389bdc5c7 100644
--- a/conf/map/battle/monster.conf
+++ b/conf/map/battle/monster.conf
@@ -269,3 +269,8 @@ boss_icewall_walk_block: 1
// only have a range of 9. If you put a number higher than 0, their range will
// be increased by that number.
monster_eye_range_bonus: 0
+
+// Should slaves chase after what their master is chasing?
+// false: Don't chase after what master is chasing. (old behavior)
+// true: Chase after what master is chasing. (official, default)
+slave_chase_masters_chasetarget: true
diff --git a/src/map/battle.c b/src/map/battle.c
index 37fc03bca..606c79357 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -4343,7 +4343,7 @@ static struct Damage battle_calc_misc_attack(struct block_list *src, struct bloc
}
break;
}
-
+
battle->reflect_trap(target, src, &md, skill_id);
return md;
@@ -7321,6 +7321,7 @@ static const struct battle_data {
{ "mob_remove_delay", &battle_config.mob_remove_delay, 60000, 1000, INT_MAX, },
{ "mob_active_time", &battle_config.mob_active_time, 0, 0, INT_MAX, },
{ "boss_active_time", &battle_config.boss_active_time, 0, 0, INT_MAX, },
+ { "slave_chase_masters_chasetarget", &battle_config.slave_chase_masters_chasetarget, 1, 0, 1, },
{ "sg_miracle_skill_duration", &battle_config.sg_miracle_skill_duration, 3600000, 0, INT_MAX, },
{ "hvan_explosion_intimate", &battle_config.hvan_explosion_intimate, 45000, 0, 100000, },
{ "quest_exp_rate", &battle_config.quest_exp_rate, 100, 0, INT_MAX, },
diff --git a/src/map/battle.h b/src/map/battle.h
index 4400d37d1..3dee6f239 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -405,6 +405,7 @@ struct Battle_Config {
int mob_remove_delay; // Dynamic Mobs - delay before removing mobs from a map [Skotlex]
int mob_active_time; //Duration through which mobs execute their Hard AI after players leave their area of sight.
int boss_active_time;
+ int slave_chase_masters_chasetarget;
int show_hp_sp_drain, show_hp_sp_gain; //[Skotlex]
int show_katar_crit_bonus;
diff --git a/src/map/mob.c b/src/map/mob.c
index e04d6944e..c8226cd57 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -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;
@@ -5805,6 +5832,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;
diff --git a/src/map/mob.h b/src/map/mob.h
index a48c4cc74..9b0f6ffe0 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -529,6 +529,7 @@ struct mob_interface {
int (*ai_sub_hard_bg_ally) (struct block_list *bl, va_list ap);
int (*ai_sub_hard_lootsearch) (struct block_list *bl, va_list ap);
int (*warpchase_sub) (struct block_list *bl, va_list ap);
+ bool (*is_in_battle_state) (const struct mob_data *md);
int (*ai_sub_hard_slavemob) (struct mob_data *md, int64 tick);
int (*unlocktarget) (struct mob_data *md, int64 tick);
int (*randomwalk) (struct mob_data *md, int64 tick);