From 1fe2e1773b9a7218fe5e39c4d2116194216b6986 Mon Sep 17 00:00:00 2001 From: L0ne_W0lf Date: Sat, 27 Aug 2011 03:25:00 +0000 Subject: - 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 --- src/map/battle.c | 46 ++- src/map/battle.h | 6 +- src/map/clif.c | 95 +++++-- src/map/clif.h | 2 +- src/map/guild.c | 2 +- src/map/map.h | 2 +- src/map/pc.c | 31 +- src/map/pc.h | 6 +- src/map/script.c | 3 +- src/map/skill.c | 835 ++++++++++++++++++++++++++++++++++++++++-------------- src/map/skill.h | 9 +- src/map/status.c | 196 +++++++++++-- src/map/status.h | 40 ++- src/map/unit.c | 46 +-- src/map/vending.c | 6 +- 15 files changed, 1009 insertions(+), 316 deletions(-) (limited to 'src/map') diff --git a/src/map/battle.c b/src/map/battle.c index f60b375ed..ccda6bc44 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -265,6 +265,9 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag if( tsc->data[SC_SPIDERWEB]->val2 == 0 ) status_change_end(target, SC_SPIDERWEB, INVALID_TIMER); } + if( atk_elem == ELE_HOLY && tsc && tsc->count && tsc->data[SC_ORATIO] ) + ratio += tsc->data[SC_ORATIO]->val2; + return damage*ratio/100; } @@ -1727,6 +1730,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo case NPC_VAMPIRE_GIFT: skillratio += ((skill_lv-1)%5+1)*100; break; + case AB_DUPLELIGHT_MELEE: + skillratio += 100 + 10 * skill_lv; + break; } ATK_RATE(skillratio); @@ -1842,6 +1848,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo signed char def1 = status_get_def(target); //Don't use tstatus->def1 due to skill timer reductions. short def2 = (short)tstatus->def2; + if( sc && sc->data[SC_EXPIATIO] ) + { + def1 -= def1 * sc->data[SC_EXPIATIO]->val2 / 100; + def2 -= def2 * sc->data[SC_EXPIATIO]->val2 / 100; + } + if( sd ) { i = sd->ignore_def[is_boss(target)?RC_BOSS:RC_NONBOSS]; @@ -2398,6 +2410,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list case AL_HEAL: case PR_BENEDICTIO: case PR_SANCTUARY: + case AB_HIGHNESSHEAL: ad.damage = skill_calc_heal(src, target, skill_num, skill_lv, false); break; case PR_ASPERSIO: @@ -2417,6 +2430,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list case PF_SOULBURN: ad.damage = tstatus->sp * 2; break; + case AB_RENOVATIO: + ad.damage = (int)((15 * status_get_lv(src)) + (1.5 * sstatus->int_)); + break; default: { if (sstatus->matk_max > sstatus->matk_min) { @@ -2513,6 +2529,15 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list case NPC_EARTHQUAKE: skillratio += 100 +100*skill_lv +100*(skill_lv/2); break; + case AB_JUDEX: + skillratio += ((skill_lv < 5)?280 + 20 * skill_lv:400) * (status_get_lv(src) / 100); // Possible RE-Formula + break; + case AB_ADORAMUS: + skillratio += (500 + 100 * skill_lv) * (status_get_lv(src) / 100); //Possible RE-Formula + break; + case AB_DUPLELIGHT_MAGIC: + skillratio += 200 + 20 * skill_lv; + break; } MATK_RATE(skillratio); @@ -3165,6 +3190,14 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t damage = wd.damage + wd.damage2; if( damage > 0 && src != target ) { + if(sc && sc->data[SC_DUPLELIGHT]) { + int skilllv = sc->data[SC_DUPLELIGHT]->val1; + if(rand()%100 < sc->data[SC_DUPLELIGHT]->val2) + skill_addtimerskill(src,tick+status_get_adelay(src) / 2,target->id,0,0,AB_DUPLELIGHT_MELEE,skilllv,BF_WEAPON,flag); + else if(rand()%100 < sc->data[SC_DUPLELIGHT]->val3) + skill_addtimerskill(src,tick+status_get_adelay(src) / 2,target->id,0,0,AB_DUPLELIGHT_MAGIC,skilllv,BF_MAGIC,flag); + } + rdamage = battle_calc_return_damage(target, damage, wd.flag); if( rdamage > 0 ) { @@ -3636,8 +3669,6 @@ static const struct _battle_data { { "enable_perfect_flee", &battle_config.enable_perfect_flee, BL_PC|BL_PET, BL_NUL, BL_ALL, }, { "casting_rate", &battle_config.cast_rate, 100, 0, INT_MAX, }, { "delay_rate", &battle_config.delay_rate, 100, 0, INT_MAX, }, - { "delay_dependon_dex", &battle_config.delay_dependon_dex, 0, 0, 1, }, - { "delay_dependon_agi", &battle_config.delay_dependon_agi, 0, 0, 1, }, { "skill_delay_attack_enable", &battle_config.sdelay_attack_enable, 0, 0, 1, }, { "left_cardfix_to_right", &battle_config.left_cardfix_to_right, 0, 0, 1, }, { "skill_add_range", &battle_config.skill_add_range, 0, 0, INT_MAX, }, @@ -3773,7 +3804,7 @@ static const struct _battle_data { { "max_baby_parameter", &battle_config.max_baby_parameter, 80, 10, 10000, }, { "max_third_parameter", &battle_config.max_third_parameter, 120, 10, 10000, }, { "max_baby_third_parameter", &battle_config.max_baby_third_parameter, 108, 10, 10000, }, - { "max_def", &battle_config.max_def, 99, 0, INT_MAX, }, + { "max_def", &battle_config.max_def, 9999, 0, INT_MAX, }, { "over_def_bonus", &battle_config.over_def_bonus, 0, 0, 1000, }, { "skill_log", &battle_config.skill_log, BL_NUL, BL_NUL, BL_ALL, }, { "battle_log", &battle_config.battle_log, 0, 0, 1, }, @@ -3907,7 +3938,6 @@ static const struct _battle_data { { "min_cloth_color", &battle_config.min_cloth_color, 0, 0, INT_MAX, }, { "max_cloth_color", &battle_config.max_cloth_color, 4, 0, INT_MAX, }, { "pet_hair_style", &battle_config.pet_hair_style, 100, 0, INT_MAX, }, - { "castrate_dex_scale", &battle_config.castrate_dex_scale, 150, 1, INT_MAX, }, { "area_size", &battle_config.area_size, 14, 0, INT_MAX, }, { "zeny_from_mobs", &battle_config.zeny_from_mobs, 0, 0, 1, }, { "mobs_level_up", &battle_config.mobs_level_up, 0, 0, 1, }, @@ -4024,6 +4054,10 @@ static const struct _battle_data { { "bg_magic_attack_damage_rate", &battle_config.bg_magic_damage_rate, 60, 0, INT_MAX, }, { "bg_misc_attack_damage_rate", &battle_config.bg_misc_damage_rate, 60, 0, INT_MAX, }, { "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, }, +//MVP Decrease AGI + { "max_decagi_lv", &battle_config.max_decagi_lv, 11, 1, INT_MAX, }, + { "max_decagi_dur", &battle_config.max_decagi_dur, 120000, 1, INT_MAX, }, + { "max_decagi", &battle_config.max_decagi, 50, 0, INT_MAX, }, }; @@ -4070,8 +4104,8 @@ void battle_adjust_conf() battle_config.max_walk_speed = 100*DEFAULT_WALK_SPEED/battle_config.max_walk_speed; battle_config.max_cart_weight *= 10; - if(battle_config.max_def > 100 && !battle_config.weapon_defense_type) // added by [Skotlex] - battle_config.max_def = 100; + if(battle_config.max_def > 9999 && !battle_config.weapon_defense_type) // added by [Skotlex] + battle_config.max_def = 9999; if(battle_config.min_hitrate > battle_config.max_hitrate) battle_config.min_hitrate = battle_config.max_hitrate; diff --git a/src/map/battle.h b/src/map/battle.h index d54d49c0a..100174fcc 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -111,7 +111,6 @@ extern struct Battle_Config int enable_baseatk; int enable_perfect_flee; int cast_rate, delay_rate; - int delay_dependon_dex, delay_dependon_agi; int sdelay_attack_enable; int left_cardfix_to_right; int skill_add_range; @@ -363,7 +362,6 @@ extern struct Battle_Config int max_cloth_color; // added by [MouseJstr] int pet_hair_style; // added by [Skotlex] - int castrate_dex_scale; // added by [MouseJstr] int area_size; // added by [MouseJstr] int max_def, over_def_bonus; //added by [Skotlex] @@ -496,6 +494,10 @@ extern struct Battle_Config int bg_magic_damage_rate; int bg_misc_damage_rate; int bg_flee_penalty; + + int max_decagi_lv; + int max_decagi_dur; + int max_decagi; } battle_config; void do_init_battle(void); diff --git a/src/map/clif.c b/src/map/clif.c index 8d2159823..9c8fabfbf 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -2512,10 +2512,10 @@ int clif_updatestatus(struct map_session_data *sd,int type) WFIFOL(fd,4)=sd->battle_status.cri/10; break; case SP_MATK1: - WFIFOL(fd,4)=sd->battle_status.matk_max; + WFIFOL(fd,4)=sd->weapon_matk + sd->battle_status.rhw.atk2 + sd->equipment_matk; break; case SP_MATK2: - WFIFOL(fd,4)=sd->battle_status.matk_min; + WFIFOL(fd,4)=sd->battle_status.status_matk; break; @@ -2842,9 +2842,9 @@ int clif_initialstatus(struct map_session_data *sd) WBUFB(buf,14)=min(sd->status.luk, UCHAR_MAX); WBUFB(buf,15)=pc_need_status_point(sd,SP_LUK,1); - WBUFW(buf,16) = sd->battle_status.batk + sd->battle_status.rhw.atk + sd->battle_status.lhw.atk; + WBUFW(buf,16) = sd->battle_status.batk; WBUFW(buf,18) = sd->battle_status.rhw.atk2 + sd->battle_status.lhw.atk2; //atk bonus - WBUFW(buf,20) = sd->battle_status.matk_max; + WBUFW(buf,20) = sd->weapon_matk + sd->battle_status.rhw.atk2 + sd->equipment_matk; WBUFW(buf,22) = sd->battle_status.matk_min; WBUFW(buf,24) = sd->battle_status.def; // def WBUFW(buf,26) = sd->battle_status.def2; @@ -2872,6 +2872,9 @@ int clif_initialstatus(struct map_session_data *sd) clif_updatestatus(sd,SP_ATTACKRANGE); clif_updatestatus(sd,SP_ASPD); + clif_updatestatus(sd,SP_MATK1); + clif_updatestatus(sd,SP_MATK2); + return 0; } @@ -4357,7 +4360,8 @@ int clif_skillcastcancel(struct block_list* bl) /// btype==5 "no shout" MsgStringTable[164] /// btype==6 "no PKing" MsgStringTable[165] /// btype==7 "no alligning" MsgStringTable[383] -/// btype>=8: ignored +/// btype==8: "Insufficient level for joining a Party" +/// btype>=9: Ignored. /// if(skill_id==AL_WARP) "not enough skill level" MsgStringTable[214] /// if(skill_id==TF_STEAL) "steal failed" MsgStringTable[205] /// if(skill_id==TF_POISON) "envenom failed" MsgStringTable[207] @@ -4373,12 +4377,43 @@ int clif_skillcastcancel(struct block_list* bl) /// type==8 "blue gemstone needed" MsgStringTable[247] /// type==9 "overweight" MsgStringTable[580] /// type==10 "skill failed" MsgStringTable[285] -/// type>=11 ignored +/// type==11 "This skill can't be used on that object" +/// type==12 "You can't use skill because you have exceeded the number Ansila possession limit" +/// type==13 "need Holy Water" +/// type==14 "need Ancilla to cast skill" +/// type==15 "Can't be duplicated with certain distance" +/// type==16 "In order to use this skill, you need other skill" +/// type==17 "This skill can't be used alone" +/// type==18 "This skill can be used to certain direction only" +/// type==19 "Can't summon anymore" +/// type==20 "There is no summoned sphere" +/// type==21 "There exists no usable imitaion skill" +/// type==22 "You can't reuse this skill" +/// type==23 "Skill can't be used in this state" +/// type==24 "Paintbrush is needed" +/// type==25 "available only on the dragon" +/// type==26 "Skill can't be used on designated spot " +/// type==27 "Assistant SP is not enough" +/// type==31 "Can only be used for linked to weapon blocking" +/// type==32 "Need a weapon coated with poison of a guillotine cross v" +/// type==33 "Can only be used while riding Madogear" +/// type==37 "Load a Cannon Ball" +/// type==40 "Can only be used in Hovering state" +/// type==43 "Need a Guillotine Poison" +/// type==50 "Can't be used while on Magic Gear" +/// type==51 "Need a Magic Book" +/// type==52 "Feel sleepy since Magic Book is too difficult to understand" +/// type==53 "Not enough saved point" +/// type==54 "Can't read a Magic Book anymore" +/// type==57 "usable only when cart is put on" +/// type==60 "Can't cast anymore" +/// type==71 "[ITEMID] need AMOUNT" +/// type==72 "Need to put on [ITEMID] in order to use" /// /// if(success!=0) doesn't display any of the previous messages /// Note: when this packet is received an unknown flag is always set to 0, /// suggesting this is an ACK packet for the UseSkill packets and should be sent on success too [FlavioJS] -int clif_skill_fail(struct map_session_data *sd,int skill_id,int type,int btype) +int clif_skill_fail(struct map_session_data *sd,int skill_id,int type,int btype, int val) { int fd; @@ -4405,8 +4440,9 @@ int clif_skill_fail(struct map_session_data *sd,int skill_id,int type,int btype) WFIFOHEAD(fd,packet_len(0x110)); WFIFOW(fd,0) = 0x110; WFIFOW(fd,2) = skill_id; - WFIFOL(fd,4) = btype; - WFIFOB(fd,8) = 0;// success + WFIFOW(fd,4) = btype; + WFIFOW(fd,6) = val; + WFIFOB(fd,8) = 0; WFIFOB(fd,9) = type; WFIFOSET(fd,packet_len(0x110)); @@ -4896,7 +4932,8 @@ int clif_status_change(struct block_list *bl,int type,int flag,unsigned int tick type == SI_TENSIONRELAX || type == SI_LANDENDOW || type == SI_AUTOBERSERK || type == SI_BUMP || type == SI_READYSTORM || type == SI_READYDOWN || type == SI_READYTURN || type == SI_READYCOUNTER || type == SI_DODGE || - type == SI_DEVIL || type == SI_NIGHT || type == SI_INTRAVISION) + type == SI_DEVIL || type == SI_NIGHT || type == SI_INTRAVISION || + type == SI_CLOAKING) tick=0; if( battle_config.display_status_timers && tick>0 ) @@ -5381,7 +5418,7 @@ int clif_item_repair_list(struct map_session_data *sd,struct map_session_data *d sd->menuskill_id = BS_REPAIRWEAPON; sd->menuskill_val = dstsd->bl.id; }else - clif_skill_fail(sd,sd->ud.skillid,0,0); + clif_skill_fail(sd,sd->ud.skillid,0,0,0); return 0; } @@ -9037,13 +9074,13 @@ void clif_parse_Emotion(int fd, struct map_session_data *sd) if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, NV_BASIC) >= 2) { if (emoticon == E_MUTE) {// prevent use of the mute emote [Valaris] - clif_skill_fail(sd, 1, 0, 1); + clif_skill_fail(sd, 1, 0, 1, 0); return; } // fix flood of emotion icon (ro-proxy): flood only the hacker player if (sd->emotionlasttime >= time(NULL)) { sd->emotionlasttime = time(NULL) + 1; // not more than 1 per second (using /commands the client can spam it) - clif_skill_fail(sd, 1, 0, 1); + clif_skill_fail(sd, 1, 0, 1, 0); return; } sd->emotionlasttime = time(NULL) + 1; // not more than 1 per second (using /commands the client can spam it) @@ -9055,7 +9092,7 @@ void clif_parse_Emotion(int fd, struct map_session_data *sd) clif_emotion(&sd->bl, emoticon); } else - clif_skill_fail(sd, 1, 0, 1); + clif_skill_fail(sd, 1, 0, 1, 0); } /*========================================== @@ -9104,7 +9141,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, if (!battle_config.sdelay_attack_enable && pc_checkskill(sd, SA_FREECAST) <= 0) { if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) { - clif_skill_fail(sd, 1, 4, 0); + clif_skill_fail(sd, 1, 4, 0, 0); return; } } @@ -9115,7 +9152,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, break; case 0x02: // sitdown if (battle_config.basic_skill_check && pc_checkskill(sd, NV_BASIC) < 3) { - clif_skill_fail(sd, 1, 0, 2); + clif_skill_fail(sd, 1, 0, 2, 0); break; } @@ -9642,7 +9679,7 @@ void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd) if (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) return; if(battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 4) { - clif_skill_fail(sd,1,0,3); + clif_skill_fail(sd,1,0,3,0); return; } @@ -9754,7 +9791,7 @@ void clif_parse_TradeRequest(int fd,struct map_session_data *sd) if( battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 1) { - clif_skill_fail(sd,1,0,0); + clif_skill_fail(sd,1,0,0,0); return; } @@ -9940,7 +9977,7 @@ static void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct return; if( DIFF_TICK(tick, md->ud.canact_tick) < 0 ) { - clif_skill_fail(md->master, skillnum, 4, 0); + clif_skill_fail(md->master, skillnum, 4, 0, 0); return; } @@ -10010,7 +10047,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) { if( sd->skillitem != skillnum ) { - clif_skill_fail(sd, skillnum, 4, 0); + clif_skill_fail(sd, skillnum, 0x04, 0, 0); return; } } @@ -10086,7 +10123,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, short skil { if( pc_issit(sd) ) { - clif_skill_fail(sd, skillnum, 0, 0); + clif_skill_fail(sd, skillnum, 0, 0, 0); return; } //You can't use Graffiti/TalkieBox AND have a vending open, so this is safe. @@ -10100,7 +10137,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, short skil { if( sd->skillitem != skillnum ) { - clif_skill_fail(sd, skillnum, 4, 0); + clif_skill_fail(sd, skillnum, 4, 0, 0); return; } } @@ -10209,7 +10246,7 @@ void clif_parse_ProduceMix(int fd,struct map_session_data *sd) if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skillid,0,0); + clif_skill_fail(sd,sd->ud.skillid,0,0,0); sd->menuskill_val = sd->menuskill_id = 0; return; } @@ -10231,7 +10268,7 @@ void clif_parse_Cooking(int fd,struct map_session_data *sd) if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skillid,0,0); + clif_skill_fail(sd,sd->ud.skillid,0,0,0); sd->menuskill_val = sd->menuskill_id = 0; return; } @@ -10247,7 +10284,7 @@ void clif_parse_RepairItem(int fd, struct map_session_data *sd) return; if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skillid,0,0); + clif_skill_fail(sd,sd->ud.skillid,0,0,0); sd->menuskill_val = sd->menuskill_id = 0; return; } @@ -10266,7 +10303,7 @@ void clif_parse_WeaponRefine(int fd, struct map_session_data *sd) return; if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skillid,0,0); + clif_skill_fail(sd,sd->ud.skillid,0,0,0); sd->menuskill_val = sd->menuskill_id = 0; return; } @@ -10369,7 +10406,7 @@ void clif_parse_SelectArrow(int fd,struct map_session_data *sd) return; if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skillid,0,0); + clif_skill_fail(sd,sd->ud.skillid,0,0,0); sd->menuskill_val = sd->menuskill_id = 0; return; } @@ -10575,7 +10612,7 @@ void clif_parse_CreateParty(int fd, struct map_session_data *sd) } if( battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 7 ) { - clif_skill_fail(sd,1,0,4); + clif_skill_fail(sd,1,0,4,0); return; } @@ -10596,7 +10633,7 @@ void clif_parse_CreateParty2(int fd, struct map_session_data *sd) } if( battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 7 ) { - clif_skill_fail(sd,1,0,4); + clif_skill_fail(sd,1,0,4,0); return; } diff --git a/src/map/clif.h b/src/map/clif.h index 0feeb22b5..b0c4dde8e 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -328,7 +328,7 @@ int clif_deleteskill(struct map_session_data *sd, int skill); void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, int skill_num, int property, int casttime); int clif_skillcastcancel(struct block_list* bl); -int clif_skill_fail(struct map_session_data *sd,int skill_id,int type,int btype); +int clif_skill_fail(struct map_session_data *sd,int skill_id,int type,int btype, int val); int clif_skill_cooldown(struct map_session_data *sd, int skillid, unsigned int tick); int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,int skill_id,int skill_lv,int type); //int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,int skill_id,int skill_lv,int type); diff --git a/src/map/guild.c b/src/map/guild.c index 0b77aa9a1..ca25be9cb 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -1045,7 +1045,7 @@ int guild_change_emblem(struct map_session_data *sd,int len,const char *data) if (battle_config.require_glory_guild && !((g = guild_search(sd->status.guild_id)) && guild_checkskill(g, GD_GLORYGUILD)>0)) { - clif_skill_fail(sd,GD_GLORYGUILD,0,0); + clif_skill_fail(sd,GD_GLORYGUILD,0,0,0); return 0; } diff --git a/src/map/map.h b/src/map/map.h index fe86574bd..a9277c330 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -380,7 +380,7 @@ enum _sp { SP_WEAPON_ATK,SP_WEAPON_ATK_RATE, // 1081-1082 SP_DELAYRATE,SP_HP_DRAIN_RATE_RACE,SP_SP_DRAIN_RATE_RACE, // 1083-1085 SP_IGNORE_MDEF_RATE,SP_IGNORE_DEF_RATE,SP_SKILL_HEAL2,SP_ADDEFF_ONSKILL, //1086-1089 - SP_ADD_HEAL_RATE,SP_ADD_HEAL2_RATE, //1090-1091 + SP_ADD_HEAL_RATE,SP_ADD_HEAL2_RATE,SP_FIXEDCASTRATE,SP_BASE_MATK,SP_WEAPON_MATK,SP_EQUIPMENT_MATK, //1090-1095 SP_RESTART_FULL_RECOVER=2000,SP_NO_CASTCANCEL,SP_NO_SIZEFIX,SP_NO_MAGIC_DAMAGE,SP_NO_WEAPON_DAMAGE,SP_NO_GEMSTONE, // 2000-2005 SP_NO_CASTCANCEL2,SP_NO_MISC_DAMAGE,SP_UNBREAKABLE_WEAPON,SP_UNBREAKABLE_ARMOR, SP_UNBREAKABLE_HELM, // 2006-2010 diff --git a/src/map/pc.c b/src/map/pc.c index 5e454415c..cd00e0ffc 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1962,6 +1962,10 @@ int pc_bonus(struct map_session_data *sd,int type,int val) if(sd->state.lr_flag != 2) sd->castrate+=val; break; + case SP_FIXEDCASTRATE: + if(sd->state.lr_flag != 2) + sd->fixedcastrate+=val; + break; case SP_MAXHPRATE: if(sd->state.lr_flag != 2) sd->hprate+=val; @@ -2009,7 +2013,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) break; case SP_ASPD_RATE: //Stackable increase - Made it linear as per rodatazone if(sd->state.lr_flag != 2) - status->aspd_rate -= 10*val; + status->aspd_rate -= 10 * val; break; case SP_HP_RECOV_RATE: if(sd->state.lr_flag != 2) @@ -2043,6 +2047,14 @@ int pc_bonus(struct map_session_data *sd,int type,int val) if(sd->state.lr_flag != 2) sd->matk_rate += val; break; + case SP_WEAPON_MATK: + if(sd->state.lr_flag != 2) + sd->weapon_matk += val; + break; + case SP_EQUIPMENT_MATK: + if(sd->state.lr_flag != 2) + sd->equipment_matk += val; + break; case SP_IGNORE_DEF_ELE: if(val >= ELE_MAX) { ShowError("pc_bonus: SP_IGNORE_DEF_ELE: Invalid element %d\n", val); @@ -2738,6 +2750,23 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) } break; + case SP_FIXEDCASTRATE: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->fixedskillcast), i, sd->fixedskillcast[i].id == 0 || sd->fixedskillcast[i].id == type2); + if (i == ARRAYLENGTH(sd->fixedskillcast)) + { //Better mention this so the array length can be updated. [Skotlex] + ShowDebug("run_script: bonus2 bFixedCastRate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->fixedskillcast), type2, val); + break; + } + if(sd->fixedskillcast[i].id == type2) + sd->fixedskillcast[i].val += val; + else { + sd->fixedskillcast[i].id = type2; + sd->fixedskillcast[i].val = val; + } + break; + case SP_HP_LOSS_RATE: if(sd->state.lr_flag != 2) { sd->hp_loss.value = type2; diff --git a/src/map/pc.h b/src/map/pc.h index 6cf9be63c..46e96ff85 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -251,7 +251,7 @@ struct map_session_data { struct { //skillatk raises bonus dmg% of skills, skillheal increases heal%, skillblown increases bonus blewcount for some skills. unsigned short id; short val; - } skillatk[MAX_PC_BONUS], skillheal[5], skillheal2[5], skillblown[MAX_PC_BONUS], skillcast[MAX_PC_BONUS]; + } skillatk[MAX_PC_BONUS], skillheal[5], skillheal2[5], skillblown[MAX_PC_BONUS], skillcast[MAX_PC_BONUS], fixedskillcast[MAX_PC_BONUS]; struct { short value; int rate; @@ -309,9 +309,9 @@ struct map_session_data { // zeroed vars end here. - int castrate,delayrate,hprate,sprate,dsprate; + int castrate,fixedcastrate,delayrate,hprate,sprate,dsprate; int hprecov_rate,sprecov_rate; - int matk_rate; + int matk_rate,weapon_matk,equipment_matk; int critical_rate,hit_rate,flee_rate,flee2_rate,def_rate,def2_rate,mdef_rate,mdef2_rate; int itemid; diff --git a/src/map/script.c b/src/map/script.c index 632dc0e14..451e5a40b 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -7016,7 +7016,8 @@ BUILDIN_FUNC(bonus) case SP_ADD_SKILL_BLOW: case SP_CASTRATE: case SP_ADDEFF_ONSKILL: - // these bonuses support skill names + case SP_FIXEDCASTRATE: + // these bonuses support skill names val1 = ( script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3) ); break; default: 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 #include #include - +#include #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;idata[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; @@ -8988,31 +9451,6 @@ int skill_castfix (struct block_list *bl, int skill_id, int skill_lv) return (time > 0) ? time : 0; } -/*========================================== - * 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, ... *------------------------------------------*/ @@ -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); diff --git a/src/map/skill.h b/src/map/skill.h index 1ad6ea25a..73b3e9fd0 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -90,7 +90,7 @@ struct s_skill_db { char desc[40]; int range[MAX_SKILL_LEVEL],hit,inf,element[MAX_SKILL_LEVEL],nk,splash[MAX_SKILL_LEVEL],max; int num[MAX_SKILL_LEVEL]; - int cast[MAX_SKILL_LEVEL],walkdelay[MAX_SKILL_LEVEL],delay[MAX_SKILL_LEVEL]; + int cast[MAX_SKILL_LEVEL],walkdelay[MAX_SKILL_LEVEL],delay[MAX_SKILL_LEVEL],fixedcast[MAX_SKILL_LEVEL],cooldown[MAX_SKILL_LEVEL]; int upkeep_time[MAX_SKILL_LEVEL],upkeep_time2[MAX_SKILL_LEVEL]; int castcancel,cast_def_rate; int inf2,maxcount[MAX_SKILL_LEVEL],skill_type; @@ -239,7 +239,9 @@ int skill_get_state(int id); int skill_get_zeny( int id ,int lv ); int skill_get_num( int id ,int lv ); int skill_get_cast( int id ,int lv ); +int skill_get_fixedcast( int id ,int lv ); int skill_get_delay( int id ,int lv ); +int skill_get_cooldown( int id ,int lv ); int skill_get_walkdelay( int id ,int lv ); int skill_get_time( int id ,int lv ); int skill_get_time2( int id ,int lv ); @@ -290,7 +292,6 @@ int skill_clear_group(struct block_list *bl, int flag); int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl,int damage,unsigned int tick); int skill_castfix( struct block_list *bl, int skill_id, int skill_lv); -int skill_castfix_sc( struct block_list *bl, int time); int skill_delayfix( struct block_list *bl, int skill_id, int skill_lv); // Skill conditions check and remove [Inkfish] @@ -1310,7 +1311,7 @@ enum e_skill { GN_S_PHARMACY, GN_SLINGITEM_RANGEMELEEATK, - AB_SECRAMENT, + AB_SECRAMENT = 2515, WM_SEVERE_RAINSTORM_MELEE, SR_HOWLINGOFLION, SR_RIDEINLIGHTNING, @@ -1501,7 +1502,7 @@ enum { UNT_EVILLAND, UNT_DARK_RUNNER, //TODO UNT_DARK_TRANSFER, //TODO - UNT_EPICLESIS, //TODO + UNT_EPICLESIS, UNT_EARTHSTRAIN, //TODO UNT_MANHOLE, //TODO UNT_DIMENSIONDOOR, //TODO diff --git a/src/map/status.c b/src/map/status.c index 37dad30b9..8294d4873 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -35,7 +35,7 @@ #include #include #include - +#include //Regen related flags. enum e_regen @@ -52,6 +52,7 @@ static int hp_coefficient2[CLASS_COUNT]; static int hp_sigma_val[CLASS_COUNT][MAX_LEVEL+1]; static int sp_coefficient[CLASS_COUNT]; static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE]; //[blackhole89] +static int shield_aspd_base[CLASS_COUNT]; static int refinebonus[MAX_REFINE_BONUS][3]; // Έ˜Bƒ{[ƒiƒXƒe[ƒuƒ‹(refine_db.txt) int percentrefinery[5][MAX_REFINE+1]; // Έ˜B¬Œχ—¦(refine_db.txt) static int atkmods[3][MAX_WEAPON_TYPE]; // •ŠνATKƒTƒCƒYC³(size_fix.txt) @@ -399,7 +400,7 @@ void initChangeTables(void) set_sc( CASH_INCAGI , SC_INCREASEAGI , SI_INCREASEAGI , SCB_AGI|SCB_SPEED ); set_sc( CASH_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_NONE ); - //set_sc( ALL_PARTYFLEE , SC_INCFLEE , SI_PARTYFLEE , SCB_NONE ); + set_sc( ALL_PARTYFLEE , SC_PARTYFLEE , SI_PARTYFLEE , SCB_FLEE ); set_sc( CR_SHRINK , SC_SHRINK , SI_SHRINK , SCB_NONE ); set_sc( RG_CLOSECONFINE , SC_CLOSECONFINE2 , SI_CLOSECONFINE2 , SCB_NONE ); @@ -412,6 +413,19 @@ void initChangeTables(void) add_sc( SA_ELEMENTGROUND , SC_ELEMENTALCHANGE ); add_sc( SA_ELEMENTWIND , SC_ELEMENTALCHANGE ); + set_sc( AB_ADORAMUS , SC_ADORAMUS , SI_ADORAMUS , SCB_AGI|SCB_SPEED ); + add_sc( AB_CLEMENTIA , SC_BLESSING ); + add_sc( AB_CANTO , SC_INCREASEAGI ); + add_sc( AB_PRAEFATIO , SC_KYRIE ); + set_sc( AB_EPICLESIS , SC_EPICLESIS , SI_EPICLESIS , SCB_MAXHP ); + set_sc( AB_ORATIO , SC_ORATIO , SI_ORATIO , SCB_NONE ); + set_sc( AB_LAUDAAGNUS , SC_LAUDAAGNUS , SI_LAUDAAGNUS , SCB_VIT ); + set_sc( AB_LAUDARAMUS , SC_LAUDARAMUS , SI_LAUDARAMUS , SCB_LUK ); + set_sc( AB_RENOVATIO , SC_RENOVATIO , SI_RENOVATIO , SCB_REGEN ); + set_sc( AB_EXPIATIO , SC_EXPIATIO , SI_EXPIATIO , SCB_NONE ); + set_sc( AB_DUPLELIGHT , SC_DUPLELIGHT , SI_DUPLELIGHT , SCB_NONE ); + set_sc( AB_SECRAMENT , SC_AB_SECRAMENT , SI_AB_SECRAMENT , SCB_NONE ); + set_sc( HLIF_AVOID , SC_AVOID , SI_BLANK , SCB_SPEED ); set_sc( HLIF_CHANGE , SC_CHANGE , SI_BLANK , SCB_VIT|SCB_INT ); set_sc( HFLI_FLEET , SC_FLEET , SI_BLANK , SCB_ASPD|SCB_BATK|SCB_WATK ); @@ -489,6 +503,7 @@ void initChangeTables(void) StatusIconChangeTable[SC_SPL_DEF] = SI_SPL_DEF; StatusIconChangeTable[SC_MANU_MATK] = SI_MANU_MATK; StatusIconChangeTable[SC_SPL_MATK] = SI_SPL_MATK; + //StatusIconChangeTable[SC_MOVHASTE_INFINITY] = SI_MOVHASTE_INFINITY; // Causes client to crash when mousing over state icon? //Cash Items StatusIconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH; StatusIconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH; @@ -560,6 +575,8 @@ void initChangeTables(void) StatusChangeFlagTable[SC_SPCOST_RATE] |= SCB_ALL; StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED; StatusChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL; + //StatusChangeFlagTable[SC_MOVHASTE_INFINITY] = SCB_SPEED; + // Cash Items StatusChangeFlagTable[SC_FOOD_STR_CASH] = SCB_STR; StatusChangeFlagTable[SC_FOOD_AGI_CASH] = SCB_AGI; @@ -1266,20 +1283,23 @@ int status_check_visibility(struct block_list *src, struct block_list *target) // Basic ASPD value int status_base_amotion_pc(struct map_session_data* sd, struct status_data* status) { - int amotion; + int amotion, shield = 0; // base weapon delay amotion = (sd->status.weapon < MAX_WEAPON_TYPE) ? (aspd_base[pc_class2idx(sd->status.class_)][sd->status.weapon]) // single weapon : (aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype1] + aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype2])*7/10; // dual-wield + if (sd->status.shield) + shield = shield_aspd_base[pc_class2idx(sd->status.class_)] * 10; + // percentual delay reduction from stats - amotion-= amotion * (4*status->agi + status->dex)/1000; - + amotion-= ( amotion - shield ) * (4*status->agi + status->dex)/1000; + // raw delay adjustment from bAspd bonus amotion+= sd->aspd_add; - - return amotion; + + return amotion; } static unsigned short status_base_atk(const struct block_list *bl, const struct status_data *status) @@ -1334,10 +1354,12 @@ void status_calc_misc(struct block_list *bl, struct status_data *status, int lev status->matk_min = status_base_matk_min(status); status->matk_max = status_base_matk_max(status); - status->hit += level + status->dex; - status->flee += level + status->agi; + status->hit += 175 + status->dex + (unsigned short)floor((double)status->luk/3) + level; //Renewal calclation. + status->flee += 100 + status->agi + level; status->def2 += status->vit; - status->mdef2 += status->int_ + (status->vit>>1); + status->mdef2 += status->mdef; + //Status MATK = floor(Base Level/4 + INT + INT/2 + DEX/5 + LUK/3) + status->status_matk = (unsigned short)floor((double)level/4 + (double)status->int_ + (double)status->int_/2 + (double)status->dex/5 + (double)status->luk/3); if( bl->type&battle_config.enable_critical ) status->cri += status->luk*3 + 10; @@ -1734,6 +1756,9 @@ int status_calc_pc_(struct map_session_data* sd, bool first) sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100; sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100; sd->regen.state.block = 0; + sd->fixedcastrate=0; + sd->weapon_matk = 0; + sd->equipment_matk = 0; // zeroed arrays, order follows the order in pc.h. // add new arrays to the end of zeroed area in pc.h (see comments) and size here. [zzo] @@ -1963,7 +1988,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) memcpy(sd->param_equip,sd->param_bonus,sizeof(sd->param_equip)); memset(sd->param_bonus, 0, sizeof(sd->param_bonus)); - status->def += (refinedef+50)/100; + status->def += refinedef; //Parse Cards for(i=0;idsprate = 0; if(sd->castrate < 0) sd->castrate = 0; + if( sd->fixedcastrate < 0 ) + sd->fixedcastrate = 0; if(sd->delayrate < 0) sd->delayrate = 0; if(sd->hprecov_rate < 0) @@ -2377,6 +2404,17 @@ int status_calc_pc_(struct map_session_data* sd, bool first) sd->magic_addrace[RC_DRAGON]+=skill; sd->subrace[RC_DRAGON]+=skill; } + if( (skill = pc_checkskill(sd, AB_EUCHARISTICA)) > 0 ) + { + sd->right_weapon.addrace[RC_DEMON]+=skill; + sd->right_weapon.addele[ELE_DARK]+=skill; + sd->left_weapon.addrace[RC_DEMON]+=skill; + sd->left_weapon.addele[ELE_DARK]+=skill; + sd->magic_addrace[RC_DEMON]+=skill; + sd->magic_addele[ELE_DARK]+=skill; + sd->subrace[RC_DEMON]+=skill; + sd->subele[ELE_DARK]+=skill; + } if(sc->count){ if(sc->data[SC_CONCENTRATE]) @@ -2976,10 +3014,26 @@ void status_calc_bl_main(struct block_list *bl, enum scb_flag flag) } if(flag&SCB_MATK) { + int wlv = 1, wmatk = 0; + short index = sd->equip_index[EQI_HAND_R]; + //New matk status->matk_min = status_base_matk_min(status); status->matk_max = status_base_matk_max(status); + // iRO Wiki states as of 2011/02/24: + // Status MATK = floor(Base Level/4 + INT + INT/2 + DEX/5 + LUK/3) + status->status_matk = status_get_lv(bl)/4 + status->int_ + status->int_/2 + status->dex/5 + status->luk/3; + wmatk = sd->weapon_matk + sd->battle_status.rhw.atk2 + sd->equipment_matk; + + if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON ) + wlv = sd->inventory_data[index]->wlv; + + // Variance = ± 0.1 * Weapon Level * Base Weapon MATK + // Used in a lot of magical attack calculations still. + status->matk_min = status->status_matk + wmatk; + status->matk_max = status->status_matk + wmatk + (wmatk * wlv / 10); + if( bl->type&BL_PC && sd->matk_rate != 100 ) { //Bonuses from previous matk @@ -3138,7 +3192,10 @@ void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first) if(b_status.speed != status->speed) clif_updatestatus(sd,SP_SPEED); if(b_status.rhw.atk != status->rhw.atk || b_status.lhw.atk != status->lhw.atk || b_status.batk != status->batk) + { clif_updatestatus(sd,SP_ATK1); + clif_updatestatus(sd,SP_MATK1); + } if(b_status.def != status->def) clif_updatestatus(sd,SP_DEF1); if(b_status.rhw.atk2 != status->rhw.atk2 || b_status.lhw.atk2 != status->lhw.atk2) @@ -3150,13 +3207,15 @@ void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first) if(b_status.cri != status->cri) clif_updatestatus(sd,SP_CRITICAL); if(b_status.matk_max != status->matk_max) - clif_updatestatus(sd,SP_MATK1); - if(b_status.matk_min != status->matk_min) - clif_updatestatus(sd,SP_MATK2); - if(b_status.mdef != status->mdef) + { + clif_updatestatus(sd,SP_MATK1); + clif_updatestatus(sd,SP_MATK2); + } + if(b_status.mdef != status->mdef || b_status.mdef2 != status->mdef2) + { clif_updatestatus(sd,SP_MDEF1); - if(b_status.mdef2 != status->mdef2) clif_updatestatus(sd,SP_MDEF2); + } if(b_status.rhw.range != status->rhw.range) clif_updatestatus(sd,SP_ATTACKRANGE); if(b_status.max_hp != status->max_hp) @@ -3285,6 +3344,8 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang agi += ((sc->data[SC_MARIONETTE2]->val3)>>8)&0xFF; if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && agi < 50) agi = 50; + if(sc->data[SC_ADORAMUS]) + agi -= sc->data[SC_ADORAMUS]->val2; return (unsigned short)cap_value(agi,0,USHRT_MAX); } @@ -3316,6 +3377,8 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang vit += sc->data[SC_MARIONETTE2]->val3&0xFF; if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && vit < 50) vit = 50; + if(sc->data[SC_LAUDAAGNUS]) + vit += sc->data[SC_LAUDAAGNUS]->val2; return (unsigned short)cap_value(vit,0,USHRT_MAX); } @@ -3426,6 +3489,8 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang luk += sc->data[SC_MARIONETTE2]->val4&0xFF; if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && luk < 50) luk = 50; + if(sc->data[SC_LAUDARAMUS]) + luk += sc->data[SC_LAUDARAMUS]->val2; return (unsigned short)cap_value(luk,0,USHRT_MAX); } @@ -3619,6 +3684,8 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change flee -= sc->data[SC_GATLINGFEVER]->val4; if(sc->data[SC_SPEED]) flee += 10 + sc->data[SC_SPEED]->val1 * 10; + if(sc->data[SC_PARTYFLEE]) + flee += sc->data[SC_PARTYFLEE]->val1 * 10; if(sc->data[SC_MERC_FLEEUP]) flee += sc->data[SC_MERC_FLEEUP]->val2; @@ -3826,6 +3893,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha val = max( val, sc->data[SC_SUITON]->val3 ); if( sc->data[SC_SWOO] ) val = max( val, 300 ); + if( sc->data[SC_ADORAMUS] ) + val = max( val, 25 ); if( sd && sd->speed_rate + sd->speed_add_rate > 0 ) // permanent item-based speedup val = max( val, sd->speed_rate + sd->speed_add_rate ); @@ -3858,6 +3927,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha val = max( val, 10 * sc->data[SC_AVOID]->val1 ); if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) val = max( val, 75 ); + //if( sc->data[SC_MOVHASTE_INFINITY] ) + // val = max( val, 25 ); //FIXME: official items use a single bonus for this [ultramage] if( sc->data[SC_SPEEDUP0] ) // temporary item-based speedup @@ -4026,6 +4097,9 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang if(sc->data[SC_MERC_HPUP]) maxhp += maxhp * sc->data[SC_MERC_HPUP]->val2/100; + if(sc->data[SC_EPICLESIS]) + maxhp += maxhp * sc->data[SC_EPICLESIS]->val2/100; + return cap_value(maxhp,1,UINT_MAX); } @@ -4581,6 +4655,7 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti case SC_STONE: case SC_QUAGMIRE: case SC_SUITON: + case SC_ADORAMUS: return 0; } @@ -4599,6 +4674,7 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti sc_def = 3 +status->int_; break; case SC_DECREASEAGI: + case SC_ADORAMUS: if (sd) tick>>=1; //Half duration for players. case SC_STONE: case SC_FREEZE: @@ -4731,6 +4807,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val struct status_data *status; struct view_data *vd; int opt_flag, calc_flag, undead_flag; + int duration = tick; nullpo_ret(bl); sc = status_get_sc(bl); @@ -4799,7 +4876,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if(sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE))) return 0; if (sc->data[SC_QUAGMIRE] || - sc->data[SC_DECREASEAGI] + sc->data[SC_DECREASEAGI] || + sc->data[SC_ADORAMUS] ) return 0; break; @@ -4807,14 +4885,16 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if(sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE2))) return 0; if (sc->data[SC_QUAGMIRE] || - sc->data[SC_DECREASEAGI] + sc->data[SC_DECREASEAGI] || + sc->data[SC_ADORAMUS] ) return 0; break; case SC_ONEHAND: case SC_MERC_QUICKEN: case SC_TWOHANDQUICKEN: - if(sc->data[SC_DECREASEAGI]) + if(sc->data[SC_DECREASEAGI] || + sc->data[SC_ADORAMUS]) return 0; case SC_CONCENTRATE: case SC_INCREASEAGI: @@ -4994,6 +5074,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_RICHMANKIM: case SC_ROKISWEIL: case SC_FOGWALL: + case SC_ADORAMUS: return 0; } } @@ -5012,6 +5093,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_INCREASEAGI: status_change_end(bl, SC_DECREASEAGI, INVALID_TIMER); + status_change_end(bl, SC_ADORAMUS, INVALID_TIMER); break; case SC_QUAGMIRE: status_change_end(bl, SC_CONCENTRATE, INVALID_TIMER); @@ -5019,6 +5101,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val status_change_end(bl, SC_WINDWALK, INVALID_TIMER); //Also blocks the ones below... case SC_DECREASEAGI: + case SC_ADORAMUS: status_change_end(bl, SC_CARTBOOST, INVALID_TIMER); //Also blocks the ones below... case SC_DONTFORGETME: @@ -5076,9 +5159,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); break; case SC_CARTBOOST: - if(sc->data[SC_DECREASEAGI]) + if(sc->data[SC_DECREASEAGI] || sc->data[SC_ADORAMUS]) { //Cancel Decrease Agi, but take no further effect [Skotlex] status_change_end(bl, SC_DECREASEAGI, INVALID_TIMER); + status_change_end(bl, SC_ADORAMUS, INVALID_TIMER); return 0; } break; @@ -5227,6 +5311,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val { case SC_DECREASEAGI: case SC_INCREASEAGI: + case SC_ADORAMUS: val2 = 2 + val1; //Agi change break; case SC_ENDURE: @@ -5277,7 +5362,14 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_KYRIE: val2 = status->max_hp * (val1 * 2 + 10) / 100; //%Max HP to absorb - val3 = (val1 / 2 + 5); //Hits + // val1 determines if status is casued by Kyrie or Praefatio, + // as Praefatio blocks more hits than Kyrie Elesion. + if( !val4 ) + val3 = (val1 / 2 + 5); + else + val3 = 6 + val1; + if( sd ) + val1 = min(val1,pc_checkskill(sd,PR_KYRIE)); // uses kill level to determine barrier health. break; case SC_MAGICPOWER: //val1: Skill lv @@ -6037,6 +6129,31 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_KAIZEL: val2 = 10*val1; //% of life to be revived with break; + case SC_EPICLESIS: + val2 = 5 * val1; // % HP gained * level of Epiclesis cast. + break; + case SC_ORATIO: + val2 = 2 * val1; // % Damage increased by level of Oratio cast. + break; + case SC_LAUDAAGNUS: + case SC_LAUDARAMUS: + val2 = 4+val1; // Bonus status points gained + break; + case SC_RENOVATIO: + val2 = tick / 5000; // Heal every 5 seconds. + tick = 5000; + break; + case SC_EXPIATIO: + val2 = 5*val1; // DEF reduced by 5*Skill Level percent. + break; + case SC_DUPLELIGHT: + val2 = 10+val1*2; //Chance of MELEE proc + val3 = 10+val1*2; //Chance of MAGIC proc + break; + + case SC_AB_SECRAMENT: + val2 = 10*val1; //Fixed cast time reduced by 10*Skill Level + break; // case SC_ARMOR_ELEMENT: // case SC_ARMOR_RESIST: // Mod your resistance against elements: @@ -6288,8 +6405,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val calc_flag&=~SCB_DYE; } - if( vd && (pcdb_checkid(vd->class_) || bl->type == BL_MER ) ) //Only for players sprites, client crashes if they receive this for a mob o.O [Skotlex] - clif_status_change(bl,StatusIconChangeTable[type],1,tick); + if( vd && ((pcdb_checkid(vd->class_) || bl->type == BL_MER ) //Only for players sprites, client crashes if they receive this for a mob o.O [Skotlex] + || (bl->type == BL_MOB && type == SC_ORATIO)) ) // Required to show the proper status for monsters. Possible this may need an overhaul. + clif_status_change(bl,StatusIconChangeTable[type],1,duration); else if( sd ) //Send packet to self otherwise (disguised player?) clif_status_load(bl,StatusIconChangeTable[type],1); @@ -6455,8 +6573,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const return 0; if (tid == INVALID_TIMER) { - if (type == SC_ENDURE && sce->val4) - //Do not end infinite endure. + if( (type == SC_ENDURE /*|| type == SC_MOVHASTE_INFINITY*/ ) && sce->val4 ) + //Do not end infinite endure or speed adjustment. return 0; if (sce->timer != INVALID_TIMER) //Could be a SC with infinite duration delete_timer(sce->timer,status_change_timer); @@ -6943,7 +7061,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } //On Aegis, when turning off a status change, first goes the sc packet, then the option packet. - if( vd && (pcdb_checkid(vd->class_) || bl->type == BL_MER ) ) + if( vd && ((pcdb_checkid(vd->class_) || bl->type == BL_MER ) + || (bl->type == BL_MOB && type == SC_ORATIO)) ) // Required to remove SI_ORATIO indicator from monsters. clif_status_change(bl,StatusIconChangeTable[type],0,0); else if (sd) clif_status_load(bl,StatusIconChangeTable[type],0); @@ -7345,6 +7464,20 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) return 0; } break; + case SC_RENOVATIO: + if((--sc->data[type]->val2) > 0) { + int heal = status->max_hp * 3 / 100; + if( status->hp + heal > status->max_hp ) + heal = status->max_hp - status->hp; + if(heal > 0) + { + clif_heal(sd->fd,SP_HP,heal); + status_heal(bl, heal, 0, 0); + } + sc_timer_next(5000+tick, status_change_timer, bl->id, data); + return 0; + } + break; } // default for all non-handled control paths is to end the status @@ -7480,6 +7613,7 @@ int status_change_clear_buffs (struct block_list* bl, int type) case SC_STRIPSHIELD: case SC_STRIPARMOR: case SC_STRIPHELM: + case SC_ADORAMUS: if (!(type&2)) continue; break; @@ -7730,6 +7864,7 @@ static bool status_readdb_job1(char* fields[], int columns, int current) { aspd_base[idx][i] = atoi(fields[i+5]); } + shield_aspd_base[idx] = atoi(fields[29]); // Won't take 5+MAX_WEAPON_TYPE+1 return true; } @@ -7792,6 +7927,7 @@ int status_readdb(void) memset(hp_coefficient2, 0, sizeof(hp_coefficient2)); memset(sp_coefficient, 0, sizeof(sp_coefficient)); memset(aspd_base, 0, sizeof(aspd_base)); + memset(shield_aspd_base, 0, sizeof(shield_aspd_base)); // job_db2.txt memset(job_bonus,0,sizeof(job_bonus)); // Job-specific stats bonus @@ -7814,10 +7950,10 @@ int status_readdb(void) // read databases // - sv_readdb(db_path, "job_db1.txt", ',', 5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE, -1, &status_readdb_job1); - sv_readdb(db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, &status_readdb_job2); - sv_readdb(db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(atkmods), &status_readdb_sizefix); - sv_readdb(db_path, "refine_db.txt", ',', 3+MAX_REFINE+1, 3+MAX_REFINE+1, ARRAYLENGTH(percentrefinery), &status_readdb_refine); + sv_readdb(db_path, "job_db1.txt", ',', 5+MAX_WEAPON_TYPE+1, 5+MAX_WEAPON_TYPE+1, -1, &status_readdb_job1); + sv_readdb(db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, &status_readdb_job2); + sv_readdb(db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(atkmods), &status_readdb_sizefix); + sv_readdb(db_path, "refine_db.txt", ',', 3+MAX_REFINE+1, 3+MAX_REFINE+1, ARRAYLENGTH(percentrefinery), &status_readdb_refine); return 0; } diff --git a/src/map/status.h b/src/map/status.h index abaeff75e..4eeadef12 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -325,11 +325,25 @@ typedef enum sc_type { SC_SPL_MATK, SC_FOOD_STR_CASH, SC_FOOD_AGI_CASH, - SC_FOOD_VIT_CASH, + SC_FOOD_VIT_CASH, //305 SC_FOOD_DEX_CASH, SC_FOOD_INT_CASH, SC_FOOD_LUK_CASH, + //SC_MOVHASTE_INFINITY, + SC_PARTYFLEE = 310 , + //SC_ENDURE_MDEF, //311 + // Third Jobs - Maintaining SI order for SCs. + SC_EPICLESIS = 325, + SC_ORATIO, + SC_LAUDAAGNUS, + SC_LAUDARAMUS, + SC_RENOVATIO = 332, + SC_EXPIATIO = 336, + SC_DUPLELIGHT, + SC_ADORAMUS = 380, + SC_AB_SECRAMENT = 451, + SC_MAX, //Automatically updated max, used in for's to check we are within bounds. } sc_type; @@ -649,7 +663,7 @@ enum si_type { // SI_REUSE_LIMIT_F = 310, SI_INVINCIBLE = 311, SI_CASH_PLUSONLYJOBEXP = 312, -// SI_PARTYFLEE = 313, + SI_PARTYFLEE = 313, // SI_ANGEL_PROTECT = 314, /* SI_ENDURE_MDEF = 315, @@ -666,18 +680,20 @@ enum si_type { SI_REUSE_REFRESH = 326, SI_REUSE_STORMBLAST = 327, SI_VENOMIMPRESS = 328, +*/ SI_EPICLESIS = 329, SI_ORATIO = 330, SI_LAUDAAGNUS = 331, SI_LAUDARAMUS = 332, - SI_CLOAKINGEXCEED = 333, - SI_HALLUCINATIONWALK = 334, - SI_HALLUCINATIONWALK_POSTDELAY = 335, +// SI_CLOAKINGEXCEED = 333, +// SI_HALLUCINATIONWALK = 334, +// SI_HALLUCINATIONWALK_POSTDELAY = 335, SI_RENOVATIO = 336, - SI_WEAPONBLOCKING = 337, - SI_WEAPONBLOCKING_POSTDELAY = 338, - SI_ROLLINGCUTTER = 339, +// SI_WEAPONBLOCKING = 337, +// SI_WEAPONBLOCKING_POSTDELAY = 338, +// SI_ROLLINGCUTTER = 339, SI_EXPIATIO = 340, +/* SI_POISONINGWEAPON = 341, SI_TOXIN = 342, SI_PARALYSE = 343, @@ -687,7 +703,9 @@ enum si_type { SI_PYREXIA = 347, SI_OBLIVIONCURSE = 348, SI_LEECHESEND = 349, +*/ SI_DUPLELIGHT = 350, +/* SI_FROSTMISTY = 351, SI_FEARBREEZE = 352, SI_ELECTRICSHOCKER = 353, @@ -740,7 +758,9 @@ enum si_type { SI_SHIELDSPELL_REF = 398, SI_BODYPAINT = 399, SI_EXEEDBREAK = 400, +*/ SI_ADORAMUS = 401, +/* SI_PRESTIGE = 402, SI_INVISIBILITY = 403, SI_DEADLYINFECT = 404, @@ -811,7 +831,9 @@ enum si_type { SI_BLOCKING_PLAY = 469, SI_MANDRAGORA = 470, SI_ACTIVATE = 471, +*/ SI_AB_SECRAMENT = 472, +/* SI_ASSUMPTIO2 = 473, SI_TK_SEVENWIND = 474, SI_LIMIT_ODINS_RECALL = 475, @@ -1112,7 +1134,7 @@ struct status_data { unsigned short str, agi, vit, int_, dex, luk, batk, - matk_min, matk_max, + matk_min, matk_max, status_matk, speed, amotion, adelay, dmotion, mode; diff --git a/src/map/unit.c b/src/map/unit.c index 2165532b4..b992d028b 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -961,7 +961,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh return 0; target = (struct block_list*)map_charid2sd(sd->status.partner_id); if (!target) { - clif_skill_fail(sd,skill_num,0,0); + clif_skill_fail(sd,skill_num,0,0,0); return 0; } break; @@ -1013,7 +1013,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh case BD_ENCORE: //Prevent using the dance skill if you no longer have the skill in your tree. if(!sd->skillid_dance || pc_checkskill(sd,sd->skillid_dance)<=0){ - clif_skill_fail(sd,skill_num,0,0); + clif_skill_fail(sd,skill_num,0,0,0); return 0; } sd->skillid_old = skill_num; @@ -1029,7 +1029,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh case CG_MOONLIT: if (skill_check_pc_partner(sd, skill_num, &skill_lv, 1, 0) < 1) { - clif_skill_fail(sd,skill_num,0,0); + clif_skill_fail(sd,skill_num,0,0,0); return 0; } break; @@ -1098,18 +1098,10 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh case SA_SPELLBREAKER: temp = 1; break; - case ST_CHASEWALK: - if (sc && sc->data[SC_CHASEWALK]) - casttime = 0; - break; case TK_RUN: if (sc && sc->data[SC_RUN]) casttime = 0; break; - case HP_BASILICA: - if( sc && sc->data[SC_BASILICA] ) - casttime = 0; // No Casting time on basilica cancel - break; case KN_CHARGEATK: { unsigned int k = (distance_bl(src,target)-1)/3; //+100% every 3 cells of distance @@ -1123,9 +1115,17 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh break; } - // moved here to prevent Suffragium from ending if skill fails - if (!(skill_get_castnodex(skill_num, skill_lv)&2)) - casttime = skill_castfix_sc(src, casttime); + // Cancel status effects that lower cast time. + if( !(skill_get_castnodex(skill_num, skill_lv)&2) && sc ) + { + if( sc->data[SC_SUFFRAGIUM] ) + status_change_end(src, SC_SUFFRAGIUM, INVALID_TIMER); + if( sc->data[SC_MEMORIZE] ) + { + if ((--sc->data[SC_MEMORIZE]->val2) <= 0) + status_change_end(src, SC_MEMORIZE, INVALID_TIMER); + } + } if( casttime > 0 || temp ) { @@ -1245,7 +1245,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh if( map_getcell(src->m, skill_x, skill_y, CELL_CHKWALL) ) {// can't cast ground targeted spells on wall cells - if (sd) clif_skill_fail(sd,skill_num,0,0); + if (sd) clif_skill_fail(sd,skill_num,0,0,0); return 0; } @@ -1265,9 +1265,17 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh unit_stop_attack(src); - // moved here to prevent Suffragium from ending if skill fails - if (!(skill_get_castnodex(skill_num, skill_lv)&2)) - casttime = skill_castfix_sc(src, casttime); + // Cancel status effects that lower cast time. + if( !(skill_get_castnodex(skill_num, skill_lv)&2) && sc ) + { + if( sc->data[SC_SUFFRAGIUM] ) + status_change_end(src, SC_SUFFRAGIUM, INVALID_TIMER); + if( sc->data[SC_MEMORIZE] ) + { + if ((--sc->data[SC_MEMORIZE]->val2) <= 0) + status_change_end(src, SC_MEMORIZE, INVALID_TIMER); + } + } ud->state.skillcastcancel = castcancel&&casttime>0?1:0; if( !sd || sd->skillitem != skill_num || skill_get_cast(skill_num,skill_lv) ) @@ -1573,7 +1581,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t { // attacking when under cast delay has restrictions: if( tid == INVALID_TIMER ) { //requested attack. - if(sd) clif_skill_fail(sd,1,4,0); + if(sd) clif_skill_fail(sd,1,4,0,0); return 0; } //Otherwise, we are in a combo-attack, delay this until your canact time is over. [Skotlex] diff --git a/src/map/vending.c b/src/map/vending.c index c5ead6513..37557990e 100644 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -261,14 +261,14 @@ void vending_openvending(struct map_session_data* sd, const char* message, bool // skill level and cart check if( !vending_skill_lvl || !pc_iscarton(sd) ) { - clif_skill_fail(sd, MC_VENDING, 0, 0); + clif_skill_fail(sd, MC_VENDING, 0, 0, 0); return; } // check number of items in shop if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { // invalid item count - clif_skill_fail(sd, MC_VENDING, 0, 0); + clif_skill_fail(sd, MC_VENDING, 0, 0, 0); return; } @@ -303,7 +303,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, bool if( i == 0 ) { // no valid item found - clif_skill_fail(sd, MC_VENDING, 0, 0); // custom reply packet + clif_skill_fail(sd, MC_VENDING, 0, 0, 0); // custom reply packet return; } -- cgit v1.2.3-70-g09d2