From ecb01c44f4465e7716606a25966ed33b3e6e5c63 Mon Sep 17 00:00:00 2001 From: Playtester Date: Fri, 4 Mar 2016 21:22:16 +0100 Subject: [PATCH] Monster angry mode and provoke (fixes #1011) * When provoked, monsters will now only switch targets when they would also change targets on damage * Added a new option to the mob_ai setting to restore the old behavior (monsters always go after the one casting provoke) * When casting provoke on an angry mode monster before it was attacked, it will now go for the one casting provoke and not switch back to the closest target * Angry mode will now always be reset when the monster switches to idle --- conf/battle/monster.conf | 2 ++ src/map/battle.c | 2 +- src/map/mob.c | 12 +++++++----- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/conf/battle/monster.conf b/conf/battle/monster.conf index 0d8443828d..8d4bb623a3 100644 --- a/conf/battle/monster.conf +++ b/conf/battle/monster.conf @@ -50,6 +50,8 @@ monster_max_aspd: 199 // will receive the delay). This will make monsters harder, especially MvPs. // 0x400: Set this to make mobs have a range of 9 for all skills. Otherwise, they // will obey the normal skill range rules. +// 0x800: When set, monsters that are provoked will always change target to the +// provoking person, even if they would usually not change target on attack. // Example: 0x140 -> Chase players through warps + use skills in random order. monster_ai: 0 diff --git a/src/map/battle.c b/src/map/battle.c index 97c7b05ea1..bc6f691dbe 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -8014,7 +8014,7 @@ static const struct _battle_data { { "ignore_items_gender", &battle_config.ignore_items_gender, 1, 0, 1, }, { "berserk_cancels_buffs", &battle_config.berserk_cancels_buffs, 0, 0, 1, }, { "debuff_on_logout", &battle_config.debuff_on_logout, 1|2, 0, 1|2, }, - { "monster_ai", &battle_config.mob_ai, 0x000, 0x000, 0x7FF, }, + { "monster_ai", &battle_config.mob_ai, 0x000, 0x000, 0xFFF, }, { "hom_setting", &battle_config.hom_setting, 0xFFFF, 0x0000, 0xFFFF, }, { "dynamic_mobs", &battle_config.dynamic_mobs, 1, 0, 1, }, { "mob_remove_damaged", &battle_config.mob_remove_damaged, 1, 0, 1, }, diff --git a/src/map/mob.c b/src/map/mob.c index 8f067430da..c8b42d14c2 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1036,8 +1036,8 @@ int mob_spawn (struct mob_data *md) *------------------------------------------*/ static int mob_can_changetarget(struct mob_data* md, struct block_list* target, enum e_mode mode) { - // if the monster was provoked ignore the above rule [celest] - if(md->state.provoke_flag) + // Special feature that makes monsters always attack the person that provoked them + if(battle_config.mob_ai&0x800 && md->state.provoke_flag) { if (md->state.provoke_flag == target->id) return 1; @@ -1083,6 +1083,9 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist) md->target_id = bl->id; // Since there was no disturbance, it locks on to target. if (md->state.provoke_flag && bl->id != md->state.provoke_flag) md->state.provoke_flag = 0; + // When an angry monster is provoked, it will switch to retaliate AI + if (md->state.provoke_flag && md->state.aggressive) + md->state.aggressive = 0; md->min_chase=dist+md->db->range3; if(md->min_chase>MAX_MINCHASE) md->min_chase=MAX_MINCHASE; @@ -1362,6 +1365,8 @@ int mob_unlocktarget(struct mob_data *md, unsigned int tick) default: mob_stop_attack(md); mob_stop_walking(md,1); //Stop chasing. + if (md->status.mode&MD_ANGRY && !md->state.aggressive) + md->state.aggressive = 1; //Restore angry state when switching to idle md->state.skillstate = MSS_IDLE; if(battle_config.mob_ai&0x8) //Walk instantly after dropping target md->next_walktime = tick+rnd()%1000; @@ -1615,9 +1620,6 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) } if (!tbl) { //No targets available. - if (mode&MD_ANGRY && !md->state.aggressive) - md->state.aggressive = 1; //Restore angry state when no targets are available. - /* bg guardians follow allies when no targets nearby */ if( md->bg_id && mode&MD_CANATTACK ) { if( md->ud.walktimer != INVALID_TIMER )