Преглед изворни кода

Fixed #141 & Changed regen rate value from 1 to 100
* 1 = 1%, 100 = 100%... previously 1 = 100%
* Increase calculation accuracy. Example for previous calculation of Concentrated_White_Potion_Z (12428) bonus to add 20% HP recovery rate always be fail, since "1*20/100" always be round down to 0, didn't add 20%!
* Vitata_500 (12436) has incomplete vals for SC

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>

Cydh Ramdh пре 10 година
родитељ
комит
071cb76bc3
4 измењених фајлова са 91 додато и 81 уклоњено
  1. 1 1
      db/re/item_db.txt
  2. 1 1
      sql-files/item_db_re.sql
  3. 83 71
      src/map/status.c
  4. 6 8
      src/map/status.h

+ 1 - 1
db/re/item_db.txt

@@ -6253,7 +6253,7 @@
 12433,Drosera_Herb_Salad,Drosera Herb Salad,2,,,50,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_DROCERA_HERB_STEAMED,300000,20; },{},{}
 12434,Petite_Tail_Noodles,Petite Tail Noodles,2,,,50,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_PUTTI_TAILS_NOODLES,300000,20; },{},{}
 12435,Black_Mass,Black Mass,2,,,50,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_STOMACHACHE,60000,rand(5,10); },{},{}
-12436,Vitata_500,Vitata 500,0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_VITATA_500,500000,0; itemheal 0,200; },{},{}
+12436,Vitata_500,Vitata 500,0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start2 SC_VITATA_500,500000,20,5; itemheal 0,200; },{},{}
 12437,Concentrated_Ceromain_Soup,Concentrated Ceromain Soup,2,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_EXTRACT_SALAMINE_JUICE,500000,10; },{},{}
 12438,F_Giant_Fly_Wing,F Giant Fly Wing,2,2,,10,,,,,0xFFFFFFFF,63,2,,,,,,{},{},{}
 12439,F_Battle_Manual,F Old Battle Manual,2,2,,10,,,,,0xFFFFFFFF,63,2,,,,,,{},{},{}

+ 1 - 1
sql-files/item_db_re.sql

@@ -6284,7 +6284,7 @@ REPLACE INTO `item_db_re` VALUES (12432,'Siroma_Iced_Tea','Siroma Iced Tea',2,NU
 REPLACE INTO `item_db_re` VALUES (12433,'Drosera_Herb_Salad','Drosera Herb Salad',2,NULL,NULL,50,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_DROCERA_HERB_STEAMED,300000,20;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12434,'Petite_Tail_Noodles','Petite Tail Noodles',2,NULL,NULL,50,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_PUTTI_TAILS_NOODLES,300000,20;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12435,'Black_Mass','Black Mass',2,NULL,NULL,50,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_STOMACHACHE,60000,rand(5,10);',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (12436,'Vitata_500','Vitata 500',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_VITATA_500,500000,0; itemheal 0,200;',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (12436,'Vitata_500','Vitata 500',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start2 SC_VITATA_500,500000,20,5; itemheal 0,200;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12437,'Concentrated_Ceromain_Soup','Concentrated Ceromain Soup',2,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_EXTRACT_SALAMINE_JUICE,500000,10;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12438,'F_Giant_Fly_Wing','F Giant Fly Wing',2,2,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12439,'F_Battle_Manual','F Old Battle Manual',2,2,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

+ 83 - 71
src/map/status.c

@@ -42,10 +42,11 @@
 
 // Regen related flags.
 enum e_regen {
-	RGN_HP  = 0x01,
-	RGN_SP  = 0x02,
-	RGN_SHP = 0x04,
-	RGN_SSP = 0x08,
+	RGN_NONE = 0x00,
+	RGN_HP   = 0x01,
+	RGN_SP   = 0x02,
+	RGN_SHP  = 0x04,
+	RGN_SSP  = 0x08,
 };
 
 // Bonus values and upgrade chances for refining equipment
@@ -937,7 +938,6 @@ void initChangeTables(void)
 
 	StatusIconChangeTable[SC_CURSEDCIRCLE_ATKER] = SI_CURSEDCIRCLE_ATKER;
 	StatusIconChangeTable[SC__BLOODYLUST] = SI_BLOODYLUST;
-	StatusIconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE;
 	StatusIconChangeTable[SC_MYSTERIOUS_POWDER] = SI_MYSTERIOUS_POWDER;
 	StatusIconChangeTable[SC_MELON_BOMB] = SI_MELON_BOMB;
 	StatusIconChangeTable[SC_BANANA_BOMB] = SI_BANANA_BOMB;
@@ -950,15 +950,15 @@ void initChangeTables(void)
 	StatusIconChangeTable[SC_SIROMA_ICE_TEA] = SI_SIROMA_ICE_TEA;
 	StatusIconChangeTable[SC_DROCERA_HERB_STEAMED] = SI_DROCERA_HERB_STEAMED;
 	StatusIconChangeTable[SC_PUTTI_TAILS_NOODLES] = SI_PUTTI_TAILS_NOODLES;
-
+	StatusIconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE;
+	StatusIconChangeTable[SC_EXTRACT_WHITE_POTION_Z] = SI_EXTRACT_WHITE_POTION_Z;
+	StatusIconChangeTable[SC_VITATA_500] = SI_VITATA_500;
+	StatusIconChangeTable[SC_EXTRACT_SALAMINE_JUICE] = SI_EXTRACT_SALAMINE_JUICE;
 	StatusIconChangeTable[SC_BOOST500] = SI_BOOST500;
 	StatusIconChangeTable[SC_FULL_SWING_K] = SI_FULL_SWING_K;
 	StatusIconChangeTable[SC_MANA_PLUS] = SI_MANA_PLUS;
 	StatusIconChangeTable[SC_MUSTLE_M] = SI_MUSTLE_M;
 	StatusIconChangeTable[SC_LIFE_FORCE_F] = SI_LIFE_FORCE_F;
-	StatusIconChangeTable[SC_EXTRACT_WHITE_POTION_Z] = SI_EXTRACT_WHITE_POTION_Z;
-	StatusIconChangeTable[SC_VITATA_500] = SI_VITATA_500;
-	StatusIconChangeTable[SC_EXTRACT_SALAMINE_JUICE] = SI_EXTRACT_SALAMINE_JUICE;
 
 	/* Elemental Spirit's 'side' status change icons */
 	StatusIconChangeTable[SC_CIRCLE_OF_FIRE] = SI_CIRCLE_OF_FIRE;
@@ -1092,7 +1092,7 @@ void initChangeTables(void)
 	StatusChangeFlagTable[SC_MUSTLE_M] |= SCB_MAXHP;
 	StatusChangeFlagTable[SC_LIFE_FORCE_F] |= SCB_MAXSP;
 	StatusChangeFlagTable[SC_EXTRACT_WHITE_POTION_Z] |= SCB_REGEN;
-	StatusChangeFlagTable[SC_VITATA_500] |= SCB_REGEN;
+	StatusChangeFlagTable[SC_VITATA_500] |= SCB_REGEN|SCB_MAXSP;
 	StatusChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD;
 	StatusChangeFlagTable[SC_REBOUND] |= SCB_SPEED|SCB_REGEN;
 	StatusChangeFlagTable[SC_DEFSET] |= SCB_DEF|SCB_DEF2;
@@ -1587,7 +1587,8 @@ int status_heal(struct block_list *bl,int64 hhp,int64 hsp, int flag)
 		sc = NULL;
 
 	if (hp < 0) {
-		if (hp == INT_MIN) hp++; // -INT_MIN == INT_MIN in some architectures!
+		if (hp == INT_MIN) // -INT_MIN == INT_MIN in some architectures!
+			hp++;
 		status_damage(NULL, bl, -hp, 0, 0, 1);
 		hp = 0;
 	}
@@ -1605,7 +1606,8 @@ int status_heal(struct block_list *bl,int64 hhp,int64 hsp, int flag)
 	}
 
 	if(sp < 0) {
-		if (sp==INT_MIN) sp++;
+		if (sp == INT_MIN)
+			sp++;
 		status_damage(NULL, bl, 0, -sp, 0, 1);
 		sp = 0;
 	}
@@ -1615,10 +1617,11 @@ int status_heal(struct block_list *bl,int64 hhp,int64 hsp, int flag)
 			sp = status->max_sp - status->sp;
 	}
 
-	if(!sp && !hp) return 0;
+	if(!sp && !hp)
+		return 0;
 
-	status->hp+= hp;
-	status->sp+= sp;
+	status->hp += hp;
+	status->sp += sp;
 
 	if(hp && sc &&
 		sc->data[SC_AUTOBERSERK] &&
@@ -2742,6 +2745,8 @@ static int status_get_spbonus(struct block_list *bl, enum e_status_bonus type) {
 				bonus += sc->data[SC_MERC_SPUP]->val2;
 			if(sc->data[SC_LIFE_FORCE_F])
 				bonus += sc->data[SC_LIFE_FORCE_F]->val1;
+			if(sc->data[SC_VITATA_500])
+				bonus += sc->data[SC_VITATA_500]->val2;
 		}
 		// Max rate reduce is -100%
 		bonus = cap_value(bonus,-100,INT_MAX);
@@ -3965,25 +3970,26 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
 	regen->flag = RGN_HP|RGN_SP;
 	if(regen->sregen) {
 		if (regen->sregen->hp)
-			regen->flag|=RGN_SHP;
+			regen->flag |= RGN_SHP;
 
 		if (regen->sregen->sp)
-			regen->flag|=RGN_SSP;
-		regen->sregen->rate.hp = regen->sregen->rate.sp = 1;
+			regen->flag |= RGN_SSP;
+		regen->sregen->rate.hp = regen->sregen->rate.sp = 100;
 	}
 	if (regen->ssregen) {
 		if (regen->ssregen->hp)
-			regen->flag|=RGN_SHP;
+			regen->flag |= RGN_SHP;
 
 		if (regen->ssregen->sp)
-			regen->flag|=RGN_SSP;
-		regen->ssregen->rate.hp = regen->ssregen->rate.sp = 1;
+			regen->flag |= RGN_SSP;
+		regen->ssregen->rate.hp = regen->ssregen->rate.sp = 100;
 	}
-	regen->rate.hp = regen->rate.sp = 1;
+	regen->rate.hp = regen->rate.sp = 100;
 
 	if (!sc || !sc->count)
 		return;
 
+	// No HP or SP regen
 	if ((sc->data[SC_POISON] && !sc->data[SC_SLOWPOISON])
 		|| (sc->data[SC_DPOISON] && !sc->data[SC_SLOWPOISON])
 		|| sc->data[SC_BERSERK]
@@ -3992,8 +3998,9 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
 		|| sc->data[SC_MAGICMUSHROOM]
 		|| sc->data[SC_SATURDAYNIGHTFEVER]
 		|| sc->data[SC_REBOUND])
-		regen->flag = 0; // No HP or SP regen
+		regen->flag = RGN_NONE;
 
+	// No natural SP regen
 	if (sc->data[SC_DANCING] ||
 #ifdef RENEWAL
 		sc->data[SC_MAXIMIZEPOWER] ||
@@ -4006,38 +4013,38 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
 		sc->data[SC_EXTREMITYFIST] && (!sc->data[SC_SPIRIT] || sc->data[SC_SPIRIT]->val2 != SL_MONK)) ||
 #endif
 		sc->data[SC_OBLIVIONCURSE] || sc->data[SC_VITALITYACTIVATION])
-		regen->flag &= ~RGN_SP; // No natural SP regen
+		regen->flag &= ~RGN_SP;
 
 	if(sc->data[SC_TENSIONRELAX]) {
-		regen->rate.hp += 2;
+		regen->rate.hp += 200;
 		if (regen->sregen)
-			regen->sregen->rate.hp += 3;
+			regen->sregen->rate.hp += 300;
 	}
 	if (sc->data[SC_MAGNIFICAT]) {
-		regen->rate.hp += 1;
-		regen->rate.sp += 1;
+		regen->rate.hp += 100;
+		regen->rate.sp += 100;
 	}
 	if (sc->data[SC_REGENERATION]) {
 		const struct status_change_entry *sce = sc->data[SC_REGENERATION];
 		if (!sce->val4) {
-			regen->rate.hp += sce->val2;
-			regen->rate.sp += sce->val3;
+			regen->rate.hp += (sce->val2*100);
+			regen->rate.sp += (sce->val3*100);
 		} else
-			regen->flag&=~sce->val4; // Remove regen as specified by val4
+			regen->flag &= ~sce->val4; // Remove regen as specified by val4
 	}
 	if(sc->data[SC_GT_REVITALIZE]) {
-		regen->hp += cap_value(regen->hp*sc->data[SC_GT_REVITALIZE]->val3/100, 1, SHRT_MAX);
+		regen->hp += cap_value(regen->hp * sc->data[SC_GT_REVITALIZE]->val3/100, 1, SHRT_MAX);
 		regen->state.walk = 1;
 	}
 	if ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1) // If insignia lvl 1
-	        || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1)
-	        || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1)
-	        || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1))
-	    regen->rate.hp *= 2;
+		|| (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1)
+		|| (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1)
+		|| (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1))
+		regen->rate.hp *= 2;
 	if (sc->data[SC_EXTRACT_WHITE_POTION_Z])
-		regen->rate.hp += regen->rate.hp * sc->data[SC_EXTRACT_WHITE_POTION_Z]->val1 / 100;
+		regen->rate.hp += (unsigned short)(regen->rate.hp * sc->data[SC_EXTRACT_WHITE_POTION_Z]->val1 / 100.);
 	if (sc->data[SC_VITATA_500])
-		regen->rate.sp += regen->rate.sp * sc->data[SC_VITATA_500]->val1 / 100;
+		regen->rate.sp += (unsigned short)(regen->rate.sp * sc->data[SC_VITATA_500]->val1 / 100.);
 }
 
 /**
@@ -12572,10 +12579,11 @@ static int status_natural_heal(struct block_list* bl, va_list args)
 	struct view_data *vd = NULL;
 	struct regen_data_sub *sregen;
 	struct map_session_data *sd;
-	int val,rate,bonus = 0,flag;
+	int rate, bonus = 0,flag;
 
 	regen = status_get_regen_data(bl);
-	if (!regen) return 0;
+	if (!regen)
+		return 0;
 	status = status_get_status_data(bl);
 	sc = status_get_sc(bl);
 	if (sc && !sc->count)
@@ -12584,15 +12592,15 @@ static int status_natural_heal(struct block_list* bl, va_list args)
 
 	flag = regen->flag;
 	if (flag&RGN_HP && (status->hp >= status->max_hp || regen->state.block&1))
-		flag&=~(RGN_HP|RGN_SHP);
+		flag &= ~(RGN_HP|RGN_SHP);
 	if (flag&RGN_SP && (status->sp >= status->max_sp || regen->state.block&2))
-		flag&=~(RGN_SP|RGN_SSP);
+		flag &= ~(RGN_SP|RGN_SSP);
 
 	if (flag && (
 		status_isdead(bl) ||
 		(sc && (sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || sc->data[SC__INVISIBILITY]))
 	))
-		flag=0;
+		flag = RGN_NONE;
 
 	if (sd) {
 		if (sd->hp_loss.value || sd->sp_loss.value)
@@ -12602,30 +12610,31 @@ static int status_natural_heal(struct block_list* bl, va_list args)
 	}
 
 	if(flag&(RGN_SHP|RGN_SSP) && regen->ssregen &&
-		(vd = status_get_viewdata(bl)) && vd->dead_sit == 2) { // Apply sitting regen bonus.
+		(vd = status_get_viewdata(bl)) && vd->dead_sit == 2)
+	{ // Apply sitting regen bonus.
 		sregen = regen->ssregen;
 		if(flag&(RGN_SHP)) { // Sitting HP regen
-			val = natural_heal_diff_tick * sregen->rate.hp;
+			rate = (int)(natural_heal_diff_tick * (sregen->rate.hp / 100.));
 			if (regen->state.overweight)
-				val>>=1; // Half as fast when overweight.
-			sregen->tick.hp += val;
+				rate >>= 1; // Half as fast when overweight.
+			sregen->tick.hp += rate;
 			while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) {
 				sregen->tick.hp -= battle_config.natural_heal_skill_interval;
 				if(status_heal(bl, sregen->hp, 0, 3) < sregen->hp) { // Full
-					flag&=~(RGN_HP|RGN_SHP);
+					flag &= ~(RGN_HP|RGN_SHP);
 					break;
 				}
 			}
 		}
 		if(flag&(RGN_SSP)) { // Sitting SP regen
-			val = natural_heal_diff_tick * sregen->rate.sp;
+			rate = (int)(natural_heal_diff_tick * (sregen->rate.sp / 100.));
 			if (regen->state.overweight)
-				val>>=1; // Half as fast when overweight.
-			sregen->tick.sp += val;
+				rate >>= 1; // Half as fast when overweight.
+			sregen->tick.sp += rate;
 			while(sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval) {
 				sregen->tick.sp -= battle_config.natural_heal_skill_interval;
 				if(status_heal(bl, 0, sregen->sp, 3) < sregen->sp) { // Full
-					flag&=~(RGN_SP|RGN_SSP);
+					flag &= ~(RGN_SP|RGN_SSP);
 					break;
 				}
 			}
@@ -12633,53 +12642,56 @@ static int status_natural_heal(struct block_list* bl, va_list args)
 	}
 
 	if (flag && regen->state.overweight)
-		flag=0;
+		flag = RGN_NONE;
 
 	ud = unit_bl2ud(bl);
 
 	if (flag&(RGN_HP|RGN_SHP|RGN_SSP) && ud && ud->walktimer != INVALID_TIMER) {
-		flag&=~(RGN_SHP|RGN_SSP);
+		flag &= ~(RGN_SHP|RGN_SSP);
 		if(!regen->state.walk)
-			flag&=~RGN_HP;
+			flag &= ~RGN_HP;
 	}
 
 	if (!flag)
 		return 0;
 
 	if (flag&(RGN_HP|RGN_SP)) {
-		if(!vd) vd = status_get_viewdata(bl);
+		if(!vd)
+			vd = status_get_viewdata(bl);
 		if(vd && vd->dead_sit == 2)
-			bonus++;
+			bonus += 100;
 		if(regen->state.gc)
-			bonus++;
+			bonus += 100;
 	}
 
 	// Natural Hp regen
 	if (flag&RGN_HP) {
-		rate = natural_heal_diff_tick*(regen->rate.hp+bonus);
+		rate = (int)(natural_heal_diff_tick * (regen->rate.hp/100. + bonus/100.));
 		if (ud && ud->walktimer != INVALID_TIMER)
-			rate/=2;
+			rate /= 2;
 		// Homun HP regen fix (they should regen as if they were sitting (twice as fast)
-		if(bl->type==BL_HOM) rate *=2;
+		if(bl->type == BL_HOM)
+			rate *= 2;
 
 		regen->tick.hp += rate;
 
 		if(regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval) {
-			val = 0;
+			int val = 0;
 			do {
 				val += regen->hp;
 				regen->tick.hp -= battle_config.natural_healhp_interval;
 			} while(regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval);
 			if (status_heal(bl, val, 0, 1) < val)
-				flag&=~RGN_SHP; // Full.
+				flag &= ~RGN_SHP; // Full.
 		}
 	}
 
 	// Natural SP regen
 	if(flag&RGN_SP) {
-		rate = natural_heal_diff_tick*(regen->rate.sp+bonus);
+		rate = (int)(natural_heal_diff_tick * (regen->rate.sp/100. + bonus/100.));
 		// Homun SP regen fix (they should regen as if they were sitting (twice as fast)
-		if(bl->type==BL_HOM) rate *=2;
+		if(bl->type==BL_HOM)
+			rate *= 2;
 #ifdef RENEWAL
 		if (bl->type == BL_PC && (((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK &&
 			sc && sc->data[SC_EXPLOSIONSPIRITS] && (!sc->data[SC_SPIRIT] || sc->data[SC_SPIRIT]->val2 != SL_MONK))
@@ -12688,13 +12700,13 @@ static int status_natural_heal(struct block_list* bl, va_list args)
 		regen->tick.sp += rate;
 
 		if(regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval) {
-			val = 0;
+			int val = 0;
 			do {
 				val += regen->sp;
 				regen->tick.sp -= battle_config.natural_healsp_interval;
 			} while(regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval);
 			if (status_heal(bl, 0, val, 1) < val)
-				flag&=~RGN_SSP; // full.
+				flag &= ~RGN_SSP; // full.
 		}
 	}
 
@@ -12705,7 +12717,7 @@ static int status_natural_heal(struct block_list* bl, va_list args)
 	sregen = regen->sregen;
 
 	if(flag&RGN_SHP) { // Skill HP regen
-		sregen->tick.hp += natural_heal_diff_tick * sregen->rate.hp;
+		sregen->tick.hp += (int)(natural_heal_diff_tick * (sregen->rate.hp / 100.));
 
 		while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) {
 			sregen->tick.hp -= battle_config.natural_heal_skill_interval;
@@ -12714,11 +12726,11 @@ static int status_natural_heal(struct block_list* bl, va_list args)
 		}
 	}
 	if(flag&RGN_SSP) { // Skill SP regen
-		sregen->tick.sp += natural_heal_diff_tick * sregen->rate.sp;
+		sregen->tick.sp += (int)(natural_heal_diff_tick * (sregen->rate.sp /100.));
 		while(sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval) {
-			val = sregen->sp;
+			int val = sregen->sp;
 			if (sd && sd->state.doridori) {
-				val*=2;
+				val *= 2;
 				sd->state.doridori = 0;
 				if ((rate = pc_checkskill(sd,TK_SPTIME)))
 					sc_start(bl,bl,status_skill2sc(TK_SPTIME),

+ 6 - 8
src/map/status.h

@@ -1846,27 +1846,25 @@ struct regen_data_sub {
 		unsigned int hp,sp;
 	} tick;
 
-	//Regen rates (where every 1 means +100% regen)
+	//Regen rates. n/100
 	struct {
-		unsigned char hp,sp;
+		unsigned short hp,sp;
 	} rate;
 };
 
 ///Regen data
 struct regen_data {
-	unsigned short flag; //Marks what stuff you may heal or not.
-	unsigned short
-		hp,sp,shp,ssp;
+	unsigned char flag; //Marks what stuff you may heal or not.
+	unsigned short hp,sp,shp,ssp;
 
 	//tick accumulation before healing.
 	struct {
 		unsigned int hp,sp,shp,ssp;
 	} tick;
 
-	//Regen rates (where every 1 means +100% regen)
+	//Regen rates. n/100
 	struct {
-		unsigned char
-		hp,sp,shp,ssp;
+		unsigned short hp, sp, shp, ssp;
 	} rate;
 
 	struct {