diff options
author | shennetsind <shennetsind@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2012-01-07 03:04:24 +0000 |
---|---|---|
committer | shennetsind <shennetsind@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2012-01-07 03:04:24 +0000 |
commit | 73ad7989194c210cd90f6f3a696250df162b69eb (patch) | |
tree | cf3795a1afaff4226a5d5c75c76c4403105b1a4d /src | |
parent | 6d5d8185e0213433def88dece01f66f180bb1a92 (diff) | |
download | hercules-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.c | 168 | ||||
-rw-r--r-- | src/map/battle.h | 4 | ||||
-rw-r--r-- | src/map/clif.c | 2 | ||||
-rw-r--r-- | src/map/pc.c | 120 | ||||
-rw-r--r-- | src/map/pc.h | 8 | ||||
-rw-r--r-- | src/map/skill.c | 484 | ||||
-rw-r--r-- | src/map/status.c | 122 |
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; } |