Просмотр исходного кода

- Some cleanup on mob_can_reach code to prevent unnecessary path-searching
- Optimized the path-searching ai for mobs to try target cells around the target in order rather than randomly picked cells.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@5434 54d463be-8e91-2dee-dedb-b68131a5f0ec

skotlex 19 лет назад
Родитель
Сommit
65dfdfc978
4 измененных файлов с 60 добавлено и 43 удалено
  1. 4 0
      Changelog-Trunk.txt
  2. 55 42
      src/map/mob.c
  3. 0 1
      src/map/skill.c
  4. 1 0
      src/map/skill.h

+ 4 - 0
Changelog-Trunk.txt

@@ -5,6 +5,10 @@ IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.  EV
 GOES INTO TRUNK AND WILL BE MERGED INTO STABLE BY VALARIS AND WIZPUTER. -- VALARIS
 
 2006/03/02
+	* Some cleanup on mob_can_reach code to prevent unnecessary path-searching
+	  [Skotlex]
+	* Optimized the path-searching ai for mobs to try target cells around the
+	  target in order rather than randomly picked cells. [Skotlex]
 	* Applied Snufkin's patch to fix compilation on FreeBSD. [Skotlex]
 	* Fixed mobs targetting themselves after using a support skill. [Skotlex]
 	* Gospel no longer blocks item usage of whoever is in the area of effect,

+ 55 - 42
src/map/mob.c

@@ -622,16 +622,22 @@ int mob_can_reach(struct mob_data *md,struct block_list *bl,int range, int state
 		return 1;
 
 	// It judges whether it can adjoin or not.
-	dx=abs(bl->x - md->bl.x);
-	dy=abs(bl->y - md->bl.y);
+	dx=bl->x - md->bl.x;
+	dy=bl->y - md->bl.y;
 	dx=(dx>0)?1:((dx<0)?-1:0);
 	dy=(dy>0)?1:((dy<0)?-1:0);
+	if (map_getcell(md->bl.m,bl->x+dx,bl->y+dy,CELL_CHKNOREACH))
+	{	//Look for a suitable cell to place in.
+		for(i=0;i<9 && map_getcell(md->bl.m,bl->x-1+i/3,bl->y-1+i%3,CELL_CHKNOREACH);i++);
+		if (i<9) {
+			dx = 1-i/3;
+			dy = 1-i%3;
+		}
+	}
+	
 	if(path_search_real(&wpd,md->bl.m,md->bl.x,md->bl.y,bl->x-dx,bl->y-dy,easy,CELL_CHKNOREACH)!=-1)
 		return 1;
-	for(i=0;i<9;i++){
-		if(path_search_real(&wpd,md->bl.m,md->bl.x,md->bl.y,bl->x-1+i/3,bl->y-1+i%3,easy, CELL_CHKNOREACH)!=-1)
-			return 1;
-	}
+		
 	return 0;
 }
 
@@ -1563,7 +1569,7 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
 	struct mob_data *md;
 	struct block_list *tbl = NULL, *abl = NULL;
 	unsigned int tick;
-	int i, dx, dy, dist;
+	int i, j, dx, dy, dist;
 	int attack_type = 0;
 	int mode;
 	int search_size = AREA_SIZE*2;
@@ -1747,51 +1753,58 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
 					return 0;
 				}
 				//Target reachable. Locate suitable spot to move to.
-				i = 0;
+				i = j = 0;
 				dx = tbl->x - md->bl.x;
 				dy = tbl->y - md->bl.y;
-				if (dx < 0) dx++;
-				else if (dx > 0) dx--;
-				if (dy < 0) dy++;
-				else if (dy > 0) dy--;
+				if (dx < 0) dx=-1;
+				else if (dx > 0) dx=1;
+				if (dy < 0) dy=-1;
+				else if (dy > 0) dy=1;
+				if(mob_walktoxy(md, tbl->x -dx, tbl->y -dy, 0)) {
+					j = (dy+1) + 3*(dx+1);
+					for (i = j+1; i%9 != j; i++) {
+						dx = -1+(i%9)/3;
+						dy = -1+(i%3);
+#ifdef CELL_NOSTACK
+						if (map_getcell(md->bl.m,  tbl->x-dx, tbl->y-dy, CELL_CHKSTACK))
+							continue;
+#endif
+						if (!mob_walktoxy(md, tbl->x-dx, tbl->y-dy, 0))
+							break;
+					}
 #ifdef CELL_NOSTACK
-				while (mob_walktoxy(md, md->bl.x + dx, md->bl.y + dy, 0))
-				{	//Attempt to chase to nearby blocks
-					do {
-						if (i < 5) {
-							dx = tbl->x - md->bl.x + rand()%3 - 1;
-							dy = tbl->y - md->bl.y + rand()%3 - 1;
-						} else { //Try some more...
-							dx = tbl->x - md->bl.x + rand()%5 - 2;
-							dy = tbl->y - md->bl.y + rand()%5 - 2;
+					if (i%9 == j) 
+					{ //All adjacent cells are taken. Try roaming around on 5x5
+						for (i = j+1; i%9 != j; i++) {
+							dx = 2*(-1+(i%9)/3);
+							dy = 2*(-1+(i%3));
+							if (map_getcell(md->bl.m,  tbl->x-dx, tbl->y-dy, CELL_CHKSTACK))
+								continue;
+							if (!mob_walktoxy(md, tbl->x-dx, tbl->y-dy, 0)) {
+								md->next_walktime = tick + 1000;
+								break;
+							}
 						}
-						i++;
-					} while (i < 15 && map_getcell(md->bl.m,  md->bl.x+dx, md->bl.y+dy, CELL_CHKSTACK));
-					if (i >= 15) {
+					}
+					if (i%9 == j)
+				  	{
 						//On stacked mode, it is much more likely that you just can't reach the target. So unlock it
 						mob_unlocktarget(md, tick);
-						//Make it give up for 1 second to avoid unnecessary server load in case the target is already mobbed to death.
-						mob_changestate(md,MS_DELAY,1000);
+						md->next_walktime = tick + 1000;
 						return 0;
 					}
-				}
 #else
-				while (i < 5 && mob_walktoxy(md, md->bl.x + dx, md->bl.y + dy, 0))
-				{	//Attempt to chase to nearby blocks
-					dx = tbl->x - md->bl.x + rand()%3 - 1;
-					dy = tbl->y - md->bl.y + rand()%3 - 1;
-					i++;
-				}
-				if (i==5)
-				{	//Failed? Try going away from the target before retrying.
-					if (dx < 0) dx = 2;
-					else if (dx > 0) dx = -2;
-					if (dy < 0) dy = 2;
-					else if (dy > 0) dy = -2;
-				}
+					if (i%9 == j)
+					{	//Failed? Try going away from the target before retrying.
+						if (dx < 0) dx = 2;
+						else if (dx > 0) dx = -2;
+						if (dy < 0) dy = 2;
+						else if (dy > 0) dy = -2;
+						mob_walktoxy (md, tbl->x+dx, tbl->y+dy, 0);
+						md->next_walktime = tick + 500;
+					}
 #endif
-				md->next_walktime = tick + 500;
-				mob_walktoxy (md, md->bl.x+dx, md->bl.y+dy, 0);
+				}
 				return 0;
 			}
 			//Target within range, engage

+ 0 - 1
src/map/skill.c

@@ -637,7 +637,6 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 int skill_frostjoke_scream(struct block_list *bl,va_list ap);
 int status_change_timer_sub(struct block_list *bl, va_list ap);
 int skill_attack_area(struct block_list *bl,va_list ap);
-int skill_clear_element_field(struct block_list *bl);
 struct skill_unit_group *skill_locate_element_field(struct block_list *bl); // [Skotlex]
 int skill_graffitiremover(struct block_list *bl, va_list ap); // [Valaris]
 int skill_greed(struct block_list *bl, va_list ap);

+ 1 - 0
src/map/skill.h

@@ -187,6 +187,7 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src,
 	int count,int skillid,int skilllv,int unit_id);
 int skill_delunitgroup(struct skill_unit_group *group);
 int skill_clear_unitgroup(struct block_list *src);
+int skill_clear_element_field(struct block_list *bl);
 
 int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl,
 	int damage,unsigned int tick);