Bläddra i källkod

- Multiple optimizations to the unit_data auto-chase upgrade, also simplified the mob and pet ai routines.
- Simplified the walk routines to half the number of timers required for walking.


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

skotlex 19 år sedan
förälder
incheckning
42c6f89d86
8 ändrade filer med 133 tillägg och 157 borttagningar
  1. 4 0
      Changelog-Trunk.txt
  2. 2 2
      src/map/battle.c
  3. 1 2
      src/map/map.h
  4. 18 23
      src/map/mob.c
  5. 9 17
      src/map/pet.c
  6. 2 2
      src/map/script.c
  7. 2 2
      src/map/skill.c
  8. 95 109
      src/map/unit.c

+ 4 - 0
Changelog-Trunk.txt

@@ -4,6 +4,10 @@ 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.
 
 2006/04/10
+	* Multiple optimizations to the unit_data auto-chase upgrade, also
+	  simplified the mob and pet ai routines. [Skotlex]
+	* Simplified the walk routines to half the number of timers required for
+	  walking. [Skotlex]
 	* Finished fixing the unit_data auto-chase update. Still need to do some
 	  optimizations... but the current code-base should be usable. [Skotlex]
 	* Fixes to the unit_data update that lets characters auto-chase while

+ 2 - 2
src/map/battle.c

@@ -69,7 +69,7 @@ static int battle_gettargeted_sub(struct block_list *bl, va_list ap)
 	ud = unit_bl2ud(bl);
 	if (!ud) return 0;
 
-	if (ud->attacktarget == target_id || ud->skilltarget == target_id) {
+	if (ud->target == target_id || ud->skilltarget == target_id) {
 		bl_list[(*c)++] = bl;
 		return 1;
 	}
@@ -96,7 +96,7 @@ int battle_gettarget(struct block_list *bl)
 	switch (bl->type)
 	{
 		case BL_PC:
-			return ((struct map_session_data*)bl)->ud.attacktarget;
+			return ((struct map_session_data*)bl)->ud.target;
 		case BL_MOB:
 			return ((struct mob_data*)bl)->target_id;
 		case BL_PET:

+ 1 - 2
src/map/map.h

@@ -357,9 +357,8 @@ struct unit_data {
 	short skillid,skilllv;
 	int   skilltarget;
 	int   skilltimer;
-	int   attacktarget;
+	int   target;
 	int   attacktimer;
-	int	walktarget;
 	int   walktimer;
 	int	chaserange;
 	unsigned int attackabletime;

+ 18 - 23
src/map/mob.c

@@ -935,8 +935,8 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
 		
 		if (ud) {
 			struct block_list *tbl=NULL;
-			if (ud->attacktarget && ud->attacktimer != -1)
-				tbl=map_id2bl(ud->attacktarget);
+			if (ud->target && ud->attacktimer != -1)
+				tbl=map_id2bl(ud->target);
 			else if (ud->skilltarget) {
 				tbl = map_id2bl(ud->skilltarget);
 				//Required check as skilltarget is not always an enemy. [Skotlex]
@@ -967,7 +967,6 @@ int mob_unlocktarget(struct mob_data *md,int tick)
 	md->state.skillstate=MSS_IDLE;
 	md->next_walktime=tick+rand()%3000+3000;
 	mob_stop_attack(md);
-	md->ud.attacktarget = md->ud.walktarget = 0;
 	return 0;
 }
 /*==========================================
@@ -1068,7 +1067,9 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
 	{	//Check validity of current target. [Skotlex]
 		tbl = map_id2bl(md->target_id);
 		if (!tbl || tbl->m != md->bl.m ||
-			(md->ud.attacktimer == -1 && !status_check_skilluse(&md->bl, tbl, 0, 0)) || (
+			(md->ud.attacktimer == -1 && !status_check_skilluse(&md->bl, tbl, 0, 0)) ||
+			(md->ud.walktimer != -1 && !check_distance_bl(&md->bl, tbl, md->min_chase)) ||
+			(
 				tbl->type == BL_PC && !(mode&MD_BOSS) &&
 				((struct map_session_data*)tbl)->state.gangsterparadise
 		)) {	//Unlock current target.
@@ -1137,9 +1138,6 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
 		md->attacked_id = 0;
 	}
 	
-	if (md->ud.attacktimer != -1 && tbl && md->ud.attacktarget == tbl->id)
-		return 0; //Already attacking the current target.
-
 	// Processing of slave monster, is it needed when there's a target to deal with?
 	if (md->master_id > 0 && !tbl)
 		mob_ai_sub_hard_slavemob(md, tick);
@@ -1167,47 +1165,48 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
 		if (tbl->type != BL_ITEM)
 		{	//Attempt to attack.
 			//At this point we know the target is attackable, we just gotta check if the range matches.
-
+			if (md->ud.target == tbl->id && md->ud.attacktimer != -1)
+				return 0; //Already locked.
+			
 			if (!battle_check_range (&md->bl, tbl, md->db->range))
 			{	//Out of range...
-				mob_stop_attack(md);
 				if (!(mode&MD_CANMOVE))
 				{	//Can't chase. Attempt to use a ranged skill at least?
 					mobskill_use(md, tick, MSC_LONGRANGEATTACKED);
 					mob_unlocktarget(md,tick);
 					return 0;
 				}
-				//Follow up
-				if (!mob_can_reach(md, tbl, md->min_chase, MSS_RUSH))
-				{	//Give up.
-					mob_unlocktarget(md,tick);
-					return 0;
-				}
 				md->state.skillstate = md->state.aggressive?MSS_FOLLOW:MSS_RUSH;
-				if (md->ud.walktimer != -1 && md->ud.walktarget == tbl->id &&
+				if (md->ud.walktimer != -1 && md->ud.target == tbl->id &&
 					(
 						!battle_config.mob_ai&1 ||
 						check_distance_blxy(tbl, md->ud.to_x, md->ud.to_y, md->db->range)
 				)) //Current target tile is still within attack range.
 					return 0;
-				//Target reachable. Locate suitable spot to move to.
-				unit_walktobl(&md->bl, tbl, md->db->range, 2|(!battle_config.mob_ai&1));
+
+				//Follow up
+				if (!mob_can_reach(md, tbl, md->min_chase, MSS_RUSH) ||
+					!unit_walktobl(&md->bl, tbl, md->db->range, 2|(!battle_config.mob_ai&1)))
+					//Give up.
+					mob_unlocktarget(md,tick);
 				return 0;
 			}
 			//Target within range, engage
-			mob_stop_walking(md,1);
 			md->state.skillstate = md->state.aggressive?MSS_ANGRY:MSS_BERSERK;
 			unit_attack(&md->bl,tbl->id,1);
 			return 0;
 		} else {	//Target is BL_ITEM, attempt loot.
 			struct flooritem_data *fitem;
 			int i;	
+			if (md->ud.target == tbl->id && md->ud.walktimer != -1)
+				return 0; //Already locked.
 			if (md->lootitem == NULL)
 			{	//Can't loot...
 				mob_unlocktarget (md, tick);
 				mob_stop_walking(md,0);
 				return 0;
 			}
+
 			if (!check_distance_bl(&md->bl, tbl, 1))
 			{	//Still not within loot range.
 				if (!(mode&MD_CANMOVE))
@@ -1218,9 +1217,6 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
 				if (!can_move)	// 動けない状態にある
 					return 0;
 				md->state.skillstate = MSS_LOOT;	// ルート時スキル使用
-				if (md->ud.walktimer != -1 && md->ud.walktarget == tbl->id)
-					//Already on the way to looting.
-					return 0;
 				if (!unit_walktobl(&md->bl, tbl, 0, 1))
 					mob_unlocktarget(md, tick); //Can't loot...
 				return 0;
@@ -1228,7 +1224,6 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
 			//Within looting range.
 			if (md->ud.attacktimer != -1)
 				return 0; //Busy attacking?
-			mob_stop_walking(md,0);
 
 			fitem = (struct flooritem_data *)tbl;
 			if (md->lootitem_count < LOOTITEM_SIZE) {

+ 9 - 17
src/map/pet.c

@@ -123,7 +123,7 @@ int pet_unlocktarget(struct pet_data *pd)
 
 	pd->target_id=0;
 	pet_stop_attack(pd);
-	pd->ud.attacktarget = pd->ud.walktarget = 0;
+	pet_stop_walking(pd,1);
 	return 0;
 }
 
@@ -960,7 +960,7 @@ static int pet_ai_sub_hard(struct pet_data *pd,unsigned int tick)
 		//Master too far, chase.
 		if(pd->target_id)
 			pet_unlocktarget(pd);
-		if(pd->ud.walktimer != -1 && pd->ud.walktarget == sd->bl.id)
+		if(pd->ud.walktimer != -1 && pd->ud.target == sd->bl.id)
 			return 0; //Already walking to him
 		
 		pd->speed = (sd->speed>>1);
@@ -1007,36 +1007,28 @@ static int pet_ai_sub_hard(struct pet_data *pd,unsigned int tick)
 		return 0;
 	}
 	
+	if(pd->ud.target == target->id &&
+		(pd->ud.attacktimer != -1 || pd->ud.walktimer != -1))
+		return 0; //Target already locked.
+
 	if (target->type != BL_ITEM) 
 	{ //enemy targetted
 		if(!battle_check_range(&pd->bl,target,pd->db->range))
 		{	//Chase
-			if(pd->ud.walktimer != -1 && check_distance_blxy(target, pd->ud.to_x,pd->ud.to_y, pd->db->range))
-				return 0;
-			
 			if(!unit_walktobl(&pd->bl, target, pd->db->range, 2))
-			{	//Unreachable target.
-				pet_unlocktarget(pd);
-			}
+				pet_unlocktarget(pd); //Unreachable target.
 			return 0;
-		}	//End Chase
-		pet_stop_walking(pd,1);
-		if (pd->ud.attacktimer != -1 && pd->ud.attacktarget == pd->target_id)
-			return 0;	//Already attacking.
+		}
 		//Continuous attack.
 		unit_attack(&pd->bl, pd->target_id, 1);
 	} else {	//Item Targeted, attempt loot
 		if (!check_distance_bl(&pd->bl, target, 1))
 		{	//Out of range
-			if(pd->ud.walktimer != -1 && pd->ud.walktarget == pd->target_id)
-				return 0;
-
 			if(!unit_walktobl(&pd->bl, target, 0, 1)) //Unreachable target.
 				pet_unlocktarget(pd);
 			return 0;
-		} else{	// アイテムまでたどり着いた
+		} else{
 			struct flooritem_data *fitem = (struct flooritem_data *)target;
-			pet_stop_walking(pd,1);
 			if(pd->loot->count < pd->loot->max){
 				memcpy(&pd->loot->item[pd->loot->count++],&fitem->item_data,sizeof(pd->loot->item[0]));
 				pd->loot->weight += itemdb_search(fitem->item_data.nameid)->weight*fitem->item_data.amount;

+ 2 - 2
src/map/script.c

@@ -10405,8 +10405,8 @@ int buildin_mobassist(struct script_state *st) {
 			ud = unit_bl2ud(bl);
 			md->master_id = bl->id;
 			if (ud) {
-				if (ud->attacktarget)
-					md->target_id = ud->attacktarget;
+				if (ud->target)
+					md->target_id = ud->target;
 				else if (ud->skilltarget)
 					md->target_id = ud->skilltarget;
 				md->min_chase = distance_bl(&md->bl,map_id2bl(md->target_id)) + md->db->range2;

+ 2 - 2
src/map/skill.c

@@ -3418,8 +3418,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 					if (!bl) bl = src;
 					unit_skilluse_id(src, bl->id, abra_skillid, abra_skilllv); 
 				} else {	//Assume offensive skills
-					if (ud->attacktarget)
-						target_id = ud->attacktarget;
+					if (ud->target)
+						target_id = ud->target;
 					else switch (src->type) {
 						case BL_MOB:
 							target_id = ((TBL_MOB*)src)->target_id;

+ 95 - 109
src/map/unit.c

@@ -57,7 +57,7 @@ int unit_walktoxy_sub(struct block_list *bl)
 
 	memcpy(&ud->walkpath,&wpd,sizeof(wpd));
 	
-	if (ud->walktarget && ud->chaserange >0) {
+	if (ud->target && ud->chaserange >0) {
 		//Trim the last part of the path to account for range.
 		for (i = ud->chaserange*10; i > 0 && ud->walkpath.path_len>0;) {
 			int dir;
@@ -72,8 +72,8 @@ int unit_walktoxy_sub(struct block_list *bl)
 		}
 		if (!ud->walkpath.path_len) {
 			//Already within requested range.
-			if (ud->attacktarget == ud->walktarget)
-				unit_attack(bl, ud->attacktarget, ud->state.attack_continue);
+			if (ud->target && ud->state.attack_continue)
+				unit_attack(bl, ud->target, 1);
 			return 0;
 		}
 	}
@@ -134,84 +134,80 @@ static int unit_walktoxy_timer(int tid,unsigned int tick,int id,int data)
 		sd->inchealspirithptick = 0;
 		sd->inchealspiritsptick = 0;
 	}
-	ud->walkpath.path_half ^= 1;
-	if(ud->walkpath.path_half==0){ // マス目中心へ到着
-		ud->walkpath.path_pos++;
-		if(ud->state.change_walk_target) {
-			unit_walktoxy_sub(bl);
-			return 0;
-		}
-	} else {
-		if(ud->walkpath.path[ud->walkpath.path_pos]>=8)
-			return 1;
-		x = bl->x;
-		y = bl->y;
+	
+	if(ud->walkpath.path[ud->walkpath.path_pos]>=8)
+		return 1;
+	x = bl->x;
+	y = bl->y;
 
-		dir = ud->walkpath.path[ud->walkpath.path_pos];
-		ud->dir = dir;
-		if (sd) 
-			sd->head_dir = dir;
+	dir = ud->walkpath.path[ud->walkpath.path_pos];
+	ud->dir = dir;
+	if (sd) 
+		sd->head_dir = dir;
 
-		dx = dirx[(int)dir];
-		dy = diry[(int)dir];
+	dx = dirx[(int)dir];
+	dy = diry[(int)dir];
 
-		if(map_getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS))
-			return unit_walktoxy_sub(bl);
-		
-		// バシリカ判定
+	if(map_getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS))
+		return unit_walktoxy_sub(bl);
+	
+	// バシリカ判定
 
-		map_foreachinmovearea(clif_outsight,bl->m,
-			x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,
-			dx,dy,sd?BL_ALL:BL_PC,bl);
+	map_foreachinmovearea(clif_outsight,bl->m,
+		x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,
+		dx,dy,sd?BL_ALL:BL_PC,bl);
 
-		x += dx;
-		y += dy;
-		map_moveblock(bl, x, y, tick);
+	x += dx;
+	y += dy;
+	map_moveblock(bl, x, y, tick);
 
-		ud->walktimer = 1;
-		map_foreachinmovearea(clif_insight,bl->m,
-			x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,
-			-dx,-dy,sd?BL_ALL:BL_PC,bl);
-		ud->walktimer = -1;
-		
-		if(sd) {
-			if(map_getcell(bl->m,x,y,CELL_CHKNPC)) {
-				npc_touch_areanpc(sd,bl->m,x,y);
-				if (bl->prev == NULL) //Script could have warped char, abort remaining of the function.
-					return 0;
-			} else
-				sd->areanpc_id=0;
-			if (sd->state.gmaster_flag)
-			{ //Guild Aura: Likely needs to be recoded, this method seems inefficient.
-				struct guild *g = sd->state.gmaster_flag;
-				int skill, guildflag = 0;
-				if ((skill = guild_checkskill(g, GD_LEADERSHIP)) > 0) guildflag |= skill<<12;
-				if ((skill = guild_checkskill(g, GD_GLORYWOUNDS)) > 0) guildflag |= skill<<8;
-				if ((skill = guild_checkskill(g, GD_SOULCOLD)) > 0) guildflag |= skill<<4;
-				if ((skill = guild_checkskill(g, GD_HAWKEYES)) > 0) guildflag |= skill;
-				if (guildflag)
-					map_foreachinrange(skill_guildaura_sub, bl,2, BL_PC,
-						bl->id, sd->status.guild_id, &guildflag);
-			}
-			if (
-				(sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR &&
-				sd->sc.data[SC_MIRACLE].timer==-1 &&
-				ud->walkpath.path_pos && ud->walkpath.path_pos%WALK_SKILL_INTERVAL == 0 &&
-				rand()%10000 < battle_config.sg_miracle_skill_ratio
-			) {	//SG_MIRACLE [Komurka]
-				clif_displaymessage(sd->fd,"[Miracle of the Sun, Moon and Stars]");
-				sc_start(&sd->bl,SC_MIRACLE,100,1,battle_config.sg_miracle_skill_duration);
-			}
-		} else if (md) {
-			if (ud->attacktarget) {
-				if(md->min_chase > md->db->range2) md->min_chase--;
-				if(ud->walkpath.path_pos && ud->walkpath.path_pos%WALK_SKILL_INTERVAL == 0 &&
-					mobskill_use(md, tick, -1))
-					return 0;
-			}
+	ud->walktimer = 1;
+	map_foreachinmovearea(clif_insight,bl->m,
+		x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,
+		-dx,-dy,sd?BL_ALL:BL_PC,bl);
+	ud->walktimer = -1;
+	
+	if(sd) {
+		if(map_getcell(bl->m,x,y,CELL_CHKNPC)) {
+			npc_touch_areanpc(sd,bl->m,x,y);
+			if (bl->prev == NULL) //Script could have warped char, abort remaining of the function.
+				return 0;
+		} else
+			sd->areanpc_id=0;
+		if (sd->state.gmaster_flag)
+		{ //Guild Aura: Likely needs to be recoded, this method seems inefficient.
+			struct guild *g = sd->state.gmaster_flag;
+			int skill, guildflag = 0;
+			if ((skill = guild_checkskill(g, GD_LEADERSHIP)) > 0) guildflag |= skill<<12;
+			if ((skill = guild_checkskill(g, GD_GLORYWOUNDS)) > 0) guildflag |= skill<<8;
+			if ((skill = guild_checkskill(g, GD_SOULCOLD)) > 0) guildflag |= skill<<4;
+			if ((skill = guild_checkskill(g, GD_HAWKEYES)) > 0) guildflag |= skill;
+			if (guildflag)
+				map_foreachinrange(skill_guildaura_sub, bl,2, BL_PC,
+					bl->id, sd->status.guild_id, &guildflag);
+		}
+		if (
+			(sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR &&
+			sd->sc.data[SC_MIRACLE].timer==-1 &&
+			ud->walkpath.path_pos && ud->walkpath.path_pos%WALK_SKILL_INTERVAL == 0 &&
+			rand()%10000 < battle_config.sg_miracle_skill_ratio
+		) {	//SG_MIRACLE [Komurka]
+			clif_displaymessage(sd->fd,"[Miracle of the Sun, Moon and Stars]");
+			sc_start(&sd->bl,SC_MIRACLE,100,1,battle_config.sg_miracle_skill_duration);
+		}
+	} else if (md) {
+		if (ud->target && ud->state.attack_continue) {
+			if(md->min_chase > md->db->range2) md->min_chase--;
+			if(ud->walkpath.path_pos && ud->walkpath.path_pos%WALK_SKILL_INTERVAL == 0 &&
+				mobskill_use(md, tick, -1))
+				return 0;
 		}
 	}
 
+	if(ud->state.change_walk_target)
+		return unit_walktoxy_sub(bl);
+
+	ud->walkpath.path_pos++;
 	if(ud->walkpath.path_pos>=ud->walkpath.path_len)
 		i = -1;
 	else if(ud->walkpath.path[ud->walkpath.path_pos]&1)
@@ -219,16 +215,13 @@ static int unit_walktoxy_timer(int tid,unsigned int tick,int id,int data)
 	else
 		i = status_get_speed(bl);
 
-	if(i > 0) {
-		i = i>>1;
-//		if(i < 1 && ud->walkpath.path_half == 0)
-//			i = 1;
+	if(i > 0)
 		ud->walktimer = add_timer(tick+i,unit_walktoxy_timer,id,ud->walkpath.path_pos);
-	} else if(sd && sd->sc.count && sd->sc.data[SC_RUN].timer!=-1) //Keep trying to run.
+	else if(sd && sd->sc.count && sd->sc.data[SC_RUN].timer!=-1) //Keep trying to run.
 		pc_run(sd, sd->sc.data[SC_RUN].val1, sd->sc.data[SC_RUN].val2);
-	else if (ud->walktarget) {
+	else if (ud->target) {
 		//Update target trajectory.
-		struct block_list *tbl = map_id2bl(ud->walktarget);
+		struct block_list *tbl = map_id2bl(ud->target);
 		if (!tbl) {	//Cancel chase.
 			ud->to_x = bl->x;
 			ud->to_y = bl->y;
@@ -236,10 +229,10 @@ static int unit_walktoxy_timer(int tid,unsigned int tick,int id,int data)
 		}
 		if (tbl->m == bl->m && check_distance_bl(bl, tbl, ud->chaserange))
 		{	//Reached destination.
-			if (ud->attacktarget == tbl->id)
+			if (ud->state.attack_continue)
 				unit_attack(bl, tbl->id, ud->state.attack_continue);
 		} else { //Update chase-path
-			unit_walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy);
+			unit_walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy|(ud->state.attack_continue?2:0));
 			return 0;
 		}
 	} else {	//Stopped walking. Update to_x and to_y to current location [Skotlex]
@@ -266,7 +259,7 @@ int unit_walktoxy( struct block_list *bl, int x, int y, int easy) {
 		return 0;
 
 	ud->state.walk_easy = easy;
-	ud->walktarget	= 0;
+	ud->target = 0;
 	ud->to_x = x;
 	ud->to_y = y;
 	
@@ -289,7 +282,7 @@ static int unit_walktobl_sub(int tid,unsigned int tick,int id,int data)
 	struct block_list *bl = map_id2bl(id);
 	struct unit_data *ud = bl?unit_bl2ud(bl):NULL;
 
-	if (ud && ud->walktimer == -1 && ud->walktarget == data)
+	if (ud && ud->walktimer == -1 && ud->target == data)
 	{
 		if (DIFF_TICK(ud->canmove_tick, tick) > 0) //Keep waiting?
 			add_timer(ud->canmove_tick+1, unit_walktobl_sub, id, data);
@@ -300,7 +293,7 @@ static int unit_walktobl_sub(int tid,unsigned int tick,int id,int data)
 }
 
 // Chases a tbl. If the flag&1, use hard-path seek,
-// if flag&2, start attacking upon arrival within range.
+// if flag&2, start attacking upon arrival within range, otherwise just walk to that character.
 int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int flag) {
 	struct unit_data        *ud = NULL;
 	struct status_change		*sc = NULL;
@@ -320,17 +313,14 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
 	}
 
 	ud->state.walk_easy = flag&1;
-	ud->walktarget	= tbl->id;
+	ud->target = tbl->id;
 	ud->chaserange = range;
+	ud->state.attack_continue = flag&2?1:0; //Chase to attack.
 
 	sc = status_get_sc(bl);
 	if (sc && sc->count && sc->data[SC_CONFUSION].timer != -1) //Randomize the target position
 		map_random_dir(bl, &ud->to_x, &ud->to_y);
 
-	if (flag&2) { //Chase to attack.
-		ud->attacktarget = tbl->id;
-		ud->state.attack_continue = 1;
-	}
 	
 	if(ud->walktimer != -1) {
 		ud->state.change_walk_target = 1;
@@ -338,7 +328,7 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
 	}
 	if (DIFF_TICK(ud->canmove_tick, gettick()) > 0)
 	{	//Can't move, wait a bit before invoking the movement.
-		add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->walktarget);
+		add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->target);
 		return 1;
 	} else if (!unit_can_move(bl))
 		return 0;
@@ -651,8 +641,8 @@ int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int
 		delete_timer(ud->walktimer, unit_walktoxy_timer);
 		ud->walktimer = -1;
 		clif_fixpos(bl);
-		if(ud->walktarget)
-			add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->walktarget);
+		if(ud->target)
+			add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->target);
 	}
 	return 1;
 }
@@ -722,8 +712,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, int skill_num, int
 	temp = (target_id == src->id && !(sd && sd->state.skill_flag)
 		&& skill_get_inf(skill_num)&INF_SELF_SKILL
 		&& skill_get_inf2(skill_num)&INF2_NO_TARGET_SELF);
-	if (temp)	
-		target_id = ud->attacktarget; //Auto-select skills. [Skotlex]
+	if (temp)
+		target_id = ud->target; //Auto-select skills. [Skotlex]
 
 	if (sd) {
 		//Target_id checking.
@@ -1064,8 +1054,8 @@ int unit_stop_attack(struct block_list *bl)
 int unit_unattackable(struct block_list *bl) {
 	struct unit_data *ud = unit_bl2ud(bl);
 	if (ud) {
-		ud->attacktarget = 0;
-		ud->walktarget = 0;
+		ud->target = 0;
+		ud->state.attack_continue = 0;
 	}
 	
 	if(bl->type == BL_MOB)
@@ -1106,12 +1096,10 @@ int unit_attack(struct block_list *src,int target_id,int type)
 		return 1;
 	}
 
-	ud->attacktarget = target_id;
+	ud->target = target_id;
 	ud->state.attack_continue = type;
-	if (type) {	//If you re to attack continously, set to auto-case character
-		ud->walktarget = target_id;
+	if (type) //If you re to attack continously, set to auto-case character
 		ud->chaserange = status_get_range(src);
-	}
 	
 	//Just change target/type. [Skotlex]
 	if(ud->attacktimer != -1)
@@ -1222,7 +1210,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
 	BL_CAST( BL_PC , src, sd);
 	BL_CAST( BL_MOB, src, md);
 	ud->attacktimer=-1;
-	target=map_id2bl(ud->attacktarget);
+	target=map_id2bl(ud->target);
 
 	if(src->prev == NULL || target==NULL || target->prev == NULL)
 		return 0;
@@ -1252,26 +1240,24 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
 
 	range = status_get_range(src);
 	
-	if(ud->walktimer != -1) range++; //Extra range when walking.
 	if(!sd || sd->status.weapon != 11) range++; //Dunno why everyone but bows gets this extra range...
 	if(unit_is_walking(target)) range++; //Extra range when chasing
 
 	if(!check_distance_bl(src,target,range) ) {
 		//Chase if required.
-		if(ud->state.attack_continue && ud->walktarget == target->id) {
+		if(ud->state.attack_continue) {
 			if(sd)
 				clif_movetoattack(sd,target);
 			else
-				unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy);
+				unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy|2);
 		}
 		return 1;
 	}
 	if(!battle_check_range(src,target,range)) {
 	  	//Within range, but no direct line of attack
-		if(ud->state.attack_continue && ud->walktarget == target->id) {
+		if(ud->state.attack_continue) {
 			if(ud->chaserange > 2) ud->chaserange-=2;
-			unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy);
-			ud->attacktimer = add_timer(tick + status_get_adelay(src),unit_attack_timer,src->id,0);
+			unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy|2);
 		}
 		return 1;
 	}
@@ -1422,7 +1408,7 @@ static int unit_counttargeted_sub(struct block_list *bl, va_list ap)
 
 	ud = unit_bl2ud(bl);
 
-	if (ud && ud->attacktarget == id && ud->attacktimer != -1 && ud->attacktarget_lv >= target_lv)
+	if (ud && ud->target == id && ud->attacktimer != -1 && ud->attacktarget_lv >= target_lv)
 		return 1;
 
 	return 0;	
@@ -1463,7 +1449,7 @@ int unit_counttargeted(struct block_list *bl,int target_lv)
 int unit_mobstopattacked(struct map_session_data *sd,va_list ap)
 {
 	int id=va_arg(ap,int);
-	if(sd->ud.attacktarget==id)
+	if(sd->ud.target==id)
 		unit_stop_attack(&sd->bl);
 	return 0;
 }