Explorar o código

- Fixed a bunch of invalid memory access bugs as reported by Valgrind.
- Updated unit_stop_walking to not move character an extra cell when it is already half-way there unless flag 0x4 is passed. (bugreport:3078)
- Fixed the monster MD_CASTSENSOR code not correctly setting the monster's aggressive state.
- Corrected a few compiler warnings
- Changed a bit the code for SC_BOSSMAPINFO so it is not so hideously ugly.



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

skotlex %!s(int64=16) %!d(string=hai) anos
pai
achega
418f0d9200
Modificáronse 13 ficheiros con 58 adicións e 70 borrados
  1. 1 1
      src/map/atcommand.c
  2. 3 4
      src/map/clif.c
  3. 1 1
      src/map/guild.c
  4. 2 2
      src/map/map.c
  5. 5 2
      src/map/mob.c
  6. 1 1
      src/map/mob.h
  7. 1 1
      src/map/npc.c
  8. 1 1
      src/map/pc.c
  9. 4 2
      src/map/script.c
  10. 5 3
      src/map/skill.c
  11. 13 24
      src/map/status.c
  12. 2 2
      src/map/storage.c
  13. 19 26
      src/map/unit.c

+ 1 - 1
src/map/atcommand.c

@@ -9176,7 +9176,7 @@ void do_final_atcommand()
 int atcommand_commands(const int fd, struct map_session_data* sd, const char* command, const char* message)
 int atcommand_commands(const int fd, struct map_session_data* sd, const char* command, const char* message)
 {
 {
 	char line_buff[CHATBOX_SIZE];
 	char line_buff[CHATBOX_SIZE];
-	int i, gm_lvl = pc_isGM(sd), count = 0, count2 = 0;
+	int i, gm_lvl = pc_isGM(sd), count = 0;
 	char* cur = line_buff;
 	char* cur = line_buff;
 
 
 	memset(line_buff,' ',CHATBOX_SIZE);
 	memset(line_buff,' ',CHATBOX_SIZE);

+ 3 - 4
src/map/clif.c

@@ -9707,7 +9707,7 @@ void clif_parse_ProduceMix(int fd,struct map_session_data *sd)
  *------------------------------------------*/
  *------------------------------------------*/
 void clif_parse_Cooking(int fd,struct map_session_data *sd)
 void clif_parse_Cooking(int fd,struct map_session_data *sd)
 {
 {
-	int type = RFIFOW(fd,2); // '1' for cooking
+	//int type = RFIFOW(fd,2); // '1' for cooking, but what do other values mean?
 	int nameid = RFIFOW(fd,4);
 	int nameid = RFIFOW(fd,4);
 
 
 	if (pc_istrading(sd)) {
 	if (pc_istrading(sd)) {
@@ -11605,7 +11605,6 @@ void clif_parse_HomAttack(int fd,struct map_session_data *sd)
 		bl = &sd->md->bl;
 		bl = &sd->md->bl;
 	else return;
 	else return;
 
 
-	unit_stop_walking(bl, 1);
 	unit_stop_attack(bl);
 	unit_stop_attack(bl);
 	unit_attack(bl, target_id, action_type != 0);
 	unit_attack(bl, target_id, action_type != 0);
 }
 }
@@ -12494,7 +12493,7 @@ void clif_bossmapinfo(int fd, struct mob_data *md, short flag)
 			else
 			else
 				WFIFOB(fd,2) = 2; // First Time
 				WFIFOB(fd,2) = 2; // First Time
 		}
 		}
-		else
+		else if (md->spawn_timer != -1)
 		{ // Boss is Dead
 		{ // Boss is Dead
 			const struct TimerData * timer_data = get_timer(md->spawn_timer);
 			const struct TimerData * timer_data = get_timer(md->spawn_timer);
 			unsigned int seconds;
 			unsigned int seconds;
@@ -13311,7 +13310,7 @@ static int packetdb_readdb(void)
 	    0,  0,  0,  0,  8,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	    0,  0,  0,  0,  8,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	//#0x0280
 	//#0x0280
 	    0,  0,  0,  6,  0,  0,  0,  0,  0,  8, 18,  0,  0,  0,  0,  0,
 	    0,  0,  0,  6,  0,  0,  0,  0,  0,  8, 18,  0,  0,  0,  0,  0,
-	    0,  4,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	    0,  4,  0, 70,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	    0,  0,  0,  0,  0,  0,  0,  0,  0,191,  0,  0,  0,  0,  0,  0,
 	    0,  0,  0,  0,  0,  0,  0,  0,  0,191,  0,  0,  0,  0,  0,  0,
 	//#0x02C0
 	//#0x02C0

+ 1 - 1
src/map/guild.c

@@ -1730,7 +1730,7 @@ int guild_addcastleinfoevent(int castle_id,int index,const char *name)
 		return 0;
 		return 0;
 
 
 	ev = (struct eventlist *)aMalloc(sizeof(struct eventlist));
 	ev = (struct eventlist *)aMalloc(sizeof(struct eventlist));
-	memcpy(ev->name,name,sizeof(ev->name));
+	strncpy(ev->name,name,ARRAYLENGTH(ev->name));
 	//The next event becomes whatever was currently stored.
 	//The next event becomes whatever was currently stored.
 	ev->next = (struct eventlist *)idb_put(guild_castleinfoevent_db,code,ev);
 	ev->next = (struct eventlist *)idb_put(guild_castleinfoevent_db,code,ev);
 	return 0;
 	return 0;

+ 2 - 2
src/map/map.c

@@ -1459,10 +1459,10 @@ void map_addiddb(struct block_list *bl)
 	}
 	}
 	else if( bl->type == BL_MOB )
 	else if( bl->type == BL_MOB )
 	{
 	{
-		struct mob_data* md = BL_CAST(BL_MOB, bl);
+		TBL_MOB* md = (TBL_MOB*)bl;
 		idb_put(mobid_db,bl->id,bl);
 		idb_put(mobid_db,bl->id,bl);
 
 
-		if( md && (md->db->status.mode&MD_BOSS) && md->db->mexp > 0 )
+		if( (md->db->status.mode&MD_BOSS) && md->db->mexp > 0 )
 			idb_put(bossid_db, bl->id, bl);
 			idb_put(bossid_db, bl->id, bl);
 	}
 	}
 
 

+ 5 - 2
src/map/mob.c

@@ -3281,12 +3281,16 @@ int mob_clone_spawn(struct map_session_data *sd, int m, int x, int y, const char
 	return md->bl.id;
 	return md->bl.id;
 }
 }
 
 
-int mob_clone_delete(int class_)
+int mob_clone_delete(struct mob_data *md)
 {
 {
+	const int class_ = md->class_;
 	if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END
 	if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END
 		&& mob_db_data[class_]!=NULL) {
 		&& mob_db_data[class_]!=NULL) {
 		aFree(mob_db_data[class_]);
 		aFree(mob_db_data[class_]);
 		mob_db_data[class_]=NULL;
 		mob_db_data[class_]=NULL;
+		//Clear references to the db
+		md->db = NULL;
+		md->vd = NULL;
 		return 1;
 		return 1;
 	}
 	}
 	return 0;
 	return 0;
@@ -4134,7 +4138,6 @@ static int mob_readskilldb(void)
 		while(fgets(line, sizeof(line), fp))
 		while(fgets(line, sizeof(line), fp))
 		{
 		{
 			char *str[20], *p, *np;
 			char *str[20], *p, *np;
-			int j=0;
 
 
 			lines++;
 			lines++;
 			if(line[0] == '/' && line[1] == '/')
 			if(line[0] == '/' && line[1] == '/')

+ 1 - 1
src/map/mob.h

@@ -254,7 +254,7 @@ int mob_countslave(struct block_list *bl);
 int mob_is_clone(int class_);
 int mob_is_clone(int class_);
 
 
 int mob_clone_spawn(struct map_session_data *sd, int m, int x, int y, const char *event, int master_id, int mode, int flag, unsigned int duration);
 int mob_clone_spawn(struct map_session_data *sd, int m, int x, int y, const char *event, int master_id, int mode, int flag, unsigned int duration);
-int mob_clone_delete(int class_);
+int mob_clone_delete(struct mob_data *md);
 
 
 void mob_reload(void);
 void mob_reload(void);
 
 

+ 1 - 1
src/map/npc.c

@@ -666,7 +666,7 @@ int npc_settimerevent_tick(struct npc_data* nd, int newtimer)
 {
 {
 	bool flag;
 	bool flag;
 	int old_rid;
 	int old_rid;
-	struct map_session_data *sd = NULL;
+	//struct map_session_data *sd = NULL;
 
 
 	nullpo_retr(0, nd);
 	nullpo_retr(0, nd);
 
 

+ 1 - 1
src/map/pc.c

@@ -5206,7 +5206,7 @@ int pc_resethate(struct map_session_data* sd)
 int pc_skillatk_bonus(struct map_session_data *sd, int skill_num)
 int pc_skillatk_bonus(struct map_session_data *sd, int skill_num)
 {
 {
 	int i, bonus = 0;
 	int i, bonus = 0;
-	ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id && sd->skillatk[i].id == skill_num);
+	ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, !sd->skillatk[i].id || sd->skillatk[i].id == skill_num);
 	if( i < ARRAYLENGTH(sd->skillatk) && sd->skillatk[i].id )
 	if( i < ARRAYLENGTH(sd->skillatk) && sd->skillatk[i].id )
 		bonus = sd->skillatk[i].val;
 		bonus = sd->skillatk[i].val;
 	if( sd->sc.data[SC_SKILLATKBONUS] )
 	if( sd->sc.data[SC_SKILLATKBONUS] )

+ 4 - 2
src/map/script.c

@@ -7519,7 +7519,9 @@ BUILDIN_FUNC(killmonster)
 		}
 		}
 	}
 	}
 	
 	
+	map_freeblock_lock();
 	map_foreachinmap(buildin_killmonster_sub_strip, m, BL_MOB, event ,allflag);
 	map_foreachinmap(buildin_killmonster_sub_strip, m, BL_MOB, event ,allflag);
+	map_freeblock_unlock();
 	return 0;
 	return 0;
 }
 }
 
 
@@ -11160,7 +11162,7 @@ BUILDIN_FUNC(npcstop)
 	struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
 	struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
 
 
 	if(nd) {
 	if(nd) {
-		unit_stop_walking(&nd->bl,1);
+		unit_stop_walking(&nd->bl,5);
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -12738,7 +12740,7 @@ BUILDIN_FUNC(unitstop)
 	if( bl != NULL )
 	if( bl != NULL )
 	{
 	{
 		unit_stop_attack(bl);
 		unit_stop_attack(bl);
-		unit_stop_walking(bl,0);
+		unit_stop_walking(bl,4);
 		if( bl->type == BL_MOB )
 		if( bl->type == BL_MOB )
 			((TBL_MOB*)bl)->target_id = 0;
 			((TBL_MOB*)bl)->target_id = 0;
 	}
 	}

+ 5 - 3
src/map/skill.c

@@ -5904,7 +5904,8 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr data)
 		if(battle_config.skill_log && battle_config.skill_log&src->type)
 		if(battle_config.skill_log && battle_config.skill_log&src->type)
 			ShowInfo("Type %d, ID %d skill castend pos [id =%d, lv=%d, (%d,%d)]\n",
 			ShowInfo("Type %d, ID %d skill castend pos [id =%d, lv=%d, (%d,%d)]\n",
 				src->type, src->id, ud->skillid, ud->skilllv, ud->skillx, ud->skilly);
 				src->type, src->id, ud->skillid, ud->skilllv, ud->skillx, ud->skilly);
-		unit_stop_walking(src,1);
+		if (ud->walktimer != -1)
+			unit_stop_walking(src,1);
 		ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv);
 		ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv);
 		if ( battle_config.display_status_timers && sd )
 		if ( battle_config.display_status_timers && sd )
 			clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, ud->skillid, ud->skilllv));
 			clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, ud->skillid, ud->skilllv));
@@ -7707,7 +7708,7 @@ static int skill_unit_effect (struct block_list* bl, va_list ap)
 	int skill_id;
 	int skill_id;
 	bool dissonance;
 	bool dissonance;
 
 
-	if( !unit->alive || bl->prev == NULL )
+	if( (!unit->alive && !(flag&4)) || bl->prev == NULL )
 		return 0;
 		return 0;
 
 
 	nullpo_retr(0, group);
 	nullpo_retr(0, group);
@@ -9751,6 +9752,8 @@ int skill_delunit (struct skill_unit* unit)
 	nullpo_retr(0, unit);
 	nullpo_retr(0, unit);
 	if( !unit->alive )
 	if( !unit->alive )
 		return 0;
 		return 0;
+	unit->alive=0;
+
 	nullpo_retr(0, group=unit->group);
 	nullpo_retr(0, group=unit->group);
 
 
 	if( group->state.song_dance&0x1 ) //Cancel dissonance effect.
 	if( group->state.song_dance&0x1 ) //Cancel dissonance effect.
@@ -9784,7 +9787,6 @@ int skill_delunit (struct skill_unit* unit)
 	clif_skill_delunit(unit);
 	clif_skill_delunit(unit);
 
 
 	unit->group=NULL;
 	unit->group=NULL;
-	unit->alive=0;
 	map_delblock(&unit->bl); // don't free yet
 	map_delblock(&unit->bl); // don't free yet
 	map_deliddb(&unit->bl);
 	map_deliddb(&unit->bl);
 	idb_remove(skillunit_db, unit->bl.id);
 	idb_remove(skillunit_db, unit->bl.id);

+ 13 - 24
src/map/status.c

@@ -817,7 +817,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
 	else
 	else
 	{ //Some death states that would normally be handled by unit_remove_map
 	{ //Some death states that would normally be handled by unit_remove_map
 		unit_stop_attack(target);
 		unit_stop_attack(target);
-		unit_stop_walking(target,0);
+		unit_stop_walking(target,1);
 		unit_skillcastcancel(target,0);
 		unit_skillcastcancel(target,0);
 		clif_clearunit_area(target,1);
 		clif_clearunit_area(target,1);
 		skill_unit_move(target,gettick(),4);
 		skill_unit_move(target,gettick(),4);
@@ -2992,8 +2992,7 @@ void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag)	//[orn]
 void status_calc_bl_sub_mer(struct mercenary_data *md, unsigned long flag)
 void status_calc_bl_sub_mer(struct mercenary_data *md, unsigned long flag)
 {
 {
 	struct status_data
 	struct status_data
-		*status = &md->battle_status,
-		*b_status = &md->base_status;
+		*status = &md->battle_status;
 
 
 	if( flag&(SCB_MAXHP|SCB_VIT) )
 	if( flag&(SCB_MAXHP|SCB_VIT) )
 	{
 	{
@@ -3192,7 +3191,7 @@ void status_calc_bl(struct block_list *bl, unsigned long flag)
 		if (!(status->mode&MD_CANATTACK))
 		if (!(status->mode&MD_CANATTACK))
 			unit_stop_attack(bl);
 			unit_stop_attack(bl);
 		if (!(status->mode&MD_CANMOVE))
 		if (!(status->mode&MD_CANMOVE))
-			unit_stop_walking(bl,0);
+			unit_stop_walking(bl,1);
 	}
 	}
 
 
 // No status changes alter these yet.
 // No status changes alter these yet.
@@ -4441,7 +4440,7 @@ void status_set_viewdata(struct block_list *bl, int class_)
 	struct view_data* vd;
 	struct view_data* vd;
 	nullpo_retv(bl);
 	nullpo_retv(bl);
 	if (mobdb_checkid(class_) || mob_is_clone(class_))
 	if (mobdb_checkid(class_) || mob_is_clone(class_))
-		vd =  mob_get_viewdata(class_);
+		vd = mob_get_viewdata(class_);
 	else if (npcdb_checkid(class_) || (bl->type == BL_NPC && class_ == WARP_CLASS))
 	else if (npcdb_checkid(class_) || (bl->type == BL_NPC && class_ == WARP_CLASS))
 		vd = npc_get_viewdata(class_);
 		vd = npc_get_viewdata(class_);
 	else if (homdb_checkid(class_))
 	else if (homdb_checkid(class_))
@@ -4774,8 +4773,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 	struct view_data *vd;
 	struct view_data *vd;
 	int opt_flag, calc_flag, undead_flag;
 	int opt_flag, calc_flag, undead_flag;
 
 
-	struct mob_data *boss_md = NULL;
-
 	nullpo_retr(0, bl);
 	nullpo_retr(0, bl);
 	sc = status_get_sc(bl);
 	sc = status_get_sc(bl);
 	status = status_get_status_data(bl);
 	status = status_get_status_data(bl);
@@ -5465,13 +5462,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 		case SC_BOSSMAPINFO:
 		case SC_BOSSMAPINFO:
 			if( sd != NULL )
 			if( sd != NULL )
 			{
 			{
-				boss_md = map_getmob_boss(bl->m); // Search for Boss on this Map
+				struct mob_data *boss_md = map_getmob_boss(bl->m); // Search for Boss on this Map
 				if( boss_md == NULL || boss_md->bl.prev == NULL )
 				if( boss_md == NULL || boss_md->bl.prev == NULL )
 				{ // No MVP on this map - MVP is dead
 				{ // No MVP on this map - MVP is dead
 					clif_bossmapinfo(sd->fd, boss_md, 1);
 					clif_bossmapinfo(sd->fd, boss_md, 1);
 					return 0; // No need to start SC
 					return 0; // No need to start SC
 				}
 				}
-
 				val1 = boss_md->bl.id;
 				val1 = boss_md->bl.id;
 				if( (val4 = tick/1000) < 1 )
 				if( (val4 = tick/1000) < 1 )
 					val4 = 1;
 					val4 = 1;
@@ -6280,8 +6276,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 			}
 			}
 			break;
 			break;
 		case SC_BOSSMAPINFO:
 		case SC_BOSSMAPINFO:
-			if( boss_md != NULL )
-				clif_bossmapinfo(sd->fd, boss_md, 0); // First Message
+			clif_bossmapinfo(sd->fd, map_id2boss(sce->val1), 0); // First Message
 			break;
 			break;
 		case SC_MERC_HPUP:
 		case SC_MERC_HPUP:
 			status_percent_heal(bl, 100, 0); // Recover Full HP
 			status_percent_heal(bl, 100, 0); // Recover Full HP
@@ -6894,9 +6889,6 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr data)
 	struct status_change *sc;
 	struct status_change *sc;
 	struct status_change_entry *sce;
 	struct status_change_entry *sce;
 
 
-	struct mob_data *boss_md = NULL;
-	int result;
-
 	bl = map_id2bl(id);
 	bl = map_id2bl(id);
 	if(!bl)
 	if(!bl)
 	{
 	{
@@ -7097,12 +7089,14 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr data)
 	case SC_BOSSMAPINFO:
 	case SC_BOSSMAPINFO:
 		if( sd && --(sce->val4) >= 0 )
 		if( sd && --(sce->val4) >= 0 )
 		{
 		{
-			boss_md = map_id2boss(sce->val1);
-			if( boss_md && boss_md->bl.prev != NULL && sd->bl.m == boss_md->bl.m )
+			struct mob_data *boss_md = map_id2boss(sce->val1);
+			if( boss_md && sd->bl.m == boss_md->bl.m )
 			{
 			{
 				clif_bossmapinfo(sd->fd, boss_md, 1); // Update X - Y on minimap
 				clif_bossmapinfo(sd->fd, boss_md, 1); // Update X - Y on minimap
-				sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
-				return 0;
+				if (boss_md->bl.prev != NULL) {
+					sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
+					return 0;
+				}
 			}
 			}
 		}
 		}
 		break;
 		break;
@@ -7258,12 +7252,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr data)
 	}
 	}
 
 
 	// default for all non-handled control paths is to end the status
 	// default for all non-handled control paths is to end the status
-	result = status_change_end( bl,type,tid );
-	
-	if( sd && boss_md && boss_md->bl.prev == NULL )
-		clif_bossmapinfo(sd->fd, boss_md, 1); // Killed MVP - Show next spawn info
-
-	return result;
+	return status_change_end( bl,type,tid );	
 #undef sc_timer_next
 #undef sc_timer_next
 }
 }
 
 

+ 2 - 2
src/map/storage.c

@@ -42,13 +42,13 @@ static int storage_comp_item(const void *_i1, const void *_i2)
 		return -1;
 		return -1;
 	return i1->nameid - i2->nameid;
 	return i1->nameid - i2->nameid;
 }
 }
- 
+/* In case someone wants to use it in the future.
 static void storage_sortitem(struct storage_data* stor)
 static void storage_sortitem(struct storage_data* stor)
 {
 {
 	nullpo_retv(stor);
 	nullpo_retv(stor);
 	qsort(stor->items, MAX_STORAGE, sizeof(struct item), storage_comp_item);
 	qsort(stor->items, MAX_STORAGE, sizeof(struct item), storage_comp_item);
 }
 }
-
+*/
 static void storage_gsortitem(struct guild_storage* gstor)
 static void storage_gsortitem(struct guild_storage* gstor)
 {
 {
 	nullpo_retv(gstor);
 	nullpo_retv(gstor);

+ 19 - 26
src/map/unit.c

@@ -508,7 +508,7 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool
 
 
 	map_moveblock(bl, dst_x, dst_y, gettick());
 	map_moveblock(bl, dst_x, dst_y, gettick());
 	
 	
-	ud->walktimer = 1; //FIXME: why '1'? [ultramage]
+	ud->walktimer = 1; //Enables clif_insight related packets to spawn character in moving animation.
 	map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl);
 	map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl);
 	ud->walktimer = INVALID_TIMER;
 	ud->walktimer = INVALID_TIMER;
 		
 		
@@ -631,7 +631,12 @@ int unit_warp(struct block_list *bl,short m,short x,short y,int type)
 }
 }
 
 
 /*==========================================
 /*==========================================
- * •à�s’âŽ~
+ * Caused the target object to stop moving.
+ * Flag values:
+ * &0x1: Issue a fixpos packet afterwards
+ * &0x2: Force the unit to move one cell if it hasn't yet
+ * &0x4: Enable moving to the next cell when unit was already half-way there
+ *       (could trigger additional on-touch/place code)
  *------------------------------------------*/
  *------------------------------------------*/
 int unit_stop_walking(struct block_list *bl,int type)
 int unit_stop_walking(struct block_list *bl,int type)
 {
 {
@@ -652,7 +657,7 @@ int unit_stop_walking(struct block_list *bl,int type)
 	ud->state.change_walk_target = 0;
 	ud->state.change_walk_target = 0;
 	tick = gettick();
 	tick = gettick();
 	if ((type&0x02 && !ud->walkpath.path_pos) //Force moving at least one cell.
 	if ((type&0x02 && !ud->walkpath.path_pos) //Force moving at least one cell.
-		|| (td && DIFF_TICK(td->tick, tick) <= td->data/2)) //Enough time has passed to cover half-cell
+		|| (!(type&0x04) && td && DIFF_TICK(td->tick, tick) <= td->data/2)) //Enough time has passed to cover half-cell
 	{	
 	{	
 		ud->walkpath.path_len = ud->walkpath.path_pos+1;
 		ud->walkpath.path_len = ud->walkpath.path_pos+1;
 		unit_walktoxy_timer(-1, tick, bl->id, ud->walkpath.path_pos);
 		unit_walktoxy_timer(-1, tick, bl->id, ud->walkpath.path_pos);
@@ -800,7 +805,7 @@ int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int
 	{	//Stop walking, if chasing, readjust timers.
 	{	//Stop walking, if chasing, readjust timers.
 		if (delay == 1)
 		if (delay == 1)
 		{	//Minimal delay (walk-delay) disabled. Just stop walking.
 		{	//Minimal delay (walk-delay) disabled. Just stop walking.
-			unit_stop_walking(bl,0);
+			unit_stop_walking(bl,4);
 		} else {
 		} else {
 			//Resume running after can move again [Kevin]
 			//Resume running after can move again [Kevin]
 			if(ud->state.running)
 			if(ud->state.running)
@@ -809,7 +814,7 @@ int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int
 			}
 			}
 			else
 			else
 			{
 			{
-				unit_stop_walking(bl,2);
+				unit_stop_walking(bl,6);
 				if(ud->target)
 				if(ud->target)
 					add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->target);
 					add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->target);
 			}
 			}
@@ -1034,13 +1039,13 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 
 
 	if( casttime > 0 || temp )
 	if( casttime > 0 || temp )
 	{ 
 	{ 
+		unit_stop_walking(src,1);
 		clif_skillcasting(src, src->id, target_id, 0,0, skill_num, skill_get_ele(skill_num, skill_lv), casttime);
 		clif_skillcasting(src, src->id, target_id, 0,0, skill_num, skill_get_ele(skill_num, skill_lv), casttime);
 
 
 		if (sd && target->type == BL_MOB)
 		if (sd && target->type == BL_MOB)
 		{
 		{
 			TBL_MOB *md = (TBL_MOB*)target;
 			TBL_MOB *md = (TBL_MOB*)target;
 			mobskill_event(md, src, tick, -1); //Cast targetted skill event.
 			mobskill_event(md, src, tick, -1); //Cast targetted skill event.
-			//temp: used to store mob's mode now.
 			if (tstatus->mode&(MD_CASTSENSOR_IDLE|MD_CASTSENSOR_CHASE) &&
 			if (tstatus->mode&(MD_CASTSENSOR_IDLE|MD_CASTSENSOR_CHASE) &&
 				battle_check_target(target, src, BCT_ENEMY) > 0)
 				battle_check_target(target, src, BCT_ENEMY) > 0)
 			{
 			{
@@ -1050,7 +1055,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 					if (!(tstatus->mode&MD_CASTSENSOR_CHASE))
 					if (!(tstatus->mode&MD_CASTSENSOR_CHASE))
 						break;
 						break;
 					md->target_id = src->id;
 					md->target_id = src->id;
-					md->state.aggressive = (temp&MD_ANGRY)?1:0;
+					md->state.aggressive = (tstatus->mode&MD_ANGRY)?1:0;
 					md->min_chase = md->db->range3;
 					md->min_chase = md->db->range3;
 					break;
 					break;
 				case MSS_IDLE:
 				case MSS_IDLE:
@@ -1058,7 +1063,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 					if (!(tstatus->mode&MD_CASTSENSOR_IDLE))
 					if (!(tstatus->mode&MD_CASTSENSOR_IDLE))
 						break;
 						break;
 					md->target_id = src->id;
 					md->target_id = src->id;
-					md->state.aggressive = (temp&MD_ANGRY)?1:0;
+					md->state.aggressive = (tstatus->mode&MD_ANGRY)?1:0;
 					md->min_chase = md->db->range3;
 					md->min_chase = md->db->range3;
 					break;
 					break;
 				}
 				}
@@ -1098,8 +1103,6 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 		ud->skilltimer = add_timer( tick+casttime, skill_castend_id, src->id, 0 );
 		ud->skilltimer = add_timer( tick+casttime, skill_castend_id, src->id, 0 );
 		if( sd && pc_checkskill(sd,SA_FREECAST) > 0 )
 		if( sd && pc_checkskill(sd,SA_FREECAST) > 0 )
 			status_calc_bl(&sd->bl, SCB_SPEED);
 			status_calc_bl(&sd->bl, SCB_SPEED);
-		else
-			unit_stop_walking(src,1);
 	}
 	}
 	else
 	else
 		skill_castend_id(ud->skilltimer,tick,src->id,0);
 		skill_castend_id(ud->skilltimer,tick,src->id,0);
@@ -1172,20 +1175,12 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh
 		return 0; //Arrow-path check failed.
 		return 0; //Arrow-path check failed.
 
 
 	unit_stop_attack(src);
 	unit_stop_attack(src);
-	ud->state.skillcastcancel = castcancel;
 
 
 	// moved here to prevent Suffragium from ending if skill fails
 	// moved here to prevent Suffragium from ending if skill fails
 	if (!(skill_get_castnodex(skill_num, skill_lv)&2))
 	if (!(skill_get_castnodex(skill_num, skill_lv)&2))
 		casttime = skill_castfix_sc(src, casttime);
 		casttime = skill_castfix_sc(src, casttime);
 
 
-	if( casttime > 0 )
-	{
-		unit_stop_walking( src, 1);
-		clif_skillcasting(src, src->id, 0, skill_x, skill_y, skill_num, skill_get_ele(skill_num, skill_lv), casttime);
-	}
-	else
-		ud->state.skillcastcancel=0;
-
+	ud->state.skillcastcancel = castcancel&&casttime>0?1:0;
 	ud->canact_tick  = tick + casttime + 100;
 	ud->canact_tick  = tick + casttime + 100;
 	if ( battle_config.display_status_timers && sd )
 	if ( battle_config.display_status_timers && sd )
 		clif_status_change(src, SI_ACTIONDELAY, 1, casttime);
 		clif_status_change(src, SI_ACTIONDELAY, 1, casttime);
@@ -1211,11 +1206,11 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh
 
 
 	if( casttime > 0 )
 	if( casttime > 0 )
 	{
 	{
+		unit_stop_walking(src,1);
+		clif_skillcasting(src, src->id, 0, skill_x, skill_y, skill_num, skill_get_ele(skill_num, skill_lv), casttime);
 		ud->skilltimer = add_timer( tick+casttime, skill_castend_pos, src->id, 0 );
 		ud->skilltimer = add_timer( tick+casttime, skill_castend_pos, src->id, 0 );
 		if( sd && pc_checkskill(sd,SA_FREECAST) > 0 )
 		if( sd && pc_checkskill(sd,SA_FREECAST) > 0 )
 			status_calc_bl(&sd->bl, SCB_SPEED);
 			status_calc_bl(&sd->bl, SCB_SPEED);
-		else
-			unit_stop_walking(src,1);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -1283,10 +1278,9 @@ int unit_attack(struct block_list *src,int target_id,int continuous)
 			npc_click(sd,(TBL_NPC*)target); // submitted by leinsirk10 [Celest]
 			npc_click(sd,(TBL_NPC*)target); // submitted by leinsirk10 [Celest]
 			return 0;
 			return 0;
 		}
 		}
-		else if( pc_is90overweight(sd) )
-		{ // overwheight - stop attacking and walking
+		if( pc_is90overweight(sd) )
+		{ // overweight - stop attacking
 			unit_stop_attack(src);
 			unit_stop_attack(src);
-			unit_stop_walking(src,1);
 			return 0;
 			return 0;
 		}
 		}
 	}
 	}
@@ -2117,8 +2111,7 @@ int unit_free(struct block_list *bl, int clrtype)
 				md->base_status = NULL;
 				md->base_status = NULL;
 			}
 			}
 			if( mob_is_clone(md->class_) )
 			if( mob_is_clone(md->class_) )
-				mob_clone_delete(md->class_);
-
+				mob_clone_delete(md);
 			break;
 			break;
 		}
 		}
 		case BL_HOM:
 		case BL_HOM: