瀏覽代碼

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 年之前
父節點
當前提交
c70762a18f
共有 10 個文件被更改,包括 1185 次插入1080 次删除
  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

File diff suppressed because it is too large
+ 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.

Some files were not shown because too many files changed in this diff