summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorshennetsind <shennetsind@54d463be-8e91-2dee-dedb-b68131a5f0ec>2012-01-07 03:04:24 +0000
committershennetsind <shennetsind@54d463be-8e91-2dee-dedb-b68131a5f0ec>2012-01-07 03:04:24 +0000
commit73ad7989194c210cd90f6f3a696250df162b69eb (patch)
treecf3795a1afaff4226a5d5c75c76c4403105b1a4d /src
parent6d5d8185e0213433def88dece01f66f180bb1a92 (diff)
downloadhercules-73ad7989194c210cd90f6f3a696250df162b69eb.tar.gz
hercules-73ad7989194c210cd90f6f3a696250df162b69eb.tar.bz2
hercules-73ad7989194c210cd90f6f3a696250df162b69eb.tar.xz
hercules-73ad7989194c210cd90f6f3a696250df162b69eb.zip
Initial support for Royal Guard and some adjustments here and there.
- credits to 3ceam for the base. - should you step by any bugs let us know, http://rathena.org/board/tracker/ git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@15404 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src')
-rw-r--r--src/map/battle.c168
-rw-r--r--src/map/battle.h4
-rw-r--r--src/map/clif.c2
-rw-r--r--src/map/pc.c120
-rw-r--r--src/map/pc.h8
-rw-r--r--src/map/skill.c484
-rw-r--r--src/map/status.c122
7 files changed, 819 insertions, 89 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index 84ff53804..bc42609ec 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -454,6 +454,11 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
return 0;
}
+ if( flag&BF_MAGIC && (sce=sc->data[SC_PRESTIGE]) && rand()%100 < sce->val2) {
+ clif_specialeffect(bl, 462, AREA); // Still need confirm it.
+ return 0;
+ }
+
if (((sce=sc->data[SC_UTSUSEMI]) || sc->data[SC_BUNSINJYUTSU])
&&
flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK))
@@ -585,6 +590,9 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
rand()%100 < sce->val3)
status_heal(src, damage*sce->val4/100, 0, 3);
+ if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rand()%100 < sce->val2 )
+ pc_addspiritball(sd,skill_get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3);
+
}
//SC effects from caster side.
@@ -1135,6 +1143,8 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
case CR_SHIELDBOOMERANG:
case PA_SHIELDCHAIN:
+ case LG_SHIELDPRESS:
+ case LG_EARTHDRIVE:
flag.weapon = 0;
break;
@@ -1162,6 +1172,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
break;
case NPC_CRITICALSLASH:
+ case LG_PINPOINTATTACK:
flag.cri = 1; //Always critical skill.
break;
@@ -1439,6 +1450,8 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
break;
case CR_SHIELDBOOMERANG:
case PA_SHIELDCHAIN:
+ case LG_SHIELDPRESS:
+ case LG_EARTHDRIVE:
wd.damage = sstatus->batk;
if (sd) {
short index = sd->equip_index[EQI_HAND_L];
@@ -1971,7 +1984,70 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
skillratio += 100 + 100 * skill_lv + sstatus->vit;
if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
break;
-
+ case LG_CANNONSPEAR:// Stimated formula. Still need confirm it.
+ skillratio += -100 + (50 + sstatus->str) * skill_lv;
+ if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
+ break;
+ case LG_BANISHINGPOINT:
+ skillratio += -100 + ((50 * skill_lv) + (30 * ((sd)?pc_checkskill(sd,SM_BASH):1)));
+ if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
+ break;
+ case LG_SHIELDPRESS:
+ skillratio += 60 + 43 * skill_lv;
+ //if( sc && sc->data[SC_GLOOMYDAY_SK] )
+ // skillratio += 80 + (5 * sc->data[SC_GLOOMYDAY_SK]->val1);
+ if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
+ break;
+ case LG_PINPOINTATTACK:
+ skillratio = ((100 * skill_lv) + (10 * status_get_agi(src)) );
+ if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
+ break;
+ case LG_RAGEBURST:
+ if( sd && sd->spiritball_old )
+ skillratio += -100 + (sd->spiritball_old * 200);
+ else
+ skillratio += -100 + 15 * 200;
+ if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
+ break;
+ case LG_SHIELDSPELL:
+ if( wflag&1 ) {
+ skillratio += 200;
+ if( sd ) {
+ struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]];
+ if( shield_data )
+ skillratio *= shield_data->def;
+ } else
+ skillratio *= 9;
+ } else
+ skillratio += (sd) ? sd->shieldmdef * 20 : 1000;
+ break;
+ case LG_MOONSLASHER:
+ skillratio += -100 + (120 * skill_lv + ((sd) ? pc_checkskill(sd,LG_OVERBRAND) : 5) * 80);
+ if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
+ break;
+ case LG_OVERBRAND:
+ skillratio = 400 * skill_lv + (pc_checkskill(sd,CR_SPEARQUICKEN) * 30);
+ if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
+ break;
+ case LG_OVERBRAND_BRANDISH:
+ skillratio = 300 * skill_lv + (2 * (sstatus->str + sstatus->dex) / 3);
+ if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
+ break;
+ case LG_OVERBRAND_PLUSATK:
+ skillratio = 150 * skill_lv;
+ if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
+ break;
+ case LG_RAYOFGENESIS:
+ skillratio = skillratio + 200 + 300 * skill_lv;
+ if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
+ break;
+ case LG_EARTHDRIVE:
+ skillratio = (skillratio + 100) * skill_lv;
+ if( status_get_lv(src) > 100 ) skillratio += skillratio * (status_get_lv(src) - 100) / 200; // Base level bonus.
+ break;
+ case LG_HESPERUSLIT:
+ skillratio += 120 * skill_lv - 100;
+ break;
}
ATK_RATE(skillratio);
@@ -2009,7 +2085,15 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
if(sd)
ATK_ADD(30*pc_checkskill(sd, RA_TOOTHOFWUG));
break;
-
+ /**
+ * Royal Guard
+ **/
+ case LG_RAYOFGENESIS:
+ if( sc && sc->data[SC_BANDING] ) {// Increase only if the RG is under Banding.
+ short lv = (short)skill_lv;
+ ATK_ADDRATE( 190 * ((sd) ? skill_check_pc_partner(sd,(short)skill_num,&lv,skill_get_splash(skill_num,skill_lv),0) : 1));
+ }
+ break;
}
}
//Div fix.
@@ -2588,21 +2672,25 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
hp = 2*hp/100; //2% hp loss per hit
status_zap(src, hp, 0);
}
- /**
- * affecting non-skills
- **/
- if( !skill_num ) {
/**
- * RK Enchant Blade
+ * affecting non-skills
**/
- if( sc->data[SC_ENCHANTBLADE] && sd && ( (flag.rh && sd->weapontype1) || (flag.lh && sd->weapontype2) ) ) {
- struct Damage md = battle_calc_magic_attack(src, target, RK_ENCHANTBLADE, pc_checkskill(sd,RK_ENCHANTBLADE), wflag);
- wd.damage += md.damage;
- wd.flag |= md.flag;
+ if( !skill_num ) {
+ /**
+ * RK Enchant Blade
+ **/
+ if( sc->data[SC_ENCHANTBLADE] && sd && ( (flag.rh && sd->weapontype1) || (flag.lh && sd->weapontype2) ) ) {
+ struct Damage md = battle_calc_magic_attack(src, target, RK_ENCHANTBLADE, pc_checkskill(sd,RK_ENCHANTBLADE), wflag);
+ wd.damage += md.damage;
+ wd.flag |= md.flag;
+ }
}
}
-
+ if( skill_num == LG_RAYOFGENESIS ) {
+ struct Damage md = battle_calc_magic_attack(src, target, skill_num, skill_lv, wflag);
+ wd.damage += md.damage;
}
+
return wd;
}
@@ -3502,18 +3590,21 @@ int battle_calc_return_damage(struct block_list* bl, struct block_list *src, int
{
struct map_session_data* sd = NULL;
int rdamage = 0, damage = *dmg;
+ struct status_change* sc;
sd = BL_CAST(BL_PC, bl);
-
- //Bounces back part of the damage.
- if (flag & BF_SHORT) {
- struct status_change* sc;
+ sc = status_get_sc(bl);
+
+ if( sc && sc->data[SC_REFLECTDAMAGE] ) {
+ int max_damage = status_get_max_hp(bl) * status_get_lv(bl) / 100;
+ rdamage = (*dmg) * sc->data[SC_REFLECTDAMAGE]->val2 / 100;
+ if( rdamage > max_damage ) rdamage = max_damage;
+ } else if (flag & BF_SHORT) {//Bounces back part of the damage.
if (sd && sd->short_weapon_damage_return)
{
rdamage += damage * sd->short_weapon_damage_return / 100;
if(rdamage < 1) rdamage = 1;
}
- sc = status_get_sc(bl);
if( sc && sc->count ) {
if (sc->data[SC_REFLECTSHIELD]) {
rdamage += damage * sc->data[SC_REFLECTSHIELD]->val2 / 100;
@@ -3587,7 +3678,34 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage,
if (rhp || rsp)
status_zap(tbl, rhp, rsp);
}
+// Deals the same damage to targets in area. [pakpil]
+int battle_damage_area( struct block_list *bl, va_list ap) {
+ unsigned int tick;
+ int amotion, dmotion, damage;
+ struct block_list *src;
+ nullpo_ret(bl);
+
+ tick=va_arg(ap, unsigned int);
+ src=va_arg(ap,struct block_list *);
+ amotion=va_arg(ap,int);
+ dmotion=va_arg(ap,int);
+ damage=va_arg(ap,int);
+ if( bl->type == BL_MOB && ((TBL_MOB*)bl)->class_ == MOBID_EMPERIUM )
+ return 0;
+ if( bl != src && battle_check_target(src,bl,BCT_ENEMY) > 0 ) {
+ map_freeblock_lock();
+ if( amotion )
+ battle_delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0);
+ else
+ status_fix_damage(src,bl,damage,0);
+ clif_damage(bl,bl,tick,amotion,dmotion,damage,1,ATK_BLOCK,0);
+ skill_additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
+ map_freeblock_unlock();
+ }
+
+ return 0;
+}
/*==========================================
* ’Ê??UŒ‚?ˆ—?‚Ü‚Æ‚ß
*------------------------------------------*/
@@ -3750,11 +3868,15 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
}
rdamage = battle_calc_return_damage(target,src, &damage, wd.flag);
- 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,ATK_DEF,tick);
+ if( rdamage > 0 ) {
+ if( tsc && tsc->data[SC_REFLECTDAMAGE] ) {
+ if( src != target )// Don't reflect your own damage (Grand Cross)
+ map_foreachinshootrange(battle_damage_area,target,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd.amotion,wd.dmotion,rdamage,tstatus->race,0);
+ } else {
+ 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,ATK_DEF,tick);
+ }
}
}
@@ -3818,7 +3940,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
battle_drain(sd, target, wd.damage, wd.damage2, tstatus->race, is_boss(target));
}
}
- if (rdamage > 0) { //By sending attack type "none" skill_additional_effect won't be invoked. [Skotlex]
+ if (rdamage > 0 && !(tsc && tsc->data[SC_REFLECTDAMAGE])) { //By sending attack type "none" skill_additional_effect won't be invoked. [Skotlex]
if(tsd && src != target)
battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src));
battle_delay_damage(tick, wd.amotion, target, src, 0, CR_REFLECTSHIELD, 0, rdamage, ATK_DEF, rdelay);
diff --git a/src/map/battle.h b/src/map/battle.h
index 6c280e085..e1e196d4d 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -512,5 +512,9 @@ int battle_get_value(const char* w1);
//
struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int range, int type, int ignore_id);
+/**
+ * Royal Guard
+ **/
+int battle_damage_area( struct block_list *bl, va_list ap);
#endif /* _BATTLE_H_ */
diff --git a/src/map/clif.c b/src/map/clif.c
index 03fee5668..65d16f0a6 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -15549,7 +15549,7 @@ static int packetdb_readdb(void)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 25,
//#0x0440
- 0, 4, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 10, 4, -1, 0, 0, 0, 14, 0, 0, 0, 6, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
diff --git a/src/map/pc.c b/src/map/pc.c
index 0a7d1c901..25c0f5789 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -182,7 +182,10 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max)
memmove(sd->spirit_timer+i+1, sd->spirit_timer+i, (sd->spiritball-i)*sizeof(int));
sd->spirit_timer[i] = tid;
sd->spiritball++;
- clif_spiritball(sd);
+ if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
+ clif_millenniumshield(sd,sd->spiritball);
+ else
+ clif_spiritball(sd);
return 0;
}
@@ -217,11 +220,111 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type)
sd->spirit_timer[i] = INVALID_TIMER;
}
- if(!type)
- clif_spiritball(sd);
+ if(!type) {
+ if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
+ clif_millenniumshield(sd,sd->spiritball);
+ else
+ clif_spiritball(sd);
+ }
+ return 0;
+}
+static int pc_check_banding( struct block_list *bl, va_list ap ) {
+ int *c, *b_sd;
+ struct block_list *src;
+ struct map_session_data *tsd;
+ struct status_change *sc;
+
+ nullpo_ret(bl);
+ nullpo_ret(tsd = (struct map_session_data*)bl);
+ nullpo_ret(src = va_arg(ap,struct block_list *));
+ c = va_arg(ap,int *);
+ b_sd = va_arg(ap, int *);
+
+ if(pc_isdead(tsd))
+ return 0;
+
+ sc = status_get_sc(bl);
+
+ if( bl == src )
+ return 0;
+
+ if( sc && sc->data[SC_BANDING] )
+ {
+ b_sd[(*c)++] = tsd->bl.id;
+ return 1;
+ }
return 0;
}
+int pc_banding(struct map_session_data *sd, short skill_lv) {
+ int c;
+ int b_sd[MAX_PARTY]; // In case of a full Royal Guard party.
+ int i, j, hp, extra_hp = 0, tmp_qty = 0, tmp_hp;
+ struct map_session_data *bsd;
+ struct status_change *sc;
+ int range = skill_get_splash(LG_BANDING,skill_lv);
+
+ nullpo_ret(sd);
+
+ c = 0;
+ memset(b_sd, 0, sizeof(b_sd));
+ i = party_foreachsamemap(pc_check_banding,sd,range,&sd->bl,&c,&b_sd);
+
+ if( c < 1 )
+ { // No more Royal Guards in Banding found.
+ if( (sc = status_get_sc(&sd->bl)) != NULL && sc->data[SC_BANDING] )
+ {
+ sc->data[SC_BANDING]->val2 = 0; // Reset the counter
+ status_calc_bl(&sd->bl,StatusChangeFlagTable[SC_BANDING]);
+ }
+ return 0;
+ }
+
+ //Add yourself
+ hp = status_get_hp(&sd->bl);
+ i++;
+
+ // Get total HP of all Royal Guards in party.
+ for( j = 0; j < i; j++ )
+ {
+ bsd = map_id2sd(b_sd[j]);
+ if( bsd != NULL )
+ hp += status_get_hp(&bsd->bl);
+ }
+
+ // Set average HP.
+ hp = hp / i;
+
+ // If a Royal Guard have full HP, give more HP to others that haven't full HP.
+ for( j = 0; j < i; j++ )
+ {
+ bsd = map_id2sd(b_sd[j]);
+ if( bsd != NULL && (tmp_hp = hp - status_get_max_hp(&bsd->bl)) > 0 )
+ {
+ extra_hp += tmp_hp;
+ tmp_qty++;
+ }
+ }
+
+ if( extra_hp > 0 && tmp_qty > 0 )
+ hp += extra_hp / tmp_qty;
+
+ for( j = 0; j < i; j++ )
+ {
+ bsd = map_id2sd(b_sd[j]);
+ if( bsd != NULL )
+ {
+ status_set_hp(&bsd->bl,hp,0); // Set hp
+ if( (sc = status_get_sc(&bsd->bl)) != NULL && sc->data[SC_BANDING] )
+ {
+ sc->data[SC_BANDING]->val2 = c; // Set the counter. It doesn't count your self.
+ status_calc_bl(&bsd->bl,StatusChangeFlagTable[SC_BANDING]); // Set atk and def.
+ }
+ }
+ }
+
+ return c;
+}
// Increases a player's fame points and displays a notice to him
void pc_addfame(struct map_session_data *sd,int count)
@@ -1845,7 +1948,11 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
case SP_DEF1:
if(sd->state.lr_flag != 2) {
bonus = status->def + val;
+ #if REMODE
+ status->def = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ #else
status->def = cap_value(bonus, CHAR_MIN, CHAR_MAX);
+ #endif
}
break;
case SP_DEF2:
@@ -1857,7 +1964,14 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
case SP_MDEF1:
if(sd->state.lr_flag != 2) {
bonus = status->mdef + val;
+ #if REMODE
+ status->mdef = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ #else
status->mdef = cap_value(bonus, CHAR_MIN, CHAR_MAX);
+ #endif
+ if( sd->state.lr_flag == 3 ) {//Shield, used for royal guard
+ sd->shieldmdef += bonus;
+ }
}
break;
case SP_MDEF2:
diff --git a/src/map/pc.h b/src/map/pc.h
index 8a82a278a..58ea2401c 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -101,7 +101,7 @@ struct map_session_data {
unsigned int active : 1; //Marks active player (not active is logging in/out, or changing map servers)
unsigned int menu_or_input : 1;// if a script is waiting for feedback from the player
unsigned int dead_sit : 2;
- unsigned int lr_flag : 2;
+ unsigned int lr_flag : 3;//1: left h. weapon; 2: arrow; 3: shield
unsigned int connect_new : 1;
unsigned int arrow_atk : 1;
unsigned int gangsterparadise : 1;
@@ -298,6 +298,7 @@ struct map_session_data {
int classchange; // [Valaris]
int speed_rate, speed_add_rate, aspd_add;
int itemhealrate2; // [Epoque] Increase heal rate of all healing items.
+ int shieldmdef;//royal guard's
unsigned int setitem_hash, setitem_hash2; //Split in 2 because shift operations only work on int ranges. [Skotlex]
short splash_range, splash_add_range;
@@ -460,6 +461,7 @@ struct map_session_data {
// temporary debugging of bug #3504
const char* delunit_prevfile;
int delunit_prevline;
+
};
//Update this max as necessary. 55 is the value needed for Super Baby currently
@@ -839,4 +841,8 @@ int pc_disguise(struct map_session_data *sd, int class_);
* Mechanic (Mado Gear)
**/
void pc_overheat(struct map_session_data *sd, int val);
+/**
+ * Royal Guard
+ **/
+int pc_banding(struct map_session_data *sd, short skill_lv);
#endif /* _PC_H_ */
diff --git a/src/map/skill.c b/src/map/skill.c
index de6dd518b..f0790efe3 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -90,6 +90,7 @@ int earthstrain_unit_pos;
int skill_stasis_check(struct block_list *bl, int src_id, int skillid);
static int skill_check_unit_range (struct block_list *bl, int x, int y, int skillid, int skilllv);
static int skill_check_unit_range2 (struct block_list *bl, int x, int y, int skillid, int skilllv);
+static int skill_destroy_trap( struct block_list *bl, va_list ap );
//Since only mob-casted splash skills can hit ice-walls
static inline int splash_target(struct block_list* bl)
{
@@ -1151,6 +1152,42 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
case GC_WEAPONCRUSH:
skill_castend_nodamage_id(src,bl,skillid,skilllv,tick,BCT_ENEMY);
break;
+ /**
+ * Royal Guard
+ **/
+ case LG_SHIELDPRESS:
+ sc_start(bl, SC_STUN, 30 + 8 * skilllv, skilllv, skill_get_time(skillid,skilllv));
+ break;
+ case LG_PINPOINTATTACK:
+ rate = 12 + (10 * skilllv + (sstatus->agi / 100) ) * 140 / 100;
+ switch( skilllv ) {
+ case 1:
+ sc_start(bl,SC_BLEEDING,rate,skilllv,skill_get_time(skillid,skilllv));
+ break;
+ case 2:
+ if( dstsd && dstsd->spiritball && rand()%100 < rate )
+ pc_delspiritball(dstsd, dstsd->spiritball, 0);
+ break;
+ default:
+ skill_break_equip(bl,(skilllv == 3) ? EQP_SHIELD : (skilllv == 4) ? EQP_ARMOR : EQP_WEAPON,rate,BCT_ENEMY);
+ break;
+ }
+ break;
+ case LG_MOONSLASHER:
+ rate = 32 + 8 * skilllv;
+ if( rand()%100 < rate && dstsd ) // Uses skill_addtimerskill to avoid damage and setsit packet overlaping. Officially clif_setsit is received about 500 ms after damage packet.
+ skill_addtimerskill(src,tick+500,bl->id,0,0,skillid,skilllv,BF_WEAPON,0);
+ else if( dstmd && !is_boss(bl) )
+ sc_start(bl,SC_STOP,100,skilllv,skill_get_time(skillid,skilllv));
+ break;
+ case LG_RAYOFGENESIS: // 50% chance to cause Blind on Undead and Demon monsters.
+ if ( battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON )
+ sc_start(bl, SC_BLIND,50, skilllv, skill_get_time(skillid,skilllv));
+ break;
+ case LG_EARTHDRIVE:
+ skill_break_equip(src, EQP_SHIELD, 500, BCT_SELF);
+ sc_start(bl, SC_EARTHDRIVE, 100, skilllv, skill_get_time(skillid, skilllv));
+ break;
}
if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai)
@@ -1988,8 +2025,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
skillid == MER_INCAGI || skillid == MER_BLESSING) && tsd->sc.data[SC_CHANGEUNDEAD] )
damage = 1;
- if( damage > 0 && dmg.flag&BF_WEAPON && src != bl && ( src == dsrc || ( dsrc->type == BL_SKILL && ( skillid == SG_SUN_WARM || skillid == SG_MOON_WARM || skillid == SG_STAR_WARM ) ) )
- && skillid != WS_CARTTERMINATION )
+ if( damage > 0 && (( dmg.flag&BF_WEAPON && src != bl && ( src == dsrc || ( dsrc->type == BL_SKILL && ( skillid == SG_SUN_WARM || skillid == SG_MOON_WARM || skillid == SG_STAR_WARM ) ) )
+ && skillid != WS_CARTTERMINATION) || (sc && sc->data[SC_REFLECTDAMAGE])) )
rdamage = battle_calc_return_damage(bl,src, &damage, dmg.flag);
//Skill hit type
@@ -2137,6 +2174,13 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_TETRAVORTEX_FIRE,-2,type);
break;
/**
+ * Royal Guard
+ **/
+ case LG_OVERBRAND_BRANDISH:
+ case LG_OVERBRAND_PLUSATK:
+ dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skillid,-1,5);
+ break;
+ /**
* Arch Bishop
**/
case AB_DUPLELIGHT_MELEE:
@@ -2168,6 +2212,10 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
case WL_CHAINLIGHTNING_ATK:
copy_skill = WL_CHAINLIGHTNING;
break;
+ case LG_OVERBRAND_BRANDISH:
+ case LG_OVERBRAND_PLUSATK:
+ copy_skill = LG_OVERBRAND;
+ break;
}
if ((tsd->status.skill[copy_skill].id == 0 || tsd->status.skill[copy_skill].flag == SKILL_FLAG_PLAGIARIZED) &&
@@ -2234,15 +2282,29 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
if (dmg.blewcount > 0 && bl!=dsrc && !status_isdead(bl))
{
int direction = -1; // default
- switch(skillid)
- {
- case MG_FIREWALL: direction = unit_getdir(bl); break; // backwards
- case WZ_STORMGUST: direction = unit_getdir(bl); break; // backwards
- case PR_SANCTUARY: direction = unit_getdir(bl); break; // backwards
- case WL_CRIMSONROCK: direction = map_calc_dir(bl,skill_area_temp[4],skill_area_temp[5]); break;
+ switch(skillid) {
+ case MG_FIREWALL:
+ case WZ_STORMGUST:
+ case PR_SANCTUARY:
+ case LG_OVERBRAND:
+ direction = unit_getdir(bl);// backwards
+ break;
+ case WL_CRIMSONROCK:
+ direction = map_calc_dir(bl,skill_area_temp[4],skill_area_temp[5]);
+ break;
}
- skill_blown(dsrc,bl,dmg.blewcount,direction,0);
+ if( skillid == LG_OVERBRAND ) {
+ if( skill_blown(dsrc,bl,dmg.blewcount,direction,0) ) {
+ short dir_x, dir_y;
+ dir_x = dirx[(direction+4)%8];
+ dir_y = diry[(direction+4)%8];
+ if( map_getcell(bl->m, bl->x+dir_x, bl->y+dir_y, CELL_CHKNOPASS) != 0 )
+ skill_addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skilllv, BF_WEAPON, flag );
+ } else
+ skill_addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skilllv, BF_WEAPON, flag );
+ } else
+ skill_blown(dsrc,bl,dmg.blewcount,direction,0);
}
//Delayed damage must be dealt after the knockback (it needs to know actual position of target)
@@ -2287,17 +2349,21 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
battle_drain(sd, bl, dmg.damage, dmg.damage2, tstatus->race, tstatus->mode&MD_BOSS);
}
- if( rdamage > 0 )
- {
- if( dmg.amotion )
- battle_delay_damage(tick, dmg.amotion,bl,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,0);
- else
- status_fix_damage(bl,src,rdamage,0);
- clif_damage(src,src,tick, dmg.amotion,0,rdamage,dmg.div_>1?dmg.div_:1,4,0);
- //Use Reflect Shield to signal this kind of skill trigger. [Skotlex]
- if( tsd && src != bl )
- battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src));
- skill_additional_effect(bl, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
+ if( rdamage > 0 ) {
+ if( sc && sc->data[SC_REFLECTDAMAGE] ) {
+ if( src != bl )// Don't reflect your own damage (Grand Cross)
+ map_foreachinshootrange(battle_damage_area,bl,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,bl,dmg.amotion,sstatus->dmotion,rdamage,tstatus->race);
+ } else {
+ if( dmg.amotion )
+ battle_delay_damage(tick, dmg.amotion,bl,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,0);
+ else
+ status_fix_damage(bl,src,rdamage,0);
+ clif_damage(src,src,tick, dmg.amotion,0,rdamage,dmg.div_>1?dmg.div_:1,4,0);
+ //Use Reflect Shield to signal this kind of skill trigger. [Skotlex]
+ if( tsd && src != bl )
+ battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src));
+ skill_additional_effect(bl, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
+ }
}
if( damage > 0 ) {
if( skillid == RK_CRUSHSTRIKE ) // Your weapon will not be broken if you miss.
@@ -2773,6 +2839,20 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data)
}
}
break;
+ case LG_MOONSLASHER:
+ if( target->type == BL_PC ) {
+ struct map_session_data *tsd = NULL;
+ if( (tsd = ((TBL_PC*)target)) && !pc_issit(tsd) ) {
+ pc_setsit(tsd);
+ skill_sit(tsd,1);
+ clif_sitting(&tsd->bl);
+ }
+ }
+ break;
+ case LG_OVERBRAND_BRANDISH:
+ case LG_OVERBRAND_PLUSATK:
+ skill_attack(BF_WEAPON, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag|SD_LEVEL);
+ break;
default:
skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
break;
@@ -3026,7 +3106,14 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
**/
case GC_CROSSIMPACT:
case GC_VENOMPRESSURE:
-
+ /**
+ * Royal Guard
+ **/
+ case LG_BANISHINGPOINT:
+ case LG_SHIELDPRESS:
+ case LG_RAGEBURST:
+ case LG_RAYOFGENESIS:
+ case LG_HESPERUSLIT:
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
break;
@@ -3112,6 +3199,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
case SN_SHARPSHOOTING:
case MA_SHARPSHOOTING:
case NJ_KAMAITACHI:
+ case LG_CANNONSPEAR:
//It won't shoot through walls since on castend there has to be a direct
//line of sight between caster and target.
skill_area_temp[1] = bl->id;
@@ -3267,6 +3355,11 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
**/
case GC_ROLLINGCUTTER:
case GC_COUNTERSLASH:
+ /**
+ * Royal Guard
+ **/
+ case LG_MOONSLASHER:
+ case LG_EARTHDRIVE:
if( flag&1 )
{ //Recursive invocation
// skill_area_temp[0] holds number of targets in area
@@ -3285,10 +3378,11 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
status_heal(src,heal,0,0);
}
}
- else
- {
- if ( skillid == NJ_BAKUENRYU )
+ else {
+ if( skillid == NJ_BAKUENRYU || skillid == LG_EARTHDRIVE )
clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ else if( skillid == LG_MOONSLASHER )
+ clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6);
skill_area_temp[0] = 0;
skill_area_temp[1] = bl->id;
@@ -3917,6 +4011,28 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
case NC_MAGNETICFIELD:
sc_start2(bl,SC_MAGNETICFIELD,100,skilllv,src->id,skill_get_time(skillid,skilllv));
break;
+ /**
+ * Royal Guard
+ **/
+ case LG_PINPOINTATTACK:
+ if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 1, 1) )
+ clif_slide(src,bl->x,bl->y);
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+ break;
+
+ case LG_SHIELDSPELL:
+ // flag&1: Phisycal Attack, flag&2: Magic Attack.
+ skill_attack((flag&1)?BF_WEAPON:BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
+ break;
+
+ case LG_OVERBRAND:
+ skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag|SD_LEVEL);
+ break;
+
+ case LG_OVERBRAND_BRANDISH:
+ skill_addtimerskill(src, tick + status_get_amotion(src)*8/10, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag|SD_LEVEL);
+ break;
+
case 0:
if(sd) {
if (flag & 3){
@@ -4559,7 +4675,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
* Guillotine Cross
**/
case GC_VENOMIMPRESS:
-
+ /**
+ * Royal Guard
+ **/
+ case LG_EXEEDBREAK:
+ case LG_PRESTIGE:
clif_skill_nodamage(src,bl,skillid,skilllv,
sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
break;
@@ -4876,6 +4996,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case NPC_VAMPIRE_GIFT:
case NPC_HELLJUDGEMENT:
case NPC_PULSESTRIKE:
+ case LG_MOONSLASHER:
skill_castend_damage_id(src, src, skillid, skilllv, tick, flag);
break;
@@ -5040,11 +5161,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
* Guilotine Cross
**/
case GC_CLOAKINGEXCEED:
+ /**
+ * Royal Guard
+ **/
+ case LG_FORCEOFVANGUARD:
if (tsce)
{
i = status_change_end(bl, type, INVALID_TIMER);
if( i )
- clif_skill_nodamage(src,bl,skillid,-1,i);
+ clif_skill_nodamage(src,bl,skillid,( skillid == LG_FORCEOFVANGUARD ) ? skilllv : -1,i);
else if( sd )
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
@@ -5052,7 +5177,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
}
i = sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv));
if( i )
- clif_skill_nodamage(src,bl,skillid,-1,i);
+ clif_skill_nodamage(src,bl,skillid,( skillid == LG_FORCEOFVANGUARD ) ? skilllv : -1,i);
else if( sd )
clif_skill_fail(sd,skillid,0,0);
break;
@@ -6618,16 +6743,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
}
break;
case RK_IGNITIONBREAK:
- //case LG_EARTHDRIVE:
- clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6);
- //if( skillid == LG_EARTHDRIVE )
- //{
- // int dummy = 1;
- // i = skill_get_splash(skillid,skilllv);
- // map_foreachinarea(skill_cell_overlap, src->m, src->x-i, src->y-i, src->x+i, src->y+i, BL_SKILL, LG_EARTHDRIVE, &dummy, src);
- //}
- map_foreachinrange(skill_area_sub, bl,skill_get_splash(skillid,skilllv),BL_CHAR,
- src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id);
+ case LG_EARTHDRIVE:
+ clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6);
+ i = skill_get_splash(skillid,skilllv);
+ if( skillid == LG_EARTHDRIVE ) {
+ int dummy = 1;
+ map_foreachinarea(skill_cell_overlap, src->m, src->x-i, src->y-i, src->x+i, src->y+i, BL_SKILL, LG_EARTHDRIVE, &dummy, src);
+ }
+ map_foreachinrange(skill_area_sub, bl,i,BL_CHAR,
+ src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id);
break;
case RK_STONEHARDSKIN:
if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 4 )
@@ -7203,6 +7327,153 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
clif_skill_nodamage(src, bl, skillid, skilllv, 1);
}
break;
+ /**
+ * Royal Guard
+ **/
+ case LG_TRAMPLE:
+ clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6);
+ map_foreachinrange(skill_destroy_trap,bl,skill_get_splash(skillid,skilllv),BL_SKILL,tick);
+ break;
+
+ case LG_REFLECTDAMAGE:
+ if( tsc && tsc->data[type] )
+ status_change_end(bl,type,-1);
+ else
+ sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv));
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ break;
+
+ case LG_SHIELDSPELL:
+ if( flag&1 ) {
+ int duration = /*(sd) ? sd->shieldmdef * 2000 :*/ 10000;
+ sc_start(bl,SC_SILENCE,100,skilllv,duration);
+ } else if( sd ) {
+ int opt = skilllv;
+ int rate = rand()%100;
+ int val, brate;
+ switch( skilllv ) {
+ case 1:
+ {
+ struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]];
+ if( !shield_data || shield_data->type != IT_ARMOR ) { // No shield?
+ clif_skill_fail(sd, skillid, 0, 0);
+ break;
+ }
+ brate = shield_data->def * 10;
+ if( rate < 50 )
+ opt = 1;
+ else if( rate < 75 )
+ opt = 2;
+ else
+ opt = 3;
+
+ switch( opt ) {
+ case 1:
+ sc_start(bl,SC_SHIELDSPELL_DEF,100,opt,-1);
+ clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6);
+ if( rate < brate )
+ map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id);
+ status_change_end(bl,SC_SHIELDSPELL_DEF,-1);
+ break;
+ case 2:
+ val = 10 * shield_data->def; // % Reflected damage.
+ sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 30000);
+ break;
+ case 3:
+ val = 20 * shield_data->def; // Attack increase.
+ sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 30000);
+ break;
+ }
+ }
+ break;
+
+ case 2:
+ brate = sd->shieldmdef * 20;
+ if( rate < 30 )
+ opt = 1;
+ else if( rate < 60 )
+ opt = 2;
+ else
+ opt = 3;
+ switch( opt ) {
+ case 1:
+ sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1);
+ clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6);
+ if( rate < brate )
+ map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|2,skill_castend_damage_id);
+ status_change_end(bl,SC_SHIELDSPELL_MDEF,-1);
+ break;
+ case 2:
+ sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1);
+ clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6);
+ if( rate < brate )
+ map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id);
+ break;
+ case 3:
+ if( sc_start(bl,SC_SHIELDSPELL_MDEF,brate,opt,sd->shieldmdef * 30000) )
+ clif_skill_nodamage(src,bl,PR_MAGNIFICAT,skilllv,
+ sc_start(bl,SC_MAGNIFICAT,100,1,sd->shieldmdef * 30000));
+ break;
+ }
+ break;
+
+ case 3:
+ {
+ struct item *it = &sd->status.inventory[sd->equip_index[EQI_HAND_L]];
+ if( !it ) { // No shield?
+ clif_skill_fail(sd,skillid,0,0);
+ break;
+ }
+ brate = it->refine * 5;
+ if( rate < 25 )
+ opt = 1;
+ else if( rate < 50 )
+ opt = 2;
+ else
+ opt = 3;
+ switch( opt ) {
+ case 1:
+ val = 105 * it->refine / 10;
+ sc_start2(bl,SC_SHIELDSPELL_REF,brate,opt,val,skill_get_time(skillid,skilllv));
+ break;
+ case 2: case 3:
+ if( rate < brate )
+ {
+ val = sstatus->max_hp * (11 + it->refine) / 100;
+ status_heal(bl, val, 0, 3);
+ }
+ break;
+ /*case 3:
+ // Full protection. I need confirm what effect should be here. Moved to case 2 to until we got it.
+ break;*/
+ }
+ }
+ break;
+ }
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ }
+ break;
+
+ case LG_PIETY:
+ if( flag&1 )
+ sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv));
+ else {
+ skill_area_temp[2] = 0;
+ map_foreachinrange(skill_area_sub,bl,skill_get_splash(skillid,skilllv),BL_PC,src,skillid,skilllv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill_castend_nodamage_id);
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ }
+ break;
+
+ case LG_INSPIRATION:
+ if( sd && !map[sd->bl.m].flag.noexppenalty && sd->status.base_level != MAX_LEVEL ) {
+ sd->status.base_exp -= min(sd->status.base_exp, pc_nextbaseexp(sd) * 1 / 1000); //.1% penalty.
+ sd->status.job_exp -= min(sd->status.job_exp, pc_nextjobexp(sd) * 1 / 1000);
+ clif_updatestatus(sd,SP_BASEEXP);
+ clif_updatestatus(sd,SP_JOBEXP);
+ }
+ clif_skill_nodamage(bl,src,skillid,skilllv,
+ sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)));
+ break;
case RETURN_TO_ELDICASTES:
case ALL_GUARDIAN_RECALL:
@@ -7305,7 +7576,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
return 0;
}
- if( sd && ud->skilltimer != INVALID_TIMER && pc_checkskill(sd,SA_FREECAST) > 0 )
+ if( sd && ud->skilltimer != INVALID_TIMER && (pc_checkskill(sd,SA_FREECAST) > 0 || ud->skillid == LG_EXEEDBREAK) )
{// restore original walk speed
ud->skilltimer = INVALID_TIMER;
status_calc_bl(&sd->bl, SCB_SPEED);
@@ -7587,7 +7858,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
return 0;
}
- if( sd && ud->skilltimer != INVALID_TIMER && pc_checkskill(sd,SA_FREECAST) > 0 )
+ if( sd && ud->skilltimer != INVALID_TIMER && ( pc_checkskill(sd,SA_FREECAST) > 0 || ud->skillid == LG_EXEEDBREAK ) )
{// restore original walk speed
ud->skilltimer = INVALID_TIMER;
status_calc_bl(&sd->bl, SCB_SPEED);
@@ -7738,6 +8009,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
case MO_BODYRELOCATION:
case CR_CULTIVATION:
case HW_GANBANTEIN:
+ case LG_EARTHDRIVE:
break; //Effect is displayed on respective switch case.
default:
if(skill_get_inf(skillid)&INF_SELF_SKILL)
@@ -8233,7 +8505,39 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
case NC_MAGICDECOY:
if( sd ) clif_magicdecoy_list(sd,skilllv,x,y);
break;
+ /**
+ * Royal Guard
+ **/
+ case LG_OVERBRAND:
+ {
+ int width;//according to data from irowiki it actually is a square
+ for( width = 0; width < 7; width++ )
+ for( i = 0; i < 7; i++ )
+ map_foreachincell(skill_area_sub, src->m, x-2+i, y-2+width, BL_CHAR, src, LG_OVERBRAND_BRANDISH, skilllv, tick, flag|BCT_ENEMY,skill_castend_damage_id);
+ for( width = 0; width < 7; width++ )
+ for( i = 0; i < 7; i++ )
+ map_foreachincell(skill_area_sub, src->m, x-2+i, y-2+width, BL_CHAR, src, skillid, skilllv, tick, flag|BCT_ENEMY,skill_castend_damage_id);
+ }
+ break;
+ case LG_BANDING:
+ if( sc && sc->data[SC_BANDING] )
+ status_change_end(src,SC_BANDING,-1);
+ else if( (sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0)) != NULL ) {
+ sc_start4(src,SC_BANDING,100,skilllv,0,0,sg->group_id,skill_get_time(skillid,skilllv));
+ if( sd ) pc_banding(sd,skilllv);
+ }
+ clif_skill_nodamage(src,src,skillid,skilllv,1);
+ break;
+
+ case LG_RAYOFGENESIS:
+ if( status_charge(src,status_get_max_hp(src)*3*skilllv / 100,0) ) {
+ i = skill_get_splash(skillid,skilllv);
+ map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,BL_CHAR,
+ src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id);
+ } else if( sd )
+ clif_skill_fail(sd,skillid,0xa,0);
+ break;
default:
ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skillid);
return 1;
@@ -8751,7 +9055,12 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
val2 = sc->data[SC_POISONINGWEAPON]->val2; // Type of Poison
limit = 4000 + 2000 * skilllv;
break;
-
+ /**
+ * Royal Guard
+ **/
+ case LG_BANDING:
+ limit = -1;
+ break;
}
nullpo_retr(NULL, group=skill_initunitgroup(src,layout->count,skillid,skilllv,skill_get_unit_id(skillid,flag&1)+subunt, limit, interval));
@@ -9849,18 +10158,20 @@ static int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
return 1;
}
case AB_ADORAMUS:
- { // Adoramus does not consume Blue Gemstone when there is at least 1 Priest class next to the caster
+ // Adoramus does not consume Blue Gemstone when there is at least 1 Priest class next to the caster
if( (tsd->class_&MAPID_UPPERMASK) == MAPID_PRIEST )
p_sd[(*c)++] = tsd->bl.id;
return 1;
- }
case WL_COMET:
- { // Comet does not consume Red Gemstones when there is at least 1 Warlock class next to the caster
- if( tsd->status.class_ == 4055 || tsd->status.class_ == 4061 )
+ // Comet does not consume Red Gemstones when there is at least 1 Warlock class next to the caster
+ if( ( sd->class_&MAPID_THIRDMASK ) == MAPID_WARLOCK )
+ p_sd[(*c)++] = tsd->bl.id;
+ return 1;
+ case LG_RAYOFGENESIS:
+ if( tsd->status.party_id == sd->status.party_id && (tsd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD &&
+ tsd->sc.data[SC_BANDING] )
p_sd[(*c)++] = tsd->bl.id;
return 1;
- }
-
default: //Warning: Assuming Ensemble Dance/Songs for code speed. [Skotlex]
{
int skilllv;
@@ -10440,6 +10751,43 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
return 0;
}
break;
+ /**
+ * Royal Guard
+ **/
+ case LG_BANDING:
+ if( sc && sc->data[SC_INSPIRATION] ) {
+ clif_skill_fail(sd,skill,0,0);
+ return 0;
+ }
+ break;
+ case LG_PRESTIGE:
+ if( sc && (sc->data[SC_BANDING] || sc->data[SC_INSPIRATION]) ) {
+ clif_skill_fail(sd,skill,0,0);
+ return 0;
+ }
+ break;
+ case LG_RAGEBURST:
+ if( sd->spiritball == 0 ) {
+ clif_skill_fail(sd,skill,0x04,0);
+ return 0;
+ }
+ sd->spiritball_old = require.spiritball = sd->spiritball;
+ break;
+ case LG_RAYOFGENESIS:
+ if( sc && sc->data[SC_INSPIRATION] )
+ return 1; // Don't check for partner.
+ if( !(sc && sc->data[SC_BANDING]) ) {
+ clif_skill_fail(sd,skill,0xa,0);
+ return 0;
+ } else if( skill_check_pc_partner(sd,skill,&lv,skill_get_range(skill,lv),0) < 1 )
+ return 0; // Just fails, no msg here.
+ break;
+ case LG_HESPERUSLIT:
+ if( !sc || !sc->data[SC_BANDING] ) {
+ clif_skill_fail(sd,skill,0,0);
+ return 0;
+ }
+ break;
}
switch(require.state) {
@@ -11863,8 +12211,8 @@ static int skill_cell_overlap(struct block_list *bl, va_list ap)
}
break;
case HW_GANBANTEIN:
- if( !(unit->group->state.song_dance&0x1) )
- {// Don't touch song/dance.
+ case LG_EARTHDRIVE:
+ if( !(unit->group->state.song_dance&0x1) ) {// Don't touch song/dance.
skill_delunit(unit);
return 1;
}
@@ -12380,6 +12728,15 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
}
}
break;
+ case LG_BANDING:
+ {
+ struct status_change *sc = NULL;
+ if( (sc = status_get_sc(src)) && sc->data[SC_BANDING] ) {
+ sc->data[SC_BANDING]->val4 = 0;
+ status_change_end(src,SC_BANDING,-1);
+ }
+ }
+ break;
}
if (src->type==BL_PC && group->state.ammo_consume)
@@ -13540,8 +13897,37 @@ int skill_spellbook (struct map_session_data *sd, int nameid) {
return 1;
}
+/**
+ * for Royal Guard's LG_TRAMPLE
+ **/
+static int skill_destroy_trap( struct block_list *bl, va_list ap ) {
+ struct skill_unit *su = (struct skill_unit *)bl;
+ struct skill_unit_group *sg;
+ unsigned int tick;
+
+ nullpo_ret(su);
+ tick = va_arg(ap, unsigned int);
-
+ if (su->alive && (sg = su->group) && skill_get_inf2(sg->skill_id)&INF2_TRAP) {
+ switch( sg->unit_id ) {
+ case UNT_LANDMINE:
+ case UNT_CLAYMORETRAP:
+ case UNT_BLASTMINE:
+ case UNT_SHOCKWAVE:
+ case UNT_SANDMAN:
+ case UNT_FLASHER:
+ case UNT_FREEZINGTRAP:
+ case UNT_CLUSTERBOMB:
+ case UNT_FIRINGTRAP:
+ case UNT_ICEBOUNDTRAP:
+ map_foreachinrange(skill_trap_splash,&su->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &su->bl,tick);
+ break;
+ }
+ // Traps aren't recovered.
+ skill_delunit(su);
+ }
+ return 0;
+}
/*==========================================
*
*------------------------------------------*/
diff --git a/src/map/status.c b/src/map/status.c
index d8c5bf495..2565d8856 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -523,6 +523,18 @@ void initChangeTables(void)
set_sc( NC_MAGNETICFIELD , SC_MAGNETICFIELD , SI_MAGNETICFIELD , SCB_NONE );
set_sc( NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SI_NEUTRALBARRIER , SCB_NONE );
set_sc( NC_STEALTHFIELD , SC_STEALTHFIELD , SI_STEALTHFIELD , SCB_NONE );
+ /**
+ * Royal Guard
+ **/
+ set_sc( LG_REFLECTDAMAGE , SC_REFLECTDAMAGE , SI_LG_REFLECTDAMAGE, SCB_NONE );
+ set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP|SCB_DEF );
+ set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE );
+ set_sc( LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF2 );
+ set_sc( LG_BANDING , SC_BANDING , SI_BANDING , SCB_DEF2|SCB_WATK );// Renewal: atk2 & def2
+ set_sc( LG_PIETY , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE );
+ set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SI_EARTHDRIVE , SCB_DEF|SCB_ASPD );
+ set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK);
+
///**
// * Shadow Chaser
// **/
@@ -543,17 +555,6 @@ void initChangeTables(void)
//add_sc( SC_CHAOSPANIC , SC_CHAOS );
//set_sc( SC_BLOODYLUST , SC__BLOODYLUST , SI_BLOODYLUST , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
///**
- // * Royal Guard
- // **/
- //set_sc( LG_REFLECTDAMAGE , SC_REFLECTDAMAGE , SI_LG_REFLECTDAMAGE, SCB_NONE );
- //set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP|SCB_DEF );
- //set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE );
- //set_sc( LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF2 );
- //set_sc( LG_BANDING , SC_BANDING , SI_BANDING , SCB_DEF2|SCB_WATK );// Renewal: atk2 & def2
- //set_sc( LG_PIETY , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE );
- //set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SI_EARTHDRIVE , SCB_DEF|SCB_ASPD );
- //set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK);
- ///**
// * Sura
// **/
//add_sc( SR_DRAGONCOMBO , SC_STUN );
@@ -2155,6 +2156,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
+ sizeof(sd->setitem_hash)
+ sizeof(sd->setitem_hash2)
+ sizeof(sd->itemhealrate2)
+ + sizeof(sd->shieldmdef)
// shorts
+ sizeof(sd->splash_range)
+ sizeof(sd->splash_add_range)
@@ -2265,7 +2267,11 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
else if(sd->inventory_data[index]->type == IT_ARMOR) {
refinedef += sd->status.inventory[index].refine*refinebonus[0][0];
if(sd->inventory_data[index]->script) {
+ if( i == EQI_HAND_L ) //Shield
+ sd->state.lr_flag = 3;
run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
+ if( i == EQI_HAND_L ) //Shield
+ sd->state.lr_flag = 0;
if (!calculating) //Abort, run_script retriggered this. [Skotlex]
return 1;
}
@@ -3632,6 +3638,8 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang
**/
if(sc->data[SC_GIANTGROWTH])
str += 30;
+ if(sc->data[SC_INSPIRATION])
+ str += sc->data[SC_INSPIRATION]->val3;
return (unsigned short)cap_value(str,0,USHRT_MAX);
}
@@ -3676,6 +3684,8 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang
**/
if(sc->data[SC_ADORAMUS])
agi -= sc->data[SC_ADORAMUS]->val2;
+ if(sc->data[SC_INSPIRATION])
+ agi += sc->data[SC_INSPIRATION]->val3;
return (unsigned short)cap_value(agi,0,USHRT_MAX);
}
@@ -3705,6 +3715,8 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang
vit -= sc->data[SC_MARIONETTE]->val3&0xFF;
if(sc->data[SC_MARIONETTE2])
vit += sc->data[SC_MARIONETTE2]->val3&0xFF;
+ if(sc->data[SC_INSPIRATION])
+ vit += sc->data[SC_INSPIRATION]->val3;
if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && vit < 50)
vit = 50;
@@ -3744,6 +3756,8 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang
int_ -= ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF;
if(sc->data[SC_MARIONETTE2])
int_ += ((sc->data[SC_MARIONETTE2]->val4)>>16)&0xFF;
+ if(sc->data[SC_INSPIRATION])
+ int_ += sc->data[SC_INSPIRATION]->val3;
if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && int_ < 50)
int_ = 50;
@@ -3786,6 +3800,8 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang
dex -= ((sc->data[SC_MARIONETTE]->val4)>>8)&0xFF;
if(sc->data[SC_MARIONETTE2])
dex += ((sc->data[SC_MARIONETTE2]->val4)>>8)&0xFF;
+ if(sc->data[SC_INSPIRATION])
+ dex += sc->data[SC_INSPIRATION]->val3;
if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && dex < 50)
dex = 50;
@@ -3815,6 +3831,8 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang
luk -= sc->data[SC_MARIONETTE]->val4&0xFF;
if(sc->data[SC_MARIONETTE2])
luk += sc->data[SC_MARIONETTE2]->val4&0xFF;
+ if(sc->data[SC_INSPIRATION])
+ luk += sc->data[SC_INSPIRATION]->val3;
if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && luk < 50)
luk = 50;
@@ -3904,6 +3922,13 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan
watk -= watk * sc->data[SC_STRIPWEAPON]->val2/100;
if(sc->data[SC_MERC_ATKUP])
watk += sc->data[SC_MERC_ATKUP]->val2;
+ if(sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 3)
+ watk += sc->data[SC_SHIELDSPELL_DEF]->val2;
+ if(sc->data[SC_INSPIRATION])
+ watk += sc->data[SC_INSPIRATION]->val2;
+ if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 )
+ watk += (10 + 10 * sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2);
+
#if RE_EDP
/**
* in RE EDP increases your weapon atk by watk x Skill Level - 1
@@ -3984,6 +4009,8 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change
hit += sc->data[SC_MERC_HITUP]->val2;
if(sc->data[SC_FEAR])
hit -= hit * 20 / 100;
+ if(sc->data[SC_INSPIRATION])
+ hit += 5 * sc->data[SC_INSPIRATION]->val1;
return (short)cap_value(hit,1,SHRT_MAX);
}
@@ -4602,6 +4629,10 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang
maxhp += maxhp * 5 * sc->data[SC_EPICLESIS]->val1 / 100;
if(sc->data[SC_VENOMBLEED])
maxhp -= maxhp * 15 / 100;
+ if(sc->data[SC_FORCEOFVANGUARD])
+ maxhp += maxhp * 3 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100;
+ if(sc->data[SC_INSPIRATION]) //Custom value.
+ maxhp += maxhp * 3 * sc->data[SC_INSPIRATION]->val1 / 100;
return cap_value(maxhp,1,UINT_MAX);
@@ -5380,6 +5411,54 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
return 0; //Emperium/BG Monsters can't be afflicted by status changes
}
+ if( sc->data[SC_REFRESH] ) {
+ if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed.
+ return 0; // Immune to status ailements
+ switch( type ) {
+ case SC_QUAGMIRE://Tester said it protects against this and decrease agi.
+ case SC_DECREASEAGI:
+ case SC_BURNING:
+ case SC_FREEZING:
+ //case SC_WHITEIMPRISON://Need confirm. Protected against this in the past. [Rytech]
+ case SC_MARSHOFABYSS:
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
+ case SC_OBLIVIONCURSE:
+ //case SC_LEECHESEND://Need confirm. If it protects against nearly every Guillotine poison, it should work on this too right? [Rytech]
+ case SC_CRYSTALIZE:
+ case SC_DEEPSLEEP:
+ case SC_MANDRAGORA:
+ return 0;
+ }
+ }
+ else if( sc->data[SC_INSPIRATION] ) {
+ if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX )
+ return 0; // Immune to status ailements
+ switch( type ) {
+ case SC_DEEPSLEEP:
+ case SC_SATURDAYNIGHTFEVER:
+ case SC_PYREXIA:
+ case SC_DEATHHURT:
+ case SC_MAGICMUSHROOM:
+ case SC_VENOMBLEED:
+ case SC_TOXIN:
+ case SC_OBLIVIONCURSE:
+ case SC_LEECHESEND:
+ case SC__ENERVATION:
+ case SC__GROOMY:
+ case SC__LAZINESS:
+ case SC__UNLUCKY:
+ case SC__WEAKNESS:
+ case SC__BODYPAINT:
+ case SC__IGNORANCE:
+ return 0;
+ }
+ }
+
sd = BL_CAST(BL_PC, bl);
//Adjust tick according to status resistances
@@ -5800,6 +5879,23 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_FOOD_LUK_CASH:
status_change_end(bl, SC_LUKFOOD, INVALID_TIMER);
break;
+ case SC_REFLECTSHIELD:
+ status_change_end(bl, SC_REFLECTDAMAGE, INVALID_TIMER);
+ break;
+ case SC_REFLECTDAMAGE:
+ status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER);
+ break;
+ case SC_SHIELDSPELL_DEF:
+ case SC_SHIELDSPELL_MDEF:
+ case SC_SHIELDSPELL_REF:
+ status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER);
+ if( type != SC_SHIELDSPELL_DEF )
+ status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER);
+ if( type != SC_SHIELDSPELL_MDEF )
+ status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER);
+ if( type != SC_SHIELDSPELL_REF )
+ status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER);
+ break;
}
//Check for overlapping fails
@@ -8019,6 +8115,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
clif_standing(bl,true);
}
break;
+ */
case SC_NEUTRALBARRIER_MASTER:
case SC_STEALTHFIELD_MASTER:
if( sce->val2 )
@@ -8039,6 +8136,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
}
break;
+ /*
case SC_CURSEDCIRCLE_ATKER:
if( sce->val3 )
map_foreachinrange(status_change_timer_sub, bl, skill_get_splash(SR_CURSEDCIRCLE, sce->val1),BL_CHAR, bl, sce, SC_CURSEDCIRCLE_TARGET, gettick());
@@ -8941,7 +9039,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
case SC_BANDING:
if( status_charge(bl, 0, 7 - sce->val1) )
{
- //if( sd ) pc_banding(sd, sce->val1);
+ if( sd ) pc_banding(sd, sce->val1);
sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
return 0;
}