From 4247bc50c52a605397508a6b6a3e9bb3a659f591 Mon Sep 17 00:00:00 2001 From: Playtester <3785983+Playtester@users.noreply.github.com> Date: Mon, 1 Apr 2024 15:15:41 +0200 Subject: [PATCH] ATKpercent, Base Damage, Occult Impaction, Freezing Trap, Acid Terror, Paladin skills (#8210) - A handful of skills grant status changes that actually are calculated together into a value "ATKpercent" rather than increasing BATK/WATK, this value is then applied to most weapon skills * Pre-re - Damage after skill ratio but before DEF reduction is multiplied with ATKpercent * Renewal - Is a linear addition to skill ratio instead (ATKpercent of 200 means +100% to any skill ratio, so 100% becomes 200%, but 500% only becomes 600%) * For further information which status changes go into ATKpercent and which skills are not influenced by it, please see the battle_get_atkpercent function - Fixed base damage not being calculated correctly for certain skills - MO_INVESTIGATE is no longer influenced by Spirit Spheres except when you have the WATK_ELEMENT effect (Magnum Break) - Freezing trap now deals 100% damage on all levels and can miss - Acid Terror now ignores DEF, but its base attack is reduced by VIT - Acid Terror skill ratio is now 50%+50%*level - Acid Terror and Martyr's Reckoning (PA_SACRIFICE) are no longer affected by refine and mastery bonus - Magnum Break/EDP bonus no longer affects Acid Terror and unit skills - Fixed damage formula of Shield Boomerang and Rapid Smiting - Code improvements - Fixes #8193 --- db/pre-re/skill_db.yml | 3 +- src/map/battle.cpp | 182 ++++++++++++++++++++++++++++++----------- src/map/status.cpp | 37 +-------- 3 files changed, 138 insertions(+), 84 deletions(-) diff --git a/db/pre-re/skill_db.yml b/db/pre-re/skill_db.yml index 0dc81368ab..adc399bfe6 100644 --- a/db/pre-re/skill_db.yml +++ b/db/pre-re/skill_db.yml @@ -4408,7 +4408,6 @@ Body: TargetType: Ground DamageFlags: Splash: true - IgnoreFlee: true Flags: IsTrap: true AlterRangeResearchTrap: true @@ -6461,6 +6460,7 @@ Body: TargetType: Attack DamageFlags: IgnoreAtkCard: true + IgnoreDefense: true IgnoreFlee: true Flags: IgnoreAutoGuard: true @@ -32636,7 +32636,6 @@ Body: TargetType: Ground DamageFlags: Splash: true - IgnoreFlee: true Flags: IsTrap: true AlterRangeResearchTrap: true diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 75689a1fca..aec3504e5c 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -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_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); +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 @@ -3365,7 +3366,9 @@ static bool battle_skill_stacks_masteries_vvs(uint16 skill_id) if ( #ifndef RENEWAL skill_id == PA_SHIELDCHAIN || skill_id == CR_SHIELDBOOMERANG || + skill_id == PA_SACRIFICE || skill_id == AM_ACIDTERROR || #endif + skill_id == MO_INVESTIGATE || skill_id == MO_EXTREMITYFIST || skill_id == RK_DRAGONBREATH || skill_id == RK_DRAGONBREATH_WATER || skill_id == NC_SELFDESTRUCTION || skill_id == LG_SHIELDPRESS || skill_id == LG_EARTHDRIVE) return false; @@ -3657,11 +3660,13 @@ static void battle_calc_element_damage(struct Damage* wd, struct block_list *src #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 (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; 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 - 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); } 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); 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 uint16 skill; wd->damage = battle_addmastery(sd,target,wd->damage,0); - wd->basedamage = battle_addmastery(sd, target, wd->basedamage, 0); #ifdef RENEWAL wd->masteryAtk = battle_addmastery(sd,target,wd->weaponAtk,0); #endif if (is_attack_left_handed(src, skill_id)) { wd->damage2 = battle_addmastery(sd,target,wd->damage2,1); - wd->basedamage2 = battle_addmastery(sd, target, wd->basedamage2, 1); #ifdef RENEWAL wd->masteryAtk2 = battle_addmastery(sd,target,wd->weaponAtk2,1); #endif @@ -3972,12 +3980,19 @@ static void battle_calc_skill_base_damage(struct Damage* wd, struct block_list * if (sd) { 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) { + 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); #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); #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 ATK_ADD(wd->damage, wd->damage2, sstatus->rhw.atk2); //Else use Atk2 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)) { 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 break; } //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 *------------------------------------------------------ @@ -4308,6 +4394,10 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list * //Skill damage modifiers that stack linearly 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)) skillratio += sc->getSCE(SC_OVERTHRUST)->val3; if(sc->getSCE(SC_MAXOVERTHRUST)) @@ -4317,10 +4407,6 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list * skillratio += 100; #else 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 if (!skill_id || skill_id == KN_AUTOCOUNTER) { 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: skillratio += 50; break; -#ifndef RENEWAL - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - skillratio += -50 + 10 * skill_lv; - break; -#endif case KN_PIERCE: skillratio += 10 * skill_lv; 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)) skillratio += 100; // !TODO: What's this bonus increase? #else - skillratio += 40 * skill_lv; + skillratio += -50 + 50 * skill_lv; #endif break; 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)) ATK_ADD(wd->equipAtk, wd->equipAtk2, sc->getSCE(SC_GATLINGFEVER)->val3); #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 if (sc->getSCE(SC_SPIRIT)) { 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; } } - 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) def2 = 1; } +#ifdef RENEWAL + if (skill_id == AM_ACIDTERROR) + def2 = 0; // Ignore only status defense. +#endif + //Damage reduction based on vitality if (tsd) { //Sd vit-eq 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_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, 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_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 } @@ -6517,8 +6589,10 @@ static void battle_calc_attack_post_defense(struct Damage* wd, struct block_list // Post skill/vit reduction damage increases #ifndef RENEWAL //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); } @@ -7184,9 +7258,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl wd.dmg_lv = ATK_FLEE; 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.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; @@ -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); #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)) +#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_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); 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); - } else + } else if (skill_id != MO_INVESTIGATE) ATK_ADD(wd.damage, wd.damage2, ((wd.div_ < 1) ? 1 : wd.div_) * sd->spiritball * 3); #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]; - - 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 //Card Fix for attacker (sd), 2 is added to the "left" flag meaning "attacker cards only" diff --git a/src/map/status.cpp b/src/map/status.cpp index 1756eae5bf..4252b8cd00 100644 --- a/src/map/status.cpp +++ b/src/map/status.cpp @@ -7027,27 +7027,6 @@ static unsigned short status_calc_batk(struct block_list *bl, status_change *sc, batk += sc->getSCE(SC_ANGRIFFS_MODUS)->val2; if(sc->getSCE(SC_2011RWC_SCROLL)) batk += 30; - if(sc->getSCE(SC_INCATKRATE)) - batk += batk * sc->getSCE(SC_INCATKRATE)->val1/100; - if(sc->getSCE(SC_PROVOKE)) - batk += batk * sc->getSCE(SC_PROVOKE)->val2/100; -#ifndef RENEWAL - if(sc->getSCE(SC_CONCENTRATION)) - batk += batk * sc->getSCE(SC_CONCENTRATION)->val2/100; -#endif - if(sc->getSCE(SC_SKE)) - batk += batk * 3; - if(sc->getSCE(SC_BLOODLUST)) - batk += batk * sc->getSCE(SC_BLOODLUST)->val2/100; - if(sc->getSCE(SC_JOINTBEAT) && sc->getSCE(SC_JOINTBEAT)->val2&BREAK_WAIST) - batk -= batk * 25/100; - if(sc->getSCE(SC_CURSE)) - batk -= batk * 25/100; - /* Curse shouldn't effect on this? <- Curse OR Bleeding?? - if(sc->getSCE(SC_BLEEDING)) - batk -= batk * 25 / 100; */ - if(sc->getSCE(SC_FLEET)) - batk += batk * sc->getSCE(SC_FLEET)->val3/100; if(sc->getSCE(SC__ENERVATION)) batk -= batk * sc->getSCE(SC__ENERVATION)->val2 / 100; if( sc->getSCE(SC_ZANGETSU) ) @@ -7122,21 +7101,7 @@ static unsigned short status_calc_watk(struct block_list *bl, status_change *sc, watk += sc->getSCE(SC_NIBELUNGEN)->val2; } } - if(sc->getSCE(SC_CONCENTRATION)) - watk += watk * sc->getSCE(SC_CONCENTRATION)->val2 / 100; #endif - if(sc->getSCE(SC_INCATKRATE)) - watk += watk * sc->getSCE(SC_INCATKRATE)->val1/100; - if(sc->getSCE(SC_PROVOKE)) - watk += watk * sc->getSCE(SC_PROVOKE)->val2/100; - if(sc->getSCE(SC_SKE)) - watk += watk * 3; - if(sc->getSCE(SC_FLEET)) - watk += watk * sc->getSCE(SC_FLEET)->val3/100; - if(sc->getSCE(SC_CURSE)) - watk -= watk * 25/100; - if(sc->getSCE(SC_STRIPWEAPON) && bl->type != BL_PC) - watk -= watk * sc->getSCE(SC_STRIPWEAPON)->val2/100; if(sc->getSCE(SC_FIGHTINGSPIRIT)) watk += sc->getSCE(SC_FIGHTINGSPIRIT)->val1; if (sc->getSCE(SC_SHIELDSPELL_ATK)) @@ -12228,7 +12193,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty case SC_ASH: val2 = 0; // hit % reduc val3 = 0; // def % reduc - val4 = 0; // atk flee & reduc + val4 = 0; // atk flee % reduc if (!status_bl_has_mode(bl,MD_STATUSIMMUNE)) { val2 = 50; if (status_get_race(bl) == RC_PLANT) // plant type