Cannon Ball Skills (P.ATK and Res) (#8415)

- When using Cart Cannon or Arm Cannon, the arrow attack you get from cannon balls is no longer affected by P.ATK
- Cart Cannon and Arm Cannon are no longer reduced by Res
- More consistent naming (PATK -> P.ATK, SMATK -> S.MATK)
- Added a general rule that cannon ball attack is not added to equip attack
- Fixes #8380
This commit is contained in:
Playtester 2024-06-12 18:59:05 +02:00 committed by GitHub
parent 34eb4be25b
commit 84cdc9cae0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -3420,8 +3420,13 @@ static int battle_calc_equip_attack(struct block_list *src, int skill_id)
struct status_data *status = status_get_status_data(src);
map_session_data *sd = BL_CAST(BL_PC, src);
if (sd) // add arrow atk if using an applicable skill
eatk += (is_skill_using_arrow(src, skill_id) ? sd->bonus.arrow_atk : 0);
// Add arrow atk if using an applicable skill
if (sd != nullptr && is_skill_using_arrow(src, skill_id)) {
int16 ammo_idx = sd->equip_index[EQI_AMMO];
// Attack of cannon balls is not added to equip attack, it needs to be added by the skills that use them
if (ammo_idx >= 0 && sd->inventory_data[ammo_idx] != nullptr && sd->inventory_data[ammo_idx]->subtype != AMMO_CANNONBALL)
eatk += sd->bonus.arrow_atk;
}
return eatk + status->eatk;
}
@ -3903,6 +3908,16 @@ static void battle_calc_attack_masteries(struct Damage* wd, struct block_list *s
#endif
}
break;
#ifdef RENEWAL
case GN_CARTCANNON:
case NC_ARMSCANNON:
// Arrow attack of these skills is not influenced by P.ATK so we add it as mastery attack
if (sd != nullptr) {
struct status_data* tstatus = status_get_status_data(target);
ATK_ADD(wd->masteryAtk, wd->masteryAtk2, battle_attr_fix(src, target, sd->bonus.arrow_atk, sd->bonus.arrow_ele, tstatus->def_ele, tstatus->ele_lv));
}
break;
#endif
}
if (sc) { // Status change considered as masteries
@ -7442,7 +7457,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
if( is_attack_left_handed( src, skill_id ) ){
wd.damage2 = wd.statusAtk2 + wd.weaponAtk2 + wd.equipAtk2 + wd.percentAtk2;
}
// Apply PATK mod
// Apply P.ATK mod
// But for Dragonbreaths it only applies if Dragonic Aura is skilled
if( ( skill_id != RK_DRAGONBREATH && skill_id != RK_DRAGONBREATH_WATER ) || pc_checkskill( sd, DK_DRAGONIC_AURA ) > 0 ){
wd.damage = (int64)floor( (float)( wd.damage * ( 100 + sstatus->patk ) / 100 ) );
@ -7492,8 +7507,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
// Res reduces physical damage by a percentage and
// is calculated before DEF and other reductions.
// This should be the official formula. [Rytech]
if ((wd.damage + wd.damage2) && tstatus->res > 0 && skill_id != MO_EXTREMITYFIST) {
// TODO: It seems all skills that use the simple defense formula (damage substracted by DEF+DEF2) ignore Res
// TODO: We should add a flag for those skills or use the IgnoreDefense flag after confirming all
// TODO: Res formula probably should be: (2000+x)/(2000+5x), but with the reduction rounded down
if ((wd.damage + wd.damage2) && tstatus->res > 0 && skill_id != MO_EXTREMITYFIST && skill_id != GN_CARTCANNON && skill_id != NC_ARMSCANNON) {
short res = tstatus->res;
short ignore_res = 0;// Value used as a percentage.
@ -8733,7 +8750,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
skillratio += 25;
}
#ifdef RENEWAL
// SMATK needs to be applied before the skill ratio to prevent rounding issues
// S.MATK needs to be applied before the skill ratio to prevent rounding issues
if (sd && sstatus->smatk > 0)
ad.damage += ad.damage * sstatus->smatk / 100;
#endif
@ -8769,7 +8786,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
#ifdef RENEWAL
// MRes reduces magical damage by a percentage and
// is calculated before MDEF and other reductions.
// This should be the official formula. [Rytech]
// TODO: Check if there are skills that ignore Mres, similar to skills that ignore Res
// TODO: MRes formula probably should be: (2000+x)/(2000+5x), but with the reduction rounded down
if (ad.damage && tstatus->mres > 0) {
short mres = tstatus->mres;
short ignore_mres = 0;// Value used as percentage.