|
@@ -1295,7 +1295,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
|
|
|
const int pos[5] = { EQP_WEAPON, EQP_HELM, EQP_SHIELD, EQP_ARMOR, EQP_ACC };
|
|
|
|
|
|
for( i = 0; i < skill_lv; i++ )
|
|
|
- skill_strip_equip(src,bl,pos[i],(5 + skill_lv) * skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv));
|
|
|
+ skill_strip_equip(src,bl,pos[i],6 * skill_lv + status_get_lv(src) / 4 + status_get_dex(src) / 10,skill_lv,skill_get_time2(skill_id,skill_lv));
|
|
|
}
|
|
|
break;
|
|
|
case WL_JACKFROST:
|
|
@@ -1725,15 +1725,17 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
|
|
|
if( rate )
|
|
|
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,
|
|
|
- 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,
|
|
|
- 0, 0, 0, sd->mdef_set_race[tstatus->race].tick, 2);
|
|
|
+ if (sd && !skill_id && bl->type == BL_PC) { // This effect does not work with skills.
|
|
|
+ if (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,
|
|
|
+ 0, 0, 0, sd->def_set_race[tstatus->race].tick, 2);
|
|
|
+ if (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,
|
|
|
+ 0, 0, 0, sd->mdef_set_race[tstatus->race].tick, 2);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- if( sd && sd->ed && sc && !status_isdead(bl) && !skill_id ){
|
|
|
+ if( sd && sd->ed && sc && !status_isdead(bl) && !skill_id ) {
|
|
|
struct unit_data *ud = unit_bl2ud(src);
|
|
|
|
|
|
if( sc->data[SC_WILD_STORM_OPTION] )
|
|
@@ -2376,8 +2378,18 @@ 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 )
|
|
|
- return 0; // ankle snare cannot be knocked back
|
|
|
+
|
|
|
+ if (su && su->group) {
|
|
|
+ switch (su->group->unit_id) {
|
|
|
+ case UNT_ICEWALL:
|
|
|
+ case UNT_ANKLESNARE:
|
|
|
+ case UNT_ELECTRICSHOCKER:
|
|
|
+ case UNT_REVERBERATION:
|
|
|
+ case UNT_NETHERWORLD:
|
|
|
+ case UNT_WALLOFTHORN:
|
|
|
+ return 0; //Cannot be knocked back
|
|
|
+ }
|
|
|
+ }
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -3059,11 +3071,6 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
|
|
|
skill_addtimerskill(src, tick + 300 * ((flag&2) ? 1 : 2), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|4);
|
|
|
}
|
|
|
break;
|
|
|
- case GN_WALLOFTHORN:
|
|
|
- unit_stop_walking(bl,1);
|
|
|
- skill_blown(dsrc,bl,dmg.blewcount,dir, 0x2 );
|
|
|
- clif_fixpos(bl);
|
|
|
- break;
|
|
|
default:
|
|
|
skill_blown(dsrc,bl,dmg.blewcount,dir, 0x0 );
|
|
|
if ( !dmg.blewcount && bl->type == BL_SKILL && damage > 0 ){
|
|
@@ -9044,7 +9051,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
|
case SC_UNLUCKY:
|
|
|
case SC_WEAKNESS:
|
|
|
if( !(tsc && tsc->data[type]) ) {
|
|
|
- int rate = status_get_lv(src) / 10 + rnd_value(sstatus->dex / 12, sstatus->dex / 4) + ( sd ? sd->status.job_level : 50 ) + 10 * skill_lv
|
|
|
+ int rate;
|
|
|
+
|
|
|
+ if (is_boss(bl))
|
|
|
+ break;
|
|
|
+ rate = status_get_lv(src) / 10 + rnd_value(sstatus->dex / 12, sstatus->dex / 4) + ( sd ? sd->status.job_level : 50 ) + 10 * skill_lv
|
|
|
- (status_get_lv(bl) / 10 + rnd_value(tstatus->agi / 6, tstatus->agi / 3) + tstatus->luk / 10 + ( dstsd ? (dstsd->max_weight / 10 - dstsd->weight / 10 ) / 100 : 0));
|
|
|
rate = cap_value(rate, skill_lv + sstatus->dex / 20, 100);
|
|
|
clif_skill_nodamage(src,bl,skill_id,0,sc_start(src,bl,type,rate,skill_lv,skill_get_time(skill_id,skill_lv)));
|
|
@@ -9054,7 +9065,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
|
|
|
|
case SC_IGNORANCE:
|
|
|
if( !(tsc && tsc->data[type]) ) {
|
|
|
- int rate = status_get_lv(src) / 10 + rnd_value(sstatus->dex / 12, sstatus->dex / 4) + ( sd ? sd->status.job_level : 50 ) + 10 * skill_lv
|
|
|
+ int rate;
|
|
|
+
|
|
|
+ if (is_boss(bl))
|
|
|
+ break;
|
|
|
+ rate = status_get_lv(src) / 10 + rnd_value(sstatus->dex / 12, sstatus->dex / 4) + ( sd ? sd->status.job_level : 50 ) + 10 * skill_lv
|
|
|
- (status_get_lv(bl) / 10 + rnd_value(tstatus->agi / 6, tstatus->agi / 3) + tstatus->luk / 10 + ( dstsd ? (dstsd->max_weight / 10 - dstsd->weight / 10 ) / 100 : 0));
|
|
|
rate = cap_value(rate, skill_lv + sstatus->dex / 20, 100);
|
|
|
if (clif_skill_nodamage(src,bl,skill_id,0,sc_start(src,bl,type,rate,skill_lv,skill_get_time(skill_id,skill_lv)))) {
|
|
@@ -10823,7 +10838,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|
|
case WM_POEMOFNETHERWORLD:
|
|
|
case SO_PSYCHIC_WAVE:
|
|
|
case SO_VACUUM_EXTREME:
|
|
|
- case GN_WALLOFTHORN:
|
|
|
case GN_THORNS_TRAP:
|
|
|
case GN_DEMONIC_FIRE:
|
|
|
case GN_HELLS_PLANT:
|
|
@@ -11276,6 +11290,19 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|
|
skill_unitsetting(src,skill_id,skill_lv,x,y,0);
|
|
|
break;
|
|
|
|
|
|
+ case GN_WALLOFTHORN: {
|
|
|
+ static const int dx[] = {-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2, 2, 2, 1, 0};
|
|
|
+ static const int dy[] = { 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2};
|
|
|
+ struct unit_data *ud = unit_bl2ud(src);
|
|
|
+
|
|
|
+ for (i = 0; i < 16; i++) {
|
|
|
+ x = ud->skillx + dx[i];
|
|
|
+ y = ud->skilly + dy[i];
|
|
|
+ skill_unitsetting(src, skill_id, skill_lv, x, y, 0);
|
|
|
+ }
|
|
|
+ flag |= 1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
case GN_CRAZYWEED: {
|
|
|
int area = skill_get_splash(GN_CRAZYWEED_ATK, skill_lv);
|
|
|
for( i = 0; i < 3 + (skill_lv/2); i++ ) {
|
|
@@ -12109,6 +12136,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
|
|
val2 = 0;
|
|
|
break;
|
|
|
case WM_REVERBERATION:
|
|
|
+ case WM_POEMOFNETHERWORLD:
|
|
|
val1 = 1 + skill_lv;
|
|
|
break;
|
|
|
case GN_WALLOFTHORN:
|
|
@@ -12366,13 +12394,6 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
|
|
|
skill_blown(ss,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0);
|
|
|
break;
|
|
|
|
|
|
- case UNT_WALLOFTHORN:
|
|
|
- if( status_get_mode(bl)&MD_BOSS )
|
|
|
- break; // iRO Wiki says that this skill don't affect to Boss monsters.
|
|
|
- if( map_flag_vs(bl->m) || bl->id == src->bl.id || battle_check_target(&src->bl,bl, BCT_ENEMY) == 1 )
|
|
|
- skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
|
|
|
- break;
|
|
|
-
|
|
|
case UNT_FIRE_EXPANSION_SMOKE_POWDER:
|
|
|
if( !sce )
|
|
|
sc_start(ss, bl, type, 100, sg->skill_lv, sg->limit);
|
|
@@ -12463,7 +12484,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
|
|
int count=0;
|
|
|
const int x = bl->x, y = bl->y;
|
|
|
|
|
|
- if( sg->skill_id == GN_WALLOFTHORN && !map_flag_vs(bl->m) )
|
|
|
+ if (skill_id == GN_WALLOFTHORN && battle_check_target(ss, bl, BCT_ENEMY) <= 0)
|
|
|
break;
|
|
|
|
|
|
//Take into account these hit more times than the timer interval can handle.
|
|
@@ -12942,9 +12963,12 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
|
|
skill_attack(BF_WEAPON,ss,&src->bl,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0);
|
|
|
break;
|
|
|
case UNT_NETHERWORLD:
|
|
|
- if( !(status_get_mode(bl)&MD_BOSS) || (!map_flag_gvg2(ss->m) && battle_check_target(&src->bl,bl,BCT_PARTY) < 0) ) {
|
|
|
- if( !(tsc && tsc->data[type]) )
|
|
|
+ if (!(status_get_mode(bl)&MD_BOSS) || (!map_flag_gvg2(ss->m) && battle_check_target(&src->bl,bl,BCT_PARTY) < 0)) {
|
|
|
+ if (!(tsc && tsc->data[type])) {
|
|
|
sc_start(ss, bl, type, 100, sg->skill_lv, skill_get_time2(sg->skill_id,sg->skill_lv));
|
|
|
+ sg->limit = DIFF_TICK(tick,sg->tick);
|
|
|
+ sg->unit_id = UNT_USED_TRAPS;
|
|
|
+ }
|
|
|
}
|
|
|
break;
|
|
|
case UNT_THORNS_TRAP:
|
|
@@ -12966,6 +12990,17 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
+ case UNT_WALLOFTHORN:
|
|
|
+ if (status_get_mode(bl)&MD_BOSS)
|
|
|
+ break; // This skill doesn't affect to Boss monsters. [iRO Wiki]
|
|
|
+ if (battle_check_target(ss, bl, BCT_ENEMY) <= 0) {
|
|
|
+ unit_stop_walking(bl, 1);
|
|
|
+ skill_blown(&src->bl, bl, skill_get_blewcount(sg->skill_id, sg->skill_lv), unit_getdir(bl), 0x2);
|
|
|
+ clif_fixpos(bl);
|
|
|
+ } else
|
|
|
+ skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
|
|
|
+ break;
|
|
|
+
|
|
|
case UNT_DEMONIC_FIRE:
|
|
|
switch( sg->val2 ) {
|
|
|
case 1:
|
|
@@ -13004,13 +13039,18 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
+ case UNT_ZEPHYR:
|
|
|
+ if (ss == bl)
|
|
|
+ break; // Doesn't affect the Elemental
|
|
|
+ sc_start(ss, bl, type, 100, sg->skill_lv, sg->interval);
|
|
|
+ break;
|
|
|
+
|
|
|
case UNT_FIRE_INSIGNIA:
|
|
|
case UNT_WATER_INSIGNIA:
|
|
|
case UNT_WIND_INSIGNIA:
|
|
|
case UNT_EARTH_INSIGNIA:
|
|
|
- case UNT_ZEPHYR:
|
|
|
- sc_start(ss, bl,type, 100, sg->skill_lv, sg->interval);
|
|
|
- if (sg->unit_id != UNT_ZEPHYR && !battle_check_undead(tstatus->race, tstatus->def_ele)) {
|
|
|
+ sc_start(ss, bl, type, 100, sg->skill_lv, sg->interval);
|
|
|
+ if (!battle_check_undead(tstatus->race, tstatus->def_ele)) {
|
|
|
int hp = tstatus->max_hp / 100; //+1% each 5s
|
|
|
if ((sg->val3) % 5) { //each 5s
|
|
|
if (tstatus->def_ele == skill_get_ele(sg->skill_id,sg->skill_lv)){
|
|
@@ -13409,6 +13449,7 @@ int64 skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl, int64
|
|
|
case UNT_ICEWALL:
|
|
|
case UNT_REVERBERATION:
|
|
|
case UNT_WALLOFTHORN:
|
|
|
+ case UNT_NETHERWORLD:
|
|
|
src->val1-=(int)cap_value(damage,INT_MIN,INT_MAX);
|
|
|
break;
|
|
|
default:
|
|
@@ -16307,7 +16348,15 @@ static int skill_trap_splash (struct block_list *bl, va_list ap)
|
|
|
skill_blown(src,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),-1,0);
|
|
|
break;
|
|
|
case UNT_ELECTRICSHOCKER:
|
|
|
- clif_skill_damage(src,bl,tick,0,0,-30000,1,sg->skill_id,sg->skill_lv,5);
|
|
|
+ if (bl->id != ss->id) {
|
|
|
+ if (status_get_mode(bl)&MD_BOSS)
|
|
|
+ break;
|
|
|
+ if (status_change_start(ss, bl, SC_ELECTRICSHOCKER, 10000, sg->skill_lv, sg->group_id, 0, 0, skill_get_time2(sg->skill_id, sg->skill_lv), 8)) {
|
|
|
+ map_moveblock(bl, unit->bl.x, unit->bl.y, tick);
|
|
|
+ clif_fixpos(bl);
|
|
|
+ clif_skill_damage(src, bl, tick, 0, 0, -30000, 1, sg->skill_id, sg->skill_lv, 5);
|
|
|
+ }
|
|
|
+ }
|
|
|
break;
|
|
|
case UNT_MAGENTATRAP:
|
|
|
case UNT_COBALTTRAP:
|
|
@@ -17054,12 +17103,14 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
|
|
|
break;
|
|
|
|
|
|
case UNT_REVERBERATION:
|
|
|
+ case UNT_NETHERWORLD:
|
|
|
if( unit->val1 <= 0 ) { // If it was deactivated.
|
|
|
skill_delunit(unit);
|
|
|
break;
|
|
|
}
|
|
|
clif_changetraplook(bl,UNT_USED_TRAPS);
|
|
|
- map_foreachinrange(skill_trap_splash, bl, skill_get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick);
|
|
|
+ if (group->unit_id == UNT_REVERBERATION)
|
|
|
+ map_foreachinrange(skill_trap_splash, bl, skill_get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick);
|
|
|
group->limit = DIFF_TICK(tick,group->tick)+1000;
|
|
|
unit->limit = DIFF_TICK(tick,group->tick)+1000;
|
|
|
group->unit_id = UNT_USED_TRAPS;
|
|
@@ -17123,9 +17174,11 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
|
|
|
}
|
|
|
break;
|
|
|
case UNT_REVERBERATION:
|
|
|
- if( unit->val1 <= 0 ){
|
|
|
+ case UNT_NETHERWORLD:
|
|
|
+ if (unit->val1 <= 0) {
|
|
|
clif_changetraplook(bl,UNT_USED_TRAPS);
|
|
|
- map_foreachinrange(skill_trap_splash, bl, skill_get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick);
|
|
|
+ if (group->unit_id == UNT_REVERBERATION)
|
|
|
+ map_foreachinrange(skill_trap_splash, bl, skill_get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick);
|
|
|
group->limit = DIFF_TICK(tick,group->tick)+1000;
|
|
|
unit->limit = DIFF_TICK(tick,group->tick)+1000;
|
|
|
group->unit_id = UNT_USED_TRAPS;
|
|
@@ -17331,9 +17384,6 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 d
|
|
|
if (skill_get_unit_flag(group->skill_id)&UF_ENSEMBLE)
|
|
|
return 0; //Ensembles may not be moved around.
|
|
|
|
|
|
- if( group->unit_id == UNT_ICEWALL || group->unit_id == UNT_WALLOFTHORN )
|
|
|
- return 0; //Icewalls and Wall of Thorns don't get knocked back
|
|
|
-
|
|
|
m_flag = (int *) aCalloc(group->unit_count, sizeof(int));
|
|
|
// m_flag
|
|
|
// 0: Neither of the following (skill_unit_onplace & skill_unit_onout are needed)
|
|
@@ -18819,14 +18869,6 @@ void skill_init_unit_layout (void) {
|
|
|
pos++;
|
|
|
}
|
|
|
break;
|
|
|
- case GN_WALLOFTHORN: {
|
|
|
- static const int dx[] = {-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2, 2, 2, 1, 0};
|
|
|
- static const int dy[] = { 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2};
|
|
|
- skill_unit_layout[pos].count = 16;
|
|
|
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
|
|
|
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
|
|
|
- }
|
|
|
- break;
|
|
|
default:
|
|
|
ShowError("unknown unit layout at skill %d\n",i);
|
|
|
break;
|