فهرست منبع

Bug Fixes
* Fixed Severe Rainstorm not being able to be copied by Reproduce. (bugreport:9361)
* Fixed #137 - Updated Homunculus S Race and Element values to official.
* Fixed #163 - Proper renewal calculations for Homunculus. Merge from HerculesWS/Hercules@8faef4f
* Fixed #254 - Corrected King's Grace cooldown to be 60 seconds.
* +20 Foods cannot be dispelled or removed by death.

aleos89 10 سال پیش
والد
کامیت
083cf5d962
11فایلهای تغییر یافته به همراه255 افزوده شده و 160 حذف شده
  1. 1 1
      db/pre-re/skill_cast_db.txt
  2. 5 5
      db/re/homunculus_db.txt
  3. 1 1
      db/re/skill_cast_db.txt
  4. 13 6
      src/common/mmo.h
  5. 27 9
      src/map/clif.c
  6. 2 0
      src/map/homunculus.c
  7. 11 0
      src/map/homunculus.h
  8. 2 2
      src/map/pc.h
  9. 10 10
      src/map/skill.c
  10. 172 125
      src/map/status.c
  11. 11 1
      src/map/status.h

+ 1 - 1
db/pre-re/skill_cast_db.txt

@@ -1410,7 +1410,7 @@
 2325,2000,2000,0,30000:45000:60000:75000:90000,0,540000:480000:420000:360000:300000
 
 //-- LG_KINGS_GRACE
-5013,1000,0,0,5000,0,0
+5013,1000,0,0,5000,0,60000
 //==========================================
 
 //===== Sura Skills ========================

+ 5 - 5
db/re/homunculus_db.txt

@@ -26,8 +26,8 @@
 6006,6014,Amistr,912,60000,0,1,2,0,700,320,10,20,17,35,11,24,12,80,130,1,4,8,20,4,20,4,20,1,10,3,19,3,19,1600,3600,120,360,20,50,10,30,20,50,20,50,10,30,10,30
 6007,6015,Filir,910,60000,0,1,2,0,700,90,25,29,35,9,8,30,9,45,75,3,6,4,20,8,20,1,10,3,19,4,20,3,19,1200,3200,200,400,20,50,10,30,20,50,20,50,10,30,10,30
 6008,6016,Vanilmirth,911,60000,0,1,0,0,700,80,11,11,11,11,11,11,11,30,150,0,7,1,30,1,30,1,30,1,30,1,30,1,30,1200,4800,480,640,10,30,10,30,10,30,20,50,10,50,10,100
-6048,6048,Eira,6098,60000,1,1,7,0,700,150,40,17,20,15,35,24,12,40,160,20,42,13,39,28,42,15,25,14,48,16,36,9,18,1000,2000,10,200,1,10,1,10,1,10,1,10,1,10,1,10
-6049,6049,Bayeri,6112,60000,1,1,2,0,700,320,10,20,17,35,11,24,12,90,360,48,52,18,36,8,36,16,32,22,44,12,24,20,36,1000,2000,10,200,1,10,1,10,1,10,1,10,1,10,1,10
-6050,6050,Sera,6108,60000,1,1,4,0,700,90,25,29,35,9,8,30,9,60,240,36,64,10,25,16,32,5,25,7,35,28,40,20,40,1000,2000,10,200,1,10,1,10,1,10,1,10,1,10,1,10
-6051,6051,Dieter,6104,60000,1,1,0,0,700,80,11,11,11,11,11,11,11,240,480,40,120,20,40,13,26,18,36,15,40,16,32,4,16,1000,2000,10,200,1,10,1,10,1,10,1,10,1,10,1,10
-6052,6052,Eleanor,6115,60000,1,1,2,0,700,320,10,20,17,35,11,24,12,60,300,10,20,20,40,10,50,24,48,5,15,12,36,2,10,1000,2000,10,200,1,10,1,10,1,10,1,10,1,10,1,10
+6048,6048,Eira,6098,60000,1,1,8,4,700,150,40,17,20,15,35,24,12,40,160,20,42,13,39,28,42,15,25,14,48,16,36,9,18,1000,2000,10,200,1,10,1,10,1,10,1,10,1,10,1,10
+6049,6049,Bayeri,6112,60000,1,1,2,6,700,320,10,20,17,35,11,24,12,90,360,48,52,18,36,8,36,16,32,22,44,12,24,20,36,1000,2000,10,200,1,10,1,10,1,10,1,10,1,10,1,10
+6050,6050,Sera,6108,60000,1,1,4,2,700,90,25,29,35,9,8,30,9,60,240,36,64,10,25,16,32,5,25,7,35,28,40,20,40,1000,2000,10,200,1,10,1,10,1,10,1,10,1,10,1,10
+6051,6051,Dieter,6104,60000,1,1,0,3,700,80,11,11,11,11,11,11,11,240,480,40,120,20,40,13,26,18,36,15,40,16,32,4,16,1000,2000,10,200,1,10,1,10,1,10,1,10,1,10,1,10
+6052,6052,Eleanor,6115,60000,1,1,7,5,700,320,10,20,17,35,11,24,12,60,300,10,20,20,40,10,50,24,48,5,15,12,36,2,10,1000,2000,10,200,1,10,1,10,1,10,1,10,1,10,1,10

+ 1 - 1
db/re/skill_cast_db.txt

@@ -1411,7 +1411,7 @@
 //-- LG_INSPIRATION
 2325,2000,2000,0,30000:45000:60000:75000:90000,0,540000:480000:420000:360000:300000,1000
 //-- LG_KINGS_GRACE
-5013,1000,0,0,5000,0,0,-1
+5013,1000,0,0,5000,0,60000,-1
 //==========================================
 
 //===== Sura Skills ========================

+ 13 - 6
src/common/mmo.h

@@ -317,12 +317,19 @@ struct s_homunculus {	//[orn]
 	unsigned int exp;
 	short rename_flag;
 	short vaporize; //albator
-	int str ;
-	int agi ;
-	int vit ;
-	int int_ ;
-	int dex ;
-	int luk ;
+	int str;
+	int agi;
+	int vit;
+	int int_;
+	int dex;
+	int luk;
+
+	int str_value;
+	int agi_value;
+	int vit_value;
+	int int_value;
+	int dex_value;
+	int luk_value;
 
 	char spiritball; //for homun S [lighta]
 };

+ 27 - 9
src/map/clif.c

@@ -1411,15 +1411,24 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag)
 	WBUFW(buf,29)=hd->homunculus.hunger;
 	WBUFW(buf,31)=(unsigned short) (hd->homunculus.intimacy / 100) ;
 	WBUFW(buf,33)=0; // equip id
+#ifdef RENEWAL
+	WBUFW(buf,35)=cap_value(status->rhw.atk2, 0, INT16_MAX);
+#else
 	WBUFW(buf,35)=cap_value(status->rhw.atk2+status->batk, 0, INT16_MAX);
+#endif
 	WBUFW(buf,37)=min(status->matk_max, INT16_MAX); //FIXME capping to INT16 here is too late
 	WBUFW(buf,39)=status->hit;
 	if (battle_config.hom_setting&HOMSET_DISPLAY_LUK)
 		WBUFW(buf,41)=status->luk/3 + 1;	//crit is a +1 decimal value! Just display purpose.[Vicious]
 	else
 		WBUFW(buf,41)=status->cri/10;
-	WBUFW(buf,43)=status->def + status->vit ;
+#ifdef RENEWAL
+	WBUFW(buf,43)=status->def + status->def2;
+	WBUFW(buf,45)=status->mdef + status->mdef2;
+#else
+	WBUFW(buf,43)=status->def + status->vit;
 	WBUFW(buf,45)=status->mdef;
+#endif
 	WBUFW(buf,47)=status->flee;
 	WBUFW(buf,49)=(flag)?0:status->amotion;
 	if (status->max_hp > INT16_MAX) {
@@ -2904,7 +2913,6 @@ void clif_updatestatus(struct map_session_data *sd,int type)
 		WFIFOL(fd,4)=pc_leftside_matk(sd);
 		break;
 
-
 	case SP_ZENY:
 		WFIFOW(fd,0)=0xb1;
 		WFIFOL(fd,4)=sd->status.zeny;
@@ -11257,16 +11265,20 @@ static void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_sess
 
 	if( !hd )
 		return;
-	if( skill_isNotOk_hom(skill_id, hd) )
+	if( skill_isNotOk_hom(skill_id, hd) ) {
+		clif_emotion(&hd->bl, E_DOTS);
 		return;
+	}
 	if( hd->bl.id != target_id && skill_get_inf(skill_id)&INF_SELF_SKILL )
 		target_id = hd->bl.id;
-	if( hd->ud.skilltimer != INVALID_TIMER )
-	{
+	if( hd->ud.skilltimer != INVALID_TIMER ) {
 		if( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST ) return;
-	}
-	else if( DIFF_TICK(tick, hd->ud.canact_tick) < 0 )
+	} else if( DIFF_TICK(tick, hd->ud.canact_tick) < 0 ) {
+		clif_emotion(&hd->bl, E_DOTS);
+		if (hd->master)
+			clif_skill_fail(hd->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0);
 		return;
+	}
 
 	lv = hom_checkskill(hd, skill_id);
 	if( skill_lv > lv )
@@ -11280,12 +11292,18 @@ static void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_ses
 	int lv;
 	if( !hd )
 		return;
-	if( skill_isNotOk_hom(skill_id, hd) )
+	if( skill_isNotOk_hom(skill_id, hd) ) {
+		clif_emotion(&hd->bl, E_DOTS);
 		return;
+	}
 	if( hd->ud.skilltimer != INVALID_TIMER ) {
 		if( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST ) return;
-	} else if( DIFF_TICK(tick, hd->ud.canact_tick) < 0 )
+	} else if( DIFF_TICK(tick, hd->ud.canact_tick) < 0 ) {
+		clif_emotion(&hd->bl, E_DOTS);
+		if (hd->master)
+			clif_skill_fail(hd->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0);
 		return;
+	}
 
 	if( hd->sc.data[SC_BASILICA] )
 		return;

+ 2 - 0
src/map/homunculus.c

@@ -471,6 +471,8 @@ int hom_levelup(struct homun_data *hd)
 	hom->int_+= growth_int;
 	hom->luk += growth_luk;
 
+	APPLY_HOMUN_LEVEL_STATWEIGHT();
+
 	if ( battle_config.homunculus_show_growth ) {
 		char output[256] ;
 		sprintf(output,

+ 11 - 0
src/map/homunculus.h

@@ -7,6 +7,17 @@
 #include "status.h" // struct status_data, struct status_change
 #include "unit.h" // struct unit_data
 
+#ifdef RENEWAL
+	#define	HOMUN_LEVEL_STATWEIGHT_VALUE 0
+	#define APPLY_HOMUN_LEVEL_STATWEIGHT()( \
+		hom->str_value = hom->agi_value = \
+		hom->vit_value = hom->int_value = \
+		hom->dex_value = hom->luk_value = hom->level / 10 - HOMUN_LEVEL_STATWEIGHT_VALUE \
+		)
+#else
+	#define APPLY_HOMUN_LEVEL_STATWEIGHT()
+#endif
+
 struct h_stats {
 	unsigned int HP, SP;
 	unsigned short str, agi, vit, int_, dex, luk;

+ 2 - 2
src/map/pc.h

@@ -800,8 +800,8 @@ short pc_maxaspd(struct map_session_data *sd);
 	#define pc_rightside_def(sd) ((sd)->battle_status.def)
 	#define pc_leftside_mdef(sd) ((sd)->battle_status.mdef2)
 	#define pc_rightside_mdef(sd) ((sd)->battle_status.mdef)
-#define pc_leftside_matk(sd) (status_base_matk(status_get_status_data(&(sd)->bl), (sd)->status.base_level))
-#define pc_rightside_matk(sd) ((sd)->battle_status.rhw.matk+(sd)->battle_status.lhw.matk+(sd)->bonus.ematk)
+	#define pc_leftside_matk(sd) (status_base_matk(&(sd)->bl, status_get_status_data(&(sd)->bl), (sd)->status.base_level))
+	#define pc_rightside_matk(sd) ((sd)->battle_status.rhw.matk+(sd)->battle_status.lhw.matk+(sd)->bonus.ematk)
 #else
 	#define pc_leftside_atk(sd) ((sd)->battle_status.batk + (sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk)
 	#define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2)

+ 10 - 10
src/map/skill.c

@@ -420,7 +420,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
 				struct status_data *status = status_get_status_data(src);
 				int min, max;
 
-				min = max = status_base_matk(status, status_get_lv(src));
+				min = max = status_base_matk(src, status, status_get_lv(src));
 				if( status->rhw.matk > 0 ){
 					int wMatk, variance;
 					wMatk = status->rhw.matk;
@@ -1631,8 +1631,8 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 					case SC_FOOD_INT_CASH:	case SC_FOOD_LUK_CASH:	case SC_SEVENWIND:
 					case SC_MIRACLE:		case SC_S_LIFEPOTION:	case SC_L_LIFEPOTION:
 					case SC_INCHEALRATE:	case SC_ELECTRICSHOCKER:		case SC__STRIPACCESSORY:
-					//case SC_SAVAGE_STEAK:			case SC_COCKTAIL_WARG_BLOOD:		case SC_MINOR_BBQ:
-					//case SC_SIROMA_ICE_TEA:			case SC_DROCERA_HERB_STEAMED:		case SC_PUTTI_TAILS_NOODLES:
+					case SC_SAVAGE_STEAK:			case SC_COCKTAIL_WARG_BLOOD:		case SC_MINOR_BBQ:
+					case SC_SIROMA_ICE_TEA:			case SC_DROCERA_HERB_STEAMED:		case SC_PUTTI_TAILS_NOODLES:
 					case SC_NEUTRALBARRIER_MASTER:		case SC_NEUTRALBARRIER:			case SC_STEALTHFIELD_MASTER:
 					case SC_STEALTHFIELD:	case SC_GIANTGROWTH:	case SC_MILLENNIUMSHIELD:
 					case SC_REFRESH:		case SC_STONEHARDSKIN:	case SC_VITALITYACTIVATION:
@@ -3138,7 +3138,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 			dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,(flag&1)?8:5);
 			break;
 		case WM_SEVERE_RAINSTORM_MELEE:
-			dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,-2,6);
+			dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,-2,5);
 			break;
 		case WM_REVERBERATION_MELEE:
 		case WM_REVERBERATION_MAGIC:
@@ -7347,8 +7347,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				case SC_FOOD_INT_CASH:	case SC_FOOD_LUK_CASH:	case SC_SEVENWIND:
 				case SC_MIRACLE:		case SC_S_LIFEPOTION:	case SC_L_LIFEPOTION:
 				case SC_INCHEALRATE:	case SC_ELECTRICSHOCKER:		case SC__STRIPACCESSORY:
-				//case SC_SAVAGE_STEAK:			case SC_COCKTAIL_WARG_BLOOD:		case SC_MINOR_BBQ:
-				//case SC_SIROMA_ICE_TEA:			case SC_DROCERA_HERB_STEAMED:		case SC_PUTTI_TAILS_NOODLES:
+				case SC_SAVAGE_STEAK:			case SC_COCKTAIL_WARG_BLOOD:		case SC_MINOR_BBQ:
+				case SC_SIROMA_ICE_TEA:			case SC_DROCERA_HERB_STEAMED:		case SC_PUTTI_TAILS_NOODLES:
 				case SC_NEUTRALBARRIER_MASTER:		case SC_NEUTRALBARRIER:			case SC_STEALTHFIELD_MASTER:
 				case SC_STEALTHFIELD:	case SC_GIANTGROWTH:	case SC_MILLENNIUMSHIELD:
 				case SC_REFRESH:		case SC_STONEHARDSKIN:	case SC_VITALITYACTIVATION:
@@ -8828,9 +8828,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				case SC_FOOD_LUK_CASH:   case SC_ELECTRICSHOCKER: case SC_BITE:
 				case SC__STRIPACCESSORY: case SC__ENERVATION: case SC__GROOMY:
 				case SC__IGNORANCE:  case SC__LAZINESS:   case SC__UNLUCKY:
-				case SC__WEAKNESS:   //case SC_SAVAGE_STEAK:  case SC_COCKTAIL_WARG_BLOOD:
-				case SC_MAGNETICFIELD://case SC_MINOR_BBQ:   case SC_SIROMA_ICE_TEA:
-				//case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES:
+				case SC__WEAKNESS:   case SC_SAVAGE_STEAK:  case SC_COCKTAIL_WARG_BLOOD:
+				case SC_MAGNETICFIELD: case SC_MINOR_BBQ:   case SC_SIROMA_ICE_TEA:
+				case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES:
 				case SC_NEUTRALBARRIER_MASTER: case SC_NEUTRALBARRIER:
 				case SC_STEALTHFIELD_MASTER: case SC_STEALTHFIELD:
 				case SC_LEADERSHIP:		case SC_GLORYWOUNDS:	case SC_SOULCOLD:
@@ -10120,7 +10120,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		{
 			int heal = 5 * status_get_lv(&hd->bl) +
 #ifdef RENEWAL
-						status_base_matk(&hd->battle_status, status_get_lv(&hd->bl));
+						status_base_matk(bl, &hd->battle_status, status_get_lv(&hd->bl));
 #else
 						status_base_matk_min(&hd->battle_status);
 #endif

+ 172 - 125
src/map/status.c

@@ -2078,7 +2078,7 @@ int status_base_amotion_pc(struct map_session_data* sd, struct status_data* stat
  * @return base attack
  * Note: Function only calculates Homunculus bATK in RENEWAL
  */
-static unsigned short status_base_atk(const struct block_list *bl, const struct status_data *status)
+unsigned short status_base_atk(const struct block_list *bl, const struct status_data *status)
 {
 	int flag = 0, str, dex,
 #ifdef RENEWAL
@@ -2086,7 +2086,6 @@ static unsigned short status_base_atk(const struct block_list *bl, const struct
 #endif
 		dstr;
 
-
 	if(!(bl->type&battle_config.enable_baseatk))
 		return 0;
 
@@ -2121,7 +2120,7 @@ static unsigned short status_base_atk(const struct block_list *bl, const struct
 	**/
 #ifdef RENEWAL
 	if (bl->type == BL_HOM)
-		str = (int)(floor((rstr + dex + status->luk) / 3) + floor(((TBL_HOM*)bl)->homunculus.level / 10));
+		str = 2 * ((((TBL_HOM*)bl)->homunculus.level) + status_get_homstr(bl));
 #endif
 	dstr = str/10;
 	str += dstr*dstr;
@@ -2155,9 +2154,24 @@ unsigned int status_weapon_atk(struct weapon_atk wa, struct status_data *status)
 #ifndef RENEWAL
 	unsigned short status_base_matk_min(const struct status_data* status) { return status->int_ + (status->int_ / 7) * (status->int_ / 7); }
 	unsigned short status_base_matk_max(const struct status_data* status) { return status->int_ + (status->int_ / 5) * (status->int_ / 5); }
+#endif
+
+unsigned short status_base_matk(struct block_list *bl, const struct status_data* status, int level)
+{
+#ifdef RENEWAL
+	switch (bl->type) {
+	case BL_MOB:
+		return status->int_ + level;
+	case BL_HOM:
+		return status_get_homint(bl) + level;
+	case BL_PC:
+	default:
+		return status->int_ + (status->int_ / 2) + (status->dex / 5) + (status->luk / 3) + (level / 4);
+	}
 #else
-	unsigned short status_base_matk(const struct status_data* status, int level) { return status->int_ + (status->int_ / 2) + (status->dex / 5) + (status->luk / 3) + (level / 4); }
+	return 0;
 #endif
+}
 
 /**
  * Fills in the misc data that can be calculated from the other status info (except for level)
@@ -2175,73 +2189,84 @@ void status_calc_misc(struct block_list *bl, struct status_data *status, int lev
 		status->cri = status->flee2 = 0;
 
 #ifdef RENEWAL // Renewal formulas
-	if (bl->type == BL_MOB) {
-		//Hit
-		stat = status->hit;
-		stat += level + status->dex + 175;
-		status->hit = cap_value(stat,1,SHRT_MAX);
-		//Flee
-		stat = status->flee;
-		stat += level + status->agi + 100;
-		status->flee = cap_value(stat,1,SHRT_MAX);
-	} else if (bl->type == BL_HOM) {
-		status->hit = cap_value(level + status->dex + 150,1,SHRT_MAX); // base level + dex + 150
-		status->flee = cap_value(level + status->agi + level/10,1,SHRT_MAX); // base level + agi + base level/10
+	if (bl->type == BL_HOM) {
+		// Def2
+		stat = status_get_homvit(bl) + status_get_homagi(bl) / 2;
+		status->def2 = cap_value(stat, 0, SHRT_MAX);
+		// Mdef2
+		stat = (status_get_homvit(bl) + status_get_homint(bl)) / 2;
+		status->mdef2 = cap_value(stat, 0, SHRT_MAX);
+		// Def
+		stat = status->def;
+		stat += status_get_homvit(bl) + level / 2;
+		status->def = cap_value(stat, 0, SHRT_MAX);
+		// Mdef
+		stat = (int)(((float)status_get_homvit(bl) + level) / 4 + (float)status_get_homint(bl) / 2);
+		status->mdef = cap_value(stat, 0, SHRT_MAX);
+		// Hit
+		stat = level + status->dex + 150;
+		status->hit = cap_value(stat, 1, SHRT_MAX);
+		// Flee
+		stat = level + status_get_homagi(bl);
+		status->flee = cap_value(stat, 1, SHRT_MAX);
+		// Atk
+		stat = (status_get_homstr(bl) + status_get_homdex(bl)) / 5;
+		status->rhw.atk = cap_value(stat, 0, SHRT_MAX);
+		// Atk2
+		stat = (status_get_homluk(bl) + status_get_homstr(bl) + status_get_homdex(bl)) / 3;
+		status->rhw.atk2 = cap_value(stat, 0, SHRT_MAX);
 	} else {
-		//Hit
+		// Hit
 		stat = status->hit;
-		stat += level + status->dex + status->luk/3 + 175; // base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175
-		status->hit = cap_value(stat,1,SHRT_MAX);
-		//Flee
+		stat += level + status->dex + (bl->type == BL_PC ? status->luk / 3 + 175 : 150); //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175
+		status->hit = cap_value(stat, 1, SHRT_MAX);
+		// Flee
 		stat = status->flee;
-		stat += level + status->agi + status->luk/5 + 100; // base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100
-		status->flee = cap_value(stat,1,SHRT_MAX);
+		stat += level + status->agi + (bl->type == BL_PC ? status->luk / 5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100
+		status->flee = cap_value(stat, 1, SHRT_MAX);
+		// Def2
+		stat = status->def2;
+		stat += (int)(((float)level + status->vit) / 2 + (bl->type == BL_PC ? ((float)status->agi / 5) : 0)); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def)
+		status->def2 = cap_value(stat, 0, SHRT_MAX);
+		// Mdef2
+		stat = status->mdef2;
+		stat += (int)(bl->type == BL_PC ? (status->int_ + ((float)level / 4) + ((float)(status->dex + status->vit) / 5)) : ((float)(status->int_ + level) / 4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef)
+		status->mdef2 = cap_value(stat, 0, SHRT_MAX);
 	}
-	status->matk_min = status->matk_max = status_base_matk(status, level);
-	//Def2
-	stat = status->def2;
-	stat += (int)(((float)level + status->vit)/2 + ((float)status->agi/5)); // base level + (every 2 vit = +1 def) + (every 5 agi = +1 def)
-	status->def2 = cap_value(stat,0,SHRT_MAX);
-	//MDef2
-	stat = status->mdef2;
-	stat += (int)(status->int_ + ((float)level/4) + ((float)status->dex/5) + ((float)status->vit/5)); // (every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef)
-	status->mdef2 = cap_value(stat,0,SHRT_MAX);
 #else
 	status->matk_min = status_base_matk_min(status);
 	status->matk_max = status_base_matk_max(status);
-	//Hit
+	// Hit
 	stat = status->hit;
 	stat += level + status->dex;
-	status->hit = cap_value(stat,1,SHRT_MAX);
-	//Flee
+	status->hit = cap_value(stat, 1, SHRT_MAX);
+	// Flee
 	stat = status->flee;
 	stat += level + status->agi;
-	status->flee = cap_value(stat,1,SHRT_MAX);
-	//Def2
+	status->flee = cap_value(stat, 1, SHRT_MAX);
+	// Def2
 	stat = status->def2;
 	stat += status->vit;
-	status->def2 = cap_value(stat,0,SHRT_MAX);
-	//MDef2
+	status->def2 = cap_value(stat, 0, SHRT_MAX);
+	// Mdef2
 	stat = status->mdef2;
 	stat += status->int_ + (status->vit>>1);
-	status->mdef2 = cap_value(stat,0,SHRT_MAX);
+	status->mdef2 = cap_value(stat, 0, SHRT_MAX);
 #endif
 
 	//Critical
 	if( bl->type&battle_config.enable_critical ) {
 		stat = status->cri;
 		stat += 10 + (status->luk*10/3); // (every 1 luk = +0.3 critical)
-		status->cri = cap_value(stat,1,SHRT_MAX);
-	}
-	else
+		status->cri = cap_value(stat, 1, SHRT_MAX);
+	} else
 		status->cri = 0;
 
 	if (bl->type&battle_config.enable_perfect_flee) {
 		stat = status->flee2;
 		stat += status->luk + 10; // (every 10 luk = +1 perfect flee)
-		status->flee2 = cap_value(stat,0,SHRT_MAX);
-	}
-	else
+		status->flee2 = cap_value(stat, 0, SHRT_MAX);
+	} else
 		status->flee2 = 0;
 
 	if (status->batk) {
@@ -2249,22 +2274,24 @@ void status_calc_misc(struct block_list *bl, struct status_data *status, int lev
 		status->batk = cap_value(temp, 0, USHRT_MAX);
 	} else
 		status->batk = status_base_atk(bl, status);
-	if (status->cri)
-	switch (bl->type) {
-	case BL_MOB:
-		if(battle_config.mob_critical_rate != 100)
-			status->cri = cap_value(status->cri*battle_config.mob_critical_rate/100,1,SHRT_MAX);
-		if(!status->cri && battle_config.mob_critical_rate)
-		  	status->cri = 10;
-		break;
-	case BL_PC:
-		// Players don't have a critical adjustment setting as of yet.
-		break;
-	default:
-		if(battle_config.critical_rate != 100)
-			status->cri = cap_value(status->cri*battle_config.critical_rate/100,1,SHRT_MAX);
-		if (!status->cri && battle_config.critical_rate)
-			status->cri = 10;
+
+	if (status->cri) {
+		switch (bl->type) {
+		case BL_MOB:
+			if(battle_config.mob_critical_rate != 100)
+				status->cri = cap_value(status->cri*battle_config.mob_critical_rate/100,1,SHRT_MAX);
+			if(!status->cri && battle_config.mob_critical_rate)
+			  	status->cri = 10;
+			break;
+		case BL_PC:
+			// Players don't have a critical adjustment setting as of yet.
+			break;
+		default:
+			if(battle_config.critical_rate != 100)
+				status->cri = cap_value(status->cri*battle_config.critical_rate/100,1,SHRT_MAX);
+			if (!status->cri && battle_config.critical_rate)
+				status->cri = 10;
+		}
 	}
 	if(bl->type&BL_REGEN)
 		status_calc_regen(bl, status, status_get_regen_data(bl));
@@ -3651,7 +3678,7 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt)
 {
 	struct status_data *status = &hd->base_status;
 	struct s_homunculus *hom = &hd->homunculus;
-	int skill;
+	int skill_lv;
 	int amotion;
 
 	status->str = hom->str / 10;
@@ -3661,13 +3688,15 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt)
 	status->int_ = hom->int_ / 10;
 	status->luk = hom->luk / 10;
 
+	APPLY_HOMUN_LEVEL_STATWEIGHT();
+
 	if (opt&SCO_FIRST) {
 		const struct s_homunculus_db *db = hd->homunculusDB;
-		status->def_ele =  db->element;
+		status->def_ele = db->element;
 		status->ele_lv = 1;
 		status->race = db->race;
 		status->class_ = CLASS_NORMAL;
-		status->size = (hom->class_ == db->evo_class)?db->evo_size:db->base_size;
+		status->size = (hom->class_ == db->evo_class) ? db->evo_size : db->base_size;
 		status->rhw.range = 1 + status->size;
 		status->mode = MD_CANMOVE|MD_CANATTACK;
 		status->speed = DEFAULT_WALK_SPEED;
@@ -3681,45 +3710,43 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt)
 	status->aspd_rate = 1000;
 
 #ifdef RENEWAL
-	status->def = (status->vit + (hom->level / 10)) + ((status->agi + (hom->level / 10)) / 2);
-	status->mdef = status->int_ + ((status->int_ + status->dex + status->luk) / 3) + (hom->level / 10) * 2;
-
-	amotion = (1000 -2*status->agi -status->dex) * hd->homunculusDB->baseASPD/1000;
+	amotion = hd->homunculusDB->baseASPD;
+	amotion = amotion - amotion * (status->dex + hom->dex_value) / 1000 - (status->agi + hom->agi_value) * amotion / 250;
 #else
-	skill = hom->level/10 + status->vit/5;
-	status->def = cap_value(skill, 0, 99);
+	skill_lv = hom->level / 10 + status->vit / 5;
+	status->def = cap_value(skill_lv, 0, 99);
 
-	skill = hom->level/10 + status->int_/5;
-	status->mdef = cap_value(skill, 0, 99);
+	skill_lv = hom->level / 10 + status->int_ / 5;
+	status->mdef = cap_value(skill_lv, 0, 99);
 
-	amotion = (1000 -4*status->agi -status->dex) * hd->homunculusDB->baseASPD/1000;
+	amotion = (1000 - 4 * status->agi - status->dex) * hd->homunculusDB->baseASPD / 1000;
 #endif
 
-	status->amotion = cap_value(amotion,battle_config.max_aspd,2000);
-	status->adelay = status->amotion; /// It seems adelay = amotion for Homunculus.
+	status->amotion = cap_value(amotion, battle_config.max_aspd, 2000);
+	status->adelay = status->amotion; //It seems adelay = amotion for Homunculus.
 
-	status->max_hp = hom->max_hp ;
-	status->max_sp = hom->max_sp ;
+	status->max_hp = hom->max_hp;
+	status->max_sp = hom->max_sp;
 
 	hom_calc_skilltree(hd, 0);
 
-	if((skill=hom_checkskill(hd,HAMI_SKIN)) > 0)
-		status->def +=	skill * 4;
+	if((skill_lv = hom_checkskill(hd, HAMI_SKIN)) > 0)
+		status->def += skill_lv * 4;
 
-	if((skill = hom_checkskill(hd,HVAN_INSTRUCT)) > 0) {
-		status->int_ += 1 +skill/2 +skill/4 +skill/5;
-		status->str  += 1 +skill/3 +skill/3 +skill/4;
+	if((skill_lv = hom_checkskill(hd, HVAN_INSTRUCT)) > 0) {
+		status->int_ += 1 + skill_lv / 2 + skill_lv / 4 + skill_lv / 5;
+		status->str += 1 + skill_lv / 3 + skill_lv / 3 + skill_lv / 4;
 	}
 
-	if((skill=hom_checkskill(hd,HAMI_SKIN)) > 0)
-		status->max_hp += skill * 2 * status->max_hp / 100;
+	if((skill_lv = hom_checkskill(hd, HAMI_SKIN)) > 0)
+		status->max_hp += skill_lv * 2 * status->max_hp / 100;
 
-	if((skill = hom_checkskill(hd,HLIF_BRAIN)) > 0)
-		status->max_sp += (1 +skill/2 -skill/4 +skill/5) * status->max_sp / 100 ;
+	if((skill_lv = hom_checkskill(hd, HLIF_BRAIN)) > 0)
+		status->max_sp += (1 + skill_lv / 2 - skill_lv / 4 + skill_lv / 5) * status->max_sp / 100;
 
 	if (opt&SCO_FIRST) {
-		hd->battle_status.hp = hom->hp ;
-		hd->battle_status.sp = hom->sp ;
+		hd->battle_status.hp = hom->hp;
+		hd->battle_status.sp = hom->sp;
 		if(hom->class_ == 6052) // Eleanor
 			sc_start(&hd->bl,&hd->bl, SC_STYLE_CHANGE, 100, MH_MD_FIGHTING, -1);
 	}
@@ -3731,10 +3758,6 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt)
 
 	status_calc_misc(&hd->bl, status, hom->level);
 
-#ifdef RENEWAL
-	status->matk_max = status->matk_min;
-#endif
-
 	status_cpy(&hd->battle_status, status);
 	return 1;
 }
@@ -4409,13 +4432,14 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 		 * RE MATK Formula (from irowiki:http:// irowiki.org/wiki/MATK)
 		 * MATK = (sMATK + wMATK + eMATK) * Multiplicative Modifiers
 		 **/
-		status->matk_min = status->matk_max = status_base_matk(status, status_get_lv(bl));
-		if( bl->type&BL_PC ) {
+		status->matk_min = status->matk_max = status_base_matk(bl, status, status_get_lv(bl));
+		switch( bl->type ) {
+		case BL_PC: {
 			int wMatk = 0;
 			int variance = 0;
 
 			// Any +MATK you get from skills and cards, including cards in weapon, is added here.
-			if( sd->bonus.ematk > 0 ) {
+			if (sd->bonus.ematk > 0) {
 				status->matk_max += sd->bonus.ematk;
 				status->matk_min += sd->bonus.ematk;
 			}
@@ -4423,7 +4447,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 			status->matk_max = status_calc_ematk(bl, sc, status->matk_max);
 			// This is the only portion in MATK that varies depending on the weapon level and refinement rate.
 
-			if(b_status->lhw.matk) {
+			if (b_status->lhw.matk) {
 				if (sd) {
 					//sd->state.lr_flag = 1; //?? why was that set here
 					status->lhw.matk = b_status->lhw.matk;
@@ -4433,22 +4457,44 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 				}
 			}
 
-			if(b_status->rhw.matk) {
+			if (b_status->rhw.matk) {
 				status->rhw.matk = b_status->rhw.matk;
 			}
 
-			if(status->rhw.matk) {
+			if (status->rhw.matk) {
 				wMatk += status->rhw.matk;
 				variance += wMatk * status->rhw.wlv / 10;
 			}
 
-			if(status->lhw.matk) {
+			if (status->lhw.matk) {
 				wMatk += status->lhw.matk;
 				variance += status->lhw.matk * status->lhw.wlv / 10;
 			}
 
 			status->matk_min += wMatk - variance;
 			status->matk_max += wMatk + variance;
+			}
+			break;
+
+		case BL_HOM:
+			if ((bl->type&BL_HOM && battle_config.hom_setting&HOMSET_SAME_MATK)  /// Hom Min Matk is always the same as Max Matk
+					|| (sc && sc->data[SC_RECOGNIZEDSPELL]))
+				status->matk_min = status->matk_max;
+			else
+				status->matk_min += (status_get_homint(bl) + status_get_homdex(bl)) / 5;
+
+			status->matk_max += (status_get_homluk(bl) + status_get_homint(bl) + status_get_homdex(bl)) / 3;
+			break;
+
+		case BL_MOB:
+			status->matk_min += 70 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100;
+			status->matk_max += 130 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100;
+			break;
+
+		default:
+			status->matk_max = status_calc_matk(bl, sc, status->matk_max);
+			status->matk_min = status_calc_matk(bl, sc, status->matk_min);
+			break;
 		}
 #endif
 		if (bl->type&BL_PC && sd->matk_rate != 100) {
@@ -4456,15 +4502,6 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 			status->matk_min = status->matk_min * sd->matk_rate/100;
 		}
 
-
-		status->matk_max = status_calc_matk(bl, sc, status->matk_max);
-
-		if ((bl->type&BL_HOM && battle_config.hom_setting&HOMSET_SAME_MATK)  /// Hom Min Matk is always the same as Max Matk
-				|| (sc && sc->data[SC_RECOGNIZEDSPELL]))
-			status->matk_min = status->matk_max;
-		else
-			status->matk_min = status_calc_matk(bl, sc, status->matk_min);
-
 #ifdef RENEWAL
 		if( sd && sd->right_weapon.overrefine > 0) {
 			status->matk_min++;
@@ -4475,7 +4512,25 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 
 	if(flag&SCB_ASPD) {
 		int amotion;
-		if( bl->type&BL_PC ) {
+		if ( bl->type&BL_HOM ) {
+#ifdef RENEWAL
+			amotion = ((TBL_HOM*)bl)->homunculusDB->baseASPD;
+			amotion = amotion - amotion * status_get_homdex(bl) / 1000 - status_get_homagi(bl) * amotion / 250;
+			amotion = (amotion * status_calc_aspd(bl, sc, 1) + status_calc_aspd(bl, sc, 2)) / - 100 + amotion;
+#else
+			amotion = (1000 - 4 * status->agi - status->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD / 1000;
+
+			amotion = status_calc_aspd_rate(bl, sc, b_status->aspd_rate);
+
+			if (status->aspd_rate != 1000)
+				amotion = amotion * status->aspd_rate / 1000;
+#endif
+
+			amotion = status_calc_fix_aspd(bl, sc, amotion);
+			status->amotion = cap_value(amotion, battle_config.max_aspd, 2000);
+
+			status->adelay = status->amotion;
+		} else if ( bl->type&BL_PC ) {
 			amotion = status_base_amotion_pc(sd,status);
 #ifndef RENEWAL_ASPD
 			status->aspd_rate = status_calc_aspd_rate(bl, sc, b_status->aspd_rate);
@@ -4497,21 +4552,6 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 			status->amotion = cap_value(amotion,pc_maxaspd(sd),2000);
 
 			status->adelay = 2*status->amotion;
-		} else if( bl->type&BL_HOM ) {
-#ifdef RENEWAL
-			amotion = (1000 -2*status->agi -status->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD/1000;
-#else
-			amotion = (1000 -4*status->agi -status->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD/1000;
-#endif
-			status->aspd_rate = status_calc_aspd_rate(bl, sc, b_status->aspd_rate);
-
-			if(status->aspd_rate != 1000)
-				amotion = amotion*status->aspd_rate/1000;
-
-			amotion = status_calc_fix_aspd(bl, sc, amotion);
-			status->amotion = cap_value(amotion,battle_config.max_aspd,2000);
-
-			status->adelay = status->amotion;
 		} else { // Mercenary and mobs
 			amotion = b_status->amotion;
 			status->aspd_rate = status_calc_aspd_rate(bl, sc, b_status->aspd_rate);
@@ -4544,8 +4584,9 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 			dmotion = 800-status->agi*4;
 			status->dmotion = cap_value(dmotion, 400, 800);
 			status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion);
-		} else // Mercenary and mobs
+		} else { // Mercenary and mobs
 			status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion);
+		}
 	}
 
 	if(flag&(SCB_VIT|SCB_MAXHP|SCB_INT|SCB_MAXSP) && bl->type&BL_REGEN)
@@ -10457,6 +10498,12 @@ int status_change_clear(struct block_list* bl, int type)
 			case SC_FOOD_DEX_CASH:
 			case SC_FOOD_INT_CASH:
 			case SC_FOOD_LUK_CASH:
+			case SC_SAVAGE_STEAK:
+			case SC_COCKTAIL_WARG_BLOOD:
+			case SC_MINOR_BBQ:
+			case SC_SIROMA_ICE_TEA:
+			case SC_DROCERA_HERB_STEAMED:
+			case SC_PUTTI_TAILS_NOODLES:
 			case SC_DEF_RATE:
 			case SC_MDEF_RATE:
 			case SC_INCHEALRATE:

+ 11 - 1
src/map/status.h

@@ -1992,6 +1992,14 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch
 #define status_get_class_(bl) status_get_status_data(bl)->class_
 #define status_get_size(bl) status_get_status_data(bl)->size
 #define status_get_mode(bl) status_get_status_data(bl)->mode
+
+#define status_get_homstr(bl) (status->str + ((TBL_HOM*)bl)->homunculus.str_value)
+#define status_get_homagi(bl) (status->agi + ((TBL_HOM*)bl)->homunculus.agi_value)
+#define status_get_homvit(bl) (status->vit + ((TBL_HOM*)bl)->homunculus.vit_value)
+#define status_get_homint(bl) (status->int_ + ((TBL_HOM*)bl)->homunculus.int_value)
+#define status_get_homdex(bl) (status->dex + ((TBL_HOM*)bl)->homunculus.dex_value)
+#define status_get_homluk(bl) (status->luk + ((TBL_HOM*)bl)->homunculus.luk_value)
+
 int status_get_party_id(struct block_list *bl);
 int status_get_guild_id(struct block_list *bl);
 int status_get_emblem_id(struct block_list *bl);
@@ -2052,9 +2060,11 @@ int status_change_spread( struct block_list *src, struct block_list *bl );
 	unsigned short status_base_matk_max(const struct status_data* status);
 #else
 	unsigned int status_weapon_atk(struct weapon_atk wa, struct status_data *status);
-	unsigned short status_base_matk(const struct status_data* status, int level);
 #endif
 
+unsigned short status_base_atk(const struct block_list *bl, const struct status_data *status);
+unsigned short status_base_matk(struct block_list *bl, const struct status_data* status, int level);
+
 int status_readdb(void);
 int do_init_status(void);
 void do_final_status(void);