summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
authorzephyrus <zephyrus@54d463be-8e91-2dee-dedb-b68131a5f0ec>2008-09-10 14:30:25 +0000
committerzephyrus <zephyrus@54d463be-8e91-2dee-dedb-b68131a5f0ec>2008-09-10 14:30:25 +0000
commitd3f9255b3d67e570a7784b44b151ed15198425ee (patch)
treeb48e75936e8b77b61d3f65b8b972556ac511d0c4 /src/map
parente02e0c5cba6e83986da6fdce9c69a9201f9a271f (diff)
downloadhercules-d3f9255b3d67e570a7784b44b151ed15198425ee.tar.gz
hercules-d3f9255b3d67e570a7784b44b151ed15198425ee.tar.bz2
hercules-d3f9255b3d67e570a7784b44b151ed15198425ee.tar.xz
hercules-d3f9255b3d67e570a7784b44b151ed15198425ee.zip
- Full implementation of mercenary skills.
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@13203 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map')
-rw-r--r--src/map/battle.c82
-rw-r--r--src/map/clif.c205
-rw-r--r--src/map/clif.h2
-rw-r--r--src/map/mob.c25
-rw-r--r--src/map/pc.c2
-rw-r--r--src/map/skill.c352
-rw-r--r--src/map/skill.h5
-rw-r--r--src/map/status.c205
-rw-r--r--src/map/status.h1
-rw-r--r--src/map/unit.c65
10 files changed, 622 insertions, 322 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index 8dc6eb394..d671be45e 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -39,7 +39,8 @@ int battle_getcurrentskill(struct block_list *bl)
{ //Returns the current/last skill in use by this bl.
struct unit_data *ud;
- if (bl->type == BL_SKILL) {
+ if( bl->type == BL_SKILL )
+ {
struct skill_unit * su = (struct skill_unit*)bl;
return su->group?su->group->skill_id:0;
}
@@ -322,9 +323,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
if( sc->data[SC_PNEUMA] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG )
return 0;
- if((sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON &&
- !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK) &&
- rand()%100 < sce->val2)
+ if( (sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK) && rand()%100 < sce->val2 )
{
int delay;
clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sce->val1,1);
@@ -342,11 +341,9 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
return 0;
}
- if((sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON
- && skill_num != WS_CARTTERMINATION
- && rand()%100 < sce->val2)
- {// attack blocked by Parrying
- clif_skill_nodamage(bl,bl,LK_PARRYING,sce->val1,1);
+ if( (sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON && skill_num != WS_CARTTERMINATION && rand()%100 < sce->val2 )
+ { // attack blocked by Parrying
+ clif_skill_nodamage(bl, bl, LK_PARRYING, sce->val1,1);
return 0;
}
@@ -948,6 +945,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
break;
case KN_PIERCE:
+ case ML_PIERCE:
wd.div_= (wd.div_>0?tstatus->size+1:-(tstatus->size+1));
break;
@@ -959,6 +957,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
case GS_GROUNDDRIFT:
case KN_SPEARSTAB:
case KN_BOWLINGBASH:
+ case MS_BOWLINGBASH:
case MO_BALKYOUNG:
case TK_TURNKICK:
wd.blewcount=0;
@@ -1011,7 +1010,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
if(!flag.cri && sstatus->cri &&
(!skill_num ||
skill_num == KN_AUTOCOUNTER ||
- skill_num == SN_SHARPSHOOTING ||
+ skill_num == SN_SHARPSHOOTING || skill_num == MA_SHARPSHOOTING ||
skill_num == NJ_KIRIKAGE))
{
short cri = sstatus->cri;
@@ -1042,6 +1041,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
cri <<= 1;
break;
case SN_SHARPSHOOTING:
+ case MA_SHARPSHOOTING:
cri += 200;
break;
case NJ_KIRIKAGE:
@@ -1123,6 +1123,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
case MS_BASH:
hitrate += hitrate * 5 * skill_lv / 100;
break;
+ case MS_MAGNUM:
case SM_MAGNUM:
hitrate += hitrate * 10 * skill_lv / 100;
break;
@@ -1141,6 +1142,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
hitrate += hitrate * 20 / 100;
break;
case KN_PIERCE:
+ case ML_PIERCE:
hitrate += hitrate * 5 * skill_lv / 100;
break;
case AS_SONICBLOW:
@@ -1194,6 +1196,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
}
break;
case LK_SPIRALPIERCE:
+ case ML_SPIRALPIERCE:
if (sd) {
short index = sd->equip_index[EQI_HAND_R];
@@ -1295,18 +1298,15 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
if(sc->data[SC_BERSERK])
skillratio += 100;
}
- if (!skill_num)
- {
- // Random chance to deal multiplied damage - Consider it as part of skill-based-damage
- if(sd &&
- sd->random_attack_increase_add > 0 &&
- sd->random_attack_increase_per &&
- rand()%100 < sd->random_attack_increase_per
- )
+ if( !skill_num )
+ { // Random chance to deal multiplied damage - Consider it as part of skill-based-damage
+ if( sd && sd->random_attack_increase_add > 0 && sd->random_attack_increase_per && rand()%100 < sd->random_attack_increase_per )
skillratio += sd->random_attack_increase_add;
-
+
ATK_RATE(skillratio);
- } else { //Skills
+ }
+ else
+ {
switch( skill_num )
{
case SM_BASH:
@@ -1314,6 +1314,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
skillratio += 30*skill_lv;
break;
case SM_MAGNUM:
+ case MS_MAGNUM:
skillratio += 20*skill_lv;
break;
case MC_MAMMONITE:
@@ -1323,18 +1324,26 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
skillratio += 5*sstatus->str;
break;
case AC_DOUBLE:
+ case MA_DOUBLE:
skillratio += 10*(skill_lv-1);
break;
case AC_SHOWER:
+ case MA_SHOWER:
skillratio += 5*skill_lv-25;
break;
case AC_CHARGEARROW:
+ case MA_CHARGEARROW:
skillratio += 50;
break;
case HT_FREEZINGTRAP:
+ case MA_FREEZINGTRAP:
skillratio += -50+10*skill_lv;
break;
case KN_PIERCE:
+ case ML_PIERCE:
+ skillratio += 10*skill_lv;
+ break;
+ case MER_CRASH:
skillratio += 10*skill_lv;
break;
case KN_SPEARSTAB:
@@ -1344,6 +1353,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
skillratio += 50*skill_lv;
break;
case KN_BRANDISHSPEAR:
+ case ML_BRANDISH:
{
int ratio = 100+20*skill_lv;
skillratio += ratio-100;
@@ -1356,6 +1366,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
break;
}
case KN_BOWLINGBASH:
+ case MS_BOWLINGBASH:
skillratio+= 40*skill_lv;
break;
case AS_GRIMTOOTH:
@@ -1478,6 +1489,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
skillratio += 40*skill_lv-60;
break;
case SN_SHARPSHOOTING:
+ case MA_SHARPSHOOTING:
skillratio += 100+50*skill_lv;
break;
case CG_ARROWVULCAN:
@@ -1754,15 +1766,16 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
}
//Post skill/vit reduction damage increases
- if (sc && skill_num != LK_SPIRALPIERCE)
+ if( sc && skill_num != LK_SPIRALPIERCE && skill_num != ML_SPIRALPIERCE )
{ //SC skill damages
if(sc->data[SC_AURABLADE])
ATK_ADD(20*sc->data[SC_AURABLADE]->val1);
}
//Refine bonus
- if (sd && flag.weapon && skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST) {
- if (skill_num == MO_FINGEROFFENSIVE) //Counts refine bonus multiple times
+ if( sd && flag.weapon && skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST )
+ { // Counts refine bonus multiple times
+ if( skill_num == MO_FINGEROFFENSIVE )
{
ATK_ADD2(wd.div_*sstatus->rhw.atk2, wd.div_*sstatus->lhw.atk2);
} else {
@@ -2498,8 +2511,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
//Skill Range Criteria
md.flag |= battle_range_type(src, target, skill_num, skill_lv);
- switch(skill_num){
+ switch( skill_num )
+ {
case HT_LANDMINE:
+ case MA_LANDMINE:
md.damage=skill_lv*(sstatus->dex+75)*(100+sstatus->int_)/100;
break;
case HT_BLASTMINE:
@@ -2917,9 +2932,11 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
battle_consume_ammo(sd, 0, 0);
damage = wd.damage + wd.damage2;
- if (damage > 0 && src != target) {
+ if( damage > 0 && src != target )
+ {
rdamage = battle_calc_return_damage(target, damage, wd.flag);
- if (rdamage > 0) {
+ if( rdamage > 0 )
+ {
rdelay = clif_damage(src, src, tick, wd.amotion, sstatus->dmotion, rdamage, 1, 4, 0);
//Use Reflect Shield to signal this kind of skill trigger. [Skotlex]
skill_additional_effect(target,src,CR_REFLECTSHIELD,1,BF_WEAPON|BF_SHORT|BF_NORMAL,tick);
@@ -3094,17 +3111,20 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
case BL_SKILL:
{
TBL_SKILL *su = (TBL_SKILL*)target;
- if (!su->group)
+ if( !su->group )
return 0;
- if (skill_get_inf2(su->group->skill_id)&INF2_TRAP)
- { //Only a few skills can target traps...
- switch (battle_getcurrentskill(src))
+ if( skill_get_inf2(su->group->skill_id)&INF2_TRAP )
+ { //Only a few skills can target traps...
+ switch( battle_getcurrentskill(src) )
{
+ case MA_REMOVETRAP:
case HT_REMOVETRAP:
case AC_SHOWER:
+ case MA_SHOWER:
case WZ_SIGHTRASHER:
case WZ_SIGHTBLASTER:
case SM_MAGNUM:
+ case MS_MAGNUM:
state |= BCT_ENEMY;
strip_enemy = 0;
break;
@@ -3312,7 +3332,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
/*==========================================
* 射程判定
*------------------------------------------*/
-bool battle_check_range(struct block_list *src,struct block_list *bl,int range)
+bool battle_check_range(struct block_list *src, struct block_list *bl, int range)
{
int d;
nullpo_retr(false, src);
diff --git a/src/map/clif.c b/src/map/clif.c
index 489a765cf..20808ad3a 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -3313,8 +3313,8 @@ void clif_storageclose(struct map_session_data* sd)
*------------------------------------------*/
static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* dstsd)
{
- struct map_session_data* tmpsd;
int gmlvl;
+ struct block_list *d_bl;
int i;
if(dstsd->chatID)
@@ -3338,19 +3338,15 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d
// display link (sd - dstsd) to sd
ARR_FIND( 0, 5, i, sd->devotion[i] == dstsd->bl.id );
- if( i < 5 ) clif_devotion(sd, sd);
+ if( i < 5 ) clif_devotion(&sd->bl, sd);
// display links (dstsd - devotees) to sd
ARR_FIND( 0, 5, i, dstsd->devotion[i] > 0 );
- if( i < 5 ) clif_devotion(dstsd, sd);
+ if( i < 5 ) clif_devotion(&dstsd->bl, sd);
// display link (dstsd - crusader) to sd
- if( dstsd->sc.data[SC_DEVOTION] && (tmpsd = map_id2sd(dstsd->sc.data[SC_DEVOTION]->val1)) != NULL )
- clif_devotion(tmpsd, sd);
-
- // pvp circle for duel [LuzZza]
- //if(dstsd->duel_group)
- // clif_specialeffect(&dstsd->bl, 159, 4);
-
+ if( dstsd->sc.data[SC_DEVOTION] && (d_bl = map_id2bl(dstsd->sc.data[SC_DEVOTION]->val1)) != NULL )
+ clif_devotion(d_bl, sd);
}
+
void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl)
{
uint8 buf[128];
@@ -3381,6 +3377,10 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl)
clif_specialeffect_single(bl,421,sd->fd);
}
break;
+ case BL_MER: // Devotion Effects
+ if( ((TBL_MER*)bl)->devotion_flag )
+ clif_devotion(bl, sd);
+ break;
case BL_NPC:
{
TBL_NPC* nd = (TBL_NPC*)bl;
@@ -4339,7 +4339,7 @@ int clif_skill_estimation(struct map_session_data *sd,struct block_list *dst)
nullpo_retr(0, sd);
nullpo_retr(0, dst);
- if(dst->type!=BL_MOB )
+ if( dst->type != BL_MOB )
return 0;
status = status_get_status_data(dst);
@@ -5870,23 +5870,39 @@ int clif_autospell(struct map_session_data *sd,int skilllv)
* Devotion's visual effect
* S 01cf <devoter id>.L { <devotee id>.L }[5] <max distance>.W
*------------------------------------------*/
-void clif_devotion(struct map_session_data *sd, struct map_session_data *tsd)
+void clif_devotion(struct block_list *src, struct map_session_data *tsd)
{
unsigned char buf[56];
int i;
-
- nullpo_retv(sd);
+
+ nullpo_retv(src);
+ memset(buf,0,packet_len(0x1cf));
WBUFW(buf,0) = 0x1cf;
- WBUFL(buf,2) = sd->bl.id;
- for( i = 0; i < 5; i++ )
- WBUFL(buf,6+4*i) = sd->devotion[i];
- WBUFW(buf,26) = skill_get_range2(&sd->bl,CR_DEVOTION,pc_checkskill(sd,CR_DEVOTION)); // ignored
+ WBUFL(buf,2) = src->id;
+ if( src->type == BL_MER )
+ {
+ struct mercenary_data *md = BL_CAST(BL_MER,src);
+ if( md && md->master && md->devotion_flag )
+ WBUFL(buf,6) = md->master->bl.id;
+
+ WBUFW(buf,26) = skill_get_range2(src, ML_DEVOTION, mercenary_checkskill(md, ML_DEVOTION));
+ }
+ else
+ {
+ struct map_session_data *sd = BL_CAST(BL_PC,src);
+ if( sd == NULL )
+ return;
+
+ for( i = 0; i < 5; i++ )
+ WBUFL(buf,6+4*i) = sd->devotion[i];
+ WBUFW(buf,26) = skill_get_range2(src, CR_DEVOTION, pc_checkskill(sd, CR_DEVOTION));
+ }
if( tsd )
- clif_send(buf,packet_len(0x1cf),&tsd->bl,SELF);
+ clif_send(buf, packet_len(0x1cf), &tsd->bl, SELF);
else
- clif_send(buf,packet_len(0x1cf),&sd->bl,AREA);
+ clif_send(buf, packet_len(0x1cf), src, AREA);
}
/*==========================================
@@ -9216,6 +9232,30 @@ static void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct
unit_skilluse_id(&md->bl, target_id, skillnum, skilllv);
}
+static void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, short skillnum, short skilllv, short x, short y, int skillmoreinfo)
+{
+ int lv;
+ if( !md )
+ return;
+ if( skillnotok_mercenary(skillnum, md) )
+ return;
+ if( md->ud.skilltimer != INVALID_TIMER )
+ return;
+ if( DIFF_TICK(tick, md->ud.canact_tick) < 0 )
+ {
+ clif_skill_fail(md->master, skillnum, 4, 0);
+ return;
+ }
+
+ if( md->sc.data[SC_BASILICA] )
+ return;
+ lv = mercenary_checkskill(md, skillnum);
+ if( skilllv > lv )
+ skilllv = lv;
+ if( skilllv )
+ unit_skilluse_pos(&md->bl, x, y, skillnum, skilllv);
+}
+
/*==========================================
* スキル使用(ID指定)
*------------------------------------------*/
@@ -9229,20 +9269,19 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
skillnum = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]);
target_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[2]);
- if (skilllv < 1) skilllv = 1; //No clue, I have seen the client do this with guild skills :/ [Skotlex]
-
+ if( skilllv < 1 ) skilllv = 1; //No clue, I have seen the client do this with guild skills :/ [Skotlex]
tmp = skill_get_inf(skillnum);
if (tmp&INF_GROUND_SKILL || !tmp)
return; //Using a ground/passive skill on a target? WRONG.
- if( skillnum >= HM_SKILLBASE && skillnum < HM_SKILLBASE+MAX_HOMUNSKILL )
+ if( skillnum >= HM_SKILLBASE && skillnum < HM_SKILLBASE + MAX_HOMUNSKILL )
{
clif_parse_UseSkillToId_homun(sd->hd, sd, tick, skillnum, skilllv, target_id);
return;
}
- if( skillnum >= MC_SKILLBASE && skillnum < MC_SKILLBASE+MAX_MERCSKILL )
+ if( skillnum >= MC_SKILLBASE && skillnum < MC_SKILLBASE + MAX_MERCSKILL )
{
clif_parse_UseSkillToId_mercenary(sd->md, sd, tick, skillnum, skilllv, target_id);
return;
@@ -9251,21 +9290,24 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
// Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
sd->idletime = last_tick;
- if (pc_cant_act(sd))
+ if( pc_cant_act(sd) )
return;
- if (pc_issit(sd))
+ if( pc_issit(sd) )
return;
- if (skillnotok(skillnum, sd))
+ if( skillnotok(skillnum, sd) )
return;
- if (sd->bl.id != target_id && !sd->state.skill_flag && tmp&INF_SELF_SKILL)
+ if( sd->bl.id != target_id && !sd->state.skill_flag && tmp&INF_SELF_SKILL )
target_id = sd->bl.id; //What good is it to mess up the target in self skills? Wished I knew... [Skotlex]
- if (sd->ud.skilltimer != -1) {
- if (skillnum != SA_CASTCANCEL)
+ if( sd->ud.skilltimer != -1 )
+ {
+ if( skillnum != SA_CASTCANCEL )
return;
- } else if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) {
+ }
+ else if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 )
+ {
clif_skill_fail(sd, skillnum, 4, 0);
return;
}
@@ -9276,70 +9318,81 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
if( sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) )
return; // On basilica only caster can use Basilica again to stop it.
- if(target_id<0 && -target_id == sd->bl.id) // for disguises [Valaris]
+ if( target_id < 0 && -target_id == sd->bl.id ) // for disguises [Valaris]
target_id = sd->bl.id;
- if(sd->menuskill_id)
+ if( sd->menuskill_id )
{
- if (sd->menuskill_id == SA_TAMINGMONSTER)
+ if( sd->menuskill_id == SA_TAMINGMONSTER )
sd->menuskill_id = sd->menuskill_val = 0; //Cancel pet capture.
- else
- if (sd->menuskill_id != SA_AUTOSPELL)
+ else if( sd->menuskill_id != SA_AUTOSPELL )
return; //Can't use skills while a menu is open.
}
- if (sd->skillitem == skillnum) {
- if (skilllv != sd->skillitemlv)
+ if( sd->skillitem == skillnum )
+ {
+ if( skilllv != sd->skillitemlv )
skilllv = sd->skillitemlv;
unit_skilluse_id(&sd->bl, target_id, skillnum, skilllv);
return;
}
sd->skillitem = sd->skillitemlv = 0;
- if (skillnum == MO_EXTREMITYFIST) {
- if ((!sd->sc.data[SC_COMBO] ||
+ if( skillnum == MO_EXTREMITYFIST )
+ {
+ if( (!sd->sc.data[SC_COMBO] ||
(sd->sc.data[SC_COMBO]->val1 != MO_COMBOFINISH &&
sd->sc.data[SC_COMBO]->val1 != CH_TIGERFIST &&
sd->sc.data[SC_COMBO]->val1 != CH_CHAINCRUSH))) {
- if (!sd->state.skill_flag ) {
+ if( !sd->state.skill_flag )
+ {
sd->state.skill_flag = 1;
clif_skillinfo(sd, MO_EXTREMITYFIST, INF_ATTACK_SKILL, -1);
return;
- } else if (sd->bl.id == target_id) {
+ } else if( sd->bl.id == target_id )
+ {
clif_skillinfo(sd, MO_EXTREMITYFIST, INF_ATTACK_SKILL, -1);
return;
}
}
}
- if (skillnum == TK_JUMPKICK) {
- if (!sd->sc.data[SC_COMBO] || sd->sc.data[SC_COMBO]->val1 != TK_JUMPKICK) {
- if (!sd->state.skill_flag ) {
+ if( skillnum == TK_JUMPKICK )
+ {
+ if( !sd->sc.data[SC_COMBO] || sd->sc.data[SC_COMBO]->val1 != TK_JUMPKICK )
+ {
+ if( !sd->state.skill_flag )
+ {
sd->state.skill_flag = 1;
clif_skillinfo(sd, TK_JUMPKICK, INF_ATTACK_SKILL, -1);
return;
- } else if (sd->bl.id == target_id) {
+ }
+ else if( sd->bl.id == target_id )
+ {
clif_skillinfo(sd, TK_JUMPKICK, INF_ATTACK_SKILL, -1);
return;
}
}
}
- if (skillnum >= GD_SKILLBASE) {
- if (sd->state.gmaster_flag)
+ if( skillnum >= GD_SKILLBASE )
+ {
+ if( sd->state.gmaster_flag )
skilllv = guild_checkskill(sd->state.gmaster_flag, skillnum);
else
skilllv = 0;
- } else {
+ }
+ else
+ {
tmp = pc_checkskill(sd, skillnum);
- if (skilllv > tmp)
+ if( skilllv > tmp )
skilllv = tmp;
}
pc_delinvincibletimer(sd);
- if (skilllv)
+ if( skilllv )
unit_skilluse_id(&sd->bl, target_id, skillnum, skilllv);
- if (sd->state.skill_flag)
+ if( sd->state.skill_flag )
sd->state.skill_flag = 0;
}
@@ -9351,17 +9404,24 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, short skil
int lv;
unsigned int tick = gettick();
- //Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
- sd->idletime = last_tick;
+ if( !(skill_get_inf(skillnum)&INF_GROUND_SKILL) )
+ return; //Using a target skill on the ground? WRONG.
- if (skillnotok(skillnum, sd))
+ if( skillnum >= MC_SKILLBASE && skillnum < MC_SKILLBASE + MAX_MERCSKILL )
+ {
+ clif_parse_UseSkillToPos_mercenary(sd->md, sd, tick, skillnum, skilllv, x, y, skillmoreinfo);
return;
+ }
- if (!(skill_get_inf(skillnum)&INF_GROUND_SKILL))
- return; //Using a target skill on the ground? WRONG.
+ //Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
+ sd->idletime = last_tick;
- if (skillmoreinfo != -1) {
- if (pc_issit(sd)) {
+ if( skillnotok(skillnum, sd) )
+ return;
+ if( skillmoreinfo != -1 )
+ {
+ if( pc_issit(sd) )
+ {
clif_skill_fail(sd, skillnum, 0, 0);
return;
}
@@ -9369,10 +9429,10 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, short skil
safestrncpy(sd->message, (char*)RFIFOP(fd,skillmoreinfo), MESSAGE_SIZE);
}
- if (sd->ud.skilltimer != -1)
+ if( sd->ud.skilltimer != -1 )
return;
- if (DIFF_TICK(tick, sd->ud.canact_tick) < 0)
+ if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 )
{
clif_skill_fail(sd, skillnum, 4, 0);
return;
@@ -9384,32 +9444,34 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, short skil
if( sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) )
return; // On basilica only caster can use Basilica again to stop it.
- if(sd->menuskill_id)
+ if( sd->menuskill_id )
{
- if (sd->menuskill_id == SA_TAMINGMONSTER)
+ if( sd->menuskill_id == SA_TAMINGMONSTER )
sd->menuskill_id = sd->menuskill_val = 0; //Cancel pet capture.
- else
- if (sd->menuskill_id != SA_AUTOSPELL)
+ else if( sd->menuskill_id != SA_AUTOSPELL )
return; //Can't use skills while a menu is open.
}
pc_delinvincibletimer(sd);
- if (sd->skillitem == skillnum) {
- if (skilllv != sd->skillitemlv)
+ if( sd->skillitem == skillnum )
+ {
+ if( skilllv != sd->skillitemlv )
skilllv = sd->skillitemlv;
unit_skilluse_pos(&sd->bl, x, y, skillnum, skilllv);
- } else {
+ }
+ else
+ {
sd->skillitem = sd->skillitemlv = 0;
- if ((lv = pc_checkskill(sd, skillnum)) > 0) {
- if (skilllv > lv)
+ if( (lv = pc_checkskill(sd, skillnum)) > 0 )
+ {
+ if( skilllv > lv )
skilllv = lv;
unit_skilluse_pos(&sd->bl, x, y, skillnum,skilllv);
}
}
}
-
void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd)
{
if (pc_cant_act(sd))
@@ -12484,7 +12546,6 @@ void clif_mercenary_info(struct map_session_data *sd)
// Mercenary shows ATK as a random value between ATK ~ ATK2
atk = rand()%(status->rhw.atk2 - status->rhw.atk + 1) + status->rhw.atk;
WFIFOW(fd,6) = cap_value(atk, 0, SHRT_MAX);
-
WFIFOW(fd,8) = cap_value(status->matk_max, 0, SHRT_MAX);
WFIFOW(fd,10) = status->hit;
WFIFOW(fd,12) = status->cri/10;
diff --git a/src/map/clif.h b/src/map/clif.h
index dc9f4ef52..6ff91a957 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -233,7 +233,7 @@ void clif_skill_delunit(struct skill_unit *unit);
void clif_01ac(struct block_list* bl);
int clif_autospell(struct map_session_data *sd,int skilllv);
-void clif_devotion(struct map_session_data *sd, struct map_session_data *tsd);
+void clif_devotion(struct block_list *src, struct map_session_data *tsd);
int clif_spiritball(struct map_session_data *sd);
int clif_combo_delay(struct block_list *src,int wait);
int clif_bladestop(struct block_list *src,struct block_list *dst,int bool_);
diff --git a/src/map/mob.c b/src/map/mob.c
index 309b47000..1305a9eb7 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -1286,8 +1286,8 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
|| !mob_can_reach(md, tbl, md->min_chase, MSS_RUSH)
)
&& md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
- && !mobskill_use(md, tick, MSC_RUDEATTACKED) //If can't rude Attack
- && can_move && unit_escape(&md->bl, tbl, rand()%10 +1)) //Attempt escape
+ && !mobskill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack
+ && can_move && unit_escape(&md->bl, tbl, rand()%10 +1)) // Attempt escape
{ //Escaped
md->attacked_id = 0;
return true;
@@ -1297,18 +1297,17 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
if( (abl = map_id2bl(md->attacked_id)) && (!tbl || mob_can_changetarget(md, abl, mode)) )
{
if( md->bl.m != abl->m || abl->prev == NULL
- || (dist = distance_bl(&md->bl, abl)) >= MAX_MINCHASE
- || battle_check_target(&md->bl, abl, BCT_ENEMY) <= 0
- || (battle_config.mob_ai&0x2 && !status_check_skilluse(&md->bl, abl, 0, 0)) //Retaliate check
- || (!battle_check_range(&md->bl, abl, md->status.rhw.range)
- &&
- ( //Reach check
- (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || md->sc.data[SC_SPIDERWEB]))
- || !mob_can_reach(md, abl, dist+md->db->range3, MSS_RUSH)
- )
+ || (dist = distance_bl(&md->bl, abl)) >= MAX_MINCHASE // Attacker longer than visual area
+ || battle_check_target(&md->bl, abl, BCT_ENEMY) <= 0 // Attacker is not enemy of mob
+ || status_isdead(abl) // Attacker is Dead (Reflecting Damage?)
+ || (battle_config.mob_ai&0x2 && !status_check_skilluse(&md->bl, abl, 0, 0)) // Cannot normal attack back to Attacker
+ || (!battle_check_range(&md->bl, abl, md->status.rhw.range) // Not on Melee Range and ...
+ && ( // Reach check
+ (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || md->sc.data[SC_SPIDERWEB]))
+ || !mob_can_reach(md, abl, dist+md->db->range3, MSS_RUSH)
)
- )
- { //Rude attacked
+ ) )
+ { // Rude attacked
if (md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
&& !mobskill_use(md, tick, MSC_RUDEATTACKED) && can_move
&& !tbl && unit_escape(&md->bl, abl, rand()%10 +1))
diff --git a/src/map/pc.c b/src/map/pc.c
index eb8e87159..debc3361f 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -3155,6 +3155,8 @@ int pc_isUseitem(struct map_session_data *sd,int n)
case 12243: // Mercenary's Berserk Potion
if( sd->md == NULL || sd->md->db == NULL )
return 0;
+ if( sd->md->sc.data[SC_BERSERK] )
+ return 0;
if( nameid == 12242 && sd->md->db->lv < 40 )
return 0;
if( nameid == 12243 && sd->md->db->lv < 80 )
diff --git a/src/map/skill.c b/src/map/skill.c
index 1a8cdf0a1..5dbd6d8be 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -215,26 +215,31 @@ int skill_get_casttype (int id)
int skill_get_range2 (struct block_list *bl, int id, int lv)
{
int range;
- if(bl->type == BL_MOB && !(battle_config.mob_ai&0x400))
+ if( bl->type == BL_MOB && !(battle_config.mob_ai&0x400) )
return 9; //Mobs have a range of 9 regardless of skill used.
range = skill_get_range(id, lv);
- if(range < 0) {
- if (battle_config.use_weapon_skill_range&bl->type)
+ if( range < 0 )
+ {
+ if( battle_config.use_weapon_skill_range&bl->type )
return status_get_range(bl);
range *=-1;
}
+
//TODO: Find a way better than hardcoding the list of skills affected by AC_VULTURE
- switch (id) {
- case AC_SHOWER:
- case AC_DOUBLE:
+ switch( id )
+ {
+ case AC_SHOWER: case MA_SHOWER:
+ case AC_DOUBLE: case MA_DOUBLE:
case HT_BLITZBEAT:
case AC_CHARGEARROW:
+ case MA_CHARGEARROW:
case SN_FALCONASSAULT:
case SN_SHARPSHOOTING:
+ case MA_SHARPSHOOTING:
case HT_POWER:
- if (bl->type == BL_PC)
+ if( bl->type == BL_PC )
range += pc_checkskill((TBL_PC*)bl, AC_VULTURE);
else
range += 10; //Assume level 10?
@@ -256,7 +261,7 @@ int skill_get_range2 (struct block_list *bl, int id, int lv)
break;
}
- if(!range && bl->type != BL_PC)
+ if( !range && bl->type != BL_PC )
return 9; // Enable non players to use self skills on others. [Skotlex]
return range;
}
@@ -553,6 +558,10 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
}
break;
+ case MER_CRASH:
+ sc_start(bl,SC_STUN,(6*skilllv),skilllv,skill_get_time2(skillid,skilllv));
+ break;
+
case AS_VENOMKNIFE:
if (sd) //Poison chance must be that of Envenom. [Skotlex]
skilllv = pc_checkskill(sd, TF_POISON);
@@ -593,6 +602,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
break;
case HT_FREEZINGTRAP:
+ case MA_FREEZINGTRAP:
sc_start(bl,SC_FREEZE,(3*skilllv+35),skilllv,skill_get_time2(skillid,skilllv));
break;
@@ -601,6 +611,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
break;
case HT_LANDMINE:
+ case MA_LANDMINE:
sc_start(bl,SC_STUN,(5*skilllv+30),skilllv,skill_get_time2(skillid,skilllv));
break;
@@ -609,6 +620,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
break;
case HT_SANDMAN:
+ case MA_SANDMAN:
sc_start(bl,SC_SLEEP,(10*skilllv+40),skilllv,skill_get_time2(skillid,skilllv));
break;
@@ -728,6 +740,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
break;
case LK_SPIRALPIERCE:
+ case ML_SPIRALPIERCE:
sc_start(bl,SC_STOP,(15+skilllv*5),0,skill_get_time2(skillid,skilllv));
break;
@@ -852,12 +865,12 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
break;
}
- if(sd && attack_type&BF_WEAPON &&
+ if( sd && attack_type&BF_WEAPON &&
skillid != WS_CARTTERMINATION &&
skillid != AM_DEMONSTRATION &&
- skillid != CR_REFLECTSHIELD &&
- skillid != ASC_BREAKER
- ){ //Trigger status effects
+ skillid != CR_REFLECTSHIELD && skillid != MS_REFLECTSHIELD &&
+ skillid != ASC_BREAKER )
+ { // Trigger status effects
enum sc_type type;
int i;
for(i=0; i < ARRAYLENGTH(sd->addeff) && sd->addeff[i].flag; i++)
@@ -1679,11 +1692,12 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
clif_skillinfoblock(tsd);
}
}
- if (skillid != WZ_SIGHTRASHER &&
+ if( skillid != WZ_SIGHTRASHER &&
skillid != WZ_SIGHTBLASTER &&
- skillid != AC_SHOWER &&
- skillid != SM_MAGNUM &&
- bl->type == BL_SKILL && damage > 0) {
+ skillid != AC_SHOWER && skillid != MA_SHOWER &&
+ skillid != SM_MAGNUM && skillid != MS_MAGNUM &&
+ bl->type == BL_SKILL && damage > 0 )
+ {
struct skill_unit* su = (struct skill_unit*)bl;
if (su->group && skill_get_inf2(su->group->skill_id)&INF2_TRAP)
damage = 0; //Sight rasher, blaster, and arrow shower may dmg traps. [Kevin]
@@ -1835,12 +1849,16 @@ static int skill_check_unit_range_sub (struct block_list *bl, va_list ap)
break;
case AL_WARP:
case HT_SKIDTRAP:
+ case MA_SKIDTRAP:
case HT_LANDMINE:
+ case MA_LANDMINE:
case HT_ANKLESNARE:
case HT_SHOCKWAVE:
case HT_SANDMAN:
+ case MA_SANDMAN:
case HT_FLASHER:
case HT_FREEZINGTRAP:
+ case MA_FREEZINGTRAP:
case HT_BLASTMINE:
case HT_CLAYMORETRAP:
case HT_TALKIEBOX:
@@ -2289,17 +2307,21 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
switch(skillid)
{
+ case MER_CRASH:
case SM_BASH:
case MS_BASH:
case MC_MAMMONITE:
case TF_DOUBLE:
case AC_DOUBLE:
+ case MA_DOUBLE:
case AS_SONICBLOW:
case KN_PIERCE:
+ case ML_PIERCE:
case KN_SPEARBOOMERANG:
case TF_POISON:
case TF_SPRINKLESAND:
case AC_CHARGEARROW:
+ case MA_CHARGEARROW:
case RG_INTIMIDATE:
case AM_ACIDTERROR:
case BA_MUSICALSTRIKE:
@@ -2338,6 +2360,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
case NPC_SLEEPATTACK:
case LK_AURABLADE:
case LK_SPIRALPIERCE:
+ case ML_SPIRALPIERCE:
case LK_HEADCRUSH:
case CG_ARROWVULCAN:
case HW_MAGICCRASHER:
@@ -2438,6 +2461,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
break;
case SN_SHARPSHOOTING:
+ case MA_SHARPSHOOTING:
case NJ_KAMAITACHI:
//It won't shoot through walls since on castend there has to be a direct
//line of sight between caster and target.
@@ -2552,8 +2576,10 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
flag |= SD_PREAMBLE; // a fake packet will be sent for the first target to be hit
case AS_SPLASHER:
case SM_MAGNUM:
+ case MS_MAGNUM:
case HT_BLITZBEAT:
case AC_SHOWER:
+ case MA_SHOWER:
case MG_NAPALMBEAT:
case MG_FIREBALL:
case RG_RAID:
@@ -2598,15 +2624,19 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id);
//FIXME: move this to skill_additional_effect or some such? [ultramage]
- if (skillid == SM_MAGNUM) {
- //Initiate 10% of your damage becomes fire element.
+ if( skillid == SM_MAGNUM || skillid == MS_MAGNUM )
+ { // Initiate 10% of your damage becomes fire element.
sc_start4(src,SC_WATK_ELEMENT,100,3,20,0,0,skill_get_time2(skillid, skilllv));
- if (sd) skill_blockpc_start (sd, skillid, skill_get_time(skillid, skilllv));
+ if( sd )
+ skill_blockpc_start(sd, skillid, skill_get_time(skillid, skilllv));
+ if( bl->type == BL_MER )
+ skill_blockmerc_start((TBL_MER*)bl, skillid, skill_get_time(skillid, skilllv));
}
}
break;
case KN_BRANDISHSPEAR:
+ case ML_BRANDISH:
//Coded apart for it needs the flag passed to the damage calculation.
if (skill_area_temp[1] != bl->id)
skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag|SD_ANIMATION);
@@ -2615,6 +2645,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
break;
case KN_BOWLINGBASH:
+ case MS_BOWLINGBASH:
if(flag&1){
if(bl->id==skill_area_temp[1])
break;
@@ -2883,14 +2914,14 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
*------------------------------------------*/
int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, int skillid, int skilllv, unsigned int tick, int flag)
{
- struct map_session_data *sd;
+ struct map_session_data *sd, *dstsd;
+ struct mob_data *md, *dstmd;
struct homun_data *hd;
- struct map_session_data *dstsd;
+ struct mercenary_data *mer;
struct status_data *sstatus, *tstatus;
struct status_change *tsc;
struct status_change_entry *tsce;
- struct mob_data *md;
- struct mob_data *dstmd;
+
int i;
enum sc_type type;
@@ -2905,6 +2936,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
sd = BL_CAST(BL_PC, src);
hd = BL_CAST(BL_HOM, src);
md = BL_CAST(BL_MOB, src);
+ mer = BL_CAST(BL_MER, src);
dstsd = BL_CAST(BL_PC, bl);
dstmd = BL_CAST(BL_MOB, bl);
@@ -3080,10 +3112,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
break;
case AL_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)));
+ 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)));
break;
case AL_CRUCIS:
@@ -3097,12 +3128,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
break;
case PR_LEXDIVINA:
- if (tsce) {
+ case MER_LEXDIVINA:
+ if( tsce )
+ {
status_change_end(bl,type, -1);
clif_skill_nodamage (src, bl, skillid, skilllv, 1);
- } else
- clif_skill_nodamage (src, bl, skillid, skilllv,
- sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
+ }
+ else
+ clif_skill_nodamage (src, bl, skillid, skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
break;
case SA_ABRACADABRA:
@@ -3338,6 +3371,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
break;
//Passive Magnum, should had been casted on yourself.
case SM_MAGNUM:
+ case MS_MAGNUM:
skill_area_temp[1] = 0;
map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid, skilllv), BL_SKILL|BL_CHAR,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1, skill_castend_damage_id);
@@ -3359,11 +3393,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case PR_SUFFRAGIUM:
case PR_BENEDICTIO:
case LK_BERSERK:
+ case MS_BERSERK:
case KN_AUTOCOUNTER:
case KN_TWOHANDQUICKEN:
case KN_ONEHAND:
+ case MER_QUICKEN:
case CR_SPEARQUICKEN:
case CR_REFLECTSHIELD:
+ case MS_REFLECTSHIELD:
case AS_POISONREACT:
case MC_LOUD:
case MG_ENERGYCOAT:
@@ -3371,7 +3408,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case MO_STEELBODY:
case MO_BLADESTOP:
case LK_AURABLADE:
- case LK_PARRYING:
+ case LK_PARRYING:
+ case MS_PARRYING:
case LK_CONCENTRATION:
case WS_CARTBOOST:
case SN_SIGHT:
@@ -3401,6 +3439,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
break;
case MG_SIGHT:
+ case MER_SIGHT:
case AL_RUWACH:
case WZ_SIGHTBLASTER:
case NPC_WIDESIGHT:
@@ -3503,74 +3542,90 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
break;
case SM_PROVOKE:
- if((tstatus->mode&MD_BOSS) || battle_check_undead(tstatus->race,tstatus->def_ele)) {
+ case MER_PROVOKE:
+ if( (tstatus->mode&MD_BOSS) || battle_check_undead(tstatus->race,tstatus->def_ele) )
+ {
map_freeblock_unlock();
return 1;
}
//TODO: How much does base level affects? Dummy value of 1% per level difference used. [Skotlex]
clif_skill_nodamage(src,bl,skillid,skilllv,
- (i=sc_start(bl,type,
- 50 +3*skilllv +status_get_lv(src) -status_get_lv(bl),
- skilllv,skill_get_time(skillid,skilllv))));
- if (!i)
+ (i = sc_start(bl,type, 50 + 3*skilllv + status_get_lv(src) - status_get_lv(bl), skilllv, skill_get_time(skillid,skilllv))));
+ if( !i )
{
- if (sd)
+ if( sd )
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 0;
}
unit_skillcastcancel(bl, 2);
- if(tsc && tsc->count){
- if(tsc->data[SC_FREEZE])
+ if( tsc && tsc->count )
+ {
+ if( tsc->data[SC_FREEZE] )
status_change_end(bl,SC_FREEZE,-1);
- if(tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE)
+ if( tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE )
status_change_end(bl,SC_STONE,-1);
- if(tsc->data[SC_SLEEP])
+ if( tsc->data[SC_SLEEP] )
status_change_end(bl,SC_SLEEP,-1);
}
- if(dstmd) {
+ if( dstmd )
+ {
dstmd->state.provoke_flag = src->id;
- mob_target(dstmd,src,skill_get_range2(src,skillid,skilllv));
+ mob_target(dstmd, src, skill_get_range2(src,skillid,skilllv));
}
break;
+ case ML_DEVOTION:
case CR_DEVOTION:
- if(sd && dstsd)
{
- int count = min(skilllv, 5);
- int lv = sd->status.base_level - dstsd->status.base_level;
- if (lv < 0) lv = -lv;
- if (lv > battle_config.devotion_level_difference ||
- (dstsd->sc.data[type] && dstsd->sc.data[type]->val1 != src->id) || //Avoid overriding [Skotlex]
- (dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER) {
- clif_skill_fail(sd,skillid,0,0);
+ int count, lv;
+ if( !dstsd )
+ { // Only players can be devoted
+ if( sd )
+ clif_skill_fail(sd, skillid, 0, 0);
+ break;
+ }
+
+ if( (lv = status_get_lv(src) - dstsd->status.base_level) < 0 )
+ lv = -lv;
+ if( lv > battle_config.devotion_level_difference || // Level difference requeriments
+ (dstsd->sc.data[type] && dstsd->sc.data[type]->val1 != src->id) || // Cannot Devote a player devoted from another source
+ (skillid == ML_DEVOTION && (!mer || mer != dstsd->md)) || // Mercenary only can devote owner
+ (dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER ) // Crusader Cannot be devoted
+ {
+ if( sd )
+ clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
}
- // check if the char isn't devoted already
- ARR_FIND( 0, count, i, sd->devotion[i] == bl->id );
- if( i == count )
- {// not there, find first empty slot
- ARR_FIND( 0, count, i, sd->devotion[i] == 0 );
+ i = 0;
+ count = (sd)? min(skilllv,5) : 1; // Mercenary only can Devote owner
+ if( sd )
+ { // Player Devoting Player
+ ARR_FIND(0, count, i, sd->devotion[i] == bl->id );
if( i == count )
- {// all slots full, fail
- clif_skill_fail(sd,skillid,0,0);
- map_freeblock_unlock();
- return 1;
+ {
+ ARR_FIND(0, count, i, sd->devotion[i] == 0 );
+ if( i == count )
+ { // No free slots, skill Fail
+ clif_skill_fail(sd, skillid, 0, 0);
+ map_freeblock_unlock();
+ return 1;
+ }
}
+
+ sd->devotion[i] = bl->id;
}
+ else
+ mer->devotion_flag = 1; // Mercenary Devoting Owner
- sd->devotion[i] = bl->id;
- clif_skill_nodamage(src,bl,skillid,skilllv,
- sc_start4(bl,type,100,src->id,i,skill_get_range2(src,skillid,skilllv),skill_get_time2(skillid, skilllv),1000));
- clif_devotion(sd,NULL);
+ clif_skill_nodamage(src, bl, skillid, skilllv,
+ sc_start4(bl, type, 100, src->id, i, skill_get_range2(src,skillid,skilllv), skill_get_time2(skillid, skilllv), 1000));
+ clif_devotion(src, NULL);
}
- else
- if (sd)
- clif_skill_fail(sd,skillid,0,0);
break;
case MO_CALLSPIRITS:
@@ -3662,6 +3717,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
break;
case KN_BRANDISHSPEAR:
+ case ML_BRANDISH:
{
int c,n=4;
int dir = map_calc_dir(src,bl->x,bl->y);
@@ -3749,14 +3805,19 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case PR_MAGNIFICAT:
case PR_GLORIA:
case SN_WINDWALK:
- if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) {
- 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);
+ if( sd == NULL || sd->status.party_id == 0 || (flag & 1) )
+ 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 MER_MAGNIFICAT:
+ if( mer != NULL )
+ {
+ clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
+ if( mer->master && mer->master->status.party_id != 0 && !(flag&1) )
+ party_foreachsamemap(skill_area_sub, mer->master, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id);
+ else if( mer->master && !(flag&1) )
+ clif_skill_nodamage(src, &mer->master->bl, skillid, skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
}
break;
@@ -3778,7 +3839,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case BS_MAXIMIZE:
case NV_TRICKDEAD:
case CR_DEFENDER:
+ case ML_DEFENDER:
case CR_AUTOGUARD:
+ case ML_AUTOGUARD:
case TK_READYSTORM:
case TK_READYDOWN:
case TK_READYTURN:
@@ -3814,9 +3877,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
clif_skill_nodamage(src,bl,skillid,skilllv,
sc_start(bl,type,100,skilllv,skill_get_time(skillid, skilllv)));
break;
- case SM_AUTOBERSERK: // Celest
- if (tsce)
- i = status_change_end(bl, type, -1);
+ case SM_AUTOBERSERK:
+ case MER_AUTOBERSERK:
+ if( tsce )
+ i = status_change_end(bl, type, -1);
else
i = sc_start(bl,type,100,skilllv,60000);
clif_skill_nodamage(src,bl,skillid,skilllv,i);
@@ -3996,18 +4060,63 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
mob_unlocktarget(dstmd,tick);
break;
+ // Mercenary Supportive Skills
+ case MER_BENEDICTION:
+ status_change_end(bl, SC_CURSE, -1);
+ status_change_end(bl, SC_BLIND, -1);
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ break;
+ case MER_COMPRESS:
+ status_change_end(bl, SC_BLEEDING, -1);
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ break;
+ case MER_MENTALCURE:
+ status_change_end(bl, SC_CONFUSION, -1);
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ break;
+ case MER_RECUPERATE:
+ status_change_end(bl, SC_POISON, -1);
+ status_change_end(bl, SC_SILENCE, -1);
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ break;
+ case MER_REGAIN:
+ status_change_end(bl, SC_SLEEP, -1);
+ status_change_end(bl, SC_STUN, -1);
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ break;
+ case MER_TENDER:
+ status_change_end(bl, SC_FREEZE, -1);
+ status_change_end(bl, SC_STONE, -1);
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ break;
+
+ case MER_SCAPEGOAT:
+ if( mer && mer->master )
+ {
+ status_heal(&mer->master->bl, mer->battle_status.hp, 0, 2);
+ status_damage(src, src, mer->battle_status.max_hp, 0, 0, 1);
+ }
+ break;
+
+ case MER_ESTIMATION:
+ if( !mer )
+ break;
+ sd = mer->master;
case WZ_ESTIMATION:
- if(sd) {
- if (dstsd) {
- clif_skill_fail(sd,skillid,0,0);
- break;
- }
- if (dstmd && dstmd->class_ == MOBID_EMPERIUM) {
- break;
- }
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- clif_skill_estimation((struct map_session_data *)src,bl);
+ if( sd == NULL )
+ break;
+ if( dstsd )
+ { // Fail on Players
+ clif_skill_fail(sd,skillid,0,0);
+ break;
}
+ if( dstmd && dstmd->class_ == MOBID_EMPERIUM )
+ break; // Cannot be Used on Emperium
+
+ clif_skill_nodamage(src, bl, skillid, skilllv, 1);
+ clif_skill_estimation(sd, bl);
+ if( skillid == MER_ESTIMATION )
+ sd = NULL;
break;
case BS_REPAIRWEAPON:
@@ -4676,6 +4785,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
}
break;
+ case MA_REMOVETRAP:
case HT_REMOVETRAP:
//FIXME: I think clif_skill_fail() is supposed to be sent if it fails below [ultramage]
clif_skill_nodamage(src, bl, skillid, skilllv, 1);
@@ -4684,13 +4794,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
struct skill_unit_group* sg;
su = BL_CAST(BL_SKILL, bl);
- if( (su)
- && (sg = su->group)
- && (sg->src_id == src->id || map_flag_vs(bl->m))
- && (skill_get_inf2(sg->skill_id)&INF2_TRAP) )
- { // prevent picking up expired traps
- if( !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) )
- {
+ // Mercenaries can remove any trap
+ // Players can only remove their own traps or traps on Vs maps.
+ if( su && (sg = su->group) && (src->type == BL_MER || sg->src_id == src->id || map_flag_vs(bl->m)) && (skill_get_inf2(sg->skill_id)&INF2_TRAP) )
+ {
+ if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) )
+ { // prevent picking up expired traps
if( battle_config.skill_removetrap_type )
{ // get back all items used to deploy the trap
for( i = 0; i < 10; i++ )
@@ -5095,7 +5204,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
clif_skill_nodamage(src,bl,skillid,skilllv,1);
for(i = 0; i < g->max_member; i++, j++) {
if (j>8) j=0;
- if ((dstsd = g->member[i].sd) != NULL && sd != dstsd) {
+ if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && !pc_isdead(dstsd)) {
if (map[dstsd->bl.m].flag.nowarp && !map_flag_gvg2(dstsd->bl.m))
continue;
if(map_getcell(src->m,src->x+dx[j],src->y+dy[j],CELL_CHKNOREACH))
@@ -5358,7 +5467,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr data)
break;
}
}
- if (ud->skillid == PR_LEXDIVINA)
+ if( ud->skillid == PR_LEXDIVINA || ud->skillid == MER_LEXDIVINA )
{
sc = status_get_sc(target);
if( battle_check_target(src,target, BCT_ENEMY) <= 0 && (!sc || !sc->data[SC_SILENCE]) )
@@ -5723,12 +5832,16 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
case CR_GRANDCROSS:
case NPC_GRANDDARKNESS:
case HT_SKIDTRAP:
+ case MA_SKIDTRAP:
case HT_LANDMINE:
+ case MA_LANDMINE:
case HT_ANKLESNARE:
case HT_SHOCKWAVE:
case HT_SANDMAN:
+ case MA_SANDMAN:
case HT_FLASHER:
case HT_FREEZINGTRAP:
+ case MA_FREEZINGTRAP:
case HT_BLASTMINE:
case HT_CLAYMORETRAP:
case AS_VENOMDUST:
@@ -5740,6 +5853,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
case WE_CALLPARENT:
case WE_CALLBABY:
case AC_SHOWER: //Ground-placed skill implementation.
+ case MA_SHOWER:
case SA_VOLCANO:
case SA_DELUGE:
case SA_VIOLENTGALE:
@@ -6333,12 +6447,16 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
case HT_SHOCKWAVE:
val1=skilllv*15+10;
case HT_SANDMAN:
+ case MA_SANDMAN:
case HT_CLAYMORETRAP:
case HT_SKIDTRAP:
+ case MA_SKIDTRAP:
case HT_LANDMINE:
+ case MA_LANDMINE:
case HT_ANKLESNARE:
case HT_FLASHER:
case HT_FREEZINGTRAP:
+ case MA_FREEZINGTRAP:
case HT_BLASTMINE:
if( map_flag_gvg(src->m) )
limit *= 4; // longer trap times in WOE [celest]
@@ -6557,13 +6675,17 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
val2 = map_getcell(src->m, ux, uy, CELL_GETTYPE);
break;
case HT_LANDMINE:
+ case MA_LANDMINE:
case HT_ANKLESNARE:
case HT_SHOCKWAVE:
case HT_SANDMAN:
+ case MA_SANDMAN:
case HT_FLASHER:
case HT_FREEZINGTRAP:
+ case MA_FREEZINGTRAP:
case HT_TALKIEBOX:
case HT_SKIDTRAP:
+ case MA_SKIDTRAP:
val1 = 3500;
break;
case GS_DESPERADO:
@@ -7780,7 +7902,9 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in
case TF_HIDING:
case AS_CLOAKING:
case CR_AUTOGUARD:
+ case ML_AUTOGUARD:
case CR_DEFENDER:
+ case ML_DEFENDER:
case ST_CHASEWALK:
case PA_GOSPEL:
case CR_SHRINK:
@@ -8411,10 +8535,11 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv)
{
int delaynodex = skill_get_delaynodex(skill_id, skill_lv);
int time = skill_get_delay(skill_id, skill_lv);
- //struct map_session_data *sd = BL_CAST(BL_PC, bl);
+ struct map_session_data *sd;
struct status_change *sc = status_get_sc(bl);
nullpo_retr(0, bl);
+ sd = BL_CAST(BL_PC, bl);
if (skill_id == SA_ABRACADABRA)
return 0; //Will use picked skill's delay.
@@ -8477,9 +8602,8 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv)
}
}
- if (!(delaynodex&4))
- if (bl->type == BL_PC && ((TBL_PC*)bl)->delayrate != 100)
- time = time * ((TBL_PC*)bl)->delayrate / 100;
+ if( !(delaynodex&4) && sd && sd->delayrate != 100 )
+ time = time * sd->delayrate / 100;
if (battle_config.delay_rate != 100)
time = time * battle_config.delay_rate / 100;
@@ -10557,6 +10681,30 @@ int skill_blockhomun_start(struct homun_data *hd, int skillid, int tick) //[orn]
return add_timer(gettick() + tick, skill_blockhomun_end, hd->bl.id, skillid);
}
+int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr data) //[orn]
+{
+ struct mercenary_data *md = (TBL_MER*)map_id2bl(id);
+ if( data <= 0 || data >= MAX_SKILL )
+ return 0;
+ if( md ) md->blockskill[data] = 0;
+
+ return 1;
+}
+
+int skill_blockmerc_start(struct mercenary_data *md, int skillid, int tick)
+{
+ nullpo_retr (-1, md);
+
+ if( (skillid = skill_get_index(skillid)) == 0 )
+ return -1;
+ if( tick < 1 )
+ {
+ md->blockskill[skillid] = 0;
+ return -1;
+ }
+ md->blockskill[skillid] = 1;
+ return add_timer(gettick() + tick, skill_blockmerc_end, md->bl.id, skillid);
+}
/*
*
diff --git a/src/map/skill.h b/src/map/skill.h
index 34ce889b8..75cb63e9c 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -327,8 +327,9 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag );
int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skilllv,unsigned int tick,int flag);
-int skill_blockpc_start (struct map_session_data*,int,int); // [celest]
-int skill_blockhomun_start (struct homun_data*,int,int); //[orn]
+int skill_blockpc_start (struct map_session_data*,int,int);
+int skill_blockhomun_start (struct homun_data*,int,int);
+int skill_blockmerc_start (struct mercenary_data*,int,int);
// スキル攻?一括?理
int skill_attack( int attack_type, struct block_list* src, struct block_list *dsrc,struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag );
diff --git a/src/map/status.c b/src/map/status.c
index 44c829078..b1fd9df34 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -403,6 +403,26 @@ void initChangeTables(void)
set_sc( HAMI_DEFENCE , SC_DEFENCE , SI_BLANK , SCB_DEF );
set_sc( HAMI_BLOODLUST , SC_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK );
+ add_sc( MER_CRASH , SC_STUN );
+ set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
+ add_sc( MS_MAGNUM , SC_WATK_ELEMENT );
+ add_sc( MER_SIGHT , SC_SIGHT );
+ set_sc( MER_DECAGI , SC_DECREASEAGI , SI_DECREASEAGI , SCB_AGI|SCB_SPEED );
+ set_sc( MER_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN );
+ add_sc( MER_LEXDIVINA , SC_SILENCE );
+ add_sc( MA_LANDMINE , SC_STUN );
+ add_sc( MA_SANDMAN , SC_SLEEP );
+ add_sc( MA_FREEZINGTRAP , SC_FREEZE );
+ set_sc( MER_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE );
+ set_sc( ML_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE );
+ set_sc( MS_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE );
+ set_sc( ML_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD );
+ set_sc( MS_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE );
+ set_sc( MS_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN );
+ add_sc( ML_SPIRALPIERCE , SC_STOP );
+ set_sc( MER_QUICKEN , SC_MERC_QUICKEN , SI_BLANK , SCB_ASPD );
+ add_sc( ML_DEVOTION , SC_DEVOTION );
+
set_sc( GD_LEADERSHIP , SC_GUILDAURA , SI_BLANK , SCB_STR|SCB_AGI|SCB_VIT|SCB_DEX );
set_sc( GD_BATTLEORDER , SC_BATTLEORDERS , SI_BLANK , SCB_STR|SCB_INT|SCB_DEX );
set_sc( GD_REGENERATION , SC_REGENERATION , SI_BLANK , SCB_REGEN );
@@ -637,18 +657,23 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
if (sc && !sc->count)
sc = NULL;
- if (hp && !(flag&1)) {
- if (sc) {
+ if( hp && !(flag&1) ) {
+ if( sc ) {
struct status_change_entry *sce;
- if ((sce=sc->data[SC_DEVOTION]) && src && battle_getcurrentskill(src) != PA_PRESSURE)
- { //Devotion prevents any of the other ailments from ending.
- struct map_session_data *sd2 = map_id2sd(sce->val1);
- if (sd2 && sd2->devotion[sce->val2] == target->id && check_distance_bl(target, &sd2->bl, sce->val3))
+ if( (sce = sc->data[SC_DEVOTION]) && src && battle_getcurrentskill(src) != PA_PRESSURE )
+ { // Devotion prevents any of the other ailments from ending.
+ struct block_list *d_bl = map_id2bl(sce->val1);
+
+ if( d_bl && (
+ (d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == target->id) ||
+ (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id)
+ ) && check_distance_bl(target, d_bl, sce->val3) )
{
- clif_damage(&sd2->bl, &sd2->bl, gettick(), 0, 0, hp, 0, 0, 0);
- status_fix_damage(NULL, &sd2->bl, hp, 0);
+ clif_damage(d_bl, d_bl, gettick(), 0, 0, hp, 0, 0, 0);
+ status_fix_damage(NULL, d_bl, hp, 0);
return 0;
}
+
status_change_end(target, SC_DEVOTION, -1);
}
if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
@@ -2963,11 +2988,6 @@ void status_calc_bl_sub_mer(struct mercenary_data *md, unsigned long flag)
status->max_sp = cap_value(status->max_sp, 1, battle_config.max_sp);
status->sp = cap_value(status->sp, 0, status->max_sp);
}
- if( flag&SCB_VIT )
- {
- flag |= SCB_DEF;
- status->def += status->vit; // Doddler says Merc DEF = DEF + VIT
- }
if( flag == SCB_ALL )
return; // Client Refresh invoked by status_calc_mercenary
@@ -3908,6 +3928,10 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
max < sc->data[SC_ONEHAND]->val2)
max = sc->data[SC_ONEHAND]->val2;
+ if(sc->data[SC_MERC_QUICKEN] &&
+ max < sc->data[SC_MERC_QUICKEN]->val2)
+ max = sc->data[SC_MERC_QUICKEN]->val2;
+
if(sc->data[SC_ADRENALINE2] &&
max < sc->data[SC_ADRENALINE2]->val3)
max = sc->data[SC_ADRENALINE2]->val3;
@@ -4804,6 +4828,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
return 0;
break;
case SC_ONEHAND:
+ case SC_MERC_QUICKEN:
case SC_TWOHANDQUICKEN:
if(sc->data[SC_DECREASEAGI])
return 0;
@@ -4974,6 +4999,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
status_change_end(bl,SC_SPEARQUICKEN,-1);
status_change_end(bl,SC_TWOHANDQUICKEN,-1);
status_change_end(bl,SC_ONEHAND,-1);
+ status_change_end(bl,SC_MERC_QUICKEN,-1);
break;
case SC_ONEHAND:
//Removes the Aspd potion effect, as reported by Vicious. [Skotlex]
@@ -5010,6 +5036,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
status_change_end(bl,SC_CONCENTRATION,-1);
status_change_end(bl,SC_PARRYING,-1);
status_change_end(bl,SC_AURABLADE,-1);
+ status_change_end(bl,SC_MERC_QUICKEN,-1);
}
break;
case SC_ASSUMPTIO:
@@ -5140,19 +5167,23 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_ENDURE:
val2 = 7; // Hit-count [Celest]
- if (!(flag&1) && sd && !map_flag_gvg(bl->m) && (type != SC_ENDURE || !val4))
- { //See if there are devoted characters, and pass the status to them. [Skotlex]
- //(but do not pass infinite endure)
+ if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !val4 )
+ {
struct map_session_data *tsd;
- int i;
- for (i = 0; i < 5; i++)
- {
- if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])))
- status_change_start(&tsd->bl,type,10000,val1,val2,val3,val4,tick,1);
+ if( sd )
+ {
+ int i;
+ for( i = 0; i < 5; i++ )
+ {
+ if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) )
+ status_change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1);
+ }
}
+ else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
+ status_change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1);
}
//val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk)
- if(val4)
+ if( val4 )
tick = -1;
break;
case SC_AUTOBERSERK:
@@ -5221,16 +5252,21 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val2=val1*5; //Race/Ele resist
break;
case SC_REFLECTSHIELD:
- val2=10+val1*3; //% Dmg reflected
- if (sd && !(flag&1))
- { //Pass it to devoted chars.
+ val2=10+val1*3; // %Dmg reflected
+ if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) )
+ {
struct map_session_data *tsd;
- int i;
- for (i = 0; i < 5; i++)
- { //Pass the status to the other affected chars. [Skotlex]
- if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])))
- status_change_start(&tsd->bl,type,10000,val1,val2,0,0,tick,1);
+ if( sd )
+ {
+ int i;
+ for( i = 0; i < 5; i++ )
+ {
+ if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) )
+ status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
+ }
}
+ else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
+ status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
}
break;
case SC_STRIPWEAPON:
@@ -5290,6 +5326,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if (val1 > 10) //For boss casted skills [Skotlex]
val2 += 20*(val1-10);
break;
+ case SC_MERC_QUICKEN:
+ val2 = 300;
+ break;
+
case SC_SPEARQUICKEN:
val2 = 200+10*val1;
break;
@@ -5458,19 +5498,28 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_AUTOGUARD:
- if (!(flag&1))
+ if( !(flag&1) )
{
struct map_session_data *tsd;
int i,t;
- for(i=val2=0;i<val1;i++) {
+ for( i = val2 = 0; i < val1; i++)
+ {
t = 5-(i>>1);
val2 += (t < 0)? 1:t;
}
- if (sd)
- for (i = 0; i < 5; i++)
- { //Pass the status to the other affected chars. [Skotlex]
- if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])))
- status_change_start(&tsd->bl,type,10000,val1,val2,0,0,tick,1);
+
+ if( bl->type&(BL_PC|BL_MER) )
+ {
+ if( sd )
+ {
+ for( i = 0; i < 5; i++ )
+ {
+ if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) )
+ status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
+ }
+ }
+ else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
+ status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
}
}
break;
@@ -5702,19 +5751,19 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_DEVOTION:
{
- struct map_session_data *src;
- if ((src = map_id2sd(val1)) && src->sc.count)
- { //Try to inherit the status from the Crusader [Skotlex]
- //Ideally, we should calculate the remaining time and use that, but we'll trust that
- //once the Crusader's status changes, it will reflect on the others.
+ struct block_list *d_bl;
+ struct status_change *d_sc;
+
+ if( (d_bl = map_id2bl(val1)) && (d_sc = status_get_sc(d_bl)) && d_sc->count )
+ { // Inherits Status From Source
const enum sc_type types[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, SC_ENDURE };
enum sc_type type2;
int i = map_flag_gvg(bl->m)?2:3;
- while (i >= 0) {
+ while( i >= 0 )
+ {
type2 = types[i];
- if (src->sc.data[type2])
- sc_start(bl,type2,100,src->sc.data[type2]->val1,
- skill_get_time(status_sc2skill(type2),src->sc.data[type2]->val1));
+ if( d_sc->data[type2] )
+ sc_start(bl, type2, 100, d_sc->data[type2]->val1, skill_get_time(status_sc2skill(type2),d_sc->data[type2]->val1));
i--;
}
}
@@ -6476,32 +6525,44 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
case SC_DEFENDER:
case SC_REFLECTSHIELD:
case SC_AUTOGUARD:
- if (sd) {
- struct map_session_data *tsd;
- int i;
- for (i = 0; i < 5; i++)
- { //Clear the status from the others too [Skotlex]
- if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) && tsd->sc.data[type])
- status_change_end(&tsd->bl,type,-1);
+ {
+ struct map_session_data *tsd;
+ if( bl->type == BL_PC )
+ { // Clear Status from others
+ int i;
+ for( i = 0; i < 5; i++ )
+ {
+ if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) && tsd->sc.data[type] )
+ status_change_end(&tsd->bl, type, -1);
+ }
+ }
+ else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag )
+ { // Clear Status from Master
+ tsd = ((TBL_MER*)bl)->master;
+ if( tsd && tsd->sc.data[type] )
+ status_change_end(&tsd->bl, type, -1);
+ }
}
- }
- break;
- case SC_DEVOTION:
- {
- struct map_session_data *md = map_id2sd(sce->val1);
- //The status could have changed because the Crusader left the game. [Skotlex]
- if (md)
+ break;
+ case SC_DEVOTION:
{
- md->devotion[sce->val2] = 0;
- clif_devotion(md,NULL);
+ struct block_list *d_bl = map_id2bl(sce->val1);
+ if( d_bl )
+ {
+ if( d_bl->type == BL_PC )
+ ((TBL_PC*)d_bl)->devotion[sce->val2] = 0;
+ else if( d_bl->type == BL_MER )
+ ((TBL_MER*)d_bl)->devotion_flag = 0;
+ clif_devotion(d_bl, NULL);
+ }
+
+ status_change_end(bl,SC_AUTOGUARD,-1);
+ status_change_end(bl,SC_DEFENDER,-1);
+ status_change_end(bl,SC_REFLECTSHIELD,-1);
+ status_change_end(bl,SC_ENDURE,-1);
}
- //Remove inherited status [Skotlex]
- status_change_end(bl,SC_AUTOGUARD,-1);
- status_change_end(bl,SC_DEFENDER,-1);
- status_change_end(bl,SC_REFLECTSHIELD,-1);
- status_change_end(bl,SC_ENDURE,-1);
- }
- break;
+ break;
+
case SC_BLADESTOP:
if(sce->val4)
{
@@ -6608,8 +6669,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
sc->data[SC_ENDURE]->val4 = 0;
status_change_end(bl, SC_ENDURE, -1);
}
- sc_start4(bl, SC_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP),
- skill_get_time(LK_BERSERK, sce->val1));
+ sc_start4(bl, SC_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill_get_time(LK_BERSERK, sce->val1));
break;
case SC_GOSPEL:
if (sce->val3) { //Clear the group.
@@ -6725,6 +6785,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
case SC_ONEHAND:
case SC_SPEARQUICKEN:
case SC_CONCENTRATION:
+ case SC_MERC_QUICKEN:
sc->opt3 &= ~0x1;
opt_flag = 0;
break;
@@ -6813,7 +6874,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
}
//On Aegis, when turning off a status change, first goes the sc packet, then the option packet.
- if( vd && pcdb_checkid(vd->class_) )
+ if( vd && (pcdb_checkid(vd->class_) || bl->type == BL_MER ) )
clif_status_change(bl,StatusIconChangeTable[type],0);
else if (sd)
clif_status_load(bl,StatusIconChangeTable[type],0);
diff --git a/src/map/status.h b/src/map/status.h
index ae26c499e..f5e36ec88 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -302,6 +302,7 @@ typedef enum sc_type {
SC_MERC_HPUP,
SC_MERC_SPUP,
SC_MERC_HITUP,
+ SC_MERC_QUICKEN,
SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
} sc_type;
diff --git a/src/map/unit.c b/src/map/unit.c
index 4003e89c6..daa96819f 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -945,29 +945,32 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
return 0;
}
//TODO: Add type-independant skill_check_condition function.
- if (src->type == BL_MOB) {
- switch (skill_num) {
+ if( src->type == BL_MOB )
+ switch( skill_num )
+ {
case NPC_SUMMONSLAVE:
case NPC_SUMMONMONSTER:
case AL_TELEPORT:
- if (((TBL_MOB*)src)->master_id && ((TBL_MOB*)src)->special_state.ai)
+ if( ((TBL_MOB*)src)->master_id && ((TBL_MOB*)src)->special_state.ai )
return 0;
}
- }
-
+
//Check range when not using skill on yourself or is a combo-skill during attack
//(these are supposed to always have the same range as your attack)
- if(src->id != target_id && (!temp || ud->attacktimer == -1))
+ if( src->id != target_id && (!temp || ud->attacktimer == -1) )
{
- if (skill_get_state(ud->skillid) == ST_MOVE_ENABLE)
+ if( skill_get_state(ud->skillid) == ST_MOVE_ENABLE )
{
- if (!unit_can_reach_bl(src, target, skill_get_range2(src, skill_num,skill_lv)+1, 1, NULL, NULL))
- return 0; //Walk-path check failed.
- } else
- if (!battle_check_range(src, target, skill_get_range2(src, skill_num,skill_lv)
- +(skill_num==RG_CLOSECONFINE?0:1)))
- //Close confine is exploitable thanks to this extra range "feature" of the client. [Skotlex]
- return 0; //Arrow-path check failed.
+ if( !unit_can_reach_bl(src, target, skill_get_range2(src, skill_num,skill_lv) + 1, 1, NULL, NULL) )
+ return 0; // Walk-path check failed.
+ }
+ else if( src->type == BL_MER && skill_num == MA_REMOVETRAP )
+ {
+ if( !battle_check_range(battle_get_master(src), target, skill_get_range2(src, skill_num, skill_lv) + 1) )
+ return 0; // Aegis calc remove trap based on Master position, ignoring mercenary O.O
+ }
+ else if( !battle_check_range(src, target, skill_get_range2(src, skill_num,skill_lv) + (skill_num == RG_CLOSECONFINE?0:1)) )
+ return 0; // Arrow-path check failed.
}
if (!temp) //Stop attack on non-combo skills [Skotlex]
@@ -1028,8 +1031,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
if (!(skill_get_castnodex(skill_num, skill_lv)&2))
casttime = skill_castfix_sc(src, casttime);
- if( casttime>0 || temp){
-
+ if( casttime > 0 || temp )
+ {
clif_skillcasting(src, src->id, target_id, 0,0, skill_num, skill_get_ele(skill_num, skill_lv), casttime);
if (sd && target->type == BL_MOB)
@@ -1062,8 +1065,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
}
}
- if( casttime<=0 )
- ud->state.skillcastcancel=0;
+ if( casttime <= 0 )
+ ud->state.skillcastcancel = 0;
ud->canact_tick = tick + casttime + 100;
ud->skilltarget = target_id;
@@ -1072,14 +1075,14 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
ud->skillid = skill_num;
ud->skilllv = skill_lv;
- if(sc && sc->data[SC_CLOAKING] &&
- !(sc->data[SC_CLOAKING]->val4&4) && skill_num != AS_CLOAKING)
+ if( sc && sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&4) && skill_num != AS_CLOAKING )
{
status_change_end(src,SC_CLOAKING,-1);
if (!src->prev) return 0; //Warped away!
}
- if(casttime > 0) {
+ if( casttime > 0 )
+ {
ud->skilltimer = add_timer( tick+casttime, skill_castend_id, src->id, 0 );
if( sd && pc_checkskill(sd,SA_FREECAST) > 0 )
status_calc_bl(&sd->bl, SCB_SPEED);
@@ -1147,12 +1150,12 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh
bl.x = skill_x;
bl.y = skill_y;
- if (skill_get_state(ud->skillid) == ST_MOVE_ENABLE)
+ if( skill_get_state(ud->skillid) == ST_MOVE_ENABLE )
{
- if (!unit_can_reach_bl(src, &bl, skill_get_range2(src, skill_num,skill_lv)+1, 1, NULL, NULL))
+ if( !unit_can_reach_bl(src, &bl, skill_get_range2(src, skill_num,skill_lv) + 1, 1, NULL, NULL) )
return 0; //Walk-path check failed.
- } else
- if (!battle_check_range(src,&bl,skill_get_range2(src, skill_num,skill_lv)+1))
+ }
+ else if( !battle_check_range(src, &bl, skill_get_range2(src, skill_num,skill_lv) + 1) )
return 0; //Arrow-path check failed.
unit_stop_attack(src);
@@ -1162,10 +1165,12 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh
if (!(skill_get_castnodex(skill_num, skill_lv)&2))
casttime = skill_castfix_sc(src, casttime);
- if( casttime>0 ) {
+ if( casttime > 0 )
+ {
unit_stop_walking( src, 1);
clif_skillcasting(src, src->id, 0, skill_x, skill_y, skill_num, skill_get_ele(skill_num, skill_lv), casttime);
- } else
+ }
+ else
ud->state.skillcastcancel=0;
ud->canact_tick = tick + casttime + 100;
@@ -1181,14 +1186,16 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh
if (!src->prev) return 0; //Warped away!
}
- if(casttime > 0) {
+ if( casttime > 0 )
+ {
ud->skilltimer = add_timer( tick+casttime, skill_castend_pos, src->id, 0 );
if( sd && pc_checkskill(sd,SA_FREECAST) > 0 )
status_calc_bl(&sd->bl, SCB_SPEED);
else
unit_stop_walking(src,1);
}
- else {
+ else
+ {
ud->skilltimer = INVALID_TIMER;
skill_castend_pos(ud->skilltimer,tick,src->id,0);
}