summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-09-17 20:15:36 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-09-17 20:15:36 +0000
commit0594ed80d95621d3e6af7d150e7c56fc2b0bc6ca (patch)
tree488f022ac5a1bbdfd40f4755b3ed676b22b60962 /src
parent064924d37b34eb38c5b602f6f816c2abd1b995b1 (diff)
downloadhercules-0594ed80d95621d3e6af7d150e7c56fc2b0bc6ca.tar.gz
hercules-0594ed80d95621d3e6af7d150e7c56fc2b0bc6ca.tar.bz2
hercules-0594ed80d95621d3e6af7d150e7c56fc2b0bc6ca.tar.xz
hercules-0594ed80d95621d3e6af7d150e7c56fc2b0bc6ca.zip
- Finally got some time to clean up and fix monster_ai&0x40 (chase through warps). It works correctly now regardless of the number of players on the source/destination maps.
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@11233 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src')
-rw-r--r--src/map/mob.c63
-rw-r--r--src/map/mob.h2
-rw-r--r--src/map/unit.c11
3 files changed, 58 insertions, 18 deletions
diff --git a/src/map/mob.c b/src/map/mob.c
index 7de4fd50a..86d60a152 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -875,19 +875,32 @@ static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
return 0;
}
-static int mob_ai_sub_hard_warpsearch(struct block_list *bl,va_list ap)
+static int mob_warpchase_sub(struct block_list *bl,va_list ap)
{
struct mob_data* md;
- struct block_list **target;
+ struct block_list *target;
+ struct npc_data **target_nd;
+ struct npc_data *nd;
+ int *min_distance;
+ int cur_distance;
md=va_arg(ap,struct mob_data *);
- target= va_arg(ap,struct block_list**);
-
- if (*target) return 0;
-
- if(bl->subtype == WARP)
- {
- *target = bl;
+ target= va_arg(ap, struct block_list*);
+ target_nd= va_arg(ap, struct npc_data**);
+ min_distance= va_arg(ap, int*);
+
+ if(bl->subtype != WARP)
+ return 0; //Not a warp
+ nd = (TBL_NPC*) bl;
+
+ if(nd->u.warp.mapindex != map[target->m].index)
+ return 0; //Does not lead to the same map.
+
+ cur_distance = distance_blxy(target, nd->u.warp.x, nd->u.warp.y);
+ if (cur_distance < *min_distance)
+ { //Pick warp that leads closest to target.
+ *target_nd = nd;
+ *min_distance = cur_distance;
return 1;
}
return 0;
@@ -1073,6 +1086,29 @@ int mob_randomwalk(struct mob_data *md,unsigned int tick)
return 1;
}
+int mob_warpchase(struct mob_data *md, struct block_list *target)
+{
+ struct npc_data *warp = NULL;
+ int distance = AREA_SIZE;
+ if (!(target && battle_config.mob_ai&0x40 && battle_config.mob_warp&1))
+ return 0; //Can't warp chase.
+
+ if (target->m == md->bl.m && check_distance_bl(&md->bl, target, AREA_SIZE))
+ return 0; //No need to do a warp chase.
+
+ if (md->ud.walktimer != -1 &&
+ map_getcell(md->bl.m,md->ud.to_x,md->ud.to_y,CELL_CHKNPC))
+ return 1; //Already walking to a warp.
+
+ //Search for warps within mob's viewing range.
+ map_foreachinrange (mob_warpchase_sub, &md->bl,
+ md->db->range2, BL_NPC, md, target, &warp, &distance);
+
+ if (warp && unit_walktobl(&md->bl, &warp->bl, 0, 1))
+ return 1;
+ return 0;
+}
+
/*==========================================
* AI of MOB whose is near a Player
*------------------------------------------*/
@@ -1128,13 +1164,8 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
((((TBL_PC*)tbl)->state.gangsterparadise && !(mode&MD_BOSS)) ||
((TBL_PC*)tbl)->invincible_timer != INVALID_TIMER)
)) { //Unlock current target.
- if (tbl && tbl->m != md->bl.m && battle_config.mob_ai&0x40)
- { //Chase to a nearby warp [Skotlex]
- tbl = NULL;
- map_foreachinrange (mob_ai_sub_hard_warpsearch, &md->bl,
- view_range, BL_NPC, md, &tbl);
- if (tbl) unit_walktobl(&md->bl, tbl, 0, 1);
- }
+ if (mob_warpchase(md, tbl))
+ return 0; //Chasing this target.
mob_unlocktarget(md, tick-(battle_config.mob_ai&0x8?3000:0)); //Imediately do random walk.
tbl = NULL;
}
diff --git a/src/map/mob.h b/src/map/mob.h
index 93fe8225e..25a314d75 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -163,7 +163,7 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam
int mob_guardian_guildchange(struct block_list *bl,va_list ap); //Change Guardian's ownership. [Skotlex]
int mob_randomwalk(struct mob_data *md,unsigned int tick);
-
+int mob_warpchase(struct mob_data *md, struct block_list *target);
int mob_target(struct mob_data *md,struct block_list *bl,int dist);
int mob_unlocktarget(struct mob_data *md,int tick);
struct mob_data* mob_spawn_dataset(struct spawn_data *data);
diff --git a/src/map/unit.c b/src/map/unit.c
index b92804459..3befc3f2d 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -233,6 +233,8 @@ static int unit_walktoxy_timer(int tid,unsigned int tick,int id,int data)
if (!tbl || !status_check_visibility(bl, tbl)) { //Cancel chase.
ud->to_x = bl->x;
ud->to_y = bl->y;
+ if (tbl && bl->type == BL_MOB) //See if the mob can do a warp chase.
+ mob_warpchase((TBL_MOB*)bl, tbl);
return 0;
}
if (tbl->m == bl->m && check_distance_bl(bl, tbl, ud->chaserange))
@@ -1367,9 +1369,16 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
if(src == NULL || src->prev == NULL || target==NULL || target->prev == NULL)
return 0;
- if(src->m != target->m || status_isdead(src) || status_isdead(target) || !status_check_skilluse(src, target, 0, 0))
+ if(status_isdead(src) || status_isdead(target) || !status_check_skilluse(src, target, 0, 0))
return 0; // can't attack under these conditions
+ if (src->m != target->m)
+ {
+ if (src->type == BL_MOB && mob_warpchase((TBL_MOB*)src, target))
+ return 1; // Follow up.
+ return 0;
+ }
+
if(ud->skilltimer != -1 && !(sd && pc_checkskill(sd,SA_FREECAST) > 0))
return 0; // can't attack while casting