Browse Source

ReqItems and Various Fixs

-Add requiered equiped item to cast in skill_require_db.
-Fix SC_ASH not always giving 50% chance failing, wrong emplacement
-Fix SC_STYLE_CHANGE not being relaunch when eleanor resurected.
-Fix cardfix for target not being reseted and therefor using same value
as caster.
-Move ADJUST_SKILL_DAMAGE in battle_calc_weapon_final_atk_modifiers
(since it shuold alter the final dammage just like it do for magic and
misc)
-Add battle_do_reflect and skill_do_copy small function to encapsulate
code.
-Upd channel_clean and channel_delete to simplify autodelete case for
public chans
-Fix SC_FEINTBOMB that had a fixed blewcount and not 3*skilllv
-Fix SC_VACUUM_EXTREME where some scenario was setting scs_nomove to -1
and therefor blocking char forever.
-Fix SC_STRIKING where val1 was overwritten for sp cast but also used as
skilllv for critical bonus...
-Upd SC_GN_CARTBOOST, should be ending be DECREASE_AGI
-Upd SC_MAGNETICFIELD should be endend when getting earth dmg or
quagmire
-Mv SC_WARMER, SC_WHITEIMPRISON, SC_FREEZING ending other status section
in proper area.
lighta 11 năm trước cách đây
mục cha
commit
c70762a18f
10 tập tin đã thay đổi với 1185 bổ sung1080 xóa
  1. 759 759
      db/re/skill_require_db.txt
  2. 197 164
      src/map/battle.c
  3. 6 2
      src/map/channel.c
  4. 6 14
      src/map/clif.c
  5. 2 0
      src/map/homunculus.c
  6. 16 0
      src/map/pc.c
  7. 1 0
      src/map/pc.h
  8. 153 111
      src/map/skill.c
  9. 4 2
      src/map/skill.h
  10. 41 28
      src/map/status.c

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 759 - 759
db/re/skill_require_db.txt


+ 197 - 164
src/map/battle.c

@@ -267,7 +267,7 @@ int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src,
 	if ( !battle_config.delay_battle_damage || amotion <= 1 ) {
 		map_freeblock_lock();
 		status_fix_damage(src, target, damage, ddelay); // We have to seperate here between reflect damage and others [icescope]
-		if( attack_type && !status_isdead(target) && additional_effects ) 
+		if( attack_type && !status_isdead(target) && additional_effects )
 			skill_additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, gettick());
 		if( dmg_lv > ATK_BLOCK && attack_type )
 			skill_counter_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick());
@@ -327,13 +327,18 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
 	}
 
 	ratio = attr_fix_table[def_lv-1][atk_elem][def_type];
-	if (sc && sc->count) {
-		if(sc->data[SC_VOLCANO] && atk_elem == ELE_FIRE)
-			ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1];
-		if(sc->data[SC_VIOLENTGALE] && atk_elem == ELE_WIND)
-			ratio += enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1];
-		if(sc->data[SC_DELUGE] && atk_elem == ELE_WATER)
-			ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1];
+	if (sc && sc->count) { //increase dmg by src status
+		switch(atk_elem){
+		case ELE_FIRE:
+			if(sc->data[SC_VOLCANO]) ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1];
+			break;
+		case ELE_WIND:
+			if(sc->data[SC_VIOLENTGALE]) ratio += enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1];
+			break;
+		case ELE_WATER:
+			if(sc->data[SC_DELUGE]) ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1];
+			break;
+		}
 	}
 	if( target && target->type == BL_SKILL ) {
 		if( atk_elem == ELE_FIRE && battle_getcurrentskill(target) == GN_WALLOFTHORN ) {
@@ -355,45 +360,48 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
 			}
 		}
 	}
-	if( tsc && tsc->count ) { //since an atk can only have one type let's optimise this a bit
+
+
+	if( tsc && tsc->count ) { //increase dmg by target status
 		switch(atk_elem){
-                case ELE_FIRE:
-                        if( tsc->data[SC_SPIDERWEB]) {
-                                tsc->data[SC_SPIDERWEB]->val1 = 0; // free to move now
-                                if( tsc->data[SC_SPIDERWEB]->val2-- > 0 )
-                                        damage <<= 1; // double damage
-                                if( tsc->data[SC_SPIDERWEB]->val2 == 0 )
-                                        status_change_end(target, SC_SPIDERWEB, INVALID_TIMER);
-                        }
-                        if( tsc->data[SC_THORNSTRAP])
-                                status_change_end(target, SC_THORNSTRAP, INVALID_TIMER);
-                        if( tsc->data[SC_FIRE_CLOAK_OPTION])
-                                DAMAGE_SUBRATE(tsc->data[SC_FIRE_CLOAK_OPTION]->val2)
-                        if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB)
-                                status_change_end(target, SC_CRYSTALIZE, INVALID_TIMER);
-                        if( tsc->data[SC_EARTH_INSIGNIA]) damage += damage/2;
-						if( tsc->data[SC_ASH]) damage += damage/2; //150%
-                        break;
-                case ELE_HOLY:
-                        if( tsc->data[SC_ORATIO]) ratio += tsc->data[SC_ORATIO]->val1 * 2;
-                        break;
-                case ELE_POISON:
-                        if( tsc->data[SC_VENOMIMPRESS]) ratio += tsc->data[SC_VENOMIMPRESS]->val2;
-                        break;
-                case ELE_WIND:
-                        if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB) damage += damage/2;
-                        if( tsc->data[SC_WATER_INSIGNIA]) damage += damage/2;
-                        break;
-                case ELE_WATER:
-                        if( tsc->data[SC_FIRE_INSIGNIA]) damage += damage/2;
-                        break;
-                case ELE_EARTH:
-                        if( tsc->data[SC_WIND_INSIGNIA]) damage += damage/2;
-                        break;
+		case ELE_FIRE:
+			if( tsc->data[SC_SPIDERWEB]) {
+				tsc->data[SC_SPIDERWEB]->val1 = 0; // free to move now
+				if( tsc->data[SC_SPIDERWEB]->val2-- > 0 )
+					ratio += 200; // double damage
+				if( tsc->data[SC_SPIDERWEB]->val2 == 0 )
+					status_change_end(target, SC_SPIDERWEB, INVALID_TIMER);
+			}
+			if( tsc->data[SC_THORNSTRAP])
+				status_change_end(target, SC_THORNSTRAP, INVALID_TIMER);
+			if( tsc->data[SC_FIRE_CLOAK_OPTION])
+				DAMAGE_SUBRATE(tsc->data[SC_FIRE_CLOAK_OPTION]->val2)
+			if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB)
+				status_change_end(target, SC_CRYSTALIZE, INVALID_TIMER);
+			if( tsc->data[SC_EARTH_INSIGNIA]) ratio += 150;
+			if( tsc->data[SC_ASH]) ratio += 150; //150%
+			break;
+		case ELE_HOLY:
+			if( tsc->data[SC_ORATIO]) ratio += tsc->data[SC_ORATIO]->val1 * 2;
+			break;
+		case ELE_POISON:
+			if( tsc->data[SC_VENOMIMPRESS]) ratio += tsc->data[SC_VENOMIMPRESS]->val2;
+			break;
+		case ELE_WIND:
+			if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB) ratio += 150;
+			if( tsc->data[SC_WATER_INSIGNIA]) ratio += 150;
+			break;
+		case ELE_WATER:
+			if( tsc->data[SC_FIRE_INSIGNIA]) ratio += 150;
+			break;
+		case ELE_EARTH:
+			if( tsc->data[SC_WIND_INSIGNIA]) ratio += 150;
+			status_change_end(target, SC_MAGNETICFIELD, INVALID_TIMER); //freed if received earth dmg
+			break;
 		}
 	} //end tsc check
-	if( src && src->type == BL_PC ){
-		struct map_session_data *sd = BL_CAST(BL_PC, src);
+	if (src && src->type == BL_PC) {
+		TBL_PC *sd = BL_CAST(BL_PC,src);
 		int s;
 
 		ARR_FIND(1, 6, s, sd->talisman[s] > 0);
@@ -402,11 +410,10 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
 			ratio += sd->talisman[s] * 2; // +2% custom value
 	}
 	if( target && target->type == BL_PC ) {
-		struct map_session_data *tsd = BL_CAST(BL_PC, target);
+		TBL_PC *tsd = BL_CAST(BL_PC, target);
 		int t;
 
 		ARR_FIND(1, 6, t, tsd->talisman[t] > 0);
-
 		if( t < 5 && atk_elem == t )
 			DAMAGE_SUBRATE(tsd->talisman[t] * 3) // -3% custom value
 	}
@@ -458,6 +465,8 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 
 			if( tsd && !(nk&NK_NO_CARDFIX_DEF) )
 			{ // Target cards.
+				cardfix = 1000; //reset  var for target
+
 				if (!(nk&NK_NO_ELEFIX))
 				{
 					int ele_fix = tsd->subele[s_ele];
@@ -746,8 +755,8 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 	if( battle_config.ksprotection && mob_ksprotected(src, bl) )
 		return 0;
 
-	if( map_getcell(bl->m, bl->x, bl->y, CELL_CHKMAELSTROM) && skill_get_type(skill_id) != BF_MISC  
-		&& skill_get_casttype(skill_id) == CAST_GROUND ) 
+	if( map_getcell(bl->m, bl->x, bl->y, CELL_CHKMAELSTROM) && skill_get_type(skill_id) != BF_MISC
+		&& skill_get_casttype(skill_id) == CAST_GROUND )
 		return 0;
 
 	if (bl->type == BL_PC) {
@@ -1481,10 +1490,10 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in
 				damage += (skill * 3);
 			break;
 	}
-	
+
 	if(sd && (skill=pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) // weapon research bonus applies to all weapons
 		damage += skill*2;
-		
+
 	if(sd->sc.data[SC_GN_CARTBOOST]) // cart boost adds mastery type damage
 		damage += 10*sd->sc.data[SC_GN_CARTBOOST]->val1;
 
@@ -1516,22 +1525,23 @@ static int battle_calc_status_attack(struct status_data *status, short hand)
 static int battle_calc_base_weapon_attack(struct block_list *src, struct status_data *tstatus, struct weapon_atk *wa, struct map_session_data *sd)
 {
 	struct status_data *status = status_get_status_data(src);
-	unsigned short atkmax = (wa == &status->lhw)?status->watk2:status->watk;
-	unsigned short atkmin = atkmax;
-	unsigned short weapon_perfection = 0;
-	int damage;
+	uint8 type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R;
+	uint16 atkmin = (type == EQI_HAND_L)?status->watk2:status->watk;
+	uint16 atkmax = atkmin;
+	int damage = atkmin;
+	uint16 weapon_perfection = 0;
 	struct status_change *sc = status_get_sc(src);
-	unsigned char type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R;
 
 	if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]]) {
-		atkmin -= wa->atk * (sd->inventory_data[sd->equip_index[type]]->wlv*5)/100;
-		atkmax += wa->atk * (sd->inventory_data[sd->equip_index[type]]->wlv*5)/100;
-	}
+		int variance =   wa->atk * (sd->inventory_data[sd->equip_index[type]]->wlv*5)/100;
+		atkmin -= variance;
+		atkmax += variance;
 
-	if (sc && sc->data[SC_MAXIMIZEPOWER])
-		damage = atkmax;
-	else
-		damage = (atkmax>atkmin? rnd()%(atkmax-atkmin):0) + atkmin;
+		if (sc && sc->data[SC_MAXIMIZEPOWER])
+			damage = atkmax;
+		else
+			damage =  rnd_value(atkmin,atkmax);
+	}
 
 	if (sc && sc->data[SC_WEAPONPERFECTION])
 		weapon_perfection = 1;
@@ -1576,7 +1586,7 @@ static int64 battle_calc_base_damage(struct status_data *status, struct weapon_a
 			atkmin = atkmax;
 	} else { //PCs
 		atkmax = wa->atk;
-		type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R; 
+		type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R;
 
 		if (!(flag&1) || (flag&2)) { //Normal attacks
 			atkmin = status->dex;
@@ -1592,7 +1602,7 @@ static int64 battle_calc_base_damage(struct status_data *status, struct weapon_a
 				if (atkmin > atkmax)
 					atkmax = atkmin;
 			}
-		} 
+		}
 	}
 
 	if (sc && sc->data[SC_MAXIMIZEPOWER])
@@ -1637,7 +1647,7 @@ static int64 battle_calc_base_damage(struct status_data *status, struct weapon_a
 				DAMAGE_ADDRATE(sd->weapon_atk_rate[sd->weapontype1])
 		}
 	}
-	
+
 #ifdef RENEWAL
 	if (flag&1)
 		damage = (damage * 14) / 10;
@@ -1672,7 +1682,7 @@ void battle_consume_ammo(TBL_PC*sd, int skill, int lv)
 }
 
 static int battle_range_type(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv)
-{	
+{
 	// [Akinari] , [Xynvaroth]: Traps are always short range.
 	if( skill_get_inf2( skill_id ) & INF2_TRAP )
 		return BF_SHORT;
@@ -1735,10 +1745,10 @@ int battle_skill_damage_skill(struct block_list *src, struct block_list *target,
 	unsigned short m = src->m;
 	int idx;
 	struct s_skill_damage *damage = NULL;
-	
+
 	if ((idx = skill_get_index(skill_id)) < 0 || !skill_db[idx].damage.map)
 		return 0;
-		
+
 	damage = &skill_db[idx].damage;
 
 	//check the adjustment works for specified type
@@ -1882,7 +1892,7 @@ static bool is_attack_right_handed(struct block_list *src, int skill_id)
 {
 	if(src != NULL) {
 		struct map_session_data *sd = BL_CAST(BL_PC, src);
-		
+
 		//Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2)
 		if(!skill_id && sd && sd->weapontype1 == 0 && sd->weapontype2 > 0)
 			return false;
@@ -1908,7 +1918,7 @@ static bool is_attack_left_handed(struct block_list *src, int skill_id)
 		if(!skill_id) {
 			if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0)
 				return true;
-			
+
 			if (sstatus->lhw.atk)
 				return true;
 
@@ -2003,10 +2013,10 @@ static int is_attack_piercing(struct Damage wd, struct block_list *src, struct b
 		struct map_session_data *sd = BL_CAST(BL_PC, src);
 		struct status_data *tstatus = status_get_status_data(target);
 #ifdef RENEWAL
-		if( skill_id != PA_SACRIFICE && skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS 
+		if( skill_id != PA_SACRIFICE && skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS
 			&& skill_id != PA_SHIELDCHAIN && skill_id != ASC_BREAKER ) // Renewal: Soul Breaker no longer gains ice pick effect and ice pick effect gets crit benefit [helvetica]
 #else
-		if( skill_id != PA_SACRIFICE && skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS 
+		if( skill_id != PA_SACRIFICE && skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS
 			&& skill_id != PA_SHIELDCHAIN && !is_attack_critical(wd, src, target, skill_id, skill_lv, false) )
 #endif
 		{ //Elemental/Racial adjustments
@@ -2159,7 +2169,7 @@ static bool is_attack_hitting(struct Damage wd, struct block_list *src, struct b
 		case GC_VENOMPRESSURE:
 			hitrate += 10 + 4 * skill_lv;
 			break;
-			
+
 	}
 	else if( sd && wd.type&0x08 && wd.div_ == 2 ) // +1 hit per level of Double Attack on a successful double attack (making sure other multi attack skills do not trigger this) [helvetica]
 		hitrate += pc_checkskill(sd,TF_DOUBLE);
@@ -2305,7 +2315,7 @@ static int battle_get_weapon_element(struct Damage wd, struct block_list *src, s
 		// on official endows override all other elements [helvetica]
 		if( sd ){ //Summoning 10 talisman will endow your weapon.
 			ARR_FIND(1, 6, i, sd->talisman[i] >= 10);
-			if( i < 5 ) 
+			if( i < 5 )
 				element = i;
 			if(sc) { // check for endows
 				if(sc->data[SC_ENCHANTARMS])
@@ -2323,7 +2333,7 @@ static int battle_get_weapon_element(struct Damage wd, struct block_list *src, s
 			element = wd.miscflag; //element comes in flag.
 			break;
 		case LK_SPIRALPIERCE:
-			if (!sd) 
+			if (!sd)
 				element = ELE_NEUTRAL; //forced neutral for monsters
 			break;
 		case KO_KAIHOU:
@@ -2379,13 +2389,13 @@ static struct Damage battle_calc_element_damage(struct Damage wd, struct block_l
 		if( wd.damage > 0 )
 		{
 			wd.damage=battle_attr_fix(src, target, wd.damage, right_element, tstatus->def_ele, tstatus->ele_lv);
-			
+
 			if( skill_id == MC_CARTREVOLUTION ) //Cart Revolution apply the element fix once more with neutral element
 				wd.damage = battle_attr_fix(src, target, wd.damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
-			
+
 			if( skill_id == GS_GROUNDDRIFT ) //Additional 50*lv Neutral damage.
 				wd.damage += battle_attr_fix(src, target, 50*skill_lv, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
-			
+
 		}
 		if( is_attack_left_handed(src, skill_id) && wd.damage2 > 0 )
 			wd.damage2 = battle_attr_fix(src, target, wd.damage2, left_element ,tstatus->def_ele, tstatus->ele_lv);
@@ -2508,13 +2518,13 @@ struct Damage battle_calc_damage_parts(struct Damage wd, struct block_list *src,
 	if (!skill_id) { // status atk is considered neutral on normal attacks [helvetica]
 		if(sd && sd->sc.data[SC_SEVENWIND]) { // Mild Wind applies element to status ATK as well as weapon ATK [helvetica]
 			wd.statusAtk = (int)battle_attr_fix(src, target, wd.statusAtk, right_element, tstatus->def_ele, tstatus->ele_lv);
-			wd.statusAtk2 = (int)battle_attr_fix(src, target, wd.statusAtk, left_element, tstatus->def_ele, tstatus->ele_lv);	
-		}	
+			wd.statusAtk2 = (int)battle_attr_fix(src, target, wd.statusAtk, left_element, tstatus->def_ele, tstatus->ele_lv);
+		}
 		else {
 			wd.statusAtk = (int)battle_attr_fix(src, target, wd.statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
 			wd.statusAtk2 = (int)battle_attr_fix(src, target, wd.statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
-		}	
-	} 
+		}
+	}
 	else {
 		wd.statusAtk = (int)battle_attr_fix(src, target, wd.statusAtk, right_element, tstatus->def_ele, tstatus->ele_lv);
 		wd.statusAtk2 = (int)battle_attr_fix(src, target, wd.statusAtk, left_element, tstatus->def_ele, tstatus->ele_lv);
@@ -2652,14 +2662,14 @@ struct Damage battle_calc_skill_base_damage(struct Damage wd, struct block_list
 #ifdef RENEWAL
 			wd.weaponAtk = (int)wd.damage;
 			wd.weaponAtk2 = (int)wd.damage2;
-#endif				
+#endif
 			break;
 		case HFLI_SBR44:	//[orn]
 			if(src->type == BL_HOM) {
 				wd.damage = ((TBL_HOM*)src)->homunculus.intimacy ;
 			}
 			break;
-			
+
 		default:
 		{
 #ifdef RENEWAL
@@ -2715,7 +2725,7 @@ struct Damage battle_calc_skill_base_damage(struct Damage wd, struct block_list
 					ATK_ADDRATE(wd.damage, wd.damage2, sd->bonus.atk_rate);
 					RE_ALLATK_ADDRATE(wd, sd->bonus.atk_rate);
 				}
-#ifndef RENEWAL					
+#ifndef RENEWAL
 				if(is_attack_critical(wd, src, target, skill_id, skill_lv, false) && sd->bonus.crit_atk_rate) { // add +crit damage bonuses here in pre-renewal mode [helvetica]
 					ATK_ADDRATE(wd.damage, wd.damage2, sd->bonus.crit_atk_rate);
 				}
@@ -2795,7 +2805,7 @@ static struct Damage battle_calc_multi_attack(struct Damage wd, struct block_lis
 				wd.div_ = wd.div_ * -1;// needs more info
 			break;
 	}
-	
+
 	return wd;
 }
 
@@ -3496,11 +3506,12 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
 		case WM_SOUND_OF_DESTRUCTION:
 			skillratio += 400;
 			break;
-		case GN_CART_TORNADO:
-			// ATK [( Skill Level x 50 ) + ( Cart Weight / ( 150 - Caster Base STR ))] + ( Cart Remodeling Skill Level x 50 )] %
-			skillratio = 50 * skill_lv;
+		case GN_CART_TORNADO: { // ATK [( Skill Level x 50 ) + ( Cart Weight / ( 150 - Caster Base STR ))] + ( Cart Remodeling Skill Level x 50 )] %
+			int str = status_get_base_status(src)->str; //only using base str
+			skillratio += -100 + 50 * skill_lv;
 			if( sd && sd->cart_weight)
-					skillratio += sd->cart_weight/10 / max(150-sd->status.str,1) + pc_checkskill(sd, GN_REMODELING_CART) * 50;
+				skillratio += sd->cart_weight/10 / (150-str) + pc_checkskill(sd, GN_REMODELING_CART) * 50;
+			}
 			break;
 		case GN_CARTCANNON:
 			// ATK [{( Cart Remodeling Skill Level x 50 ) x ( INT / 40 )} + ( Cart Cannon Skill Level x 60 )] %
@@ -3757,7 +3768,7 @@ struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, u
 			if( sc->data[SC_EDP] ){
 				switch(skill_id){
 					case AS_SPLASHER:
-			// Pre-Renewal only: Soul Breaker and Meteor Assault ignores EDP 
+			// Pre-Renewal only: Soul Breaker and Meteor Assault ignores EDP
 			// Renewal only: Grimtooth and Venom Knife ignore EDP
 			// Both: Venom Splasher ignores EDP [helvetica]
 #ifndef RENEWAL
@@ -3778,7 +3789,7 @@ struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, u
 					case ASC_BREAKER:
 					case GC_COUNTERSLASH:
 					case GC_CROSSIMPACT:
-						ATK_RATE(wd.weaponAtk, wd.weaponAtk2, 50); 
+						ATK_RATE(wd.weaponAtk, wd.weaponAtk2, 50);
 						ATK_RATE(wd.equipAtk, wd.equipAtk2, 50);
 					default: // fall through to apply EDP bonuses
 						// Renewal EDP formula [helvetica]
@@ -3790,7 +3801,7 @@ struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, u
 #else
 					default:
 						ATK_ADDRATE(wd.damage, wd.damage2, sc->data[SC_EDP]->val3);
-						
+
 #endif
 				}
 			}
@@ -4073,7 +4084,7 @@ struct Damage battle_calc_attack_left_right_hands(struct Damage wd, struct block
 	int skill;
 
 	if (sd) {
-		if (!is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id)) { 
+		if (!is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id)) {
 			wd.damage = wd.damage2;
 			wd.damage2 = 0;
 		}
@@ -4172,6 +4183,9 @@ struct Damage battle_calc_weapon_final_atk_modifiers(struct Damage wd, struct bl
 	struct status_change *tsc = status_get_sc(target);
 	struct status_data *sstatus = status_get_status_data(src);
 	struct status_data *tstatus = status_get_status_data(target);
+#ifdef ADJUST_SKILL_DAMAGE
+	int skill_damage;
+#endif
 
 	//Reject Sword bugreport:4493 by Daegaladh
 	if(wd.damage && tsc && tsc->data[SC_REJECTSWORD] &&
@@ -4247,6 +4261,12 @@ struct Damage battle_calc_weapon_final_atk_modifiers(struct Damage wd, struct bl
 			break;
 #endif
 	}
+
+	/* Skill damage adjustment */
+#ifdef ADJUST_SKILL_DAMAGE
+	if ((skill_damage = battle_skill_damage(src, target, skill_id)) != 0)
+		ATK_ADDRATE(wd.damage, wd.damage2, skill_damage);
+#endif
 	return wd;
 }
 
@@ -4269,7 +4289,7 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
 	wd.div_=skill_id?skill_get_num(skill_id,skill_lv):1;
 	wd.amotion=(skill_id && skill_get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills.
 	// counter attack DOES obey ASPD delay on official, uncomment if you want the old (bad) behavior [helvetica]
-	/*if(skill_id == KN_AUTOCOUNTER) 
+	/*if(skill_id == KN_AUTOCOUNTER)
 		wd.amotion >>= 1; */
 	wd.dmotion=tstatus->dmotion;
 	wd.blewcount=skill_get_blewcount(skill_id,skill_lv);
@@ -4277,8 +4297,8 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
 	wd.flag = BF_WEAPON; //Initial Flag
 	wd.flag |= (skill_id||wd.miscflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish]
 
-	wd.damage = wd.damage2 = 
-#ifdef RENEWAL	
+	wd.damage = wd.damage2 =
+#ifdef RENEWAL
 	wd.statusAtk = wd.statusAtk2 = wd.equipAtk = wd.equipAtk2 = wd.weaponAtk = wd.weaponAtk2 = wd.masteryAtk = wd.masteryAtk2 =
 #endif
 	0;
@@ -4339,6 +4359,63 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
 	return wd;
 }
 
+/*
+ * Check if we should reflect the dammage and calculate it if so
+ * @param attack_type : BL_WEAPON,BL_MAGIC or BL_MISC
+ * @param wd : weapon damage
+ * @param src : bl who did the attack
+ * @param target : target of the attack
+ * @parem skill_id : id of casted skill, 0 = basic atk
+ * @param skill_lv : lvl of skill casted
+ */
+void battle_do_reflect(int attack_type, struct Damage *wd, struct block_list* src, struct block_list* target, uint16 skill_id, uint16 skill_lv){
+
+	if( (wd->damage + wd->damage2) && src && target && src != target &&
+		(src->type != BL_SKILL ||
+		(src->type == BL_SKILL && ( skill_id == SG_SUN_WARM || skill_id == SG_MOON_WARM || skill_id == SG_STAR_WARM )) )
+	){ //don't reflect to ourself
+		int64 damage = wd->damage + wd->damage2, rdamage = 0;
+		struct map_session_data *tsd = BL_CAST(BL_PC, target);
+		struct status_change *tsc = status_get_sc(target);
+		struct status_data *sstatus = status_get_status_data(src);
+		int tick = gettick(), rdelay = 0;
+
+		// Item reflect gets calculated first
+		rdamage = battle_calc_return_damage(target, src, &damage, wd->flag, skill_id, 0);
+		if( rdamage > 0 ) {
+			//Use Reflect Shield to signal this kind of skill trigger. [Skotlex]
+			rdelay = clif_damage(src, src, tick, wd->amotion, sstatus->dmotion, rdamage, 1, 4, 0);
+			if( tsd ) battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src));
+			battle_delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
+			skill_additional_effect(target, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
+		}
+
+		// Calculate skill reflect damage separately
+		if( tsc ) {
+			struct status_data *tstatus = status_get_status_data(target);
+			rdamage = battle_calc_return_damage(target, src, &damage, wd->flag, skill_id, 1);
+			if( rdamage > 0 ) {
+				//if(tsc->data[SC__SHADOWFORM]) {
+				//	struct block_list *s_bl = map_id2bl(tsc->data[SC__SHADOWFORM]->val2);
+				//	if(s_bl)
+				//		status_damage(src, s_bl, rdamage, 0, clif_damage(src, s_bl, gettick(), 500, 500, rdamage, -1, 0, 0), 0);
+				//	wd->damage = wd->damage2 = 0;
+				//	wd->dmg_lv = ATK_BLOCK;
+				//}
+
+				if(attack_type == BF_WEAPON && tsc->data[SC_REFLECTDAMAGE] ) // Don't reflect your own damage (Grand Cross)
+					map_foreachinshootrange(battle_damage_area,target,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd->amotion,sstatus->dmotion,rdamage,tstatus->race);
+				else if(attack_type == BF_WEAPON || attack_type == BF_MISC) {
+					rdelay = clif_damage(src, src, tick, wd->amotion, sstatus->dmotion, rdamage, 1, 4, 0);
+					if( tsd ) battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src));
+					// It appears that official servers give skill reflect damage a longer delay
+					battle_delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
+					skill_additional_effect(target, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
+				}
+			}
+		}
+	}
+}
 /*============================================
  * Calculate "weapon"-type attacks and skills
  *--------------------------------------------
@@ -4350,9 +4427,6 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
 static struct Damage battle_calc_weapon_attack(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int wflag)
 {
 	int i;
-#ifdef ADJUST_SKILL_DAMAGE
-	int skill_damage;
-#endif
 	struct map_session_data *sd, *tsd;
 	struct Damage wd;
 	struct status_change *sc = status_get_sc(src);
@@ -4388,10 +4462,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 		if (wd.div_ < 0) wd.div_*=-1;
 		return wd;
 	}
-	
+
 	// on official check for multi hit first so we can override crit on double attack [helvetica]
 	wd = battle_calc_multi_attack(wd, src, target, skill_id, skill_lv);
-	
+
 	// crit check is next since crits always hit on official [helvetica]
 	if (is_attack_critical(wd, src, target, skill_id, skill_lv, true))
 		wd.type = 0x0a;
@@ -4421,12 +4495,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 			}
 		}
 #endif
-		// add any miscellaneous player ATK bonuses			
+		// add any miscellaneous player ATK bonuses
 		if( sd && skill_id && (i = pc_skillatk_bonus(sd, skill_id))) {
 			ATK_ADDRATE(wd.damage, wd.damage2, i);
 			RE_ALLATK_ADDRATE(wd, i);
 		}
-	
+
 #ifdef RENEWAL
 		// In Renewal we only cardfix to the weapon and equip ATK
 		//Card Fix for attacker (sd), 2 is added to the "left" flag meaning "attacker cards only"
@@ -4473,10 +4547,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 	if(!sd) // monsters only have a single ATK for element, in pre-renewal we also apply element to entire ATK on players [helvetica]
 #endif
 		wd = battle_calc_element_damage(wd, src, target, skill_id, skill_lv);
-				
+
 	if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS)
 		return wd; //Enough, rest is not needed.
-		
+
 #ifdef RENEWAL
 	if(is_attack_critical(wd, src, target, skill_id, skill_lv, false)) {
 		if(sd) // check for player so we don't crash out, monsters don't have bonus crit rates [helvetica]
@@ -4509,7 +4583,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 			wd.damage2 += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.damage2, 3, wd.flag);
 #endif
 	}
-	
+
 	if(tsd) { // Card Fix for target (tsd), 2 is not added to the "left" flag meaning "target cards only"
 		switch(skill_id) { // These skills will do a card fix later
 #ifdef RENEWAL
@@ -4539,19 +4613,18 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 			wd.damage = battle_attr_fix(src,target,wd.damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
 			break;
 	}
-	
+
 	// perform multihit calculations
 #ifdef RENEWAL
 	damage_div_fix_renewal(wd, wd.div_);
-#endif 
+#endif
 	damage_div_fix(wd.damage, wd.div_);
-	
+
 	// only do 1 dmg to plant, no need to calculate rest
 	if(target_has_infinite_defense(target, skill_id))
 		return battle_calc_attack_plant(wd, src, target, skill_id, skill_lv);
 
 	wd = battle_calc_attack_left_right_hands(wd, src, target, skill_id, skill_lv);
-	wd = battle_calc_weapon_final_atk_modifiers(wd, src, target, skill_id, skill_lv);
 
 	switch (skill_id) { // These skills will do a GVG fix later
 #ifdef RENEWAL
@@ -4566,52 +4639,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 			break;
 	}
 
-	/* Skill damage adjustment */
-#ifdef ADJUST_SKILL_DAMAGE
-	if ((skill_damage = battle_skill_damage(src, target, skill_id)) != 0)
-		ATK_ADDRATE(wd.damage, wd.damage2, skill_damage);
-#endif
-	
-	// Do reflect calculation after all atk modifier
-	// Don't reflect your own damage (Grand Cross)
-	if( wd.damage + wd.damage2 && src != target &&
-		(src->type != BL_SKILL ||
-		(src->type == BL_SKILL && ( skill_id == SG_SUN_WARM || skill_id == SG_MOON_WARM || skill_id == SG_STAR_WARM ))) )
-	{
-		int64 damage = wd.damage + wd.damage2, rdamage = 0;
-		struct status_data *sstatus = status_get_status_data(src);
-		int tick = gettick(), rdelay = 0;
-
-		rdamage = battle_calc_return_damage(target, src, &damage, wd.flag, skill_id, 0);
-
-		// Item reflect gets calculated first
-		if( rdamage > 0 ) {
-			//Use Reflect Shield to signal this kind of skill trigger. [Skotlex]
-			rdelay = clif_damage(src,src,tick,wd.amotion,sstatus->dmotion,rdamage,1,4,0);
-			if( tsd )
-				battle_drain(tsd,src,rdamage,rdamage,sstatus->race,is_boss(src));
-			battle_delay_damage(tick,wd.amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
-			skill_additional_effect(target,src,CR_REFLECTSHIELD,1,BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
-		}
+	wd = battle_calc_weapon_final_atk_modifiers(wd, src, target, skill_id, skill_lv);
 
-		// Calculate skill reflect damage separately
-		if( tsc ) {
-			struct status_data *tstatus = status_get_status_data(target);
-			rdamage = battle_calc_return_damage(target,src,&damage,wd.flag,skill_id,1);
-			if( rdamage > 0 ) {
-				if( tsc->data[SC_REFLECTDAMAGE] )
-					map_foreachinshootrange(battle_damage_area,target,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd.amotion,sstatus->dmotion,rdamage,tstatus->race);
-				else {
-					rdelay = clif_damage(src,src,tick,wd.amotion,sstatus->dmotion,rdamage,1,4,0);
-					if( tsd )
-						battle_drain(tsd,src,rdamage,rdamage,sstatus->race,is_boss(src));
-					// It appears that official servers give skill reflect damage a longer delay
-					battle_delay_damage(tick,wd.amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
-					skill_additional_effect(target,src,CR_REFLECTSHIELD,1,BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
-				}
-			}
-		}
-	}
+	battle_do_reflect(BF_WEAPON,&wd, src, target, skill_id, skill_lv); //WIP [lighta]
 
 	return wd;
 }
@@ -4973,11 +5003,11 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 						break;
 					case WL_COMET:
 						i = ( sc ? distance_xy(target->x, target->y, sc->comet_x, sc->comet_y) : 8 );
-						if( i <= 3 ) 
+						if( i <= 3 )
 							skillratio += 2400 + 500 * skill_lv; // 7 x 7 cell
-						else if( i <= 5 ) 
+						else if( i <= 5 )
 							skillratio += 1900 + 500 * skill_lv; // 11 x 11 cell
-						else if( i <= 7 ) 
+						else if( i <= 7 )
 							skillratio += 1400 + 500 * skill_lv; // 15 x 15 cell
 						else
 							skillratio += 900 + 500 * skill_lv; // 19 x 19 cell
@@ -5302,6 +5332,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 		MATK_ADDRATE(skill_damage);
 #endif
 
+	battle_do_reflect(BF_MAGIC,&ad, src, target, skill_id, skill_lv); //WIP [lighta]
 	return ad;
 }
 
@@ -5436,11 +5467,11 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 			struct Damage atk = battle_calc_weapon_attack(src, target, skill_id, skill_lv, 0);
 			struct Damage matk = battle_calc_magic_attack(src, target, skill_id, skill_lv, 0);
 			md.damage = 7 * ((atk.damage/skill_lv + matk.damage/skill_lv) * tstatus->vit / 100 );
-			
+
 			// AD benefits from endow/element but damage is forced back to neutral
 			battle_attr_fix(src, target, md.damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
 		}
-#else 
+#else
 		if(tstatus->vit+sstatus->int_) //crash fix
 			md.damage = (int)((int64)7*tstatus->vit*sstatus->int_*sstatus->int_ / (10*(tstatus->vit+sstatus->int_)));
 		else
@@ -5460,8 +5491,8 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 		break;
 #ifdef RENEWAL
 	case NJ_ISSEN:
-		// Official Renewal formula [helvetica] 
-		// base damage = currenthp + ((atk * currenthp * skill level) / maxhp) 
+		// Official Renewal formula [helvetica]
+		// base damage = currenthp + ((atk * currenthp * skill level) / maxhp)
 		// final damage = base damage + ((mirror image count + 1) / 5 * base damage) - (edef + sdef)
 		// modified def formula
 		{
@@ -5484,7 +5515,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 	case GS_FLING:
 		md.damage = sd?sd->status.job_level:status_get_lv(src);
 		break;
-	case GS_GROUNDDRIFT: 
+	case GS_GROUNDDRIFT:
 		// Official formula [helvetica]
 		// damage = 50 * skill level
 		// fixed damage, ignores DEF and benefits from weapon +%ATK cards
@@ -5699,6 +5730,8 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 	if(tstatus->mode&MD_IGNOREMISC && md.flag&(BF_MISC) )	//misc @TODO optimize me
 		md.damage = md.damage2 = 1;
 
+	battle_do_reflect(BF_MISC,&md, src, target, skill_id, skill_lv); //WIP [lighta]
+
 	return md;
 }
 /*==========================================

+ 6 - 2
src/map/channel.c

@@ -70,11 +70,14 @@ struct Channel* channel_create(char *name, char *pass, unsigned char color, enum
  * return
  *  0 : success
  *  -1 : invalid channel
+ *  -2 : can't delete now
  */
 int channel_delete(struct Channel *channel) {
 	if(!channel)
 		return -1;
-	else if( db_size(channel->users)) {
+	if(channel->type == CHAN_TYPE_PUBLIC && runflag != MAPSERVER_ST_RUNNING) //only delete those serv stop
+		return -2;
+	if( db_size(channel->users)) {
 		struct map_session_data *sd;
 		DBIterator *iter = db_iterator(channel->users);
 		for( sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter) ) { //for all users
@@ -270,7 +273,8 @@ int channel_clean(struct Channel *channel, struct map_session_data *sd, int flag
 	}
 
 	idb_remove(channel->users,sd->status.char_id); //remove user for channel user list
-	if( !db_size(channel->users) && !(flag&1) && channel->type != CHAN_TYPE_PUBLIC )
+	//auto delete when no more user in
+	if( !db_size(channel->users) && !(flag&1) )
 		channel_delete(channel);
 
 	return 0;

+ 6 - 14
src/map/clif.c

@@ -5361,6 +5361,8 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id
 	nullpo_retv(sd);
 	fd = sd->fd;
 
+	if(sd->menuskill_id == skill_id)
+		return; //Avoid resending the menu twice or more times...
 	WFIFOHEAD(fd, 6 + 2 * MAX_SKILL_PRODUCE_DB);
 	WFIFOW(fd,0) = 0x25a;
 	WFIFOW(fd,4) = list_type; // list type
@@ -5378,30 +5380,20 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id
 		c++;
 	}
 
-	if( skill_id == AM_PHARMACY ) {	// Only send it while Cooking else check for c.
-		WFIFOW(fd,2) = 6 + 2 * c;
-		WFIFOSET(fd,WFIFOW(fd,2));
-	}
-
-	if( c > 0 ) {
+	if( c > 0 || skill_id == AM_PHARMACY) {
 		sd->menuskill_id = skill_id;
 		sd->menuskill_val = trigger;
-		if( skill_id != AM_PHARMACY ) {
-			sd->menuskill_val2 = qty; // amount.
-			WFIFOW(fd,2) = 6 + 2 * c;
-			WFIFOSET(fd,WFIFOW(fd,2));
-		}
+		sd->menuskill_val2 = qty; // amount.
+		WFIFOW(fd,2) = 6 + 2 * c;
+		WFIFOSET(fd,WFIFOW(fd,2));
 	} else {
 		clif_menuskill_clear(sd);
-		if( skill_id != AM_PHARMACY ) { // AM_PHARMACY is used to Cooking.
-			// It fails.
 #if PACKETVER >= 20090922
 			clif_msg_skill(sd,skill_id,0x625);
 #else
 			WFIFOW(fd,2) = 6 + 2 * c;
 			WFIFOSET(fd,WFIFOW(fd,2));
 #endif
-		}
 	}
 }
 

+ 2 - 0
src/map/homunculus.c

@@ -973,6 +973,8 @@ void merc_hom_revive(struct homun_data *hd, unsigned int hp, unsigned int sp)
 	clif_hominfo(sd,hd,1);
 	clif_hominfo(sd,hd,0);
 	clif_homskillinfoblock(sd);
+	if(hd->homunculus.class_ == 6052) //eleanor
+		sc_start(&hd->bl,&hd->bl, SC_STYLE_CHANGE, 100, MH_MD_FIGHTING, -1);
 }
 
 void merc_reset_stats(struct homun_data *hd)

+ 16 - 0
src/map/pc.c

@@ -5177,6 +5177,22 @@ int pc_checkequip(struct map_session_data *sd,int pos)
 	return -1;
 }
 
+/*==========================================
+ * Check if sd as nameid equiped somewhere
+ * -return true,false
+ *------------------------------------------*/
+int pc_checkequip2(struct map_session_data *sd,int nameid){
+	int i;
+	for(i=0;i<EQI_MAX;i++){
+		if(equip_pos[i]){
+			int idx = sd->equip_index[i];
+			if (sd->status.inventory[idx].nameid == nameid)
+				return true;
+		}
+	}
+	return false;
+}
+
 /*==========================================
  * Convert's from the client's lame Job ID system
  * to the map server's 'makes sense' system. [Skotlex]

+ 1 - 0
src/map/pc.h

@@ -771,6 +771,7 @@ int pc_setinventorydata(struct map_session_data *sd);
 int pc_checkskill(struct map_session_data *sd,uint16 skill_id);
 int pc_checkallowskill(struct map_session_data *sd);
 int pc_checkequip(struct map_session_data *sd,int pos);
+int pc_checkequip2(struct map_session_data *sd,int nameid);
 
 int pc_calc_skilltree(struct map_session_data *sd);
 int pc_calc_skilltree_normalize_job(struct map_session_data *sd);

+ 153 - 111
src/map/skill.c

@@ -1021,8 +1021,8 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
 		break;
 
 	case TF_THROWSTONE:
-		sc_start(src,bl,SC_STUN,3,skill_lv,skill_get_time(skill_id,skill_lv));
-		sc_start(src,bl,SC_BLIND,3,skill_lv,skill_get_time2(skill_id,skill_lv));
+		if (!sc_start(src,bl,SC_STUN,3,skill_lv,skill_get_time(skill_id,skill_lv))) //only blind if success
+			sc_start(src,bl,SC_BLIND,3,skill_lv,skill_get_time2(skill_id,skill_lv));
 		break;
 
 	case NPC_DARKCROSS:
@@ -1528,10 +1528,10 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
 				skill_break_equip(src,bl, EQP_ARMOR, rate, BCT_ENEMY);
 		}
 		if( sd && sd->def_set_race[tstatus->race].rate )
-				status_change_start(src,bl, SC_DEFSET, sd->def_set_race[tstatus->race].rate, sd->def_set_race[tstatus->race].value, 
+				status_change_start(src,bl, SC_DEFSET, sd->def_set_race[tstatus->race].rate, sd->def_set_race[tstatus->race].value,
 				0, 0, 0, sd->def_set_race[tstatus->race].tick, 2);
 		if( sd && sd->def_set_race[tstatus->race].rate )
-				status_change_start(src,bl, SC_MDEFSET, sd->mdef_set_race[tstatus->race].rate, sd->mdef_set_race[tstatus->race].value, 
+				status_change_start(src,bl, SC_MDEFSET, sd->mdef_set_race[tstatus->race].rate, sd->mdef_set_race[tstatus->race].value,
 				0, 0, 0, sd->mdef_set_race[tstatus->race].tick, 2);
 	}
 
@@ -1720,14 +1720,14 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1
 		if( skill_isNotOk((skill > 0) ? skill : skill*-1, sd) )
 			continue;
 
-		sd->state.autocast = 0;		
+		sd->state.autocast = 0;
 
 		if( skill >= 0 && bl == NULL )
 			continue; // No target
 		if( rnd()%1000 >= sd->autospell3[i].rate )
 			continue;
-		
-		skill_lv = sd->autospell3[i].lv ? sd->autospell3[i].lv : 1;	
+
+		skill_lv = sd->autospell3[i].lv ? sd->autospell3[i].lv : 1;
 		if( skill < 0 ) {
 			tbl = &sd->bl;
 			skill *= -1;
@@ -2358,6 +2358,92 @@ void skill_combo(struct block_list* src,struct block_list *dsrc, struct block_li
 	}
 }
 
+
+void skill_do_copy(struct block_list* src,struct block_list *bl, struct Damage *dmg, int64 damage, uint16 skill_id, uint16 skill_lv){
+	TBL_PC *tsd = BL_CAST(BL_PC,bl);
+	struct status_change *tsc = status_get_sc(bl);
+
+	//Check for copying skill
+	if (damage > 0 && dmg->flag&BF_SKILL && tsd
+		&& damage < tsd->battle_status.hp	//Updated to not be able to copy skills if the blow will kill you. [Skotlex]
+		&& (pc_checkskill(tsd, RG_PLAGIARISM) || pc_checkskill(tsd, SC_REPRODUCE)))
+	{
+		uint16 copy_skill = skill_id;
+		short copy_flag;
+
+		// Copy Referal: dummy skills should point to their source upon copying
+		switch (skill_id) {
+			case AB_DUPLELIGHT_MELEE:
+			case AB_DUPLELIGHT_MAGIC:
+				copy_skill = AB_DUPLELIGHT;
+				break;
+			case WL_CHAINLIGHTNING_ATK:
+				copy_skill = WL_CHAINLIGHTNING;
+				break;
+			case WM_REVERBERATION_MELEE:
+			case WM_REVERBERATION_MAGIC:
+				copy_skill = WM_REVERBERATION;
+				break;
+			case WM_SEVERE_RAINSTORM_MELEE:
+				copy_skill = WM_SEVERE_RAINSTORM;
+			break;
+			case GN_CRAZYWEED_ATK:
+				copy_skill = GN_CRAZYWEED;
+				break;
+			case GN_HELLS_PLANT_ATK:
+				copy_skill = GN_HELLS_PLANT;
+				break;
+			case LG_OVERBRAND_BRANDISH:
+			case LG_OVERBRAND_PLUSATK:
+				copy_skill = LG_OVERBRAND;
+				break;
+		}
+
+		if ((copy_flag = skill_isCopyable(tsd,copy_skill,bl))) {
+			int lv;
+			if (copy_flag == 2 && (lv = tsc->data[SC__REPRODUCE]->val1)) {
+				//Level dependent and limitation.
+				lv = min(lv,skill_get_max(copy_skill));
+				if( tsd->reproduceskill_id && tsd->status.skill[tsd->reproduceskill_id].flag == SKILL_FLAG_PLAGIARIZED ) {
+					tsd->status.skill[tsd->reproduceskill_id].id = 0;
+					tsd->status.skill[tsd->reproduceskill_id].lv = 0;
+					tsd->status.skill[tsd->reproduceskill_id].flag = SKILL_FLAG_PERMANENT;
+					clif_deleteskill(tsd,tsd->reproduceskill_id);
+				}
+
+				tsd->reproduceskill_id = copy_skill;
+				pc_setglobalreg(tsd,SKILL_VAR_REPRODUCE,copy_skill);
+				pc_setglobalreg(tsd,SKILL_VAR_REPRODUCE_LV,lv);
+
+				tsd->status.skill[copy_skill].id = copy_skill;
+				tsd->status.skill[copy_skill].lv = lv;
+				tsd->status.skill[copy_skill].flag = SKILL_FLAG_PLAGIARIZED;
+				clif_addskill(tsd,copy_skill);
+			} else if (copy_flag == 1) {
+				int type;
+				lv = skill_lv;
+				if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED) {
+					tsd->status.skill[tsd->cloneskill_id].id = 0;
+					tsd->status.skill[tsd->cloneskill_id].lv = 0;
+					tsd->status.skill[tsd->cloneskill_id].flag = SKILL_FLAG_PERMANENT;
+					clif_deleteskill(tsd,tsd->cloneskill_id);
+				}
+
+				if ((type = pc_checkskill(tsd,RG_PLAGIARISM)) < lv)
+					lv = type;
+
+				tsd->cloneskill_id = copy_skill;
+				pc_setglobalreg(tsd,SKILL_VAR_PLAGIARISM,copy_skill);
+				pc_setglobalreg(tsd,SKILL_VAR_PLAGIARISM_LV,lv);
+
+				tsd->status.skill[skill_id].id = copy_skill;
+				tsd->status.skill[skill_id].lv = lv;
+				tsd->status.skill[skill_id].flag = SKILL_FLAG_PLAGIARIZED;
+				clif_addskill(tsd,skill_id);
+			}
+		}
+	}
+}
 /*
  * =========================================================================
  * Does a skill attack with the given properties.
@@ -2381,14 +2467,13 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 	int64 damage;
 	int8 rmdamage=0;//magic reflected
 	int type;
-	int idx;
 	bool additional_effects = true;
 
 	if(skill_id > 0 && !skill_lv) return 0;
 
 	nullpo_ret(src);	//Source is the master behind the attack (player/mob/pet)
-	nullpo_ret(dsrc); //dsrc is the actual originator of the damage, can be the same as src, or a skill casted by src.
-	nullpo_ret(bl); //Target to be attacked.
+	nullpo_ret(dsrc);	//dsrc is the actual originator of the damage, can be the same as src, or a skill casted by src.
+	nullpo_ret(bl);		//Target to be attacked.
 
 	if (src != dsrc) {
 		//When caster is not the src of attack, this is a ground skill, and as such, do the relevant target checking. [Skotlex]
@@ -2672,86 +2757,8 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 
 	map_freeblock_lock();
 
-	idx = skill_get_index(skill_id);
-	//Check for copying skill
-	if (damage > 0 && dmg.flag&BF_SKILL && tsd
-		&& damage < tsd->battle_status.hp	//Updated to not be able to copy skills if the blow will kill you. [Skotlex]
-		&& (pc_checkskill(tsd, RG_PLAGIARISM) || pc_checkskill(tsd, SC_REPRODUCE)))
-	{
-		uint16 copy_skill = skill_id;
-		short copy_flag;
-
-		// Copy Referal: dummy skills should point to their source upon copying
-		switch (skill_id) {
-			case AB_DUPLELIGHT_MELEE:
-			case AB_DUPLELIGHT_MAGIC:
-				copy_skill = AB_DUPLELIGHT;
-				break;
-			case WL_CHAINLIGHTNING_ATK:
-				copy_skill = WL_CHAINLIGHTNING;
-				break;
-			case WM_REVERBERATION_MELEE:
-			case WM_REVERBERATION_MAGIC:
-				copy_skill = WM_REVERBERATION;
-				break;
-			case WM_SEVERE_RAINSTORM_MELEE:
-				copy_skill = WM_SEVERE_RAINSTORM;
-			break;
-			case GN_CRAZYWEED_ATK:
-				copy_skill = GN_CRAZYWEED;
-				break;
-			case GN_HELLS_PLANT_ATK:
-				copy_skill = GN_HELLS_PLANT;
-				break;
-			case LG_OVERBRAND_BRANDISH:
-			case LG_OVERBRAND_PLUSATK:
-				copy_skill = LG_OVERBRAND;
-				break;
-		}
-
-		if ((copy_flag = skill_isCopyable(tsd,copy_skill,bl))) {
-			int lv;
-			if (copy_flag == 2 && (lv = tsc->data[SC__REPRODUCE]->val1)) {
-				//Level dependent and limitation.
-				lv = min(lv,skill_get_max(copy_skill));
-				if( tsd->reproduceskill_id && tsd->status.skill[tsd->reproduceskill_id].flag == SKILL_FLAG_PLAGIARIZED ) {
-					tsd->status.skill[tsd->reproduceskill_id].id = 0;
-					tsd->status.skill[tsd->reproduceskill_id].lv = 0;
-					tsd->status.skill[tsd->reproduceskill_id].flag = SKILL_FLAG_PERMANENT;
-					clif_deleteskill(tsd,tsd->reproduceskill_id);
-				}
-
-				tsd->reproduceskill_id = copy_skill;
-				pc_setglobalreg(tsd,SKILL_VAR_REPRODUCE,copy_skill);
-				pc_setglobalreg(tsd,SKILL_VAR_REPRODUCE_LV,lv);
-
-				tsd->status.skill[copy_skill].id = copy_skill;
-				tsd->status.skill[copy_skill].lv = lv;
-				tsd->status.skill[copy_skill].flag = SKILL_FLAG_PLAGIARIZED;
-				clif_addskill(tsd,copy_skill);
-			} else if (copy_flag == 1) {
-				lv = skill_lv;
-				if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED) {
-					tsd->status.skill[tsd->cloneskill_id].id = 0;
-					tsd->status.skill[tsd->cloneskill_id].lv = 0;
-					tsd->status.skill[tsd->cloneskill_id].flag = SKILL_FLAG_PERMANENT;
-					clif_deleteskill(tsd,tsd->cloneskill_id);
-				}
-
-				if ((type = pc_checkskill(tsd,RG_PLAGIARISM)) < lv)
-					lv = type;
-
-				tsd->cloneskill_id = copy_skill;
-				pc_setglobalreg(tsd,SKILL_VAR_PLAGIARISM,copy_skill);
-				pc_setglobalreg(tsd,SKILL_VAR_PLAGIARISM_LV,lv);
+	skill_do_copy(src,bl,&dmg,damage,skill_id,skill_lv); //try to copy a skill
 
-				tsd->status.skill[skill_id].id = copy_skill;
-				tsd->status.skill[skill_id].lv = lv;
-				tsd->status.skill[skill_id].flag = SKILL_FLAG_PLAGIARIZED;
-				clif_addskill(tsd,skill_id);
-			}
-		}
-	}
 
 	if (dmg.dmg_lv >= ATK_MISS && (type = skill_get_walkdelay(skill_id, skill_lv)) > 0)
 	{	//Skills with can't walk delay also stop normal attacking for that
@@ -5551,11 +5558,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		if (sd) {
 			int bonus = 25 + 10 * skill_lv;
 			bonus += (pc_checkskill(sd, SA_FLAMELAUNCHER)+pc_checkskill(sd, SA_FROSTWEAPON)+pc_checkskill(sd, SA_LIGHTNINGLOADER)+pc_checkskill(sd, SA_SEISMICWEAPON))*5;
+
 			clif_skill_nodamage( src, bl, skill_id, skill_lv,
-								battle_check_target(src,bl,BCT_PARTY) ?
-								sc_start2(src,bl, type, 100, skill_lv, bonus, skill_get_time(skill_id,skill_lv)) :
-								0
-				);
+				battle_check_target(src,bl,BCT_PARTY|BCT_SELF)>0 ? //only on self or party member
+				sc_start2(src,bl, type, 100, skill_lv, bonus, skill_get_time(skill_id,skill_lv)) :
+				0
+			);
 		}
 		break;
 
@@ -9360,19 +9368,21 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		    skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
 		}
 		break;
-	case MH_STYLE_CHANGE: {
-	    struct status_change_entry *sce;
-	    if(hd && (sce=hd->sc.data[SC_STYLE_CHANGE])){ //in preparation for other bl usage
-		if(sce->val1 == MH_MD_FIGHTING) sce->val1 = MH_MD_GRAPPLING;
-		else sce->val1 = MH_MD_FIGHTING;
-		if(hd->master && hd->sc.data[SC_STYLE_CHANGE]) {
-		    char output[128];
-		    safesnprintf(output,sizeof(output),msg_txt(sd,378),(sce->val1==MH_MD_FIGHTING?"fighthing":"grappling"));
-		    clif_colormes(hd->master,color_table[COLOR_RED],output);
+	case MH_STYLE_CHANGE:
+		if(hd){
+			struct status_change_entry *sce;
+			if((sce=hd->sc.data[SC_STYLE_CHANGE])!=NULL){ //in preparation for other bl usage
+				if(sce->val1 == MH_MD_FIGHTING) sce->val1 = MH_MD_GRAPPLING;
+				else sce->val1 = MH_MD_FIGHTING;
+				if(hd->master && hd->sc.data[SC_STYLE_CHANGE]) {
+					char output[128];
+					safesnprintf(output,sizeof(output),msg_txt(sd,378),(sce->val1==MH_MD_FIGHTING?"fighthing":"grappling"));
+					clif_colormes(hd->master,color_table[COLOR_RED],output);
+				}
+			}
+			else sc_start(&hd->bl,&hd->bl, SC_STYLE_CHANGE, 100, MH_MD_FIGHTING, -1);
 		}
-	    }
-	    break;
-	}
+		break;
 	case MH_MAGMA_FLOW:
 	case MH_PAIN_KILLER:
 	   sc_start(src,bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
@@ -10523,7 +10533,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
 	case SC_FEINTBOMB:
 		clif_skill_nodamage(src,src,skill_id,skill_lv,1);
 		skill_unitsetting(src,skill_id,skill_lv,x,y,0); // Set bomb on current Position
-		if( skill_blown(src,src,6,unit_getdir(src),0) )
+		if( skill_blown(src,src,3*skill_lv,unit_getdir(src),0) )
 			skill_castend_nodamage_id(src,src,TF_HIDING,1,tick,0);
 		break;
 
@@ -10681,8 +10691,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
 		(sd->sc.data[SC_STASIS] && skill_block_check(&sd->bl, SC_STASIS, skill_id)) ||
 		(sd->sc.data[SC_KAGEHUMI] && skill_block_check(&sd->bl, SC_KAGEHUMI, skill_id)) ||
 		sd->sc.data[SC_OBLIVIONCURSE] ||
-		sd->sc.data[SC__MANHOLE] ||
-		(sd->sc.data[SC_ASH] && rnd()%2) //50% fail chance under ASH
+		sd->sc.data[SC__MANHOLE]
 	 )) {
 		skill_failed(sd);
 		return 0;
@@ -11411,8 +11420,11 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
 
 	sc = status_get_sc(bl);
 
-	if (sc && sc->option&OPTION_HIDE && sg->skill_id != WZ_HEAVENDRIVE && sg->skill_id != WL_EARTHSTRAIN )
+	if (sc && (sc->data[SC_HOVERING]
+		|| (sc->option&OPTION_HIDE && sg->skill_id != WZ_HEAVENDRIVE && sg->skill_id != WL_EARTHSTRAIN )
+		))
 		return 0; //Hidden characters are immune to AoE skills except to these. [Skotlex]
+			//Under hovering characters are immune to trap and ground target skills.
 
 	type = status_skill2sc(sg->skill_id);
 	sce = (sc && type != -1)?sc->data[type]:NULL;
@@ -13581,6 +13593,19 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
 		}
 	}
 
+	//check if equiped item
+	for (i = 0; i < 10; i++) {
+		int reqeqit = require.eqItem[i];
+		if(!reqeqit) break; //no more required item get out of here
+		if (!pc_checkequip2(sd,reqeqit)) {
+			char output[128];
+			//clif_skill_fail(sd, skill_id, USESKILL_FAIL_NEED_EQUIPMENT, reqeqit);
+			sprintf(output,"need to put on [%d] in order to use.",reqeqit);
+			clif_colormes(sd,color_table[COLOR_RED],output);
+			return 0;
+		}
+	}
+
 	if(require.mhp > 0 && get_percentage(status->hp, status->max_hp) > require.mhp) {
 		//mhp is the max-hp-requirement, that is,
 		//you must have this % or less of HP to cast it.
@@ -13940,6 +13965,8 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
 	req.status_count = skill_db[idx].require.status_count;
 	memset(req.status,SC_NONE,sizeof(req.status));
 	memcpy(req.status,skill_db[idx].require.status,sizeof(skill_db[idx].require.status));
+	memset(req.eqItem,0,sizeof(req.eqItem));
+	memcpy(req.eqItem,skill_db[idx].require.eqItem,sizeof(skill_db[idx].require.eqItem));
 
 	for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++ ) {
 		if( (skill_id == AM_POTIONPITCHER || skill_id == CR_SLIMPITCHER || skill_id == CR_CULTIVATION) && i != skill_lv%11 - 1 )
@@ -18054,11 +18081,12 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current)
 	else skill_db[idx].require.state = ST_NONE;	// Unknown or no state
 
 	//Status requirements
+	memset(skill_db[idx].require.status,SC_NONE,sizeof(skill_db[idx].require.status));
 	skill_db[idx].require.status_count = 0;
 	p = strtok(split[11],":");
 	for( i = 0; i < MAX_SKILL_STATUS_REQUIRE && p != NULL; i++ ) {
 		int status = SC_NONE;
-		script_get_constant(trim(p), &status);		
+		script_get_constant(trim(p), &status);
 		if (status > SC_NONE) {
 			skill_db[idx].require.status[skill_db[idx].require.status_count] = (enum sc_type)status;
 			skill_db[idx].require.status_count++;
@@ -18073,6 +18101,20 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current)
 		skill_db[idx].require.amount[i] = atoi(split[14+ 2*i]);
 	}
 
+	//require equiped
+	memset(skill_db[idx].require.eqItem,0,sizeof(skill_db[idx].require.eqItem));
+	p = strtok(split[33],":");
+	for( i = 0; i < 10 && p != NULL; i++ ) {
+		int itid = atoi(p);
+		p = strtok(NULL,":"); //for easy continue don,t read p after this
+		if(itid <= 0) continue; //silent
+		if(itemdb_exists(itid)== NULL) {
+			ShowWarning("Invalid reqIt=%d specified for skillid=%d\n",itid,skill_id);
+			continue; //invalid id
+		}
+		skill_db[idx].require.eqItem[i] = itid;
+	}
+
 	return true;
 }
 
@@ -18414,7 +18456,7 @@ static void skill_readdb(void)
 	safestrncpy(skill_db[0].desc, "Unknown Skill", sizeof(skill_db[0].desc));
 
 	sv_readdb(db_path, DBPATH"skill_db.txt"          , ',',  18, 18, MAX_SKILL_DB, skill_parse_row_skilldb);
-	sv_readdb(db_path, DBPATH"skill_require_db.txt"  , ',',  33, 33, MAX_SKILL_DB, skill_parse_row_requiredb);
+	sv_readdb(db_path, DBPATH"skill_require_db.txt"  , ',',  34, 34, MAX_SKILL_DB, skill_parse_row_requiredb);
 #ifdef RENEWAL_CAST
 	sv_readdb(db_path, "re/skill_cast_db.txt"        , ',',   8,  8, MAX_SKILL_DB, skill_parse_row_castdb);
 #else

+ 4 - 2
src/map/skill.h

@@ -118,7 +118,8 @@ struct skill_condition {
 		state,
 		spiritball,
 		itemid[MAX_SKILL_ITEM_REQUIRE],
-		amount[MAX_SKILL_ITEM_REQUIRE];
+		amount[MAX_SKILL_ITEM_REQUIRE],
+		eqItem[10]; //max eq_item
 	uint8 status_count;
 	enum sc_type status[MAX_SKILL_STATUS_REQUIRE];
 };
@@ -136,7 +137,8 @@ struct s_skill_require {
 		state,
 		spiritball[MAX_SKILL_LEVEL],
 		itemid[MAX_SKILL_ITEM_REQUIRE],
-		amount[MAX_SKILL_ITEM_REQUIRE];
+		amount[MAX_SKILL_ITEM_REQUIRE],
+		eqItem[10]; //max eq_item
 	uint8 status_count;
 	enum sc_type status[MAX_SKILL_STATUS_REQUIRE];
 };

+ 41 - 28
src/map/status.c

@@ -1592,6 +1592,10 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
 	if ( src ) sc = status_get_sc(src);
 
 	if( sc && sc->count ) {
+		if((sc->data[SC_ASH] && rnd()%2)){
+			if(src->type==BL_PC) clif_skill_fail((TBL_PC*)src,skill_id,0,0);
+			return 0;
+		}
 
 		if (skill_id != RK_REFRESH && sc->opt1 >0 && !(sc->opt1 == OPT1_CRYSTALIZE && src->type == BL_MOB) && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { //Stuned/Frozen/etc
 			if (flag != 1) //Can't cast, casted stuff can't damage.
@@ -1779,9 +1783,9 @@ int status_check_visibility(struct block_list *src, struct block_list *target)
 	switch (target->type)
 	{	//Check for chase-walk/hiding/cloaking opponents.
 	case BL_PC:
-		if ( tsc->data[SC_CLOAKINGEXCEED] && !(status->mode&MD_BOSS) )
+		if ( tsc && tsc->data[SC_CLOAKINGEXCEED] && !(status->mode&MD_BOSS) )
 			return 0;
-		if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(status->mode&MD_BOSS) &&
+		if( ( tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE])) && !(status->mode&MD_BOSS) &&
 			( ((TBL_PC*)target)->special_state.perfect_hiding || !(status->mode&MD_DETECTOR) ) )
 			return 0;
 		break;
@@ -2745,7 +2749,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 #else
 	status->watk = status_weapon_atk(status->rhw, status);
 	status->watk2 = status_weapon_atk(status->lhw, status);
-	status->eatk = (sd->bonus.eatk >= 0) ? sd->bonus.eatk : 0;
+	status->eatk = max(sd->bonus.eatk,0);
 #endif
 
 // ----- HP MAX CALCULATION -----
@@ -3565,6 +3569,7 @@ void status_calc_state( struct block_list *bl, struct status_change *sc, enum sc
 	if( flag&SCS_NOMOVE ) {
 		if( !(flag&SCS_NOMOVECOND) ) {
 			sc->cant.move += ( start ? 1 : -1 );
+			sc->cant.move = max(sc->cant.move,0); //safecheck
 		} else if(
 				     (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF)	// cannot move while gospel is in effect
 				  || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move
@@ -4798,7 +4803,7 @@ static signed short status_calc_critical(struct block_list *bl, struct status_ch
 	if(sc->data[SC_CLOAKING])
 		critical += critical;
 	if(sc->data[SC_STRIKING])
-		critical += sc->data[SC_STRIKING]->val1;
+		critical += sc->data[SC_STRIKING]->val1*10;
 #ifdef RENEWAL
 	if (sc->data[SC_SPEARQUICKEN])
 		critical += 3*sc->data[SC_SPEARQUICKEN]->val1*10;
@@ -7031,10 +7036,12 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		status_change_end(bl, SC_CONCENTRATE, INVALID_TIMER);
 		status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER);
 		status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
+		status_change_end(bl, SC_MAGNETICFIELD, INVALID_TIMER);
 		//Also blocks the ones below...
 	case SC_DECREASEAGI:
 	case SC_ADORAMUS:
 		status_change_end(bl, SC_CARTBOOST, INVALID_TIMER);
+		status_change_end(bl, SC_GN_CARTBOOST, INVALID_TIMER);
 		//Also blocks the ones below...
 	case SC_DONTFORGETME:
 		status_change_end(bl, SC_INCREASEAGI, INVALID_TIMER);
@@ -7097,6 +7104,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 	case SC_KAITE:
 		status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
 		break;
+	case SC_GN_CARTBOOST:
 	case SC_CARTBOOST:
 		if(sc->data[SC_DECREASEAGI] || sc->data[SC_ADORAMUS])
 		{	//Cancel Decrease Agi, but take no further effect [Skotlex]
@@ -7235,6 +7243,11 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		if( type != SC_GT_CHANGE )
 			status_change_end(bl, SC_GT_CHANGE, INVALID_TIMER);
 		break;
+	case SC_WARMER:
+		status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER);
+		status_change_end(bl, SC_FREEZING, INVALID_TIMER);
+		status_change_end(bl, SC_FREEZE, INVALID_TIMER);
+		break;
 	case SC_INVINCIBLE:
 		status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER);
 		break;
@@ -7244,6 +7257,15 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 	case SC_MAGICPOWER:
 		status_change_end(bl, type, INVALID_TIMER);
 		break;
+	case SC_WHITEIMPRISON:
+		status_change_end(bl, SC_BURNING, INVALID_TIMER);
+		status_change_end(bl, SC_FREEZING, INVALID_TIMER);
+		status_change_end(bl, SC_FREEZE, INVALID_TIMER);
+		status_change_end(bl, SC_STONE, INVALID_TIMER);
+		break;
+	case SC_FREEZING:
+		status_change_end(bl, SC_BURNING, INVALID_TIMER);
+		break;
 	}
 
 	//Check for overlapping fails
@@ -8309,15 +8331,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			val3 = 10 * val1; // Evasion rate of magical attacks.
 			val_flag |= 1|2|4;
 			break;
-		case SC_WHITEIMPRISON:
-			status_change_end(bl, SC_BURNING, INVALID_TIMER);
-			status_change_end(bl, SC_FREEZING, INVALID_TIMER);
-			status_change_end(bl, SC_FREEZE, INVALID_TIMER);
-			status_change_end(bl, SC_STONE, INVALID_TIMER);
-			break;
-		case SC_FREEZING:
-			status_change_end(bl, SC_BURNING, INVALID_TIMER);
-			break;
 		case SC_READING_SB:
 			// val2 = sp reduction per second
 			tick_time = 5000; // [GodLesZ] tick time
@@ -8429,13 +8442,9 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			val_flag |= 1|2;
 			val3 = 0;
 			break;
-		case SC_WARMER:
-			status_change_end(bl, SC_FREEZE, INVALID_TIMER);
-			status_change_end(bl, SC_FREEZING, INVALID_TIMER);
-			status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER);
-			break;
 		case SC_STRIKING:
-			val1 = 6 - val1;//spcost = 6 - level (lvl1:5 ... lvl 5: 1)
+			//val2 = watk bonus already calc
+			val3 = 6 - val1;//spcost = 6 - level (lvl1:5 ... lvl 5: 1)
 			val4 = tick / 1000;
 			tick_time = 1000; // [GodLesZ] tick time
 			break;
@@ -9106,6 +9115,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 	if(sd && sd->pd)
 		pet_sc_check(sd, type); //Skotlex: Pet Status Effect Healing
 
+	 //1st thing to execute when loading status
     switch (type) {
 		case SC_BERSERK:
 			if (!(sce->val2)) { //don't heal if already set
@@ -9197,7 +9207,7 @@ int status_change_clear(struct block_list* bl, int type) {
 			continue;
 
 		if(type == 0)
-		switch (i) {	//Type 0: PC killed -> Place here statuses that do not dispel on death.
+			switch (i) {	//Type 0: PC killed -> Place here statuses that do not dispel on death.
 			case SC_ELEMENTALCHANGE://Only when its Holy or Dark that it doesn't dispell on death
 				if( sc->data[i]->val2 != ELE_HOLY && sc->data[i]->val2 != ELE_DARK )
 					break;
@@ -9246,16 +9256,18 @@ int status_change_clear(struct block_list* bl, int type) {
 			case SC_S_LIFEPOTION:
 			case SC_L_LIFEPOTION:
 			case SC_PUSH_CART:
+			case SC_STYLE_CHANGE:
 				continue;
 		}
 
 		if( type == 3 ) {
 			switch (i) {// TODO: This list may be incomplete
-				case SC_WEIGHT50:
-				case SC_WEIGHT90:
-				case SC_NOCHAT:
-				case SC_PUSH_CART:
-					continue;
+			case SC_WEIGHT50:
+			case SC_WEIGHT90:
+			case SC_NOCHAT:
+			case SC_PUSH_CART:
+			case SC_STYLE_CHANGE:
+				continue;
 			}
 		}
 
@@ -9756,7 +9768,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 			}
 			break;
 		case SC_VACUUM_EXTREME:
-			if(sc && sc->cant.move > 0) sc->cant.move--;
+			if(sc && sce->val2 && sc->cant.move > 0) sc->cant.move--;
 			break;
 		case SC_KYOUGAKU:
 			clif_status_load(bl, SI_KYOUGAKU, 0); // Avoid client crash
@@ -10522,7 +10534,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_ELECTRICSHOCKER:
 		if( --(sce->val4) >= 0 )
 		{
-			status_charge(bl, 0, status->max_sp / 100 * sce->val1 );
+			status_charge(bl, 0, status->max_sp / 100 * sce->val1 * 5 );
 			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
 			return 0;
 		}
@@ -10565,7 +10577,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_STRIKING:
 		if( --(sce->val4) >= 0 )
 		{
-			if( !status_charge(bl,0, sce->val1 ) )
+			if( !status_charge(bl,0, sce->val3 ) )
 				break;
 			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
 			return 0;
@@ -10975,6 +10987,7 @@ int status_change_clear_buffs (struct block_list* bl, int type)
 			case SC_CURSEDCIRCLE_ATKER:
 			case SC_CURSEDCIRCLE_TARGET:
 			case SC_PUSH_CART:
+			case SC_STYLE_CHANGE:
 				continue;
 
 		 //Debuffs that can be removed.

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác