summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrud0lp20 <rud0lp20@54d463be-8e91-2dee-dedb-b68131a5f0ec>2012-07-23 15:00:12 +0000
committerrud0lp20 <rud0lp20@54d463be-8e91-2dee-dedb-b68131a5f0ec>2012-07-23 15:00:12 +0000
commit98cabc236656a475473c7b4c07a81210a1eb9541 (patch)
tree4fadf225f15bce90e3924f60da00997b0e5b28bc /src
parent211a15e56f8ec2344790421930024d2eb401f291 (diff)
downloadhercules-98cabc236656a475473c7b4c07a81210a1eb9541.tar.gz
hercules-98cabc236656a475473c7b4c07a81210a1eb9541.tar.bz2
hercules-98cabc236656a475473c7b4c07a81210a1eb9541.tar.xz
hercules-98cabc236656a475473c7b4c07a81210a1eb9541.zip
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://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16483 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src')
-rw-r--r--src/map/battle.c121
-rw-r--r--src/map/pc.c3
-rw-r--r--src/map/skill.c227
-rw-r--r--src/map/skill.h1
-rw-r--r--src/map/status.c33
-rw-r--r--src/map/unit.c13
6 files changed, 263 insertions, 135 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index a9c8ba6ea..a04f3c328 100644
--- a/src/map/battle.c
+++ b/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.
diff --git a/src/map/pc.c b/src/map/pc.c
index f918ce9ca..007c4ee67 100644
--- a/src/map/pc.c
+++ b/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,
diff --git a/src/map/skill.c b/src/map/skill.c
index 458cf7518..2eb778f8c 100644
--- a/src/map/skill.c
+++ b/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;
diff --git a/src/map/skill.h b/src/map/skill.h
index 8a7af1509..f9f5607e4 100644
--- a/src/map/skill.h
+++ b/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;
diff --git a/src/map/status.c b/src/map/status.c
index f6a5e5997..541123050 100644
--- a/src/map/status.c
+++ b/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))
diff --git a/src/map/unit.c b/src/map/unit.c
index 53ad02d8a..63b2805fb 100644
--- a/src/map/unit.c
+++ b/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);