|
@@ -482,6 +482,11 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
|
|
hp += hp * skill * 2 / 100;
|
|
hp += hp * skill * 2 / 100;
|
|
if( sd && tsd && sd->status.partner_id == tsd->status.char_id && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0 )
|
|
if( sd && tsd && sd->status.partner_id == tsd->status.char_id && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0 )
|
|
hp *= 2;
|
|
hp *= 2;
|
|
|
|
+ if (sd && ((skill = pc_checkskill(sd, SU_POWEROFSEA)) > 0)) {
|
|
|
|
+ hp += hp * 10 / 100;
|
|
|
|
+ if (pc_checkskill(sd, SU_TUNABELLY) == 5 && pc_checkskill(sd, SU_TUNAPARTY) == 5 && pc_checkskill(sd, SU_BUNCHOFSHRIMP) == 5 && pc_checkskill(sd, SU_FRESHSHRIMP) == 5)
|
|
|
|
+ hp += hp * 20 / 100;
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -916,6 +921,15 @@ struct s_skill_nounit_layout* skill_get_nounit_layout(uint16 skill_id, uint16 sk
|
|
return &skill_nounit_layout[0];
|
|
return &skill_nounit_layout[0];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/** Stores temporary values.
|
|
|
|
+ * Common usages:
|
|
|
|
+ * [0] holds number of targets in area
|
|
|
|
+ * [1] holds the id of the original target
|
|
|
|
+ * [2] counts how many targets have been processed. counter is added in skill_area_sub if the foreach function flag is: flag&(SD_SPLASH|SD_PREAMBLE)
|
|
|
|
+ */
|
|
|
|
+static int skill_area_temp[8];
|
|
|
|
+static int64 skill_area_temp_i64[1];
|
|
|
|
+
|
|
/*==========================================
|
|
/*==========================================
|
|
* Add effect to skill when hit succesfully target
|
|
* Add effect to skill when hit succesfully target
|
|
*------------------------------------------*/
|
|
*------------------------------------------*/
|
|
@@ -1793,6 +1807,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
|
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
|
|
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
|
|
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
|
|
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
|
|
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT:
|
|
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT:
|
|
|
|
+ case SC_SPRITEMABLE: case SC_BITESCAR:
|
|
continue;
|
|
continue;
|
|
case SC_WHISTLE: case SC_ASSNCROS: case SC_POEMBRAGI:
|
|
case SC_WHISTLE: case SC_ASSNCROS: case SC_POEMBRAGI:
|
|
case SC_APPLEIDUN: case SC_HUMMING: case SC_DONTFORGETME:
|
|
case SC_APPLEIDUN: case SC_HUMMING: case SC_DONTFORGETME:
|
|
@@ -1831,6 +1846,23 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
|
sc_start(src,bl,SC_STUN,100,skill_lv,skill_get_time2(skill_id,skill_lv));
|
|
sc_start(src,bl,SC_STUN,100,skill_lv,skill_get_time2(skill_id,skill_lv));
|
|
status_change_end(bl, SC_C_MARKER, INVALID_TIMER);
|
|
status_change_end(bl, SC_C_MARKER, INVALID_TIMER);
|
|
break;
|
|
break;
|
|
|
|
+ case SU_SCRATCH:
|
|
|
|
+ sc_start2(src, bl, SC_BLEEDING, (skill_lv * 3), skill_lv, src->id, skill_get_time(skill_id, skill_lv)); // TODO: What's the chance/time?
|
|
|
|
+ break;
|
|
|
|
+ case SU_SV_STEMSPEAR:
|
|
|
|
+ sc_start2(src, bl, SC_BLEEDING, 10, skill_lv, src->id, skill_get_time(skill_id, skill_lv));
|
|
|
|
+ break;
|
|
|
|
+ case SU_CN_METEOR:
|
|
|
|
+ if (skill_area_temp[3] == 1)
|
|
|
|
+ sc_start(src, bl, SC_CURSE, 10, skill_lv, skill_get_time2(skill_id, skill_lv)); // TODO: What's the chance/time?
|
|
|
|
+ break;
|
|
|
|
+ //case SU_SCAROFTAROU:
|
|
|
|
+ // sc_start(src, bl, SC_STUN, 10, skill_lv, skill_get_time2(skill_id, skill_lv)); // TODO: What's the chance/time?
|
|
|
|
+ // break;
|
|
|
|
+ case SU_LUNATICCARROTBEAT:
|
|
|
|
+ if (skill_area_temp[3] == 1)
|
|
|
|
+ sc_start(src, bl, SC_STUN, 10, skill_lv, skill_get_time(skill_id, skill_lv)); // TODO: What's the chance/time?
|
|
|
|
+ break;
|
|
} //end switch skill_id
|
|
} //end switch skill_id
|
|
|
|
|
|
if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai)
|
|
if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai)
|
|
@@ -2506,15 +2538,6 @@ int skill_strip_equip(struct block_list *src,struct block_list *bl, unsigned sho
|
|
return where?1:0;
|
|
return where?1:0;
|
|
}
|
|
}
|
|
|
|
|
|
-/** Stores temporary values.
|
|
|
|
- * Common usages:
|
|
|
|
- * [0] holds number of targets in area
|
|
|
|
- * [1] holds the id of the original target
|
|
|
|
- * [2] counts how many targets have been processed. counter is added in skill_area_sub if the foreach function flag is: flag&(SD_SPLASH|SD_PREAMBLE)
|
|
|
|
- */
|
|
|
|
-static int skill_area_temp[8];
|
|
|
|
-static int64 skill_area_temp_i64[1];
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
Used to knock back players, monsters, traps, etc
|
|
Used to knock back players, monsters, traps, etc
|
|
* @param src Object that give knock back
|
|
* @param src Object that give knock back
|
|
@@ -2535,6 +2558,7 @@ short skill_blown(struct block_list* src, struct block_list* target, char count,
|
|
{
|
|
{
|
|
int dx = 0, dy = 0;
|
|
int dx = 0, dy = 0;
|
|
uint8 reason = 0, checkflag = 0;
|
|
uint8 reason = 0, checkflag = 0;
|
|
|
|
+ struct status_change *tsc = status_get_sc(target);
|
|
|
|
|
|
nullpo_ret(src);
|
|
nullpo_ret(src);
|
|
nullpo_ret(target);
|
|
nullpo_ret(target);
|
|
@@ -2569,6 +2593,9 @@ short skill_blown(struct block_list* src, struct block_list* target, char count,
|
|
dy = -diry[dir];
|
|
dy = -diry[dir];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (tsc && tsc->data[SC_SU_STOOP]) // Any knockback will cancel it.
|
|
|
|
+ status_change_end(target, SC_SU_STOOP, INVALID_TIMER);
|
|
|
|
+
|
|
return unit_blown(target, dx, dy, count, flag); // Send over the proper flag
|
|
return unit_blown(target, dx, dy, count, flag); // Send over the proper flag
|
|
}
|
|
}
|
|
|
|
|
|
@@ -4083,6 +4110,7 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data)
|
|
switch( skl->skill_id )
|
|
switch( skl->skill_id )
|
|
{
|
|
{
|
|
case WZ_METEOR:
|
|
case WZ_METEOR:
|
|
|
|
+ case SU_CN_METEOR:
|
|
if( skl->type >= 0 )
|
|
if( skl->type >= 0 )
|
|
{
|
|
{
|
|
int x = skl->type>>16, y = skl->type&0xFFFF;
|
|
int x = skl->type>>16, y = skl->type&0xFFFF;
|
|
@@ -4617,6 +4645,14 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
|
|
skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case SU_PICKYPECK:
|
|
|
|
+ clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
|
|
|
+ case SU_BITE:
|
|
|
|
+ skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
|
|
|
|
+ if (status_get_lv(src) >= 30 && (rnd() % 100 < (int)(status_get_lv(src) / 30) + 10)) // TODO: Need activation chance.
|
|
|
|
+ skill_addtimerskill(src, tick + skill_get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag);
|
|
|
|
+ break;
|
|
|
|
+
|
|
//Splash attack skills.
|
|
//Splash attack skills.
|
|
case AS_GRIMTOOTH:
|
|
case AS_GRIMTOOTH:
|
|
case MC_CARTREVOLUTION:
|
|
case MC_CARTREVOLUTION:
|
|
@@ -4672,6 +4708,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
case RL_R_TRIP:
|
|
case RL_R_TRIP:
|
|
case MH_XENO_SLASHER:
|
|
case MH_XENO_SLASHER:
|
|
case NC_ARMSCANNON:
|
|
case NC_ARMSCANNON:
|
|
|
|
+ case SU_SCRATCH:
|
|
|
|
+ case SU_LUNATICCARROTBEAT:
|
|
if( flag&1 ) {//Recursive invocation
|
|
if( flag&1 ) {//Recursive invocation
|
|
int sflag = skill_area_temp[0] & 0xFFF;
|
|
int sflag = skill_area_temp[0] & 0xFFF;
|
|
int heal = 0;
|
|
int heal = 0;
|
|
@@ -4690,6 +4728,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
clif_skill_nodamage(NULL, src, AL_HEAL, heal, 1);
|
|
clif_skill_nodamage(NULL, src, AL_HEAL, heal, 1);
|
|
status_heal(src,heal,0,0);
|
|
status_heal(src,heal,0,0);
|
|
}
|
|
}
|
|
|
|
+ if (skill_id == SU_SCRATCH && status_get_lv(src) >= 30 && (rnd() % 100 < (int)(status_get_lv(src) / 30) + 10)) // TODO: Need activation chance.
|
|
|
|
+ skill_addtimerskill(src, tick + skill_get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag);
|
|
} else {
|
|
} else {
|
|
int starget = splash_target(src);
|
|
int starget = splash_target(src);
|
|
|
|
|
|
@@ -4698,8 +4738,11 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
skill_area_temp[2] = 0;
|
|
skill_area_temp[2] = 0;
|
|
|
|
|
|
switch ( skill_id ) {
|
|
switch ( skill_id ) {
|
|
|
|
+ case SU_LUNATICCARROTBEAT:
|
|
|
|
+ skill_area_temp[3] = 0;
|
|
case LG_EARTHDRIVE:
|
|
case LG_EARTHDRIVE:
|
|
case GN_CARTCANNON:
|
|
case GN_CARTCANNON:
|
|
|
|
+ case SU_SCRATCH:
|
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
break;
|
|
break;
|
|
case LG_MOONSLASHER:
|
|
case LG_MOONSLASHER:
|
|
@@ -4737,6 +4780,15 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
map_foreachinshootrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), starget, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id);
|
|
map_foreachinshootrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), starget, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id);
|
|
else
|
|
else
|
|
map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), starget, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id);
|
|
map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), starget, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id);
|
|
|
|
+
|
|
|
|
+ if (sd && skill_id == SU_LUNATICCARROTBEAT) {
|
|
|
|
+ short item_idx = pc_search_inventory(sd, ITEMID_CARROT);
|
|
|
|
+
|
|
|
|
+ if (item_idx >= 0) {
|
|
|
|
+ pc_delitem(sd, item_idx, 1, 0, 1, LOG_TYPE_CONSUME);
|
|
|
|
+ skill_area_temp[3] = 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
if( skill_id == AS_SPLASHER ) {
|
|
if( skill_id == AS_SPLASHER ) {
|
|
map_freeblock_unlock(); // Don't consume a second gemstone.
|
|
map_freeblock_unlock(); // Don't consume a second gemstone.
|
|
return 0;
|
|
return 0;
|
|
@@ -5719,6 +5771,14 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case SU_SCAROFTAROU:
|
|
|
|
+ sc_start(src, bl, status_skill2sc(skill_id), 10, skill_lv, skill_get_time(skill_id, skill_lv)); // TODO: What's the activation chance for the Bite effect?
|
|
|
|
+ case SU_SV_STEMSPEAR:
|
|
|
|
+ skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
|
|
|
|
+ if (status_get_lv(src) >= 30 && (rnd() % 100 < (int)(status_get_lv(src) / 30) + 10)) // TODO: Need activation chance.
|
|
|
|
+ skill_addtimerskill(src, tick + skill_get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, (skill_id == SU_SV_STEMSPEAR) ? BF_MAGIC : BF_WEAPON, flag);
|
|
|
|
+ break;
|
|
|
|
+
|
|
case 0:/* no skill - basic/normal attack */
|
|
case 0:/* no skill - basic/normal attack */
|
|
if(sd) {
|
|
if(sd) {
|
|
if (flag & 3){
|
|
if (flag & 3){
|
|
@@ -5912,6 +5972,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAYNIGHTFEVER])
|
|
else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAYNIGHTFEVER])
|
|
heal = 0; //Needed so that it actually displays 0 when healing.
|
|
heal = 0; //Needed so that it actually displays 0 when healing.
|
|
}
|
|
}
|
|
|
|
+ if (skill_id == AL_HEAL)
|
|
|
|
+ status_change_end(bl, SC_BITESCAR, INVALID_TIMER);
|
|
clif_skill_nodamage (src, bl, skill_id, heal, 1);
|
|
clif_skill_nodamage (src, bl, skill_id, heal, 1);
|
|
if( tsc && tsc->data[SC_AKAITSUKI] && heal && skill_id != HLIF_HEAL )
|
|
if( tsc && tsc->data[SC_AKAITSUKI] && heal && skill_id != HLIF_HEAL )
|
|
heal = ~heal + 1;
|
|
heal = ~heal + 1;
|
|
@@ -6299,6 +6361,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
|
|
|
|
case PR_KYRIE:
|
|
case PR_KYRIE:
|
|
case MER_KYRIE:
|
|
case MER_KYRIE:
|
|
|
|
+ case SU_TUNAPARTY:
|
|
clif_skill_nodamage(bl,bl,skill_id,skill_lv,
|
|
clif_skill_nodamage(bl,bl,skill_id,skill_lv,
|
|
sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)));
|
|
sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)));
|
|
break;
|
|
break;
|
|
@@ -6409,10 +6472,17 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
case RL_HEAT_BARREL:
|
|
case RL_HEAT_BARREL:
|
|
case RL_P_ALTER:
|
|
case RL_P_ALTER:
|
|
case RL_E_CHAIN:
|
|
case RL_E_CHAIN:
|
|
|
|
+ case SU_FRESHSHRIMP:
|
|
|
|
+ case SU_ARCLOUSEDASH:
|
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,
|
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,
|
|
sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)));
|
|
sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)));
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case SU_STOOP:
|
|
|
|
+ clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
|
|
|
+ sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
|
|
|
+ break;
|
|
|
|
+
|
|
case KN_AUTOCOUNTER:
|
|
case KN_AUTOCOUNTER:
|
|
sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv));
|
|
sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv));
|
|
skill_addtimerskill(src,tick + 100,bl->id,0,0,skill_id,skill_lv,BF_WEAPON,flag);
|
|
skill_addtimerskill(src,tick + 100,bl->id,0,0,skill_id,skill_lv,BF_WEAPON,flag);
|
|
@@ -7104,6 +7174,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
status_change_end(bl, SC_SILENCE, INVALID_TIMER);
|
|
status_change_end(bl, SC_SILENCE, INVALID_TIMER);
|
|
status_change_end(bl, SC_BLIND, INVALID_TIMER);
|
|
status_change_end(bl, SC_BLIND, INVALID_TIMER);
|
|
status_change_end(bl, SC_CONFUSION, INVALID_TIMER);
|
|
status_change_end(bl, SC_CONFUSION, INVALID_TIMER);
|
|
|
|
+ status_change_end(bl, SC_BITESCAR, INVALID_TIMER);
|
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
break;
|
|
break;
|
|
|
|
|
|
@@ -7646,6 +7717,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
|
|
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
|
|
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
|
|
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
|
|
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT:
|
|
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT:
|
|
|
|
+ case SC_SPRITEMABLE: case SC_BITESCAR:
|
|
continue;
|
|
continue;
|
|
//bugreport:4888 these songs may only be dispelled if you're not in their song area anymore
|
|
//bugreport:4888 these songs may only be dispelled if you're not in their song area anymore
|
|
case SC_WHISTLE:
|
|
case SC_WHISTLE:
|
|
@@ -9153,6 +9225,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
|
|
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
|
|
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
|
|
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
|
|
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT:
|
|
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT:
|
|
|
|
+ case SC_SPRITEMABLE:
|
|
continue;
|
|
continue;
|
|
case SC_ASSUMPTIO:
|
|
case SC_ASSUMPTIO:
|
|
if( bl->type == BL_MOB )
|
|
if( bl->type == BL_MOB )
|
|
@@ -9523,6 +9596,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
|
|
clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
|
|
if (rnd()%100 < (25 + 25 * skill_lv))
|
|
if (rnd()%100 < (25 + 25 * skill_lv))
|
|
map_foreachinrange(skill_destroy_trap,bl,skill_get_splash(skill_id,skill_lv),BL_SKILL,tick);
|
|
map_foreachinrange(skill_destroy_trap,bl,skill_get_splash(skill_id,skill_lv),BL_SKILL,tick);
|
|
|
|
+ status_change_end(bl, SC_SV_ROOTTWIST, INVALID_TIMER);
|
|
break;
|
|
break;
|
|
|
|
|
|
case LG_REFLECTDAMAGE:
|
|
case LG_REFLECTDAMAGE:
|
|
@@ -10721,6 +10795,37 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case SU_HIDE:
|
|
|
|
+ if (tsce) {
|
|
|
|
+ clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
|
|
|
+ status_change_end(bl, type, INVALID_TIMER);
|
|
|
|
+ map_freeblock_unlock();
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
|
|
|
+ sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SU_TUNABELLY:
|
|
|
|
+ {
|
|
|
|
+ int heal;
|
|
|
|
+
|
|
|
|
+ if (!dstmd || dstmd->mob_id != MOBID_EMPERIUM || !mob_is_battleground(dstmd)) {
|
|
|
|
+ heal = ((2 * skill_lv - 1) * 10) * status_get_max_hp(bl) / 100;
|
|
|
|
+ status_heal(bl, heal, 0, 0);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ clif_skill_nodamage(src, bl, skill_id, heal, 1);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SU_BUNCHOFSHRIMP:
|
|
|
|
+ if (sd == NULL || sd->status.party_id == 0 || flag&1)
|
|
|
|
+ clif_skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)));
|
|
|
|
+ else if (sd)
|
|
|
|
+ party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id);
|
|
|
|
+ break;
|
|
|
|
+
|
|
default:
|
|
default:
|
|
ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skill_id);
|
|
ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skill_id);
|
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
@@ -10964,6 +11069,8 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
|
|
}
|
|
}
|
|
case GN_WALLOFTHORN:
|
|
case GN_WALLOFTHORN:
|
|
case SC_ESCAPE:
|
|
case SC_ESCAPE:
|
|
|
|
+ case SU_CN_POWDERING:
|
|
|
|
+ case SU_SV_ROOTTWIST:
|
|
ud->skillx = target->x;
|
|
ud->skillx = target->x;
|
|
ud->skilly = target->y;
|
|
ud->skilly = target->y;
|
|
ud->skilltimer = tid;
|
|
ud->skilltimer = tid;
|
|
@@ -11347,6 +11454,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|
case LG_EARTHDRIVE:
|
|
case LG_EARTHDRIVE:
|
|
case SC_ESCAPE:
|
|
case SC_ESCAPE:
|
|
case RL_HAMMER_OF_GOD:
|
|
case RL_HAMMER_OF_GOD:
|
|
|
|
+ case SU_CN_METEOR:
|
|
break; //Effect is displayed on respective switch case.
|
|
break; //Effect is displayed on respective switch case.
|
|
default:
|
|
default:
|
|
if(skill_get_inf(skill_id)&INF_SELF_SKILL)
|
|
if(skill_get_inf(skill_id)&INF_SELF_SKILL)
|
|
@@ -11513,6 +11621,8 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|
case MH_XENO_SLASHER:
|
|
case MH_XENO_SLASHER:
|
|
case LG_KINGS_GRACE:
|
|
case LG_KINGS_GRACE:
|
|
case RL_B_TRAP:
|
|
case RL_B_TRAP:
|
|
|
|
+ case SU_CN_POWDERING:
|
|
|
|
+ case SU_SV_ROOTTWIST:
|
|
flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete).
|
|
flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete).
|
|
case GS_GROUNDDRIFT: //Ammo should be deleted right away.
|
|
case GS_GROUNDDRIFT: //Ammo should be deleted right away.
|
|
case GN_WALLOFTHORN:
|
|
case GN_WALLOFTHORN:
|
|
@@ -11560,10 +11670,21 @@ 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);
|
|
skill_unitsetting(src,skill_id,skill_lv,x,y,0);
|
|
break;
|
|
break;
|
|
|
|
|
|
- case WZ_METEOR: {
|
|
|
|
|
|
+ case WZ_METEOR:
|
|
|
|
+ case SU_CN_METEOR: {
|
|
int area = skill_get_splash(skill_id, skill_lv);
|
|
int area = skill_get_splash(skill_id, skill_lv);
|
|
short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0;
|
|
short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0;
|
|
|
|
|
|
|
|
+ if (sd && skill_id == SU_CN_METEOR) {
|
|
|
|
+ short item_idx = pc_search_inventory(sd, ITEMID_CATNIP_FRUIT);
|
|
|
|
+
|
|
|
|
+ if (item_idx >= 0) {
|
|
|
|
+ pc_delitem(sd, item_idx, 1, 0, 1, LOG_TYPE_CONSUME);
|
|
|
|
+ skill_area_temp[3] = 1;
|
|
|
|
+ } else
|
|
|
|
+ skill_area_temp[3] = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
for( i = 0; i < 2 + (skill_lv>>1); i++ ) {
|
|
for( i = 0; i < 2 + (skill_lv>>1); i++ ) {
|
|
// Creates a random Cell in the Splash Area
|
|
// Creates a random Cell in the Splash Area
|
|
tmpx = x - area + rnd()%(area * 2 + 1);
|
|
tmpx = x - area + rnd()%(area * 2 + 1);
|
|
@@ -12093,6 +12214,18 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case SU_LOPE:
|
|
|
|
+ if (map[src->m].flag.noteleport && !(map[src->m].flag.battleground || map_flag_gvg2(src->m))) {
|
|
|
|
+ x = src->x;
|
|
|
|
+ y = src->y;
|
|
|
|
+ }
|
|
|
|
+ clif_skill_nodamage(src, src, SU_LOPE, skill_lv, 1);
|
|
|
|
+ if (!map_count_oncell(src->m, x, y, BL_PC|BL_NPC|BL_MOB, 0) && path_search(NULL, src->m, src->x, src->y, x, y, 1, CELL_CHKNOREACH)) {
|
|
|
|
+ clif_slide(src, x, y);
|
|
|
|
+ unit_movepos(src, x, y, 1, 0);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+
|
|
default:
|
|
default:
|
|
ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skill_id);
|
|
ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skill_id);
|
|
return 1;
|
|
return 1;
|
|
@@ -13158,6 +13291,13 @@ static int skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, un
|
|
status_change_start(ss, bl, type, 10000, sg->skill_lv, 0, 0, 0, sg->limit, SCSTART_NOICON);
|
|
status_change_start(ss, bl, type, 10000, sg->skill_lv, 0, 0, 0, sg->limit, SCSTART_NOICON);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case UNT_CATNIPPOWDER:
|
|
|
|
+ if (sg->src_id == bl->id || (status_get_mode(bl)&MD_BOSS))
|
|
|
|
+ break; // Does not affect the caster or Boss.
|
|
|
|
+ if (!sce && battle_check_target(&unit->bl, bl, BCT_ENEMY) > 0)
|
|
|
|
+ sc_start(ss, bl, type, 100, sg->skill_lv, skill_get_time(sg->skill_id, sg->skill_lv));
|
|
|
|
+ break;
|
|
|
|
+
|
|
case UNT_GD_LEADERSHIP:
|
|
case UNT_GD_LEADERSHIP:
|
|
case UNT_GD_GLORYWOUNDS:
|
|
case UNT_GD_GLORYWOUNDS:
|
|
case UNT_GD_SOULCOLD:
|
|
case UNT_GD_SOULCOLD:
|
|
@@ -13277,6 +13417,9 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns
|
|
++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status_isdead(bl) );
|
|
++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status_isdead(bl) );
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
+ case WZ_HEAVENDRIVE:
|
|
|
|
+ status_change_end(bl, SC_SV_ROOTTWIST, INVALID_TIMER);
|
|
|
|
+ break;
|
|
#ifndef RENEWAL // The storm gust counter was dropped in renewal
|
|
#ifndef RENEWAL // The storm gust counter was dropped in renewal
|
|
case WZ_STORMGUST: //SG counter does not reset per stormgust. IE: One hit from a SG and two hits from another will freeze you.
|
|
case WZ_STORMGUST: //SG counter does not reset per stormgust. IE: One hit from a SG and two hits from another will freeze you.
|
|
if (tsc)
|
|
if (tsc)
|
|
@@ -13318,7 +13461,6 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns
|
|
skill_delunit(unit);
|
|
skill_delunit(unit);
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
-
|
|
|
|
case UNT_SANCTUARY:
|
|
case UNT_SANCTUARY:
|
|
if( battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race==RC_DEMON )
|
|
if( battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race==RC_DEMON )
|
|
{ //Only damage enemies with offensive Sanctuary. [Skotlex]
|
|
{ //Only damage enemies with offensive Sanctuary. [Skotlex]
|
|
@@ -13920,6 +14062,28 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns
|
|
skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,SD_ANIMATION|SD_SPLASH),
|
|
skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,SD_ANIMATION|SD_SPLASH),
|
|
1,sg->skill_id,sg->skill_lv,6);
|
|
1,sg->skill_id,sg->skill_lv,6);
|
|
break;
|
|
break;
|
|
|
|
+
|
|
|
|
+ case UNT_SV_ROOTTWIST:
|
|
|
|
+ if (status_get_mode(bl)&MD_BOSS)
|
|
|
|
+ break;
|
|
|
|
+ if (tsc) {
|
|
|
|
+ if (!sg->val2) {
|
|
|
|
+ int sec = skill_get_time(sg->skill_id, sg->skill_lv);
|
|
|
|
+
|
|
|
|
+ if (sc_start2(ss, bl, type, 100, sg->skill_lv, sg->group_id, sec)) {
|
|
|
|
+ const struct TimerData* td = tsc->data[type]?get_timer(tsc->data[type]->timer):NULL;
|
|
|
|
+
|
|
|
|
+ if(td)
|
|
|
|
+ sec = DIFF_TICK(td->tick, tick);
|
|
|
|
+ clif_fixpos(bl);
|
|
|
|
+ sg->val2 = bl->id;
|
|
|
|
+ } else // Couldn't trap it?
|
|
|
|
+ sec = 7000;
|
|
|
|
+ sg->limit = DIFF_TICK(tick, sg->tick) + sec;
|
|
|
|
+ } else if (tsc->data[type] && bl->id == sg->val2)
|
|
|
|
+ skill_attack(skill_get_type(SU_SV_ROOTTWIST_ATK), ss, &unit->bl, bl, SU_SV_ROOTTWIST_ATK, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION);
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
|
|
if (bl->type == BL_MOB && ss != bl)
|
|
if (bl->type == BL_MOB && ss != bl)
|
|
@@ -20242,6 +20406,7 @@ int skill_disable_check(struct status_change *sc, uint16 skill_id)
|
|
case KO_YAMIKUMO:
|
|
case KO_YAMIKUMO:
|
|
case RA_WUGDASH:
|
|
case RA_WUGDASH:
|
|
case RA_CAMOUFLAGE:
|
|
case RA_CAMOUFLAGE:
|
|
|
|
+ case SU_HIDE:
|
|
if( sc->data[status_skill2sc(skill_id)] )
|
|
if( sc->data[status_skill2sc(skill_id)] )
|
|
return 1;
|
|
return 1;
|
|
break;
|
|
break;
|