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
This commit is contained in:
parent
b1b3aae1e9
commit
ecb01c44f4
@ -50,6 +50,8 @@ monster_max_aspd: 199
|
|||||||
// will receive the delay). This will make monsters harder, especially MvPs.
|
// 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
|
// 0x400: Set this to make mobs have a range of 9 for all skills. Otherwise, they
|
||||||
// will obey the normal skill range rules.
|
// 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.
|
// Example: 0x140 -> Chase players through warps + use skills in random order.
|
||||||
monster_ai: 0
|
monster_ai: 0
|
||||||
|
|
||||||
|
@ -8014,7 +8014,7 @@ static const struct _battle_data {
|
|||||||
{ "ignore_items_gender", &battle_config.ignore_items_gender, 1, 0, 1, },
|
{ "ignore_items_gender", &battle_config.ignore_items_gender, 1, 0, 1, },
|
||||||
{ "berserk_cancels_buffs", &battle_config.berserk_cancels_buffs, 0, 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, },
|
{ "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, },
|
{ "hom_setting", &battle_config.hom_setting, 0xFFFF, 0x0000, 0xFFFF, },
|
||||||
{ "dynamic_mobs", &battle_config.dynamic_mobs, 1, 0, 1, },
|
{ "dynamic_mobs", &battle_config.dynamic_mobs, 1, 0, 1, },
|
||||||
{ "mob_remove_damaged", &battle_config.mob_remove_damaged, 1, 0, 1, },
|
{ "mob_remove_damaged", &battle_config.mob_remove_damaged, 1, 0, 1, },
|
||||||
|
@ -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)
|
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]
|
// Special feature that makes monsters always attack the person that provoked them
|
||||||
if(md->state.provoke_flag)
|
if(battle_config.mob_ai&0x800 && md->state.provoke_flag)
|
||||||
{
|
{
|
||||||
if (md->state.provoke_flag == target->id)
|
if (md->state.provoke_flag == target->id)
|
||||||
return 1;
|
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.
|
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)
|
if (md->state.provoke_flag && bl->id != md->state.provoke_flag)
|
||||||
md->state.provoke_flag = 0;
|
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;
|
md->min_chase=dist+md->db->range3;
|
||||||
if(md->min_chase>MAX_MINCHASE)
|
if(md->min_chase>MAX_MINCHASE)
|
||||||
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:
|
default:
|
||||||
mob_stop_attack(md);
|
mob_stop_attack(md);
|
||||||
mob_stop_walking(md,1); //Stop chasing.
|
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;
|
md->state.skillstate = MSS_IDLE;
|
||||||
if(battle_config.mob_ai&0x8) //Walk instantly after dropping target
|
if(battle_config.mob_ai&0x8) //Walk instantly after dropping target
|
||||||
md->next_walktime = tick+rnd()%1000;
|
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 (!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 */
|
/* bg guardians follow allies when no targets nearby */
|
||||||
if( md->bg_id && mode&MD_CANATTACK ) {
|
if( md->bg_id && mode&MD_CANATTACK ) {
|
||||||
if( md->ud.walktimer != INVALID_TIMER )
|
if( md->ud.walktimer != INVALID_TIMER )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user