summaryrefslogtreecommitdiff
path: root/src/map/skill.c
diff options
context:
space:
mode:
authorL0ne_W0lf <L0ne_W0lf@54d463be-8e91-2dee-dedb-b68131a5f0ec>2011-08-27 03:25:00 +0000
committerL0ne_W0lf <L0ne_W0lf@54d463be-8e91-2dee-dedb-b68131a5f0ec>2011-08-27 03:25:00 +0000
commit1fe2e1773b9a7218fe5e39c4d2116194216b6986 (patch)
tree31a19349a7c55280bd21eeab4831fc0b838678bc /src/map/skill.c
parenta2ec62d8f24cbc11dcb646712c4c16a5cf897372 (diff)
downloadhercules-1fe2e1773b9a7218fe5e39c4d2116194216b6986.tar.gz
hercules-1fe2e1773b9a7218fe5e39c4d2116194216b6986.tar.bz2
hercules-1fe2e1773b9a7218fe5e39c4d2116194216b6986.tar.xz
hercules-1fe2e1773b9a7218fe5e39c4d2116194216b6986.zip
- Implemented first version of Archbishop skills. Preliminary version, see doc/3rd_job_notes.txt for details/bugs/issues with skills.
- Implemented fixed cast time, old cast time mechanics no longer available. Added bFixedCastRate used for reducing fixed cast time mechanic. Cast time calculations probably still needs work, as the cast rate reductions are probably additive and multiplicative as they used to be. - As a result, skill_delayfix_sc() has been removed, status effects that modify cast time are now calculated DURING cast time, not after. - Implemented skill cooldown in skill_cast_db.txt. Known issue is that the cooldowns should save on logout/server shutdown/etc. - Implemented new heal calculation and started work on MATK. Added bWeaponMatk, and bEquipmentMatk for use with new MATK mechanic. - Removed custom features and their config settings: delay_dependon_dex, delay_dependon_agi, castrate_dex_scale. - Increased max_def to 9999 for now, as that is by default the largest defense increase found in the Renewal database (Ahura_mazdah, GM item) - Added shield aspd reduction from job_db1.txt-- Not 100% sure on this one yet. Should be considered a WIP. - Modified updatestatus(), to display information more in line with the client's status window. - Updated some calculations in status_calc_misc to match renewal, needs a lot of work still. - ST_CHASEWALK and HP_BASILICA no longer have 0 cast time while being canceled. * Implemented 'Boss' Decrease AGI, like 'Boss' Heal - editable in skill.conf * clif_skill_fail() now accepts a new parameter, to be used in later messages. * status_change_start() now stores tick as duration upon being called, which fixes timers calling the function from showing negative durations. * Implemented skill ALL_PARTYFLEE. 1 level, increases party member flee by 10. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/branches/renewal@14941 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map/skill.c')
-rw-r--r--src/map/skill.c835
1 files changed, 629 insertions, 206 deletions
diff --git a/src/map/skill.c b/src/map/skill.c
index d33d35d6e..7f4f895d1 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -37,7 +37,7 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
-
+#include <math.h>
#define SKILLUNITTIMER_INTERVAL 100
@@ -143,7 +143,9 @@ int skill_get_itemqty(int id, int idx) { skill_get (skill_db[id].amount[idx],
int skill_get_zeny( int id ,int lv ) { skill_get (skill_db[id].zeny[lv-1], id, lv); }
int skill_get_num( int id ,int lv ) { skill_get (skill_db[id].num[lv-1], id, lv); }
int skill_get_cast( int id ,int lv ) { skill_get (skill_db[id].cast[lv-1], id, lv); }
+int skill_get_fixedcast( int id ,int lv ) { skill_get (skill_db[id].fixedcast[lv-1], id, lv); }
int skill_get_delay( int id ,int lv ) { skill_get (skill_db[id].delay[lv-1], id, lv); }
+int skill_get_cooldown( int id ,int lv ) { skill_get (skill_db[id].cooldown[lv-1], id, lv); }
int skill_get_walkdelay( int id ,int lv ) { skill_get (skill_db[id].walkdelay[lv-1], id, lv); }
int skill_get_time( int id ,int lv ) { skill_get (skill_db[id].upkeep_time[lv-1], id, lv); }
int skill_get_time2( int id ,int lv ) { skill_get (skill_db[id].upkeep_time2[lv-1], id, lv); }
@@ -267,10 +269,13 @@ int skill_get_range2 (struct block_list *bl, int id, int lv)
int skill_calc_heal(struct block_list *src, struct block_list *target, int skill_id, int skill_lv, bool heal)
{
- int skill, hp;
+ int skill, hp, mod = 100;
struct map_session_data *sd = map_id2sd(src->id);
struct map_session_data *tsd = map_id2sd(target->id);
struct status_change* sc;
+ struct status_data *status;
+
+ status = status_get_status_data(src);
switch( skill_id )
{
@@ -288,32 +293,77 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, int skill
default:
if (skill_lv >= battle_config.max_heal_lv)
return battle_config.max_heal;
+
+ // iRO Wiki states as of 2011/08/22:
+ // heal = ( [(Base Level + INT) / 5] × 30 ) × (Heal Level / 10) × (1 + (Modifiers / 100)) + MATK
+ // fixme: Does not match up with iRO's heal, level 1 or level 10
+ // with 219 mak + HP_MEDITATO, level 1 = 361; level 10 = 1839
+ if( skill_id == AB_HIGHNESSHEAL ) {
+ skill = pc_checkskill(sd,AL_HEAL);
+ if( skill < 0 )
+ skill = 10;
+ }
+ else
+ skill = skill_lv;
- hp = ( status_get_lv(src)+status_get_int(src) )/8 *(4+ skill_lv*8);
+ // Calculate base heal rate
+ hp = ( ( ( status_get_lv(src) + status_get_int(src) ) / 5) * 30 ) * skill / 10;
+
+ // Increment skill and status based modifiers
if( sd && ((skill = pc_checkskill(sd, HP_MEDITATIO)) > 0) )
- hp += hp * skill * 2 / 100;
+ mod += skill * 2;
else if( src->type == BL_HOM && (skill = merc_hom_checkskill(((TBL_HOM*)src), HLIF_BRAIN)) > 0 )
- hp += hp * skill * 2 / 100;
+ mod += skill * 2;
+ if( sd && (skill = pc_skillheal_bonus(sd, skill_id)) )
+ mod += skill;
+ if( tsd && (skill = pc_skillheal2_bonus(tsd, skill_id)) )
+ mod += skill;
+
+ sc = status_get_sc(target);
+ if( sc && sc->count )
+ {
+ if( sc->data[SC_CRITICALWOUND] && heal ) // Critical Wound has no effect on offensive heal. [Inkfish]
+ mod -= sc->data[SC_CRITICALWOUND]->val2;
+ if( sc->data[SC_INCHEALRATE] && skill_id != NPC_EVILLAND && skill_id != BA_APPLEIDUN )
+ mod += sc->data[SC_INCHEALRATE]->val1; // Only affects Heal, Sanctuary and PotionPitcher.(like bHealPower) [Inkfish]
+ }
+
+ // Adjust the HP recovered rate by adding all of the modifiers together.
+ hp = hp * mod / 100;
+
+ // Get weapon level and weapon matk for variance calculations if it's a player.
+ // Mobs have their own variance, we've assumed:
+ // Weapon Level = 1
+ // Weapom_Matk = ?
+ // Need more information before that can be implemented.
+ if( sd )
+ {
+ int matk = 0;
+ int smatk = sd->battle_status.status_matk;
+ int ematk = sd->equipment_matk;
+ int wmatk = 0;
+ int wlv = 1;
+ int index = sd->equip_index[EQI_HAND_R];
+
+ if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON )
+ wlv = sd->inventory_data[index]->wlv;
+
+ wmatk = (int)( sd->weapon_matk + ( (float)( ( rand() % 20 ) - 10 ) / 100 * wlv * sd->weapon_matk ) + ( sd->battle_status.rhw.atk2 ) );
+ matk = ( smatk + wmatk + ematk );
+
+ hp += matk;
+ }
+
break;
}
+ // mercenaries only take half-effectiveness from heals.
if( ( (target && target->type == BL_MER) || !heal ) && skill_id != NPC_EVILLAND )
hp >>= 1;
- if( sd && (skill = pc_skillheal_bonus(sd, skill_id)) )
- hp += hp*skill/100;
-
- if( tsd && (skill = pc_skillheal2_bonus(tsd, skill_id)) )
- hp += hp*skill/100;
-
- sc = status_get_sc(target);
- if( sc && sc->count )
- {
- if( sc->data[SC_CRITICALWOUND] && heal ) // Critical Wound has no effect on offensive heal. [Inkfish]
- hp -= hp * sc->data[SC_CRITICALWOUND]->val2/100;
- if( sc->data[SC_INCHEALRATE] && skill_id != NPC_EVILLAND && skill_id != BA_APPLEIDUN )
- hp += hp * sc->data[SC_INCHEALRATE]->val1/100; // Only affects Heal, Sanctuary and PotionPitcher.(like bHealPower) [Inkfish]
- }
+ // Give Highness Heal it's extra heal
+ if( skill_id == AB_HIGHNESSHEAL )
+ hp = hp * (170 + 30 * skill_lv) / 100;
return hp;
}
@@ -403,7 +453,7 @@ int skillnotok (int skillid, struct map_session_data *sd)
case WZ_ICEWALL:
// noicewall flag [Valaris]
if (map[m].flag.noicewall) {
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
return 1;
}
break;
@@ -413,7 +463,7 @@ int skillnotok (int skillid, struct map_session_data *sd)
!(battle_config.emergency_call&(map[m].flag.gvg || map[m].flag.gvg_castle?8:4)) ||
(battle_config.emergency_call&16 && map[m].flag.nowarpto && !map[m].flag.gvg_castle)
) {
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
return 1;
}
break;
@@ -591,7 +641,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
if(pc_steal_item(sd,bl,pc_checkskill(sd,TF_STEAL)))
clif_skill_nodamage(src,bl,TF_STEAL,skill,1);
else
- clif_skill_fail(sd,RG_SNATCHER,0,0);
+ clif_skill_fail(sd,RG_SNATCHER,0,0,0);
}
// Chance to trigger Taekwon kicks [Dralnu]
if(sc && !sc->data[SC_COMBO]) {
@@ -654,7 +704,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
if(!sc_start(bl,SC_POISON,(4*skilllv+10),skilllv,skill_get_time2(skillid,skilllv))
&& sd && skillid==TF_POISON
)
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
case AS_SONICBLOW:
@@ -926,6 +976,10 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
case NPC_CRITICALWOUND:
sc_start(bl,SC_CRITICALWOUND,100,skilllv,skill_get_time2(skillid,skilllv));
break;
+ case AB_ADORAMUS:
+ sc_start(bl, SC_BLIND, 100, skilllv, skill_get_time(skillid, skilllv));
+ sc_start(bl, SC_ADORAMUS, 100, skilllv, skill_get_time2(skillid, skilllv));
+ break;
}
if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai)
@@ -2214,12 +2268,12 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int
{
if( hp > 0 && status->hp <= (unsigned int)hp )
{
- clif_skill_fail(sd, skill, 2, 0);
+ clif_skill_fail(sd, skill, 2, 0, 0);
return 0;
}
if( sp > 0 && status->sp <= (unsigned int)sp )
{
- clif_skill_fail(sd, skill, 1, 0);
+ clif_skill_fail(sd, skill, 1, 0, 0);
return 0;
}
}
@@ -2230,7 +2284,7 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int
case ST_MOVE_ENABLE:
if( !unit_can_move(bl) )
{
- clif_skill_fail(sd, skill, 0, 0);
+ clif_skill_fail(sd, skill, 0, 0, 0);
return 0;
}
break;
@@ -2246,7 +2300,7 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int
index[i] = pc_search_inventory(sd, itemid[i]);
if( index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i] )
{
- clif_skill_fail(sd, skill, 0, 0);
+ clif_skill_fail(sd, skill, 0, 0, 0);
return 0;
}
}
@@ -2570,6 +2624,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
case NPC_BLEEDING:
case NPC_CRITICALWOUND:
case NPC_HELLPOWER:
+ case AB_DUPLELIGHT_MELEE:
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
break;
@@ -2675,7 +2730,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
unit_setdir(bl,dir);
}
else if (sd)
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
}
break;
@@ -2767,6 +2822,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
case NPC_PULSESTRIKE:
case NPC_HELLJUDGEMENT:
case NPC_VAMPIRE_GIFT:
+ case AB_JUDEX:
if( flag&1 )
{ //Recursive invocation
// skill_area_temp[0] holds number of targets in area
@@ -2921,6 +2977,10 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
case NJ_KOUENKA:
case NJ_HYOUSENSOU:
case NJ_HUUJIN:
+ case AB_ADORAMUS:
+ case AB_RENOVATIO:
+ case AB_HIGHNESSHEAL:
+ case AB_DUPLELIGHT_MAGIC:
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
break;
@@ -2992,7 +3052,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
case SL_STUN:
if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) {
status_change_start(src,SC_STUN,10000,skilllv,0,0,0,500,10);
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
@@ -3098,6 +3158,9 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
skill_consume_requirement(sd,skillid,skilllv,2);
}
+ if( sd && skill_get_cooldown(skillid,skilllv) )
+ skill_blockpc_start (sd, skillid, skill_get_cooldown(skillid, skilllv));
+
return 0;
}
@@ -3148,17 +3211,19 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
switch (skillid) {
case HLIF_HEAL: //[orn]
if (bl->type != BL_HOM) {
- if (sd) clif_skill_fail(sd,skillid,0,0) ;
+ if (sd) clif_skill_fail(sd,skillid,0,0,0) ;
break ;
}
case AL_HEAL:
case ALL_RESURRECTION:
case PR_ASPERSIO:
+ case AB_RENOVATIO:
+ case AB_HIGHNESSHEAL:
//Apparently only player casted skills can be offensive like this.
if (sd && battle_check_undead(tstatus->race,tstatus->def_ele)) {
if (battle_check_target(src, bl, BCT_ENEMY) < 1) {
//Offensive heal does not works on non-enemies. [Skotlex]
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
return 0;
}
return skill_castend_damage_id (src, bl, skillid, skilllv, tick, flag);
@@ -3187,6 +3252,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
{
case HLIF_HEAL: //[orn]
case AL_HEAL:
+ case AB_HIGHNESSHEAL:
{
int heal = skill_calc_heal(src, bl, skillid, skilllv, true);
int heal_get_jobexp;
@@ -3228,7 +3294,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case PR_REDEMPTIO:
if (sd && !(flag&1)) {
if (sd->status.party_id == 0) {
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
skill_area_temp[0] = 0;
@@ -3237,7 +3303,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
src,skillid,skilllv,tick, flag|BCT_PARTY|1,
skill_castend_nodamage_id);
if (skill_area_temp[0] == 0) {
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
skill_area_temp[0] = 5 - skill_area_temp[0]; // The actual penalty...
@@ -3259,7 +3325,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case ALL_RESURRECTION:
if(sd && (map_flag_gvg(bl->m) || map[bl->m].flag.battleground))
{ //No reviving in WoE grounds!
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
if (!status_isdead(bl))
@@ -3304,8 +3370,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case AL_DECAGI:
case MER_DECAGI:
- clif_skill_nodamage (src, bl, skillid, skilllv,
- sc_start(bl, type, (40 + skilllv * 2 + (status_get_lv(src) + sstatus->int_)/5), skilllv, skill_get_time(skillid,skilllv)));
+ if (skilllv >= battle_config.max_decagi_lv)
+ clif_skill_nodamage (src, bl, skillid, skilllv,
+ sc_start(bl, type, (40 + skilllv * 2 + (status_get_lv(src) + sstatus->int_)/5), (battle_config.max_decagi - 2), (battle_config.max_decagi_dur * 100)));
+ else
+ clif_skill_nodamage (src, bl, skillid, skilllv,
+ sc_start(bl, type, (40 + skilllv * 2 + (status_get_lv(src) + sstatus->int_)/5), skilllv, skill_get_time(skillid,skilllv)));
break;
case AL_CRUCIS:
@@ -3425,7 +3495,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
int class_;
if ( sd && dstmd->status.mode&MD_BOSS )
{
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
class_ = skillid==SA_MONOCELL?1002:mob_get_random_id(2, 1, 0);
@@ -3444,7 +3514,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case SA_DEATH:
if ( sd && dstmd && dstmd->status.mode&MD_BOSS )
{
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
@@ -3470,7 +3540,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case CR_PROVIDENCE:
if(sd && dstsd){ //Check they are not another crusader [Skotlex]
if ((dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER) {
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 1;
}
@@ -3485,7 +3555,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if( sd && dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && dstsd->status.sex == sd->status.sex )
{// Cannot cast on another bard/dancer-type class of the same gender as caster
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 1;
}
@@ -3508,7 +3578,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
else
{
if( sd )
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 1;
@@ -3538,7 +3608,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
dstsd->sc.data[SC_ENCPOISON]
))
) {
- if (sd) clif_skill_fail(sd,skillid,0,0);
+ if (sd) clif_skill_fail(sd,skillid,0,0,0);
clif_skill_nodamage(src,bl,skillid,skilllv,0);
break;
}
@@ -3546,7 +3616,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
// 100% success rate at lv4 & 5, but lasts longer at lv5
if(!clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,type,(60+skilllv*10),skilllv, skill_get_time(skillid,skilllv)))) {
if (sd)
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
if (skill_break_equip(bl, EQP_WEAPON, 10000, BCT_PARTY) && sd && sd != dstsd)
clif_displaymessage(sd->fd,"You broke target's weapon");
}
@@ -3658,6 +3728,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case ST_PRESERVE:
case NPC_INVINCIBLE:
case NPC_INVINCIBLEOFF:
+ case AB_RENOVATIO:
+ case AB_EXPIATIO:
+ case AB_DUPLELIGHT:
+ case AB_SECRAMENT:
clif_skill_nodamage(src,bl,skillid,skilllv,
sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
break;
@@ -3668,7 +3742,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
break;
case HP_ASSUMPTIO:
if( sd && dstmd )
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
else
clif_skill_nodamage(src,bl,skillid,skilllv,
sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
@@ -3726,7 +3800,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
// dstsd->sc.data[SC_ENCPOISON] //People say you should be able to recast to lengthen the timer. [Skotlex]
) {
clif_skill_nodamage(src,bl,skillid,skilllv,0);
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
}
@@ -3749,12 +3823,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
int id;
if (sd->mission_mobid && (sd->mission_count || rand()%100)) { //Cannot change target when already have one
clif_mission_info(sd, sd->mission_mobid, sd->mission_count);
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
id = mob_get_random_id(0,0xE, sd->status.base_level);
if (!id) {
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
sd->mission_mobid = id;
@@ -3789,7 +3863,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if( !i )
{
if( sd )
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 0;
}
@@ -3817,7 +3891,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if( !dstsd || (!sd && !mer) )
{ // Only players can be devoted
if( sd )
- clif_skill_fail(sd, skillid, 0, 0);
+ clif_skill_fail(sd, skillid, 0, 0, 0);
break;
}
@@ -3830,7 +3904,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
(dstsd->sc.data[SC_HELLPOWER])) // Players affected by SC_HELLPOWERR cannot be devoted.
{
if( sd )
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 1;
}
@@ -3845,7 +3919,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
ARR_FIND(0, count, i, sd->devotion[i] == 0 );
if( i == count )
{ // No free slots, skill Fail
- clif_skill_fail(sd, skillid, 0, 0);
+ clif_skill_fail(sd, skillid, 0, 0, 0);
map_freeblock_unlock();
return 1;
}
@@ -4070,7 +4144,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
dstsd->status.char_id == sd->status.child
)) {
status_change_start(src,SC_STUN,10000,skilllv,0,0,0,500,8);
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
}
@@ -4113,7 +4187,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if( i )
clif_skill_nodamage(src,bl,skillid,-1,i);
else if( sd )
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 0;
}
@@ -4121,7 +4195,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if( i )
clif_skill_nodamage(src,bl,skillid,-1,i);
else if( sd )
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
case BD_ADAPTATION:
@@ -4162,7 +4236,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
else
{
clif_skill_nodamage(src,bl,skillid,skilllv,0);
- if(sd) clif_skill_fail(sd,skillid,0,0);
+ if(sd) clif_skill_fail(sd,skillid,0,0,0);
}
}
break;
@@ -4172,7 +4246,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if(pc_steal_item(sd,bl,skilllv))
clif_skill_nodamage(src,bl,skillid,skilllv,1);
else
- clif_skill_fail(sd,skillid,0x0a,0);
+ clif_skill_fail(sd,skillid,10,0,0);
}
break;
@@ -4186,14 +4260,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
}
else
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
}
break;
case MG_STONECURSE:
{
if (tstatus->mode&MD_BOSS) {
- if (sd) clif_skill_fail(sd,skillid,0,0);
+ if (sd) clif_skill_fail(sd,skillid,0,0,0);
break;
}
if(status_isimmune(bl) || !tsc)
@@ -4201,7 +4275,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if (tsc->data[SC_STONE]) {
status_change_end(bl, SC_STONE, INVALID_TIMER);
- if (sd) clif_skill_fail(sd,skillid,0,0);
+ if (sd) clif_skill_fail(sd,skillid,0,0,0);
break;
}
if (sc_start4(bl,SC_STONE,(skilllv*4+20),
@@ -4209,7 +4283,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
skill_get_time2(skillid,skilllv)))
clif_skill_nodamage(src,bl,skillid,skilllv,1);
else if(sd) {
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
// Level 6-10 doesn't consume a red gem if it fails [celest]
if (skilllv > 5)
{ // not to consume items
@@ -4313,7 +4387,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
break;
if( dstsd )
{ // Fail on Players
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
if( dstmd && dstmd->class_ == MOBID_EMPERIUM )
@@ -4345,7 +4419,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if(sd)
{ //Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex]
if ( !pc_can_give_items(pc_isGM(sd)) )
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
else
clif_openvendingreq(sd,2+skilllv);
}
@@ -4391,7 +4465,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if (skill_produce_mix(sd, skillid, 523, 0, 0, 0, 1))
clif_skill_nodamage(src,bl,skillid,skilllv,1);
else
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
}
break;
@@ -4473,7 +4547,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
//Nothing stripped.
if( sd && !i )
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
}
break;
@@ -4492,13 +4566,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
i = pc_search_inventory(sd,skill_db[skillid].itemid[x]);
if(i < 0 || skill_db[skillid].itemid[x] <= 0)
{
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 1;
}
if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skillid].amount[x])
{
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 1;
}
@@ -4506,7 +4580,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
{
if( dstsd && dstsd->status.base_level < (unsigned int)sd->inventory_data[i]->elv )
{
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 1;
}
@@ -4599,7 +4673,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
clif_skill_nodamage(src,bl,skillid,skilllv,1);
//Prepare 200 White Potions.
if (!skill_produce_mix(sd, skillid, 504, 0, 0, 0, 200))
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
}
break;
case AM_TWILIGHT2:
@@ -4607,7 +4681,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
clif_skill_nodamage(src,bl,skillid,skilllv,1);
//Prepare 200 Slim White Potions.
if (!skill_produce_mix(sd, skillid, 547, 0, 0, 0, 200))
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
}
break;
case AM_TWILIGHT3:
@@ -4617,7 +4691,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|| !skill_can_produce_mix(sd,7136,-1, 50) //50 Acid Bottle
|| !skill_can_produce_mix(sd,7135,-1, 50) //50 Flame Bottle
) {
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
@@ -4635,7 +4709,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|| rand()%100 >= 50+10*skilllv)
{
if (sd)
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
if(status_isimmune(bl) || !tsc || !tsc->count)
@@ -4750,7 +4824,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
{ //Only 10% success chance against bosses. [Skotlex]
if (rand()%100 < 90)
{
- if (sd) clif_skill_fail(sd,skillid,0,0);
+ if (sd) clif_skill_fail(sd,skillid,0,0,0);
break;
}
} else if (!dstsd || map_flag_vs(bl->m)) //HP damage only on pvp-maps when against players.
@@ -5024,7 +5098,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
struct map_session_data *m_sd = pc_get_mother(sd);
// if neither was found
if(!f_sd && !m_sd){
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 0;
}
@@ -5040,7 +5114,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
hp = sstatus->max_hp/10;
sp = hp * 10 * skilllv / 100;
if (!status_charge(src,hp,0)) {
- if (sd) clif_skill_fail(sd,skillid,0,0);
+ if (sd) clif_skill_fail(sd,skillid,0,0,0);
break;
}
clif_skill_nodamage(src, bl, skillid, skilllv, 1);
@@ -5136,7 +5210,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case AS_SPLASHER:
if(tstatus->mode&MD_BOSS || tstatus-> hp > tstatus->max_hp*3/4) {
- if (sd) clif_skill_fail(sd,skillid,0,0);
+ if (sd) clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 1;
}
@@ -5164,7 +5238,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if (!clif_skill_nodamage(src,bl,skillid,skilllv,
sc_start(bl,type,55+5*skilllv,skilllv,skill_get_time(skillid,skilllv))))
{
- if (sd) clif_skill_fail(sd,skillid,0,0);
+ if (sd) clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 0;
}
@@ -5188,7 +5262,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
unsigned int sp1 = 0, sp2 = 0;
if (dstmd) {
if (dstmd->state.soul_change_flag) {
- if(sd) clif_skill_fail(sd,skillid,0,0);
+ if(sd) clif_skill_fail(sd,skillid,0,0,0);
break;
}
dstmd->state.soul_change_flag = 1;
@@ -5270,7 +5344,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if( rand() % 100 > skilllv * 8 || (dstmd && ((dstmd->guardian_data && dstmd->class_ == MOBID_EMPERIUM) || mob_is_battleground(dstmd))) )
{
if( sd )
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
map_freeblock_unlock();
return 0;
@@ -5373,7 +5447,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case SL_WIZARD:
//NOTE: here, 'type' has the value of the associated MAPID, not of the SC_SPIRIT constant.
if (sd && !(dstsd && (dstsd->class_&MAPID_UPPERMASK) == type)) {
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
if (skillid == SL_SUPERNOVICE && dstsd && dstsd->die_counter && !(rand()%100))
@@ -5389,7 +5463,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
break;
case SL_HIGH:
if (sd && !(dstsd && (dstsd->class_&JOBL_UPPER) && !(dstsd->class_&JOBL_2) && dstsd->status.base_level < 70)) {
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
clif_skill_nodamage(src,bl,skillid,skilllv,
@@ -5405,7 +5479,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case SL_SKA: // [marquis007]
case SL_SKE:
if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) {
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
status_change_start(src,SC_STUN,10000,skilllv,0,0,0,500,10);
break;
}
@@ -5497,7 +5571,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if (sd) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if (!pc_set_hate_mob(sd, skilllv-1, bl))
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
}
break;
@@ -5520,12 +5594,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
sc_start(bl,SC_STUN, i,skilllv,skill_get_time2(skillid,skilllv));
}
else if (sd)
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
case AM_CALLHOMUN: //[orn]
if (sd && !merc_call_homunculus(sd))
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
case AM_REST:
@@ -5534,7 +5608,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
if (merc_hom_vaporize(sd,1))
clif_skill_nodamage(src, bl, skillid, skilllv, 1);
else
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
}
break;
@@ -5563,9 +5637,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
}
// Failed
else if (hd && hd->master)
- clif_skill_fail(hd->master, skillid, 0, 0);
+ clif_skill_fail(hd->master, skillid, 0, 0, 0);
else if (sd)
- clif_skill_fail(sd, skillid, 0, 0);
+ clif_skill_fail(sd, skillid, 0, 0, 0);
break;
case HVAN_CHAOTIC: //[orn]
{
@@ -5645,6 +5719,19 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
skill_castend_nodamage_id);
}
break;
+ case ALL_PARTYFLEE:
+ if( sd && !(flag&1) )
+ {
+ if( !sd->status.party_id )
+ {
+ clif_skill_fail(sd,skillid,0,0,0);
+ break;
+ }
+ party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id);
+ }
+ else
+ clif_skill_nodamage(src,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
+ break;
case NPC_TALK:
case ALL_WEWISH:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
@@ -5655,6 +5742,193 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
clif_skill_nodamage(src, bl, skillid, skilllv, buyingstore_setup(sd, MAX_BUYINGSTORE_SLOTS));
}
break;
+ case AB_ANCILLA:
+ if(sd) {
+ if (skill_produce_mix(sd, skillid, 12333, 0, 0, 0, 1))
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ else
+ clif_skill_fail(sd,skillid,0,0,0);
+ }
+ break;
+ case AB_CLEMENTIA:
+ case AB_CANTO:
+ if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) {
+ int lv = 0;
+ switch(skillid) {
+ case AB_CLEMENTIA: lv = pc_checkskill(sd,AL_BLESSING); break;
+ case AB_CANTO: lv = pc_checkskill(sd,AL_INCAGI); break;
+ }
+ clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl,type,100,(lv < 1)? 1: lv,skill_get_time(skillid,skilllv)));
+ }
+ else if( sd )
+ party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id);
+ break;
+ case AB_CHEAL:
+ if( sd == NULL || sd->status.party_id == 0 || flag&1 )
+ {
+ int lv = pc_checkskill(sd, AL_HEAL);
+ if( sd && tstatus && !battle_check_undead(tstatus->race, tstatus->def_ele) )
+ {
+ int heal = skill_calc_heal(src, bl, AL_HEAL, lv>=1?lv:1, true);
+ if( status_isimmune(bl) )
+ heal = 0;
+ clif_skill_nodamage(bl, bl, skillid, heal, 1);
+ status_heal(bl, heal, 0, 0);
+ }
+ }
+ else if( sd )
+ party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id);
+ break;
+ case AB_PRAEFATIO:
+ if( (flag&1) || sd == NULL || sd->status.party_id == 0 )
+ {
+ if( dstsd && dstsd->special_state.no_magic_damage )
+ break;
+ clif_skill_nodamage(bl,bl,skillid,skilllv,1);
+ clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start4(bl, type, 100, skilllv, 0, 0, 1, skill_get_time(skillid, skilllv)));
+ }
+ else
+ party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id);
+ break;
+ case AB_ORATIO:
+ if (flag&1)
+ sc_start(bl, type, 40+skilllv*5, skilllv, skill_get_time(skillid, skilllv));
+ else {
+ clif_skill_nodamage(src, bl, skillid, skilllv, 1);
+ map_foreachinrange(skill_area_sub, bl,
+ skill_get_splash(skillid, skilllv), BL_CHAR,
+ src, skillid, skilllv, tick, flag|BCT_ENEMY|1,
+ skill_castend_nodamage_id);
+ }
+ break;
+ case AB_LAUDAAGNUS:
+ case AB_LAUDARAMUS:
+ if( flag&1 || sd == NULL )
+ {
+ if( tsc && (rand()%100 < 30+5*skilllv) )
+ {
+ switch(skillid)
+ {
+ case AB_LAUDAAGNUS:
+ if( tsc->data[SC_STONE] || tsc->data[SC_FREEZE] || tsc->data[SC_BLIND] )
+ {
+ status_change_end(bl, SC_STONE, INVALID_TIMER);
+ status_change_end(bl, SC_FREEZE, INVALID_TIMER);
+ status_change_end(bl, SC_BLIND, INVALID_TIMER);
+ }
+ break;
+ case AB_LAUDARAMUS:
+ if( tsc->data[SC_STUN] || tsc->data[SC_SLEEP] || tsc->data[SC_SILENCE] )
+ {
+ status_change_end(bl, SC_STUN, INVALID_TIMER);
+ status_change_end(bl, SC_SLEEP, INVALID_TIMER);
+ status_change_end(bl, SC_SILENCE, INVALID_TIMER);
+ }
+ break;
+ }
+ }
+ clif_skill_nodamage(bl, bl, skillid, skilllv,
+ sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)));
+ }
+ else if( sd )
+ party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv),
+ src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id);
+ break;
+ case AB_CLEARANCE:
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if( rand()%100 >= 50+10*skilllv )
+ {
+ if (sd)
+ clif_skill_fail(sd,skillid,0,0,0);
+ break;
+ }
+
+ if(status_isimmune(bl) || !tsc || !tsc->count)
+ break;
+ for(i=0;i<SC_MAX;i++)
+ {
+ if (!tsc->data[i])
+ continue;
+ //Initial list of status effects cancelled by Clearance. Does not contain third job status.
+ switch (i) {
+ case SC_WEIGHT50: case SC_WEIGHT90: case SC_TWOHANDQUICKEN:
+ case SC_QUAGMIRE: case SC_SLOWPOISON: case SC_BENEDICTIO:
+ case SC_TRICKDEAD: case SC_HALLUCINATION: case SC_ASPDPOTION0:
+ case SC_ASPDPOTION1: case SC_SPEEDUP1: case SC_STRIPWEAPON:
+ case SC_STRIPSHIELD: case SC_STRIPARMOR: case SC_STRIPHELM:
+ case SC_CP_WEAPON: case SC_CP_SHIELD: case SC_CP_ARMOR:
+ case SC_CP_HELM: case SC_AUTOGUARD: case SC_REFLECTSHIELD:
+ case SC_MAGICROD: case SC_SAFETYWALL: case SC_FIREWEAPON:
+ case SC_WATERWEAPON: case SC_WINDWEAPON: case SC_EARTHWEAPON:
+ case SC_VOLCANO: case SC_DELUGE: case SC_VIOLENTGALE:
+ case SC_AUTOBERSERK: case SC_CARTBOOST: case SC_BLADESTOP:
+ case SC_ARMOR_ELEMENT: case SC_STOP: case SC_EXPLOSIONSPIRITS:
+ case SC_NOCHAT: case SC_PARRYING: case SC_TENSIONRELAX:
+ case SC_SACRIFICE: case SC_BASILICA: case SC_GUILDAURA:
+ case SC_BLEEDING: case SC_JOINTBEAT: case SC_FOGWALL:
+ case SC_SPIDERWEB: case SC_RUN: case SC_SPURT:
+ case SC_SHADOWWEAPON: case SC_GHOSTWEAPON: case SC_SPIRIT:
+ case SC_WATKFOOD: case SC_MATKFOOD: case SC_KAITE:
+ case SC_KAAHI: case SC_KAUPE: case SC_ONEHAND:
+ case SC_CHASEWALK: case SC_SLOWDOWN: case SC_DOUBLECAST:
+ case SC_GRAVITATION: case SC_CLOSECONFINE: case SC_CLOSECONFINE2:
+ case SC_UTSUSEMI: case SC_BUNSINJYUTSU: case SC_SUITON:
+ case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD:
+ case SC_DEXFOOD: case SC_INTFOOD: case SC_LUKFOOD:
+ case SC_FLEEFOOD: case SC_HITFOOD: case SC_JAILED:
+ case SC_SUMMER: case SC_WEDDING: case SC_DANCING:
+ case SC_EXPBOOST: case SC_LIFEINSURANCE: case SC_ITEMBOOST:
+ case SC_BOSSMAPINFO: case SC_FOOD_STR_CASH: case SC_FOOD_AGI_CASH:
+ case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH: case SC_FOOD_INT_CASH:
+ case SC_FOOD_LUK_CASH: case SC_MERC_FLEEUP: case SC_MERC_ATKUP:
+ case SC_MERC_HPUP: case SC_MERC_SPUP: case SC_MERC_HITUP:
+ case SC_SLOWCAST: case SC_CRITICALWOUND: case SC_SPEEDUP0:
+ case SC_DEF_RATE: case SC_MDEF_RATE: case SC_INCHEALRATE:
+ case SC_S_LIFEPOTION: case SC_L_LIFEPOTION: case SC_INCCRI:
+ case SC_SPCOST_RATE: case SC_COMMONSC_RESIST: case SC_ELEMENTALCHANGE:
+ case SC_INCFLEE2: case SC_PNEUMA: case SC_AUTOTRADE:
+ case SC_KSPROTECTED: case SC_ARMOR_RESIST: case SC_HELLPOWER:
+ case SC_JEXPBOOST: case SC_ITEMSCRIPT: case SC_INVINCIBLE:
+ case SC_INVINCIBLEOFF: case SC_MANU_ATK: case SC_MANU_DEF:
+ case SC_SPL_ATK: case SC_SPL_DEF: case SC_MANU_MATK:
+ case SC_SPL_MATK: case SC_SEVENWIND: case SC_NEN:
+ case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN:
+ case SC_READYCOUNTER: case SC_DODGE: case SC_WARM:
+ case SC_SMA: case SC_RICHMANKIM: case SC_ETERNALCHAOS:
+ case SC_DRUMBATTLE: case SC_NIBELUNGEN: case SC_ROKISWEIL:
+ case SC_INTOABYSS: case SC_SIEGFRIED: case SC_WHISTLE:
+ case SC_ASSNCROS: case SC_POEMBRAGI: case SC_APPLEIDUN:
+ case SC_HUMMING: case SC_DONTFORGETME: case SC_FORTUNE:
+ case SC_SERVICE4U: case SC_EPICLESIS: case SC_PARTYFLEE:
+ // not implemented
+ //case SC_ANGEL_PROTECT: case SC_BUCHEDENOEL: case SC_POPECOOKIE:
+ //case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: case SC_MINOR_BBQ:
+ //case SC_SIROMA_ICE_TEA: case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES:
+ //case SC_CRIFOOD: case SC_STR_SCROLL: case SC_INT_SCROLL:
+ //case SC_ACARAJE:
+ //
+ continue;
+ case SC_ASSUMPTIO:
+ if( bl->type == BL_MOB )
+ continue;
+ break;
+ }
+ if(i==SC_BERSERK) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0.
+ status_change_end(bl, (sc_type)i, INVALID_TIMER);
+ }
+ break;
+ case AB_SILENTIUM:
+ if (flag&1)
+ sc_start(bl,SC_SILENCE,100,skilllv,skill_get_time(skillid,skilllv));
+ else {
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ map_foreachinrange(skill_area_sub, bl,
+ skill_get_splash(skillid, skilllv),BL_CHAR,
+ src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
+ skill_castend_nodamage_id);
+ }
+ break;
+
default:
ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
@@ -5675,6 +5949,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
skill_consume_requirement(sd,skillid,skilllv,2);
}
+ if( sd && skill_get_cooldown(skillid,skilllv) )
+ skill_blockpc_start (sd, skillid, skill_get_cooldown(skillid, skilllv));
+
map_freeblock_unlock();
return 0;
}
@@ -5819,7 +6096,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
sc->data[SC_FOGWALL] &&
rand()%100 < 75)
{ //Fogwall makes all offensive-type targetted skills fail at 75%
- if (sd) clif_skill_fail(sd,ud->skillid,0,0);
+ if (sd) clif_skill_fail(sd,ud->skillid,0,0,0);
break;
}
}
@@ -5838,7 +6115,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
!check_distance_bl(src, target, skill_get_range2(src,ud->skillid,ud->skilllv)+battle_config.skill_add_range))
{
if (sd) {
- clif_skill_fail(sd,ud->skillid,0,0);
+ clif_skill_fail(sd,ud->skillid,0,0,0);
if(battle_config.skill_out_range_consume) //Consume items anyway. [Skotlex]
skill_consume_requirement(sd,ud->skillid,ud->skilllv,3);
}
@@ -5952,7 +6229,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
clif_slide(src,src->x,src->y);
clif_skill_damage(src,target,tick,sd->battle_status.amotion,0,0,1,ud->skillid, ud->skilllv, 5);
}
- clif_skill_fail(sd,ud->skillid,0,0);
+ clif_skill_fail(sd,ud->skillid,0,0,0);
}
}
@@ -6013,7 +6290,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
skill_check_unit_range(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv)
)
{
- if (sd) clif_skill_fail(sd,ud->skillid,0,0);
+ if (sd) clif_skill_fail(sd,ud->skillid,0,0,0);
break;
}
if( src->type&battle_config.skill_nofootset &&
@@ -6021,7 +6298,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
skill_check_unit_range2(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv)
)
{
- if (sd) clif_skill_fail(sd,ud->skillid,0,0);
+ if (sd) clif_skill_fail(sd,ud->skillid,0,0,0);
break;
}
if( src->type&battle_config.land_skill_limit &&
@@ -6034,7 +6311,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
}
if( maxcount == 0 )
{
- if (sd) clif_skill_fail(sd,ud->skillid,0,0);
+ if (sd) clif_skill_fail(sd,ud->skillid,0,0,0);
break;
}
}
@@ -6386,7 +6663,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
int j = pc_search_inventory(sd,skill_db[skillid].itemid[i]);
if( j < 0 || skill_db[skillid].itemid[i] <= 0 || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < skill_db[skillid].amount[i] )
{
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
return 1;
}
potion_flag = 1;
@@ -6442,7 +6719,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
i = skill_get_splash(skillid, skilllv);
map_foreachinarea(skill_cell_overlap, src->m, x-i, y-i, x+i, y+i, BL_SKILL, HW_GANBANTEIN, &dummy, src);
} else {
- if (sd) clif_skill_fail(sd,skillid,0,0);
+ if (sd) clif_skill_fail(sd,skillid,0,0,0);
return 1;
}
break;
@@ -6459,12 +6736,12 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
int i;
if( map_count_oncell(src->m,x,y,BL_CHAR) > 0 )
{
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
return 1;
}
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
if (rand()%100 < 50) {
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
} else {
TBL_MOB* md = mob_once_spawn_sub(src, src->m, x, y, "--ja--",(skilllv < 2 ? 1084+rand()%2 : 1078+rand()%6),"");
if (!md) break;
@@ -6514,12 +6791,23 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
{
if (!merc_resurrect_homunculus(sd, 20*skilllv, x, y))
{
- clif_skill_fail(sd,skillid,0,0);
+ clif_skill_fail(sd,skillid,0,0,0);
break;
}
}
break;
+ case AB_EPICLESIS:
+ if( skill_unitsetting(src, skillid, skilllv, x, y, 0) )
+ {
+ int range = skill_get_splash(skillid,skilllv); // Use Splash Range.
+ map_foreachinarea(skill_area_sub,
+ src->m, x-range, y-range, x+range, y+range, BL_CHAR,
+ src, ALL_RESURRECTION, 1, tick, flag|BCT_NOENEMY|1,
+ skill_castend_nodamage_id);
+ }
+ break;
+
default:
ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skillid);
return 1;
@@ -6535,6 +6823,9 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
skill_consume_requirement(sd,skillid,skilllv,2);
}
+ if( sd && skill_get_cooldown(skillid,skilllv) )
+ skill_blockpc_start (sd, skillid, skill_get_cooldown(skillid, skilllv));
+
return 0;
}
@@ -6604,7 +6895,7 @@ int skill_castend_map (struct map_session_data *sd, short skill_num, const char
mapindex = mapindex_name2id((char*)map);
if(!mapindex) { //Given map not found?
- clif_skill_fail(sd,skill_num,0,0);
+ clif_skill_fail(sd,skill_num,0,0,0);
skill_failed(sd);
return 0;
}
@@ -6619,7 +6910,7 @@ int skill_castend_map (struct map_session_data *sd, short skill_num, const char
maxcount--;
}
if(!maxcount) {
- clif_skill_fail(sd,skill_num,0,0);
+ clif_skill_fail(sd,skill_num,0,0,0);
skill_failed(sd);
return 0;
}
@@ -7723,6 +8014,61 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
//clif_changetraplook(&src->bl, UNT_FIREPILLAR_ACTIVE);
sg->limit=DIFF_TICK(tick,sg->tick)+1500;
break;
+
+ case UNT_EPICLESIS:
+ sg->val2--; // track when units should be healed. Initial tick heals immediately.
+ if ( !battle_check_undead(tstatus->race, tstatus->def_ele) || bl->type == BL_PC)
+ { //Effect only players who are not undead element.
+
+ //Unknown if any status effects should prevent Epiclesis.
+ //if( tsc->data[SC_BERSERK] )
+ // break;
+
+ //Apply status effect if standing in unit, should cancel upon stepping out of skill_get_splash() area. [FIXME]
+ if( tsc && !tsc->data[SC_EPICLESIS] )
+ sc_start(bl, type, 100, sg->skill_lv, skill_get_time(sg->skill_id,sg->skill_lv));
+
+ //There's probably a better way to handle this...
+ if( sg->val2 < 1 )
+ {
+ int heal, sp;
+ struct map_session_data *sd = (struct map_session_data *)bl;
+
+ if( tstatus->hp < tstatus->max_hp )
+ {
+ heal = tstatus->max_hp * (((sg->skill_lv - 1) / 2) + 3) / 100;
+ if( tstatus->hp + heal > tstatus->max_hp )
+ heal = tstatus->max_hp - tstatus->hp;
+ if( heal > 0 )
+ {
+ clif_heal(sd->fd,SP_HP,heal);
+ status_heal(bl, heal, 0, 0);
+ }
+ }
+
+ if( tstatus->sp < tstatus->max_sp )
+ {
+ sp = tstatus->max_sp * (((sg->skill_lv - 1) / 2) + 2) / 100;
+ if( tstatus->sp + sp > tstatus->max_sp )
+ sp = tstatus->max_sp - tstatus->sp;
+ if( sp > 0 )
+ {
+ clif_heal(sd->fd,SP_SP,sp);
+ status_heal(bl, 0, sp, 0);
+ }
+ }
+ sg->val2 = 3; // then every three seconds after.
+ }
+ }
+
+ sg->val3--; // track when units should be unhidden. Initial tick unhides units immediately.
+ if( sg->val3 < 1 )
+ {
+ status_change_end(bl,SC_HIDING,-1);
+ status_change_end(bl,SC_CLOAKING,-1);
+ sg->val3 = 5; //then every five seconds after.
+ }
+ break;
}
if (sg->state.magic_power && sc && !sc->data[SC_MAGICPOWER])
@@ -7760,6 +8106,7 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in
switch(sg->unit_id){
case UNT_SAFETYWALL:
case UNT_PNEUMA:
+ case UNT_EPICLESIS:
if (sce)
status_change_end(bl, type, INVALID_TIMER);
break;
@@ -8004,6 +8351,13 @@ static int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
p_sd[(*c)++]=tsd->bl.id;
return 1;
}
+ case AB_ADORAMUS:
+ {
+ int skilllv = pc_checkskill(sd,skillid);
+ if( (tsd->class_&MAPID_UPPERMASK) == MAPID_PRIEST && tsd->status.sp >= 2*skilllv)
+ p_sd[(*c)++]=tsd->bl.id;
+ return 1;
+ }
default: //Warning: Assuming Ensemble Dance/Songs for code speed. [Skotlex]
{
int skilllv;
@@ -8053,6 +8407,10 @@ int skill_check_pc_partner (struct map_session_data *sd, short skill_id, short*
status_charge(&tsd->bl, 0, 10);
}
return c;
+ case AB_ADORAMUS:
+ if( c > 0 && (tsd = map_id2sd(p_sd[0])) != NULL )
+ status_charge(&tsd->bl, 0, 2*(*skill_lv));
+ break;
default: //Warning: Assuming Ensemble skills here (for speed)
if (c > 0 && sd->sc.data[SC_DANCING] && (tsd = map_id2sd(p_sd[0])) != NULL)
{
@@ -8071,7 +8429,7 @@ int skill_check_pc_partner (struct map_session_data *sd, short skill_id, short*
memset (p_sd, 0, sizeof(p_sd));
i = map_foreachinrange(skill_check_condition_char_sub, &sd->bl, range, BL_PC, &sd->bl, &c, &p_sd, skill_id);
- if (skill_id != PR_BENEDICTIO) //Apply the average lv to encore skills.
+ if (skill_id != PR_BENEDICTIO || skill_id != AB_ADORAMUS) //Apply the average lv to encore skills.
*skill_lv = (i+(*skill_lv))/(c+1); //I know c should be one, but this shows how it could be used for the average of n partners.
return c;
}
@@ -8180,7 +8538,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
if( pc_is90overweight(sd) )
{
- clif_skill_fail(sd,skill,9,0);
+ clif_skill_fail(sd,skill,9,0,0);
return 0;
}
@@ -8207,7 +8565,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
{
case SA_CASTCANCEL:
if(sd->ud.skilltimer == INVALID_TIMER) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
@@ -8219,7 +8577,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
break;
case MO_CALLSPIRITS:
if(sd->spiritball >= lv) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
@@ -8270,7 +8628,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
}
else if( !unit_can_move(&sd->bl) )
{ //Placed here as ST_MOVE_ENABLE should not apply if rooted or on a combo. [Skotlex]
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
@@ -8278,7 +8636,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
case TK_MISSION:
if( (sd->class_&MAPID_UPPERMASK) != MAPID_TAEKWON )
{// Cannot be used by Non-Taekwon classes
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
@@ -8290,7 +8648,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
case TK_JUMPKICK:
if( (sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER )
{// Soul Linkers cannot use this skill
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
@@ -8323,7 +8681,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
int time;
if(!(sc && sc->data[SC_DANCING]))
{
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
time = 1000*(sc->data[SC_DANCING]->val3>>16);
@@ -8332,7 +8690,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
(sc->data[SC_DANCING]->val1>>16)) //Dance Skill LV
- time <= skill_get_time2(skill,lv))
{
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
}
@@ -8341,7 +8699,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
case PR_BENEDICTIO:
if (skill_check_pc_partner(sd, skill, &lv, 1, 0) < 2)
{
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
@@ -8359,7 +8717,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
case CG_HERMODE:
if(!npc_check_areanpc(1,sd->bl.m,sd->bl.x,sd->bl.y,skill_get_splash(skill, lv)))
{
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
@@ -8371,7 +8729,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
x = sd->bl.x+(i%size-range);
y = sd->bl.y+(i/size-range);
if (map_getcell(sd->bl.m,x,y,CELL_CHKWALL)) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
}
@@ -8382,7 +8740,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
int exp;
if( ((exp = pc_nextbaseexp(sd)) > 0 && get_percentage(sd->status.base_exp, exp) < 1) ||
((exp = pc_nextjobexp(sd)) > 0 && get_percentage(sd->status.job_exp, exp) < 1)) {
- clif_skill_fail(sd,skill,0,0); //Not enough exp.
+ clif_skill_fail(sd,skill,0,0,0); //Not enough exp.
return 0;
}
break;
@@ -8391,7 +8749,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
case AM_TWILIGHT3:
if (!party_skill_check(sd, sd->status.party_id, skill, lv))
{
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
@@ -8403,7 +8761,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
i = skill-SG_SUN_WARM;
if (sd->bl.m == sd->feel_map[i].m)
break;
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
break;
case SG_SUN_COMFORT:
@@ -8415,7 +8773,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
if (sd->bl.m == sd->feel_map[i].m &&
(battle_config.allow_skill_without_day || sg_info[i].day_func()))
break;
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
case SG_FUSION:
if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_STAR)
@@ -8425,7 +8783,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
if( require.sp > 0 )
{
if (status->sp < (unsigned int)require.sp)
- clif_skill_fail(sd,skill,1,0);
+ clif_skill_fail(sd,skill,1,0,0);
else
status_zap(&sd->bl, 0, require.sp);
}
@@ -8434,7 +8792,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
case GD_REGENERATION:
case GD_RESTORE:
if (!map_flag_gvg2(sd->bl.m)) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
case GD_EMERGENCYCALL:
@@ -8445,26 +8803,26 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
case GS_GLITTERING:
if(sd->spiritball >= 10) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
case NJ_ISSEN:
if (status->hp < 2) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
case NJ_BUNSINJYUTSU:
if (!(sc && sc->data[SC_NEN])) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
case NJ_ZENYNAGE:
if(sd->status.zeny < require.zeny) {
- clif_skill_fail(sd,skill,5,0);
+ clif_skill_fail(sd,skill,5,0,0);
return 0;
}
break;
@@ -8474,82 +8832,119 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
break;
case AM_CALLHOMUN: //Can't summon if a hom is already out
if (sd->status.hom_id && sd->hd && !sd->hd->homunculus.vaporize) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
case AM_REST: //Can't vapo homun if you don't have an active homunc or it's hp is < 80%
if (!merc_is_hom_active(sd->hd) || sd->hd->battle_status.hp < (sd->hd->battle_status.max_hp*80/100))
{
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
+ return 0;
+ }
+ break;
+ case AB_ANCILLA:
+ i = pc_search_inventory(sd,12333);
+ if( i >= 0 && sd->status.inventory[i].amount >= 3 )
+ {
+ clif_skill_fail(sd, skill, 12, 0, 0);
+ return 0;
+ }
+ break;
+ case AB_ADORAMUS: // Should this be here or in skill_check_condition_castend?
+ i = pc_search_inventory(sd,require.itemid[0]);
+ if( skill_check_pc_partner(sd,skill,&lv,1,0) <= 0 &&
+ (i < 0 || sd->status.inventory[i].amount < require.amount[0]) )
+ {
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
+ case AB_EPICLESIS: // Skill should fail if items are not present. Why the curveball, RO?
+ if ( require.itemid[0] )
+ {
+ i = pc_search_inventory(sd,require.itemid[0]);
+ if( i < 0 || sd->status.inventory[i].amount < require.amount[0] )
+ {
+ clif_skill_fail(sd,skill,14,0,0); //Ancilla required
+ return 0;
+ }
+ }
+ if ( require.itemid[1] )
+ {
+ i = pc_search_inventory(sd,require.itemid[1]);
+ if(i < 0 || sd->status.inventory[i].amount < require.amount[1] )
+ {
+ clif_skill_fail(sd,skill,13,0,0); //Holy Water required
+ return 0;
+ }
+ }
+ break;
}
switch(require.state) {
case ST_HIDING:
if(!(sc && sc->option&OPTION_HIDE)) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
case ST_CLOAKING:
if(!pc_iscloaking(sd)) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
case ST_HIDDEN:
if(!pc_ishiding(sd)) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
case ST_RIDING:
if(!pc_isriding(sd)) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
case ST_FALCON:
if(!pc_isfalcon(sd)) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
case ST_CARTBOOST:
if(!(sc && sc->data[SC_CARTBOOST])) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
case ST_CART:
if(!pc_iscarton(sd)) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
case ST_SHIELD:
if(sd->status.shield <= 0) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
case ST_SIGHT:
if(!(sc && sc->data[SC_SIGHT])) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
case ST_EXPLOSIONSPIRITS:
if(!(sc && sc->data[SC_EXPLOSIONSPIRITS])) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
case ST_RECOV_WEIGHT_RATE:
if(battle_config.natural_heal_weight_rate <= 100 && sd->weight*100/sd->max_weight >= (unsigned int)battle_config.natural_heal_weight_rate) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
@@ -8558,7 +8953,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
sd->ud.canmove_tick = gettick(); //When using a combo, cancel the can't move delay to enable the skill. [Skotlex]
if (!unit_can_move(&sd->bl)) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
break;
@@ -8567,34 +8962,34 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
break;
if (map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER))
break;
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
if(require.mhp > 0 && get_percentage(status->hp, status->max_hp) > require.mhp) {
//mhp is the max-hp-requirement, that is,
//you must have this % or less of HP to cast it.
- clif_skill_fail(sd,skill,2,0);
+ clif_skill_fail(sd,skill,2,0,0);
return 0;
}
if( require.weapon && !pc_check_weapontype(sd,require.weapon) ) {
- clif_skill_fail(sd,skill,6,0);
+ clif_skill_fail(sd,skill,6,0,0);
return 0;
}
if( require.sp > 0 && status->sp < (unsigned int)require.sp) {
- clif_skill_fail(sd,skill,1,0);
+ clif_skill_fail(sd,skill,1,0,0);
return 0;
}
if( require.zeny > 0 && sd->status.zeny < require.zeny ) {
- clif_skill_fail(sd,skill,5,0);
+ clif_skill_fail(sd,skill,5,0,0);
return 0;
}
if( require.spiritball > 0 && sd->spiritball < require.spiritball) {
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
@@ -8639,7 +9034,7 @@ int skill_check_condition_castend(struct map_session_data* sd, short skill, shor
if( pc_is90overweight(sd) )
{
- clif_skill_fail(sd,skill,9,0);
+ clif_skill_fail(sd,skill,9,0,0);
return 0;
}
@@ -8662,12 +9057,20 @@ int skill_check_condition_castend(struct map_session_data* sd, short skill, shor
if(c >= maxcount ||
(skill==AM_CANNIBALIZE && c != i && battle_config.summon_flora&2))
{ //Fails when: exceed max limit. There are other plant types already out.
- clif_skill_fail(sd,skill,0,0);
+ clif_skill_fail(sd,skill,0,0,0);
return 0;
}
}
break;
}
+ case AB_LAUDAAGNUS:
+ case AB_LAUDARAMUS:
+ if( !sd->status.party_id )
+ {
+ clif_skill_fail(sd,skill,0,0,0);
+ return 0;
+ }
+ break;
}
status = &sd->battle_status;
@@ -8675,7 +9078,7 @@ int skill_check_condition_castend(struct map_session_data* sd, short skill, shor
require = skill_get_requirement(sd,skill,lv);
if( require.hp > 0 && status->hp <= (unsigned int)require.hp) {
- clif_skill_fail(sd,skill,2,0);
+ clif_skill_fail(sd,skill,2,0,0);
return 0;
}
@@ -8703,11 +9106,18 @@ int skill_check_condition_castend(struct map_session_data* sd, short skill, shor
index[i] = pc_search_inventory(sd,require.itemid[i]);
if( index[i] < 0 || sd->status.inventory[index[i]].amount < require.amount[i] ) {
if( require.itemid[i] == ITEMID_RED_GEMSTONE )
- clif_skill_fail(sd,skill,7,0);// red gemstone required
+ clif_skill_fail(sd,skill,7,0,0);// red gemstone required
else if( require.itemid[i] == ITEMID_BLUE_GEMSTONE )
- clif_skill_fail(sd,skill,8,0);// blue gemstone required
+ clif_skill_fail(sd,skill,8,0,0);// blue gemstone required
+ else if( require.itemid[i] == 523 )
+ clif_skill_fail(sd,skill,13,0,0); //Holy Water required
+ else if( require.itemid[i] == 12333 )
+ clif_skill_fail(sd,skill,14,0,0); //Ancilla required
else
- clif_skill_fail(sd,skill,0,0);
+ {
+ //clif_skill_fail(sd,skill,71,require.amount[i],require.itemid[i]);
+ clif_skill_fail(sd,skill,0,0,0);
+ }
return 0;
}
}
@@ -8864,7 +9274,8 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, short
if( itemid_isgemstone(req.itemid[i]) && skill != HW_GANBANTEIN )
{
- if( sd->special_state.no_gemstone )
+ if( sd->special_state.no_gemstone ||
+ (skill == AB_ADORAMUS && skill_check_pc_partner(sd,skill,&lv, 1, 2) )) // Do not consume Gemstone if next to another priest.
{ //Make it substract 1 gem rather than skipping the cost.
if( --req.amount[i] < 1 )
req.itemid[i] = 0;
@@ -8949,22 +9360,39 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, short
*------------------------------------------*/
int skill_castfix (struct block_list *bl, int skill_id, int skill_lv)
{
- int time = skill_get_cast(skill_id, skill_lv);
+ int scale = 0, max_fixedReduction = 0;
+ int time = skill_get_cast(skill_id, skill_lv); // Skill's base cast time.
+ int fixedcasttime = skill_get_fixedcast(skill_id, skill_lv); // Skills fixed cast time.
struct map_session_data *sd;
+ struct status_change *sc;
nullpo_ret(bl);
sd = BL_CAST(BL_PC, bl);
+ sc = status_get_sc(bl);
- // calculate base cast time (reduced by dex)
+ // calculate base cast time (reduced by dex and int)
if( !(skill_get_castnodex(skill_id, skill_lv)&1) )
+ {
+ // iRO Wiki states as of 2011/08/22:
+ // castTime = (1 - SQRT((DEX * 2 + INT) / 530)) * (1 - sum_castReduction/100%) * baseCast * 0.8 + (1 - max_fixedReduction/100%) * baseCast * 0.2
+ // let's do (DEX * 2 + INT) here; the rest will come after.
+ scale = cap_value((status_get_dex(bl) * 2 + status_get_int(bl)) * 10000, 0, INT_MAX);
+ }
+
+ //apply variable cast rate modifiers via status effects.
+ if( !(skill_get_castnodex(skill_id, skill_lv)&2) && sc && sc->count )
{
- int scale = battle_config.castrate_dex_scale - status_get_dex(bl);
- if( scale > 0 ) // not instant cast
- time = time * scale / battle_config.castrate_dex_scale;
- else return 0; // instant cast
+ if (sc->data[SC_SLOWCAST])
+ time += time * sc->data[SC_SLOWCAST]->val2 / 100;
+ if (sc->data[SC_SUFFRAGIUM])
+ time -= time * sc->data[SC_SUFFRAGIUM]->val2 / 100;
+ if (sc->data[SC_MEMORIZE])
+ time>>=1;
+ if (sc->data[SC_POEMBRAGI])
+ time -= time * sc->data[SC_POEMBRAGI]->val2 / 100;
}
- // calculate cast time reduced by item/card bonuses
+ // calculate variable cast time reduced by item/card bonuses
if( !(skill_get_castnodex(skill_id, skill_lv)&4) && sd )
{
int i;
@@ -8980,6 +9408,41 @@ int skill_castfix (struct block_list *bl, int skill_id, int skill_lv)
}
}
+ //TODO: apply fixed cast rate modifiers via status effects.
+ if( !(skill_get_castnodex(skill_id, skill_lv)&2) && sc && sc->count )
+ {
+ if( sc->data[SC_AB_SECRAMENT] && sc->data[SC_AB_SECRAMENT]->val2 > max_fixedReduction )
+ max_fixedReduction = sc->data[SC_AB_SECRAMENT]->val2;
+ }
+
+ // calculate fixed cast time reduced by item/card bonuses
+ if( !(skill_get_castnodex(skill_id, skill_lv)&4) && sd )
+ {
+ int i;
+ if( sd->fixedcastrate != 100 )
+ fixedcasttime = fixedcasttime * sd->fixedcastrate / 100;
+ for( i = 0; i < ARRAYLENGTH(sd->skillcast) && sd->skillcast[i].id; i++ )
+ {
+ if( sd->skillcast[i].id == skill_id )
+ {
+ fixedcasttime+= fixedcasttime * sd->skillcast[i].val / 100;
+ break;
+ }
+ }
+ }
+
+ // Apply more of the cast time formula for variable cast time post reduction.
+ // Now let's do (1 - SQRT(scale / 530)) * (1 - sum_castReduction/100%)
+ // Ensure this value is not reduced past 0.
+ time = cap_value((100 - (int)sqrt(scale/530.)) * time / 100, 0, INT_MAX);
+
+ // Reduce fixedcasttime by only the highest max_fixedReduction found
+ if( max_fixedReduction )
+ fixedcasttime -= fixedcasttime * max_fixedReduction / 100;
+
+ // Apply the modified fixed cast time to variable cast time.
+ time += fixedcasttime;
+
// config cast time multiplier
if (battle_config.cast_rate != 100)
time = time * battle_config.cast_rate / 100;
@@ -8989,31 +9452,6 @@ int skill_castfix (struct block_list *bl, int skill_id, int skill_lv)
}
/*==========================================
- * Does cast-time reductions based on sc data.
- *------------------------------------------*/
-int skill_castfix_sc (struct block_list *bl, int time)
-{
- struct status_change *sc = status_get_sc(bl);
-
- if (sc && sc->count) {
- if (sc->data[SC_SLOWCAST])
- time += time * sc->data[SC_SLOWCAST]->val2 / 100;
- if (sc->data[SC_SUFFRAGIUM]) {
- time -= time * sc->data[SC_SUFFRAGIUM]->val2 / 100;
- status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER);
- }
- if (sc->data[SC_MEMORIZE]) {
- time>>=1;
- if ((--sc->data[SC_MEMORIZE]->val2) <= 0)
- status_change_end(bl, SC_MEMORIZE, INVALID_TIMER);
- }
- if (sc->data[SC_POEMBRAGI])
- time -= time * sc->data[SC_POEMBRAGI]->val2 / 100;
- }
- return (time > 0) ? time : 0;
-}
-
-/*==========================================
* Does delay reductions based on dex/agi, sc data, item bonuses, ...
*------------------------------------------*/
int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv)
@@ -9049,23 +9487,6 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv)
if( sc && !sc->data[SC_BASILICA] )
time = 0; // There is no Delay on Basilica creation, only on cancel
break;
- default:
- if (battle_config.delay_dependon_dex && !(delaynodex&1))
- { // if skill delay is allowed to be reduced by dex
- int scale = battle_config.castrate_dex_scale - status_get_dex(bl);
- if (scale > 0)
- time = time * scale / battle_config.castrate_dex_scale;
- else //To be capped later to minimum.
- time = 0;
- }
- if (battle_config.delay_dependon_agi && !(delaynodex&1))
- { // if skill delay is allowed to be reduced by agi
- int scale = battle_config.castrate_dex_scale - status_get_agi(bl);
- if (scale > 0)
- time = time * scale / battle_config.castrate_dex_scale;
- else //To be capped later to minimum.
- time = 0;
- }
}
if ( sc && sc->data[SC_SPIRIT] )
@@ -9314,7 +9735,7 @@ void skill_repairweapon (struct map_session_data *sd, int idx)
else
material = materials [2]; // Armors consume 1 Steel
if (pc_search_inventory(sd,material) < 0 ) {
- clif_skill_fail(sd,sd->menuskill_id,0,0);
+ clif_skill_fail(sd,sd->menuskill_id,0,0,0);
return;
}
clif_skill_nodamage(&sd->bl,&target_sd->bl,sd->menuskill_id,1,1);
@@ -9367,7 +9788,7 @@ void skill_weaponrefine (struct map_session_data *sd, int idx)
|| ditem->flag.no_refine // if the item isn't refinable
|| (i = pc_search_inventory(sd, material [ditem->wlv])) < 0 )
{
- clif_skill_fail(sd,sd->menuskill_id,0,0);
+ clif_skill_fail(sd,sd->menuskill_id,0,0,0);
return;
}
@@ -11707,17 +12128,19 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current)
}
static bool skill_parse_row_castdb(char* split[], int columns, int current)
-{// SkillID,CastingTime,AfterCastActDelay,AfterCastWalkDelay,Duration1,Duration2
+{// SkillID,CastingTime,FixedCastingTime,AfterCastActDelay,Cooldown,AfterCastWalkDelay,Duration1,Duration2
int i = atoi(split[0]);
i = skill_get_index(i);
if( !i ) // invalid skill id
return false;
skill_split_atoi(split[1],skill_db[i].cast);
- skill_split_atoi(split[2],skill_db[i].delay);
- skill_split_atoi(split[3],skill_db[i].walkdelay);
- skill_split_atoi(split[4],skill_db[i].upkeep_time);
- skill_split_atoi(split[5],skill_db[i].upkeep_time2);
+ skill_split_atoi(split[2],skill_db[i].fixedcast);
+ skill_split_atoi(split[3],skill_db[i].delay);
+ skill_split_atoi(split[4],skill_db[i].cooldown);
+ skill_split_atoi(split[5],skill_db[i].walkdelay);
+ skill_split_atoi(split[6],skill_db[i].upkeep_time);
+ skill_split_atoi(split[7],skill_db[i].upkeep_time2);
return true;
}
@@ -11864,7 +12287,7 @@ static void skill_readdb(void)
safestrncpy(skill_db[0].desc, "Unknown Skill", sizeof(skill_db[0].desc));
sv_readdb(db_path, "skill_db.txt" , ',', 17, 17, MAX_SKILL_DB, skill_parse_row_skilldb);
sv_readdb(db_path, "skill_require_db.txt" , ',', 32, 32, MAX_SKILL_DB, skill_parse_row_requiredb);
- sv_readdb(db_path, "skill_cast_db.txt" , ',', 6, 6, MAX_SKILL_DB, skill_parse_row_castdb);
+ sv_readdb(db_path, "skill_cast_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill_parse_row_castdb);
sv_readdb(db_path, "skill_castnodex_db.txt", ',', 2, 3, MAX_SKILL_DB, skill_parse_row_castnodexdb);
sv_readdb(db_path, "skill_nocast_db.txt" , ',', 2, 2, MAX_SKILL_DB, skill_parse_row_nocastdb);
sv_readdb(db_path, "skill_unit_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill_parse_row_unitdb);