Bläddra i källkod

Monster random walk code optimized (fixes #208)
* Monsters will now always find a cell to walk to on first attempt as long as there is at least one cell available
* Performance for searching a cell improved, a monster no longer tries the same cell twice
* Removed the "MOB can't move" warning by default; the warning could appear with legit behavior like using Icewall and actually made the monster re-spawn
* Added a config option to monster.conf, where you can re-enable the warning and the re-spawning again

Playtester 9 år sedan
förälder
incheckning
78419baa76
4 ändrade filer med 30 tillägg och 18 borttagningar
  1. 4 0
      conf/battle/monster.conf
  2. 1 0
      src/map/battle.c
  3. 1 0
      src/map/battle.h
  4. 24 18
      src/map/mob.c

+ 4 - 0
conf/battle/monster.conf

@@ -251,3 +251,7 @@ boss_icewall_walk_block: 0
 // 2012-04-04aRagexeRE or higher client required.
 monster_hp_bars_info: yes
 
+// Should a monster respawn and a warning printed to the map server when a monster couldn't move for a long time?
+// This can be legit gameplay (e.g. players keeping an MVP stuck inside icewall), but if you want to prevent any
+// exploits and be notified about them, you can set this to yes.
+monster_stuck_warning: no

+ 1 - 0
src/map/battle.c

@@ -8195,6 +8195,7 @@ static const struct _battle_data {
 	{ "max_body_style",                     &battle_config.max_body_style,                  4,      0,      SHRT_MAX,       },
 	{ "save_body_style",                    &battle_config.save_body_style,                 0,      0,      1,              },
 	{ "monster_eye_range_bonus",            &battle_config.mob_eye_range_bonus,             0,      0,      10,             },
+	{ "monster_stuck_warning",              &battle_config.mob_stuck_warning,               0,      0,      1,              },
 };
 
 #ifndef STATS_OPT_OUT

+ 1 - 0
src/map/battle.h

@@ -601,6 +601,7 @@ extern struct Battle_Config
 	int max_body_style;
 	int save_body_style;
 	int mob_eye_range_bonus; //Vulture's Eye and Snake's Eye range bonus
+	int mob_stuck_warning; //Show warning if a monster is stuck too long
 } battle_config;
 
 void do_init_battle(void);

+ 24 - 18
src/map/mob.c

@@ -1385,8 +1385,8 @@ int mob_unlocktarget(struct mob_data *md, unsigned int tick)
  *------------------------------------------*/
 int mob_randomwalk(struct mob_data *md,unsigned int tick)
 {
-	const int retrycount=20;
-	int i,c,d;
+	const int d=7;
+	int i,c,r,dx,dy;
 	int speed;
 
 	nullpo_ret(md);
@@ -1397,26 +1397,32 @@ int mob_randomwalk(struct mob_data *md,unsigned int tick)
 	   !(status_get_mode(&md->bl)&MD_CANMOVE))
 		return 0;
 
-	d =12-md->move_fail_count;
-	if(d<5) d=5;
-	if(d>7) d=7;
-	for(i=0;i<retrycount;i++){	// Search of a movable place
-		int r=rnd();
-		int x=r%(d*2+1)-d;
-		int y=r/(d*2+1)%(d*2+1)-d;
-		x+=md->bl.x;
-		y+=md->bl.y;
-
+	r=rnd();
+	dx=r%(d*2+1)-d;
+	dy=r/(d*2+1)%(d*2+1)-d;
+	for(i=0;i<d*d;i++){	// Search of a movable place
+		int x = dx + md->bl.x;
+		int y = dy + md->bl.y;
 		if(((x != md->bl.x) || (y != md->bl.y)) && map_getcell(md->bl.m,x,y,CELL_CHKPASS) && unit_walktoxy(&md->bl,x,y,8)){
 			break;
 		}
+		// Could not move to cell, try the next one
+		if (++dx>d) {
+			dx=-d;
+			if (++dy>d) {
+				dy=-d;
+			}
+		}
 	}
-	if(i==retrycount){
-		md->move_fail_count++;
-		if(md->move_fail_count>1000){
-			ShowWarning("MOB can't move. random spawn %d, class = %d, at %s (%d,%d)\n",md->bl.id,md->mob_id,map[md->bl.m].name, md->bl.x, md->bl.y);
-			md->move_fail_count=0;
-			mob_spawn(md);
+	if(i==d*d){
+		// None of the available cells worked, try again next interval
+		if(battle_config.mob_stuck_warning) {
+			md->move_fail_count++;
+			if(md->move_fail_count>1000){
+				ShowWarning("MOB can't move. random spawn %d, class = %d, at %s (%d,%d)\n",md->bl.id,md->mob_id,map[md->bl.m].name, md->bl.x, md->bl.y);
+				md->move_fail_count=0;
+				mob_spawn(md);
+			}
 		}
 		return 0;
 	}