From 00be89f64050ff5373a63cc599f533f57ffaead1 Mon Sep 17 00:00:00 2001
From: ultramage <ultramage@54d463be-8e91-2dee-dedb-b68131a5f0ec>
Date: Mon, 15 Jun 2009 14:00:27 +0000
Subject: Improving the r13888 crashfix to cover similar crash scenarios
 discovered: Reordered code in status_change_end(SC_DANCING) so that an
 ensemble's skill unit group is deleted only after removing both performers'
 status changes. Modified the call to skill_delunitgroup() IN
 status_change_end(SC_DANCING) so that it always processes the group's true
 owner and not others (bugreport:3253). Replaced calls to skill_stop_dancing()
 with status_change_end(SC_DANCING), since it now provides identical
 functionality.

git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@13891 54d463be-8e91-2dee-dedb-b68131a5f0ec
---
 src/map/pc.c     |  2 +-
 src/map/skill.c  | 43 ++-----------------------------------------
 src/map/skill.h  |  1 -
 src/map/status.c | 42 ++++++++++++++++++++----------------------
 src/map/unit.c   |  2 +-
 5 files changed, 24 insertions(+), 66 deletions(-)

diff --git a/src/map/pc.c b/src/map/pc.c
index a53a3a7fe..21173b673 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -6916,7 +6916,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
 		pc_calcweapontype(sd);
 		clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
 		if(sd->sc.data[SC_DANCING]) //When unequipping, stop dancing. [Skotlex]
-			skill_stop_dancing(&sd->bl);
+			status_change_end(&sd->bl, SC_DANCING, -1);
 	}
 	if(sd->status.inventory[n].equip & EQP_HAND_L) {
 		sd->status.shield = sd->weapontype2 = 0;
diff --git a/src/map/skill.c b/src/map/skill.c
index bfe20c8c9..a2b337e6a 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -4163,7 +4163,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case BD_ADAPTATION:
 		if(tsc && tsc->data[SC_DANCING]){
 			clif_skill_nodamage(src,bl,skillid,skilllv,1);
-			skill_stop_dancing(bl);
+			status_change_end(bl, SC_DANCING, -1);
 		}
 		break;
 
@@ -7810,7 +7810,7 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int
 				//it only checks if you are doing the same ensemble. So if there's two chars doing an ensemble
 				//which overlaps, by stepping outside of the other parther's ensemble will cause you to cancel
 				//your own. Let's pray that scenario is pretty unlikely and noone will complain too much about it.
-				skill_stop_dancing(bl);
+				status_change_end(bl, SC_DANCING, -1);
 			}
 		case MG_SAFETYWALL:
 		case AL_PNEUMA:
@@ -9899,45 +9899,6 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce
 	return wall;
 }
 
-/*==========================================
- *
- *
- *------------------------------------------*/
-void skill_stop_dancing (struct block_list *src)
-{
-	struct status_change* sc;
-	struct status_change_entry *sce;
-	struct skill_unit_group* group;
-	struct map_session_data* dsd = NULL;
-
-	nullpo_retv(src);
-	nullpo_retv(sc = status_get_sc(src));
-
-	if(!sc->count || !(sce=sc->data[SC_DANCING]))
-		return;
-
-	group = skill_id2group(sce->val2);
-	sce->val2 = 0;
-
-	if (sce->val4)
-	{
-		if (sce->val4 != BCT_SELF)
-			dsd = map_id2sd(sce->val4);
-		sce->val4 = 0;
-	}
-
-	status_change_end(src, SC_DANCING, -1);
-
-	if (dsd && (sce=dsd->sc.data[SC_DANCING]))
-	{
-		sce->val4 = sce->val2 = 0;
-		status_change_end(&dsd->bl, SC_DANCING, -1);
-	}
-
-	if (group)
-		skill_delunitgroup(NULL, group);
-}
-
 /*==========================================
  *
  *------------------------------------------*/
diff --git a/src/map/skill.h b/src/map/skill.h
index b6495538e..bb1e10ef3 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -302,7 +302,6 @@ int skill_unit_move(struct block_list *bl,unsigned int tick,int flag);
 int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy);
 
 struct skill_unit_group *skill_check_dancing( struct block_list *src );
-void skill_stop_dancing(struct block_list *src);
 
 // Guild skills [celest]
 int skill_guildaura_sub (struct block_list *bl,va_list ap);
diff --git a/src/map/status.c b/src/map/status.c
index 5f24e244d..62170bf27 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -710,7 +710,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
 				}
 			}
 			if(sc->data[SC_DANCING] && (unsigned int)hp > status->max_hp>>2)
-				skill_stop_dancing(target);
+				status_change_end(target, SC_DANCING, -1);
 		}
 		unit_skillcastcancel(target, 2);
 	}
@@ -5947,7 +5947,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 				pc_setstand(sd);
 		case SC_TRICKDEAD:
 			unit_stop_attack(bl);
-			skill_stop_dancing(bl);
+			status_change_end(bl, SC_DANCING, -1);
 			// Cancel cast when get status [LuzZza]
 			if (battle_config.sc_castcancel&bl->type)
 				unit_skillcastcancel(bl, 0);
@@ -6205,9 +6205,6 @@ int status_change_clear(struct block_list* bl, int type)
 	if (!sc || !sc->count)
 		return 0;
 
-	if(sc->data[SC_DANCING])
-		skill_stop_dancing(bl);
-
 	for(i = 0; i < SC_MAX; i++)
 	{
 		if(!sc->data[i])
@@ -6426,25 +6423,29 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 				struct map_session_data *dsd;
 				struct status_change_entry *dsc;
 				struct skill_unit_group *group;
-				if(sce->val2)
-				{
-					group = skill_id2group(sce->val2);
-					sce->val2 = 0;
-					skill_delunitgroup(bl, group);
-				}
-				if(sce->val4 && sce->val4 != BCT_SELF && (dsd=map_id2sd(sce->val4))){
-					dsc = dsd->sc.data[type];
+
+				if(sce->val4 && sce->val4 != BCT_SELF && (dsd=map_id2sd(sce->val4)))
+				{// end status on partner as well
+					dsc = dsd->sc.data[SC_DANCING];
 					if(dsc)
 					{	//This will prevent recursive loops. 
 						dsc->val2 = dsc->val4 = 0;
-						status_change_end(&dsd->bl, type, -1);
+						status_change_end(&dsd->bl, SC_DANCING, -1);
 					}
 				}
-			}
-			if ((sce->val1&0xFFFF) == CG_MOONLIT)
-				clif_status_change(bl,SI_MOONLIT,0,0);
 
-			status_change_end(bl,SC_LONGING,-1);
+				if(sce->val2)
+				{// erase associated land skill
+					group = skill_id2group(sce->val2);
+					sce->val2 = 0;
+					skill_delunitgroup(NULL, group);
+				}
+
+				if((sce->val1&0xFFFF) == CG_MOONLIT)
+					clif_status_change(bl,SI_MOONLIT,0,0);
+
+				status_change_end(bl,SC_LONGING,-1);
+			}
 			break;
 		case SC_NOCHAT:
 			if (sd && sd->status.manner < 0 && tid != -1)
@@ -7059,10 +7060,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr data)
 				if (sc->data[SC_LONGING])
 					sp*= 3;
 				if (!status_charge(bl, 0, sp))
-				{
-					skill_stop_dancing(bl);
-					return 0;
-				}
+					break;
 			}
 			sc_timer_next(1000+tick, status_change_timer, bl->id, data);
 			return 0;
diff --git a/src/map/unit.c b/src/map/unit.c
index 9a637fd60..116b8c3d5 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1752,7 +1752,7 @@ int unit_remove_map_(struct block_list *bl, int clrtype, const char* file, int l
 		status_change_end(bl,SC_TRICKDEAD,-1);
 		status_change_end(bl,SC_BLADESTOP_WAIT,-1);
 		status_change_end(bl,SC_RUN,-1);
-		skill_stop_dancing(bl);
+		status_change_end(bl,SC_DANCING,-1);
 		status_change_end(bl,SC_WARM,-1);
 		status_change_end(bl,SC_DEVOTION,-1);
 		status_change_end(bl,SC_MARIONETTE,-1);
-- 
cgit v1.2.3-70-g09d2