Jelajahi Sumber

- Fixed a typo bug in SC_STAR_COMFORT handling.
- Fixed a possible crash bug in SC_POISONREACT handling.
- Simplified the skill trigger code for ST_PRESERVE, SG_FUSION, SG_*_COMFORT
- Unified the status change variables into a single structure (sc_count, opt1, opt2, opt3, option, and the array of status change data) which should make it easier to handle sc related stuff.
- TK_DODGE now won't trigger if your opt1 is set ;)


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

skotlex 19 tahun lalu
induk
melakukan
697d29d7d4
18 mengubah file dengan 1219 tambahan dan 1218 penghapusan
  1. 4 0
      Changelog-Trunk.txt
  2. 20 20
      src/map/atcommand.c
  3. 158 163
      src/map/battle.c
  4. 2 2
      src/map/charcommand.c
  5. 3 3
      src/map/charsave.c
  6. 8 8
      src/map/chrif.c
  7. 171 171
      src/map/clif.c
  8. 8 8
      src/map/map.c
  9. 13 8
      src/map/map.h
  10. 58 58
      src/map/mob.c
  11. 7 7
      src/map/npc.c
  12. 181 164
      src/map/pc.c
  13. 7 7
      src/map/pc.h
  14. 1 1
      src/map/pet.c
  15. 3 3
      src/map/script.c
  16. 253 263
      src/map/skill.c
  17. 321 326
      src/map/status.c
  18. 1 6
      src/map/status.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/02/01
+	* Integrated the status change variables into a single structure for easier
+	  management. [Skotlex]
+	* Break fall should no longer trigger when inflicted by freeze/stone/etc
+	  [Skotlex]
 	* Fixed an overflow in grfio causing read problems in Win32 builds [celest]
 	* Changed resnametable loading behaviour - grfio will load from data directory
 	  first, and then from the highest priority grf only if that fails [celest]

+ 20 - 20
src/map/atcommand.c

@@ -748,7 +748,7 @@ is_atcommand(const int fd, struct map_session_data* sd, const char* message, int
 	nullpo_retr(AtCommand_None, sd);
 
 	if (!battle_config.allow_atcommand_when_mute &&
-		sd->sc_count && sd->sc_data[SC_NOCHAT].timer != -1) {
+		sd->sc.count && sd->sc.data[SC_NOCHAT].timer != -1) {
 		return AtCommand_Unknown;
 	}
 
@@ -1407,7 +1407,7 @@ int atcommand_who3(
 	for (i = 0; i < users; i++) {
 		if ((pl_sd = pl_allsd[i])) {
 			pl_GM_level = pc_isGM(pl_sd);
-			if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
+			if (!((battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
 				memcpy(player_name, pl_sd->status.name, NAME_LENGTH);
 				for (j = 0; player_name[j]; j++)
 					player_name[j] = tolower(player_name[j]);
@@ -1482,7 +1482,7 @@ int atcommand_who2(
 	for (i = 0; i < users; i++) {
 		if ((pl_sd = pl_allsd[i])) {
 			pl_GM_level = pc_isGM(pl_sd);
-			if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
+			if (!((battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
 				memcpy(player_name, pl_sd->status.name, NAME_LENGTH);
 				for (j = 0; player_name[j]; j++)
 					player_name[j] = tolower(player_name[j]);
@@ -1555,7 +1555,7 @@ int atcommand_who(
 	for (i = 0; i < users; i++) {
 		if ((pl_sd = pl_allsd[i])) {
 			pl_GM_level = pc_isGM(pl_sd);
-			if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
+			if (!((battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
 				memcpy(player_name, pl_sd->status.name, NAME_LENGTH);
 				for (j = 0; player_name[j]; j++)
 					player_name[j] = tolower(player_name[j]);
@@ -1635,7 +1635,7 @@ int atcommand_whomap3(
 	for (i = 0; i < users; i++) {
 		if ((pl_sd = pl_allsd[i])) {
 			pl_GM_level = pc_isGM(pl_sd);
-			if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
+			if (!((battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
 				if (pl_sd->bl.m == map_id) {
 					if (pl_GM_level > 0)
 						sprintf(atcmd_output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_GM_level, mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y);
@@ -1695,7 +1695,7 @@ int atcommand_whomap2(
 	for (i = 0; i < users; i++) {
 		if ((pl_sd = pl_allsd[i])) {
 			pl_GM_level = pc_isGM(pl_sd);
-			if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
+			if (!((battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
 				if (pl_sd->bl.m == map_id) {
 					if (pl_GM_level > 0)
 						sprintf(atcmd_output, "Name: %s (GM:%d) | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_GM_level, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level);
@@ -1762,7 +1762,7 @@ int atcommand_whomap(
 	for (i = 0; i < users; i++) {
 		if ((pl_sd = pl_allsd[i])) {
 			pl_GM_level = pc_isGM(pl_sd);
-			if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
+			if (!((battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
 				if (pl_sd->bl.m == map_id) {
 					g = guild_search(pl_sd->status.guild_id);
 					if (g == NULL)
@@ -1835,7 +1835,7 @@ int atcommand_whogm(
 		if ((pl_sd = pl_allsd[i])) {
 			pl_GM_level = pc_isGM(pl_sd);
 			if (pl_GM_level > 0) {
-				if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
+				if (!((battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
 					memcpy(player_name, pl_sd->status.name, NAME_LENGTH);
 					for (j = 0; player_name[j]; j++)
 						player_name[j] = tolower(player_name[j]);
@@ -2134,9 +2134,9 @@ int atcommand_option(
 		return -1;
 	}
 
-	sd->opt1 = param1;
-	sd->opt2 = param2;
-	if (!(sd->status.option & CART_MASK) && param3 & CART_MASK) {
+	sd->sc.opt1 = param1;
+	sd->sc.opt2 = param2;
+	if (!(sd->sc.option & CART_MASK) && param3 & CART_MASK) {
 		if (sd->status.class_ == JOB_BABY_MERCHANT)
 			clif_cart_itemlist(sd);
 		clif_cart_equiplist(sd);
@@ -2158,11 +2158,11 @@ int atcommand_hide(
 	const char* command, const char* message)
 {
 	nullpo_retr(-1, sd);
-	if (sd->status.option & OPTION_INVISIBLE) {
-		sd->status.option &= ~OPTION_INVISIBLE;
+	if (sd->sc.option & OPTION_INVISIBLE) {
+		sd->sc.option &= ~OPTION_INVISIBLE;
 		clif_displaymessage(fd, msg_table[10]); // Invisible: Off
 	} else {
-		sd->status.option |= OPTION_INVISIBLE;
+		sd->sc.option |= OPTION_INVISIBLE;
 		clif_displaymessage(fd, msg_table[11]); // Invisible: On
 	}
 	clif_changeoption(&sd->bl);
@@ -5753,14 +5753,14 @@ int atcommand_mount_peco(
 
 	if (!pc_isriding(sd)) { // if actually no peco
 		if (pc_checkskill(sd, KN_RIDING)) {
-			pc_setoption(sd, sd->status.option | 0x0020);
+			pc_setoption(sd, sd->sc.option | 0x0020);
 			clif_displaymessage(fd, msg_table[102]); // Mounted Peco.
 		} else {
 			clif_displaymessage(fd, msg_table[213]); // You can not mount a peco with your job.
 			return -1;
 		}
 	} else {	//Dismount
-		pc_setoption(sd, sd->status.option & ~0x0020);
+		pc_setoption(sd, sd->sc.option & ~0x0020);
 		clif_displaymessage(fd, msg_table[214]); // Unmounted Peco.
 	}
 
@@ -5789,14 +5789,14 @@ int atcommand_char_mount_peco(
 
 		if (!pc_isriding(pl_sd)) { // if actually no peco
 			if (pc_checkskill(pl_sd, KN_RIDING)) {
-				pc_setoption(pl_sd, pl_sd->status.option | 0x0020);
+				pc_setoption(pl_sd, pl_sd->sc.option | 0x0020);
 				clif_displaymessage(fd, msg_table[216]); // Mounted Peco.
 			} else {
 				clif_displaymessage(fd, msg_table[217]); // You can not mount a peco with your job.
 				return -1;
 			}
 		} else {	//Dismount
-			pc_setoption(pl_sd, pl_sd->status.option & ~0x0020);
+			pc_setoption(pl_sd, pl_sd->sc.option & ~0x0020);
 			clif_displaymessage(fd, msg_table[218]); // Unmounted Peco.
 		}
 	} else {
@@ -8258,7 +8258,7 @@ int atcommand_unmute(
         	return -1;
 
 	if((pl_sd=map_nick2sd((char *) message)) != NULL) {
-		if(pl_sd->sc_data[SC_NOCHAT].timer!=-1) {
+		if(pl_sd->sc.data[SC_NOCHAT].timer!=-1) {
 			pl_sd->status.manner = 0; // have to set to 0 first [celest]
 			status_change_end(&pl_sd->bl,SC_NOCHAT,-1);
 			clif_displaymessage(sd->fd,"Player unmuted");
@@ -9995,7 +9995,7 @@ int atcommand_main(
 				sd->state.mainchat = 1;
 				clif_displaymessage(fd, msg_txt(380)); // Main chat has been activated.
 			}
-			if (sd->sc_data[SC_NOCHAT].timer != -1) {
+			if (sd->sc.data[SC_NOCHAT].timer != -1) {
 				clif_displaymessage(fd, msg_txt(387));
 				return -1;
 			}

+ 158 - 163
src/map/battle.c

@@ -237,13 +237,11 @@ int battle_delay_damage (unsigned int tick, struct block_list *src, struct block
 int battle_damage(struct block_list *bl,struct block_list *target,int damage, int flag)
 {
 	struct map_session_data *sd = NULL;
-	struct status_change *sc_data;
-	short *sc_count;
+	struct status_change *sc;
 
 	nullpo_retr(0, target); //blはNULLで呼ばれることがあるので他でチェック
 	
-	sc_data = status_get_sc_data(target);
-	sc_count = status_get_sc_count(target);
+	sc = status_get_sc(target);
 
 	if (damage == 0 ||
 		target->prev == NULL ||
@@ -261,15 +259,15 @@ int battle_damage(struct block_list *bl,struct block_list *target,int damage, in
 	if (damage < 0)
 		return battle_heal(bl,target,-damage,0,flag);
 
-	if (!flag && sc_count && *sc_count > 0) {
+	if (!flag && sc && sc->count) {
 		// 凍結?A?ホ化?A?⊥ーを?チ去
-		if (sc_data[SC_FREEZE].timer != -1)
+		if (sc->data[SC_FREEZE].timer != -1)
 			status_change_end(target,SC_FREEZE,-1);
-		if (sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2 == 0)
+		if (sc->data[SC_STONE].timer!=-1 && sc->data[SC_STONE].val2 == 0)
 			status_change_end(target,SC_STONE,-1);
-		if (sc_data[SC_SLEEP].timer != -1)
+		if (sc->data[SC_SLEEP].timer != -1)
 			status_change_end(target,SC_SLEEP,-1);
-		if (sc_data[SC_WINKCHARM].timer != -1)
+		if (sc->data[SC_WINKCHARM].timer != -1)
 			status_change_end(target,SC_WINKCHARM,-1);
 	}
 
@@ -282,10 +280,10 @@ int battle_damage(struct block_list *bl,struct block_list *target,int damage, in
 		struct map_session_data *tsd = (struct map_session_data *)target;
 		if (!tsd)
 			return 0;
-		if (sc_data[SC_DEVOTION].val1 && bl && battle_getcurrentskill(bl) != PA_PRESSURE)
+		if (sc->count && sc->data[SC_DEVOTION].val1 && bl && battle_getcurrentskill(bl) != PA_PRESSURE)
 		{	//Devotion only works on attacks from a source (prevent it from absorbing coma) [Skotlex]
-			struct map_session_data *sd2 = map_id2sd(tsd->sc_data[SC_DEVOTION].val1);
-			if (sd2 && sd2->devotion[sc_data[SC_DEVOTION].val2] == target->id)
+			struct map_session_data *sd2 = map_id2sd(tsd->sc.data[SC_DEVOTION].val1);
+			if (sd2 && sd2->devotion[sc->data[SC_DEVOTION].val2] == target->id)
 			{
 				clif_damage(bl, &sd2->bl, gettick(), 0, 0, damage, 0, 0, 0);
 				pc_damage(&sd2->bl, sd2, damage);
@@ -377,11 +375,11 @@ int battle_stopwalking(struct block_list *bl,int type)
 int battle_attr_fix(struct block_list *src, struct block_list *target, int damage,int atk_elem,int def_elem)
 {
 	int def_type = def_elem % 10, def_lv = def_elem / 10 / 2;
-	struct status_change *sc_data=NULL, *tsc_data=NULL;
+	struct status_change *sc=NULL, *tsc=NULL;
 	int ratio;
 	
-	if (src) sc_data = status_get_sc_data(src);
-	if (target) tsc_data = status_get_sc_data(target);
+	if (src) sc = status_get_sc(src);
+	if (target) tsc = status_get_sc(target);
 	
 	if (atk_elem < 0 || atk_elem > 9)
 		atk_elem = rand()%9;	//�?器属?ォランダムで付加
@@ -427,24 +425,24 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag
 	}
 
 	ratio = attr_fix_table[def_lv-1][atk_elem][def_type];
-	if (sc_data)
+	if (sc && sc->count)
 	{
-		if(sc_data[SC_VOLCANO].timer!=-1 && atk_elem == 3)
-			ratio += enchant_eff[sc_data[SC_VOLCANO].val1-1];
-		if(sc_data[SC_VIOLENTGALE].timer!=-1 && atk_elem == 4)
-			ratio += enchant_eff[sc_data[SC_VIOLENTGALE].val1-1];
-		if(sc_data[SC_DELUGE].timer!=-1 && atk_elem == 1)
-			ratio += enchant_eff[sc_data[SC_DELUGE].val1-1];
+		if(sc->data[SC_VOLCANO].timer!=-1 && atk_elem == 3)
+			ratio += enchant_eff[sc->data[SC_VOLCANO].val1-1];
+		if(sc->data[SC_VIOLENTGALE].timer!=-1 && atk_elem == 4)
+			ratio += enchant_eff[sc->data[SC_VIOLENTGALE].val1-1];
+		if(sc->data[SC_DELUGE].timer!=-1 && atk_elem == 1)
+			ratio += enchant_eff[sc->data[SC_DELUGE].val1-1];
 	}
-	if (tsc_data)
+	if (tsc && tsc->count)
 	{
-		if(tsc_data[SC_ARMOR_ELEMENT].timer!=-1)
+		if(tsc->data[SC_ARMOR_ELEMENT].timer!=-1)
 		{
-			if (tsc_data[SC_ARMOR_ELEMENT].val1 == atk_elem)
-				ratio -= tsc_data[SC_ARMOR_ELEMENT].val2;
+			if (tsc->data[SC_ARMOR_ELEMENT].val1 == atk_elem)
+				ratio -= tsc->data[SC_ARMOR_ELEMENT].val2;
 			else
-			if (tsc_data[SC_ARMOR_ELEMENT].val3 == atk_elem)
-				ratio -= tsc_data[SC_ARMOR_ELEMENT].val4;
+			if (tsc->data[SC_ARMOR_ELEMENT].val3 == atk_elem)
+				ratio -= tsc->data[SC_ARMOR_ELEMENT].val4;
 		}
 	}
 	return damage*ratio/100;
@@ -536,8 +534,8 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 {
 	struct map_session_data *sd = NULL;
 	struct mob_data *md = NULL;
-	struct status_change *sc_data, *sc;
-	short *sc_count;
+	struct status_change *sc;
+	struct status_change_entry *sci;
 	int class_;
 
 	nullpo_retr(0, bl);
@@ -553,8 +551,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 		sd=(struct map_session_data *)bl;
 	}
 
-	sc_data = status_get_sc_data(bl);
-	sc_count = status_get_sc_count(bl);
+	sc = status_get_sc(bl);
 
 	if(flag&BF_LONG && map_getcell(bl->m, bl->x, bl->y, CELL_CHKPNEUMA) &&
 		((flag&BF_WEAPON && skill_num != NPC_GUIDEDATTACK) ||
@@ -563,12 +560,12 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 		return 0;
 	}
 	
-	if (sc_count && *sc_count > 0) {
+	if (sc && sc->count) {
 		//First, sc_*'s that reduce damage to 0.
-		if (sc_data[SC_SAFETYWALL].timer!=-1 && flag&BF_SHORT && (skill_num != NPC_GUIDEDATTACK && skill_num != AM_DEMONSTRATION)
+		if (sc->data[SC_SAFETYWALL].timer!=-1 && flag&BF_SHORT && (skill_num != NPC_GUIDEDATTACK && skill_num != AM_DEMONSTRATION)
 		) {
 			// セ?[フティウォ?[ル
-			struct skill_unit_group *group = (struct skill_unit_group *)sc_data[SC_SAFETYWALL].val3;
+			struct skill_unit_group *group = (struct skill_unit_group *)sc->data[SC_SAFETYWALL].val3;
 			if (group) {
 				if (--group->val2<=0)
 					skill_delunitgroup(group);
@@ -578,28 +575,17 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 			}
 		}
 	
-		if(sc_data[SC_LANDPROTECTOR].timer!=-1 && flag&BF_MAGIC)
+		if(sc->data[SC_LANDPROTECTOR].timer!=-1 && flag&BF_MAGIC)
 			return 0;
 		
-		/* Moved to battle_calc_weapon_attack for now.
-		if(sc_data[SC_KAUPE].timer != -1 && damage > 0 && !skill_num) {
-			if(rand()%100 < sc_data[SC_KAUPE].val2) {
-				clif_skill_nodamage(bl,bl,SL_KAUPE,sc_data[SC_KAUPE].val1,1);
-				if (--sc_data[SC_KAUPE].val3 <= 0) //We make it work like Safety Wall, even though it only blocks 1 time.
-					status_change_end(bl, SC_KAUPE, -1);
-				return 0;
-			}
-		}
-		*/
-		
-		if(sc_data[SC_AUTOGUARD].timer != -1 && flag&BF_WEAPON &&
-			rand()%100 < sc_data[SC_AUTOGUARD].val2) {
+		if(sc->data[SC_AUTOGUARD].timer != -1 && flag&BF_WEAPON &&
+			rand()%100 < sc->data[SC_AUTOGUARD].val2) {
 			int delay;
-			clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sc_data[SC_AUTOGUARD].val1,1);
+			clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sc->data[SC_AUTOGUARD].val1,1);
 			// different delay depending on skill level [celest]
-			if (sc_data[SC_AUTOGUARD].val1 <= 5)
+			if (sc->data[SC_AUTOGUARD].val1 <= 5)
 				delay = 300;
-			else if (sc_data[SC_AUTOGUARD].val1 > 5 && sc_data[SC_AUTOGUARD].val1 <= 9)
+			else if (sc->data[SC_AUTOGUARD].val1 > 5 && sc->data[SC_AUTOGUARD].val1 <= 9)
 				delay = 200;
 			else
 				delay = 100;
@@ -608,39 +594,39 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 			else if(md)
 				md->canmove_tick = gettick() + delay;
 
-			if(sc_data[SC_SHRINK].timer != -1 && rand()%100<5*sc_data[SC_AUTOGUARD].val1)
+			if(sc->data[SC_SHRINK].timer != -1 && rand()%100<5*sc->data[SC_AUTOGUARD].val1)
 				skill_blown(bl,src,skill_get_blewcount(CR_SHRINK,1));
 			return 0;
 		}
 
 // -- moonsoul (chance to block attacks with new Lord Knight skill parrying)
 //
-		if(sc_data[SC_PARRYING].timer != -1 && flag&BF_WEAPON &&
-			rand()%100 < sc_data[SC_PARRYING].val2) {
-			clif_skill_nodamage(bl,bl,LK_PARRYING,sc_data[SC_PARRYING].val1,1);
+		if(sc->data[SC_PARRYING].timer != -1 && flag&BF_WEAPON &&
+			rand()%100 < sc->data[SC_PARRYING].val2) {
+			clif_skill_nodamage(bl,bl,LK_PARRYING,sc->data[SC_PARRYING].val1,1);
 			return 0;
 		}
 		
-		if(sc_data[SC_DODGE].timer != -1 && (flag&BF_LONG || (sc_data[SC_SPURT].timer != -1 && flag&BF_WEAPON))
+		if(sc->data[SC_DODGE].timer != -1 && !sc->opt1 && (flag&BF_LONG || (sc->data[SC_SPURT].timer != -1 && flag&BF_WEAPON))
 			&& rand()%100 < 20) {
 			clif_skill_nodamage(bl,bl,TK_DODGE,1,1);
-			if (sc_data[SC_COMBO].timer == -1)
+			if (sc->data[SC_COMBO].timer == -1)
 				status_change_start(bl, SC_COMBO, TK_JUMPKICK, src->id, 0, 0, 2000, 0);
 			return 0;
 		}
 
-		if(sc_data[SC_FOGWALL].timer != -1 && flag&BF_MAGIC
+		if(sc->data[SC_FOGWALL].timer != -1 && flag&BF_MAGIC
 			&& rand()%100 < 75 && !(skill_get_inf(skill_num)&INF_GROUND_SKILL))
 			return 0;
 
 		//Now damage increasing effects
-		if(sc_data[SC_AETERNA].timer!=-1 && skill_num != PA_PRESSURE){
+		if(sc->data[SC_AETERNA].timer!=-1 && skill_num != PA_PRESSURE){
 			damage<<=1;
 			if (skill_num != ASC_BREAKER || flag & BF_MAGIC) //Only end it on the second attack of breaker. [Skotlex]
 				status_change_end( bl,SC_AETERNA,-1 );
 		}
 
-		if(sc_data[SC_SPIDERWEB].timer!=-1)	// [Celest]
+		if(sc->data[SC_SPIDERWEB].timer!=-1)	// [Celest]
 			if ((flag&BF_SKILL && skill_get_pl(skill_num)==3) ||
 				(!flag&BF_SKILL && status_get_attack_element(src)==3)) {
 				damage<<=1;
@@ -648,20 +634,20 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 			}
 
 		//Finally damage reductions....
-		if(sc_data[SC_ASSUMPTIO].timer != -1){
+		if(sc->data[SC_ASSUMPTIO].timer != -1){
 			if(map_flag_vs(bl->m))
 				damage=damage*2/3; //Receive 66% damage
 			else
 				damage>>=1; //Receive 50% damage
 		}
 
-		if(sc_data[SC_DEFENDER].timer != -1 && flag&BF_LONG && flag&BF_WEAPON)
-			damage=damage*(100-sc_data[SC_DEFENDER].val2)/100;
+		if(sc->data[SC_DEFENDER].timer != -1 && flag&BF_LONG && flag&BF_WEAPON)
+			damage=damage*(100-sc->data[SC_DEFENDER].val2)/100;
 
-		if(sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG && flag&BF_WEAPON)
+		if(sc->data[SC_FOGWALL].timer != -1 && flag&BF_LONG && flag&BF_WEAPON)
 			damage >>=1;
 
-		if(sc_data[SC_ENERGYCOAT].timer!=-1 && flag&BF_WEAPON){
+		if(sc->data[SC_ENERGYCOAT].timer!=-1 && flag&BF_WEAPON){
 			if(sd){
 				if(sd->status.sp>0){
 					int per = sd->status.sp * 5 / (sd->status.max_sp + 1);
@@ -674,45 +660,44 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 					status_change_end( bl,SC_ENERGYCOAT,-1 );
 			}
 			else
-				damage -= damage * (sc_data[SC_ENERGYCOAT].val1 * 6) / 100;
+				damage -= damage * (sc->data[SC_ENERGYCOAT].val1 * 6) / 100;
 		}
 
-		if(sc_data[SC_REJECTSWORD].timer!=-1 && flag&BF_WEAPON &&
+		if(sc->data[SC_REJECTSWORD].timer!=-1 && flag&BF_WEAPON &&
 			// Fixed the condition check [Aalye]
 			(src->type==BL_MOB || (src->type==BL_PC && (((struct map_session_data *)src)->status.weapon == 1 ||
 			((struct map_session_data *)src)->status.weapon == 2 ||
 			((struct map_session_data *)src)->status.weapon == 3)))){
-			if(rand()%100 < (15*sc_data[SC_REJECTSWORD].val1)){
+			if(rand()%100 < (15*sc->data[SC_REJECTSWORD].val1)){
 				damage = damage*50/100;
 				clif_damage(bl,src,gettick(),0,0,damage,0,0,0);
 				battle_damage(bl,src,damage,0);
-				clif_skill_nodamage(bl,bl,ST_REJECTSWORD,sc_data[SC_REJECTSWORD].val1,1);
-				if((--sc_data[SC_REJECTSWORD].val2)<=0)
+				clif_skill_nodamage(bl,bl,ST_REJECTSWORD,sc->data[SC_REJECTSWORD].val1,1);
+				if((--sc->data[SC_REJECTSWORD].val2)<=0)
 					status_change_end(bl, SC_REJECTSWORD, -1);
 			}
 		}
 
 		//Finally Kyrie because it may, or not, reduce damage to 0.
-		if(sc_data[SC_KYRIE].timer!=-1){
-			sc=&sc_data[SC_KYRIE];
-			sc->val2-=damage;
+		if(sc->data[SC_KYRIE].timer!=-1){
+			sci=&sc->data[SC_KYRIE];
+			sci->val2-=damage;
 			if(flag&BF_WEAPON || skill_num == TF_THROWSTONE){
-				if(sc->val2>=0)
+				if(sci->val2>=0)
 					damage=0;
 				else
-				  	damage=-sc->val2;
+				  	damage=-sci->val2;
 			}
-			if((--sc->val3)<=0 || (sc->val2<=0) || skill_num == AL_HOLYLIGHT)
+			if((--sci->val3)<=0 || (sci->val2<=0) || skill_num == AL_HOLYLIGHT)
 				status_change_end(bl, SC_KYRIE, -1);
 		}
 		if (damage <= 0) return 0;
 	}
 	
 	//SC effects from caster side.
-	sc_data = status_get_sc_data(src);
-	sc_count = status_get_sc_count(src);
-	if (sc_count && *sc_count > 0) {
-		if(sc_data[SC_FOGWALL].timer != -1 && flag&(BF_LONG|BF_MAGIC)) {
+	sc = status_get_sc(src);
+	if (sc && sc->count) {
+		if(sc->data[SC_FOGWALL].timer != -1 && flag&(BF_LONG|BF_MAGIC)) {
 			if (flag&BF_MAGIC) {
 				if(!(skill_get_inf(skill_num)&INF_GROUND_SKILL) && rand()%100 < 75)
 					return 0;
@@ -830,7 +815,7 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int
 	// ビ?[ストベイン(+4 ?` +40) vs 動物 or ?ゥ虫
 	if((skill = pc_checkskill(sd,HT_BEASTBANE)) > 0 && (race==2 || race==4) ) {
 		damage += (skill * 4);
-		if (sd->sc_data[SC_SPIRIT].timer != -1 && sd->sc_data[SC_SPIRIT].val2 == SL_HUNTER)
+		if (sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_HUNTER)
 			damage += sd->status.str;
 	}
 
@@ -953,7 +938,7 @@ static void battle_calc_base_damage(struct block_list *src, struct block_list *t
 {
 	unsigned short baseatk=0, baseatk_=0, atkmin=0, atkmax=0, atkmin_=0, atkmax_=0;
 	struct map_session_data *sd;
-	struct status_change *sc_data = status_get_sc_data(src);
+	struct status_change *sc= status_get_sc(src);
 	int t_size = status_get_size(target);
 
 	if (src->type == BL_PC)
@@ -1026,7 +1011,7 @@ static void battle_calc_base_damage(struct block_list *src, struct block_list *t
 		}
 	}
 	
-	if (sc_data && sc_data[SC_MAXIMIZEPOWER].timer!=-1)
+	if (sc && sc->data[SC_MAXIMIZEPOWER].timer!=-1)
 	{
 		atkmin = atkmax;
 		atkmin_ = atkmax_;
@@ -1053,7 +1038,7 @@ static void battle_calc_base_damage(struct block_list *src, struct block_list *t
 		//SizeFix only for players
 		if (!(
 			sd->special_state.no_sizefix ||
-			(sc_data && sc_data[SC_WEAPONPERFECTION].timer!=-1) ||
+			(sc && sc->data[SC_WEAPONPERFECTION].timer!=-1) ||
 			(pc_isriding(sd) && (sd->status.weapon==4 || sd->status.weapon==5) && t_size==1) ||
 			(flag&8)
 			))
@@ -1089,8 +1074,8 @@ static struct Damage battle_calc_weapon_attack(
 	short t_race=0, t_ele=0, s_race=0;	//Set to 0 because the compiler does not notices they are NOT gonna be used uninitialized
 	short s_ele, s_ele_;
 	short def1, def2;
-	struct status_change *sc_data = status_get_sc_data(src);
-	struct status_change *t_sc_data = status_get_sc_data(target);
+	struct status_change *sc = status_get_sc(src);
+	struct status_change *tsc = status_get_sc(target);
 	struct {
 		unsigned hit : 1; //the attack Hit? (not a miss)
 		unsigned cri : 1;		//Critical hit
@@ -1129,6 +1114,11 @@ static struct Damage battle_calc_weapon_attack(
 	wd.flag=BF_SHORT|BF_WEAPON|BF_NORMAL; //Initial Flag
 	wd.dmg_lv=ATK_DEF;	//This assumption simplifies the assignation later
 
+	if (sc && !sc->count)
+		sc = NULL; //Skip checking as there are no status changes active.
+	if (tsc && !tsc->count)
+		sc = NULL; //Skip checking as there are no status changes active.
+	
 	switch (src->type)
 	{
 		case BL_PC:
@@ -1270,7 +1260,7 @@ static struct Damage battle_calc_weapon_attack(
 	//Check for counter 
 	if(!skill_num)
 	{
-		if(t_sc_data && t_sc_data[SC_AUTOCOUNTER].timer != -1)
+		if(tsc && tsc->data[SC_AUTOCOUNTER].timer != -1)
 		//If it got here and you had autocounter active, then the direction/range does not matches: critical
 			flag.cri = 1;
 	}	//End counter-check
@@ -1330,12 +1320,12 @@ static struct Damage battle_calc_weapon_attack(
 		//Therefore, we use the old value 3 on cases when an sd gets attacked by a mob
 		cri -= status_get_luk(target) * (md&&tsd?3:2);
 		
-		if(t_sc_data)
+		if(tsc)
 		{
-			if (t_sc_data[SC_SLEEP].timer!=-1 )
+			if (tsc->data[SC_SLEEP].timer!=-1 )
 				cri <<=1;
-			if(t_sc_data[SC_JOINTBEAT].timer != -1 &&
-				t_sc_data[SC_JOINTBEAT].val2 == 6) // Always take crits with Neck broken by Joint Beat [DracoRPG]
+			if(tsc->data[SC_JOINTBEAT].timer != -1 &&
+				tsc->data[SC_JOINTBEAT].val2 == 6) // Always take crits with Neck broken by Joint Beat [DracoRPG]
 				flag.cri=1;
 		}
 		switch (skill_num)
@@ -1362,7 +1352,7 @@ static struct Damage battle_calc_weapon_attack(
 	} else {	//Check for Perfect Hit
 		if(sd && sd->perfect_hit > 0 && rand()%100 < sd->perfect_hit)
 			flag.hit = 1;
-		if (sc_data && sc_data[SC_FUSION].timer != -1) {
+		if (sc && sc->count && sc->data[SC_FUSION].timer != -1) {
 			flag.hit = 1; //SG_FUSION always hit [Komurka]
 			flag.idef = flag.idef2 = 1; //def ignore [Komurka]
 		}
@@ -1384,15 +1374,15 @@ static struct Damage battle_calc_weapon_attack(
 					flag.hit = 1;
 					break;
 				case CR_SHIELDBOOMERANG:
-					if (sc_data && sc_data[SC_SPIRIT].timer != -1 && sc_data[SC_SPIRIT].val2 == SL_CRUSADER)
+					if (sc && sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_CRUSADER)
 						flag.hit = 1;
 					break;
 			}
-		if ((t_sc_data && !flag.hit) &&
-			(t_sc_data[SC_SLEEP].timer!=-1 ||
-			t_sc_data[SC_STAN].timer!=-1 ||
-			t_sc_data[SC_FREEZE].timer!=-1 ||
-			(t_sc_data[SC_STONE].timer!=-1 && t_sc_data[SC_STONE].val2==0))
+		if ((tsc && !flag.hit) &&
+			(tsc->data[SC_SLEEP].timer!=-1 ||
+			tsc->data[SC_STAN].timer!=-1 ||
+			tsc->data[SC_FREEZE].timer!=-1 ||
+			(tsc->data[SC_STONE].timer!=-1 && tsc->data[SC_STONE].val2==0))
 			)
 			flag.hit = 1;
 	}
@@ -1456,8 +1446,8 @@ static struct Damage battle_calc_weapon_attack(
 
 		if(rand()%100 >= hitrate)
 			wd.dmg_lv = ATK_FLEE;
-		else if (t_sc_data && t_sc_data[SC_KAUPE].timer != -1 && rand()%100 < t_sc_data[SC_KAUPE].val2) {
-			if (--t_sc_data[SC_KAUPE].val3 <= 0) //We make it work like Safety Wall, even though it only blocks 1 time.
+		else if (tsc && tsc->data[SC_KAUPE].timer != -1 && rand()%100 < tsc->data[SC_KAUPE].val2) {
+			if (--tsc->data[SC_KAUPE].val3 <= 0) //We make it work like Safety Wall, even though it only blocks 1 time.
 				status_change_end(target, SC_KAUPE, -1);
 			wd.dmg_lv = ATK_FLEE;
 		} else
@@ -1495,9 +1485,9 @@ static struct Damage battle_calc_weapon_attack(
 				wd.damage = hp_dmg;
 				wd.damage2 = 0;
 
-				if (sc_data && sc_data[SC_SACRIFICE].timer != -1)
+				if (sc && sc->data[SC_SACRIFICE].timer != -1)
 				{
-					if (--sc_data[SC_SACRIFICE].val2 <= 0)
+					if (--sc->data[SC_SACRIFICE].val2 <= 0)
 						status_change_end(src, SC_SACRIFICE,-1);
 				}
 				break;
@@ -1567,13 +1557,13 @@ static struct Damage battle_calc_weapon_attack(
 		} //End switch(skill_num)
 
 		//Skill damage modifiers that stack linearly
-		if(sc_data && skill_num != PA_SACRIFICE)
+		if(sc && skill_num != PA_SACRIFICE)
 		{
-			if(sc_data[SC_OVERTHRUST].timer != -1)
-				skillratio += 5*sc_data[SC_OVERTHRUST].val1;
-			if(sc_data[SC_MAXOVERTHRUST].timer != -1)
-				skillratio += 20*sc_data[SC_MAXOVERTHRUST].val1;
-			if(sc_data[SC_BERSERK].timer != -1)
+			if(sc->data[SC_OVERTHRUST].timer != -1)
+				skillratio += 5*sc->data[SC_OVERTHRUST].val1;
+			if(sc->data[SC_MAXOVERTHRUST].timer != -1)
+				skillratio += 20*sc->data[SC_MAXOVERTHRUST].val1;
+			if(sc->data[SC_BERSERK].timer != -1)
 				skillratio += 100;
 		}
 		if (!skill_num)
@@ -1700,7 +1690,7 @@ static struct Damage battle_calc_weapon_attack(
 					break;
 				case CR_SHIELDBOOMERANG:
 					skillratio += 30*skill_lv;
-					if (sc_data && sc_data[SC_SPIRIT].timer != -1 && sc_data[SC_SPIRIT].val2 == SL_CRUSADER)
+					if (sc && sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_CRUSADER)
 						skillratio += 100;
 					break;
 				case NPC_DARKCROSS:
@@ -1823,7 +1813,7 @@ static struct Damage battle_calc_weapon_attack(
 					break;
 				case TK_JUMPKICK:
 					skillratio += -70 + 10*skill_lv;
-					if (sc_data && sc_data[SC_COMBO].timer != -1 && sc_data[SC_COMBO].val1 == skill_num)
+					if (sc && sc->data[SC_COMBO].timer != -1 && sc->data[SC_COMBO].val1 == skill_num)
 						skillratio += 10*status_get_lv(src)/3;
 					break;
 				case KN_CHARGEATK:
@@ -1858,16 +1848,16 @@ static struct Damage battle_calc_weapon_attack(
 		//Here comes a second pass for skills that stack to the previously defined % damage. [Skotlex]
 		skillratio = 100;
 		//Skill damage modifiers that affect linearly stacked damage.
-		if (sc_data && skill_num != PA_SACRIFICE) {
-			if(sc_data[SC_TRUESIGHT].timer != -1)
-				skillratio += 2*sc_data[SC_TRUESIGHT].val1;
+		if (sc && skill_num != PA_SACRIFICE) {
+			if(sc->data[SC_TRUESIGHT].timer != -1)
+				skillratio += 2*sc->data[SC_TRUESIGHT].val1;
 			// It is still not quite decided whether it works on bosses or not...
-			if(sc_data[SC_EDP].timer != -1 /*&& !(t_mode&MD_BOSS)*/ && skill_num != ASC_BREAKER && skill_num != ASC_METEORASSAULT)
-				skillratio += 50 +50*sc_data[SC_EDP].val1;
+			if(sc->data[SC_EDP].timer != -1 /*&& !(t_mode&MD_BOSS)*/ && skill_num != ASC_BREAKER && skill_num != ASC_METEORASSAULT)
+				skillratio += 50 +50*sc->data[SC_EDP].val1;
 		}
 		switch (skill_num) {
 			case AS_SONICBLOW:
-				if (sc_data && sc_data[SC_SPIRIT].timer != -1 && sc_data[SC_SPIRIT].val2 == SL_ASSASIN)
+				if (sc && sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_ASSASIN)
 					skillratio += (map_flag_gvg(src->m))?25:100; //+25% dmg on woe/+100% dmg on nonwoe
 				if(sd && pc_checkskill(sd,AS_SONICACCEL)>0)
 					skillratio += 10;
@@ -1975,10 +1965,10 @@ static struct Damage battle_calc_weapon_attack(
 		}
 
 		//Post skill/vit reduction damage increases
-		if (sc_data && skill_num != LK_SPIRALPIERCE)
+		if (sc && skill_num != LK_SPIRALPIERCE)
 		{	//SC skill damages
-			if(sc_data[SC_AURABLADE].timer!=-1) 
-				ATK_ADD(20*sc_data[SC_AURABLADE].val1);
+			if(sc->data[SC_AURABLADE].timer!=-1) 
+				ATK_ADD(20*sc->data[SC_AURABLADE].val1);
 		}
 
 		//Refine bonus
@@ -2043,12 +2033,12 @@ static struct Damage battle_calc_weapon_attack(
 			if (flag.lh && wd.damage2 > 0)
 				wd.damage2 = battle_attr_fix(src,target,wd.damage2,s_ele_,t_element);
 		}
-		if(sc_data && sc_data[SC_WATK_ELEMENT].timer != -1)
+		if(sc && sc->data[SC_WATK_ELEMENT].timer != -1)
 		{	//Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex]
 			int damage=0;
 			battle_calc_base_damage(src, target, &damage, NULL, (flag.arrow?2:0));
-			damage = damage*sc_data[SC_WATK_ELEMENT].val2/100;
-			damage = battle_attr_fix(src,target,damage,sc_data[SC_WATK_ELEMENT].val1,t_element);
+			damage = damage*sc->data[SC_WATK_ELEMENT].val2/100;
+			damage = battle_attr_fix(src,target,damage,sc->data[SC_WATK_ELEMENT].val1,t_element);
 			ATK_ADD(damage);
 		}
 	}
@@ -2267,10 +2257,10 @@ static struct Damage battle_calc_weapon_attack(
 		(wd.damage > 0 || wd.damage2 > 0)) {
 		if (battle_config.equip_self_break_rate) {	// Self weapon breaking
 			int breakrate = battle_config.equip_natural_break_rate;
-			if (sd->sc_count) {
-				if(sd->sc_data[SC_OVERTHRUST].timer!=-1)
+			if (sc) {
+				if(sc->data[SC_OVERTHRUST].timer!=-1)
 					breakrate += 10;
-				if(sd->sc_data[SC_MAXOVERTHRUST].timer!=-1)
+				if(sc->data[SC_MAXOVERTHRUST].timer!=-1)
 					breakrate += 10;
 			}
 			if(rand() % 10000 < breakrate * battle_config.equip_self_break_rate / 100 || breakrate >= 10000)
@@ -2282,10 +2272,10 @@ static struct Damage battle_calc_weapon_attack(
 
 			breakrate[0] += sd->break_weapon_rate; // Break rate from equipment
 			breakrate[1] += sd->break_armor_rate;
-			if (sd->sc_count) {
-				if (sd->sc_data[SC_MELTDOWN].timer!=-1) {
-					breakrate[0] += 100*sd->sc_data[SC_MELTDOWN].val1;
-					breakrate[1] += 70*sd->sc_data[SC_MELTDOWN].val1;
+			if (sc) {
+				if (sc->data[SC_MELTDOWN].timer!=-1) {
+					breakrate[0] += 100*sc->data[SC_MELTDOWN].val1;
+					breakrate[1] += 70*sc->data[SC_MELTDOWN].val1;
 					breaktime = skill_get_time2(WS_MELTDOWN,1);
 				}
 			}	
@@ -2556,7 +2546,7 @@ struct Damage battle_calc_magic_attack(
 						break;
 					case AL_HOLYLIGHT:
 						skillratio += 25;
-						if (sd && sd->sc_data[SC_SPIRIT].timer != -1 && sd->sc_data[SC_SPIRIT].val2 == SL_PRIEST)
+						if (sd && sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_PRIEST)
 							skillratio *= 5; //Does 5x damage include bonuses from other skills?
 						break;
 					case AL_RUWACH:
@@ -2804,11 +2794,11 @@ struct Damage  battle_calc_misc_attack(
 
 	case NPC_DARKBREATH:
 		{
-			struct status_change *sc_data = status_get_sc_data(target);
+			struct status_change *sc = status_get_sc(target);
 			int hitrate=status_get_hit(bl) - status_get_flee(target) + 80;
 			hitrate = ( (hitrate>95)?95: ((hitrate<5)?5:hitrate) );
-			if(sc_data && (sc_data[SC_SLEEP].timer!=-1 || sc_data[SC_STAN].timer!=-1 ||
-				sc_data[SC_FREEZE].timer!=-1 || (sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0) ) )
+			if(sc && sc->count && (sc->data[SC_SLEEP].timer!=-1 || sc->data[SC_STAN].timer!=-1 ||
+				sc->data[SC_FREEZE].timer!=-1 || (sc->data[SC_STONE].timer!=-1 && sc->data[SC_STONE].val2==0) ) )
 				hitrate = 1000000;
 			if(rand()%100 < hitrate) {
 				damage = 500 + (skill_lv-1)*1000 + rand()%1000;
@@ -2935,11 +2925,11 @@ struct Damage battle_calc_attack(	int attack_type,
 
 int battle_calc_return_damage(struct block_list *bl, int damage, int flag) {
 	struct map_session_data *sd=NULL;
-	struct status_change *sc_data;
+	struct status_change *sc;
 	int rdamage = 0;
 	
 	if (bl->type == BL_PC) sd = (struct map_session_data*)bl;
-	sc_data = status_get_sc_data(bl);
+	sc = status_get_sc(bl);
 
 	if(flag&BF_WEAPON) {
 		if (flag & BF_SHORT) {
@@ -2948,9 +2938,9 @@ int battle_calc_return_damage(struct block_list *bl, int damage, int flag) {
 				rdamage += damage * sd->short_weapon_damage_return / 100;
 				if(rdamage < 1) rdamage = 1;
 			}
-			if (sc_data && sc_data[SC_REFLECTSHIELD].timer != -1)
+			if (sc && sc->data[SC_REFLECTSHIELD].timer != -1)
 		  	{
-				rdamage += damage * sc_data[SC_REFLECTSHIELD].val2 / 100;
+				rdamage += damage * sc->data[SC_REFLECTSHIELD].val2 / 100;
 				if (rdamage < 1) rdamage = 1;
 			}
 		} else if (flag & BF_LONG) {
@@ -2980,7 +2970,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 	 unsigned int tick,int flag)
 {
 	struct map_session_data *sd = NULL, *tsd = NULL;
-	struct status_change *sc_data, *tsc_data;
+	struct status_change *sc, *tsc;
 	int race, ele, damage,rdamage=0;
 	struct Damage wd;
 
@@ -2996,9 +2986,14 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 	if (target->type == BL_PC)
 		tsd = (struct map_session_data *)target;
 
-	sc_data = status_get_sc_data(src);
-	tsc_data = status_get_sc_data(target);
+	sc = status_get_sc(src);
+	tsc = status_get_sc(target);
 
+	if (sc && !sc->count) //Avoid sc checks when there's none to check for. [Skotlex]
+		sc = NULL;
+	if (tsc && !tsc->count)
+		tsc = NULL;
+	
 	race = status_get_race(target);
 	ele = status_get_elem_type(target);
 
@@ -3014,10 +3009,10 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 	}
 
 	//Check for counter attacks that block your attack. [Skotlex]
-	if(tsc_data)
+	if(tsc)
 	{
-		if(tsc_data[SC_AUTOCOUNTER].timer != -1 &&
-			(!sc_data || sc_data[SC_AUTOCOUNTER].timer == -1) &&
+		if(tsc->data[SC_AUTOCOUNTER].timer != -1 &&
+			(!sc || sc->data[SC_AUTOCOUNTER].timer == -1) &&
 			status_check_skilluse(target, src, KN_AUTOCOUNTER, 0)
 		)	{
 			int dir = map_calc_dir(target,src->x,src->y);
@@ -3025,7 +3020,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 			int dist = distance_bl(src, target);
 			if(dist <= 0 || (!map_check_dir(dir,t_dir) && dist <= status_get_range(target)+1))
 			{
-				int skilllv = tsc_data[SC_AUTOCOUNTER].val1;
+				int skilllv = tsc->data[SC_AUTOCOUNTER].val1;
 				clif_skillcastcancel(target); //Remove the casting bar. [Skotlex]
 				clif_damage(src, target, tick, status_get_amotion(src), 1, 0, 1, 0, 0); //Display MISS.
 				status_change_end(target,SC_AUTOCOUNTER,-1);
@@ -3033,8 +3028,8 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 				return 0;
 			}
 		}
-		if (tsc_data[SC_BLADESTOP_WAIT].timer != -1 && !is_boss(src)) {
-			int skilllv = tsc_data[SC_BLADESTOP_WAIT].val1;
+		if (tsc->data[SC_BLADESTOP_WAIT].timer != -1 && !is_boss(src)) {
+			int skilllv = tsc->data[SC_BLADESTOP_WAIT].val1;
 			int duration = skill_get_time2(MO_BLADESTOP,skilllv);
 			status_change_end(target, SC_BLADESTOP_WAIT, -1);
 			clif_damage(src, target, tick, status_get_amotion(src), 1, 0, 1, 0, 0); //Display MISS.
@@ -3049,15 +3044,15 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 	if(sd && (damage = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0 && sd->status.weapon <= 16) // triple blow works with bows ^^ [celest]
 	{
 		int triple_rate= 30 - damage; //Base Rate
-		if (sc_data && sc_data[SC_SKILLRATE_UP].timer!=-1 && sc_data[SC_SKILLRATE_UP].val1 == MO_TRIPLEATTACK)
+		if (sc && sc->data[SC_SKILLRATE_UP].timer!=-1 && sc->data[SC_SKILLRATE_UP].val1 == MO_TRIPLEATTACK)
 		{
-			triple_rate+= triple_rate*(sc_data[SC_SKILLRATE_UP].val2)/100;
+			triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP].val2)/100;
 			status_change_end(src,SC_SKILLRATE_UP,-1);
 		}
 		if (rand()%100 < triple_rate) return skill_attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,damage,tick,0);
 	}
-	else if (sc_data && sc_data[SC_SACRIFICE].timer != -1)
-		return skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,sc_data[SC_SACRIFICE].val1,tick,0);
+	else if (sc && sc->data[SC_SACRIFICE].timer != -1)
+		return skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,sc->data[SC_SACRIFICE].val1,tick,0);
 			
 	wd = battle_calc_weapon_attack(src,target, 0, 0,0);
 
@@ -3096,12 +3091,12 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 		}
 	}
 
-	if (sc_data && sc_data[SC_AUTOSPELL].timer != -1 && rand()%100 < sc_data[SC_AUTOSPELL].val4) {
+	if (sc && sc->data[SC_AUTOSPELL].timer != -1 && rand()%100 < sc->data[SC_AUTOSPELL].val4) {
 		int sp = 0, f = 0;
-		int skillid = sc_data[SC_AUTOSPELL].val2;
-		int skilllv = sc_data[SC_AUTOSPELL].val3;
+		int skillid = sc->data[SC_AUTOSPELL].val2;
+		int skilllv = sc->data[SC_AUTOSPELL].val3;
 		int i = rand()%100;
-		if (sc_data[SC_SPIRIT].timer != -1 && sc_data[SC_SPIRIT].val2 == SL_SAGE)
+		if (sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_SAGE)
 			i = 0; //Max chance, no skilllv reduction. [Skotlex]
 		if (i >= 50) skilllv -= 2;
 		else if (i >= 15) skilllv--;
@@ -3177,27 +3172,27 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 	if (rdamage > 0) //By sending attack type "none" skill_additional_effect won't be invoked. [Skotlex]
 		battle_delay_damage(tick+wd.amotion, target, src, 0, 0, 0, rdamage, ATK_DEF, 0);
 
-	if (tsc_data) {
-		if (tsc_data[SC_POISONREACT].timer != -1 && 
+	if (tsc) {
+		if (tsc->data[SC_POISONREACT].timer != -1 && 
 			check_distance_bl(src, target, status_get_range(target)+1) &&
 			status_check_skilluse(target, src, TF_POISON, 0)
 		) {	//Poison React
 			if (status_get_elem_type(src) == 5) {
-				tsc_data[SC_POISONREACT].val2 = 0;
-				skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,sc_data[SC_POISONREACT].val1,tick,0);
+				tsc->data[SC_POISONREACT].val2 = 0;
+				skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,tsc->data[SC_POISONREACT].val1,tick,0);
 			} else {
 				skill_attack(BF_WEAPON,target,target,src,TF_POISON, 5, tick, flag);
-				--tsc_data[SC_POISONREACT].val2;
+				--tsc->data[SC_POISONREACT].val2;
 			}
-			if (tsc_data[SC_POISONREACT].val2 <= 0)
+			if (tsc->data[SC_POISONREACT].val2 <= 0)
 				status_change_end(target, SC_POISONREACT, -1);
 		}
-		if (tsc_data[SC_SPLASHER].timer != -1)	//殴ったので対?ロのベナムスプラッシャ?[?�ヤを解?�
+		if (tsc->data[SC_SPLASHER].timer != -1)	//殴ったので対?ロのベナムスプラッシャ?[?�ヤを解?�
 			status_change_end(target, SC_SPLASHER, -1);
 	}
 
 	//SG_FUSION hp penalty [Komurka]
-	if (sd && sc_data && sc_data[SC_FUSION].timer!=-1)
+	if (sd && sc && sc->data[SC_FUSION].timer!=-1)
 	{
 		int hp=0;
 		if(target->type == BL_PC)

+ 2 - 2
src/map/charcommand.c

@@ -561,8 +561,8 @@ int charcommand_option(
 
 	if ((pl_sd = map_nick2sd(character)) != NULL) {
 		if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can change option only to lower or same level
-			pl_sd->opt1 = opt1;
-			pl_sd->opt2 = opt2;
+			pl_sd->sc.opt1 = opt1;
+			pl_sd->sc.opt2 = opt2;
 			pc_setoption(pl_sd, opt3);
 			clif_displaymessage(fd, msg_table[58]); // Character's options changed.
 		} else {

+ 3 - 3
src/map/charsave.c

@@ -491,14 +491,14 @@ void charsave_save_scdata(int account_id, int char_id, struct status_change* sc_
 			
 	for(i = 0; i < max_sc; i++)
 	{
-		if (sc_data[i].timer == -1)
+		if (sc.data[i].timer == -1)
 			continue;
-		timer = get_timer(sc_data[i].timer);
+		timer = get_timer(sc.data[i].timer);
 		if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0)
 			continue;
 		
 		sprintf (tmp_sql, "%s ('%d','%d','%hu','%d','%d','%d','%d','%d'),", tmp_sql, account_id, char_id,
-			i, DIFF_TICK(timer->tick,tick), sc_data[i].val1, sc_data[i].val2, sc_data[i].val3, sc_data[i].val4);
+			i, DIFF_TICK(timer->tick,tick), sc.data[i].val1, sc.data[i].val2, sc.data[i].val3, sc.data[i].val4);
 		
 		count++;
 	}

+ 8 - 8
src/map/chrif.c

@@ -1148,23 +1148,23 @@ int chrif_save_scdata(struct map_session_data *sd)
 	chrif_check(-1);
 	tick = gettick();
 	
-        WFIFOHEAD(char_fd, 14 + SC_MAX*sizeof(struct status_change_data));
+	WFIFOHEAD(char_fd, 14 + SC_MAX*sizeof(struct status_change_data));
 	WFIFOW(char_fd,0) = 0x2b1c;
 	WFIFOL(char_fd,4) = sd->status.account_id;
 	WFIFOL(char_fd,8) = sd->status.char_id;
 	for (i = 0; i < SC_MAX; i++)
 	{
-		if (sd->sc_data[i].timer == -1)
+		if (sd->sc.data[i].timer == -1)
 			continue;
-		timer = get_timer(sd->sc_data[i].timer);
+		timer = get_timer(sd->sc.data[i].timer);
 		if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0)
 			continue;
 		data.tick = DIFF_TICK(timer->tick,tick); //Duration that is left before ending.
 		data.type = i;
-		data.val1 = sd->sc_data[i].val1;
-		data.val2 = sd->sc_data[i].val2;
-		data.val3 = sd->sc_data[i].val3;
-		data.val4 = sd->sc_data[i].val4;
+		data.val1 = sd->sc.data[i].val1;
+		data.val2 = sd->sc.data[i].val2;
+		data.val3 = sd->sc.data[i].val3;
+		data.val4 = sd->sc.data[i].val4;
 		memcpy(WFIFOP(char_fd,14 +count*sizeof(struct status_change_data)),
 			&data, sizeof(struct status_change_data));
 		count++;
@@ -1467,7 +1467,7 @@ int send_users_tochar(int tid, unsigned int tick, int id, int data) {
 	WFIFOW(char_fd,0) = 0x2aff;
 	for (i = 0; i < count; i++) {
 		if (all_sd[i] && 
-			!((battle_config.hide_GM_session || (all_sd[i]->status.option & OPTION_INVISIBLE)) && pc_isGM(all_sd[i])))
+			!((battle_config.hide_GM_session || (all_sd[i]->sc.option & OPTION_INVISIBLE)) && pc_isGM(all_sd[i])))
 		{
 			WFIFOL(char_fd,6+8*users) = all_sd[i]->status.account_id;
 			WFIFOL(char_fd,6+8*users+4) = all_sd[i]->status.char_id;

+ 171 - 171
src/map/clif.c

@@ -309,9 +309,9 @@ int clif_send_sub(struct block_list *bl, va_list ap)
 				//Check if hidden, better to modify the char's buffer than the
 				//given buffer to prevent intravision affecting the packet as 
 				//it's being received by everyone. [Skotlex]
-				if ((sd->special_state.intravision || sd->sc_data[SC_INTRAVISION].timer != -1 ) && bl != src_bl) {
-					short *src_option = status_get_option(src_bl);
-					if(src_option && (*src_option)&(OPTION_HIDE|OPTION_CLOAK))
+				if ((sd->special_state.intravision || sd->sc.data[SC_INTRAVISION].timer != -1 ) && bl != src_bl) {
+					struct status_change *sc = status_get_sc(src_bl);
+					if(sc && (sc->option)&(OPTION_HIDE|OPTION_CLOAK))
 					{	//optionの修正
 						switch(((unsigned short*)buf)[0])
 						{
@@ -765,7 +765,7 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) {
 	if(sd->disguise)
 		sdoption = OPTION_INVISIBLE;
 	else {
-		sdoption = sd->status.option;
+		sdoption = sd->sc.option;
 		if(sdoption&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE))
 			sdoption &= ~OPTION_FALCON;
 	}
@@ -775,8 +775,8 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) {
 	WBUFW(buf,0)=0x78;
 	WBUFL(buf,2)=sd->bl.id;
 	WBUFW(buf,6)=sd->speed;
-	WBUFW(buf,8)=sd->opt1;
-	WBUFW(buf,10)=sd->opt2;
+	WBUFW(buf,8)=sd->sc.opt1;
+	WBUFW(buf,10)=sd->sc.opt2;
 	WBUFW(buf,12)=sdoption;
 	WBUFW(buf,14)=sd->view_class;
 	WBUFW(buf,16)=sd->status.hair;
@@ -810,8 +810,8 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) {
 	WBUFW(buf,0)=0x1d8;
 	WBUFL(buf,2)=sd->bl.id;
 	WBUFW(buf,6)=sd->speed;
-	WBUFW(buf,8)=sd->opt1;
-	WBUFW(buf,10)=sd->opt2;
+	WBUFW(buf,8)=sd->sc.opt1;
+	WBUFW(buf,10)=sd->sc.opt2;
 	WBUFW(buf,12)=sdoption;
 	WBUFW(buf,14)=sd->view_class;
 	WBUFW(buf,16)=sd->status.hair;
@@ -832,7 +832,7 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) {
 	WBUFL(buf,34)=sd->status.guild_id;
 	WBUFW(buf,38)=sd->guild_emblem_id;
 	WBUFW(buf,40)=sd->status.manner;
-	WBUFW(buf,42)=sd->opt3;
+	WBUFW(buf,42)=sd->sc.opt3;
 	WBUFB(buf,44)=sd->status.karma;
 	WBUFB(buf,45)=sd->sex;
 	WBUFPOS(buf,46,sd->bl.x,sd->bl.y);
@@ -858,7 +858,7 @@ static int clif_dis0078(struct map_session_data *sd, unsigned char *buf) {
 	WBUFW(buf,6)=sd->speed;
 	WBUFW(buf,8)=0;
 	WBUFW(buf,10)=0;
-	WBUFW(buf,12)=sd->status.option;
+	WBUFW(buf,12)=sd->sc.option;
 	WBUFW(buf,14)=sd->disguise;
 	//WBUFL(buf,34)=sd->status.guild_id;
 	//WBUFL(buf,38)=sd->guild_emblem_id;
@@ -888,7 +888,7 @@ static int clif_set007b(struct map_session_data *sd,unsigned char *buf) {
 	if(sd->disguise)
 		sdoption = OPTION_INVISIBLE;
 	else {
-		sdoption = sd->status.option;
+		sdoption = sd->sc.option;
 		if(sdoption&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE))
 			sdoption &= ~OPTION_FALCON;
 	}
@@ -899,8 +899,8 @@ static int clif_set007b(struct map_session_data *sd,unsigned char *buf) {
 	WBUFW(buf,0)=0x7b;
 	WBUFL(buf,2)=sd->bl.id;
 	WBUFW(buf,6)=sd->speed;
-	WBUFW(buf,8)=sd->opt1;
-	WBUFW(buf,10)=sd->opt2;
+	WBUFW(buf,8)=sd->sc.opt1;
+	WBUFW(buf,10)=sd->sc.opt2;
 	WBUFW(buf,12)=sdoption;
 	WBUFW(buf,14)=sd->view_class;
 	WBUFW(buf,16)=sd->status.hair;
@@ -918,7 +918,7 @@ static int clif_set007b(struct map_session_data *sd,unsigned char *buf) {
 	WBUFW(buf,36)=sd->head_dir;
 	WBUFL(buf,38)=sd->status.guild_id;
 	WBUFL(buf,42)=sd->guild_emblem_id;
-	WBUFW(buf,46)=sd->opt3;
+	WBUFW(buf,46)=sd->sc.opt3;
 	WBUFB(buf,48)=sd->status.karma;
 	WBUFB(buf,49)=sd->sex;
 	WBUFPOS2(buf,50,sd->bl.x,sd->bl.y,sd->to_x,sd->to_y);
@@ -934,8 +934,8 @@ static int clif_set007b(struct map_session_data *sd,unsigned char *buf) {
 	WBUFW(buf,0)=0x1da;
 	WBUFL(buf,2)=sd->bl.id;
 	WBUFW(buf,6)=sd->speed;
-	WBUFW(buf,8)=sd->opt1;
-	WBUFW(buf,10)=sd->opt2;
+	WBUFW(buf,8)=sd->sc.opt1;
+	WBUFW(buf,10)=sd->sc.opt2;
 	WBUFW(buf,12)=sdoption;
 	WBUFW(buf,14)=sd->view_class;
 	WBUFW(buf,16)=sd->status.hair;
@@ -957,7 +957,7 @@ static int clif_set007b(struct map_session_data *sd,unsigned char *buf) {
 	WBUFL(buf,38)=sd->status.guild_id;
 	WBUFW(buf,42)=sd->guild_emblem_id;
 	WBUFW(buf,44)=sd->status.manner;
-	WBUFW(buf,46)=sd->opt3;
+	WBUFW(buf,46)=sd->sc.opt3;
 	WBUFB(buf,48)=sd->status.karma;
 	WBUFB(buf,49)=sd->sex;
 	WBUFPOS2(buf,50,sd->bl.x,sd->bl.y,sd->to_x,sd->to_y);
@@ -982,7 +982,7 @@ static int clif_dis007b(struct map_session_data *sd,unsigned char *buf) {
 	WBUFW(buf,6)=sd->speed;
 	WBUFW(buf,8)=0;
 	WBUFW(buf,10)=0;
-	WBUFW(buf,12)=sd->status.option;
+	WBUFW(buf,12)=sd->sc.option;
 	WBUFW(buf,14)=sd->disguise;
 	WBUFL(buf,22)=gettick();
 	//WBUFL(buf,38)=sd->status.guild_id;
@@ -1074,9 +1074,9 @@ static int clif_mob0078(struct mob_data *md, unsigned char *buf)
 		WBUFW(buf,0)=0x78;
 		WBUFL(buf,2)=md->bl.id;
 		WBUFW(buf,6)=status_get_speed(&md->bl);
-		WBUFW(buf,8)=md->opt1;
-		WBUFW(buf,10)=md->opt2;
-		WBUFW(buf,12)=md->option;
+		WBUFW(buf,8)=md->sc.opt1;
+		WBUFW(buf,10)=md->sc.opt2;
+		WBUFW(buf,12)=md->sc.option;
 		WBUFW(buf,14)=view_class;
 		WBUFW(buf,16)=mob_get_hair(md->class_);
 		WBUFW(buf,18)=mob_get_weapon(md->class_);
@@ -1091,7 +1091,7 @@ static int clif_mob0078(struct mob_data *md, unsigned char *buf)
 			WBUFL(buf,34)=md->guardian_data->guild_id;
 			WBUFL(buf,38)=md->guardian_data->emblem_id;
 		}
-		WBUFW(buf,42)=md->opt3;
+		WBUFW(buf,42)=md->sc.opt3;
 		WBUFB(buf,44)=0; // karma
 		WBUFB(buf,45)=mob_get_sex(md->class_);
 		WBUFPOS(buf,46,md->bl.x,md->bl.y);
@@ -1109,9 +1109,9 @@ static int clif_mob0078(struct mob_data *md, unsigned char *buf)
 		WBUFW(buf,0)=0x1d8;
 		WBUFL(buf,2)=md->bl.id;
 		WBUFW(buf,6)=status_get_speed(&md->bl);
-		WBUFW(buf,8)=md->opt1;
-		WBUFW(buf,10)=md->opt2;
-		WBUFW(buf,12)=md->option;
+		WBUFW(buf,8)=md->sc.opt1;
+		WBUFW(buf,10)=md->sc.opt2;
+		WBUFW(buf,12)=md->sc.option;
 		WBUFW(buf,14)=view_class;
 		WBUFW(buf,16)=mob_get_hair(md->class_);
 		WBUFW(buf,18)=mob_get_weapon(md->class_);
@@ -1125,7 +1125,7 @@ static int clif_mob0078(struct mob_data *md, unsigned char *buf)
 		WBUFL(buf,34)=0; // guild id
 		WBUFW(buf,38)=0; // emblem id
 		WBUFW(buf,40)=0; // manner
-		WBUFW(buf,42)=md->opt3;
+		WBUFW(buf,42)=md->sc.opt3;
 		WBUFB(buf,44)=0; // karma
 		WBUFB(buf,45)=mob_get_sex(md->class_);
 		WBUFPOS(buf,46,md->bl.x,md->bl.y);
@@ -1144,9 +1144,9 @@ static int clif_mob0078(struct mob_data *md, unsigned char *buf)
 		WBUFW(buf,0)=0x78;
 		WBUFL(buf,2)=md->bl.id;
 		WBUFW(buf,6)=status_get_speed(&md->bl);
-		WBUFW(buf,8)=md->opt1;
-		WBUFW(buf,10)=md->opt2;
-		WBUFW(buf,12)=md->option;
+		WBUFW(buf,8)=md->sc.opt1;
+		WBUFW(buf,10)=md->sc.opt2;
+		WBUFW(buf,12)=md->sc.option;
 		WBUFW(buf,14)=view_class;
 		if (md->guardian_data && md->guardian_data->guild_id) { // Added guardian emblems [Valaris]
 			WBUFL(buf,34)=md->guardian_data->guild_id;
@@ -1180,9 +1180,9 @@ static int clif_mob007b(struct mob_data *md, unsigned char *buf) {
 		WBUFW(buf,0)=0x7b;
 		WBUFL(buf,2)=md->bl.id;
 		WBUFW(buf,6)=status_get_speed(&md->bl);
-		WBUFW(buf,8)=md->opt1;
-		WBUFW(buf,10)=md->opt2;
-		WBUFW(buf,12)=md->option;
+		WBUFW(buf,8)=md->sc.opt1;
+		WBUFW(buf,10)=md->sc.opt2;
+		WBUFW(buf,12)=md->sc.option;
 		WBUFW(buf,14)=view_class;
 		WBUFW(buf,16)=mob_get_hair(md->class_);
 		WBUFW(buf,18)=mob_get_weapon(md->class_);
@@ -1198,7 +1198,7 @@ static int clif_mob007b(struct mob_data *md, unsigned char *buf) {
 			WBUFL(buf,38)=md->guardian_data->guild_id;
 			WBUFL(buf,42)=md->guardian_data->emblem_id;
 		}
-		WBUFW(buf,46)=md->opt3;
+		WBUFW(buf,46)=md->sc.opt3;
 		WBUFB(buf,48)=0; // karma
 		WBUFB(buf,49)=mob_get_sex(md->class_);
 		WBUFPOS2(buf,50,md->bl.x,md->bl.y,md->to_x,md->to_y);
@@ -1215,9 +1215,9 @@ static int clif_mob007b(struct mob_data *md, unsigned char *buf) {
 		WBUFW(buf,0)=0x1da;
 		WBUFL(buf,2)=md->bl.id;
 		WBUFW(buf,6)=status_get_speed(&md->bl);
-		WBUFW(buf,8)=md->opt1;
-		WBUFW(buf,10)=md->opt2;
-		WBUFW(buf,12)=md->option;
+		WBUFW(buf,8)=md->sc.opt1;
+		WBUFW(buf,10)=md->sc.opt2;
+		WBUFW(buf,12)=md->sc.option;
 		WBUFW(buf,14)=view_class;
 		WBUFW(buf,16)=mob_get_hair(md->class_);
 		WBUFW(buf,18)=mob_get_weapon(md->class_);
@@ -1234,7 +1234,7 @@ static int clif_mob007b(struct mob_data *md, unsigned char *buf) {
 			WBUFW(buf,42)=md->guardian_data->emblem_id;
 		}
 		WBUFW(buf,44)=0; // manner
-		WBUFW(buf,46)=md->opt3;
+		WBUFW(buf,46)=md->sc.opt3;
 		WBUFB(buf,48)=0; // karma
 		WBUFB(buf,49)=mob_get_sex(md->class_);
 		WBUFPOS2(buf,50,md->bl.x,md->bl.y,md->to_x,md->to_y);
@@ -1252,9 +1252,9 @@ static int clif_mob007b(struct mob_data *md, unsigned char *buf) {
 		WBUFW(buf,0)=0x7b;
 		WBUFL(buf,2)=md->bl.id;
 		WBUFW(buf,6)=status_get_speed(&md->bl);
-		WBUFW(buf,8)=md->opt1;
-		WBUFW(buf,10)=md->opt2;
-		WBUFW(buf,12)=md->option;
+		WBUFW(buf,8)=md->sc.opt1;
+		WBUFW(buf,10)=md->sc.opt2;
+		WBUFW(buf,12)=md->sc.option;
 		WBUFW(buf,14)=view_class;
 		WBUFL(buf,22)=gettick();
 		if (md->guardian_data && md->guardian_data->guild_id) { // Added guardian emblems [Valaris]
@@ -1296,9 +1296,9 @@ static int clif_npc0078(struct npc_data *nd, unsigned char *buf) {
 		WBUFW(buf,0)=0x78;
 		WBUFL(buf,2)=nd->bl.id;
 		WBUFW(buf,6)=nd->speed;
-		WBUFW(buf,8)=nd->opt1;
-		WBUFW(buf,10)=nd->opt2;
-		WBUFW(buf,12)=nd->option;
+		WBUFW(buf,8)=nd->sc.opt1;
+		WBUFW(buf,10)=nd->sc.opt2;
+		WBUFW(buf,12)=nd->sc.option;
 		WBUFW(buf,14)=view_class;
 		WBUFW(buf,16)=mob_get_hair(nd->class_);
 		WBUFW(buf,18)=mob_get_weapon(nd->class_);
@@ -1313,7 +1313,7 @@ static int clif_npc0078(struct npc_data *nd, unsigned char *buf) {
 			WBUFL(buf,34)=g->guild_id;
 			WBUFL(buf,38)=g->emblem_id;
 		}
-		WBUFW(buf,42)=nd->opt3;
+		WBUFW(buf,42)=nd->sc.opt3;
 		WBUFB(buf,44)=0; // karma
 		WBUFB(buf,45)=mob_get_sex(nd->class_);
 		WBUFPOS(buf,46,nd->bl.x,nd->bl.y);
@@ -1331,9 +1331,9 @@ static int clif_npc0078(struct npc_data *nd, unsigned char *buf) {
 		WBUFW(buf,0)=0x1d8;
 		WBUFL(buf,2)=nd->bl.id;
 		WBUFW(buf,6)=nd->speed;
-		WBUFW(buf,8)=nd->opt1;
-		WBUFW(buf,10)=nd->opt2;
-		WBUFW(buf,12)=nd->option;
+		WBUFW(buf,8)=nd->sc.opt1;
+		WBUFW(buf,10)=nd->sc.opt2;
+		WBUFW(buf,12)=nd->sc.option;
 		WBUFW(buf,14)=view_class;
 		WBUFW(buf,16)=mob_get_hair(nd->class_);
 		WBUFW(buf,18)=mob_get_weapon(nd->class_);
@@ -1347,7 +1347,7 @@ static int clif_npc0078(struct npc_data *nd, unsigned char *buf) {
 		WBUFL(buf,34)=0; // guild id
 		WBUFW(buf,38)=0; // emblem id
 		WBUFW(buf,40)=0; // manner
-		WBUFW(buf,42)=nd->opt3;
+		WBUFW(buf,42)=nd->sc.opt3;
 		WBUFB(buf,44)=0; // karma
 		WBUFB(buf,45)=mob_get_sex(nd->class_);
 		WBUFPOS(buf,46,nd->bl.x,nd->bl.y);
@@ -1400,9 +1400,9 @@ static int clif_npc007b(struct npc_data *nd, unsigned char *buf) {
 		WBUFW(buf,0)=0x7b;
 		WBUFL(buf,2)=nd->bl.id;
 		WBUFW(buf,6)=nd->speed;
-		WBUFW(buf,8)=nd->opt1;
-		WBUFW(buf,10)=nd->opt2;
-		WBUFW(buf,12)=nd->option;
+		WBUFW(buf,8)=nd->sc.opt1;
+		WBUFW(buf,10)=nd->sc.opt2;
+		WBUFW(buf,12)=nd->sc.option;
 		WBUFW(buf,14)=view_class;
 		WBUFW(buf,16)=mob_get_hair(nd->class_);
 		WBUFW(buf,18)=mob_get_weapon(nd->class_);
@@ -1418,7 +1418,7 @@ static int clif_npc007b(struct npc_data *nd, unsigned char *buf) {
 			WBUFL(buf,38)=g->guild_id;
 			WBUFL(buf,42)=g->emblem_id;
 		}
-		WBUFW(buf,46)=nd->opt3;
+		WBUFW(buf,46)=nd->sc.opt3;
 		WBUFB(buf,48)=0; // karma
 		WBUFB(buf,49)=mob_get_sex(nd->class_);
 		WBUFPOS2(buf,50,nd->bl.x,nd->bl.y,nd->to_x,nd->to_y);
@@ -1435,9 +1435,9 @@ static int clif_npc007b(struct npc_data *nd, unsigned char *buf) {
 		WBUFW(buf,0)=0x1da;
 		WBUFL(buf,2)=nd->bl.id;
 		WBUFW(buf,6)=nd->speed;
-		WBUFW(buf,8)=nd->opt1;
-		WBUFW(buf,10)=nd->opt2;
-		WBUFW(buf,12)=nd->option;
+		WBUFW(buf,8)=nd->sc.opt1;
+		WBUFW(buf,10)=nd->sc.opt2;
+		WBUFW(buf,12)=nd->sc.option;
 		WBUFW(buf,14)=view_class;
 		WBUFW(buf,16)=mob_get_hair(nd->class_);
 		WBUFW(buf,18)=mob_get_weapon(nd->class_);
@@ -1454,7 +1454,7 @@ static int clif_npc007b(struct npc_data *nd, unsigned char *buf) {
 			WBUFW(buf,42)=g->emblem_id;
 		}
 		WBUFW(buf,44)=0; // manner
-		WBUFW(buf,46)=nd->opt3;
+		WBUFW(buf,46)=nd->sc.opt3;
 		WBUFB(buf,48)=0; // karma
 		WBUFB(buf,49)=mob_get_sex(nd->class_);
 		WBUFPOS2(buf,50,nd->bl.x,nd->bl.y,nd->to_x,nd->to_y);
@@ -1812,7 +1812,7 @@ int clif_spawnpc(struct map_session_data *sd) {
 		WBUFW(buf,0)=0x7c;
 		WBUFL(buf,2)=-sd->bl.id;
 		WBUFW(buf,6)=sd->speed;
-		WBUFW(buf,12)=sd->status.option;
+		WBUFW(buf,12)=sd->sc.option;
 		WBUFW(buf,20)=sd->disguise;
 		WBUFPOS(buf,36,sd->bl.x,sd->bl.y);
 		clif_send(buf,packet_len_table[0x7c],&sd->bl,AREA);
@@ -1934,9 +1934,9 @@ int clif_spawnmob(struct mob_data *md)
 		WBUFW(buf,0)=0x7c;
 		WBUFL(buf,2)=md->bl.id;
 		WBUFW(buf,6)=md->speed;
-		WBUFW(buf,8)=md->opt1;
-		WBUFW(buf,10)=md->opt2;
-		WBUFW(buf,12)=md->option;
+		WBUFW(buf,8)=md->sc.opt1;
+		WBUFW(buf,10)=md->sc.opt2;
+		WBUFW(buf,12)=md->sc.option;
 		WBUFW(buf,20)=viewclass;
 		WBUFPOS(buf,36,md->bl.x,md->bl.y);
 		clif_send(buf,packet_len_table[0x7c],&md->bl,AREA);
@@ -3548,11 +3548,10 @@ int clif_misceffect2(struct block_list *bl, int type) {
 int clif_changeoption(struct block_list* bl)
 {
 	unsigned char buf[32];
-	short option;
+	struct status_change *sc;
 
 	nullpo_retr(0, bl);
-
-	option = *status_get_option(bl);
+	sc = status_get_sc(bl);
 
 	WBUFW(buf,0) = 0x119;
 	if(bl->type==BL_PC && ((struct map_session_data *)bl)->disguise) {
@@ -3565,14 +3564,14 @@ int clif_changeoption(struct block_list* bl)
 		WBUFL(buf,2) = -bl->id;
 		WBUFW(buf,6) = 0;
 		WBUFW(buf,8) = 0;
-		WBUFW(buf,10) = option;
+		WBUFW(buf,10) = sc?sc->option:0;
 		WBUFB(buf,12) = 0;
 		clif_send(buf,packet_len_table[0x119],bl,AREA);
 	} else {
 		WBUFL(buf,2) = bl->id;
-		WBUFW(buf,6) = *status_get_opt1(bl);
-		WBUFW(buf,8) = *status_get_opt2(bl);
-		WBUFW(buf,10) = option;
+		WBUFW(buf,6) = sc?sc->opt1:0;
+		WBUFW(buf,8) = sc?sc->opt2:0;
+		WBUFW(buf,10) = sc?sc->option:0;
 		WBUFB(buf,12) = 0;	// ??
 		clif_send(buf,packet_len_table[0x119],bl,AREA);
 	}
@@ -4370,21 +4369,21 @@ static int clif_calc_delay(struct block_list *dst, int type, int delay)
 int clif_damage(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,int type,int damage2)
 {
 	unsigned char buf[256];
-	struct status_change *sc_data;
+	struct status_change *sc;
 
 	nullpo_retr(0, src);
 	nullpo_retr(0, dst);
 
 	type = clif_calc_delay(dst, type, ddelay); //Type defaults to 0 for normal attacks.
 
-	sc_data = status_get_sc_data(dst);
+	sc = status_get_sc(dst);
 
-	if(sc_data) {
-		if(sc_data[SC_HALLUCINATION].timer != -1) {
+	if(sc && sc->count) {
+		if(sc->data[SC_HALLUCINATION].timer != -1) {
 			if(damage > 0)
-				damage = damage*(5+sc_data[SC_HALLUCINATION].val1) + rand()%100;
+				damage = damage*(5+sc->data[SC_HALLUCINATION].val1) + rand()%100;
 			if(damage2 > 0)
-				damage2 = damage2*(5+sc_data[SC_HALLUCINATION].val1) + rand()%100;
+				damage2 = damage2*(5+sc->data[SC_HALLUCINATION].val1) + rand()%100;
 		}
 	}
 
@@ -5097,17 +5096,17 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,
 	unsigned int tick,int sdelay,int ddelay,int damage,int div,int skill_id,int skill_lv,int type)
 {
 	unsigned char buf[64];
-	struct status_change *sc_data;
+	struct status_change *sc;
 
 	nullpo_retr(0, src);
 	nullpo_retr(0, dst);
 	
 	type = clif_calc_delay(dst, (type>0)?type:skill_get_hit(skill_id), ddelay);
-	sc_data = status_get_sc_data(dst);
+	sc = status_get_sc(dst);
 
-	if(sc_data) {
-		if(sc_data[SC_HALLUCINATION].timer != -1 && damage > 0)
-			damage = damage*(5+sc_data[SC_HALLUCINATION].val1) + rand()%100;
+	if(sc && sc->count) {
+		if(sc->data[SC_HALLUCINATION].timer != -1 && damage > 0)
+			damage = damage*(5+sc->data[SC_HALLUCINATION].val1) + rand()%100;
 	}
 
 #if PACKETVER < 3
@@ -5164,17 +5163,17 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst,
 	unsigned int tick,int sdelay,int ddelay,int damage,int div,int skill_id,int skill_lv,int type)
 {
 	unsigned char buf[64];
-	struct status_change *sc_data;
+	struct status_change *sc;
 
 	nullpo_retr(0, src);
 	nullpo_retr(0, dst);
 
 	type = clif_calc_delay(dst, (type>0)?type:skill_get_hit(skill_id), ddelay);
-	sc_data = status_get_sc_data(dst);
+	sc = status_get_sc(dst);
 
-	if(sc_data) {
-		if(sc_data[SC_HALLUCINATION].timer != -1 && damage > 0)
-			damage = damage*(5+sc_data[SC_HALLUCINATION].val1) + rand()%100;
+	if(sc && sc->count) {
+		if(sc->data[SC_HALLUCINATION].timer != -1 && damage > 0)
+			damage = damage*(5+sc->data[SC_HALLUCINATION].val1) + rand()%100;
 	}
 
 	WBUFW(buf,0)=0x115;
@@ -5692,7 +5691,7 @@ int clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type)
 
 		WBUFW(buf,0) = 0x19a;
 		WBUFL(buf,2) = sd->bl.id;
-		if(sd->status.option&0x46)
+		if(sd->sc.option&0x46)
 		// WTF? a -1 to an unsigned value...
 			WBUFL(buf,6) = 0xFFFFFFFF;
 		else
@@ -8061,7 +8060,6 @@ int clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd,int ty
 
 	if(type)
 		clif_GM_kickack(sd,tsd->status.account_id);
-	tsd->opt1 = tsd->opt2 = 0;
 	WFIFOHEAD(tsd->fd,packet_len_table[0x18b]);
 	WFIFOW(tsd->fd,0) = 0x18b;
 	WFIFOW(tsd->fd,2) = 0;
@@ -8757,15 +8755,6 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 	   (sd->view_class==JOB_WEDDING && !battle_config.wedding_ignorepalette) || (sd->view_class==JOB_XMAS && !battle_config.xmas_ignorepalette)))
 		clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->status.clothes_color);
 
-	/* There shouldn't be a need for this anymore because... [Skotlex]
-	 * 1. sc_data is saved and loaded now.
-	 * 2. if it fails (sc_data is not being saved?) players can just reuse the skill.
-	//if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 &&
-	if(sd->status.hp<sd->status.max_hp>>2 && sd->sc_data[SC_AUTOBERSERK].timer != -1 &&
-		(sd->sc_data[SC_PROVOKE].timer==-1 || sd->sc_data[SC_PROVOKE].val2==0 ))
-		// オートバーサーク発動
-		status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0);
-	*/
 	if(battle_config.muting_players && sd->status.manner < 0 && battle_config.manner_system)
 		status_change_start(&sd->bl,SC_NOCHAT,0,0,0,0,0,0);
 
@@ -8861,7 +8850,7 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) {
 	if (!pc_can_move(sd))
 		return;
 
-	if(sd->sc_data && sd->sc_data[SC_RUN].timer != -1)
+	if(sd->sc.count && sd->sc.data[SC_RUN].timer != -1)
 		return;
 
 	if (sd->invincible_timer != -1)
@@ -8893,7 +8882,7 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd) {
 	WFIFOW(fd,0) = 0x18b;
 
 	/*	Rovert's prevent logout option fixed [Valaris]	*/
-	if (sd->sc_data[SC_CLOAKING].timer==-1 && sd->sc_data[SC_HIDING].timer==-1 &&
+	if (sd->sc.data[SC_CLOAKING].timer==-1 && sd->sc.data[SC_HIDING].timer==-1 &&
 		(!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout)
 	) {
 		clif_setwaitclose(fd);
@@ -9059,10 +9048,10 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) { // S 008c <
 	}
 	
 	if ((is_atcommand(fd, sd, message, 0) != AtCommand_None) ||
-		(is_charcommand(fd, sd, message,0) != CharCommand_None) ||
-		(sd->sc_data &&
-		(sd->sc_data[SC_BERSERK].timer != -1 || //バーサーク時は会話も不可
-		sd->sc_data[SC_NOCHAT].timer != -1 ))) //チャット禁止
+		(is_charcommand(fd, sd, message,0) != CharCommand_None))
+		return;
+	if (sd->sc.count &&
+		(sd->sc.data[SC_BERSERK].timer != -1 || sd->sc.data[SC_NOCHAT].timer != -1 ))
 		return;
 
 	buf = (unsigned char*)aCallocA(RFIFOW(fd,2) + 4, sizeof(char));
@@ -9251,12 +9240,13 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) {
 		clif_clearchar_area(&sd->bl, 1);
 		return;
 	}
-	if (sd->npc_id != 0 || sd->opt1 > 0 || sd->status.option & 2 || sd->state.storage_flag ||
-		(sd->sc_data &&
-			(sd->sc_data[SC_TRICKDEAD].timer != -1 ||
-			sd->sc_data[SC_AUTOCOUNTER].timer != -1 || //オートカウンター
-			sd->sc_data[SC_BLADESTOP].timer != -1 || //白刃取り
-			sd->sc_data[SC_DANCING].timer != -1))) //ダンス中
+	if (sd->npc_id || sd->sc.opt1 || sd->sc.option&OPTION_HIDE || sd->state.storage_flag)
+		return;
+			
+	if (sd->sc.count &&
+		(sd->sc.data[SC_TRICKDEAD].timer != -1 ||
+	 	sd->sc.data[SC_AUTOCOUNTER].timer != -1 ||
+		sd->sc.data[SC_BLADESTOP].timer != -1))
 		return;
 
 	tick = gettick();
@@ -9275,9 +9265,7 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) {
 	switch(action_type) {
 	case 0x00: // once attack
 	case 0x07: // continuous attack
-		if(sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class==JOB_WEDDING)
-			return;
-		if(sd->sc_data[SC_XMAS].timer != -1 || sd->view_class==JOB_XMAS)
+		if(sd->view_class==JOB_WEDDING || sd->view_class==JOB_XMAS)
 			return;
 		if (sd->vender_id != 0)
 			return;
@@ -9295,6 +9283,11 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) {
 		if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, NV_BASIC) >= 3) {
 			if (sd->skilltimer != -1) //No sitting while casting :P
 				break;
+			if (sd->sc.count && (
+				sd->sc.data[SC_DANCING].timer != -1 ||
+				(sd->sc.data[SC_GRAVITATION].timer != -1 && sd->sc.data[SC_GRAVITATION].val3 == BCT_SELF)
+			)) //No sitting during these states neither.
+			break;
 			pc_stopattack(sd);
 			pc_stop_walking(sd, 1);
 			pc_setsit(sd);
@@ -9376,15 +9369,16 @@ void clif_parse_Wis(int fd, struct map_session_data *sd) { // S 0096 <len>.w <ni
 
 	sprintf(gm_command, "%s : %s", sd->status.name, RFIFOP(fd,28));
 	if ((is_charcommand(fd, sd, gm_command, 0) != CharCommand_None) ||
-		(is_atcommand(fd, sd, gm_command, 0) != AtCommand_None) ||
-	    (sd && sd->sc_data &&
-	     (sd->sc_data[SC_BERSERK].timer!=-1 || //バーサーク時は会話も不可
-	      sd->sc_data[SC_NOCHAT].timer != -1))) //チャット禁止
+		(is_atcommand(fd, sd, gm_command, 0) != AtCommand_None)) {
+		if(gm_command) aFree(gm_command);
+		return;
+	}
+	if (sd->sc.count &&
+		(sd->sc.data[SC_BERSERK].timer!=-1 || sd->sc.data[SC_NOCHAT].timer != -1))
 	{
 		if(gm_command) aFree(gm_command);
 		return;
 	}
-
 	if(gm_command) aFree(gm_command);
 
 	//Chat Logging type 'W' / Whisper
@@ -9449,7 +9443,7 @@ if ((strncasecmp((const char*)RFIFOP(fd,4),"NPC:",4) == 0) && (strlen((const cha
 			sd->state.mainchat = 1;
 			clif_displaymessage(fd, msg_txt(380)); // Main chat has been activated.
 		}
-		if (sd->sc_data[SC_NOCHAT].timer != -1) {
+		if (sd->sc.data[SC_NOCHAT].timer != -1) {
 			clif_displaymessage(fd, msg_txt(387));
 			return;
 		}
@@ -9477,7 +9471,7 @@ if ((strncasecmp((const char*)RFIFOP(fd,4),"NPC:",4) == 0) && (strlen((const cha
 		// otherwise, send message and answer immediatly
 		else {
 			if (dstsd->ignoreAll == 1) {
-				if (dstsd->status.option & OPTION_INVISIBLE && pc_isGM(sd) < pc_isGM(dstsd))
+				if (dstsd->sc.option & OPTION_INVISIBLE && pc_isGM(sd) < pc_isGM(dstsd))
 					clif_wis_end(fd, 1); // 1: target character is not loged in
 				else
 					clif_wis_end(fd, 3); // 3: everyone ignored by target
@@ -9547,12 +9541,14 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd) {
 	if (fitem == NULL || fitem->bl.type != BL_ITEM || fitem->bl.m != sd->bl.m)
 		return;
 	
-	if( sd->npc_id!=0 || sd->vender_id != 0 || sd->opt1 > 0 || sd->trade_partner!=0 ||
-		pc_iscloaking(sd) || pc_ischasewalk(sd) || //Disable cloaking/chasewalking characters from looting [Skotlex]
-		sd->sc_data[SC_TRICKDEAD].timer != -1 || //死んだふり
-		sd->sc_data[SC_BLADESTOP].timer != -1 || //白刃取り
-		sd->sc_data[SC_NOCHAT].timer!=-1 )	//会話禁止
-	{
+	if(sd->npc_id || sd->vender_id || sd->sc.opt1 || sd->trade_partner ||
+		pc_iscloaking(sd) || pc_ischasewalk(sd)) //Disable cloaking/chasewalking characters from looting [Skotlex]
+		return;
+	if(sd->sc.count && (
+		sd->sc.data[SC_TRICKDEAD].timer != -1 || //死んだふり
+		sd->sc.data[SC_BLADESTOP].timer != -1 || //白刃取り
+		sd->sc.data[SC_NOCHAT].timer!=-1 )	//会話禁止
+	) {
 		clif_additem(sd,0,0,6); // send fail packet! [Valaris]
 		return;
 	}
@@ -9572,9 +9568,12 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd) {
 		clif_clearchar_area(&sd->bl, 1);
 		return;
 	}
-	if (sd->npc_id != 0 || sd->vender_id != 0 || sd->opt1 > 0 || sd->trade_partner != 0 ||
-		sd->sc_data[SC_AUTOCOUNTER].timer != -1 || //オートカウンター
-		sd->sc_data[SC_BLADESTOP].timer != -1)//白刃取り
+	if (sd->npc_id || sd->vender_id || sd->sc.opt1 || sd->trade_partner)
+		return;
+	if (sd->sc.count && (
+		sd->sc.data[SC_AUTOCOUNTER].timer != -1 || //オートカウンター
+		sd->sc.data[SC_BLADESTOP].timer != -1//白刃取り
+	))
 		return;
 
 	item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2;
@@ -9593,15 +9592,22 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd) {
 		clif_clearchar_area(&sd->bl, 1);
 		return;
 	}
-	if (sd->vender_id != 0 || (sd->opt1 > 0 && sd->opt1 != OPT1_STONEWAIT) || sd->trade_partner != 0)
+	if (sd->vender_id || sd->trade_partner)
 		return;
-	if (sd->npc_id!=0 && sd->npc_id != sd->npc_item_flag) //This flag enables you to use items while in an NPC. [Skotlex]
+
+	if (sd->sc.opt1 > 0 && sd->sc.opt1 != OPT1_STONEWAIT)
 		return;
-	if (sd->sc_data[SC_TRICKDEAD].timer != -1 || //死んだふり
-		sd->sc_data[SC_BLADESTOP].timer != -1 || //白刃取り
-		sd->sc_data[SC_BERSERK].timer!=-1 ||	//バーサーク
-		sd->sc_data[SC_NOCHAT].timer!=-1 ||
-		sd->sc_data[SC_GRAVITATION].timer!=-1)	//会話禁止
+	
+	if (sd->npc_id && sd->npc_id != sd->npc_item_flag) //This flag enables you to use items while in an NPC. [Skotlex]
+		return;
+	
+	if (sd->sc.count && (
+		sd->sc.data[SC_TRICKDEAD].timer != -1 || //死んだふり
+		sd->sc.data[SC_BLADESTOP].timer != -1 || //白刃取り
+		sd->sc.data[SC_BERSERK].timer!=-1 ||	//バーサーク
+		sd->sc.data[SC_NOCHAT].timer!=-1 ||
+		sd->sc.data[SC_GRAVITATION].timer!=-1	//会話禁止
+	))
 		return;
 
 	if (sd->invincible_timer != -1)
@@ -9635,7 +9641,8 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd)
 	if(sd->vender_id != 0 || sd->trade_partner != 0)
 		return;
 	
-	if(sd->sc_data[SC_BLADESTOP].timer!=-1 || sd->sc_data[SC_BERSERK].timer!=-1 ) return;
+	if(sd->sc.data[SC_BLADESTOP].timer!=-1 || sd->sc.data[SC_BERSERK].timer!=-1 )
+		return;
 
 	if(sd->status.inventory[index].identify != 1) {		// 未鑑定
 		clif_equipitemack(sd,index,0,0);	// fail
@@ -9665,7 +9672,7 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd)
 		clif_clearchar_area(&sd->bl,1);
 		return;
 	}
-	if(sd->npc_id!=0 || sd->vender_id != 0 || sd->opt1 > 0 || sd->trade_partner != 0)
+	if(sd->npc_id!=0 || sd->vender_id != 0 || sd->sc.opt1 > 0 || sd->trade_partner != 0)
 		return;
 	index = RFIFOW(fd,2)-2;
 
@@ -9972,7 +9979,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) {
 			return;
 	} else if (DIFF_TICK(tick, sd->canact_tick) < 0 &&
 		// allow monk combos to ignore this delay [celest]
-		!(sd->sc_count && sd->sc_data[SC_COMBO].timer!=-1 &&
+		!(sd->sc.count && sd->sc.data[SC_COMBO].timer!=-1 &&
 		(skillnum == MO_EXTREMITYFIST ||
 		skillnum == MO_CHAINCOMBO ||
 		skillnum == MO_COMBOFINISH ||
@@ -9983,12 +9990,9 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) {
 		return;
 	}
 
-	if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) ||
-	    sd->sc_data[SC_BERSERK].timer != -1 || sd->sc_data[SC_NOCHAT].timer != -1 ||
-	    sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class == JOB_WEDDING ||
-	    sd->sc_data[SC_XMAS].timer != -1 || sd->view_class == JOB_XMAS)
-
+	if (sd->view_class == JOB_WEDDING || sd->view_class == JOB_XMAS)
 		return;
+	
 	if (sd->invincible_timer != -1)
 		pc_delinvincibletimer(sd);
 	
@@ -10002,10 +10006,10 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) {
 	} else {
 		sd->skillitem = sd->skillitemlv = -1;
 		if (skillnum == MO_EXTREMITYFIST) {
-			if ((sd->sc_data[SC_COMBO].timer == -1 ||
-				(sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH &&
-				sd->sc_data[SC_COMBO].val1 != CH_TIGERFIST &&
-				sd->sc_data[SC_COMBO].val1 != CH_CHAINCRUSH))) {
+			if ((sd->sc.data[SC_COMBO].timer == -1 ||
+				(sd->sc.data[SC_COMBO].val1 != MO_COMBOFINISH &&
+				sd->sc.data[SC_COMBO].val1 != CH_TIGERFIST &&
+				sd->sc.data[SC_COMBO].val1 != CH_CHAINCRUSH))) {
 				if (!sd->state.skill_flag ) {
 					sd->state.skill_flag = 1;
 					clif_skillinfo(sd, MO_EXTREMITYFIST, INF_ATTACK_SKILL, -1);
@@ -10017,8 +10021,8 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) {
 			}
 		}
 		if (skillnum == TK_JUMPKICK) {
-			if (sd->sc_data[SC_COMBO].timer == -1 ||
-				sd->sc_data[SC_COMBO].val1 != TK_JUMPKICK) {
+			if (sd->sc.data[SC_COMBO].timer == -1 ||
+				sd->sc.data[SC_COMBO].val1 != TK_JUMPKICK) {
 				if (!sd->state.skill_flag ) {
 					sd->state.skill_flag = 1;
 					clif_skillinfo(sd, TK_JUMPKICK, INF_ATTACK_SKILL, -1);
@@ -10074,11 +10078,9 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, int skilll
 		return;
 	}
 
-	if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) ||
-	    sd->sc_data[SC_BERSERK].timer != -1 || sd->sc_data[SC_NOCHAT].timer != -1 ||
-	    sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class == JOB_WEDDING || 
-	    sd->sc_data[SC_XMAS].timer != -1 || sd->view_class == JOB_XMAS)
+	if (sd->view_class == JOB_WEDDING || sd->view_class == JOB_XMAS)
 		return;
+	
 	if (sd->invincible_timer != -1)
 		pc_delinvincibletimer(sd);
 	if (sd->skillitem >= 0 && sd->skillitem == skillnum) {
@@ -10132,18 +10134,12 @@ void clif_parse_UseSkillMap(int fd,struct map_session_data *sd)
 {
 	RFIFOHEAD(fd);
 
-	if(sd->chatID) return;
-
-	if (sd->npc_id!=0 || sd->vender_id != 0 || (sd->sc_data &&
-		(sd->sc_data[SC_TRICKDEAD].timer != -1 ||
-		sd->sc_data[SC_BERSERK].timer!=-1 ||
-		sd->sc_data[SC_NOCHAT].timer!=-1 ||
-		sd->sc_data[SC_WEDDING].timer!=-1 ||
-		sd->view_class==JOB_WEDDING ||
-	      sd->sc_data[SC_XMAS].timer != -1 ||
-		sd->view_class == JOB_XMAS)))
+	if(sd->chatID || sd->npc_id || sd->vender_id)
 		return;
 
+	if (sd->view_class==JOB_WEDDING || sd->view_class == JOB_XMAS)
+		return;
+	
 	if(sd->invincible_timer != -1)
 		pc_delinvincibletimer(sd);
 
@@ -10554,10 +10550,12 @@ void clif_parse_PartyMessage(int fd, struct map_session_data *sd) {
 	RFIFOHEAD(fd);
 
 	if (is_charcommand(fd, sd, (char*)RFIFOP(fd,4), 0) != CharCommand_None ||
-		is_atcommand(fd, sd, (char*)RFIFOP(fd,4), 0) != AtCommand_None ||
-		(sd->sc_data && 
-		(sd->sc_data[SC_BERSERK].timer!=-1 ||	//バーサーク時は会話も不可
-		sd->sc_data[SC_NOCHAT].timer!=-1)))		//チャット禁止
+		is_atcommand(fd, sd, (char*)RFIFOP(fd,4), 0) != AtCommand_None)
+		return;
+	if	(sd->sc.count && (
+			sd->sc.data[SC_BERSERK].timer!=-1 ||	//バーサーク時は会話も不可
+			sd->sc.data[SC_NOCHAT].timer!=-1		//チャット禁止
+		))
 		return;
 
 	party_send_message(sd, (char*)RFIFOP(fd,4), RFIFOW(fd,2)-4);
@@ -10755,10 +10753,12 @@ void clif_parse_GuildMessage(int fd,struct map_session_data *sd) {
 	RFIFOHEAD(fd);
 
 	if (is_charcommand(fd, sd, (char*)RFIFOP(fd, 4), 0) != CharCommand_None ||
-		is_atcommand(fd, sd, (char*)RFIFOP(fd, 4), 0) != AtCommand_None ||
-		(sd->sc_data &&
-		(sd->sc_data[SC_BERSERK].timer!=-1 ||	//バーサーク時は会話も不可
-		sd->sc_data[SC_NOCHAT].timer!=-1)))		//チャット禁止
+		is_atcommand(fd, sd, (char*)RFIFOP(fd, 4), 0) != AtCommand_None)
+		return;
+	if (sd->sc.count && (
+		sd->sc.data[SC_BERSERK].timer!=-1 ||	//バーサーク時は会話も不可
+		sd->sc.data[SC_NOCHAT].timer!=-1		//チャット禁止
+	))
 		return;
 
 	guild_send_message(sd, (char*)RFIFOP(fd,4), RFIFOW(fd,2)-4);
@@ -10945,11 +10945,11 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) {
 void clif_parse_GMHide(int fd, struct map_session_data *sd) {	// Modified by [Yor]
 	if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) &&
 	    (pc_isGM(sd) >= get_atcommand_level(AtCommand_Hide))) {
-		if (sd->status.option & OPTION_INVISIBLE) {
-			sd->status.option &= ~OPTION_INVISIBLE;
+		if (sd->sc.option & OPTION_INVISIBLE) {
+			sd->sc.option &= ~OPTION_INVISIBLE;
 			clif_displaymessage(fd, "Invisible: Off.");
 		} else {
-			sd->status.option |= OPTION_INVISIBLE;
+			sd->sc.option |= OPTION_INVISIBLE;
 			clif_displaymessage(fd, "Invisible: On.");
 		}
 		clif_changeoption(&sd->bl);

+ 8 - 8
src/map/map.c

@@ -1527,16 +1527,16 @@ int map_quit(struct map_session_data *sd) {
 		skill_stop_dancing(&sd->bl);// ダンス/演奏中?
 
 		//Status that are not saved...
-		if(sd->sc_count) {
-			if(sd->sc_data[SC_HIDING].timer!=-1)
+		if(sd->sc.count) {
+			if(sd->sc.data[SC_HIDING].timer!=-1)
 				status_change_end(&sd->bl,SC_HIDING,-1);
-			if(sd->sc_data[SC_CLOAKING].timer!=-1)
+			if(sd->sc.data[SC_CLOAKING].timer!=-1)
 				status_change_end(&sd->bl,SC_CLOAKING,-1);
-			if(sd->sc_data[SC_RUN].timer!=-1)
+			if(sd->sc.data[SC_RUN].timer!=-1)
 				status_change_end(&sd->bl,SC_RUN,-1);
-			if(sd->sc_data[SC_SPURT].timer!=-1)
+			if(sd->sc.data[SC_SPURT].timer!=-1)
 				status_change_end(&sd->bl,SC_SPURT,-1);
-			if(sd->sc_data && sd->sc_data[SC_BERSERK].timer!=-1)
+			if(sd->sc.data[SC_BERSERK].timer!=-1)
 				status_change_end(&sd->bl,SC_BERSERK,-1);
 		}
 		skill_clear_unitgroup(&sd->bl);	// スキルユニットグル?プの削除
@@ -1557,7 +1557,7 @@ int map_quit(struct map_session_data *sd) {
 			status_calc_pc(sd,4);
 	//	skill_clear_unitgroup(&sd->bl);	// [Sara-chan]
 
-		if (!(sd->status.option & OPTION_INVISIBLE))
+		if (!(sd->sc.option & OPTION_INVISIBLE))
 			clif_clearchar_area(&sd->bl,2);
 
 		chrif_save_scdata(sd); //Save status changes, then clear'em out from memory. [Skotlex]
@@ -1593,7 +1593,7 @@ int map_quit(struct map_session_data *sd) {
 	} else { //Try to free some data, without saving anything (this could be invoked on map server change. [Skotlex]
 		if (sd->bl.prev != NULL)
 		{	//Remove from map...
-			if (!(sd->status.option & OPTION_INVISIBLE))
+			if (!(sd->sc.option & OPTION_INVISIBLE))
 				clif_clearchar_area(&sd->bl,2);
 			map_delblock(&sd->bl);
 		}

+ 13 - 8
src/map/map.h

@@ -305,10 +305,19 @@ struct script_regstr {
 	int index;
 	char data[256];
 };
-struct status_change {
+
+struct status_change_entry {
 	int timer;
 	int val1,val2,val3,val4;
 };
+
+struct status_change {
+	struct status_change_entry data[MAX_STATUSCHANGE];
+	short count;
+	short opt1,opt2,opt3;
+	short option;
+};
+
 struct vending {
 	short index;
 	unsigned short amount;
@@ -469,7 +478,6 @@ struct map_session_data {
 	unsigned short mapindex;
 	short to_x,to_y;
 	short speed,prev_speed;
-	short opt1,opt2,opt3;
 	unsigned char dir,head_dir;
 	unsigned int client_tick,server_tick;
 	struct walkpath_data walkpath;
@@ -664,8 +672,7 @@ struct map_session_data {
 	int regstr_num;
 	struct script_regstr *regstr;
 
-	struct status_change sc_data[MAX_STATUSCHANGE];
-	short sc_count;
+	struct status_change sc;
 	short mission_mobid; //Stores the target mob_id for TK_MISSION
 	short mission_count; //Stores the bounty kill count for TK_MISSION
 	int devotion[5]; //Stores the char IDs of chars devoted to.
@@ -754,13 +761,13 @@ struct npc_data {
 	unsigned char name[NAME_LENGTH];
 	unsigned char exname[NAME_LENGTH];
 	int chat_id;
-	short opt1,opt2,opt3,option;
 	short flag;
 	int walktimer; // [Valaris]
 	short to_x,to_y; // [Valaris]
 	struct walkpath_data walkpath;
 	unsigned int next_walktime;
 	unsigned int canmove_tick;
+	struct status_change sc; //They can't have status changes, but.. they want the visual opt values.
 
 	struct { // [Valaris]
 		unsigned state : 8;
@@ -829,7 +836,7 @@ struct mob_data {
 		unsigned alchemist: 1;
 		int provoke_flag; // Celest
 	} state;
-	struct status_change sc_data[MAX_STATUSCHANGE];
+	struct status_change sc;
 	struct walkpath_data walkpath;
 	struct guardian_data* guardian_data; 
 	struct item *lootitem;
@@ -854,8 +861,6 @@ struct mob_data {
 	unsigned int last_deadtime,last_spawntime,last_thinktime,last_linktime;
 	short move_fail_count;
 	short lootitem_count;
-	short sc_count;
-	short opt1,opt2,opt3,option;
 	short min_chase;
 	
 	int deletetimer;

+ 58 - 58
src/map/mob.c

@@ -463,19 +463,20 @@ int mob_can_move(struct mob_data *md)
 {
 	nullpo_retr(0, md);
 
-	if(DIFF_TICK(md->canmove_tick, gettick()) > 0 || md->skilltimer != -1 || (md->opt1 > 0 && md->opt1 != OPT1_STONEWAIT) || md->option&OPTION_HIDE)
+	if(DIFF_TICK(md->canmove_tick, gettick()) > 0 || md->skilltimer != -1 || (md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT) || md->sc.option&OPTION_HIDE)
 		return 0;
 	// アンクル中で動けないとか
-	if( md->sc_data[SC_ANKLE].timer != -1 || //アンクルスネア
-		md->sc_data[SC_AUTOCOUNTER].timer != -1 || //オートカウンター
-		md->sc_data[SC_BLADESTOP].timer != -1 || //白刃取り
-		md->sc_data[SC_SPIDERWEB].timer != -1 || //スパイダーウェッブ
-		(md->sc_data[SC_DANCING].timer !=-1 && md->sc_data[SC_DANCING].val1 == CG_HERMODE) || //cannot move while Hermod is active.
-		(md->sc_data[SC_GOSPEL].timer !=-1 && md->sc_data[SC_GOSPEL].val4 == BCT_SELF) ||	// cannot move while gospel is in effect
-		md->sc_data[SC_STOP].timer != -1 ||
-		md->sc_data[SC_CLOSECONFINE].timer != -1 ||
-		md->sc_data[SC_CLOSECONFINE2].timer != -1
-		)
+	if(md->sc.count && (
+		md->sc.data[SC_ANKLE].timer != -1 || //アンクルスネア
+		md->sc.data[SC_AUTOCOUNTER].timer != -1 || //オートカウンター
+		md->sc.data[SC_BLADESTOP].timer != -1 || //白刃取り
+		md->sc.data[SC_SPIDERWEB].timer != -1 || //スパイダーウェッブ
+		(md->sc.data[SC_DANCING].timer !=-1 && md->sc.data[SC_DANCING].val1 == CG_HERMODE) || //cannot move while Hermod is active.
+		(md->sc.data[SC_GOSPEL].timer !=-1 && md->sc.data[SC_GOSPEL].val4 == BCT_SELF) ||	// cannot move while gospel is in effect
+		md->sc.data[SC_STOP].timer != -1 ||
+		md->sc.data[SC_CLOSECONFINE].timer != -1 ||
+		md->sc.data[SC_CLOSECONFINE2].timer != -1
+	))
 		return 0;
 
 	return 1;
@@ -565,7 +566,7 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data)
 		map_foreachinmovearea(clif_mobinsight,md->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,-dx,-dy,BL_PC,md);
 		md->state.state=MS_IDLE;
 
-		if(md->option&OPTION_CLOAK)
+		if(md->sc.option&OPTION_CLOAK)
 			skill_check_cloaking(&md->bl);
 	}
 	if((i=calc_next_walk_step(md))>0){
@@ -733,12 +734,12 @@ static int mob_attack(struct mob_data *md,unsigned int tick,int data)
 	if( mobskill_use(md,tick,-1) )	// スキル使用
 		return 0;
 
-	if(md->sc_data && md->sc_data[SC_WINKCHARM].timer != -1)
+	if(md->sc.count && md->sc.data[SC_WINKCHARM].timer != -1)
 		clif_emotion(&md->bl, 3);
 	else
 		md->target_lv = battle_weapon_attack(&md->bl,tbl,tick,0);
 
-	if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1)
+	if(!(battle_config.monster_cloak_check_type&2) && md->sc.data[SC_CLOAKING].timer != -1)
 		status_change_end(&md->bl,SC_CLOAKING,-1);
 
 	//Mobs can't move if they can't attack neither.
@@ -941,7 +942,7 @@ int mob_walktoxy(struct mob_data *md,int x,int y,int easy)
 	md->to_x=x;
 	md->to_y=y;
 	
-	if (md->sc_data[SC_CONFUSION].timer != -1) //Randomize target direction.
+	if (md->sc.data[SC_CONFUSION].timer != -1) //Randomize target direction.
 		map_random_dir(&md->bl, &md->to_x, &md->to_y);
 	
 	if(md->state.state == MS_WALK)
@@ -1126,27 +1127,27 @@ int mob_spawn (int id)
 		md->skilltimerskill[i].timer = -1;
 
 	for (i = 0; i < MAX_STATUSCHANGE; i++) {
-		md->sc_data[i].timer = -1;
-		md->sc_data[i].val1 = md->sc_data[i].val2 = md->sc_data[i].val3 = md->sc_data[i].val4 = 0;
+		md->sc.data[i].timer = -1;
+		md->sc.data[i].val1 = md->sc.data[i].val2 = md->sc.data[i].val3 = md->sc.data[i].val4 = 0;
 	}
-	md->sc_count = 0;
-	md->opt1 = md->opt2 = md->opt3 = md->option = 0;
+	md->sc.count = 0;
+	md->sc.opt1 = md->sc.opt2 = md->sc.opt3 = md->sc.option = 0;
 
 	if(md->db->option){ // Added for carts, falcons and pecos for cloned monsters. [Valaris]
 		if(md->db->option & 0x0008)
-			md->option |= 0x0008;
+			md->sc.option |= 0x0008;
 		if(md->db->option & 0x0080)
-			md->option |= 0x0080;
+			md->sc.option |= 0x0080;
 		if(md->db->option & 0x0100)
-			md->option |= 0x0100;
+			md->sc.option |= 0x0100;
 		if(md->db->option & 0x0200)
-			md->option |= 0x0200;
+			md->sc.option |= 0x0200;
 		if(md->db->option & 0x0400)
-			md->option |= 0x0400;
+			md->sc.option |= 0x0400;
 		if(md->db->option & OPTION_FALCON)
-			md->option |= OPTION_FALCON;
+			md->sc.option |= OPTION_FALCON;
 		if(md->db->option & OPTION_RIDING)
-			md->option |= OPTION_RIDING;
+			md->sc.option |= OPTION_RIDING;
 	}
 
 	memset(md->skillunit, 0, sizeof(md->skillunit));
@@ -1598,10 +1599,10 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
 	}
 
 	// Abnormalities
-	if((md->opt1 > 0 && md->opt1 != OPT1_STONEWAIT) || md->state.state == MS_DELAY || md->sc_data[SC_BLADESTOP].timer != -1)
+	if((md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT) || md->state.state == MS_DELAY || md->sc.data[SC_BLADESTOP].timer != -1)
 		return 0;
 
-	if (md->sc_data && md->sc_data[SC_BLIND].timer != -1)
+	if (md->sc.count && md->sc.data[SC_BLIND].timer != -1)
 		blind_flag = 1;
 
 	mode = status_get_mode(&md->bl);
@@ -2210,9 +2211,13 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
 		return 0;
 	}
 
-	if(md->sc_count) {
-		if(md->sc_data[SC_CONFUSION].timer != -1)
+	if(md->sc.count) {
+		if(md->sc.data[SC_CONFUSION].timer != -1)
 			status_change_end(&md->bl, SC_CONFUSION, -1);
+		if(md->sc.data[SC_HIDING].timer != -1)
+			status_change_end(&md->bl, SC_HIDING, -1);
+		if(md->sc.data[SC_CLOAKING].timer != -1)
+			status_change_end(&md->bl, SC_CLOAKING, -1);
 	}
 
 	if(damage > max_hp>>2)
@@ -2297,11 +2302,6 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
 		}
 	}	// end addition
 
-	if(md->option&OPTION_HIDE)
-		status_change_end(&md->bl, SC_HIDING, -1);
-	if(md->option&OPTION_CLOAK)
-		status_change_end(&md->bl, SC_CLOAKING, -1);
-
 	if(md->special_state.ai == 2 &&	//スフィアーマイン
 		src && md->master_id == src->id)
 	{
@@ -2317,11 +2317,11 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
 		return damage;
 
 		//Not the most correct way ever, but this is totally custom anyway.... [Skotlex]
-	if (md->sc_data[SC_KAIZEL].timer != -1) {
+	if (md->sc.data[SC_KAIZEL].timer != -1) {
 		max_hp = status_get_max_hp(&md->bl);
-		mob_heal(md, 10*md->sc_data[SC_KAIZEL].val1*max_hp/100);
+		mob_heal(md, 10*md->sc.data[SC_KAIZEL].val1*max_hp/100);
 		clif_resurrection(&md->bl, 1);
-		status_change_start(&md->bl,SkillStatusChangeTable[SL_KAIZEL],10,0,0,0,skill_get_time2(SL_KAIZEL, md->sc_data[SC_KAIZEL].val1),0);
+		status_change_start(&md->bl,SkillStatusChangeTable[SL_KAIZEL],10,0,0,0,skill_get_time2(SL_KAIZEL, md->sc.data[SC_KAIZEL].val1),0);
 		status_change_end(&md->bl,SC_KAIZEL,-1);
 		return damage;
 	}
@@ -2332,7 +2332,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
 
 	//changestate will clear all status effects, so we need to know if RICHMANKIM is in effect before then. [Skotlex]
 	//I just recycled ret because it isn't used until much later and I didn't want to add a new variable for it.
-	ret = (md->sc_data[SC_RICHMANKIM].timer != -1)?(25 + 11*md->sc_data[SC_RICHMANKIM].val1):0;
+	ret = (md->sc.data[SC_RICHMANKIM].timer != -1)?(25 + 11*md->sc.data[SC_RICHMANKIM].val1):0;
 	
 	map_freeblock_lock();
 	mob_changestate(md,MS_DEAD,0);
@@ -2990,22 +2990,22 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type)
 	if(type >= 0) {
 		if(map[md->bl.m].flag.monster_noteleport)
 			return 0;
-		if(md->sc_count) { //Clear a few status changes (taken directly from pc_setpos). [Skotlex]
-			if(md->sc_data[SC_TRICKDEAD].timer != -1)
+		if(md->sc.count) { //Clear a few status changes (taken directly from pc_setpos). [Skotlex]
+			if(md->sc.data[SC_TRICKDEAD].timer != -1)
 				status_change_end(&md->bl, SC_TRICKDEAD, -1);
-			if(md->sc_data[SC_BLADESTOP].timer!=-1)
+			if(md->sc.data[SC_BLADESTOP].timer!=-1)
 				status_change_end(&md->bl,SC_BLADESTOP,-1);
-			if(md->sc_data && md->sc_data[SC_RUN].timer!=-1)
+			if(md->sc.data && md->sc.data[SC_RUN].timer!=-1)
 				status_change_end(&md->bl,SC_RUN,-1);
-			if(md->sc_data[SC_DANCING].timer!=-1)
+			if(md->sc.data[SC_DANCING].timer!=-1)
 				skill_stop_dancing(&md->bl);
-			if (md->sc_data[SC_DEVOTION].timer!=-1)
+			if (md->sc.data[SC_DEVOTION].timer!=-1)
 				status_change_end(&md->bl,SC_DEVOTION,-1);
-			if (md->sc_data[SC_CLOSECONFINE].timer!=-1)
+			if (md->sc.data[SC_CLOSECONFINE].timer!=-1)
 				status_change_end(&md->bl,SC_CLOSECONFINE,-1);
-			if (md->sc_data[SC_CLOSECONFINE2].timer!=-1)
+			if (md->sc.data[SC_CLOSECONFINE2].timer!=-1)
 				status_change_end(&md->bl,SC_CLOSECONFINE2,-1);
-			if (md->sc_data[SC_RUN].timer!=-1)
+			if (md->sc.data[SC_RUN].timer!=-1)
 				status_change_end(&md->bl,SC_RUN,-1);
 		}
 		clif_clearchar_area(&md->bl,type);
@@ -3269,7 +3269,7 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
 		break;
 	}
 
-	if (md->sc_count && md->sc_data[SC_MAGICPOWER].timer != -1 && md->skillid != HW_MAGICPOWER)
+	if (md->sc.count && md->sc.data[SC_MAGICPOWER].timer != -1 && md->skillid != HW_MAGICPOWER)
 		status_change_end(&md->bl, SC_MAGICPOWER, -1);
 		
 	if (md->db->skill[md->skillidx].emotion >= 0)
@@ -3398,7 +3398,7 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
 	if(!status_check_skilluse(&md->bl, target, skill_id, 0))
 		return 0;
 
-	if(md->sc_data && md->sc_data[SC_WINKCHARM].timer != -1 && target->type == BL_PC) {
+	if(md->sc.count && md->sc.data[SC_WINKCHARM].timer != -1 && target->type == BL_PC) {
 		clif_emotion(&md->bl, 3);
 		return 0;
 	}
@@ -3457,7 +3457,7 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
 	md->skilllv		= skill_lv;
 	md->skillidx	= skill_idx;
 
-	if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1 && md->skillid != AS_CLOAKING)
+	if(!(battle_config.monster_cloak_check_type&2) && md->sc.data[SC_CLOAKING].timer != -1 && md->skillid != AS_CLOAKING)
 		status_change_end(&md->bl,SC_CLOAKING,-1);
 
 	if( casttime>0 ){
@@ -3529,7 +3529,7 @@ int mobskill_use_pos( struct mob_data *md,
 	md->skillid		= skill_id;
 	md->skilllv		= skill_lv;
 	md->skillidx	= skill_idx;
-	if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1)
+	if(!(battle_config.monster_cloak_check_type&2) && md->sc.data[SC_CLOAKING].timer != -1)
 		status_change_end(&md->bl,SC_CLOAKING,-1);
 	if( casttime>0 ){
 		md->skilltimer =
@@ -3627,11 +3627,11 @@ int mob_getfriendstatus_sub(struct block_list *bl,va_list ap)
 	if( cond2==-1 ){
 		int j;
 		for(j=SC_COMMON_MIN;j<=SC_COMMON_MAX && !flag;j++){
-			if ((flag=(md->sc_data[j].timer!=-1))) //Once an effect was found, break out. [Skotlex]
+			if ((flag=(md->sc.data[j].timer!=-1))) //Once an effect was found, break out. [Skotlex]
 				break;
 		}
 	}else
-		flag=( md->sc_data[cond2].timer!=-1 );
+		flag=( md->sc.data[cond2].timer!=-1 );
 	if( flag^( cond1==MSC_FRIENDSTATUSOFF ) )
 		(*fr)=md;
 
@@ -3697,15 +3697,15 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
 					}
 				case MSC_MYSTATUSON:		// status[num] on
 				case MSC_MYSTATUSOFF:		// status[num] off
-					if (!md->sc_data) {
+					if (!md->sc.count) {
 						flag = 0;
 					} else if (ms[i].cond2 == -1) {
 						int j;
 						for (j = SC_COMMON_MIN; j <= SC_COMMON_MAX; j++)
-							if ((flag = (md->sc_data[j].timer != -1)) != 0)
+							if ((flag = (md->sc.data[j].timer != -1)) != 0)
 								break;
 					} else {
-						flag = (md->sc_data[ms[i].cond2].timer != -1);
+						flag = (md->sc.data[ms[i].cond2].timer != -1);
 					}
 					flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF); break;
 				case MSC_FRIENDHPLTMAXRATE:	// friend HP < maxhp%
@@ -3961,7 +3961,7 @@ int mob_clone_spawn(struct map_session_data *sd, char *map, int x, int y, const
 	mob_db_data[class_]->head_top=sd->status.head_top;
 	mob_db_data[class_]->head_mid=sd->status.head_mid;
 	mob_db_data[class_]->head_buttom=sd->status.head_bottom;
-	mob_db_data[class_]->option=sd->status.option;
+	mob_db_data[class_]->option=sd->sc.option;
 	mob_db_data[class_]->clothes_color=sd->status.clothes_color;
 
 	//Skill copy [Skotlex]

+ 7 - 7
src/map/npc.c

@@ -104,11 +104,11 @@ int npc_enable(const char *name,int flag)
 		clif_spawnnpc(nd);
 	}else if (flag&2){
 		nd->flag&=~1;
-		nd->option = 0x0000;
+		nd->sc.option = 0x0000;
 		clif_changeoption(&nd->bl);
 	}else if (flag&4){
 		nd->flag|=1;
-		nd->option = 0x0002;
+		nd->sc.option = 0x0002;
 		clif_changeoption(&nd->bl);
 	}else{		// –³Œø‰»
 		nd->flag|=1;
@@ -794,7 +794,7 @@ int npc_touch_areanpc(struct map_session_data *sd,int m,int x,int y)
 	switch(map[m].npc[i]->bl.subtype) {
 		case WARP:
 			// hidden chars cannot use warps -- is it the same for scripts too?
-			if (sd->status.option&6 ||
+			if (sd->sc.option&6 ||
 				(!battle_config.duel_allow_teleport && sd->duel_group)) // duel rstrct [LuzZza]
 				break;
 			skill_stop_dancing(&sd->bl);
@@ -1950,10 +1950,10 @@ static int npc_parse_script (char *w1,char *w2,char *w3,char *w4,char *first_lin
 	nd->u.scr.src_id = src_id;
 /* Cleaned up above with memset...
 	nd->chat_id = 0;
-	nd->option = 0;
-	nd->opt1 = 0;
-	nd->opt2 = 0;
-	nd->opt3 = 0;
+	nd->sc.option = 0;
+	nd->sc.opt1 = 0;
+	nd->sc.opt2 = 0;
+	nd->sc.opt3 = 0;
 */
 	nd->walktimer = -1;
 

+ 181 - 164
src/map/pc.c

@@ -352,24 +352,31 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) {
  */
 int pc_can_move(struct map_session_data *sd)
 {
-	if (sd->canmove_tick > gettick() || (sd->opt1 > 0 && sd->opt1 != OPT1_STONEWAIT) ||
-		sd->sc_data[SC_ANKLE].timer != -1 ||
-   	sd->sc_data[SC_AUTOCOUNTER].timer !=-1 ||
-		sd->sc_data[SC_TRICKDEAD].timer !=-1 ||
-		sd->sc_data[SC_BLADESTOP].timer !=-1 ||
-		sd->sc_data[SC_SPIDERWEB].timer !=-1 ||
-		(sd->sc_data[SC_DANCING].timer !=-1 && sd->sc_data[SC_DANCING].val4 && sd->sc_data[SC_LONGING].timer == -1) ||
-		(sd->sc_data[SC_DANCING].timer !=-1 && sd->sc_data[SC_DANCING].val1 == CG_HERMODE) || //cannot move while Hermod is active.
-		(sd->sc_data[SC_GOSPEL].timer !=-1 && sd->sc_data[SC_GOSPEL].val4 == BCT_SELF) ||	// cannot move while gospel is in effect
-		sd->sc_data[SC_STOP].timer != -1 ||
-		sd->sc_data[SC_CLOSECONFINE].timer != -1 ||
-		sd->sc_data[SC_CLOSECONFINE2].timer != -1
-		)
+	
+	if (sd->sc.opt1 > 0 && sd->sc.opt1 != OPT1_STONEWAIT)
 		return 0;
 
-	if ((sd->status.option & 2) && pc_checkskill(sd, RG_TUNNELDRIVE) <= 0)
+	if ((sd->sc.option & OPTION_HIDE) && pc_checkskill(sd, RG_TUNNELDRIVE) <= 0)
+		return 0;
+	
+	if (DIFF_TICK(sd->canmove_tick, gettick()) > 0)
 		return 0;
 	
+	if (sd->sc.count && (
+		sd->sc.data[SC_ANKLE].timer != -1 ||
+   	sd->sc.data[SC_AUTOCOUNTER].timer !=-1 ||
+		sd->sc.data[SC_TRICKDEAD].timer !=-1 ||
+		sd->sc.data[SC_BLADESTOP].timer !=-1 ||
+		sd->sc.data[SC_SPIDERWEB].timer !=-1 ||
+		(sd->sc.data[SC_DANCING].timer !=-1 && sd->sc.data[SC_DANCING].val4 && sd->sc.data[SC_LONGING].timer == -1) ||
+		(sd->sc.data[SC_DANCING].timer !=-1 && sd->sc.data[SC_DANCING].val1 == CG_HERMODE) || //cannot move while Hermod is active.
+		(sd->sc.data[SC_GOSPEL].timer !=-1 && sd->sc.data[SC_GOSPEL].val4 == BCT_SELF) ||	// cannot move while gospel is in effect
+		sd->sc.data[SC_STOP].timer != -1 ||
+		sd->sc.data[SC_CLOSECONFINE].timer != -1 ||
+		sd->sc.data[SC_CLOSECONFINE2].timer != -1
+	))
+		return 0;
+
 	return 1;
 }
 
@@ -409,6 +416,7 @@ int pc_makesavestatus(struct map_session_data *sd)
 
 	// 死亡?態だったのでhpを1、位置をセ?ブ場所に?更
 	if(!sd->state.waitingdisconnect) {
+		sd->sc.option = sd->sc.option;
 		if(pc_isdead(sd)){
 			pc_setrestartvalue(sd,0);
 			memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
@@ -593,28 +601,31 @@ int pc_isequip(struct map_session_data *sd,int n)
 		return 0; 
 	if(map[sd->bl.m].zone && map[sd->bl.m].flag.restricted && (item->flag.no_equip&map[sd->bl.m].zone || !pc_isAllowedCardOn(sd,item->slot,n,map[sd->bl.m].zone)))
 		return 0;
-	if((item->equip & 0x0002 || item->equip & 0x0020) && item->type == 4 && sd->sc_data[SC_STRIPWEAPON].timer != -1) // Also works with left-hand weapons [DracoRPG]
-		return 0;
-	if(item->equip & 0x0020 && item->type == 5 && sd->sc_data[SC_STRIPSHIELD].timer != -1) // Also works with left-hand weapons [DracoRPG]
-		return 0;
-	if(item->equip & 0x0010 && sd->sc_data[SC_STRIPARMOR].timer != -1)
-		return 0;
-	if(item->equip & 0x0100 && sd->sc_data[SC_STRIPHELM].timer != -1)
-		return 0;
+	if (sd->sc.count) {
+			
+		if((item->equip & 0x0002 || item->equip & 0x0020) && item->type == 4 && sd->sc.data[SC_STRIPWEAPON].timer != -1) // Also works with left-hand weapons [DracoRPG]
+			return 0;
+		if(item->equip & 0x0020 && item->type == 5 && sd->sc.data[SC_STRIPSHIELD].timer != -1) // Also works with left-hand weapons [DracoRPG]
+			return 0;
+		if(item->equip & 0x0010 && sd->sc.data[SC_STRIPARMOR].timer != -1)
+			return 0;
+		if(item->equip & 0x0100 && sd->sc.data[SC_STRIPHELM].timer != -1)
+			return 0;
 
-	if (sd->sc_data[SC_SPIRIT].timer != -1 && sd->sc_data[SC_SPIRIT].val2 == SL_SUPERNOVICE) {
-		//Spirit of Super Novice equip bonuses. [Skotlex]
-		if (sd->status.base_level > 90 && item->equip & 0x301)
-			return 1; //Can equip all helms
-		if (sd->status.base_level > 96 && item->equip & 0x022 && item->type == 4)
-			switch(item->look) { //In weapons, the look determines type of weapon.
-				case 0x01: //Level 4 Knives are equippable.. this means all knives, I'd guess?
-				case 0x02: //All 1H swords
-				case 0x06: //All 1H Axes
-				case 0x08: //All Maces
-				case 0x0a: //All Staffs
-					return 1;
-			}
+		if (sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_SUPERNOVICE) {
+			//Spirit of Super Novice equip bonuses. [Skotlex]
+			if (sd->status.base_level > 90 && item->equip & 0x301)
+				return 1; //Can equip all helms
+			if (sd->status.base_level > 96 && item->equip & 0x022 && item->type == 4)
+				switch(item->look) { //In weapons, the look determines type of weapon.
+					case 0x01: //Level 4 Knives are equippable.. this means all knives, I'd guess?
+					case 0x02: //All 1H swords
+					case 0x06: //All 1H Axes
+					case 0x08: //All Maces
+					case 0x0a: //All Staffs
+						return 1;
+				}
+		}
 	}
 	//Not equipable by class. [Skotlex]
 	if (!(1<<(sd->class_&MAPID_BASEMASK)&item->class_base[(sd->class_&JOBL_2_1)?1:((sd->class_&JOBL_2_2)?2:0)]))
@@ -658,7 +669,7 @@ int pc_break_equip(struct map_session_data *sd, unsigned short where)
 		default:
 			return 0;
 	}
-	if (sd->sc_count && sd->sc_data[i].timer != -1)
+	if (sd->sc.count && sd->sc.data[i].timer != -1)
 		return 0;
 
 	for (i = 0; i < 11; i++) {
@@ -755,15 +766,16 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t
 
 	// ステ?タス異常の初期化
 	for(i = 0; i < MAX_STATUSCHANGE; i++) {
-		sd->sc_data[i].timer=-1;
+		sd->sc.data[i].timer=-1;
 	}
-	sd->sc_count=0;
+	sd->sc.count=0;
 	if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) &&
 	    (pc_isGM(sd) >= get_atcommand_level(AtCommand_Hide)))
 		sd->status.option &= (OPTION_MASK | OPTION_INVISIBLE);
 	else
 		sd->status.option &= OPTION_MASK;
 
+	sd->sc.option = sd->status.option; //This is the actual option used in battle.
 	// パ?ティ??係の初期化
 	sd->party_x = -1;
 	sd->party_y = -1;
@@ -1016,7 +1028,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
 			sd->status.skill[i].flag=0;
 		}
 		else
-		if(sd->sc_data[SC_SPIRIT].timer != -1 && sd->sc_data[SC_SPIRIT].val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= DC_SERVICEFORYOU)
+		if(sd->sc.count && sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= DC_SERVICEFORYOU)
 		{ //Enable Bard/Dancer spirit linked skills.
 			if (sd->status.sex) { //Link dancer skills to bard.
 				sd->status.skill[i].id=i;
@@ -1058,7 +1070,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
 					f=0; // Do not unlock normal skills when Basic Skills is not maxed out (can happen because of skill reset)
 			}
 			if(sd->status.skill[id].id==0 ){
-				if(sd->sc_data[SC_SPIRIT].timer != -1 && skill_get_inf2(id)&INF2_SPIRIT_SKILL) { //Enable Spirit Skills. [Skotlex]
+				if(sd->sc.count && sd->sc.data[SC_SPIRIT].timer != -1 && skill_get_inf2(id)&INF2_SPIRIT_SKILL) { //Enable Spirit Skills. [Skotlex]
 					sd->status.skill[id].id=id;
 					sd->status.skill[id].lv=1;
 					sd->status.skill[id].flag=1; //So it is not saved, and tagged as a "bonus" skill.
@@ -1142,17 +1154,17 @@ int pc_checkweighticon(struct map_session_data *sd)
 		flag=2;
 
 	if(flag==1){
-		if(sd->sc_data[SC_WEIGHT50].timer==-1)
+		if(sd->sc.data[SC_WEIGHT50].timer==-1)
 			status_change_start(&sd->bl,SC_WEIGHT50,0,0,0,0,0,0);
 	}else{
-		if(sd->sc_data[SC_WEIGHT50].timer!=-1)
+		if(sd->sc.data[SC_WEIGHT50].timer!=-1)
 			status_change_end(&sd->bl,SC_WEIGHT50,-1);
 	} 
 	if(flag==2){
-		if(sd->sc_data[SC_WEIGHT90].timer==-1)
+		if(sd->sc.data[SC_WEIGHT90].timer==-1)
 			status_change_start(&sd->bl,SC_WEIGHT90,0,0,0,0,0,0);
 	}else{
-		if(sd->sc_data[SC_WEIGHT90].timer!=-1)
+		if(sd->sc.data[SC_WEIGHT90].timer!=-1)
 			status_change_end(&sd->bl,SC_WEIGHT90,-1);
 	}
 	return 0;
@@ -2789,18 +2801,26 @@ int pc_useitem(struct map_session_data *sd,int n)
 		amount = sd->status.inventory[n].amount;
 		if(sd->status.inventory[n].nameid <= 0 ||
 			sd->status.inventory[n].amount <= 0 ||
-			gettick() < sd->canuseitem_tick || //Prevent mass item usage. [Skotlex]
-			sd->sc_data[SC_BERSERK].timer!=-1 ||
-			sd->sc_data[SC_MARIONETTE].timer!=-1 ||
-			sd->sc_data[SC_GRAVITATION].timer!=-1 ||
+			DIFF_TICK(sd->canuseitem_tick, gettick()) > 0 //Prevent mass item usage. [Skotlex]
+		)
+			return 1;
+		if (sd->sc.count && (
+			sd->sc.data[SC_BERSERK].timer!=-1 ||
+			sd->sc.data[SC_MARIONETTE].timer!=-1 ||
+			sd->sc.data[SC_GRAVITATION].timer!=-1 ||
 			//Cannot use Potions/Healing items while under Gospel.
-			(sd->sc_data[SC_GOSPEL].timer!=-1 && sd->sc_data[SC_GOSPEL].val4 != BCT_SELF && sd->inventory_data[n]->type == 0) ||
-			(pc_issit(sd) && (sd->itemid == 605 || sd->itemid == 606)) ||
+			(sd->sc.data[SC_GOSPEL].timer!=-1 && sd->sc.data[SC_GOSPEL].val4 != BCT_SELF && sd->inventory_data[n]->type == 0)
+		)) {
+			clif_useitemack(sd,n,0,0);
+			return 1;
+		}		
+		if ((pc_issit(sd) && (sd->itemid == 605 || sd->itemid == 606)) ||
 			//added item_noequip.txt items check by Maya&[Lupus]
 			(map[sd->bl.m].flag.pvp && (sd->inventory_data[n]->flag.no_equip&1) ) || // PVP
 			(map_flag_gvg(sd->bl.m) && (sd->inventory_data[n]->flag.no_equip&2) ) || // GVG
 			(map[sd->bl.m].zone && map[sd->bl.m].flag.restricted && (sd->inventory_data[n]->flag.no_equip&map[sd->bl.m].zone)) || // Zone restriction
-			!pc_isUseitem(sd,n) ) {
+			!pc_isUseitem(sd,n)
+		) {
 			clif_useitemack(sd,n,0,0);
 			return 1;
 		}
@@ -2822,7 +2842,7 @@ int pc_useitem(struct map_session_data *sd,int n)
 		}
 		if(sd->status.inventory[n].card[0]==0x00fe && pc_istop10fame(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST)) {
 		    potion_flag = 2; // Famous player's potions have 50% more efficiency
-			 if (sd->sc_data[SC_SPIRIT].timer != -1 && sd->sc_data[SC_SPIRIT].val2 == SL_ROGUE)
+			 if (sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_ROGUE)
 				 potion_flag = 3; //Even more effective potions.
 		}
 		sd->canuseitem_tick= gettick() + battle_config.item_use_interval; //Update item use time.
@@ -3035,7 +3055,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl)
 	if(md->state.steal_flag || status_get_mode(bl)&MD_BOSS || md->master_id ||
 		(md->class_>=1324 && md->class_<1364) || // prevent stealing from treasure boxes [Valaris]
 		map[md->bl.m].flag.nomobloot ||        // check noloot map flag [Lorky]
-		md->sc_data[SC_STONE].timer != -1 || md->sc_data[SC_FREEZE].timer != -1 //status change check
+		md->sc.data[SC_STONE].timer != -1 || md->sc.data[SC_FREEZE].timer != -1 //status change check
   )
 		return 0;
 	
@@ -3112,7 +3132,7 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *bl)
 		int rate,skill;
 		struct mob_data *md=(struct mob_data *)bl;
 		if(md && !md->state.steal_coin_flag) {
-			if (md->sc_data && (md->sc_data[SC_STONE].timer != -1 || md->sc_data[SC_FREEZE].timer != -1))
+			if (md->sc.data && (md->sc.data[SC_STONE].timer != -1 || md->sc.data[SC_FREEZE].timer != -1))
 				return 0;
 			skill = pc_checkskill(sd,RG_STEALCOIN)*10;
 			rate = skill + (sd->status.base_level - md->db->lv)*3 + sd->paramc[4]*2 + sd->paramc[5]*2;
@@ -3188,42 +3208,40 @@ int pc_setpos(struct map_session_data *sd,unsigned short mapindex,int x,int y,in
 
 	m=map_mapindex2mapid(mapindex);
 
-	if (sd->sc_count) {
-		if (sd->sc_data[SC_TRICKDEAD].timer != -1)
+	if (sd->sc.count) {
+		if (sd->sc.data[SC_TRICKDEAD].timer != -1)
 			status_change_end(&sd->bl, SC_TRICKDEAD, -1);
-		if (sd->sc_data[SC_BLADESTOP].timer!=-1)
+		if (sd->sc.data[SC_BLADESTOP].timer!=-1)
 			status_change_end(&sd->bl,SC_BLADESTOP,-1);
-		if (sd->sc_data[SC_RUN].timer!=-1)
+		if (sd->sc.data[SC_RUN].timer!=-1)
 			status_change_end(&sd->bl,SC_RUN,-1);
-		if (sd->sc_data[SC_DANCING].timer!=-1) // clear dance effect when warping [Valaris]
+		if (sd->sc.data[SC_DANCING].timer!=-1) // clear dance effect when warping [Valaris]
 			skill_stop_dancing(&sd->bl);
-		if (sd->sc_data[SC_DEVOTION].timer!=-1)
+		if (sd->sc.data[SC_DEVOTION].timer!=-1)
 			status_change_end(&sd->bl,SC_DEVOTION,-1);
-		if (sd->sc_data[SC_CLOSECONFINE].timer!=-1)
+		if (sd->sc.data[SC_CLOSECONFINE].timer!=-1)
 			status_change_end(&sd->bl,SC_CLOSECONFINE,-1);
-		if (sd->sc_data[SC_CLOSECONFINE2].timer!=-1)
+		if (sd->sc.data[SC_CLOSECONFINE2].timer!=-1)
 			status_change_end(&sd->bl,SC_CLOSECONFINE2,-1);
-		if (sd->sc_data[SC_RUN].timer!=-1)
+		if (sd->sc.data[SC_RUN].timer!=-1)
 			status_change_end(&sd->bl,SC_RUN,-1);
+		if (sd->sc.data[SC_HIDING].timer!=-1)
+			status_change_end(&sd->bl, SC_HIDING, -1);
+		if (sd->sc.data[SC_CLOAKING].timer!=-1)
+			status_change_end(&sd->bl, SC_CLOAKING, -1);
+		if (sd->sc.data[SC_CHASEWALK].timer!=-1)
+			status_change_end(&sd->bl, SC_CHASEWALK, -1);
 		if (sd->bl.m != m) { //Cancel some map related stuff.
-			if (sd->sc_data[SC_WARM].timer != -1)
+			if (sd->sc.data[SC_WARM].timer != -1)
 				status_change_end(&sd->bl,SC_WARM,-1);
-			if (sd->sc_data[SC_SUN_COMFORT].timer != -1)
+			if (sd->sc.data[SC_SUN_COMFORT].timer != -1)
 				status_change_end(&sd->bl,SC_SUN_COMFORT,-1);
-			if (sd->sc_data[SC_MOON_COMFORT].timer != -1)
+			if (sd->sc.data[SC_MOON_COMFORT].timer != -1)
 				status_change_end(&sd->bl,SC_MOON_COMFORT,-1);
-			if (sd->sc_data[SC_STAR_COMFORT].timer != -1)
+			if (sd->sc.data[SC_STAR_COMFORT].timer != -1)
 				status_change_end(&sd->bl,SC_STAR_COMFORT,-1);
 		}
 	}
-
-	if(sd->status.option&OPTION_HIDE)
-		status_change_end(&sd->bl, SC_HIDING, -1);
-	if(pc_iscloaking(sd))
-		status_change_end(&sd->bl, SC_CLOAKING, -1);
-	if(pc_ischasewalk(sd))
-		status_change_end(&sd->bl, SC_CHASEWALK, -1);
-
 	if(sd->status.pet_id > 0 && sd->pd && sd->pet.intimate > 0) {
 		pet_stopattack(sd->pd);
 		pet_changestate(sd->pd,MS_IDLE,0);
@@ -3441,7 +3459,7 @@ int pc_run(struct map_session_data *sd, int skilllv, int dir)
 	nullpo_retr(0, sd);
 
 	if (!pc_can_move(sd)) {
-		if(sd->sc_data[SC_RUN].timer!=-1)
+		if(sd->sc.data[SC_RUN].timer!=-1)
 			status_change_end(&sd->bl,SC_RUN,-1);
 		return 0;
 	}
@@ -3462,7 +3480,7 @@ int pc_run(struct map_session_data *sd, int skilllv, int dir)
 
 	//進めない場合 駆け足終了 障害物で止まった場合スパート状態解除
 	if(to_x == sd->bl.x && to_y == sd->bl.y){
-		if(sd->sc_data[SC_RUN].timer!=-1)
+		if(sd->sc.data[SC_RUN].timer!=-1)
 			status_change_end(&sd->bl,SC_RUN,-1);
 	} else
 		pc_walktoxy(sd, to_x, to_y);
@@ -3613,9 +3631,9 @@ static int pc_walk(int tid,unsigned int tick,int id,int data)
 		if (pc_iscloaking(sd))	// クロ?キングの消滅?査
 			skill_check_cloaking(&sd->bl);
 		/* 被ディボ?ション?査 */
-		if (sd->sc_count) {
-			if (sd->sc_data[SC_DANCING].timer != -1)
-				skill_unit_move_unit_group((struct skill_unit_group *)sd->sc_data[SC_DANCING].val2, sd->bl.m, dx, dy);
+		if (sd->sc.count) {
+			if (sd->sc.data[SC_DANCING].timer != -1)
+				skill_unit_move_unit_group((struct skill_unit_group *)sd->sc.data[SC_DANCING].val2, sd->bl.m, dx, dy);
 		}
 		if (map_getcell(sd->bl.m,x,y,CELL_CHKNPC))
 			npc_touch_areanpc(sd,sd->bl.m,x,y);
@@ -3629,8 +3647,8 @@ static int pc_walk(int tid,unsigned int tick,int id,int data)
 			i = 1;
 		sd->walktimer = add_timer (tick+i, pc_walk, id, sd->walkpath.path_pos);
 	}
-	else if(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(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 { //Stopped walking. Update to_x and to_y to current location [Skotlex]
 		sd->to_x = sd->bl.x;
 		sd->to_y = sd->bl.y;
@@ -3676,7 +3694,7 @@ int pc_walktoxy (struct map_session_data *sd, int x, int y)
 
 	sd->to_x = x;
 	sd->to_y = y;
-	if (sd->sc_data[SC_CONFUSION].timer != -1) //Randomize the target position
+	if (sd->sc.data[SC_CONFUSION].timer != -1) //Randomize the target position
 		map_random_dir(&sd->bl, &sd->to_x, &sd->to_y);
 	
 	if (sd->walktimer != -1)
@@ -3738,7 +3756,7 @@ int pc_stop_walking (struct map_session_data *sd, int type)
 	sd->to_y = sd->bl.y;
 	if (type & 0x01)
 		clif_fixpos(&sd->bl);
-	if (sd->sc_data[SC_RUN].timer != -1)
+	if (sd->sc.data[SC_RUN].timer != -1)
 		status_change_end(&sd->bl, SC_RUN, -1);
 	return 0;
 }
@@ -3837,36 +3855,36 @@ int pc_checkallowskill(struct map_session_data *sd)
 {
 	nullpo_retr(0, sd);
 
-	if(!sd->sc_count)
+	if(!sd->sc.count)
 		return 0;
 	
 	// Skills requiring specific weapon types
-	if(sd->sc_data[SC_TWOHANDQUICKEN].timer!=-1 && !(skill_get_weapontype(KN_TWOHANDQUICKEN)&(1<<sd->status.weapon)))
+	if(sd->sc.data[SC_TWOHANDQUICKEN].timer!=-1 && !(skill_get_weapontype(KN_TWOHANDQUICKEN)&(1<<sd->status.weapon)))
 		status_change_end(&sd->bl,SC_TWOHANDQUICKEN,-1);
-	if(sd->sc_data[SC_ONEHAND].timer!=-1 && !(skill_get_weapontype(KN_ONEHAND)&(1<<sd->status.weapon)))
+	if(sd->sc.data[SC_ONEHAND].timer!=-1 && !(skill_get_weapontype(KN_ONEHAND)&(1<<sd->status.weapon)))
 		status_change_end(&sd->bl,SC_ONEHAND,-1);
-	if(sd->sc_data[SC_AURABLADE].timer!=-1 && !(skill_get_weapontype(LK_AURABLADE)&(1<<sd->status.weapon)))
+	if(sd->sc.data[SC_AURABLADE].timer!=-1 && !(skill_get_weapontype(LK_AURABLADE)&(1<<sd->status.weapon)))
 		// Aura Blade requires any weapon but bare fists
 		status_change_end(&sd->bl,SC_AURABLADE,-1);
-	if(sd->sc_data[SC_PARRYING].timer!=-1 && !(skill_get_weapontype(LK_PARRYING)&(1<<sd->status.weapon)))
+	if(sd->sc.data[SC_PARRYING].timer!=-1 && !(skill_get_weapontype(LK_PARRYING)&(1<<sd->status.weapon)))
 		status_change_end(&sd->bl,SC_PARRYING,-1);
-	if(sd->sc_data[SC_SPEARSQUICKEN].timer!=-1 && !(skill_get_weapontype(CR_SPEARQUICKEN)&(1<<sd->status.weapon)))
+	if(sd->sc.data[SC_SPEARSQUICKEN].timer!=-1 && !(skill_get_weapontype(CR_SPEARQUICKEN)&(1<<sd->status.weapon)))
 		// Spear Quicken requires a Two-handed spear
 		status_change_end(&sd->bl,SC_SPEARSQUICKEN,-1);
-	if(sd->sc_data[SC_ADRENALINE].timer!=-1 && !(skill_get_weapontype(BS_ADRENALINE)&(1<<sd->status.weapon)))
+	if(sd->sc.data[SC_ADRENALINE].timer!=-1 && !(skill_get_weapontype(BS_ADRENALINE)&(1<<sd->status.weapon)))
 		status_change_end(&sd->bl,SC_ADRENALINE,-1);
-	if(sd->sc_data[SC_ADRENALINE2].timer!=-1 && !(skill_get_weapontype(BS_ADRENALINE2)&(1<<sd->status.weapon)))
+	if(sd->sc.data[SC_ADRENALINE2].timer!=-1 && !(skill_get_weapontype(BS_ADRENALINE2)&(1<<sd->status.weapon)))
 		status_change_end(&sd->bl,SC_ADRENALINE2,-1);
-	if( sd->sc_data[SC_SPURT].timer!=-1 && sd->status.weapon)
+	if( sd->sc.data[SC_SPURT].timer!=-1 && sd->status.weapon)
 		// Spurt requires bare hands (feet, in fact xD)
 		status_change_end(&sd->bl,SC_SPURT,-1);
 
 	if(sd->status.shield <= 0) { // Skills requiring a shield
-		if(sd->sc_data[SC_AUTOGUARD].timer!=-1)	// Guard
+		if(sd->sc.data[SC_AUTOGUARD].timer!=-1)	// Guard
 			status_change_end(&sd->bl,SC_AUTOGUARD,-1);
-		if(sd->sc_data[SC_DEFENDER].timer!=-1)	// Defending Aura
+		if(sd->sc.data[SC_DEFENDER].timer!=-1)	// Defending Aura
 			status_change_end(&sd->bl,SC_DEFENDER,-1);
-		if(sd->sc_data[SC_REFLECTSHIELD].timer!=-1) // Shield Reflect
+		if(sd->sc.data[SC_REFLECTSHIELD].timer!=-1) // Shield Reflect
 			status_change_end(&sd->bl,SC_REFLECTSHIELD,-1);
 	}
 	return 0;
@@ -4423,7 +4441,7 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data)
 		map_freeblock_lock();
 		sd->attacktarget_lv = battle_weapon_attack(&sd->bl,bl,tick,0);
 		
-		if(!(battle_config.pc_cloak_check_type&2) && sd->sc_data[SC_CLOAKING].timer != -1)
+		if(!(battle_config.pc_cloak_check_type&2) && sd->sc.data[SC_CLOAKING].timer != -1)
 			status_change_end(&sd->bl,SC_CLOAKING,-1);
 		
 		if(sd->status.pet_id > 0 && sd->pd && sd->petDB && battle_config.pet_attack_support)
@@ -5064,8 +5082,8 @@ int pc_resetlvl(struct map_session_data* sd,int type)
 	sd->status.job_level=1;
 	sd->status.base_exp=sd->status.base_exp=0;
 	sd->status.job_exp=sd->status.job_exp=0;
-	if(sd->status.option !=0)
-		sd->status.option = 0;
+	if(sd->sc.option !=0)
+		sd->sc.option = 0;
 
 	sd->status.str=1;
 	sd->status.agi=1;
@@ -5279,21 +5297,29 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
 	}
 
 	// ? いていたら足を止める
-	if (sd->sc_data) {
-		if (sd->sc_data[SC_ENDURE].timer != -1 && (src != NULL && src->type == BL_MOB) && !map_flag_gvg(sd->bl.m)) {
-			if (!sd->special_state.infinite_endure && (--sd->sc_data[SC_ENDURE].val2) < 0) 
+	if (sd->sc.count) {
+		if (sd->sc.data[SC_ENDURE].timer != -1 && (src != NULL && src->type == BL_MOB) && !map_flag_gvg(sd->bl.m)) {
+			if (!sd->special_state.infinite_endure && (--sd->sc.data[SC_ENDURE].val2) < 0) 
 				status_change_end(&sd->bl, SC_ENDURE, -1);
 		}
-		if (sd->sc_data[SC_GRAVITATION].timer != -1 &&
-			sd->sc_data[SC_GRAVITATION].val3 == BCT_SELF) {
-			struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc_data[SC_GRAVITATION].val4;
+		if (sd->sc.data[SC_GRAVITATION].timer != -1 &&
+			sd->sc.data[SC_GRAVITATION].val3 == BCT_SELF) {
+			struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc.data[SC_GRAVITATION].val4;
 			if (sg) {
 				skill_delunitgroup(sg);
 				status_change_end(&sd->bl, SC_GRAVITATION, -1);
 			}
 		}
-		if (sd->sc_data[SC_CONFUSION].timer != -1)
+		if (sd->sc.data[SC_CONFUSION].timer != -1)
 			status_change_end(&sd->bl, SC_CONFUSION, -1);
+		if (sd->sc.data[SC_TRICKDEAD].timer != -1)
+			status_change_end(&sd->bl, SC_TRICKDEAD, -1);
+		if (sd->sc.data[SC_HIDING].timer != -1)
+			status_change_end(&sd->bl, SC_HIDING, -1);
+		if (sd->sc.data[SC_CLOAKING].timer != -1)
+			status_change_end(&sd->bl, SC_CLOAKING, -1);
+		if (sd->sc.data[SC_CHASEWALK].timer != -1)
+			status_change_end(&sd->bl, SC_CHASEWALK, -1);
 	}
 
 	// 演奏/ダンスの中?
@@ -5308,20 +5334,11 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
 	if(sd->status.pet_id > 0 && sd->pd && sd->petDB && battle_config.pet_damage_support)
 		pet_target_check(sd,src,1);
 
-	if (sd->sc_data[SC_TRICKDEAD].timer != -1)
-		status_change_end(&sd->bl, SC_TRICKDEAD, -1);
-	if(sd->status.option&OPTION_HIDE)
-		status_change_end(&sd->bl, SC_HIDING, -1);
-	if(pc_iscloaking(sd))
-		status_change_end(&sd->bl, SC_CLOAKING, -1);
-	if(pc_ischasewalk(sd))
-		status_change_end(&sd->bl, SC_CHASEWALK, -1);
-
 	clif_updatestatus(sd,SP_HP);
 
 	if(sd->status.hp>0){
-		if(sd->status.hp<sd->status.max_hp>>2 && sd->sc_data[SC_AUTOBERSERK].timer != -1 &&
-			(sd->sc_data[SC_PROVOKE].timer==-1 || sd->sc_data[SC_PROVOKE].val2==0 ))
+		if(sd->status.hp<sd->status.max_hp>>2 && sd->sc.data[SC_AUTOBERSERK].timer != -1 &&
+			(sd->sc.data[SC_PROVOKE].timer==-1 || sd->sc.data[SC_PROVOKE].val2==0 ))
 			// オ?トバ?サ?ク?動
 			status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0);
 
@@ -5354,9 +5371,9 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
 	pc_stop_walking(sd,0);
 	skill_castcancel(&sd->bl,0);	// 詠唱の中止
 	skill_stop_dancing(&sd->bl); //You should stop dancing when dead... [Skotlex]
-	if (sd->sc_data[SC_GOSPEL].timer != -1 && sd->sc_data[SC_GOSPEL].val4 == BCT_SELF)
+	if (sd->sc.data[SC_GOSPEL].timer != -1 && sd->sc.data[SC_GOSPEL].val4 == BCT_SELF)
 	{	//Remove Gospel [Skotlex]
-		struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc_data[SC_GOSPEL].val3;
+		struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc.data[SC_GOSPEL].val3;
 		if (sg)
 			skill_delunitgroup(sg);
 	}
@@ -5477,7 +5494,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
 	if(battle_config.death_penalty_type && sd->state.snovice_flag != 4
 		&& (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE	// only novices will receive no penalty
 		&& !map[sd->bl.m].flag.nopenalty && !map_flag_gvg(sd->bl.m)
-		&& !(sd->sc_count && sd->sc_data[SC_BABY].timer!=-1))
+		&& !(sd->sc.count && sd->sc.data[SC_BABY].timer!=-1))
 	{
 			if(battle_config.death_penalty_type==1 && battle_config.death_penalty_base > 0)
 				sd->status.base_exp -= (int) ((double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000);
@@ -5525,7 +5542,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
 		}
 	}
 	//Clear these data here so that SC_BABY check may work. [Skotlex]
-	resurrect_flag = (sd->sc_data[SC_KAIZEL].timer != -1)?sd->sc_data[SC_KAIZEL].val1:0; //Auto-resurrect later in the code.
+	resurrect_flag = (sd->sc.data[SC_KAIZEL].timer != -1)?sd->sc.data[SC_KAIZEL].val1:0; //Auto-resurrect later in the code.
 	status_change_clear(&sd->bl,0);	// ステ?タス異常を解除する
 	clif_updatestatus(sd,SP_HP);
 	status_calc_pc(sd,0);
@@ -5908,7 +5925,7 @@ int pc_heal(struct map_session_data *sd,int hp,int sp)
 			sp = 0;
 	}
 
-	if(sd->sc_count && sd->sc_data[SC_BERSERK].timer!=-1) //バ?サ?ク中は回復させないらしい
+	if(sd->sc.count && sd->sc.data[SC_BERSERK].timer!=-1) //バ?サ?ク中は回復させないらしい
 		return 0;
 
 	if(hp+sd->status.hp>sd->status.max_hp)
@@ -5929,8 +5946,8 @@ int pc_heal(struct map_session_data *sd,int hp,int sp)
 	if(sp)
 		clif_updatestatus(sd,SP_SP);
 
-	if(sd->status.hp>=sd->status.max_hp>>2 && sd->sc_data[SC_AUTOBERSERK].timer != -1 &&
-		(sd->sc_data[SC_PROVOKE].timer!=-1 && sd->sc_data[SC_PROVOKE].val2==1 ))
+	if(sd->status.hp>=sd->status.max_hp>>2 && sd->sc.data[SC_AUTOBERSERK].timer != -1 &&
+		(sd->sc.data[SC_PROVOKE].timer!=-1 && sd->sc.data[SC_PROVOKE].val2==1 ))
 			status_change_end(&sd->bl,SC_PROVOKE,-1); //End auto berserk.
 
 	return hp + sp;
@@ -5948,7 +5965,7 @@ int pc_itemheal(struct map_session_data *sd,int hp,int sp)
 
 	nullpo_retr(0, sd);
 
-	if(sd->sc_count && sd->sc_data[SC_GOSPEL].timer!=-1) //バ?サ?ク中は回復させないらしい
+	if(sd->sc.count && sd->sc.data[SC_GOSPEL].timer!=-1) //バ?サ?ク中は回復させないらしい
 		return 0;
 
 	if(pc_checkoverhp(sd)) {
@@ -6141,7 +6158,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
 
 	if(pc_isriding(sd)) {	// remove peco status if changing into invalid class [Valaris]
 		if(!(pc_checkskill(sd,KN_RIDING)))
-			pc_setoption(sd,sd->status.option&~OPTION_RIDING);
+			pc_setoption(sd,sd->sc.option&~OPTION_RIDING);
 		else
 			pc_setriding(sd);
 	}
@@ -6255,7 +6272,7 @@ int pc_changelook(struct map_session_data *sd,int type,int val)
 int pc_setoption(struct map_session_data *sd,int type)
 {
 	nullpo_retr(0, sd);
-	if (type&OPTION_RIDING && !(sd->status.option&OPTION_RIDING) && (sd->class_&MAPID_BASEMASK) == MAPID_SWORDMAN)
+	if (type&OPTION_RIDING && !(sd->sc.option&OPTION_RIDING) && (sd->class_&MAPID_BASEMASK) == MAPID_SWORDMAN)
 	{	//We are going to mount. [Skotlex]
 		switch (sd->status.class_)
 		{
@@ -6281,7 +6298,7 @@ int pc_setoption(struct map_session_data *sd,int type)
 		clif_status_load(&sd->bl,SI_RIDING,1);
 		status_calc_pc(sd,0); //Mounting/Umounting affects walk and attack speeds.
 	}
-	else if (!(type&OPTION_RIDING) && sd->status.option&OPTION_RIDING && (sd->class_&MAPID_BASEMASK) == MAPID_SWORDMAN)
+	else if (!(type&OPTION_RIDING) && sd->sc.option&OPTION_RIDING && (sd->class_&MAPID_BASEMASK) == MAPID_SWORDMAN)
 	{	//We are going to dismount.
 		switch (sd->status.class_)
 		{
@@ -6307,22 +6324,22 @@ int pc_setoption(struct map_session_data *sd,int type)
 		clif_status_load(&sd->bl,SI_RIDING,0);
 		status_calc_pc(sd,0); //Mounting/Umounting affects walk and attack speeds.
 	}
-	if (type&OPTION_FALCON && !(sd->status.option&OPTION_FALCON)) //Falcon ON
+	if (type&OPTION_FALCON && !(sd->sc.option&OPTION_FALCON)) //Falcon ON
 		clif_status_load(&sd->bl,SI_FALCON,1);
-	else if (!(type&OPTION_FALCON) && sd->status.option&OPTION_FALCON) //Falcon OFF
+	else if (!(type&OPTION_FALCON) && sd->sc.option&OPTION_FALCON) //Falcon OFF
 		clif_status_load(&sd->bl,SI_FALCON,0);
 
 	//SG flying [Komurka]
-	if (type&OPTION_FLYING && !(sd->status.option&OPTION_FLYING)) //Flying ON
+	if (type&OPTION_FLYING && !(sd->sc.option&OPTION_FLYING)) //Flying ON
 	{
 		if (sd->status.class_==JOB_STAR_GLADIATOR) sd->status.class_ = sd->view_class = JOB_STAR_GLADIATOR2;
 	}
-	else if (!(type&OPTION_FLYING) && sd->status.option&OPTION_FLYING) //Flying OFF
+	else if (!(type&OPTION_FLYING) && sd->sc.option&OPTION_FLYING) //Flying OFF
 	{
 		if (sd->status.class_==JOB_STAR_GLADIATOR2) sd->status.class_ = sd->view_class = JOB_STAR_GLADIATOR;
 	}
 
-	sd->status.option=type;
+	sd->sc.option=type;
 	clif_changeoption(&sd->bl);
 	status_calc_pc(sd,0);
 	return 0;
@@ -6341,7 +6358,7 @@ int pc_setcart(struct map_session_data *sd,int type)
 	if (type < 0 || type > 5)
 		return 0; //Never trust the values sent by the client! [Skotlex]
 
-	option = sd->status.option;
+	option = sd->sc.option;
 	for (i = 0; i < 6; i++)
 	{	//This should preserve the current option, only modifying the cart bit.
 		if (i == type)
@@ -6372,7 +6389,7 @@ int pc_setcart(struct map_session_data *sd,int type)
 int pc_setfalcon(struct map_session_data *sd)
 {
 	if(pc_checkskill(sd,HT_FALCON)>0){	// ファルコンマスタリ?スキル所持
-		pc_setoption(sd,sd->status.option|0x0010);
+		pc_setoption(sd,sd->sc.option|0x0010);
 	}
 
 	return 0;
@@ -6385,7 +6402,7 @@ int pc_setfalcon(struct map_session_data *sd)
 int pc_setriding(struct map_session_data *sd)
 {
 	if((pc_checkskill(sd,KN_RIDING)>0)){ // ライディングスキル所持
-		pc_setoption(sd,sd->status.option|OPTION_RIDING);
+		pc_setoption(sd,sd->sc.option|OPTION_RIDING);
 	}
 	return 0;
 }
@@ -6874,7 +6891,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos)
 
 // -- moonsoul (if player is berserk then cannot equip)
 //
-	if(sd->sc_count && sd->sc_data[SC_BERSERK].timer!=-1){
+	if(sd->sc.count && sd->sc.data[SC_BERSERK].timer!=-1){
 		clif_equipitemack(sd,n,0,0);	// fail
 		return 0;
 	}
@@ -6982,16 +6999,16 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos)
 	status_calc_pc(sd,0);
 
 	if(sd->special_state.infinite_endure) {
-		if(sd->sc_data[SC_ENDURE].timer == -1)
+		if(sd->sc.data[SC_ENDURE].timer == -1)
 			status_change_start(&sd->bl,SC_ENDURE,10,1,0,0,0,0);
 	}
 	else {
-		if(sd->sc_count && sd->sc_data[SC_ENDURE].timer != -1 && sd->sc_data[SC_ENDURE].val2)
+		if(sd->sc.count && sd->sc.data[SC_ENDURE].timer != -1 && sd->sc.data[SC_ENDURE].val2)
 			status_change_end(&sd->bl,SC_ENDURE,-1);
 	}
 
-	if(sd->sc_count) {
-		if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele))
+	if(sd->sc.count) {
+		if (sd->sc.data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele))
 			status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
 	}
 
@@ -7013,7 +7030,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
 
 // -- moonsoul	(if player is berserk then cannot unequip)
 //
-	if(!(flag&2) && sd->sc_count && (sd->sc_data[SC_BLADESTOP].timer!=-1 || sd->sc_data[SC_BERSERK].timer!=-1)){
+	if(!(flag&2) && sd->sc.count && (sd->sc.data[SC_BLADESTOP].timer!=-1 || sd->sc.data[SC_BERSERK].timer!=-1)){
 		clif_unequipitemack(sd,n,0,0);
 		return 0;
 	}
@@ -7040,7 +7057,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
 			sd->status.weapon = sd->weapontype2;
 			pc_calcweapontype(sd);
 			clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
-			if(sd->sc_data[SC_DANCING].timer!=-1) //When unequipping, stop dancing. [Skotlex]
+			if(sd->sc.data[SC_DANCING].timer!=-1) //When unequipping, stop dancing. [Skotlex]
 				skill_stop_dancing(&sd->bl);
 		}
 		if(sd->status.inventory[n].equip & 0x0020) {
@@ -7075,7 +7092,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
 
 	if(flag&1) {
 		status_calc_pc(sd,0);
-		if(sd->sc_count && sd->sc_data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele))
+		if(sd->sc.count && sd->sc.data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele))
 			status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
 	}
 
@@ -7435,11 +7452,11 @@ static int pc_spheal(struct map_session_data *sd)
 	
 	if(pc_issit(sd))
 		a += a;
-	if (sd->sc_count) {
-		if (sd->sc_data[SC_MAGNIFICAT].timer!=-1)	// マグニフィカ?ト
+	if (sd->sc.count) {
+		if (sd->sc.data[SC_MAGNIFICAT].timer!=-1)	// マグニフィカ?ト
 			a += a;
-		if (sd->sc_data[SC_REGENERATION].timer != -1)
-			a *= sd->sc_data[SC_REGENERATION].val1;
+		if (sd->sc.data[SC_REGENERATION].timer != -1)
+			a *= sd->sc.data[SC_REGENERATION].val1;
 	}
 	// Re-added back to status_calc
 	//if((skill = pc_checkskill(sd,HP_MEDITATIO)) > 0) //Increase natural SP regen with Meditatio [DracoRPG]
@@ -7472,11 +7489,11 @@ static int pc_hpheal(struct map_session_data *sd)
 
 	if(pc_issit(sd))
 		a += a;
-	if (sd->sc_count) {
-		if (sd->sc_data[SC_MAGNIFICAT].timer != -1)	// Modified by RoVeRT
+	if (sd->sc.count) {
+		if (sd->sc.data[SC_MAGNIFICAT].timer != -1)	// Modified by RoVeRT
 			a += a;
-		if (sd->sc_data[SC_REGENERATION].timer != -1)
-			a *= sd->sc_data[SC_REGENERATION].val1;
+		if (sd->sc.data[SC_REGENERATION].timer != -1)
+			a *= sd->sc.data[SC_REGENERATION].val1;
 	}
 	if (sd->status.guild_id > 0) {
 		struct guild_castle *gc = guild_mapindex2gc(sd->mapindex);	// Increased guild castle regen [Valaris]
@@ -7513,7 +7530,7 @@ static int pc_natural_heal_hp(struct map_session_data *sd)
 
 	if(sd->walktimer == -1) {
 		inc_num = pc_hpheal(sd);
-		if(sd->sc_data[SC_TENSIONRELAX].timer!=-1 ){	// テンションリラックス
+		if(sd->sc.data[SC_TENSIONRELAX].timer!=-1 ){	// テンションリラックス
 			sd->hp_sub += 2*inc_num;
 			sd->inchealhptick += 3*natural_heal_diff_tick;
 		} else {
@@ -7589,7 +7606,7 @@ static int pc_natural_heal_sp(struct map_session_data *sd)
 	bsp=sd->status.sp;
 
 	inc_num = pc_spheal(sd);
-	if(sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1 || (sd->sc_data[SC_SPIRIT].timer!=-1 && sd->sc_data[SC_SPIRIT].val2 == SL_MONK))
+	if(sd->sc.data[SC_EXPLOSIONSPIRITS].timer == -1 || (sd->sc.data[SC_SPIRIT].timer!=-1 && sd->sc.data[SC_SPIRIT].val2 == SL_MONK))
 		sd->sp_sub += inc_num;
 	if(sd->walktimer == -1)
 		sd->inchealsptick += natural_heal_diff_tick;
@@ -7775,12 +7792,12 @@ static int pc_natural_heal_sub(struct map_session_data *sd,va_list ap) {
 // -- moonsoul (if conditions below altered to disallow natural healing if under berserk status)
 	if (pc_isdead(sd) || pc_ishiding(sd) ||
 	//-- cannot regen for 5 minutes after using Berserk --- [Celest]
-		(sd->sc_count && (
-			(sd->sc_data[SC_POISON].timer != -1 && sd->sc_data[SC_SLOWPOISON].timer == -1) ||
-			(sd->sc_data[SC_DPOISON].timer != -1 && sd->sc_data[SC_SLOWPOISON].timer == -1) ||
-			sd->sc_data[SC_BERSERK].timer != -1 ||
-			sd->sc_data[SC_TRICKDEAD].timer != -1 ||
-			sd->sc_data[SC_BLEEDING].timer != -1
+		(sd->sc.count && (
+			(sd->sc.data[SC_POISON].timer != -1 && sd->sc.data[SC_SLOWPOISON].timer == -1) ||
+			(sd->sc.data[SC_DPOISON].timer != -1 && sd->sc.data[SC_SLOWPOISON].timer == -1) ||
+			sd->sc.data[SC_BERSERK].timer != -1 ||
+			sd->sc.data[SC_TRICKDEAD].timer != -1 ||
+			sd->sc.data[SC_BLEEDING].timer != -1
 		))
 	) { //Cannot heal neither natural or special.
 		sd->hp_sub = sd->inchealhptick = sd->inchealspirithptick = 0;
@@ -7792,9 +7809,9 @@ static int pc_natural_heal_sub(struct map_session_data *sd,va_list ap) {
 			sd->sp_sub = sd->inchealsptick = 0;
 		} else { //natural heal
 			pc_natural_heal_hp(sd);
-			if(sd->sc_count && (
-				sd->sc_data[SC_EXTREMITYFIST].timer != -1 ||
-				sd->sc_data[SC_DANCING].timer != -1
+			if(sd->sc.count && (
+				sd->sc.data[SC_EXTREMITYFIST].timer != -1 ||
+				sd->sc.data[SC_DANCING].timer != -1
 			))	//No SP natural heal.
 				sd->sp_sub = sd->inchealsptick = 0;
 			else
@@ -7999,7 +8016,7 @@ int map_night_timer(int tid, unsigned int tick, int id, int data)
 void pc_setstand(struct map_session_data *sd){
 	nullpo_retv(sd);
 
-	if(sd->sc_count && sd->sc_data[SC_TENSIONRELAX].timer!=-1)
+	if(sd->sc.count && sd->sc.data[SC_TENSIONRELAX].timer!=-1)
 		status_change_end(&sd->bl,SC_TENSIONRELAX,-1);
 
 	sd->state.dead_sit = 0;

+ 7 - 7
src/map/pc.h

@@ -18,13 +18,13 @@
 #define pc_issit(sd) ((sd)->state.dead_sit == 2)
 #define pc_setdir(sd,b,h) ((sd)->dir = (b) ,(sd)->head_dir = (h) )
 #define pc_setchatid(sd,n) ((sd)->chatID = n)
-#define pc_ishiding(sd) ((sd)->status.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK))
-#define pc_iscloaking(sd) (!((sd)->status.option&OPTION_CHASEWALK) && ((sd)->status.option&OPTION_CLOAK))
-#define pc_ischasewalk(sd) ((sd)->status.option&OPTION_CHASEWALK)
-#define pc_iscarton(sd) ((sd)->status.option&CART_MASK)
-#define pc_isfalcon(sd) ((sd)->status.option&OPTION_FALCON)
-#define pc_isriding(sd) ((sd)->status.option&OPTION_RIDING)
-#define pc_isinvisible(sd) ((sd)->status.option&OPTION_INVISIBLE)
+#define pc_ishiding(sd) ((sd)->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK))
+#define pc_iscloaking(sd) (!((sd)->sc.option&OPTION_CHASEWALK) && ((sd)->sc.option&OPTION_CLOAK))
+#define pc_ischasewalk(sd) ((sd)->sc.option&OPTION_CHASEWALK)
+#define pc_iscarton(sd) ((sd)->sc.option&CART_MASK)
+#define pc_isfalcon(sd) ((sd)->sc.option&OPTION_FALCON)
+#define pc_isriding(sd) ((sd)->sc.option&OPTION_RIDING)
+#define pc_isinvisible(sd) ((sd)->sc.option&OPTION_INVISIBLE)
 #define pc_is50overweight(sd) (sd->weight*2 >= sd->max_weight) 
 #define pc_is90overweight(sd) (sd->weight*10 >= sd->max_weight*9)
 #define pc_maxparameter(sd) ((sd->class_&JOBL_BABY) ? battle_config.max_baby_parameter : battle_config.max_parameter)

+ 1 - 1
src/map/pet.c

@@ -1748,7 +1748,7 @@ int pet_recovery_timer(int tid,unsigned int tick,int id,int data)
 		return 0;
 	}
 
-	if(sd->sc_data && sd->sc_data[pd->recovery->type].timer != -1)
+	if(sd->sc.count && sd->sc.data[pd->recovery->type].timer != -1)
 	{	//Display a heal animation? 
 		//Detoxify is chosen for now.
 		clif_skill_nodamage(&pd->bl,&sd->bl,TF_DETOXIFY,1,1);

+ 3 - 3
src/map/script.c

@@ -4947,7 +4947,7 @@ int buildin_checkoption(struct script_state *st)
 	type=conv_num(st,& (st->stack->stack_data[st->start+2]));
 	sd=script_rid2sd(st);
 
-	if(sd->status.option & type){
+	if(sd->sc.option & type){
 		push_val(st->stack,C_INT,1);
 	} else {
 		push_val(st->stack,C_INT,0);
@@ -4967,7 +4967,7 @@ int buildin_checkoption1(struct script_state *st)
 	type=conv_num(st,& (st->stack->stack_data[st->start+2]));
 	sd=script_rid2sd(st);
 
-	if(sd->opt1 & type){
+	if(sd->sc.opt1 & type){
 		push_val(st->stack,C_INT,1);
 	} else {
 		push_val(st->stack,C_INT,0);
@@ -4987,7 +4987,7 @@ int buildin_checkoption2(struct script_state *st)
 	type=conv_num(st,& (st->stack->stack_data[st->start+2]));
 	sd=script_rid2sd(st);
 
-	if(sd->opt2 & type){
+	if(sd->sc.opt2 & type){
 		push_val(st->stack,C_INT,1);
 	} else {
 		push_val(st->stack,C_INT,0);

File diff ditekan karena terlalu besar
+ 253 - 263
src/map/skill.c


File diff ditekan karena terlalu besar
+ 321 - 326
src/map/status.c


+ 1 - 6
src/map/status.h

@@ -460,12 +460,7 @@ int status_get_mode(struct block_list *bl);
 int status_get_mexp(struct block_list *bl);
 int status_get_race2(struct block_list *bl);
 
-struct status_change *status_get_sc_data(struct block_list *bl);
-short *status_get_sc_count(struct block_list *bl);
-short *status_get_opt1(struct block_list *bl);
-short *status_get_opt2(struct block_list *bl);
-short *status_get_opt3(struct block_list *bl);
-short *status_get_option(struct block_list *bl);
+struct status_change *status_get_sc(struct block_list *bl);
 
 int status_get_matk1(struct block_list *bl);
 int status_get_matk2(struct block_list *bl);

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini