Ver Fonte

Improved bonus-adding processes by no longer having to add it to the zero'd memset bullshit, replaced it by moving the first set of bonus into its own struct and simply zeroing the struct prior to recalc.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16272 54d463be-8e91-2dee-dedb-b68131a5f0ec
shennetsind há 13 anos atrás
pai
commit
e2fd3350e5
7 ficheiros alterados com 224 adições e 295 exclusões
  1. 51 57
      src/map/battle.c
  2. 2 3
      src/map/mob.c
  3. 80 82
      src/map/pc.c
  4. 35 33
      src/map/pc.h
  5. 10 13
      src/map/script.c
  6. 21 24
      src/map/skill.c
  7. 25 83
      src/map/status.c

+ 51 - 57
src/map/battle.c

@@ -792,8 +792,8 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 			short element = skill_get_ele(skill_num, skill_lv);
 			if( !skill_num || element == -1 ) { //Take weapon's element
 				struct status_data *sstatus = NULL;
-				if( src->type == BL_PC && ((TBL_PC*)src)->arrow_ele )
-					element = ((TBL_PC*)src)->arrow_ele;
+				if( src->type == BL_PC && ((TBL_PC*)src)->bonus.arrow_ele )
+					element = ((TBL_PC*)src)->bonus.arrow_ele;
 				else if( (sstatus = status_get_status_data(src)) ) {
 					element = sstatus->rhw.ele;
 				}
@@ -1109,8 +1109,8 @@ static int battle_calc_base_damage(struct status_data *status, struct weapon_atk
 	if (sd)
 	{
 		//rodatazone says the range is 0~arrow_atk-1 for non crit
-		if (flag&2 && sd->arrow_atk)
-			damage += ((flag&1)?sd->arrow_atk:rnd()%sd->arrow_atk);
+		if (flag&2 && sd->bonus.arrow_atk)
+			damage += ( (flag&1) ? sd->bonus.arrow_atk : rnd()%sd->bonus.arrow_atk );
 
 		//SizeFix only for players
 		if (!(sd->special_state.no_sizefix || (flag&8)))
@@ -1351,8 +1351,8 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 	{ //Take weapon's element
 		s_ele = sstatus->rhw.ele;
 		s_ele_ = sstatus->lhw.ele;
-		if( flag.arrow && sd && sd->arrow_ele )
-			s_ele = sd->arrow_ele;
+		if( flag.arrow && sd && sd->bonus.arrow_ele )
+			s_ele = sd->bonus.arrow_ele;
 		if( battle_config.attack_attr_none&src->type )
 			n_ele = true; //Weapon's element is "not elemental"
 	}
@@ -1383,9 +1383,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 
 	if( sd && !skill_num ) {	//Check for double attack.
 		if( ( ( skill_lv = pc_checkskill(sd,TF_DOUBLE) ) > 0 && sd->weapontype1 == W_DAGGER )
-			|| ( sd->double_rate > 0 && sd->weapontype1 != W_FIST ) ) //Will fail bare-handed 
+			|| ( sd->bonus.double_rate > 0 && sd->weapontype1 != W_FIST ) ) //Will fail bare-handed 
 		{	//Success chance is not added, the higher one is used [Skotlex]
-			if( rnd()%100 < ( 5*skill_lv > sd->double_rate ? 5*skill_lv : sd->double_rate ) )
+			if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sd->bonus.double_rate ) )
 			{
 				wd.div_ = skill_get_num(TF_DOUBLE,skill_lv?skill_lv:1);
 				wd.type = 0x08;
@@ -1424,19 +1424,16 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 		{
 			cri+= sd->critaddrace[tstatus->race];
 			if(flag.arrow)
-				cri += sd->arrow_cri;
+				cri += sd->bonus.arrow_cri;
 		}
 		//The official equation is *2, but that only applies when sd's do critical.
 		//Therefore, we use the old value 3 on cases when an sd gets attacked by a mob
 		cri -= tstatus->luk*(!sd&&tsd?3:2);
 		
-		if(tsc)
-		{
-			if (tsc->data[SC_SLEEP])
-				cri <<=1;
+		if( tsc && tsc->data[SC_SLEEP] ) {
+			cri <<= 1;
 		}
-		switch (skill_num)
-		{
+		switch (skill_num) {
 			case KN_AUTOCOUNTER:
 				if(battle_config.auto_counter_type &&
 					(battle_config.auto_counter_type&src->type))
@@ -1452,17 +1449,17 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 				cri += 250 + 50*skill_lv;
 				break;
 		}
-		if(tsd && tsd->critical_def)
-			cri = cri*(100-tsd->critical_def)/100;
+		if(tsd && tsd->bonus.critical_def)
+			cri = cri * ( 100 - tsd->bonus.critical_def ) / 100;
 		if (rnd()%1000 < cri)
-			flag.cri= 1;
+			flag.cri = 1;
 	}
 	if (flag.cri)
 	{
 		wd.type = 0x0a;
 		flag.idef = flag.idef2 = flag.hit = 1;
 	} else {	//Check for Perfect Hit
-		if(sd && sd->perfect_hit > 0 && rnd()%100 < sd->perfect_hit)
+		if(sd && sd->bonus.perfect_hit > 0 && rnd()%100 < sd->bonus.perfect_hit)
 			flag.hit = 1;
 		if (sc && sc->data[SC_FUSION]) {
 			flag.hit = 1; //SG_FUSION always hit [Komurka]
@@ -1513,7 +1510,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 			hitrate -= 50;
 
 		if(sd && flag.arrow)
-			hitrate += sd->arrow_hit;
+			hitrate += sd->bonus.arrow_hit;
 		if(skill_num)
 			switch(skill_num)
 		{	//Hit skill modifiers
@@ -1681,13 +1678,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 				}
 
 				//Add any bonuses that modify the base baseatk+watk (pre-skills)
-				if(sd)
-				{
-					if (sd->atk_rate)
-						ATK_ADDRATE(sd->atk_rate);
+				if(sd) {
+					if (sd->bonus.atk_rate)
+						ATK_ADDRATE(sd->bonus.atk_rate);
 
-					if(flag.cri && sd->crit_atk_rate)
-						ATK_ADDRATE(sd->crit_atk_rate);
+					if(flag.cri && sd->bonus.crit_atk_rate)
+						ATK_ADDRATE(sd->bonus.crit_atk_rate);
 
 					if(sd->status.party_id && (skill=pc_checkskill(sd,TK_POWER)) > 0){
 						if( (i = party_foreachsamemap(party_sub_count, sd, 0)) > 1 ) // exclude the player himself [Inkfish]
@@ -2872,7 +2868,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 			}
 
 			if( wd.flag&BF_LONG )
-				cardfix=cardfix*(100+sd->long_attack_atk_rate)/100;
+				cardfix = cardfix * ( 100 + sd->bonus.long_attack_atk_rate ) / 100;
 
 			if( cardfix != 1000 || cardfix_ != 1000 )
 				ATK_RATE2(cardfix/10, cardfix_/10);	//What happens if you use right-to-left and there's no right weapon, only left?
@@ -2930,25 +2926,23 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 		if( sstatus->race != RC_DEMIHUMAN )
 			cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100;
 
-		for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ )
-		{
-			if( tsd->add_def[i].class_ == s_class )
-			{
+		for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ ) {
+			if( tsd->add_def[i].class_ == s_class ) {
 				cardfix=cardfix*(100-tsd->add_def[i].rate)/100;
 				break;
 			}
 		}
 
 		if( wd.flag&BF_SHORT )
-			cardfix=cardfix*(100-tsd->near_attack_def_rate)/100;
+			cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100;
 		else	// BF_LONG (there's no other choice)
-			cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
+			cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100;
 
 		if( tsd->sc.data[SC_DEF_RATE] )
-			cardfix=cardfix*(100-tsd->sc.data[SC_DEF_RATE]->val1)/100;
+			cardfix = cardfix * ( 100 - tsd->sc.data[SC_DEF_RATE]->val1 ) / 100;
 
 		if( cardfix != 1000 )
-			ATK_RATE(cardfix/10);
+			ATK_RATE( cardfix / 10 );
 	}
 
 	if( flag.infdef )
@@ -3495,7 +3489,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 						break;
 					case LG_SHIELDSPELL:// [(Caster’s Base Level x 4) + (Shield MDEF x 100) + (Caster’s INT x 2)] %
 					if( sd ) { 
-						skillratio = status_get_lv(src) * 4 + sd->shieldmdef * 100 + status_get_int(src) * 2;
+						skillratio = status_get_lv(src) * 4 + sd->bonus.shieldmdef * 100 + status_get_int(src) * 2;
 					} else
 						skillratio += 1900;	//2000%	
 						break;
@@ -3627,9 +3621,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 
 			//Ignore Defense?
 			if (!flag.imdef && (
-				sd->ignore_mdef_ele & (1<<tstatus->def_ele) ||
-				sd->ignore_mdef_race & (1<<tstatus->race) ||
-				sd->ignore_mdef_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS)
+				sd->bonus.ignore_mdef_ele & ( 1 << tstatus->def_ele ) ||
+				sd->bonus.ignore_mdef_race & ( 1 << tstatus->race ) ||
+				sd->bonus.ignore_mdef_race & ( is_boss(target) ? 1 << RC_BOSS : 1 << RC_NONBOSS )
 			))
 				flag.imdef = 1;
 		}
@@ -3744,18 +3738,18 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 				}
 			}
 			//It was discovered that ranged defense also counts vs magic! [Skotlex]
-			if (ad.flag&BF_SHORT)
-				cardfix=cardfix*(100-tsd->near_attack_def_rate)/100;
+			if ( ad.flag&BF_SHORT )
+				cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100;
 			else
-				cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
+				cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100;
 
-			cardfix=cardfix*(100-tsd->magic_def_rate)/100;
+			cardfix = cardfix * ( 100 - tsd->bonus.magic_def_rate ) / 100;
 
 			if( tsd->sc.data[SC_MDEF_RATE] )
-				cardfix=cardfix*(100-tsd->sc.data[SC_MDEF_RATE]->val1)/100;
+				cardfix = cardfix * ( 100 - tsd->sc.data[SC_MDEF_RATE]->val1 ) / 100;
 
 			if (cardfix != 1000)
-				MATK_RATE(cardfix/10);
+				MATK_RATE( cardfix / 10 );
 		}
 	}
 
@@ -4044,14 +4038,14 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 		if( sstatus->race != RC_DEMIHUMAN )
 			cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100;
 
-		cardfix=cardfix*(100-tsd->misc_def_rate)/100;
-		if(md.flag&BF_SHORT)
-			cardfix=cardfix*(100-tsd->near_attack_def_rate)/100;
+		cardfix = cardfix * ( 100 - tsd->bonus.misc_def_rate ) / 100;
+		if( md.flag&BF_SHORT )
+			cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100;
 		else	// BF_LONG (there's no other choice)
-			cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
+			cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100;
 
 		if (cardfix != 10000)
-			md.damage=(int)((int64)md.damage*cardfix/10000);
+			md.damage= (int)( (int64)md.damage * cardfix / 10000 );
 	}
 
 	if (sd && (i = pc_skillatk_bonus(sd, skill_num)))
@@ -4133,8 +4127,8 @@ int battle_calc_return_damage(struct block_list* bl, struct block_list *src, int
 		rdamage = (*dmg) * sc->data[SC_REFLECTDAMAGE]->val2 / 100;
 		if( rdamage > max_damage ) rdamage = max_damage;
 	} else if (flag & BF_SHORT) {//Bounces back part of the damage.
-		if (sd && sd->short_weapon_damage_return){
-			rdamage += damage * sd->short_weapon_damage_return / 100;
+		if ( sd && sd->bonus.short_weapon_damage_return ) {
+			rdamage += damage * sd->bonus.short_weapon_damage_return / 100;
 			if(rdamage < 1) rdamage = 1;
 		}
 		if( sc && sc->count ) {
@@ -4162,8 +4156,8 @@ int battle_calc_return_damage(struct block_list* bl, struct block_list *src, int
 			}
 		}
 	} else {
-		if (sd && sd->long_weapon_damage_return) {
-			rdamage += damage * sd->long_weapon_damage_return / 100;
+		if (sd && sd->bonus.long_weapon_damage_return) {
+			rdamage += damage * sd->bonus.long_weapon_damage_return / 100;
 			if (rdamage < 1) rdamage = 1;
 		}
 	}
@@ -4205,8 +4199,8 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage,
 		}
 	}
 
-	if (sd->sp_vanish_rate && rnd()%1000 < sd->sp_vanish_rate)
-		status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->sp_vanish_per, false);
+	if (sd->bonus.sp_vanish_rate && rnd()%1000 < sd->bonus.sp_vanish_rate)
+		status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->bonus.sp_vanish_per, false);
 
 	if( sd->sp_gain_race_attack[race] )
 		tsp += sd->sp_gain_race_attack[race];
@@ -4464,7 +4458,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 
 	wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2);
 
-	if (sd && sd->splash_range > 0 && damage > 0)
+	if (sd && sd->bonus.splash_range > 0 && damage > 0)
 		skill_castend_damage_id(src, target, 0, 1, tick, 0);
 
 	map_freeblock_lock();

+ 2 - 3
src/map/mob.c

@@ -2427,9 +2427,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 			}
 			
 			// process script-granted zeny bonus (get_zeny_num) [Skotlex]
-			if(sd->get_zeny_num && rnd()%100 < sd->get_zeny_rate)
-			{
-				i = sd->get_zeny_num > 0?sd->get_zeny_num:-md->level*sd->get_zeny_num;
+			if( sd->bonus.get_zeny_num && rnd()%100 < sd->bonus.get_zeny_rate ) {
+				i = sd->bonus.get_zeny_num > 0 ? sd->bonus.get_zeny_num : -md->level * sd->bonus.get_zeny_num;
 				if (!i) i = 1;
 				pc_getzeny(sd, 1+rnd()%i);
 			}

+ 80 - 82
src/map/pc.c

@@ -2072,7 +2072,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 			status->mdef = cap_value(bonus, CHAR_MIN, CHAR_MAX);
 #endif
 			if( sd->state.lr_flag == 3 ) {//Shield, used for royal guard
-				sd->shieldmdef += bonus;
+				sd->bonus.shieldmdef += bonus;
 			}
 		}
 		break;
@@ -2087,7 +2087,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 			bonus = status->hit + val;
 			status->hit = cap_value(bonus, SHRT_MIN, SHRT_MAX);
 		} else
-			sd->arrow_hit+=val;
+			sd->bonus.arrow_hit+=val;
 		break;
 	case SP_FLEE1:
 		if(sd->state.lr_flag != 2) {
@@ -2106,7 +2106,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 			bonus = status->cri + val*10;
 			status->cri = cap_value(bonus, SHRT_MIN, SHRT_MAX);
 		} else
-			sd->arrow_cri += val*10;
+			sd->bonus.arrow_cri += val*10;
 		break;
 	case SP_ATKELE:
 		if(val >= ELE_MAX) {
@@ -2127,7 +2127,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 					status->rhw.ele=val;
 					break;
 				default: //Become arrow element.
-					sd->arrow_ele=val;
+					sd->bonus.arrow_ele=val;
 					break;
 			}
 			break;
@@ -2200,15 +2200,15 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 		break;
 	case SP_SPEED_RATE:	//Non stackable increase
 		if(sd->state.lr_flag != 2)
-			sd->speed_rate = min(sd->speed_rate, -val);
+			sd->bonus.speed_rate = min(sd->bonus.speed_rate, -val);
 		break;
 	case SP_SPEED_ADDRATE:	//Stackable increase
 		if(sd->state.lr_flag != 2)
-			sd->speed_add_rate -= val;
+			sd->bonus.speed_add_rate -= val;
 		break;
 	case SP_ASPD:	//Raw increase
 		if(sd->state.lr_flag != 2)
-			sd->aspd_add -= 10*val;
+			sd->bonus.aspd_add -= 10*val;
 		break;
 	case SP_ASPD_RATE:	//Stackable increase - Made it linear as per rodatazone
 		if(sd->state.lr_flag != 2)
@@ -2224,23 +2224,23 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 		break;
 	case SP_CRITICAL_DEF:
 		if(sd->state.lr_flag != 2)
-			sd->critical_def += val;
+			sd->bonus.critical_def += val;
 		break;
 	case SP_NEAR_ATK_DEF:
 		if(sd->state.lr_flag != 2)
-			sd->near_attack_def_rate += val;
+			sd->bonus.near_attack_def_rate += val;
 		break;
 	case SP_LONG_ATK_DEF:
 		if(sd->state.lr_flag != 2)
-			sd->long_attack_def_rate += val;
+			sd->bonus.long_attack_def_rate += val;
 		break;
 	case SP_DOUBLE_RATE:
-		if(sd->state.lr_flag == 0 && sd->double_rate < val)
-			sd->double_rate = val;
+		if(sd->state.lr_flag == 0 && sd->bonus.double_rate < val)
+			sd->bonus.double_rate = val;
 		break;
 	case SP_DOUBLE_ADD_RATE:
 		if(sd->state.lr_flag == 0)
-			sd->double_add_rate += val;
+			sd->bonus.double_add_rate += val;
 		break;
 	case SP_MATK_RATE:
 		if(sd->state.lr_flag != 2)
@@ -2264,15 +2264,15 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 		break;
 	case SP_ATK_RATE:
 		if(sd->state.lr_flag != 2)
-			sd->atk_rate += val;
+			sd->bonus.atk_rate += val;
 		break;
 	case SP_MAGIC_ATK_DEF:
 		if(sd->state.lr_flag != 2)
-			sd->magic_def_rate += val;
+			sd->bonus.magic_def_rate += val;
 		break;
 	case SP_MISC_ATK_DEF:
 		if(sd->state.lr_flag != 2)
-			sd->misc_def_rate += val;
+			sd->bonus.misc_def_rate += val;
 		break;
 	case SP_IGNORE_MDEF_RATE:
 		if(sd->state.lr_flag != 2) {
@@ -2286,19 +2286,19 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 			break;
 		}
 		if(sd->state.lr_flag != 2)
-			sd->ignore_mdef_ele |= 1<<val;
+			sd->bonus.ignore_mdef_ele |= 1<<val;
 		break;
 	case SP_IGNORE_MDEF_RACE:
 		if(sd->state.lr_flag != 2)
-			sd->ignore_mdef_race |= 1<<val;
+			sd->bonus.ignore_mdef_race |= 1<<val;
 		break;
 	case SP_PERFECT_HIT_RATE:
-		if(sd->state.lr_flag != 2 && sd->perfect_hit < val)
-			sd->perfect_hit = val;
+		if(sd->state.lr_flag != 2 && sd->bonus.perfect_hit < val)
+			sd->bonus.perfect_hit = val;
 		break;
 	case SP_PERFECT_HIT_ADD_RATE:
 		if(sd->state.lr_flag != 2)
-			sd->perfect_hit_add += val;
+			sd->bonus.perfect_hit_add += val;
 		break;
 	case SP_CRITICAL_RATE:
 		if(sd->state.lr_flag != 2)
@@ -2401,23 +2401,23 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 			sd->special_state.no_knockback = 1;
 		break;
 	case SP_SPLASH_RANGE:
-		if(sd->splash_range < val)
-			sd->splash_range = val;
+		if(sd->bonus.splash_range < val)
+			sd->bonus.splash_range = val;
 		break;
 	case SP_SPLASH_ADD_RANGE:
-		sd->splash_add_range += val;
+		sd->bonus.splash_add_range += val;
 		break;
 	case SP_SHORT_WEAPON_DAMAGE_RETURN:
 		if(sd->state.lr_flag != 2)
-			sd->short_weapon_damage_return += val;
+			sd->bonus.short_weapon_damage_return += val;
 		break;
 	case SP_LONG_WEAPON_DAMAGE_RETURN:
 		if(sd->state.lr_flag != 2)
-			sd->long_weapon_damage_return += val;
+			sd->bonus.long_weapon_damage_return += val;
 		break;
 	case SP_MAGIC_DAMAGE_RETURN: //AppleGirl Was Here
 		if(sd->state.lr_flag != 2)
-			sd->magic_damage_return += val;
+			sd->bonus.magic_damage_return += val;
 		break;
 	case SP_ALL_STATS:	// [Valaris]
 		if(sd->state.lr_flag!=2) {
@@ -2448,51 +2448,51 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 		break;
 	case SP_UNBREAKABLE:
 		if(sd->state.lr_flag!=2)
-			sd->unbreakable += val;
+			sd->bonus.unbreakable += val;
 		break;
 	case SP_UNBREAKABLE_WEAPON:
 		if(sd->state.lr_flag != 2)
-			sd->unbreakable_equip |= EQP_WEAPON;
+			sd->bonus.unbreakable_equip |= EQP_WEAPON;
 		break;
 	case SP_UNBREAKABLE_ARMOR:
 		if(sd->state.lr_flag != 2)
-			sd->unbreakable_equip |= EQP_ARMOR;
+			sd->bonus.unbreakable_equip |= EQP_ARMOR;
 		break;
 	case SP_UNBREAKABLE_HELM:
 		if(sd->state.lr_flag != 2)
-			sd->unbreakable_equip |= EQP_HELM;
+			sd->bonus.unbreakable_equip |= EQP_HELM;
 		break;
 	case SP_UNBREAKABLE_SHIELD:
 		if(sd->state.lr_flag != 2)
-			sd->unbreakable_equip |= EQP_SHIELD;
+			sd->bonus.unbreakable_equip |= EQP_SHIELD;
 		break;
 	case SP_UNBREAKABLE_GARMENT:
 		if(sd->state.lr_flag != 2)
-			sd->unbreakable_equip |= EQP_GARMENT;
+			sd->bonus.unbreakable_equip |= EQP_GARMENT;
 		break;
 	case SP_UNBREAKABLE_SHOES:
 		if(sd->state.lr_flag != 2)
-			sd->unbreakable_equip |= EQP_SHOES;
+			sd->bonus.unbreakable_equip |= EQP_SHOES;
 		break;
 	case SP_CLASSCHANGE: // [Valaris]
 		if(sd->state.lr_flag !=2)
-			sd->classchange=val;
+			sd->bonus.classchange=val;
 		break;
 	case SP_LONG_ATK_RATE:
 		if(sd->state.lr_flag != 2)	//[Lupus] it should stack, too. As any other cards rate bonuses
-			sd->long_attack_atk_rate+=val;
+			sd->bonus.long_attack_atk_rate+=val;
 		break;
 	case SP_BREAK_WEAPON_RATE:
 		if(sd->state.lr_flag != 2)
-			sd->break_weapon_rate+=val;
+			sd->bonus.break_weapon_rate+=val;
 		break;
 	case SP_BREAK_ARMOR_RATE:
 		if(sd->state.lr_flag != 2)
-			sd->break_armor_rate+=val;
+			sd->bonus.break_armor_rate+=val;
 		break;
 	case SP_ADD_STEAL_RATE:
 		if(sd->state.lr_flag != 2)
-			sd->add_steal_rate+=val;
+			sd->bonus.add_steal_rate+=val;
 		break;
 	case SP_DELAYRATE:
 		if(sd->state.lr_flag != 2)
@@ -2500,7 +2500,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 		break;
 	case SP_CRIT_ATK_RATE:
 		if(sd->state.lr_flag != 2)
-			sd->crit_atk_rate += val;
+			sd->bonus.crit_atk_rate += val;
 		break;
 	case SP_NO_REGEN:
 		if(sd->state.lr_flag != 2)
@@ -2508,20 +2508,20 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 		break;
 	case SP_UNSTRIPABLE_WEAPON:
 		if(sd->state.lr_flag != 2)
-			sd->unstripable_equip |= EQP_WEAPON;
+			sd->bonus.unstripable_equip |= EQP_WEAPON;
 		break;
 	case SP_UNSTRIPABLE:
 	case SP_UNSTRIPABLE_ARMOR:
 		if(sd->state.lr_flag != 2)
-			sd->unstripable_equip |= EQP_ARMOR;
+			sd->bonus.unstripable_equip |= EQP_ARMOR;
 		break;
 	case SP_UNSTRIPABLE_HELM:
 		if(sd->state.lr_flag != 2)
-			sd->unstripable_equip |= EQP_HELM;
+			sd->bonus.unstripable_equip |= EQP_HELM;
 		break;
 	case SP_UNSTRIPABLE_SHIELD:
 		if(sd->state.lr_flag != 2)
-			sd->unstripable_equip |= EQP_SHIELD;
+			sd->bonus.unstripable_equip |= EQP_SHIELD;
 		break;
 	case SP_HP_DRAIN_VALUE:
 		if(!sd->state.lr_flag) {
@@ -2545,39 +2545,39 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 		break;
 	case SP_SP_GAIN_VALUE:
 		if(!sd->state.lr_flag)
-			sd->sp_gain_value += val;
+			sd->bonus.sp_gain_value += val;
 		break;
 	case SP_HP_GAIN_VALUE:
 		if(!sd->state.lr_flag)
-			sd->hp_gain_value += val;
+			sd->bonus.hp_gain_value += val;
 		break;
 	case SP_MAGIC_SP_GAIN_VALUE:
 		if(!sd->state.lr_flag)
-			sd->magic_sp_gain_value += val;
+			sd->bonus.magic_sp_gain_value += val;
 		break;
 	case SP_MAGIC_HP_GAIN_VALUE:
 		if(!sd->state.lr_flag)
-			sd->magic_hp_gain_value += val;
+			sd->bonus.magic_hp_gain_value += val;
 		break;
 	case SP_ADD_HEAL_RATE:
 		if(sd->state.lr_flag != 2)
-			sd->add_heal_rate += val;
+			sd->bonus.add_heal_rate += val;
 		break;
 	case SP_ADD_HEAL2_RATE:
 		if(sd->state.lr_flag != 2)
-			sd->add_heal2_rate += val;
+			sd->bonus.add_heal2_rate += val;
 		break;
 	case SP_ADD_ITEM_HEAL_RATE:
 		if(sd->state.lr_flag != 2)
-			sd->itemhealrate2 += val;
+			sd->bonus.itemhealrate2 += val;
 		break;
 	case SP_WEAPON_MATK:
 		if(sd->state.lr_flag != 2)
-			sd->sp_weapon_matk += val;
+			sd->bonus.sp_weapon_matk += val;
 		break;
 	case SP_BASE_MATK:
 		if(sd->state.lr_flag != 2)
-			sd->sp_base_matk += val;
+			sd->bonus.sp_base_matk += val;
 		break;
 	default:
 		ShowWarning("pc_bonus: unknown type %d %d !\n",type,val);
@@ -2806,22 +2806,20 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
 		break;
 	case SP_SP_VANISH_RATE:
 		if(sd->state.lr_flag != 2) {
-			sd->sp_vanish_rate += type2;
-			sd->sp_vanish_per += val;
+			sd->bonus.sp_vanish_rate += type2;
+			sd->bonus.sp_vanish_per += val;
 		}
 		break;
 	case SP_GET_ZENY_NUM:
-		if(sd->state.lr_flag != 2 && sd->get_zeny_rate < val)
-		{
-			sd->get_zeny_rate = val;
-			sd->get_zeny_num = type2;
+		if(sd->state.lr_flag != 2 && sd->bonus.get_zeny_rate < val) {
+			sd->bonus.get_zeny_rate = val;
+			sd->bonus.get_zeny_num = type2;
 		}
 		break;
 	case SP_ADD_GET_ZENY_NUM:
-		if(sd->state.lr_flag != 2)
-		{
-			sd->get_zeny_rate += val;
-			sd->get_zeny_num += type2;
+		if(sd->state.lr_flag != 2) {
+			sd->bonus.get_zeny_rate += val;
+			sd->bonus.get_zeny_num += type2;
 		}
 		break;
 	case SP_WEAPON_COMA_ELE:
@@ -4301,7 +4299,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, int lv)
 
 	// base skill success chance (percentual)
 	rate = (sd_status->dex - md_status->dex)/2 + lv*6 + 4;
-	rate += sd->add_steal_rate;
+	rate += sd->bonus.add_steal_rate;
 		
 	if( rate < 1 )
 		return 0;
@@ -6085,34 +6083,34 @@ int pc_skillatk_bonus(struct map_session_data *sd, int skill_num)
 	return bonus;
 }
 
-int pc_skillheal_bonus(struct map_session_data *sd, int skill_num)
-{
-	int i, bonus = sd->add_heal_rate;
+int pc_skillheal_bonus(struct map_session_data *sd, int skill_num) {
+	int i, bonus = sd->bonus.add_heal_rate;
 
-	if( bonus )
-	{
-		switch( skill_num )
-		{
-		case AL_HEAL:           if( !(battle_config.skill_add_heal_rate&1) ) bonus = 0; break;
-		case PR_SANCTUARY:      if( !(battle_config.skill_add_heal_rate&2) ) bonus = 0; break;
-		case AM_POTIONPITCHER:  if( !(battle_config.skill_add_heal_rate&4) ) bonus = 0; break;
-		case CR_SLIMPITCHER:    if( !(battle_config.skill_add_heal_rate&8) ) bonus = 0; break;
-		case BA_APPLEIDUN:      if( !(battle_config.skill_add_heal_rate&16)) bonus = 0; break;
+	if( bonus ) {
+		switch( skill_num ) {
+			case AL_HEAL:           if( !(battle_config.skill_add_heal_rate&1) ) bonus = 0; break;
+			case PR_SANCTUARY:      if( !(battle_config.skill_add_heal_rate&2) ) bonus = 0; break;
+			case AM_POTIONPITCHER:  if( !(battle_config.skill_add_heal_rate&4) ) bonus = 0; break;
+			case CR_SLIMPITCHER:    if( !(battle_config.skill_add_heal_rate&8) ) bonus = 0; break;
+			case BA_APPLEIDUN:      if( !(battle_config.skill_add_heal_rate&16)) bonus = 0; break;
 		}
 	}
 
 	ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == skill_num);
-	if( i < ARRAYLENGTH(sd->skillheal) ) bonus += sd->skillheal[i].val;
+	
+	if( i < ARRAYLENGTH(sd->skillheal) )
+		bonus += sd->skillheal[i].val;
 
 	return bonus;
 }
 
-int pc_skillheal2_bonus(struct map_session_data *sd, int skill_num)
-{
-	int i, bonus = sd->add_heal2_rate;
+int pc_skillheal2_bonus(struct map_session_data *sd, int skill_num) {
+	int i, bonus = sd->bonus.add_heal2_rate;
 
 	ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == skill_num);
-	if( i < ARRAYLENGTH(sd->skillheal2) ) bonus += sd->skillheal2[i].val;
+	
+	if( i < ARRAYLENGTH(sd->skillheal2) )
+		bonus += sd->skillheal2[i].val;
 
 	return bonus;
 }
@@ -6725,7 +6723,7 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
 		if (potion_flag > 1)
 			bonus += bonus*(potion_flag-1)*50/100;
 		//All item bonuses.
-		bonus += sd->itemhealrate2;
+		bonus += sd->bonus.itemhealrate2;
 		//Item Group bonuses
 		bonus += bonus*itemdb_group_bonus(sd, itemid)/100;
 		//Individual item bonuses.

+ 35 - 33
src/map/pc.h

@@ -284,39 +284,41 @@ struct map_session_data {
 	struct s_autobonus autobonus[MAX_PC_BONUS], autobonus2[MAX_PC_BONUS], autobonus3[MAX_PC_BONUS]; //Auto script on attack, when attacked, on skill usage
 	// manually zeroed structures end here.
 	// zeroed vars start here.
-	int atk_rate;
-	int arrow_atk,arrow_ele,arrow_cri,arrow_hit;
-	int nsshealhp,nsshealsp;
-	int critical_def,double_rate;
-	int long_attack_atk_rate; //Long range atk rate, not weapon based. [Skotlex]
-	int near_attack_def_rate,long_attack_def_rate,magic_def_rate,misc_def_rate;
-	int ignore_mdef_ele;
-	int ignore_mdef_race;
-	int perfect_hit;
-	int perfect_hit_add;
-	int get_zeny_rate;
-	int get_zeny_num; //Added Get Zeny Rate [Skotlex]
-	int double_add_rate;
-	int short_weapon_damage_return,long_weapon_damage_return;
-	int magic_damage_return; // AppleGirl Was Here
-	int break_weapon_rate,break_armor_rate;
-	int crit_atk_rate;
-	int classchange; // [Valaris]
-	int speed_rate, speed_add_rate, aspd_add;
-	int itemhealrate2; // [Epoque] Increase heal rate of all healing items.
-	int shieldmdef;//royal guard's
-	unsigned int setitem_hash, setitem_hash2; //Split in 2 because shift operations only work on int ranges. [Skotlex]
-	
-	short splash_range, splash_add_range;
-	short add_steal_rate;
-	short add_heal_rate, add_heal2_rate;
-	short sp_gain_value, hp_gain_value, magic_sp_gain_value, magic_hp_gain_value;
-	short sp_vanish_rate;
-	short sp_vanish_per;
-	short sp_weapon_matk,sp_base_matk;
-	unsigned short unbreakable;	// chance to prevent ANY equipment breaking [celest]
-	unsigned short unbreakable_equip; //100% break resistance on certain equipment
-	unsigned short unstripable_equip;
+	struct {
+		int atk_rate;
+		int arrow_atk,arrow_ele,arrow_cri,arrow_hit;
+		int nsshealhp,nsshealsp;
+		int critical_def,double_rate;
+		int long_attack_atk_rate; //Long range atk rate, not weapon based. [Skotlex]
+		int near_attack_def_rate,long_attack_def_rate,magic_def_rate,misc_def_rate;
+		int ignore_mdef_ele;
+		int ignore_mdef_race;
+		int perfect_hit;
+		int perfect_hit_add;
+		int get_zeny_rate;
+		int get_zeny_num; //Added Get Zeny Rate [Skotlex]
+		int double_add_rate;
+		int short_weapon_damage_return,long_weapon_damage_return;
+		int magic_damage_return; // AppleGirl Was Here
+		int break_weapon_rate,break_armor_rate;
+		int crit_atk_rate;
+		int classchange; // [Valaris]
+		int speed_rate, speed_add_rate, aspd_add;
+		int itemhealrate2; // [Epoque] Increase heal rate of all healing items.
+		int shieldmdef;//royal guard's
+		unsigned int setitem_hash, setitem_hash2; //Split in 2 because shift operations only work on int ranges. [Skotlex]
+
+		short splash_range, splash_add_range;
+		short add_steal_rate;
+		short add_heal_rate, add_heal2_rate;
+		short sp_gain_value, hp_gain_value, magic_sp_gain_value, magic_hp_gain_value;
+		short sp_vanish_rate;
+		short sp_vanish_per;
+		short sp_weapon_matk,sp_base_matk;
+		unsigned short unbreakable;	// chance to prevent ANY equipment breaking [celest]
+		unsigned short unbreakable_equip; //100% break resistance on certain equipment
+		unsigned short unstripable_equip;
+	} bonus;
 
 	// zeroed vars end here.
 

+ 10 - 13
src/map/script.c

@@ -12611,16 +12611,14 @@ BUILDIN_FUNC(isequipped)
 		return 0;
 	}
 
-	setitem_hash = sd->setitem_hash;
-	setitem_hash2 = sd->setitem_hash2;
-	for (i=0; id!=0; i++)
-	{
+	setitem_hash = sd->bonus.setitem_hash;
+	setitem_hash2 = sd->bonus.setitem_hash2;
+	for (i=0; id!=0; i++) {
 		FETCH (i+2, id) else id = 0;
 		if (id <= 0)
 			continue;
 		flag = 0;
-		for (j=0; j<EQI_MAX; j++)
-		{
+		for (j=0; j<EQI_MAX; j++) {
 			index = sd->equip_index[j];
 			if(index < 0) continue;
 			if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue;
@@ -12648,16 +12646,16 @@ BUILDIN_FUNC(isequipped)
 
 					hash = 1<<((j<5?j:j-5)*4 + k);
 					// check if card is already used by another set
-					if ((j<5?sd->setitem_hash:sd->setitem_hash2) & hash)
+					if ( ( j < 5 ? sd->bonus.setitem_hash : sd->bonus.setitem_hash2 ) & hash)
 						continue;
 
 					// We have found a match
 					flag = 1;
 					// Set hash so this card cannot be used by another
 					if (j<5)
-						sd->setitem_hash |= hash;
+						sd->bonus.setitem_hash |= hash;
 					else
-						sd->setitem_hash2 |= hash;
+						sd->bonus.setitem_hash2 |= hash;
 					break;
 				}
 			}
@@ -12669,10 +12667,9 @@ BUILDIN_FUNC(isequipped)
 			ret &= flag;
 		if (!ret) break;
 	}
-	if (!ret)
-  	{	//When check fails, restore original hash values. [Skotlex]
-		sd->setitem_hash = setitem_hash;
-		sd->setitem_hash2 = setitem_hash2;
+	if (!ret) {//When check fails, restore original hash values. [Skotlex]
+		sd->bonus.setitem_hash = setitem_hash;
+		sd->bonus.setitem_hash2 = setitem_hash2;
 	}
 	script_pushint(st,ret);
 	return 0;

+ 21 - 24
src/map/skill.c

@@ -1391,7 +1391,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 			// Target weapon breaking
 			rate = 0;
 			if( sd )
-				rate += sd->break_weapon_rate;
+				rate += sd->bonus.break_weapon_rate;
 			if( sc && sc->data[SC_MELTDOWN] )
 				rate += sc->data[SC_MELTDOWN]->val2;
 			if( rate )
@@ -1400,7 +1400,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 			// Target armor breaking
 			rate = 0;
 			if( sd )
-				rate += sd->break_armor_rate;
+				rate += sd->bonus.break_armor_rate;
 			if( sc && sc->data[SC_MELTDOWN] )
 				rate += sc->data[SC_MELTDOWN]->val3;
 			if( rate )
@@ -1522,9 +1522,9 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 	}
 
 	//Polymorph
-	if(sd && sd->classchange && attack_type&BF_WEAPON &&
+	if(sd && sd->bonus.classchange && attack_type&BF_WEAPON &&
 		dstmd && !(tstatus->mode&MD_BOSS) &&
-		(rnd()%10000 < sd->classchange))
+		(rnd()%10000 < sd->bonus.classchange))
 	{
 		struct mob_db *mob;
 		int class_;
@@ -1726,19 +1726,17 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 		status_heal(src, 0, status_get_lv(bl)*(95+15*rate)/100, 2);
 	}
 
-	if( sd && status_isdead(bl) )
-	{
+	if( sd && status_isdead(bl) ) {
 		int sp = 0, hp = 0;
-		if( attack_type&BF_WEAPON )
-		{
-			sp += sd->sp_gain_value;
+		if( attack_type&BF_WEAPON ) {
+			sp += sd->bonus.sp_gain_value;
 			sp += sd->sp_gain_race[status_get_race(bl)];
 			sp += sd->sp_gain_race[is_boss(bl)?RC_BOSS:RC_NONBOSS];
-			hp += sd->hp_gain_value;
+			hp += sd->bonus.hp_gain_value;
 		}
 		if( attack_type&BF_MAGIC ) {
-			sp += sd->magic_sp_gain_value;
-			hp += sd->magic_hp_gain_value;
+			sp += sd->bonus.magic_sp_gain_value;
+			hp += sd->bonus.magic_hp_gain_value;
 			if( skillid == WZ_WATERBALL ) {//(bugreport:5303)
 				struct status_change *sc = NULL;
 				if( ( sc = status_get_sc(src) ) ) {
@@ -1749,8 +1747,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 				}
 			}
 		}
-		if( hp || sp )
-		{// updated to force healing to allow healing through berserk
+		if( hp || sp ) { // updated to force healing to allow healing through berserk
 			status_heal(src, hp, sp, battle_config.show_hp_sp_gain ? 3 : 1);
 		}
 	}
@@ -1887,10 +1884,10 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in
 		sc = NULL;
 
 	if (sd) {
-		if (sd->unbreakable_equip)
-			where &= ~sd->unbreakable_equip;
-		if (sd->unbreakable)
-			rate -= rate*sd->unbreakable/100;
+		if (sd->bonus.unbreakable_equip)
+			where &= ~sd->bonus.unbreakable_equip;
+		if (sd->bonus.unbreakable)
+			rate -= rate*sd->bonus.unbreakable/100;
 		if (where&EQP_WEAPON) {
 			switch (sd->status.weapon) {
 				case W_FIST:	//Bare fists should not break :P
@@ -2059,7 +2056,7 @@ static int skill_magic_reflect(struct block_list* src, struct block_list* bl, in
 	struct map_session_data* sd = BL_CAST(BL_PC, bl);
 
 	// item-based reflection
-	if( sd && sd->magic_damage_return && type && rnd()%100 < sd->magic_damage_return )
+	if( sd && sd->bonus.magic_damage_return && type && rnd()%100 < sd->bonus.magic_damage_return )
 		return 1;
 
 	if( is_boss(src) )
@@ -4484,7 +4481,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 			} else {
 				skill_area_temp[1] = bl->id;
 				map_foreachinrange(skill_area_sub, bl,
-					sd->splash_range, BL_CHAR,
+					sd->bonus.splash_range, BL_CHAR,
 					src, skillid, skilllv, tick, flag | BCT_ENEMY | 1,
 					skill_castend_damage_id);
 				flag|=1; //Set flag to 1 so ammo is not double-consumed. [Skotlex]
@@ -7926,7 +7923,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 
 	case LG_SHIELDSPELL:
 		if( flag&1 ) {
-			int duration = (sd) ? sd->shieldmdef * 2000 : 10000;
+			int duration = (sd) ? sd->bonus.shieldmdef * 2000 : 10000;
 			sc_start(bl,SC_SILENCE,100,skilllv,duration);
 		} else if( sd ) {
 			int opt = skilllv;
@@ -7969,7 +7966,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 					break;
 
 				case 2:
-					brate = sd->shieldmdef * 20;
+					brate = sd->bonus.shieldmdef * 20;
 					if( rate < 30 )
 						opt = 1;
 					else if( rate < 60 )
@@ -7991,9 +7988,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 								map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id);
 							break;
 						case 3:
-							if( sc_start(bl,SC_SHIELDSPELL_MDEF,brate,opt,sd->shieldmdef * 30000) )
+							if( sc_start(bl,SC_SHIELDSPELL_MDEF,brate,opt,sd->bonus.shieldmdef * 30000) )
 								clif_skill_nodamage(src,bl,PR_MAGNIFICAT,skilllv,
-								sc_start(bl,SC_MAGNIFICAT,100,1,sd->shieldmdef * 30000));
+								sc_start(bl,SC_MAGNIFICAT,100,1,sd->bonus.shieldmdef * 30000));
 							break;
 					}
 					break;

+ 25 - 83
src/map/status.c

@@ -1750,10 +1750,10 @@ int status_base_amotion_pc(struct map_session_data* sd, struct status_data* stat
 	 : (aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype1] + aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype2])*7/10; // dual-wield
 	
 	// percentual delay reduction from stats
-	amotion-= amotion * (4*status->agi + status->dex)/1000;
+	amotion -= amotion * (4*status->agi + status->dex)/1000;
 	
 	// raw delay adjustment from bAspd bonus
-	amotion+= sd->aspd_add;
+	amotion += sd->bonus.aspd_add;
 
 #ifdef RENEWAL
 	if( sd->status.shield ) {// bearing a shield decreases your ASPD by a fixed value depending on your class
@@ -2353,61 +2353,8 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 		+ sizeof(sd->subele2)
 	);
 	
-	// vars zeroing. ints, shorts, chars. in that order.
-	memset (&sd->atk_rate, 0,sizeof(sd->atk_rate)
-		+ sizeof(sd->arrow_atk)
-		+ sizeof(sd->arrow_ele)
-		+ sizeof(sd->arrow_cri)
-		+ sizeof(sd->arrow_hit)
-		+ sizeof(sd->nsshealhp)
-		+ sizeof(sd->nsshealsp)
-		+ sizeof(sd->critical_def)
-		+ sizeof(sd->double_rate)
-		+ sizeof(sd->long_attack_atk_rate)
-		+ sizeof(sd->near_attack_def_rate)
-		+ sizeof(sd->long_attack_def_rate)
-		+ sizeof(sd->magic_def_rate)
-		+ sizeof(sd->misc_def_rate)
-		+ sizeof(sd->ignore_mdef_ele)
-		+ sizeof(sd->ignore_mdef_race)
-		+ sizeof(sd->perfect_hit)
-		+ sizeof(sd->perfect_hit_add)
-		+ sizeof(sd->get_zeny_rate)
-		+ sizeof(sd->get_zeny_num)
-		+ sizeof(sd->double_add_rate)
-		+ sizeof(sd->short_weapon_damage_return)
-		+ sizeof(sd->long_weapon_damage_return)
-		+ sizeof(sd->magic_damage_return)
-		+ sizeof(sd->break_weapon_rate)
-		+ sizeof(sd->break_armor_rate)
-		+ sizeof(sd->crit_atk_rate)
-		+ sizeof(sd->classchange)
-		+ sizeof(sd->speed_rate)
-		+ sizeof(sd->speed_add_rate)
-		+ sizeof(sd->aspd_add)
-		+ sizeof(sd->setitem_hash)
-		+ sizeof(sd->setitem_hash2)
-		+ sizeof(sd->itemhealrate2)
-		+ sizeof(sd->shieldmdef)
-		// shorts
-		+ sizeof(sd->splash_range)
-		+ sizeof(sd->splash_add_range)
-		+ sizeof(sd->add_steal_rate)
-		+ sizeof(sd->add_heal_rate)
-		+ sizeof(sd->add_heal2_rate)
-		+ sizeof(sd->hp_gain_value)
-		+ sizeof(sd->sp_gain_value)
-		+ sizeof(sd->magic_hp_gain_value)
-		+ sizeof(sd->magic_sp_gain_value)
-		+ sizeof(sd->sp_vanish_rate)
-		+ sizeof(sd->sp_vanish_per)
-		+ sizeof(sd->sp_weapon_matk)
-		+ sizeof(sd->sp_base_matk)
-		+ sizeof(sd->unbreakable)
-		+ sizeof(sd->unbreakable_equip)
-		+ sizeof(sd->unstripable_equip)
-		);
-
+	memset (&sd->bonus, 0,sizeof(sd->bonus));
+	
 	// Autobonus
 	pc_delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),true);
 	pc_delautobonus(sd,sd->autobonus2,ARRAYLENGTH(sd->autobonus2),true);
@@ -2520,7 +2467,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 	if(sd->equip_index[EQI_AMMO] >= 0){
 		index = sd->equip_index[EQI_AMMO];
 		if(sd->inventory_data[index]){		// Arrows
-			sd->arrow_atk += sd->inventory_data[index]->atk;
+			sd->bonus.arrow_atk += sd->inventory_data[index]->atk;
 			sd->state.lr_flag = 2;
 			if( !itemdb_is_GNthrowable(sd->inventory_data[index]->nameid) ) //don't run scripts on throwable items
 				run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
@@ -2538,7 +2485,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 	
 #ifdef RENEWAL
 	// increment the weapon ATK using the MATK max value
-	status->matk_max += sd->sp_weapon_matk;
+	status->matk_max += sd->bonus.sp_weapon_matk;
 #endif
 
 	//Parse Cards
@@ -2622,9 +2569,9 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 	if(status->rhw.range < status->lhw.range)
 		status->rhw.range = status->lhw.range;
 
-	sd->double_rate += sd->double_add_rate;
-	sd->perfect_hit += sd->perfect_hit_add;
-	sd->splash_range += sd->splash_add_range;
+	sd->bonus.double_rate += sd->bonus.double_add_rate;
+	sd->bonus.perfect_hit += sd->bonus.perfect_hit_add;
+	sd->bonus.splash_range += sd->bonus.splash_add_range;
 
 	// Damage modifiers from weapon type
 	sd->right_weapon.atkmods[0] = atkmods[0][sd->weapontype1];
@@ -3724,7 +3671,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 #ifdef RENEWAL
 		status->matk_min = status_base_matk_min(status,status_get_lv(bl));
 		if( sd )
-			status->matk_min += sd->sp_base_matk;
+			status->matk_min += sd->bonus.sp_base_matk;
 #else
 		status->matk_min = status_base_matk_min(status);
 #endif
@@ -4922,8 +4869,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
 				if( sc->data[SC_MELON_BOMB] )
 					val = max( val, sc->data[SC_MELON_BOMB]->val1 );
 
-				if( sd && sd->speed_rate + sd->speed_add_rate > 0 ) // permanent item-based speedup
-					val = max( val, sd->speed_rate + sd->speed_add_rate );
+				if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate > 0 ) // permanent item-based speedup
+					val = max( val, sd->bonus.speed_rate + sd->bonus.speed_add_rate );
 			}
 
 			speed_rate += val;
@@ -4971,8 +4918,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
 			//FIXME: official items use a single bonus for this [ultramage]
 			if( sc->data[SC_SPEEDUP0] ) // temporary item-based speedup
 				val = max( val, 25 );
-			if( sd && sd->speed_rate + sd->speed_add_rate < 0 ) // permanent item-based speedup
-				val = max( val, -(sd->speed_rate + sd->speed_add_rate) );
+			if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate < 0 ) // permanent item-based speedup
+				val = max( val, -(sd->bonus.speed_rate + sd->bonus.speed_add_rate) );
 
 			speed_rate -= val;
 		}
@@ -6207,20 +6154,16 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 		if (sd && !(flag&4)) { //apply sc anyway if loading saved sc_data
 			int i;
 			opt_flag = 0; //Reuse to check success condition.
-			if(sd->unstripable_equip&EQP_WEAPON)
+			if(sd->bonus.unstripable_equip&EQP_WEAPON)
 				return 0;
 			i = sd->equip_index[EQI_HAND_L];
-			if (i>=0 && sd->inventory_data[i] &&
-				sd->inventory_data[i]->type == IT_WEAPON)
-			{
+			if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) {
 				opt_flag|=1;
 				pc_unequipitem(sd,i,3); //L-hand weapon
 			}
 
 			i = sd->equip_index[EQI_HAND_R];
-			if (i>=0 && sd->inventory_data[i] &&
-				sd->inventory_data[i]->type == IT_WEAPON)
-			{
+			if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) {
 				opt_flag|=2;
 				pc_unequipitem(sd,i,3);
 			}
@@ -6233,11 +6176,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 		else
 		if (sd && !(flag&4)) {
 			int i;
-			if(sd->unstripable_equip&EQP_SHIELD)
+			if(sd->bonus.unstripable_equip&EQP_SHIELD)
 				return 0;
 			i = sd->equip_index[EQI_HAND_L];
-			if (i<0 || !sd->inventory_data[i] ||
-				sd->inventory_data[i]->type != IT_ARMOR)
+			if ( i < 0 || !sd->inventory_data[i] || sd->inventory_data[i]->type != IT_ARMOR )
 				return 0;
 			pc_unequipitem(sd,i,3);
 		}
@@ -6246,10 +6188,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 	case SC_STRIPARMOR:
 		if (sd && !(flag&4)) {
 			int i;
-			if(sd->unstripable_equip&EQP_ARMOR)
+			if(sd->bonus.unstripable_equip&EQP_ARMOR)
 				return 0;
 			i = sd->equip_index[EQI_ARMOR];
-			if (i<0 || !sd->inventory_data[i])
+			if ( i < 0 || !sd->inventory_data[i] )
 				return 0;
 			pc_unequipitem(sd,i,3);
 		}
@@ -6258,10 +6200,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 	case SC_STRIPHELM:
 		if (sd && !(flag&4)) {
 			int i;
-			if(sd->unstripable_equip&EQP_HELM)
+			if(sd->bonus.unstripable_equip&EQP_HELM)
 				return 0;
 			i = sd->equip_index[EQI_HEAD_TOP];
-			if (i<0 || !sd->inventory_data[i])
+			if ( i < 0 || !sd->inventory_data[i] )
 				return 0;
 			pc_unequipitem(sd,i,3);
 		}
@@ -6330,11 +6272,11 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 	case SC__STRIPACCESSORY:
 		if( sd ) {
 			int i = -1;
-			if( !(sd->unstripable_equip&EQI_ACC_L) ) {
+			if( !(sd->bonus.unstripable_equip&EQI_ACC_L) ) {
 				i = sd->equip_index[EQI_ACC_L];
 				if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR )
 					pc_unequipitem(sd,i,3); //L-Accessory
-			} if( !(sd->unstripable_equip&EQI_ACC_R) ) {
+			} if( !(sd->bonus.unstripable_equip&EQI_ACC_R) ) {
 				i = sd->equip_index[EQI_ACC_R];
 				if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR )
 					pc_unequipitem(sd,i,3); //R-Accessory