|
@@ -41,6 +41,7 @@ static struct eri *delay_damage_ers; //For battle delay damage structures.
|
|
int battle_get_weapon_element(struct Damage *wd, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, short weapon_position, bool calc_for_damage_only);
|
|
int battle_get_weapon_element(struct Damage *wd, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, short weapon_position, bool calc_for_damage_only);
|
|
int battle_get_magic_element(struct block_list* src, struct block_list* target, uint16 skill_id, uint16 skill_lv, int mflag);
|
|
int battle_get_magic_element(struct block_list* src, struct block_list* target, uint16 skill_id, uint16 skill_lv, int mflag);
|
|
int battle_get_misc_element(struct block_list* src, struct block_list* target, uint16 skill_id, uint16 skill_lv, int mflag);
|
|
int battle_get_misc_element(struct block_list* src, struct block_list* target, uint16 skill_id, uint16 skill_lv, int mflag);
|
|
|
|
+static void battle_calc_defense_reduction(struct Damage* wd, struct block_list* src, struct block_list* target, uint16 skill_id, uint16 skill_lv);
|
|
|
|
|
|
/**
|
|
/**
|
|
* Returns the current/list skill used by the bl
|
|
* Returns the current/list skill used by the bl
|
|
@@ -3365,7 +3366,9 @@ static bool battle_skill_stacks_masteries_vvs(uint16 skill_id)
|
|
if (
|
|
if (
|
|
#ifndef RENEWAL
|
|
#ifndef RENEWAL
|
|
skill_id == PA_SHIELDCHAIN || skill_id == CR_SHIELDBOOMERANG ||
|
|
skill_id == PA_SHIELDCHAIN || skill_id == CR_SHIELDBOOMERANG ||
|
|
|
|
+ skill_id == PA_SACRIFICE || skill_id == AM_ACIDTERROR ||
|
|
#endif
|
|
#endif
|
|
|
|
+ skill_id == MO_INVESTIGATE || skill_id == MO_EXTREMITYFIST ||
|
|
skill_id == RK_DRAGONBREATH || skill_id == RK_DRAGONBREATH_WATER || skill_id == NC_SELFDESTRUCTION ||
|
|
skill_id == RK_DRAGONBREATH || skill_id == RK_DRAGONBREATH_WATER || skill_id == NC_SELFDESTRUCTION ||
|
|
skill_id == LG_SHIELDPRESS || skill_id == LG_EARTHDRIVE)
|
|
skill_id == LG_SHIELDPRESS || skill_id == LG_EARTHDRIVE)
|
|
return false;
|
|
return false;
|
|
@@ -3657,11 +3660,13 @@ static void battle_calc_element_damage(struct Damage* wd, struct block_list *src
|
|
|
|
|
|
#ifndef RENEWAL
|
|
#ifndef RENEWAL
|
|
if (sd && (wd->damage > 0 || wd->damage2 > 0)) { // Applies only to player damage, monsters and mercenaries don't get this damage boost
|
|
if (sd && (wd->damage > 0 || wd->damage2 > 0)) { // Applies only to player damage, monsters and mercenaries don't get this damage boost
|
|
- if (sc && sc->getSCE(SC_WATK_ELEMENT)) { // Descriptions indicate this means adding a percent of a normal attack in another element [Skotlex]
|
|
|
|
|
|
+ // This adds a percentual damage bonus based on the damage you would deal with a normal attack
|
|
|
|
+ // Does not apply to unit skills or skills that have their own base damage formula such as AM_ACIDTERROR
|
|
|
|
+ if (sc && sc->getSCE(SC_WATK_ELEMENT) && !skill_get_unit_id(skill_id) && skill_id != AM_ACIDTERROR) {
|
|
int64 damage = wd->basedamage * sc->getSCE(SC_WATK_ELEMENT)->val2;
|
|
int64 damage = wd->basedamage * sc->getSCE(SC_WATK_ELEMENT)->val2;
|
|
damage = battle_attr_fix(src, target, damage, sc->getSCE(SC_WATK_ELEMENT)->val1, tstatus->def_ele, tstatus->ele_lv, 1);
|
|
damage = battle_attr_fix(src, target, damage, sc->getSCE(SC_WATK_ELEMENT)->val1, tstatus->def_ele, tstatus->ele_lv, 1);
|
|
//Spirit Sphere bonus damage is not affected by element
|
|
//Spirit Sphere bonus damage is not affected by element
|
|
- if (skill_id == MO_FINGEROFFENSIVE) { //Need to calculate number of Spirit Balls you had before cast
|
|
|
|
|
|
+ if (skill_id == MO_FINGEROFFENSIVE || skill_id == MO_INVESTIGATE) { //Need to calculate number of Spirit Balls you had before cast
|
|
damage += ((wd->div_ + sd->spiritball) * 3 * sc->getSCE(SC_WATK_ELEMENT)->val2);
|
|
damage += ((wd->div_ + sd->spiritball) * 3 * sc->getSCE(SC_WATK_ELEMENT)->val2);
|
|
}
|
|
}
|
|
else
|
|
else
|
|
@@ -3720,21 +3725,24 @@ static void battle_calc_attack_masteries(struct Damage* wd, struct block_list *s
|
|
struct status_data *sstatus = status_get_status_data(src);
|
|
struct status_data *sstatus = status_get_status_data(src);
|
|
int t_class = status_get_class(target);
|
|
int t_class = status_get_class(target);
|
|
|
|
|
|
- if (sd && battle_skill_stacks_masteries_vvs(skill_id) &&
|
|
|
|
- skill_id != MO_INVESTIGATE &&
|
|
|
|
- skill_id != MO_EXTREMITYFIST &&
|
|
|
|
- skill_id != CR_GRANDCROSS)
|
|
|
|
|
|
+ if (sd) {
|
|
|
|
+ wd->basedamage = battle_addmastery(sd, target, wd->basedamage, 0);
|
|
|
|
+ if (is_attack_left_handed(src, skill_id)) {
|
|
|
|
+ wd->basedamage2 = battle_addmastery(sd, target, wd->basedamage2, 1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Grand Cross is confirmed to be affected by refine bonus but not masteries
|
|
|
|
+ if (sd && battle_skill_stacks_masteries_vvs(skill_id) && skill_id != CR_GRANDCROSS)
|
|
{ //Add mastery damage
|
|
{ //Add mastery damage
|
|
uint16 skill;
|
|
uint16 skill;
|
|
|
|
|
|
wd->damage = battle_addmastery(sd,target,wd->damage,0);
|
|
wd->damage = battle_addmastery(sd,target,wd->damage,0);
|
|
- wd->basedamage = battle_addmastery(sd, target, wd->basedamage, 0);
|
|
|
|
#ifdef RENEWAL
|
|
#ifdef RENEWAL
|
|
wd->masteryAtk = battle_addmastery(sd,target,wd->weaponAtk,0);
|
|
wd->masteryAtk = battle_addmastery(sd,target,wd->weaponAtk,0);
|
|
#endif
|
|
#endif
|
|
if (is_attack_left_handed(src, skill_id)) {
|
|
if (is_attack_left_handed(src, skill_id)) {
|
|
wd->damage2 = battle_addmastery(sd,target,wd->damage2,1);
|
|
wd->damage2 = battle_addmastery(sd,target,wd->damage2,1);
|
|
- wd->basedamage2 = battle_addmastery(sd, target, wd->basedamage2, 1);
|
|
|
|
#ifdef RENEWAL
|
|
#ifdef RENEWAL
|
|
wd->masteryAtk2 = battle_addmastery(sd,target,wd->weaponAtk2,1);
|
|
wd->masteryAtk2 = battle_addmastery(sd,target,wd->weaponAtk2,1);
|
|
#endif
|
|
#endif
|
|
@@ -3972,12 +3980,19 @@ static void battle_calc_skill_base_damage(struct Damage* wd, struct block_list *
|
|
if (sd) {
|
|
if (sd) {
|
|
short index = sd->equip_index[EQI_HAND_L];
|
|
short index = sd->equip_index[EQI_HAND_L];
|
|
|
|
|
|
|
|
+ //Base damage of shield skills is [batk + 4*refine + weight]
|
|
if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR) {
|
|
if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR) {
|
|
|
|
+ ATK_ADD(wd->damage, wd->damage2, 4 * sd->inventory.u.items_inventory[index].refine);
|
|
ATK_ADD(wd->damage, wd->damage2, sd->inventory_data[index]->weight / 10);
|
|
ATK_ADD(wd->damage, wd->damage2, sd->inventory_data[index]->weight / 10);
|
|
#ifdef RENEWAL
|
|
#ifdef RENEWAL
|
|
|
|
+ ATK_ADD(wd->weaponAtk, wd->weaponAtk2, 4 * sd->inventory.u.items_inventory[index].refine);
|
|
ATK_ADD(wd->weaponAtk, wd->weaponAtk2, sd->inventory_data[index]->weight / 10);
|
|
ATK_ADD(wd->weaponAtk, wd->weaponAtk2, sd->inventory_data[index]->weight / 10);
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
+#ifndef RENEWAL
|
|
|
|
+ // Shield Boomerang and Rapid Smiting calculate DEF before the skill ratio
|
|
|
|
+ battle_calc_defense_reduction(wd, src, target, skill_id, skill_lv);
|
|
|
|
+#endif
|
|
} else
|
|
} else
|
|
ATK_ADD(wd->damage, wd->damage2, sstatus->rhw.atk2); //Else use Atk2
|
|
ATK_ADD(wd->damage, wd->damage2, sstatus->rhw.atk2); //Else use Atk2
|
|
break;
|
|
break;
|
|
@@ -4119,6 +4134,9 @@ static void battle_calc_skill_base_damage(struct Damage* wd, struct block_list *
|
|
if (tsd != nullptr && tsd->bonus.crit_def_rate != 0 && !skill_id && (bflag & BDMG_CRIT)) {
|
|
if (tsd != nullptr && tsd->bonus.crit_def_rate != 0 && !skill_id && (bflag & BDMG_CRIT)) {
|
|
ATK_ADDRATE(wd->damage, wd->damage2, -tsd->bonus.crit_def_rate);
|
|
ATK_ADDRATE(wd->damage, wd->damage2, -tsd->bonus.crit_def_rate);
|
|
}
|
|
}
|
|
|
|
+ //Acid Terror ignores DEF but will substract VIT from base attack value instead
|
|
|
|
+ if (skill_id == AM_ACIDTERROR)
|
|
|
|
+ ATK_ADD(wd->damage, wd->damage2, -tstatus->def2);
|
|
#endif
|
|
#endif
|
|
break;
|
|
break;
|
|
} //End switch(skill_id)
|
|
} //End switch(skill_id)
|
|
@@ -4287,6 +4305,74 @@ static void battle_calc_multi_attack(struct Damage* wd, struct block_list *src,s
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Calculates the percentual attack modificator (ATKpercent) based on status changes
|
|
|
|
+ * These bonuses are added together and the percent is applied to the damage before the defense reduction in pre-renewal
|
|
|
|
+ * In renewal this simply sets the base skillratio before the actual skill ratio of the skill used is added
|
|
|
|
+ * This bonus works as a separate unit to the rest (e.g., if one of these is not applied to a skill, then we know none are)
|
|
|
|
+ * Do not add additional status changes here unless they are confirmed to use ATKpercent
|
|
|
|
+ * @param bl: Object to calc atkpercent for
|
|
|
|
+ * @param skill_id: Skill used by object
|
|
|
|
+ * @param sc: Object's status change information
|
|
|
|
+ * @return atkpercent with cap_value(watk,0,USHRT_MAX)
|
|
|
|
+ */
|
|
|
|
+static unsigned short battle_get_atkpercent(struct block_list* bl, uint16 skill_id, status_change* sc)
|
|
|
|
+{
|
|
|
|
+ //These skills are not affected by ATKpercent
|
|
|
|
+ switch (skill_id) {
|
|
|
|
+#ifndef RENEWAL
|
|
|
|
+ // Need to be confirmed for renewal as masteries have been coded to apply to those two in renewal
|
|
|
|
+ case PA_SHIELDCHAIN:
|
|
|
|
+ case CR_SHIELDBOOMERANG:
|
|
|
|
+#endif
|
|
|
|
+ case AM_ACIDTERROR:
|
|
|
|
+ case CR_GRANDCROSS:
|
|
|
|
+ case NPC_GRANDDARKNESS:
|
|
|
|
+ case MO_INVESTIGATE:
|
|
|
|
+ case MO_EXTREMITYFIST:
|
|
|
|
+ case PA_SACRIFICE:
|
|
|
|
+ case NPC_DRAGONBREATH:
|
|
|
|
+ case RK_DRAGONBREATH:
|
|
|
|
+ case RK_DRAGONBREATH_WATER:
|
|
|
|
+ return 100;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ int atkpercent = 100;
|
|
|
|
+
|
|
|
|
+ if (sc->getSCE(SC_CURSE))
|
|
|
|
+ atkpercent -= 25;
|
|
|
|
+ if (sc->getSCE(SC_PROVOKE))
|
|
|
|
+ atkpercent += sc->getSCE(SC_PROVOKE)->val2;
|
|
|
|
+ if (sc->getSCE(SC_STRIPWEAPON) && bl->type != BL_PC)
|
|
|
|
+ atkpercent -= sc->getSCE(SC_STRIPWEAPON)->val2;
|
|
|
|
+ if (sc->getSCE(SC_CONCENTRATION))
|
|
|
|
+ atkpercent += sc->getSCE(SC_CONCENTRATION)->val2;
|
|
|
|
+ if (sc->getSCE(SC_TRUESIGHT))
|
|
|
|
+ atkpercent += 2 * sc->getSCE(SC_TRUESIGHT)->val1;
|
|
|
|
+ if (sc->getSCE(SC_JOINTBEAT) && sc->getSCE(SC_JOINTBEAT)->val2 & BREAK_WAIST)
|
|
|
|
+ atkpercent -= 25;
|
|
|
|
+ if (sc->getSCE(SC_INCATKRATE))
|
|
|
|
+ atkpercent += sc->getSCE(SC_INCATKRATE)->val1;
|
|
|
|
+ if (sc->getSCE(SC_SKE))
|
|
|
|
+ atkpercent += 300;
|
|
|
|
+ if (sc->getSCE(SC_BLOODLUST))
|
|
|
|
+ atkpercent += sc->getSCE(SC_BLOODLUST)->val2;
|
|
|
|
+ if (sc->getSCE(SC_FLEET))
|
|
|
|
+ atkpercent += sc->getSCE(SC_FLEET)->val3;
|
|
|
|
+
|
|
|
|
+ /* Only few selected skills should use this function, DO NOT ADD any that are not caused by the skills listed below
|
|
|
|
+ * TODO:
|
|
|
|
+ * NPC_INVINCIBLE (+100)
|
|
|
|
+ * GD_GUARDUP (2*skLevel+8)
|
|
|
|
+ * EL_WATERBARRIER (-3)
|
|
|
|
+ * SC_ENERVATION (-30/-40/-50)
|
|
|
|
+ * MH_EQC (skLevel*5)
|
|
|
|
+ * MH_VOLCANIC_ASH (-50)
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ return (unsigned short)cap_value(atkpercent, 0, USHRT_MAX);
|
|
|
|
+}
|
|
|
|
+
|
|
/*======================================================
|
|
/*======================================================
|
|
* Calculate skill level ratios for weapon-based skills
|
|
* Calculate skill level ratios for weapon-based skills
|
|
*------------------------------------------------------
|
|
*------------------------------------------------------
|
|
@@ -4308,6 +4394,10 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
|
|
|
|
|
|
//Skill damage modifiers that stack linearly
|
|
//Skill damage modifiers that stack linearly
|
|
if(sc && skill_id != PA_SACRIFICE) {
|
|
if(sc && skill_id != PA_SACRIFICE) {
|
|
|
|
+#ifdef RENEWAL
|
|
|
|
+ //ATK percent modifier (in renewal, it's applied before the skillratio)
|
|
|
|
+ skillratio = battle_get_atkpercent(src, skill_id, sc);
|
|
|
|
+#endif
|
|
if(sc->getSCE(SC_OVERTHRUST))
|
|
if(sc->getSCE(SC_OVERTHRUST))
|
|
skillratio += sc->getSCE(SC_OVERTHRUST)->val3;
|
|
skillratio += sc->getSCE(SC_OVERTHRUST)->val3;
|
|
if(sc->getSCE(SC_MAXOVERTHRUST))
|
|
if(sc->getSCE(SC_MAXOVERTHRUST))
|
|
@@ -4317,10 +4407,6 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
|
|
skillratio += 100;
|
|
skillratio += 100;
|
|
#else
|
|
#else
|
|
skillratio += 200;
|
|
skillratio += 200;
|
|
- if (sc && sc->getSCE(SC_TRUESIGHT))
|
|
|
|
- skillratio += 2 * sc->getSCE(SC_TRUESIGHT)->val1;
|
|
|
|
- if (sc->getSCE(SC_CONCENTRATION) && (skill_id != RK_DRAGONBREATH && skill_id != RK_DRAGONBREATH_WATER && skill_id != NPC_DRAGONBREATH))
|
|
|
|
- skillratio += sc->getSCE(SC_CONCENTRATION)->val2;
|
|
|
|
#endif
|
|
#endif
|
|
if (!skill_id || skill_id == KN_AUTOCOUNTER) {
|
|
if (!skill_id || skill_id == KN_AUTOCOUNTER) {
|
|
if (sc->getSCE(SC_CRUSHSTRIKE)) {
|
|
if (sc->getSCE(SC_CRUSHSTRIKE)) {
|
|
@@ -4378,12 +4464,6 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
|
|
case MA_CHARGEARROW:
|
|
case MA_CHARGEARROW:
|
|
skillratio += 50;
|
|
skillratio += 50;
|
|
break;
|
|
break;
|
|
-#ifndef RENEWAL
|
|
|
|
- case HT_FREEZINGTRAP:
|
|
|
|
- case MA_FREEZINGTRAP:
|
|
|
|
- skillratio += -50 + 10 * skill_lv;
|
|
|
|
- break;
|
|
|
|
-#endif
|
|
|
|
case KN_PIERCE:
|
|
case KN_PIERCE:
|
|
skillratio += 10 * skill_lv;
|
|
skillratio += 10 * skill_lv;
|
|
if (sc && sc->getSCE(SC_CHARGINGPIERCE_COUNT) && sc->getSCE(SC_CHARGINGPIERCE_COUNT)->val1 >= 10)
|
|
if (sc && sc->getSCE(SC_CHARGINGPIERCE_COUNT) && sc->getSCE(SC_CHARGINGPIERCE_COUNT)->val1 >= 10)
|
|
@@ -4533,7 +4613,7 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
|
|
if (sd && pc_checkskill(sd, AM_LEARNINGPOTION))
|
|
if (sd && pc_checkskill(sd, AM_LEARNINGPOTION))
|
|
skillratio += 100; // !TODO: What's this bonus increase?
|
|
skillratio += 100; // !TODO: What's this bonus increase?
|
|
#else
|
|
#else
|
|
- skillratio += 40 * skill_lv;
|
|
|
|
|
|
+ skillratio += -50 + 50 * skill_lv;
|
|
#endif
|
|
#endif
|
|
break;
|
|
break;
|
|
case MO_FINGEROFFENSIVE:
|
|
case MO_FINGEROFFENSIVE:
|
|
@@ -6151,10 +6231,9 @@ static void battle_attack_sc_bonus(struct Damage* wd, struct block_list *src, st
|
|
if (sc->getSCE(SC_GATLINGFEVER))
|
|
if (sc->getSCE(SC_GATLINGFEVER))
|
|
ATK_ADD(wd->equipAtk, wd->equipAtk2, sc->getSCE(SC_GATLINGFEVER)->val3);
|
|
ATK_ADD(wd->equipAtk, wd->equipAtk2, sc->getSCE(SC_GATLINGFEVER)->val3);
|
|
#else
|
|
#else
|
|
- if (sc->getSCE(SC_TRUESIGHT)) {
|
|
|
|
- ATK_ADDRATE(wd->damage, wd->damage2, 2 * sc->getSCE(SC_TRUESIGHT)->val1);
|
|
|
|
- ATK_ADDRATE(wd->basedamage, wd->basedamage2, 2 * sc->getSCE(SC_TRUESIGHT)->val1);
|
|
|
|
- }
|
|
|
|
|
|
+ //ATK percent modifier (in pre-renewal, it's applied multiplicatively after the skill ratio)
|
|
|
|
+ ATK_RATE(wd->damage, wd->damage2, battle_get_atkpercent(src, skill_id, sc));
|
|
|
|
+ ATK_RATE(wd->basedamage, wd->basedamage2, battle_get_atkpercent(src, 0, sc));
|
|
#endif
|
|
#endif
|
|
if (sc->getSCE(SC_SPIRIT)) {
|
|
if (sc->getSCE(SC_SPIRIT)) {
|
|
if (skill_id == AS_SONICBLOW && sc->getSCE(SC_SPIRIT)->val2 == SL_ASSASIN) {
|
|
if (skill_id == AS_SONICBLOW && sc->getSCE(SC_SPIRIT)->val2 == SL_ASSASIN) {
|
|
@@ -6377,16 +6456,15 @@ static void battle_calc_defense_reduction(struct Damage* wd, struct block_list *
|
|
def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
|
|
def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if (skill_id == AM_ACIDTERROR)
|
|
|
|
-#ifdef RENEWAL
|
|
|
|
- def2 = 0; //Ignore only status defense. [FatalEror]
|
|
|
|
-#else
|
|
|
|
- def1 = 0; //Ignores only armor defense. [Skotlex]
|
|
|
|
-#endif
|
|
|
|
if(def2 < 1)
|
|
if(def2 < 1)
|
|
def2 = 1;
|
|
def2 = 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef RENEWAL
|
|
|
|
+ if (skill_id == AM_ACIDTERROR)
|
|
|
|
+ def2 = 0; // Ignore only status defense.
|
|
|
|
+#endif
|
|
|
|
+
|
|
//Damage reduction based on vitality
|
|
//Damage reduction based on vitality
|
|
if (tsd) { //Sd vit-eq
|
|
if (tsd) { //Sd vit-eq
|
|
int skill;
|
|
int skill;
|
|
@@ -6466,18 +6544,12 @@ static void battle_calc_defense_reduction(struct Damage* wd, struct block_list *
|
|
attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_R) ?100:(is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_R) ? (int64)is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_R)*(def1+vit_def) : (100-def1)),
|
|
attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_R) ?100:(is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_R) ? (int64)is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_R)*(def1+vit_def) : (100-def1)),
|
|
attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_L) ?100:(is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_L) ? (int64)is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_L)*(def1+vit_def) : (100-def1))
|
|
attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_L) ?100:(is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_L) ? (int64)is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_L)*(def1+vit_def) : (100-def1))
|
|
);
|
|
);
|
|
- ATK_RATE2(wd->basedamage, wd->basedamage2,
|
|
|
|
- attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_R) ? 100 : (is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_R) ? (int64)is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_R) * (def1 + vit_def) : (100 - def1)),
|
|
|
|
- attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_L) ? 100 : (is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_L) ? (int64)is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_L) * (def1 + vit_def) : (100 - def1))
|
|
|
|
- );
|
|
|
|
|
|
+ ATK_RATE(wd->basedamage, wd->basedamage2, 100 - def1);
|
|
ATK_ADD2(wd->damage, wd->damage2,
|
|
ATK_ADD2(wd->damage, wd->damage2,
|
|
attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_R) || is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_R) ?0:-vit_def,
|
|
attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_R) || is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_R) ?0:-vit_def,
|
|
attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_L) || is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_L) ?0:-vit_def
|
|
attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_L) || is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_L) ?0:-vit_def
|
|
);
|
|
);
|
|
- ATK_ADD2(wd->basedamage, wd->basedamage2,
|
|
|
|
- attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_R) || is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_R) ? 0 : -vit_def,
|
|
|
|
- attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_L) || is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_L) ? 0 : -vit_def
|
|
|
|
- );
|
|
|
|
|
|
+ ATK_ADD(wd->basedamage, wd->basedamage2, -vit_def);
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
@@ -6517,8 +6589,10 @@ static void battle_calc_attack_post_defense(struct Damage* wd, struct block_list
|
|
// Post skill/vit reduction damage increases
|
|
// Post skill/vit reduction damage increases
|
|
#ifndef RENEWAL
|
|
#ifndef RENEWAL
|
|
//Refine bonus
|
|
//Refine bonus
|
|
- if (sd && battle_skill_stacks_masteries_vvs(skill_id) && skill_id != MO_INVESTIGATE && skill_id != MO_EXTREMITYFIST) { // Counts refine bonus multiple times
|
|
|
|
- ATK_ADD2(wd->damage, wd->damage2, sstatus->rhw.atk2, sstatus->lhw.atk2);
|
|
|
|
|
|
+ if (sd) {
|
|
|
|
+ if (battle_skill_stacks_masteries_vvs(skill_id)) {
|
|
|
|
+ ATK_ADD2(wd->damage, wd->damage2, sstatus->rhw.atk2, sstatus->lhw.atk2);
|
|
|
|
+ }
|
|
ATK_ADD2(wd->basedamage, wd->basedamage2, sstatus->rhw.atk2, sstatus->lhw.atk2);
|
|
ATK_ADD2(wd->basedamage, wd->basedamage2, sstatus->rhw.atk2, sstatus->lhw.atk2);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -7184,9 +7258,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
|
|
wd.dmg_lv = ATK_FLEE;
|
|
wd.dmg_lv = ATK_FLEE;
|
|
else if(!(infdef = is_infinite_defense(target, wd.flag))) { //no need for math against plants
|
|
else if(!(infdef = is_infinite_defense(target, wd.flag))) { //no need for math against plants
|
|
|
|
|
|
- battle_calc_skill_base_damage(&wd, src, target, skill_id, skill_lv); // base skill damage
|
|
|
|
|
|
+ // First call function with skill_id 0 to get base damage of a normal attack
|
|
|
|
+ battle_calc_skill_base_damage(&wd, src, target, 0, 0); // base damage
|
|
wd.basedamage = wd.damage;
|
|
wd.basedamage = wd.damage;
|
|
wd.basedamage2 = wd.damage2;
|
|
wd.basedamage2 = wd.damage2;
|
|
|
|
+ // Now get actual skill damage
|
|
|
|
+ if (skill_id != 0)
|
|
|
|
+ battle_calc_skill_base_damage(&wd, src, target, skill_id, skill_lv); // base skill damage
|
|
|
|
|
|
int64 ratio = 0;
|
|
int64 ratio = 0;
|
|
|
|
|
|
@@ -7347,8 +7425,14 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
|
|
battle_attack_sc_bonus(&wd, src, target, skill_id, skill_lv);
|
|
battle_attack_sc_bonus(&wd, src, target, skill_id, skill_lv);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
- if (wd.damage + wd.damage2) { //Check if attack ignores DEF
|
|
|
|
|
|
+ if (wd.damage + wd.damage2) {
|
|
|
|
+#ifdef RENEWAL
|
|
|
|
+ // Check if attack ignores DEF (in pre-renewal we need to update base damage even when the skill ignores DEF)
|
|
if(!attack_ignores_def(&wd, src, target, skill_id, skill_lv, EQI_HAND_L) || !attack_ignores_def(&wd, src, target, skill_id, skill_lv, EQI_HAND_R))
|
|
if(!attack_ignores_def(&wd, src, target, skill_id, skill_lv, EQI_HAND_L) || !attack_ignores_def(&wd, src, target, skill_id, skill_lv, EQI_HAND_R))
|
|
|
|
+#else
|
|
|
|
+ // Shield Boomerang and Rapid Smiting already calculated the defense before the skill ratio was applied
|
|
|
|
+ if(skill_id != PA_SHIELDCHAIN && skill_id != CR_SHIELDBOOMERANG)
|
|
|
|
+#endif
|
|
battle_calc_defense_reduction(&wd, src, target, skill_id, skill_lv);
|
|
battle_calc_defense_reduction(&wd, src, target, skill_id, skill_lv);
|
|
|
|
|
|
battle_calc_attack_post_defense(&wd, src, target, skill_id, skill_lv);
|
|
battle_calc_attack_post_defense(&wd, src, target, skill_id, skill_lv);
|
|
@@ -7455,14 +7539,20 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
|
|
ATK_ADD(wd.damage, wd.damage2, 4);
|
|
ATK_ADD(wd.damage, wd.damage2, 4);
|
|
if (skill_id == MO_FINGEROFFENSIVE) { //Need to calculate number of Spirit Balls you had before cast
|
|
if (skill_id == MO_FINGEROFFENSIVE) { //Need to calculate number of Spirit Balls you had before cast
|
|
ATK_ADD(wd.damage, wd.damage2, (wd.div_ + sd->spiritball) * 3);
|
|
ATK_ADD(wd.damage, wd.damage2, (wd.div_ + sd->spiritball) * 3);
|
|
- } else
|
|
|
|
|
|
+ } else if (skill_id != MO_INVESTIGATE)
|
|
ATK_ADD(wd.damage, wd.damage2, ((wd.div_ < 1) ? 1 : wd.div_) * sd->spiritball * 3);
|
|
ATK_ADD(wd.damage, wd.damage2, ((wd.div_ < 1) ? 1 : wd.div_) * sd->spiritball * 3);
|
|
#endif
|
|
#endif
|
|
- if( skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN ) { //Refine bonus applies after cards and elements.
|
|
|
|
|
|
+ if (sd && skill_id == PA_SHIELDCHAIN) { //Rapid Smiting has a unique mastery bonus
|
|
short index = sd->equip_index[EQI_HAND_L];
|
|
short index = sd->equip_index[EQI_HAND_L];
|
|
-
|
|
|
|
- if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
|
|
|
|
- ATK_ADD(wd.damage, wd.damage2, 10*sd->inventory.u.items_inventory[index].refine);
|
|
|
|
|
|
+ //The bonus is [max(100, Random(100, 0.7*weight + pow(skill level + refine)))]
|
|
|
|
+ if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR) {
|
|
|
|
+ //First calculate the random part of the bonus
|
|
|
|
+ int bonus = (7 * sd->inventory_data[index]->weight) / 100;
|
|
|
|
+ bonus += pow(skill_lv + sd->inventory.u.items_inventory[index].refine, 2);
|
|
|
|
+ //Now get a random value between 100 and the random part
|
|
|
|
+ bonus = max(100, rnd_value(100, bonus));
|
|
|
|
+ ATK_ADD(wd.damage, wd.damage2, bonus);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
#ifndef RENEWAL
|
|
#ifndef RENEWAL
|
|
//Card Fix for attacker (sd), 2 is added to the "left" flag meaning "attacker cards only"
|
|
//Card Fix for attacker (sd), 2 is added to the "left" flag meaning "attacker cards only"
|