Selaa lähdekoodia

- 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://svn.code.sf.net/p/rathena/svn/trunk@11233 54d463be-8e91-2dee-dedb-b68131a5f0ec
skotlex 17 vuotta sitten
vanhempi
commit
793b2aaafb
4 muutettua tiedostoa jossa 61 lisäystä ja 18 poistoa
  1. 3 0
      Changelog-Trunk.txt
  2. 47 16
      src/map/mob.c
  3. 1 1
      src/map/mob.h
  4. 10 1
      src/map/unit.c

+ 3 - 0
Changelog-Trunk.txt

@@ -4,6 +4,9 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 
 2007/09/17
 2007/09/17
+	* Cleaned up and fixed monster_ai&0x40 (chase through warps). It works
+	  correctly now regardless of the number of players on the source/destination
+	  maps.
 	* Updated sql files [Playtester]
 	* Updated sql files [Playtester]
 	* Applied various crash-protections to script commands that deal with the
 	* Applied various crash-protections to script commands that deal with the
 	  equip-position array.
 	  equip-position array.

+ 47 - 16
src/map/mob.c

@@ -875,19 +875,32 @@ static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
 	return 0;
 	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 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 *);
 	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 1;
 	}	
 	}	
 	return 0;
 	return 0;
@@ -1073,6 +1086,29 @@ int mob_randomwalk(struct mob_data *md,unsigned int tick)
 	return 1;
 	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
  * 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)->state.gangsterparadise && !(mode&MD_BOSS)) ||
 				((TBL_PC*)tbl)->invincible_timer != INVALID_TIMER)
 				((TBL_PC*)tbl)->invincible_timer != INVALID_TIMER)
 		)) {	//Unlock current target.
 		)) {	//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.
 			mob_unlocktarget(md, tick-(battle_config.mob_ai&0x8?3000:0)); //Imediately do random walk.
 			tbl = NULL;
 			tbl = NULL;
 		}
 		}

+ 1 - 1
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_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_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_target(struct mob_data *md,struct block_list *bl,int dist);
 int mob_unlocktarget(struct mob_data *md,int tick);
 int mob_unlocktarget(struct mob_data *md,int tick);
 struct mob_data* mob_spawn_dataset(struct spawn_data *data);
 struct mob_data* mob_spawn_dataset(struct spawn_data *data);

+ 10 - 1
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.
 		if (!tbl || !status_check_visibility(bl, tbl)) {	//Cancel chase.
 			ud->to_x = bl->x;
 			ud->to_x = bl->x;
 			ud->to_y = bl->y;
 			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;
 			return 0;
 		}
 		}
 		if (tbl->m == bl->m && check_distance_bl(bl, tbl, ud->chaserange))
 		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)
 	if(src == NULL || src->prev == NULL || target==NULL || target->prev == NULL)
 		return 0;
 		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
 		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))
 	if(ud->skilltimer != -1 && !(sd && pc_checkskill(sd,SA_FREECAST) > 0))
 		return 0; // can't attack while casting
 		return 0; // can't attack while casting