diff --git a/db/re/skill_db.yml b/db/re/skill_db.yml index 6d10ebcb63..92fadc9fb3 100644 --- a/db/re/skill_db.yml +++ b/db/re/skill_db.yml @@ -17164,11 +17164,12 @@ Body: Name: NPC_MAXPAIN_ATK Description: Max Pain Attack MaxLevel: 10 - Type: Misc + Type: Weapon TargetType: Attack DamageFlags: Splash: true IgnoreElement: true + IgnoreDefense: true IgnoreFlee: true IgnoreDefCard: true Flags: diff --git a/src/map/battle.cpp b/src/map/battle.cpp index b2b6dd9e3b..5e943cbf1f 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -1450,9 +1450,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) return 1; - if (sc && sc->data[SC_MAXPAIN]) - return 0; - switch (skill_id) { #ifndef RENEWAL case PA_PRESSURE: @@ -2483,6 +2480,7 @@ static int battle_range_type(struct block_list *src, struct block_list *target, case MT_RUSH_QUAKE: // 9 cell cast range. case ABC_UNLUCKY_RUSH: // 7 cell cast range. //case ABC_DEFT_STAB: // 2 cell cast range??? + case NPC_MAXPAIN_ATK: return BF_SHORT; case CD_PETITIO: { // Skill range is 2 but damage is melee with books and ranged with mace. map_session_data *sd = BL_CAST(BL_PC, src); @@ -6359,6 +6357,12 @@ void battle_do_reflect(int attack_type, struct Damage *wd, struct block_list* sr if (!tsc) return; + if (tsc->data[SC_MAXPAIN]) { + tsc->data[SC_MAXPAIN]->val2 = (int)damage; + if (!tsc->data[SC_KYOMU] && !(tsc->data[SC_DARKCROW] && (wd->flag&BF_SHORT))) //SC_KYOMU invalidates reflecting ability. SC_DARKCROW also does, but only for short weapon attack. + skill_castend_damage_id(target, src, NPC_MAXPAIN_ATK, tsc->data[SC_MAXPAIN]->val1, tick, ((wd->flag & 1) ? wd->flag - 1 : wd->flag)); + } + // Calculate skill reflect damage separately if ((ud && !ud->immune_attack) || !status_bl_has_mode(target, MD_SKILLIMMUNE)) rdamage = battle_calc_return_damage(target, src, &damage, wd->flag, skill_id,true); @@ -6368,12 +6372,7 @@ void battle_do_reflect(int attack_type, struct Damage *wd, struct block_list* sr if (sc && sc->data[SC_VITALITYACTIVATION]) rdamage /= 2; - if (tsc->data[SC_MAXPAIN]) { - tsc->data[SC_MAXPAIN]->val2 = (int)rdamage; - skill_castend_damage_id(target, src, NPC_MAXPAIN_ATK, tsc->data[SC_MAXPAIN]->val1, tick, wd->flag); - tsc->data[SC_MAXPAIN]->val2 = 0; - } - else if( attack_type == BF_WEAPON && tsc->data[SC_REFLECTDAMAGE] ) // Don't reflect your own damage (Grand Cross) + if( attack_type == BF_WEAPON && tsc->data[SC_REFLECTDAMAGE] ) // 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,sstatus->dmotion,rdamage,wd->flag); else if( attack_type == BF_WEAPON || attack_type == BF_MISC) { rdelay = clif_damage(src, (!d_bl) ? src : d_bl, tick, wd->amotion, sstatus->dmotion, rdamage, 1, DMG_ENDURE, 0, false); @@ -6675,6 +6674,16 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl case MH_EQC: ATK_ADD(wd.damage, wd.damage2, 6000 * skill_lv + status_get_lv(src)); // !TODO: Confirm base level bonus break; + case NPC_MAXPAIN_ATK: + if (sc && sc->data[SC_MAXPAIN]) { + if (sc->data[SC_MAXPAIN]->val2) + wd.damage = sc->data[SC_MAXPAIN]->val2 * skill_lv / 10; + else if (sc->data[SC_MAXPAIN]->val3) + wd.damage = sc->data[SC_MAXPAIN]->val3 * skill_lv / 10; + } + else + wd.damage = 0; + break; } if(sd) { @@ -8149,12 +8158,6 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * if (status_bl_has_mode(target, MD_STATUSIMMUNE)) md.damage /= 10; break; - case NPC_MAXPAIN_ATK: - if (ssc && ssc->data[SC_MAXPAIN]) - md.damage = ssc->data[SC_MAXPAIN]->val2; - else - md.damage = 0; - break; case NPC_WIDESUCK: md.damage = tstatus->max_hp * 15 / 100; break; @@ -8425,7 +8428,7 @@ int64 battle_calc_return_damage(struct block_list* tbl, struct block_list *src, return 0; } } - if ( tsc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ) { + if ( tsc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION && skill_id != NPC_MAXPAIN_ATK ) { // Don't reflect non-skill attack if has SC_REFLECTSHIELD from Devotion bonus inheritance if (!skill_id && battle_config.devotion_rdamage_skill_only && tsc->data[SC_REFLECTSHIELD]->val4) rdamage = 0; @@ -8473,11 +8476,6 @@ int64 battle_calc_return_damage(struct block_list* tbl, struct block_list *src, } } - if (tsc) { - if (tsc->data[SC_MAXPAIN]) - rdamage = damage * tsc->data[SC_MAXPAIN]->val1 * 10 / 100; - } - // Config damage adjustment map_data *mapdata = map_getmapdata(src->m); diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 8518ec00ad..ff6bf22f0d 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -3674,6 +3674,13 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list * damage = dmg.damage + dmg.damage2; + if ((dmg.flag & BF_MAGIC) && tsc && tsc->data[SC_MAXPAIN]) { + tsc->data[SC_MAXPAIN]->val3 = (int)damage; + tsc->data[SC_MAXPAIN]->val2 = 0; + if (!tsc->data[SC_KYOMU]) //SC_KYOMU invalidates reflecting ability. + skill_castend_damage_id(bl, src, NPC_MAXPAIN_ATK, tsc->data[SC_MAXPAIN]->val1, tick, flag); + } + if( (skill_id == AL_INCAGI || skill_id == AL_BLESSING || skill_id == CASH_BLESSING || skill_id == CASH_INCAGI || skill_id == MER_INCAGI || skill_id == MER_BLESSING) && tsc && tsc->data[SC_CHANGEUNDEAD] ) @@ -7617,6 +7624,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui } sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)); break; + case CR_REFLECTSHIELD: + case MS_REFLECTSHIELD: + if (tsc && tsc->data[SC_DARKCROW]) { // SC_DARKCROW prevents using reflecting skills + if (sd) + clif_skill_fail(sd, skill_id, USESKILL_FAIL, 0); + break; + } case PR_SLOWPOISON: case PR_LEXAETERNA: #ifndef RENEWAL @@ -7629,8 +7643,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case KN_ONEHAND: case MER_QUICKEN: case CR_SPEARQUICKEN: - case CR_REFLECTSHIELD: - case MS_REFLECTSHIELD: case AS_POISONREACT: #ifndef RENEWAL case MC_LOUD: