|
@@ -3033,6 +3033,11 @@ static int battle_get_weapon_element(struct Damage* wd, struct block_list *src,
|
|
|
if (sc && sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 4)
|
|
|
element = ELE_HOLY;
|
|
|
break;
|
|
|
+ case GN_CARTCANNON:
|
|
|
+ case NC_ARMSCANNON:
|
|
|
+ if (sd && sd->state.arrow_atk > 0)
|
|
|
+ element = sd->bonus.arrow_ele;
|
|
|
+ break;
|
|
|
case SJ_PROMINENCEKICK:
|
|
|
element = ELE_FIRE;
|
|
|
break;
|
|
@@ -3067,56 +3072,77 @@ static int battle_get_weapon_element(struct Damage* wd, struct block_list *src,
|
|
|
*/
|
|
|
static void battle_calc_element_damage(struct Damage* wd, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv)
|
|
|
{
|
|
|
- struct map_session_data *sd = BL_CAST(BL_PC, src);
|
|
|
- struct status_change *sc = status_get_sc(src);
|
|
|
- struct status_data *sstatus = status_get_status_data(src);
|
|
|
- struct status_data *tstatus = status_get_status_data(target);
|
|
|
- int element = skill_get_ele(skill_id, skill_lv);
|
|
|
- int left_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_L, true);
|
|
|
- int right_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_R, true);
|
|
|
std::bitset<NK_MAX> nk = battle_skill_get_damage_properties(skill_id, wd->miscflag);
|
|
|
|
|
|
- //Elemental attribute fix
|
|
|
- if(!nk[NK_IGNOREELEMENT]) {
|
|
|
- //Non-pc physical melee attacks (mob, pet, homun) are "non elemental", they deal 100% to all target elements
|
|
|
- //However the "non elemental" attacks still get reduced by "Neutral resistance"
|
|
|
- //Also non-pc units have only a defending element, but can inflict elemental attacks using skills [exneval]
|
|
|
- if(battle_config.attack_attr_none&src->type)
|
|
|
- if(((!skill_id && !right_element) || (skill_id && (element == ELE_WEAPON || !right_element))) &&
|
|
|
- (wd->flag&(BF_SHORT|BF_WEAPON)) == (BF_SHORT|BF_WEAPON))
|
|
|
- return;
|
|
|
- if(wd->damage > 0) {
|
|
|
- //Forced to its element
|
|
|
- wd->damage = battle_attr_fix(src, target, wd->damage, right_element, tstatus->def_ele, tstatus->ele_lv);
|
|
|
+ // Elemental attribute fix
|
|
|
+ if(!nk[NK_IGNOREELEMENT] && (wd->damage > 0 || wd->damage2 > 0)) {
|
|
|
+ struct map_session_data *sd = BL_CAST(BL_PC, src);
|
|
|
+ struct status_change *sc = status_get_sc(src);
|
|
|
+ struct status_data *sstatus = status_get_status_data(src);
|
|
|
+ struct status_data *tstatus = status_get_status_data(target);
|
|
|
+ int left_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_L, true);
|
|
|
+ int right_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_R, true);
|
|
|
|
|
|
- switch( skill_id ) {
|
|
|
- case MC_CARTREVOLUTION:
|
|
|
- case SR_GATEOFHELL:
|
|
|
- case SR_TIGERCANNON:
|
|
|
- case KO_BAKURETSU:
|
|
|
- //case NC_MAGMA_ERUPTION:
|
|
|
- //Forced to neutral element
|
|
|
- wd->damage = battle_attr_fix(src, target, wd->damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
|
|
|
- break;
|
|
|
- case GN_CARTCANNON:
|
|
|
- case KO_HAPPOKUNAI:
|
|
|
- //Forced to ammo's element
|
|
|
- wd->damage = battle_attr_fix(src, target, wd->damage, (sd && sd->bonus.arrow_ele) ? sd->bonus.arrow_ele : ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
|
|
|
- break;
|
|
|
- }
|
|
|
+ switch (skill_id) {
|
|
|
+ case PA_SACRIFICE:
|
|
|
+ case RK_DRAGONBREATH:
|
|
|
+ case RK_DRAGONBREATH_WATER:
|
|
|
+ case NC_SELFDESTRUCTION:
|
|
|
+ case HFLI_SBR44:
|
|
|
+ wd->damage = battle_attr_fix(src, target, wd->damage, right_element, tstatus->def_ele, tstatus->ele_lv);
|
|
|
+ if (is_attack_left_handed(src, skill_id))
|
|
|
+ wd->damage2 = battle_attr_fix(src, target, wd->damage2, left_element, tstatus->def_ele, tstatus->ele_lv);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ if (skill_id == 0 && (battle_config.attack_attr_none & src->type))
|
|
|
+ return; // Non-player basic attacks are non-elemental, they deal 100% against all defense elements
|
|
|
+#ifdef RENEWAL
|
|
|
+ if (sd == nullptr) { // Renewal player's elemental damage calculation is already done before this point, only calculate for everything else
|
|
|
+#endif
|
|
|
+ wd->damage = battle_attr_fix(src, target, wd->damage, right_element, tstatus->def_ele, tstatus->ele_lv);
|
|
|
+ if (is_attack_left_handed(src, skill_id))
|
|
|
+ wd->damage2 = battle_attr_fix(src, target, wd->damage2, left_element, tstatus->def_ele, tstatus->ele_lv);
|
|
|
+#ifdef RENEWAL
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ break;
|
|
|
}
|
|
|
- if (is_attack_left_handed(src, skill_id) && wd->damage2 > 0)
|
|
|
- wd->damage2 = battle_attr_fix(src, target, wd->damage2, left_element ,tstatus->def_ele, tstatus->ele_lv);
|
|
|
- if (sc && sc->data[SC_WATK_ELEMENT] && (wd->damage || wd->damage2)) {
|
|
|
- // Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex]
|
|
|
- int64 damage = battle_calc_base_damage(src, sstatus, &sstatus->rhw, sc, tstatus->size, (is_skill_using_arrow(src, skill_id)?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100;
|
|
|
|
|
|
- wd->damage += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv);
|
|
|
- if (is_attack_left_handed(src, skill_id)) {
|
|
|
- damage = battle_calc_base_damage(src, sstatus, &sstatus->lhw, sc, tstatus->size, (is_skill_using_arrow(src, skill_id)?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100;
|
|
|
- wd->damage2 += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv);
|
|
|
+ // Forced to neutral skills [helvetica]
|
|
|
+ // Skills forced to neutral gain benefits from weapon element but final damage is considered "neutral" and resistances are applied again
|
|
|
+ switch (skill_id) {
|
|
|
+#ifdef RENEWAL
|
|
|
+ case MO_INVESTIGATE:
|
|
|
+ case CR_SHIELDBOOMERANG:
|
|
|
+ case PA_SHIELDCHAIN:
|
|
|
+#endif
|
|
|
+ case MC_CARTREVOLUTION:
|
|
|
+ case HW_MAGICCRASHER:
|
|
|
+ case SR_FALLENEMPIRE:
|
|
|
+ case SR_TIGERCANNON:
|
|
|
+ case SR_CRESCENTELBOW_AUTOSPELL:
|
|
|
+ case SR_GATEOFHELL:
|
|
|
+ wd->damage = battle_attr_fix(src, target, wd->damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
|
|
|
+ if (is_attack_left_handed(src, skill_id))
|
|
|
+ wd->damage2 = battle_attr_fix(src, target, wd->damage2, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+#ifdef RENEWAL
|
|
|
+ if (sd == nullptr) { // Only monsters have a single ATK for element, in pre-renewal we also apply element to entire ATK on players [helvetica]
|
|
|
+#endif
|
|
|
+ if (sc && sc->data[SC_WATK_ELEMENT]) { // Descriptions indicate this means adding a percent of a normal attack in another element [Skotlex]
|
|
|
+ int64 damage = battle_calc_base_damage(src, sstatus, &sstatus->rhw, sc, tstatus->size, (is_skill_using_arrow(src, skill_id) ? 2 : 0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100;
|
|
|
+
|
|
|
+ wd->damage += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv);
|
|
|
+ if (is_attack_left_handed(src, skill_id)) {
|
|
|
+ damage = battle_calc_base_damage(src, sstatus, &sstatus->lhw, sc, tstatus->size, (is_skill_using_arrow(src, skill_id) ? 2 : 0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100;
|
|
|
+ wd->damage2 += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv);
|
|
|
+ }
|
|
|
}
|
|
|
+#ifdef RENEWAL
|
|
|
}
|
|
|
+#endif
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3532,7 +3558,7 @@ static void battle_calc_skill_base_damage(struct Damage* wd, struct block_list *
|
|
|
//For quick div adjustment.
|
|
|
#define DAMAGE_DIV_FIX(dmg, div) { if ((div) < 0) { (div) *= -1; (dmg) /= (div); } (dmg) *= (div); }
|
|
|
#define DAMAGE_DIV_FIX2(dmg, div) { if ((div) > 1) (dmg) *= div; }
|
|
|
-#define DAMAGE_DIV_FIX_RENEWAL(wd, div) do { int div_ = (div); DAMAGE_DIV_FIX2((wd).statusAtk, div_); DAMAGE_DIV_FIX2((wd).weaponAtk, div_); DAMAGE_DIV_FIX2((wd).equipAtk, div_); DAMAGE_DIV_FIX2((wd).masteryAtk, div_); } while(0);
|
|
|
+
|
|
|
/*================================================= [Playtester]
|
|
|
* Applies DAMAGE_DIV_FIX and checks for min damage
|
|
|
* @param d: Damage struct to apply DAMAGE_DIV_FIX to
|
|
@@ -5842,10 +5868,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#ifdef RENEWAL
|
|
|
- if(!sd) // monsters only have a single ATK for element, in pre-renewal we also apply element to entire ATK on players [helvetica]
|
|
|
-#endif
|
|
|
- battle_calc_element_damage(&wd, src, target, skill_id, skill_lv);
|
|
|
+ battle_calc_element_damage(&wd, src, target, skill_id, skill_lv);
|
|
|
|
|
|
if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS)
|
|
|
return wd; //Enough, rest is not needed.
|
|
@@ -5967,58 +5990,6 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-#ifdef RENEWAL
|
|
|
- // forced to neutral skills [helvetica]
|
|
|
- // skills forced to neutral gain benefits from weapon element
|
|
|
- // but final damage is considered "neutral" and resistances are applied again
|
|
|
- switch (skill_id) {
|
|
|
- case MC_CARTREVOLUTION:
|
|
|
- case MO_INVESTIGATE:
|
|
|
- case SR_GATEOFHELL:
|
|
|
- case KO_BAKURETSU:
|
|
|
- //case NC_MAGMA_ERUPTION:
|
|
|
- // Forced to neutral element
|
|
|
- wd.damage = battle_attr_fix(src, target, wd.damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
|
|
|
- break;
|
|
|
- case CR_SHIELDBOOMERANG:
|
|
|
- case LK_SPIRALPIERCE:
|
|
|
- case ML_SPIRALPIERCE:
|
|
|
- case PA_SHIELDCHAIN:
|
|
|
- case PA_SACRIFICE:
|
|
|
- case RK_DRAGONBREATH:
|
|
|
- case RK_DRAGONBREATH_WATER:
|
|
|
- case NC_SELFDESTRUCTION:
|
|
|
- case KO_HAPPOKUNAI: {
|
|
|
- int64 tmp = wd.damage;
|
|
|
-
|
|
|
- if (sd) {
|
|
|
- if (skill_id == PA_SHIELDCHAIN) {
|
|
|
- wd.damage = battle_attr_fix(src, target, wd.damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
|
|
|
- if (wd.damage > 0) {
|
|
|
- wd.damage = battle_attr_fix(src, target, tmp, right_element, tstatus->def_ele, tstatus->ele_lv);
|
|
|
- if (!wd.damage)
|
|
|
- wd.damage = battle_attr_fix(src, target, tmp, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
|
|
|
- }
|
|
|
- } else if (skill_id == KO_HAPPOKUNAI) {
|
|
|
- wd.damage = battle_attr_fix(src, target, wd.damage, (sd->bonus.arrow_ele) ? sd->bonus.arrow_ele : ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
|
|
|
- if (wd.damage > 0) {
|
|
|
- wd.damage = battle_attr_fix(src, target, tmp, right_element, tstatus->def_ele, tstatus->ele_lv);
|
|
|
- if (!wd.damage)
|
|
|
- wd.damage = battle_attr_fix(src, target, tmp, (sd->bonus.arrow_ele) ? sd->bonus.arrow_ele : ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
|
|
|
- }
|
|
|
- } else
|
|
|
- wd.damage = battle_attr_fix(src, target, wd.damage, right_element, tstatus->def_ele, tstatus->ele_lv);
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
- case GN_CARTCANNON: // Cart Cannon gets forced to element of cannon ball (neutral or holy/shadow/ghost)
|
|
|
- wd.damage = battle_attr_fix(src, target, wd.damage, (sd && sd->bonus.arrow_ele) ? sd->bonus.arrow_ele : ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- // perform multihit calculations
|
|
|
- DAMAGE_DIV_FIX_RENEWAL(wd, wd.div_);
|
|
|
-#endif
|
|
|
// only do 1 dmg to plant, no need to calculate rest
|
|
|
if(infdef){
|
|
|
battle_calc_attack_plant(&wd, src, target, skill_id, skill_lv);
|