Renewal Physical damage cleanup (#6997)
Corrected bAtkRate item bonus behavior to be the same as official. Correction order of calculation of physical attack Enchant Deadly Poison now grants 25% poison pseudo elemental bonus. also Magnum break also grants 20% fire pseudo elemental damage. Advanced Katar Mastery bonus formula is corrected. Critical attacks now always use max attack value like Maximize Power-buffed attacks. Correction item-script of many items/combo from bAddClass,Class_All to bAtkRate according to official sources. Co-authored-by: Daegaladh <4557962+Daegaladh@users.noreply.github.com> Co-authored-by: Aleos <aleos89@users.noreply.github.com> Co-authored-by: Jittapan Pluemsumran <nightsheep@outlook.com>
This commit is contained in:
@@ -883,8 +883,10 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
|
||||
cardfix = cardfix * (100 + sd->right_weapon.addclass[tstatus->class_] + sd->left_weapon.addclass[tstatus->class_] +
|
||||
sd->right_weapon.addclass[CLASS_ALL] + sd->left_weapon.addclass[CLASS_ALL]) / 100;
|
||||
}
|
||||
#ifndef RENEWAL
|
||||
if( sd->status.weapon == W_KATAR && (skill = pc_checkskill(sd,ASC_KATAR)) > 0 ) // Adv. Katar Mastery functions similar to a +%ATK card on official [helvetica]
|
||||
cardfix = cardfix * (100 + (10 + 2 * skill)) / 100;
|
||||
#endif
|
||||
}
|
||||
|
||||
//! CHECKME: These right & left hand weapon ignores 'left_cardfix_to_right'?
|
||||
@@ -2232,7 +2234,7 @@ static int battle_calc_status_attack(struct status_data *status, short hand)
|
||||
* @param sd Player
|
||||
* @return Base weapon damage
|
||||
*/
|
||||
static int battle_calc_base_weapon_attack(struct block_list *src, struct status_data *tstatus, struct weapon_atk *wa, struct map_session_data *sd)
|
||||
static int battle_calc_base_weapon_attack(struct block_list *src, struct status_data *tstatus, struct weapon_atk *wa, struct map_session_data *sd, bool critical)
|
||||
{
|
||||
struct status_data *status = status_get_status_data(src);
|
||||
uint8 type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R;
|
||||
@@ -2270,7 +2272,7 @@ static int battle_calc_base_weapon_attack(struct block_list *src, struct status_
|
||||
atkmin = max(0, (int)(atkmin - variance + base_stat_bonus));
|
||||
atkmax = min(UINT16_MAX, (int)(atkmax + variance + base_stat_bonus));
|
||||
|
||||
if (sc && sc->data[SC_MAXIMIZEPOWER])
|
||||
if ((sc && sc->data[SC_MAXIMIZEPOWER]) || critical == true)
|
||||
damage = atkmax;
|
||||
else
|
||||
damage = rnd_value(atkmin, atkmax);
|
||||
@@ -3486,6 +3488,7 @@ static void battle_calc_damage_parts(struct Damage* wd, struct block_list *src,s
|
||||
struct status_data *sstatus = status_get_status_data(src);
|
||||
struct status_data *tstatus = status_get_status_data(target);
|
||||
struct map_session_data *sd = BL_CAST(BL_PC, src);
|
||||
bool critical = false;
|
||||
|
||||
int right_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_R, false);
|
||||
int left_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_L, false);
|
||||
@@ -3501,10 +3504,25 @@ static void battle_calc_damage_parts(struct Damage* wd, struct block_list *src,s
|
||||
wd->statusAtk2 = battle_attr_fix(src, target, wd->statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
|
||||
}
|
||||
|
||||
wd->weaponAtk += battle_calc_base_weapon_attack(src, tstatus, &sstatus->rhw, sd);
|
||||
wd->weaponAtk = battle_attr_fix(src, target, wd->weaponAtk, right_element, tstatus->def_ele, tstatus->ele_lv);
|
||||
// Check critical
|
||||
if (wd->type == DMG_MULTI_HIT_CRITICAL || wd->type == DMG_CRITICAL)
|
||||
critical = true;
|
||||
|
||||
wd->weaponAtk2 += battle_calc_base_weapon_attack(src, tstatus, &sstatus->lhw, sd);
|
||||
wd->weaponAtk += battle_calc_base_weapon_attack(src, tstatus, &sstatus->rhw, sd, critical);
|
||||
wd->weaponAtk2 += battle_calc_base_weapon_attack(src, tstatus, &sstatus->lhw, sd, critical);
|
||||
|
||||
// Weapon ATK gain bonus from SC_SUB_WEAPONPROPERTY here ( +x% pseudo element damage)
|
||||
if (sd && sd->sc.data[SC_SUB_WEAPONPROPERTY]) {
|
||||
int64 bonus_atk = (int64)floor((float)( wd->weaponAtk * sd->sc.data[SC_SUB_WEAPONPROPERTY]->val2 / 100));
|
||||
int64 bonus_atk2 = (int64)floor((float)( wd->weaponAtk2 * sd->sc.data[SC_SUB_WEAPONPROPERTY]->val2 / 100));
|
||||
bonus_atk = battle_attr_fix(src, target, bonus_atk, sd->sc.data[SC_SUB_WEAPONPROPERTY]->val1, tstatus->def_ele, tstatus->ele_lv);
|
||||
bonus_atk2 = battle_attr_fix(src, target, bonus_atk2, sd->sc.data[SC_SUB_WEAPONPROPERTY]->val1, tstatus->def_ele, tstatus->ele_lv);
|
||||
|
||||
wd->weaponAtk += bonus_atk;
|
||||
wd->weaponAtk2 += bonus_atk2;
|
||||
}
|
||||
|
||||
wd->weaponAtk = battle_attr_fix(src, target, wd->weaponAtk, right_element, tstatus->def_ele, tstatus->ele_lv);
|
||||
wd->weaponAtk2 = battle_attr_fix(src, target, wd->weaponAtk2, left_element, tstatus->def_ele, tstatus->ele_lv);
|
||||
|
||||
wd->equipAtk += battle_calc_equip_attack(src, skill_id);
|
||||
@@ -3513,6 +3531,12 @@ static void battle_calc_damage_parts(struct Damage* wd, struct block_list *src,s
|
||||
wd->equipAtk2 += battle_calc_equip_attack(src, skill_id);
|
||||
wd->equipAtk2 = battle_attr_fix(src, target, wd->equipAtk2, left_element, tstatus->def_ele, tstatus->ele_lv);
|
||||
|
||||
// AtkRate gives a static bonus from (W.ATK + E.ATK)
|
||||
if (sd && sd->bonus.atk_rate) {
|
||||
wd->percentAtk = (wd->weaponAtk + wd->equipAtk) * sd->bonus.atk_rate / 100;
|
||||
wd->percentAtk2 = (wd->weaponAtk2 + wd->equipAtk2) * sd->bonus.atk_rate / 100;
|
||||
}
|
||||
|
||||
//Mastery ATK is a special kind of ATK that has no elemental properties
|
||||
//Because masteries are not elemental, they are unaffected by Ghost armors or Raydric Card
|
||||
battle_calc_attack_masteries(wd, src, target, skill_id, skill_lv);
|
||||
@@ -3734,10 +3758,6 @@ static void battle_calc_skill_base_damage(struct Damage* wd, struct block_list *
|
||||
if(sd) {
|
||||
int skill;
|
||||
|
||||
if (sd->bonus.atk_rate) {
|
||||
ATK_ADDRATE(wd->damage, wd->damage2, sd->bonus.atk_rate);
|
||||
RE_ALLATK_ADDRATE(wd, sd->bonus.atk_rate);
|
||||
}
|
||||
#ifndef RENEWAL
|
||||
if(sd->bonus.crit_atk_rate && is_attack_critical(wd, src, target, skill_id, skill_lv, false)) { // add +crit damage bonuses here in pre-renewal mode [helvetica]
|
||||
ATK_ADDRATE(wd->damage, wd->damage2, sd->bonus.crit_atk_rate);
|
||||
@@ -5487,10 +5507,10 @@ static void battle_attack_sc_bonus(struct Damage* wd, struct block_list *src, st
|
||||
#ifdef RENEWAL
|
||||
default: // fall through to apply EDP bonuses
|
||||
// Renewal EDP formula [helvetica]
|
||||
// weapon atk * (1 + (edp level * .8))
|
||||
// equip atk * (1 + (edp level * .6))
|
||||
ATK_RATE(wd->weaponAtk, wd->weaponAtk2, 100 + (sc->data[SC_EDP]->val1 * 80));
|
||||
ATK_RATE(wd->equipAtk, wd->equipAtk2, 100 + (sc->data[SC_EDP]->val1 * 60));
|
||||
// weapon atk * (2.5 + (edp level * .3))
|
||||
// equip atk * (2.5 + (edp level * .3))
|
||||
ATK_RATE(wd->weaponAtk, wd->weaponAtk2, 250 + (sc->data[SC_EDP]->val1 * 30));
|
||||
ATK_RATE(wd->equipAtk, wd->equipAtk2, 250 + (sc->data[SC_EDP]->val1 * 30));
|
||||
break;
|
||||
#else
|
||||
default:
|
||||
@@ -5910,7 +5930,11 @@ static void battle_calc_attack_left_right_hands(struct Damage* wd, struct block_
|
||||
} else if(sd->status.weapon == W_KATAR && !skill_id) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2)
|
||||
skill = pc_checkskill(sd,TF_DOUBLE);
|
||||
wd->damage2 = (int64)wd->damage * (1 + (skill * 2))/100;
|
||||
#ifdef RENEWAL
|
||||
} else if(is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id) && sd->status.weapon != W_KATAR) { //Dual-wield
|
||||
#else
|
||||
} else if(is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id)) { //Dual-wield
|
||||
#endif
|
||||
if (wd->damage) {
|
||||
if( (sd->class_&MAPID_BASEMASK) == MAPID_THIEF ) {
|
||||
skill = pc_checkskill(sd,AS_RIGHT);
|
||||
@@ -6010,15 +6034,17 @@ static void battle_calc_attack_gvg_bg(struct Damage* wd, struct block_list *src,
|
||||
wd->damage2 = battle_calc_bg_damage(src,target,wd->damage2,skill_id,wd->flag);
|
||||
}
|
||||
else {
|
||||
int64 d1 = wd->damage + wd->damage2,d2 = wd->damage2;
|
||||
wd->damage = battle_calc_damage(src,target,wd,d1,skill_id,skill_lv);
|
||||
if( mapdata_flag_gvg2(mapdata) )
|
||||
wd->damage = battle_calc_gvg_damage(src,target,wd->damage,skill_id,wd->flag);
|
||||
else if( mapdata->flag[MF_BATTLEGROUND] )
|
||||
wd->damage = battle_calc_bg_damage(src,target,wd->damage,skill_id,wd->flag);
|
||||
wd->damage2 = (int64)d2*100/d1 * wd->damage/100;
|
||||
wd->damage = battle_calc_damage(src, target, wd, wd->damage, skill_id, skill_lv);
|
||||
wd->damage2 = battle_calc_damage(src, target, wd, wd->damage2, skill_id, skill_lv);
|
||||
if (mapdata_flag_gvg2(mapdata)) {
|
||||
wd->damage = battle_calc_gvg_damage(src, target, wd->damage, skill_id, wd->flag);
|
||||
wd->damage2 = battle_calc_gvg_damage(src, target, wd->damage2, skill_id, wd->flag);
|
||||
}
|
||||
else if (mapdata->flag[MF_BATTLEGROUND]) {
|
||||
wd->damage = battle_calc_bg_damage(src, target, wd->damage, skill_id, wd->flag);
|
||||
wd->damage2 = battle_calc_bg_damage(src, target, wd->damage2, skill_id, wd->flag);
|
||||
}
|
||||
if(wd->damage > 1 && wd->damage2 < 1) wd->damage2 = 1;
|
||||
wd->damage-=wd->damage2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6151,6 +6177,7 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
|
||||
wd.damage = wd.damage2 =
|
||||
#ifdef RENEWAL
|
||||
wd.statusAtk = wd.statusAtk2 = wd.equipAtk = wd.equipAtk2 = wd.weaponAtk = wd.weaponAtk2 = wd.masteryAtk = wd.masteryAtk2 =
|
||||
wd.percentAtk = wd.percentAtk2 =
|
||||
#endif
|
||||
0;
|
||||
|
||||
@@ -6406,14 +6433,16 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
|
||||
if(!is_attack_hitting(&wd, src, target, skill_id, skill_lv, true))
|
||||
wd.dmg_lv = ATK_FLEE;
|
||||
else if(!(infdef = is_infinite_defense(target, wd.flag))) { //no need for math against plants
|
||||
int64 ratio = 0;
|
||||
int i = 0;
|
||||
|
||||
battle_calc_skill_base_damage(&wd, src, target, skill_id, skill_lv); // base skill damage
|
||||
|
||||
int64 ratio = 0;
|
||||
|
||||
#ifndef RENEWAL
|
||||
ratio = battle_calc_attack_skill_ratio(&wd, src, target, skill_id, skill_lv); // skill level ratios
|
||||
|
||||
ATK_RATE(wd.damage, wd.damage2, ratio);
|
||||
RE_ALLATK_RATE(&wd, ratio);
|
||||
#endif
|
||||
|
||||
int64 bonus_damage = battle_calc_skill_constant_addition(&wd, src, target, skill_id, skill_lv); // other skill bonuses
|
||||
|
||||
@@ -6429,15 +6458,16 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
|
||||
ATK_ADD(wd.weaponAtk, wd.weaponAtk2, sstatus->matk_min);
|
||||
}
|
||||
#endif
|
||||
|
||||
int i = 0;
|
||||
|
||||
#ifndef RENEWAL
|
||||
// add any miscellaneous player ATK bonuses
|
||||
if( sd && skill_id && (i = pc_skillatk_bonus(sd, skill_id))) {
|
||||
if( sd && skill_id && (i = pc_skillatk_bonus(sd, skill_id)))
|
||||
ATK_ADDRATE(wd.damage, wd.damage2, i);
|
||||
RE_ALLATK_ADDRATE(&wd, i);
|
||||
}
|
||||
if (tsd && (i = pc_sub_skillatk_bonus(tsd, skill_id))) {
|
||||
if (tsd && (i = pc_sub_skillatk_bonus(tsd, skill_id)))
|
||||
ATK_ADDRATE(wd.damage, wd.damage2, -i);
|
||||
RE_ALLATK_ADDRATE(&wd, -i);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RENEWAL
|
||||
// In Renewal we only cardfix to the weapon and equip ATK
|
||||
@@ -6472,15 +6502,42 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
|
||||
battle_attack_sc_bonus(&wd, src, target, skill_id, skill_lv);
|
||||
|
||||
if (sd) { //monsters, homuns and pets have their damage computed directly
|
||||
wd.damage = (wd.statusAtk + wd.weaponAtk + wd.equipAtk) * (100 + sstatus->patk) / 100 + wd.masteryAtk + bonus_damage;
|
||||
wd.damage = (int64)floor((float)((wd.statusAtk + wd.weaponAtk + wd.equipAtk + wd.percentAtk) * (100 + sstatus->patk) / 100 + wd.masteryAtk + bonus_damage));
|
||||
if (is_attack_left_handed(src, skill_id))
|
||||
wd.damage2 = (wd.statusAtk2 + wd.weaponAtk2 + wd.equipAtk2) * (100 + sstatus->patk) / 100 + wd.masteryAtk2 + bonus_damage;
|
||||
wd.damage2 = (int64)floor((float)((wd.statusAtk2 + wd.weaponAtk2 + wd.equipAtk2 + wd.percentAtk2) * (100 + sstatus->patk) / 100 + wd.masteryAtk2 + bonus_damage));
|
||||
|
||||
// CritAtkRate modifier
|
||||
if (wd.type == DMG_CRITICAL || wd.type == DMG_MULTI_HIT_CRITICAL) {
|
||||
if (skill_id > 0) {
|
||||
wd.damage += (int64)floor((float)(wd.damage * sd->bonus.crit_atk_rate / 200));
|
||||
if (is_attack_left_handed(src, skill_id))
|
||||
wd.damage2 += (int64)floor((float)(wd.damage2 * sd->bonus.crit_atk_rate / 200));
|
||||
}
|
||||
else {
|
||||
wd.damage += (int64)floor((float)(wd.damage * sd->bonus.crit_atk_rate / 100));
|
||||
if (is_attack_left_handed(src, skill_id))
|
||||
wd.damage2 += (int64)floor((float)(wd.damage2 * sd->bonus.crit_atk_rate / 100));
|
||||
}
|
||||
}
|
||||
|
||||
if (wd.flag & BF_SHORT)
|
||||
ATK_ADDRATE(wd.damage, wd.damage2, sd->bonus.short_attack_atk_rate);
|
||||
if(wd.flag&BF_LONG && (skill_id != RA_WUGBITE && skill_id != RA_WUGSTRIKE)) //Long damage rate addition doesn't use weapon + equip attack
|
||||
ATK_ADDRATE(wd.damage, wd.damage2, sd->bonus.long_attack_atk_rate);
|
||||
}
|
||||
|
||||
ratio = battle_calc_attack_skill_ratio(&wd, src, target, skill_id, skill_lv); // skill level ratios
|
||||
|
||||
ATK_RATE(wd.damage, wd.damage2, ratio);
|
||||
|
||||
// Advance Katar Mastery
|
||||
if (sd) {
|
||||
uint16 katar_skill;
|
||||
|
||||
if (sd->status.weapon == W_KATAR && (katar_skill = pc_checkskill(sd, ASC_KATAR)) > 0) // Adv. Katar Mastery applied after calculate with skillratio.
|
||||
ATK_ADDRATE(wd.damage, wd.damage2, (10 + 2 * katar_skill));
|
||||
}
|
||||
|
||||
// Res reduces physical damage by a percentage and
|
||||
// is calculated before DEF and other reductions.
|
||||
// This should be the official formula. [Rytech]
|
||||
@@ -6510,6 +6567,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
|
||||
wd.damage = wd.damage * (5000 + res) / (5000 + 10 * res);
|
||||
wd.damage2 = wd.damage2 * (5000 + res) / (5000 + 10 * res);
|
||||
}
|
||||
|
||||
#else
|
||||
// final attack bonuses that aren't affected by cards
|
||||
battle_attack_sc_bonus(&wd, src, target, skill_id, skill_lv);
|
||||
@@ -6521,6 +6579,18 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
|
||||
|
||||
battle_calc_attack_post_defense(&wd, src, target, skill_id, skill_lv);
|
||||
}
|
||||
|
||||
#ifdef RENEWAL
|
||||
// add any miscellaneous player ATK bonuses
|
||||
if( sd && skill_id && (i = pc_skillatk_bonus(sd, skill_id))) {
|
||||
ATK_ADDRATE(wd.damage, wd.damage2, i);
|
||||
RE_ALLATK_ADDRATE(&wd, i);
|
||||
}
|
||||
if (tsd && (i = pc_sub_skillatk_bonus(tsd, skill_id))) {
|
||||
ATK_ADDRATE(wd.damage, wd.damage2, -i);
|
||||
RE_ALLATK_ADDRATE(&wd, -i);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
battle_calc_element_damage(&wd, src, target, skill_id, skill_lv);
|
||||
@@ -6531,22 +6601,14 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
|
||||
#ifdef RENEWAL
|
||||
if (is_attack_critical(&wd, src, target, skill_id, skill_lv, false)) {
|
||||
if (sd) { //Check for player so we don't crash out, monsters don't have bonus crit rates [helvetica]
|
||||
if (skill_id > 0)
|
||||
wd.damage = (int64)floor((float)((wd.damage * (140 + sstatus->crate)) / 100 * (100 + (sd->bonus.crit_atk_rate / 2))) / 100);
|
||||
else
|
||||
wd.damage = (int64)floor((float)((wd.damage * (140 + sstatus->crate)) / 100 * (100 + sd->bonus.crit_atk_rate)) / 100);
|
||||
if (is_attack_left_handed(src, skill_id)) {
|
||||
if (skill_id > 0)
|
||||
wd.damage2 = (int64)floor((float)((wd.damage2 * (140 + sstatus->crate)) / 100 * (100 + (sd->bonus.crit_atk_rate / 2))) / 100);
|
||||
else
|
||||
wd.damage2 = (int64)floor((float)((wd.damage2 * (140 + sstatus->crate)) / 100 * (100 + sd->bonus.crit_atk_rate)) / 100);
|
||||
}
|
||||
wd.damage = (int64)floor((float)((wd.damage * (1.4f + (0.01f * sstatus->crate)))));
|
||||
if (is_attack_left_handed(src, skill_id))
|
||||
wd.damage2 = (int64)floor((float)((wd.damage2 * (1.4f + (0.01f * sstatus->crate)))));
|
||||
} else
|
||||
wd.damage = (int64)floor((float)(wd.damage * 140) / 100);
|
||||
wd.damage = (int64)floor((float)(wd.damage * 1.4f));
|
||||
|
||||
if (tsd && tsd->bonus.crit_def_rate != 0) {
|
||||
if (tsd && tsd->bonus.crit_def_rate != 0)
|
||||
ATK_ADDRATE(wd.damage, wd.damage2, -tsd->bonus.crit_def_rate);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user