Explorar el Código

Updated most Ranger skills to its official behavior and damage formula.(bugreport:5272, bugreport:6249, bugreport:5548, bugreport:5888)
Fixed issues with traps: (bugreport:5906)
- if RA_REASERCHTRAP is learned Alloy Traps can now be used to Hunter traps.
- if Hunter traps expire it will now return either Booby Trap or Alloy Trap depending on item used.
- some traps should now give full damage to plants.
- update list of skills that can hit/damage/affect traps.
- damage through skills can now be shown when hitting traps.
- proper knock back behaviors
- proper animation when triggers and triggering of item bonus script 'bHPDrainRate'
Fixed an issues where some skills cannot damage UNT_REVERBERATION/UNT_POEMOFNETHERWORLD and doesn't deal 1 damage
Updated some official behavior where informational must shown when hitting, targeting, casting skills to targets.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16483 54d463be-8e91-2dee-dedb-b68131a5f0ec

rud0lp20 hace 13 años
padre
commit
041d671412
Se han modificado 8 ficheros con 269 adiciones y 137 borrados
  1. 3 1
      db/pre-re/skill_require_db.txt
  2. 3 1
      db/re/skill_require_db.txt
  3. 96 25
      src/map/battle.c
  4. 2 1
      src/map/pc.c
  5. 140 87
      src/map/skill.c
  6. 1 0
      src/map/skill.h
  7. 18 15
      src/map/status.c
  8. 6 7
      src/map/unit.c

+ 3 - 1
db/pre-re/skill_require_db.txt

@@ -19,6 +19,8 @@
 //  explosionspirits = Requires Fury skill activated
 //  cartboost = Requires a Pushcart and Cart Boost skill activated
 //  shield = Requires a 0,shield equipped
+//  warg = Requires a Warg
+//  ridingwarg = Requires to ride a Warg
 
 5,0,0,8:8:8:8:8:15:15:15:15:15,0,0,0,0:1:2:3:4:5:6:7:8:9:10:12:13:14:15:16:17:18:19:20:21:22,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//SM_BASH#ƒoƒbƒVƒ…#
 6,0,0,4:5:6:7:8:9:10:11:12:13,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//SM_PROVOKE#ƒvƒ�ƒ{ƒbƒN#
@@ -569,7 +571,7 @@
 2240,0,0,5,0,0,0,99,0,0,none,0,6124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//RA_WUGMASTERY#Warg Mastery#
 2241,0,0,20,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0		//RA_WUGRIDER#Warg Rider#
 2242,0,0,40,0,0,0,99,0,0,move_enable,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//RA_WUGDASH#Warg Dash#
-2243,0,0,20:22:24:26:28,0,0,0,99,0,0,warg,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//RA_WUGSTRIKE#Warg Strike#
+2243,0,0,20:22:24:26:28,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//RA_WUGSTRIKE#Warg Strike#
 2244,0,0,42:44:46:48:50,0,0,0,99,0,0,warg,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//RA_WUGBITE#Warg Bite#
 
 2246,0,0,12,0,0,0,99,0,0,warg,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//RA_SENSITIVEKEEN#Sensitive Keen#

+ 3 - 1
db/re/skill_require_db.txt

@@ -19,6 +19,8 @@
 //  explosionspirits = Requires Fury skill activated
 //  cartboost = Requires a Pushcart and Cart Boost skill activated
 //  shield = Requires a 0,shield equipped
+//  warg = Requires a Warg
+//  ridingwarg = Requires to ride a Warg
 
 5,0,0,8:8:8:8:8:15:15:15:15:15,0,0,0,0:1:2:3:4:5:6:7:8:9:10:12:13:14:15:16:17:18:19:20:21:22,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//SM_BASH#ƒoƒbƒVƒ…#
 6,0,0,4:5:6:7:8:9:10:11:12:13,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//SM_PROVOKE#ƒvƒ�ƒ{ƒbƒN#
@@ -569,7 +571,7 @@
 2240,0,0,5,0,0,0,99,0,0,none,0,6124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//RA_WUGMASTERY#Warg Mastery#
 2241,0,0,20,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0		//RA_WUGRIDER#Warg Rider#
 2242,0,0,40,0,0,0,99,0,0,move_enable,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//RA_WUGDASH#Warg Dash#
-2243,0,0,20:22:24:26:28,0,0,0,99,0,0,warg,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//RA_WUGSTRIKE#Warg Strike#
+2243,0,0,20:22:24:26:28,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//RA_WUGSTRIKE#Warg Strike#
 2244,0,0,42:44:46:48:50,0,0,0,99,0,0,warg,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//RA_WUGBITE#Warg Bite#
 
 2246,0,0,12,0,0,0,99,0,0,warg,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//RA_SENSITIVEKEEN#Sensitive Keen#

+ 96 - 25
src/map/battle.c

@@ -1275,10 +1275,14 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 	//Initial flag
 	flag.rh=1;
 	flag.weapon=1;
-	flag.infdef=(tstatus->mode&MD_PLANT&&skill_num!=RA_CLUSTERBOMB?1:0);
+	flag.infdef=(tstatus->mode&MD_PLANT && skill_num != RA_CLUSTERBOMB 
+#ifdef RENEWAL
+		&& skill_num != HT_FREEZINGTRAP
+#endif
+		?1:0);
 	if( target->type == BL_SKILL){
 		TBL_SKILL *su = (TBL_SKILL*)target;
-		if( su->group && su->group->skill_id == WM_REVERBERATION)
+		if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
 			flag.infdef = 1;
 	}
 
@@ -1466,6 +1470,8 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 			if(flag.arrow)
 				cri += sd->bonus.arrow_cri;
 		}
+		if( sc && sc->data[SC_CAMOUFLAGE] )
+			cri += 10 * (10-sc->data[SC_CAMOUFLAGE]->val4);
 		//The official equation is *2, but that only applies when sd's do critical.
 		//Therefore, we use the old value 3 on cases when an sd gets attacked by a mob
 		cri -= tstatus->luk*(!sd&&tsd?3:2);
@@ -1782,10 +1788,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 				case MA_CHARGEARROW:
 					skillratio += 50;
 					break;
+#ifndef RENEWAL
 				case HT_FREEZINGTRAP:
 				case MA_FREEZINGTRAP:
 					skillratio += -50+10*skill_lv;
 					break;
+#endif
 				case KN_PIERCE:
 				case ML_PIERCE:
 					skillratio += 10*skill_lv;
@@ -2162,13 +2170,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 					skillratio += 400 + 50 * skill_lv;
 					RE_LVL_DMOD(100);
 					if( tsc && (tsc->data[SC_BITE] || tsc->data[SC_ANKLE] || tsc->data[SC_ELECTRICSHOCKER]) )
-						wd.div_ = tstatus->size + 2 + rnd()%2;
+						wd.div_ = tstatus->size + 2 + ( (rnd()%100 < 50-tstatus->size*10) ? 1 : 0 );
 					break;
 				case RA_CLUSTERBOMB:
 					skillratio += 100 + 100 * skill_lv;
 					break;
-				case RA_WUGDASH:
-					skillratio = 500;
+				case RA_WUGDASH:// ATK 300%
+					skillratio += 200;
 					break;
 				case RA_WUGSTRIKE:
 					skillratio = 200 * skill_lv;
@@ -2495,7 +2503,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 				case NJ_SYURIKEN:
 					ATK_ADD(4*skill_lv);
 					break;
-				case RA_WUGDASH:
+				case HT_FREEZINGTRAP:
+					if(sd) 
+						ATK_ADD( 40 * pc_checkskill(sd, RA_RESEARCHTRAP) );
+					break;
+				case RA_WUGDASH://(Caster’s Current Weight x 10 / 8)
+					if( sd && sd->weight )
+						ATK_ADD( sd->weight / 8 );
 				case RA_WUGSTRIKE:
 				case RA_WUGBITE:
 					if(sd)
@@ -2659,6 +2673,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 			if( tsc && tsc->data[SC_GT_REVITALIZE] && tsc->data[SC_GT_REVITALIZE]->val4 )
 				def2 += 2 * tsc->data[SC_GT_REVITALIZE]->val4;
 
+			if( tsc && tsc->data[SC_CAMOUFLAGE] ){
+				i = 5 * (10-tsc->data[SC_CAMOUFLAGE]->val4);
+				def1 -= def1 * i / 100;
+				def2 -= def2 * i / 100;
+			}
+			
 			if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) {
 				unsigned char target_count; //256 max targets should be a sane max
 				target_count = unit_counttargeted(target);
@@ -2744,6 +2764,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 				if( (bl = map_id2bl(sc->data[SC_GT_CHANGE]->val2)) )
 					ATK_ADD( ( status_get_dex(bl)/4 + status_get_str(bl)/2 ) * sc->data[SC_GT_CHANGE]->val1 / 5 );
 			}
+
+			if(sc->data[SC_CAMOUFLAGE])
+				ATK_ADD(30 * (10-sc->data[SC_CAMOUFLAGE]->val4) );
 		}
 
 		//Refine bonus
@@ -3275,7 +3298,12 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 	//Skill Range Criteria
 	ad.flag |= battle_range_type(src, target, skill_num, skill_lv);
 	flag.infdef=(tstatus->mode&MD_PLANT?1:0);
-		
+	if( target->type == BL_SKILL){
+		TBL_SKILL *su = (TBL_SKILL*)target;
+		if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
+			flag.infdef = 1;
+	}
+
 	switch(skill_num)
 	{
 		case MG_FIREWALL:
@@ -3960,12 +3988,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 	case MA_LANDMINE:
 	case HT_BLASTMINE:
 	case HT_CLAYMORETRAP:
-		{
-			int level = sd?sd->status.base_level:status_get_lv(src);
-			md.damage = skill_lv*sstatus->dex*(3+level/100)*(1+sstatus->int_/35);
-			md.damage+= md.damage*(rnd()%20-10)/100;
-			md.damage+= 40*(sd?pc_checkskill(sd,RA_RESEARCHTRAP):0);
-		}
+		md.damage = skill_lv * sstatus->dex * (3+status_get_lv(src)/100) * (1+sstatus->int_/35);
+		md.damage += md.damage * (rnd()%20-10) / 100;
+		md.damage += 40 * (sd?pc_checkskill(sd,RA_RESEARCHTRAP):0);
 		break;
 #else
 	case HT_LANDMINE:
@@ -4071,10 +4096,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 	case RA_CLUSTERBOMB:
 	case RA_FIRINGTRAP:
  	case RA_ICEBOUNDTRAP:
-		md.damage = (2 * skill_lv * (sstatus->dex + 100));
-		md.damage = md.damage * 2;// Without BaseLv Bonus
+		md.damage = skill_lv * sstatus->dex + sstatus->int_ * 5 ;
 		RE_LVL_TMDMOD();
-		md.damage = md.damage + (5 * sstatus->int_) + (40 * ( sd ? pc_checkskill(sd,RA_RESEARCHTRAP) : 10 ) );
+		md.damage = md.damage * (20 * ( sd ? pc_checkskill(sd,RA_RESEARCHTRAP) : 10 ) );
+		md.damage = (md.damage?md.damage:1) / (skill_num == RA_CLUSTERBOMB?50:100);
 		break;
 	/**
 	 * Mechanic
@@ -4185,8 +4210,24 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 
 	if(md.damage < 0)
 		md.damage = 0;
-	else if(md.damage && tstatus->mode&MD_PLANT)
-		md.damage = 1;
+	else if(md.damage && tstatus->mode&MD_PLANT){
+		switch(skill_num){
+			case HT_LANDMINE:
+			case MA_LANDMINE:
+			case HT_BLASTMINE:
+			case HT_CLAYMORETRAP:
+			case RA_CLUSTERBOMB:
+#ifdef RENEWAL
+				break;
+#endif
+			default:
+				md.damage = 1;
+		}
+	}else if( target->type == BL_SKILL ){
+		TBL_SKILL *su = (TBL_SKILL*)target;
+		if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
+			md.damage = 1;
+	}
 
 	if(!(nk&NK_NO_ELEFIX))
 		md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
@@ -4198,9 +4239,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 		md.damage=battle_calc_bg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag);
 
 	switch( skill_num ) {
-		case RA_CLUSTERBOMB:
 		case RA_FIRINGTRAP:
  		case RA_ICEBOUNDTRAP:
+			if( md.damage == 1 ) break;
+		case RA_CLUSTERBOMB:
 			{
 				struct Damage wd;
 				wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag);
@@ -4554,7 +4596,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 		if( sc->data[SC_GIANTGROWTH] && (wd.flag&BF_SHORT) && rnd()%100 < sc->data[SC_GIANTGROWTH]->val2 )
 			wd.damage *= 3; // Triple Damage
 		
-		if( sc->data[SC_FEARBREEZE] && sc->data[SC_FEARBREEZE]->val4 > 0 && sd->status.inventory[sd->equip_index[EQI_AMMO]].amount >= sc->data[SC_FEARBREEZE]->val4 && battle_config.arrow_decrement){
+		if( sd && sc->data[SC_FEARBREEZE] && sc->data[SC_FEARBREEZE]->val4 > 0 && sd->status.inventory[sd->equip_index[EQI_AMMO]].amount >= sc->data[SC_FEARBREEZE]->val4 && battle_config.arrow_decrement){
 			pc_delitem(sd,sd->equip_index[EQI_AMMO],sc->data[SC_FEARBREEZE]->val4,0,1,LOG_TYPE_CONSUME);
 			sc->data[SC_FEARBREEZE]->val4 = 0;
 		}
@@ -4592,7 +4634,11 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 
 	if (sd && sd->bonus.splash_range > 0 && damage > 0)
 		skill_castend_damage_id(src, target, 0, 1, tick, 0);
-
+	if ( target->type == BL_SKILL && damage > 0 ){
+		TBL_SKILL *su = (TBL_SKILL*)target;
+		if( su->group && su->group->skill_id == HT_BLASTMINE)
+			skill_blown(src, target, 3, -1, 0);
+	}
 	map_freeblock_lock();
 
 	battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion);
@@ -4843,6 +4889,9 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 				return 0;
 			if( skill_get_inf2(su->group->skill_id)&INF2_TRAP ) { //Only a few skills can target traps...
 				switch( battle_getcurrentskill(src) ) {
+					case RK_DRAGONBREATH:// it can only hit traps in pvp/gvg maps
+						if( !map[m].flag.pvp && !map[m].flag.gvg )
+							break;
 					case 0://you can hit them without skills
 					case MA_REMOVETRAP:
 					case HT_REMOVETRAP:
@@ -4855,15 +4904,37 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 					case RA_DETONATOR:
 					case RA_SENSITIVEKEEN:
 					case GN_CRAZYWEED:
+					case RK_STORMBLAST:
+					case RK_PHANTOMTHRUST:
+					case SR_RAMPAGEBLASTER:
+					case NC_COLDSLOWER:
+					case NC_SELFDESTRUCTION:
+#ifdef RENEWAL
+					case KN_BOWLINGBASH:
+					case KN_SPEARSTAB:
+					case LK_SPIRALPIERCE:
+					case ML_SPIRALPIERCE:
+					case MO_FINGEROFFENSIVE:
+					case MO_INVESTIGATE:
+					case MO_TRIPLEATTACK:
+					case MO_EXTREMITYFIST:
+					case CR_HOLYCROSS:
+					case ASC_METEORASSAULT:
+					case RG_RAID:
+					case MC_CARTREVOLUTION:
+#endif
 						state |= BCT_ENEMY;
 						strip_enemy = 0;
 						break;
-					default:
-						return 0;
+					default:						
+						if(su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD){
+							state |= BCT_ENEMY;
+							strip_enemy = 0;
+						}else
+							return 0;
 				}
 			} else if (su->group->skill_id==WZ_ICEWALL ||
-					   su->group->skill_id == GN_WALLOFTHORN ||
-					   su->group->skill_id == WM_REVERBERATION) {
+					   su->group->skill_id == GN_WALLOFTHORN) {
 				state |= BCT_ENEMY;
 				strip_enemy = 0;
 			} else	//Excepting traps and icewall, you should not be able to target skills.

+ 2 - 1
src/map/pc.c

@@ -4789,7 +4789,8 @@ int pc_checkallowskill(struct map_session_data *sd)
 		SC_ADRENALINE,
 		SC_ADRENALINE2,
 		SC_DANCING,
-		SC_GATLINGFEVER
+		SC_GATLINGFEVER,
+		SC_FEARBREEZE
 	};
 	const enum sc_type scs_list[] = {
 		SC_AUTOGUARD,

+ 140 - 87
src/map/skill.c

@@ -119,7 +119,11 @@ static int skill_destroy_trap( struct block_list *bl, va_list ap );
 //Since only mob-casted splash skills can hit ice-walls
 static inline int splash_target(struct block_list* bl)
 {
+#ifndef RENEWAL
 	return ( bl->type == BL_MOB ) ? BL_SKILL|BL_CHAR : BL_CHAR;
+#else // Some skills can now hit ground skills(traps, ice wall & etc.)
+	return BL_SKILL|BL_CHAR;
+#endif
 }
 
 /// Returns the id of the skill, or 0 if not found.
@@ -803,6 +807,8 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 			if((sce=sc->data[SC_EDP]))
 				sc_start4(bl,SC_DPOISON,sce->val2, sce->val1,src->id,0,0,
 					skill_get_time2(ASC_EDP,sce->val1));
+			// Cancels on normal attack but benefits with the bonuses
+			status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);
 		}
 	}
 	break;
@@ -1161,23 +1167,12 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 		sc_start(bl,SC_FREEZE,100,skilllv,skill_get_time(skillid,skilllv));
 		break;
 	case RA_WUGBITE:
-		{
-			int chance = (50+10*skilllv)-(sstatus->agi/4) + (sd ? pc_checkskill(sd,RA_TOOTHOFWUG)*2 : 0);
-			if(chance < 50) chance = 50;
-			sc_start(bl, SC_BITE, chance, skilllv, (skilllv + (sd ? pc_checkskill(sd,RA_TOOTHOFWUG)/2 : 0)) * 1000);
-			break;
-		}
+		sc_start(bl, SC_BITE,  (sd ? pc_checkskill(sd,RA_TOOTHOFWUG)*2 : 0), skilllv, (skilllv*1000 + (sd ? pc_checkskill(sd,RA_TOOTHOFWUG)*500 : 0)) );
+		break;
 	case RA_SENSITIVEKEEN:
 		if( rnd()%100 < 8 * skilllv )
 			skill_castend_damage_id(src, bl, RA_WUGBITE, sd ? pc_checkskill(sd, RA_WUGBITE):skilllv, tick, SD_ANIMATION);
 		break;
-	case RA_MAGENTATRAP:
-	case RA_COBALTTRAP:
-	case RA_MAIZETRAP:
-	case RA_VERDURETRAP:
-		if( dstmd && !(dstmd->status.mode&MD_BOSS) )
-			sc_start2(bl,SC_ELEMENTALCHANGE,100,skilllv,skill_get_ele(skillid,skilllv),skill_get_time2(skillid,skilllv));
-		break;
 	case RA_FIRINGTRAP:
 	case RA_ICEBOUNDTRAP:
 		sc_start(bl, (skillid == RA_FIRINGTRAP) ? SC_BURNING:SC_FREEZING, 40 + 10 * skilllv, skilllv, skill_get_time2(skillid, skilllv));
@@ -2023,9 +2018,8 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in
 			break;
 		case BL_SKILL:
 			su = (struct skill_unit *)target;
-			if( su && su->group && (su->group->unit_id == UNT_ANKLESNARE || su->group->unit_id == UNT_ELECTRICSHOCKER
-				|| su->group->unit_id == UNT_CLUSTERBOMB || su->group->unit_id == UNT_REVERBERATION) )
-				return 0; // ankle snare, electricshocker, clusterbomb, reverberation cannot be knocked back
+			if( su && su->group && su->group->unit_id == UNT_ANKLESNARE )
+				return 0; // ankle snare cannot be knocked back
 			break;
 	}
 	
@@ -2378,7 +2372,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
 		break;
 	case EL_STONE_RAIN:
 		dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skillid,-1,(flag&1)?8:5);
-		break;			
+		break;	
 	case WM_SEVERE_RAINSTORM_MELEE:
 		dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,skilllv,5);
 		break;
@@ -2386,13 +2380,24 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
 	case WM_REVERBERATION_MAGIC:
 		dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_REVERBERATION,-2,6);
 		break;
+	case HT_CLAYMORETRAP:
+	case HT_BLASTMINE:
+	case HT_FLASHER:
+	case HT_FREEZINGTRAP:
+	case RA_CLUSTERBOMB:
+	case RA_FIRINGTRAP:
+	case RA_ICEBOUNDTRAP:
+		clif_skill_damage((bl->type==BL_PC)?dsrc:src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid,flag&SD_LEVEL?-1:skilllv, 5);
+	case HT_LANDMINE:
+		dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, -1, type);
+		break;
 	case AB_DUPLELIGHT_MELEE:
 	case AB_DUPLELIGHT_MAGIC:
 		dmg.amotion = 300;/* makes the damage value not overlap with previous damage (when displayed by the client) */
 	default:
 		if( flag&SD_ANIMATION && dmg.div_ < 2 ) //Disabling skill animation doesn't works on multi-hit.
 			type = 5;
-		dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, flag&SD_LEVEL?-1:skilllv, type);
+		dmg.dmotion = clif_skill_damage((bl->type==BL_PC)?dsrc:src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, flag&SD_LEVEL?-1:skilllv, type);
 		break;
 	}
 
@@ -2479,16 +2484,6 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
 			}
 		}
 	}
-	if( skillid != WZ_SIGHTRASHER &&
-		skillid != WZ_SIGHTBLASTER &&
-		skillid != AC_SHOWER && skillid != MA_SHOWER &&
-		skillid != SM_MAGNUM && skillid != MS_MAGNUM &&
-		bl->type == BL_SKILL && damage > 0 )
-	{
-		struct skill_unit* su = (struct skill_unit*)bl;
-		if (su->group && skill_get_inf2(su->group->skill_id)&INF2_TRAP)
-			damage = 0; //Sight rasher, blaster, and arrow shower may dmg traps. [Kevin]
-	}
 
 	if (dmg.dmg_lv >= ATK_MISS && (type = skill_get_walkdelay(skillid, skilllv)) > 0)
 	{	//Skills with can't walk delay also stop normal attacking for that
@@ -2565,6 +2560,11 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
 				break;
 			default:
 				skill_blown(dsrc,bl,dmg.blewcount,direction, 0x0 );
+				if ( !dmg.blewcount && bl->type == BL_SKILL && damage > 0 ){
+					TBL_SKILL *su = (TBL_SKILL*)bl;
+					if( su->group && su->group->skill_id == HT_BLASTMINE)
+						skill_blown(src, bl, 3, -1, 0);
+				}
 				break;
 		}
 	}
@@ -2606,7 +2606,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
 	if(skillid == CR_GRANDCROSS || skillid == NPC_GRANDDARKNESS)
 		dmg.flag |= BF_WEAPON;
 
-	if( sd && dmg.flag&BF_WEAPON && src != bl && ( src == dsrc || ( dsrc->type == BL_SKILL && ( skillid == SG_SUN_WARM || skillid == SG_MOON_WARM || skillid == SG_STAR_WARM ) ) )  && damage > 0 )
+	if( sd && src != bl && damage > 0 && ( dmg.flag&BF_WEAPON || 
+		(dmg.flag&BF_MISC && (skillid == RA_CLUSTERBOMB || skillid == RA_FIRINGTRAP || skillid == RA_ICEBOUNDTRAP || skillid == RK_DRAGONBREATH)) ) )
 	{
 		if (battle_config.left_cardfix_to_right)
 			battle_drain(sd, bl, dmg.damage, dmg.damage, tstatus->race, tstatus->mode&MD_BOSS);
@@ -3692,7 +3693,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 				skill_area_temp[0] = map_foreachinrange(skill_area_sub, bl, (skillid == AS_SPLASHER)?1:skill_get_splash(skillid, skilllv), BL_CHAR, src, skillid, skilllv, tick, BCT_ENEMY, skill_area_sub_count);
 
 			// recursive invocation of skill_castend_damage_id() with flag|1
-			map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), (skillid == WL_CRIMSONROCK)?BL_CHAR|BL_SKILL:splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id);
+			map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), ( skillid == WM_REVERBERATION_MELEE || skillid == WM_REVERBERATION_MAGIC )?BL_CHAR:splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id);
 		}
 		break;
 
@@ -4203,34 +4204,50 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 		skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag|ELE_DARK);
 		break;
 	case RA_WUGSTRIKE:
+		if( sd && pc_isridingwug(sd) ){
+			short x[8]={0,-1,-1,-1,0,1,1,1};
+			short y[8]={1,1,0,-1,-1,-1,0,1};
+			int dir = map_calc_dir(bl, src->x, src->y);
+
+			if( unit_movepos(src, bl->x+x[dir], bl->y+y[dir], 1, 1) )
+			{
+				clif_slide(src, bl->x+x[dir], bl->y+y[dir]);
+				clif_fixpos(src);
+				skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag);
+			}
+			break;
+		}
 	case RA_WUGBITE:
 		if( path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKNOREACH) ) {
 			skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
-		}
+		}else if( sd && skillid == RA_WUGBITE ) // Only RA_WUGBITE has the skill fail message.
+			clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0);
+
 		break;
 
 	case RA_SENSITIVEKEEN:
 		if( bl->type != BL_SKILL ) { // Only Hits Invisible Targets
 			struct status_change * tsc = status_get_sc(bl);
-			if(tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK) || tsc->data[SC__INVISIBILITY]) )
+			if( tsc && tsc->option&(OPTION_HIDE|OPTION_CLOAK) ){
 				skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+				status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
+			}
 		}
 		else
 		{
 			struct skill_unit *su = BL_CAST(BL_SKILL,bl);
 			struct skill_unit_group* sg;
 
-			if( su && (sg=su->group) && skill_get_inf2(sg->skill_id)&INF2_TRAP && sg->src_id != src->id &&
-				battle_check_target(src, map_id2bl(sg->src_id), BCT_ENEMY) > 0 )
+			if( su && (sg=su->group) && skill_get_inf2(sg->skill_id)&INF2_TRAP )
 			{
-				if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) )
+				if( !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) )
 				{ 
 					struct item item_tmp;
 					memset(&item_tmp,0,sizeof(item_tmp));
-					item_tmp.nameid = ( sg->unit_id >= UNT_MAGENTATRAP && sg->unit_id <= UNT_CLUSTERBOMB )?ITEMID_TRAP_ALLOY:ITEMID_TRAP;
+					item_tmp.nameid = sg->item_id?sg->item_id:ITEMID_TRAP;
 					item_tmp.identify = 1;
 					if( item_tmp.nameid )
-						map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+						map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0);
 				}
 				skill_delunit(su);
 			}
@@ -4330,7 +4347,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 		} else{
 			map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id);
 			clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6);
-		}
+			}
 		break;
 
 	case WM_LULLABY_DEEPSLEEP:
@@ -4479,6 +4496,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 					skill_castend_damage_id);
 				flag|=1; //Set flag to 1 so ammo is not double-consumed. [Skotlex]
 			}
+			status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);
 		}
 		break;
 
@@ -5619,7 +5637,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			clif_walkok(sd); // So aegis has to resend the walk ok.
 		break;
 	case AS_CLOAKING:
-	case RA_CAMOUFLAGE:
 	case GC_CLOAKINGEXCEED:
 	case LG_FORCEOFVANGUARD:
 	case SC_REPRODUCE:
@@ -5633,6 +5650,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			map_freeblock_unlock();
 			return 0;
 		}
+	case RA_CAMOUFLAGE:
 		i = sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv));
 		if( i )
 			clif_skill_nodamage(src,bl,skillid,( skillid == LG_FORCEOFVANGUARD ) ? skilllv : -1,i);
@@ -6642,7 +6660,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 					{ // get back 1 trap
 						struct item item_tmp;
 						memset(&item_tmp,0,sizeof(item_tmp));
-						item_tmp.nameid = ITEMID_TRAP;
+						item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP;
 						item_tmp.identify = 1;
 						if( item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_OTHER)) )
 						{
@@ -8204,7 +8222,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 		if( flag&1 ) {
 			sc_start2(bl,type,(skillid==WM_VOICEOFSIREN)?20+10*skilllv:100,skilllv,(skillid==WM_VOICEOFSIREN)?src->id:0,skill_get_time(skillid,skilllv));
 		} else {
-			map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),(skillid==WM_VOICEOFSIREN)?BL_CHAR:BL_PC, src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id);
+			map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),(skillid==WM_VOICEOFSIREN)?BL_CHAR|BL_SKILL:BL_PC, src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id);
 			clif_skill_nodamage(src,bl,skillid,skilllv,1);
 		}
 		break;
@@ -8747,6 +8765,11 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
 				break;
 		}
 
+		if( ud->skillid == RA_WUGSTRIKE ){
+			if( !path_search(NULL,src->m,src->x,src->y,target->x,target->y,1,CELL_CHKNOREACH))
+				break;
+		}
+
 		if( ud->skillid == PR_LEXDIVINA || ud->skillid == MER_LEXDIVINA )
 		{
 			sc = status_get_sc(target);
@@ -8785,8 +8808,10 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
 					break;
 			}
 			else
-			if (inf && battle_check_target(src, target, inf) <= 0)
+			if (inf && battle_check_target(src, target, inf) <= 0){
+				if (sd) clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0);
 				break;
+			}
 
 			if(inf&BCT_ENEMY && (sc = status_get_sc(target)) &&
 				sc->data[SC_FOGWALL] &&
@@ -8886,6 +8911,8 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
 
 		// SC_MAGICPOWER needs to switch states before any damage is actually dealt
 		skill_toggle_magicpower(src, ud->skillid);
+		if( ud->skillid != RA_CAMOUFLAGE ) // only normal attack and auto cast skills benefit from its bonuses
+			status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);
 
 		if (skill_get_casttype(ud->skillid) == CAST_NODAMAGE)
 			skill_castend_nodamage_id(src,target,ud->skillid,ud->skilllv,tick,flag);
@@ -9090,7 +9117,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
 //			}
 //		}
 		unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill_get_walkdelay(ud->skillid, ud->skilllv), 1);
-
+		status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);// only normal attack and auto cast skills benefit from its bonuses
 		map_freeblock_lock();
 		skill_castend_pos2(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv,tick,0);
 
@@ -9568,7 +9595,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 	case RK_WINDCUTTER:
 	case WM_LULLABY_DEEPSLEEP:
 		i = skill_get_splash(skillid,skilllv);
-		map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,BL_CHAR,
+		map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),
 			src,skillid,skilllv,tick,flag|(skillid==WM_LULLABY_DEEPSLEEP?BCT_ALL:BCT_ENEMY)|1,skill_castend_damage_id);
 		break;
 	/**
@@ -9602,7 +9629,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 			sc->comet_y = y;
 		}
 		i = skill_get_splash(skillid,skilllv);
-		map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id);
+		map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id);
 		break;
 
 	case WL_EARTHSTRAIN:
@@ -9675,10 +9702,10 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 			int width;//according to data from irowiki it actually is a square
 			for( width = 0; width < 7; width++ )
 				for( i = 0; i < 7; i++ )
-					map_foreachincell(skill_area_sub, src->m, x-2+i, y-2+width, BL_CHAR, src, LG_OVERBRAND_BRANDISH, skilllv, tick, flag|BCT_ENEMY,skill_castend_damage_id);
+					map_foreachincell(skill_area_sub, src->m, x-2+i, y-2+width, splash_target(src), src, LG_OVERBRAND_BRANDISH, skilllv, tick, flag|BCT_ENEMY,skill_castend_damage_id);
 			for( width = 0; width < 7; width++ )
 				for( i = 0; i < 7; i++ )
-					map_foreachincell(skill_area_sub, src->m, x-2+i, y-2+width, BL_CHAR, src, skillid, skilllv, tick, flag|BCT_ENEMY,skill_castend_damage_id);
+					map_foreachincell(skill_area_sub, src->m, x-2+i, y-2+width, splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY,skill_castend_damage_id);
 		}
 		break;
 
@@ -9695,7 +9722,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 	case LG_RAYOFGENESIS:
 		if( status_charge(src,status_get_max_hp(src)*3*skilllv / 100,0) ) {
 			i = skill_get_splash(skillid,skilllv);
-			map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,BL_CHAR,
+			map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),
 				src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id);
 		} else if( sd )
 			clif_skill_fail(sd,skillid,USESKILL_FAIL,0);
@@ -9709,7 +9736,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 		
 	case WM_GREAT_ECHO:
 		flag|=1; // Should counsume 1 item per skill usage.
-		map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),BL_CHAR, src, skillid, skilllv, tick, flag|BCT_ENEMY, skill_castend_damage_id);
+		map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY, skill_castend_damage_id);
 		break;
 
 	case GN_CRAZYWEED:
@@ -10055,7 +10082,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
 {
 	struct skill_unit_group *group;
 	int i,limit,val1=0,val2=0,val3=0;
-	int target,interval,range,unit_flag;
+	int target,interval,range,unit_flag,req_item=0;
 	struct s_skill_unit_layout *layout;
 	struct map_session_data *sd;
 	struct status_data *status;
@@ -10153,10 +10180,16 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
 	case RA_VERDURETRAP:
 	case RA_FIRINGTRAP:
 	case RA_ICEBOUNDTRAP:
-		if( map_flag_gvg(src->m) || map[src->m].flag.battleground )
-			limit *= 4; // longer trap times in WOE [celest]
-		if( battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall) )
-			target = BCT_ALL;
+		{
+			struct skill_condition req = skill_get_requirement(sd,skillid,skilllv);
+			ARR_FIND(0, MAX_SKILL_ITEM_REQUIRE, i, req.itemid[i] && (req.itemid[i] == ITEMID_TRAP || req.itemid[i] == ITEMID_TRAP_ALLOY));
+			if( req.itemid[i] )
+				req_item = req.itemid[i];
+			if( map_flag_gvg(src->m) || map[src->m].flag.battleground )
+				limit *= 4; // longer trap times in WOE [celest]
+			if( battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall) )
+				target = BCT_ALL;
+		}
 		break;
 
 	case SA_LANDPROTECTOR:
@@ -10355,6 +10388,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
 	group->state.ammo_consume = (sd && sd->state.arrow_atk && skillid != GS_GROUNDDRIFT); //Store if this skill needs to consume ammo.
 	group->state.song_dance = (unit_flag&(UF_DANCE|UF_SONG)?1:0)|(unit_flag&UF_ENSEMBLE?2:0); //Signals if this is a song/dance/duet
 	group->state.guildaura = ( skillid >= GD_LEADERSHIP && skillid <= GD_HAWKEYES )?1:0;
+	group->item_id = req_item;
   	//if tick is greater than current, do not invoke onplace function just yet. [Skotlex]
 	if (DIFF_TICK(group->tick, gettick()) > SKILLUNITTIMER_INTERVAL)
 		active_flag = 0;
@@ -10417,6 +10451,8 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
 		case HT_TALKIEBOX:
 		case HT_SKIDTRAP:
 		case MA_SKIDTRAP:
+		case HT_CLAYMORETRAP:
+		case HT_BLASTMINE:
 		/**
 		 * Ranger
 		 **/
@@ -10948,6 +10984,18 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
 				status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
 			break;
 
+			
+		case UNT_MAGENTATRAP:
+		case UNT_COBALTTRAP:
+		case UNT_MAIZETRAP:
+		case UNT_VERDURETRAP:
+			if( bl->type == BL_PC )// it won't work on players
+				break;
+		case UNT_FIRINGTRAP:
+		case UNT_ICEBOUNDTRAP:
+		case UNT_CLUSTERBOMB:
+			if( bl->id == ss->id )// it won't trigger on caster
+				break;
 		case UNT_LANDMINE:
 		case UNT_CLAYMORETRAP:
 		case UNT_BLASTMINE:
@@ -10956,20 +11004,11 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
 		case UNT_FLASHER:
 		case UNT_FREEZINGTRAP:
 		case UNT_FIREPILLAR_ACTIVE:
-		/**
-		 * Ranger
-		 **/
-		case UNT_CLUSTERBOMB:
-		case UNT_MAGENTATRAP:
-		case UNT_COBALTTRAP:
-		case UNT_MAIZETRAP:
-		case UNT_VERDURETRAP:
-		case UNT_FIRINGTRAP:
-		case UNT_ICEBOUNDTRAP:
 			map_foreachinrange(skill_trap_splash,&src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
 			if (sg->unit_id != UNT_FIREPILLAR_ACTIVE)
 				clif_changetraplook(&src->bl, sg->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS);
-			sg->limit=DIFF_TICK(tick,sg->tick)+1500 + (sg->unit_id== UNT_CLUSTERBOMB?1000:0);// Cluster Bomb has 1s to disappear once activated.
+			sg->limit=DIFF_TICK(tick,sg->tick)+1500 +
+				(sg->unit_id== UNT_CLUSTERBOMB || sg->unit_id== UNT_ICEBOUNDTRAP?1000:0);// Cluster Bomb/Icebound has 1s to disappear once activated.
 			sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again.
 			break;
 
@@ -11547,6 +11586,7 @@ int skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl, int dam
 	nullpo_ret(sg=src->group);
 
 	switch( sg->unit_id ) {
+	case UNT_BLASTMINE:
 	case UNT_SKIDTRAP:
 	case UNT_LANDMINE:
 	case UNT_SHOCKWAVE:
@@ -11561,9 +11601,6 @@ int skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl, int dam
 	case UNT_WALLOFTHORN:
 		src->val1-=damage;
 		break;
-	case UNT_BLASTMINE:
-		skill_blown(bl, &src->bl, 3, -1, 0);
-		break;
 	default:
 		damage = 0;
 		break;
@@ -11851,10 +11888,9 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
 			case HT_SKIDTRAP:     case HT_LANDMINE:     case HT_ANKLESNARE:     case HT_SHOCKWAVE:
 			case HT_SANDMAN:      case HT_FLASHER:      case HT_FREEZINGTRAP:   case HT_BLASTMINE:
 			case HT_CLAYMORETRAP: case HT_SPRINGTRAP:   case RA_DETONATOR:      case RA_CLUSTERBOMB:
-			case RA_WUGDASH:      case RA_WUGRIDER:
+			case RA_WUGDASH:      case RA_WUGRIDER:		case RA_WUGSTRIKE:
 				break;
-			default:
-				clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0);
+			default: // in official there is no message.
 				return 0;
 		}
 	}
@@ -12255,14 +12291,14 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
 		/**
 		 * Ranger
 		 **/
-		case RA_SENSITIVEKEEN:
-			if(!pc_iswug(sd)) {
-				clif_skill_fail(sd,skill,USESKILL_FAIL_CONDITION,0);
+		case RA_WUGMASTERY:
+			if( pc_isfalcon(sd) || pc_isridingwug(sd) || sd->sc.data[SC__GROOMY]) {
+				clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0);
 				return 0;
 			}
 			break;
-		case RA_WUGMASTERY:
-			if( pc_isfalcon(sd) || pc_isridingwug(sd) || sd->sc.data[SC__GROOMY]) {
+		case RA_WUGSTRIKE:
+			if( !pc_iswug(sd) && !pc_isridingwug(sd) ) {
 				clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0);
 				return 0;
 			}
@@ -12872,7 +12908,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, short
 			case SO_SUMMON_TERA:
 				if( i < 3 )
 					continue;
-				break;				
+				break;
 		}
 
 		req.itemid[i] = skill_db[j].itemid[i];
@@ -12893,6 +12929,13 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, short
 					req.amount[i] = 1; // Hocus Pocus allways use at least 1 gem
 			}
 		}
+		if( skill >= HT_SKIDTRAP && skill <= HT_TALKIEBOX && pc_checkskill(sd, RA_RESEARCHTRAP) > 0){
+			if( (j=pc_search_inventory(sd,req.itemid[i])) < 0  || ( j >= 0 && sd->status.inventory[j].amount < req.amount[i] ) ){
+				req.itemid[i] = ITEMID_TRAP_ALLOY; 
+				req.amount[i] = 1;
+			}
+			break;
+		}
 	}
 
 	/* requirements are level-dependent */
@@ -13863,7 +13906,8 @@ int skill_detonator(struct block_list *bl, va_list ap)
 
 			clif_changetraplook(bl,unit_id == UNT_FIRINGTRAP ? UNT_DUMMYSKILL : UNT_USED_TRAPS);
 			unit->group->unit_id = UNT_USED_TRAPS;
-			unit->group->limit = DIFF_TICK(gettick(),unit->group->tick) + (unit_id == UNT_TALKIEBOX ? 5000 : (unit_id == UNT_CLUSTERBOMB ? 2500 : 1500) );
+			unit->group->limit = DIFF_TICK(gettick(),unit->group->tick) + 
+				(unit_id == UNT_TALKIEBOX ? 5000 : (unit_id == UNT_CLUSTERBOMB || unit_id == UNT_ICEBOUNDTRAP? 2500 : 1500) );
 			break;
 	}
 	return 0;
@@ -14040,16 +14084,20 @@ static int skill_trap_splash (struct block_list *bl, va_list ap)
 		case UNT_FIRINGTRAP:
 		case UNT_ICEBOUNDTRAP:
 		case UNT_CLUSTERBOMB:
-			if(skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1))
-				clif_skill_damage(src,bl,tick,0,0,-30000,1,sg->skill_id,sg->skill_lv,5);
+			if( ss != bl )
+				skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1|SD_LEVEL);
 			break;
+	case UNT_MAGENTATRAP:
+	case UNT_COBALTTRAP:
+	case UNT_MAIZETRAP:
+	case UNT_VERDURETRAP:
+		if( bl->type != BL_PC && !is_boss(bl) )
+			sc_start2(bl,SC_ELEMENTALCHANGE,100,sg->skill_lv,skill_get_ele(sg->skill_id,sg->skill_lv),skill_get_time2(sg->skill_id,sg->skill_lv));
+		break;
 		case UNT_REVERBERATION:
 			skill_addtimerskill(ss,tick+50,bl->id,0,0,WM_REVERBERATION_MELEE,sg->skill_lv,BF_WEAPON,0); // for proper skill delay animation when use with Dominion Impulse
 			skill_addtimerskill(ss,tick+250,bl->id,0,0,WM_REVERBERATION_MAGIC,sg->skill_lv,BF_MAGIC,0);
 			break;
-		case UNT_SEVERE_RAINSTORM:
-			skill_attack(BF_WEAPON,ss,ss,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0);
-			break;
 		default:
 			skill_attack(skill_get_type(sg->skill_id),ss,src,bl,sg->skill_id,sg->skill_lv,tick,0);
 			break;
@@ -14609,6 +14657,9 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
 		switch( group->unit_id )
 		{
 			case UNT_BLASTMINE:
+#ifdef RENEWAL
+			case UNT_CLAYMORETRAP:
+#endif
 			case UNT_GROUNDDRIFT_WIND:
 			case UNT_GROUNDDRIFT_DARK:
 			case UNT_GROUNDDRIFT_POISON:
@@ -14633,7 +14684,9 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
 			case UNT_SANDMAN:
 			case UNT_FLASHER:
 			case UNT_FREEZINGTRAP:
+#ifndef RENEWAL
 			case UNT_CLAYMORETRAP:
+#endif
 			case UNT_TALKIEBOX:
 			case UNT_CLUSTERBOMB:
 			case UNT_MAGENTATRAP:
@@ -14649,7 +14702,7 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
 				{ // revert unit back into a trap
 					struct item item_tmp;
 					memset(&item_tmp,0,sizeof(item_tmp));
-					item_tmp.nameid = ( group->unit_id >= UNT_MAGENTATRAP && group->unit_id <= UNT_CLUSTERBOMB )?ITEMID_TRAP_ALLOY:ITEMID_TRAP;	// Ensure we're returning the correct trap
+					item_tmp.nameid = group->item_id?group->item_id:ITEMID_TRAP;
 					item_tmp.identify = 1;
 					map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0);
 				}
@@ -14736,6 +14789,7 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
 				if( unit->val1 <= 0 && unit->limit + group->tick > tick + 700 )
 					unit->limit = DIFF_TICK(tick+700,group->tick);
 				break;
+			case UNT_BLASTMINE:
 			case UNT_SKIDTRAP:
 			case UNT_LANDMINE:
 			case UNT_SHOCKWAVE:
@@ -14745,14 +14799,13 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
 			case UNT_FREEZINGTRAP:
 			case UNT_TALKIEBOX:
 			case UNT_ANKLESNARE:
-			case UNT_ELECTRICSHOCKER:
-			case UNT_CLUSTERBOMB:
 				if( unit->val1 <= 0 ) {
 					if( group->unit_id == UNT_ANKLESNARE && group->val2 > 0 )
 						skill_delunit(unit);
 					else {
-						group->unit_id = UNT_USED_TRAPS;
+						clif_changetraplook(bl, group->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS);
 						group->limit = DIFF_TICK(tick, group->tick) + 1500;
+						group->unit_id = UNT_USED_TRAPS;
 					}
 				}
 				break;

+ 1 - 0
src/map/skill.h

@@ -154,6 +154,7 @@ struct skill_unit_group {
 	int unit_id;
 	int group_id;
 	int unit_count,alive_count;
+	int item_id; //store item used.
 	struct skill_unit *unit;
 	struct {
 		unsigned ammo_consume : 1;

+ 18 - 15
src/map/status.c

@@ -569,7 +569,7 @@ void initChangeTables(void) {
 	set_sc( RA_FEARBREEZE        , SC_FEARBREEZE      , SI_FEARBREEZE      , SCB_NONE );
 	set_sc( RA_ELECTRICSHOCKER   , SC_ELECTRICSHOCKER , SI_ELECTRICSHOCKER , SCB_NONE );
 	set_sc( RA_WUGDASH           , SC_WUGDASH         , SI_WUGDASH         , SCB_SPEED );
-	set_sc( RA_CAMOUFLAGE        , SC_CAMOUFLAGE      , SI_CAMOUFLAGE      , SCB_CRI|SCB_SPEED );
+	set_sc( RA_CAMOUFLAGE        , SC_CAMOUFLAGE      , SI_CAMOUFLAGE      , SCB_SPEED );
 	add_sc( RA_MAGENTATRAP       , SC_ELEMENTALCHANGE );
 	add_sc( RA_COBALTTRAP        , SC_ELEMENTALCHANGE );
 	add_sc( RA_MAIZETRAP         , SC_ELEMENTALCHANGE );
@@ -982,6 +982,7 @@ void initChangeTables(void) {
 	StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOMOVE;
 	StatusChangeStateTable[SC_CRYSTALIZE]          |= SCS_NOMOVE|SCS_NOMOVECOND;
 	StatusChangeStateTable[SC_NETHERWORLD]         |= SCS_NOMOVE;
+	StatusChangeStateTable[SC_CAMOUFLAGE]          |= SCS_NOMOVE|SCS_NOMOVECOND;
 	
 	/* StatusChangeState (SCS_) NOPICKUPITEMS */
 	StatusChangeStateTable[SC_HIDING]              |= SCS_NOPICKITEM;
@@ -3415,6 +3416,8 @@ void status_calc_state( struct block_list *bl, struct status_change *sc, enum sc
 				  || (sc->data[SC_CLOAKING] && //Need wall at level 1-2
 							sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1))
 				  || (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB)
+				  || (sc->data[SC_CAMOUFLAGE] && sc->data[SC_CAMOUFLAGE]->val1 < 3 
+							&& !(sc->data[SC_CAMOUFLAGE]->val3&1))
 				 ) {
 			sc->cant.move += ( start ? 1 : -1 );
 		}
@@ -4487,8 +4490,6 @@ static signed short status_calc_critical(struct block_list *bl, struct status_ch
 		critical += sc->data[SC_STRIKING]->val1;
 	if(sc->data[SC__INVISIBILITY])
 		critical += critical * sc->data[SC__INVISIBILITY]->val3 / 100;
-	if(sc->data[SC_CAMOUFLAGE])
-		critical += 100;
 	if(sc->data[SC__UNLUCKY])
 		critical -= critical * sc->data[SC__UNLUCKY]->val2 / 100;
 #ifdef RENEWAL
@@ -4929,7 +4930,7 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
 				if( sc->data[SC_MARSHOFABYSS] )
 					val = max( val, 40 + 10 * sc->data[SC_MARSHOFABYSS]->val1 );
 				if( sc->data[SC_CAMOUFLAGE] && (sc->data[SC_CAMOUFLAGE]->val3&1) == 0 )
-					val = max( val, sc->data[SC_CAMOUFLAGE]->val1 < 3 ? 300 : 25 * (6 - sc->data[SC_CAMOUFLAGE]->val1) );
+					val = max( val, sc->data[SC_CAMOUFLAGE]->val1 < 3 ? 0 : 25 * (5 - sc->data[SC_CAMOUFLAGE]->val1) );
 				if( sc->data[SC__GROOMY] )
 					val = max( val, sc->data[SC__GROOMY]->val2);
 				if( sc->data[SC_STEALTHFIELD_MASTER] )
@@ -6028,14 +6029,14 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
 	case SC_OBLIVIONCURSE: // 100% - (100 - 0.8 x INT)
 		sc_def = 100 - ( 100 - status->int_* 8 / 10 ); 
 		sc_def = max(sc_def, 5); // minimum of 5%
+		break;	
+	case SC_BITE: // {(Base Success chance) - (Target's AGI / 4)}
+		rate -= status->agi*1000/4;
+		rate = max(rate,50000); // minimum of 50%
 		break;
 	case SC_ELECTRICSHOCKER:
-	case SC_BITE: {
-			if( bl->type == BL_MOB )
-				tick -= 1000 * (status->agi/10);
-			if( sd && type != SC_ELECTRICSHOCKER )
-				tick >>= 1;
-		}
+		if( bl->type == BL_MOB )
+			tick -= 1000 * (status->agi/10);
 		break;
 	case SC_CRYSTALIZE:
 		tick -= (1000*(status->vit/10))+(status_get_lv(bl)/50);
@@ -7836,7 +7837,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 			tick_time = 1000; // [GodLesZ] tick time
 			break;
 		case SC_CAMOUFLAGE:
-			//val3 |= battle_config.pc_camouflage_check_type&7;
+			val4 = tick/1000;
 			tick_time = 1000; // [GodLesZ] tick time
 			break;
 		case SC_WUGDASH:
@@ -9874,10 +9875,12 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		break;
 
 	case SC_CAMOUFLAGE:
-		if( !status_charge(bl,0,7 - sce->val1) )
-			break;
-		sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
-		return 0;
+		if(--(sce->val4) > 0){
+			status_charge(bl,0,7 - sce->val1);
+			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			return 0;
+		}
+		break;
 
 	case SC__REPRODUCE:
 		if(!status_charge(bl, 0, 1))

+ 6 - 7
src/map/unit.c

@@ -1253,11 +1253,11 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 	// moved here to prevent Suffragium from ending if skill fails
 	if (!(skill_get_castnodex(skill_num, skill_lv)&2)) 
 		casttime = skill_castfix_sc(src, casttime, skill_num, skill_lv);
-
+	// in official this is triggered even if no cast time.
+	clif_skillcasting(src, src->id, target_id, 0,0, skill_num, skill_get_ele(skill_num, skill_lv), casttime);
 	if( casttime > 0 || temp )
 	{ 
 		unit_stop_walking(src,1);
-		clif_skillcasting(src, src->id, target_id, 0,0, skill_num, skill_get_ele(skill_num, skill_lv), casttime);
 
 		if (sd && target->type == BL_MOB)
 		{
@@ -1318,8 +1318,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 		} else if( sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4&4) && skill_num != GC_CLOAKINGEXCEED ) {
 			status_change_end(src,SC_CLOAKINGEXCEED, INVALID_TIMER);
 			if (!src->prev) return 0;
-		} else if( sc->data[SC_CAMOUFLAGE] && skill_num != RA_CAMOUFLAGE )
-			status_change_end(src,SC_CAMOUFLAGE,INVALID_TIMER);
+		}
 	}
 
 
@@ -1440,13 +1439,13 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh
 		} else if (sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4&4)) {
 			status_change_end(src, SC_CLOAKINGEXCEED, INVALID_TIMER);
 			if (!src->prev) return 0;
-		} else if( sc->data[SC_CAMOUFLAGE] && skill_num != RA_CAMOUFLAGE )
-			status_change_end(src,SC_CAMOUFLAGE,INVALID_TIMER);
+		}
 	}
+	// in official this is triggered even if no cast time.
+	clif_skillcasting(src, src->id, 0, skill_x, skill_y, skill_num, skill_get_ele(skill_num, skill_lv), casttime);
 	if( casttime > 0 )
 	{
 		unit_stop_walking(src,1);
-		clif_skillcasting(src, src->id, 0, skill_x, skill_y, skill_num, skill_get_ele(skill_num, skill_lv), casttime);
 		ud->skilltimer = add_timer( tick+casttime, skill_castend_pos, src->id, 0 );
 		if( (sd && pc_checkskill(sd,SA_FREECAST) > 0) || skill_num == LG_EXEEDBREAK)
 			status_calc_bl(&sd->bl, SCB_SPEED);