From fcdcce2cfa6abc4390401a06ae342b104cdc29a8 Mon Sep 17 00:00:00 2001 From: Aleos Date: Tue, 28 Jul 2020 14:57:09 -0400 Subject: [PATCH] Fixes NPC_RUN behavior (#5236) * Fixes #3622 and fixes #5220. * Monsters now properly escape from the attacker. * NPC_RUN should determine distance based on skill level > 1. * Resolves Sphere Mine when summoned by an Alchemist not escaping. Thanks to @Balferian, @Indigo000, and @Daegaladh! --- db/pre-re/mob_skill_db.txt | 7 +++---- db/re/mob_skill_db.txt | 7 +++---- src/map/mob.cpp | 1 + src/map/skill.cpp | 10 ++++++++-- src/map/unit.cpp | 11 +++++++++-- src/map/unit.hpp | 2 +- 6 files changed, 25 insertions(+), 13 deletions(-) diff --git a/db/pre-re/mob_skill_db.txt b/db/pre-re/mob_skill_db.txt index 8ac3331051..b347ff9423 100644 --- a/db/pre-re/mob_skill_db.txt +++ b/db/pre-re/mob_skill_db.txt @@ -714,12 +714,11 @@ 1141,Marina@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,target,always,0,,,,,,6, 1141,Marina@NPC_EMOTION,walk,197,1,2000,0,5000,yes,self,always,0,19,,,,,, 1141,Marina@NPC_WATERATTACK,attack,184,2,500,500,5000,no,target,always,0,,,,,,6, -1142,Marine Sphere@NPC_RUN,idle,354,7,10000,0,30000,no,master,alchemist,,,,,,,26, -1142,Marine Sphere@NPC_SELFDESTRUCTION,any,173,1,10000,3000,0,no,self,afterskill,354,,,,,,, +1142,Marine Sphere@NPC_RANDOMMOVE,idle,331,1,10000,0,30000,yes,target,alchemist,,,,,,,, +1142,Marine Sphere@NPC_SELFDESTRUCTION,idle,173,1,10000,3000,0,yes,self,alchemist,,,,,,,, 1142,Marine Sphere@NPC_SELFDESTRUCTION,idle,173,1,500,2000,5000,no,self,myhpltmaxrate,99,,,,,,, 1142,Marine Sphere@NPC_SELFDESTRUCTION,idle,173,1,10000,2000,5000,no,self,skillused,173,,,,,,, -//1142,Marine Sphere@NPC_SELFDESTRUCTION,idle,173,1,10000,0,0,yes,self,always,0,,,,,,, -//1142,Marine Sphere@NPC_SPEEDUP,any,332,1,10000,0,700,yes,self,always,0,,,,,,, +1142,Marine Sphere@NPC_SPEEDUP,idle,332,1,10000,0,700,yes,target,always,,,,,,,, 1143,Marionette@HT_FREEZINGTRAP,idle,121,5,500,0,300000,yes,around2,always,0,,,,,,29, 1143,Marionette@MG_FIREWALL,chase,18,5,500,500,5000,yes,target,always,0,,,,,,2, 1143,Marionette@NPC_TELEKINESISATTACK,attack,191,5,500,0,5000,yes,target,always,0,,,,,,6, diff --git a/db/re/mob_skill_db.txt b/db/re/mob_skill_db.txt index d6a0dd596a..f2e475cb11 100644 --- a/db/re/mob_skill_db.txt +++ b/db/re/mob_skill_db.txt @@ -714,12 +714,11 @@ 1141,Marina@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,target,always,0,,,,,,6, 1141,Marina@NPC_EMOTION,walk,197,1,2000,0,5000,yes,self,always,0,19,,,,,, 1141,Marina@NPC_WATERATTACK,attack,184,2,500,500,5000,no,target,always,0,,,,,,6, -1142,Marine Sphere@NPC_RUN,idle,354,7,10000,0,30000,no,master,alchemist,,,,,,,26, -1142,Marine Sphere@NPC_SELFDESTRUCTION,any,173,1,10000,3000,0,no,self,afterskill,354,,,,,,, +1142,Marine Sphere@NPC_RANDOMMOVE,idle,331,1,10000,0,30000,yes,target,alchemist,,,,,,,, +1142,Marine Sphere@NPC_SELFDESTRUCTION,idle,173,1,10000,3000,0,yes,self,alchemist,,,,,,,, 1142,Marine Sphere@NPC_SELFDESTRUCTION,idle,173,1,500,2000,5000,no,self,myhpltmaxrate,99,,,,,,, 1142,Marine Sphere@NPC_SELFDESTRUCTION,idle,173,1,10000,2000,5000,no,self,skillused,173,,,,,,, -//1142,Marine Sphere@NPC_SELFDESTRUCTION,idle,173,1,10000,0,0,yes,self,always,0,,,,,,, -//1142,Marine Sphere@NPC_SPEEDUP,any,332,1,10000,0,700,yes,self,always,0,,,,,,, +1142,Marine Sphere@NPC_SPEEDUP,idle,332,1,10000,0,700,yes,target,always,,,,,,,, 1143,Marionette@HT_FREEZINGTRAP,idle,121,5,500,0,300000,yes,around2,always,0,,,,,,29, 1143,Marionette@MG_FIREWALL,chase,18,5,500,500,5000,yes,target,always,0,,,,,,2, 1143,Marionette@NPC_TELEKINESISATTACK,attack,191,5,500,0,5000,yes,target,always,0,,,,,,6, diff --git a/src/map/mob.cpp b/src/map/mob.cpp index 00589066b5..7e1066091f 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -2433,6 +2433,7 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) if( md->special_state.ai == AI_SPHERE ) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex] md->state.alchemist = 1; mobskill_use(md, gettick(), MSC_ALCHEMIST); + unit_escape(&md->bl, src, 7, 2); } } diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 0b4cc8c2ad..cfa8f192d6 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -8800,8 +8800,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui break; case NPC_RUN: - if (md && unit_escape(src, bl, rnd()%10 + 1)) - mob_unlocktarget(md, tick); + if (md) { + block_list* tbl = map_id2bl(md->target_id); + + if (tbl) { + mob_unlocktarget(md, tick); + unit_escape(src, tbl, skill_lv > 1 ? skill_lv : AREA_SIZE, 2); // Send distance in skill level > 1 + } + } break; case NPC_TRANSFORMATION: diff --git a/src/map/unit.cpp b/src/map/unit.cpp index eba9de6b31..15632f2015 100644 --- a/src/map/unit.cpp +++ b/src/map/unit.cpp @@ -977,16 +977,17 @@ bool unit_run(struct block_list *bl, struct map_session_data *sd, enum sc_type t * @param bl: Object that is running away from target * @param target: Target * @param dist: How far bl should run + * @param flag: unit_walktoxy flag * @return 1: Success 0: Fail */ -int unit_escape(struct block_list *bl, struct block_list *target, short dist) +int unit_escape(struct block_list *bl, struct block_list *target, short dist, uint8 flag) { uint8 dir = map_calc_dir(target, bl->x, bl->y); while( dist > 0 && map_getcell(bl->m, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], CELL_CHKNOREACH) ) dist--; - return ( dist > 0 && unit_walktoxy(bl, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], 0) ); + return ( dist > 0 && unit_walktoxy(bl, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], flag) ); } /** @@ -1546,6 +1547,12 @@ int unit_set_walkdelay(struct block_list *bl, t_tick tick, t_tick delay, int typ } else { // Don't set walk delays when already trapped. if (!unit_can_move(bl)) { + if (bl->type == BL_MOB) { + mob_data *md = BL_CAST(BL_MOB, bl); + + if (md && md->state.alchemist == 1) // Sphere Mine needs to escape, don't stop it + return 0; + } unit_stop_walking(bl,4); //Unit might still be moving even though it can't move return 0; } diff --git a/src/map/unit.hpp b/src/map/unit.hpp index f2b718f156..3a78b54c8f 100644 --- a/src/map/unit.hpp +++ b/src/map/unit.hpp @@ -121,7 +121,7 @@ int unit_can_move(struct block_list *bl); int unit_is_walking(struct block_list *bl); int unit_set_walkdelay(struct block_list *bl, t_tick tick, t_tick delay, int type); -int unit_escape(struct block_list *bl, struct block_list *target, short dist); +int unit_escape(struct block_list *bl, struct block_list *target, short dist, uint8 flag = 0); // Instant unit changes bool unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath);