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