[Feature] Add Item Extra Skill Damage Percent Modifier (#3127)

* [Feature] Add Item Extra Skill Damage Percent Modifier

# Notes
- Allows `Character:ItemExtraDmgCap` to be disabled if set to `-1` or lower.
- Allows operators to set `Character:ItemExtraSkillDamageCalcAsPercent` to `true` to allow skill damage for Frenzy, Backstab, Bash, Slam, Kick, and all Monk attacks to scale with a percentage based on `extradmgamt` values from items and spells.

* > 0
This commit is contained in:
Alex King 2023-03-19 09:59:13 -04:00 committed by GitHub
parent 53e6f931c9
commit 2f4c91824e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 177 additions and 106 deletions

View File

@ -211,6 +211,7 @@ RULE_BOOL(Character, IgnoreLevelBasedHasteCaps, false, "Ignores hard coded level
RULE_BOOL(Character, EnableRaidEXPModifier, true, "Enable or disable the raid experience modifier, default is true") RULE_BOOL(Character, EnableRaidEXPModifier, true, "Enable or disable the raid experience modifier, default is true")
RULE_BOOL(Character, EnableRaidMemberEXPModifier, true, "Enable or disable the raid experience modifier based on members in raid, default is true") RULE_BOOL(Character, EnableRaidMemberEXPModifier, true, "Enable or disable the raid experience modifier based on members in raid, default is true")
RULE_BOOL(Character, LeaveCursorMoneyOnCorpse, false, "Enable or disable leaving cursor money on player corpses") RULE_BOOL(Character, LeaveCursorMoneyOnCorpse, false, "Enable or disable leaving cursor money on player corpses")
RULE_BOOL(Character, ItemExtraSkillDamageCalcAsPercent, false, "If enabled, apply Item Extra Skill Damage as Percentage-based modifiers")
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Mercs) RULE_CATEGORY(Mercs)

View File

@ -520,14 +520,17 @@ void Client::AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses *newbon, b
} }
} }
if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) { if (item->ExtraDmgAmt != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) {
if ((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > if (
RuleI(Character, ItemExtraDmgCap)) RuleI(Character, ItemExtraDmgCap) >= 0 &&
(newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)
) {
newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap);
else } else {
newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt; newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt;
} }
} }
}
// Process when ammo_slot_item = true or false // Process when ammo_slot_item = true or false
if (item->SkillModValue != 0 && item->SkillModType <= EQ::skills::HIGHEST_SKILL) { if (item->SkillModValue != 0 && item->SkillModType <= EQ::skills::HIGHEST_SKILL) {

View File

@ -7339,12 +7339,16 @@ void Bot::AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool
} }
} }
if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) { if (item->ExtraDmgAmt != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) {
if ((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)) if (
RuleI(Character, ItemExtraDmgCap) >= 0 &&
(newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)
) {
newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap);
else } else {
newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt; newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt;
} }
}
if (!isAug) if (!isAug)
{ {

View File

@ -563,13 +563,17 @@ void Merc::AddItemBonuses(const EQ::ItemData *item, StatBonuses* newbon) {
} }
} }
if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) { if (item->ExtraDmgAmt != 0 && item->ExtraDmgSkill <= EQ::skills::HIGHEST_SKILL) {
if((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)) if (
RuleI(Character, ItemExtraDmgCap) >= 0 &&
(newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)
) {
newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap);
else } else {
newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt; newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt;
} }
} }
}
int Merc::GroupLeadershipAAHealthEnhancement() int Merc::GroupLeadershipAAHealthEnhancement()
{ {

View File

@ -38,39 +38,73 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target)
case EQ::skills::SkillEagleStrike: case EQ::skills::SkillEagleStrike:
case EQ::skills::SkillTigerClaw: case EQ::skills::SkillTigerClaw:
case EQ::skills::SkillRoundKick: case EQ::skills::SkillRoundKick:
if (skill_level >= 25) if (skill_level >= 25) {
base++; base++;
if (skill_level >= 75) }
if (skill_level >= 75) {
base++; base++;
if (skill_level >= 125) }
if (skill_level >= 125) {
base++; base++;
if (skill_level >= 175) }
if (skill_level >= 175) {
base++; base++;
}
if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) {
base *= std::abs(GetSkillDmgAmt(skill) / 100);
}
return base; return base;
case EQ::skills::SkillFrenzy: case EQ::skills::SkillFrenzy:
if (IsClient() && CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary)) { if (IsClient() && CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary)) {
if (GetLevel() > 15) if (GetLevel() > 15) {
base += GetLevel() - 15; base += GetLevel() - 15;
if (base > 23) }
if (base > 23) {
base = 23; base = 23;
if (GetLevel() > 50) }
if (GetLevel() > 50) {
base += 2; base += 2;
if (GetLevel() > 54) }
base++;
if (GetLevel() > 59) if (GetLevel() > 54) {
base++; base++;
} }
if (GetLevel() > 59) {
base++;
}
}
if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) {
base *= std::abs(GetSkillDmgAmt(skill) / 100);
}
return base; return base;
case EQ::skills::SkillFlyingKick: { case EQ::skills::SkillFlyingKick: {
float skill_bonus = skill_level / 9.0f; float skill_bonus = skill_level / 9.0f;
float ac_bonus = 0.0f; float ac_bonus = 0.0f;
if (IsClient()) { if (IsClient()) {
auto inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotFeet); auto inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotFeet);
if (inst) if (inst) {
ac_bonus = inst->GetItemArmorClass(true) / 25.0f; ac_bonus = inst->GetItemArmorClass(true) / 25.0f;
} }
if (ac_bonus > skill_bonus) }
if (ac_bonus > skill_bonus) {
ac_bonus = skill_bonus; ac_bonus = skill_bonus;
}
if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) {
return static_cast<int>(ac_bonus + skill_bonus) * std::abs(GetSkillDmgAmt(skill) / 100);
}
return static_cast<int>(ac_bonus + skill_bonus); return static_cast<int>(ac_bonus + skill_bonus);
} }
case EQ::skills::SkillKick: { case EQ::skills::SkillKick: {
@ -79,11 +113,19 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target)
float ac_bonus = 0.0f; float ac_bonus = 0.0f;
if (IsClient()) { if (IsClient()) {
auto inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotFeet); auto inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotFeet);
if (inst) if (inst) {
ac_bonus = inst->GetItemArmorClass(true) / 25.0f; ac_bonus = inst->GetItemArmorClass(true) / 25.0f;
} }
if (ac_bonus > skill_bonus) }
if (ac_bonus > skill_bonus) {
ac_bonus = skill_bonus; ac_bonus = skill_bonus;
}
if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) {
return static_cast<int>(ac_bonus + skill_bonus) * std::abs(GetSkillDmgAmt(skill) / 100);
}
return static_cast<int>(ac_bonus + skill_bonus); return static_cast<int>(ac_bonus + skill_bonus);
} }
case EQ::skills::SkillBash: { case EQ::skills::SkillBash: {
@ -91,17 +133,27 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target)
float ac_bonus = 0.0f; float ac_bonus = 0.0f;
const EQ::ItemInstance *inst = nullptr; const EQ::ItemInstance *inst = nullptr;
if (IsClient()) { if (IsClient()) {
if (HasShieldEquiped()) if (HasShieldEquiped()) {
inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotSecondary); inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotSecondary);
else if (HasTwoHanderEquipped()) } else if (HasTwoHanderEquipped()) {
inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary); inst = CastToClient()->GetInv().GetItem(EQ::invslot::slotPrimary);
} }
if (inst) }
if (inst) {
ac_bonus = inst->GetItemArmorClass(true) / 25.0f; ac_bonus = inst->GetItemArmorClass(true) / 25.0f;
else } else {
return 0; // return 0 in cases where we don't have an item return 0;
if (ac_bonus > skill_bonus) } // return 0 in cases where we don't have an item
if (ac_bonus > skill_bonus) {
ac_bonus = skill_bonus; ac_bonus = skill_bonus;
}
if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) {
return static_cast<int>(ac_bonus + skill_bonus) * std::abs(GetSkillDmgAmt(skill) / 100);
}
return static_cast<int>(ac_bonus + skill_bonus); return static_cast<int>(ac_bonus + skill_bonus);
} }
case EQ::skills::SkillBackstab: { case EQ::skills::SkillBackstab: {
@ -117,11 +169,13 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target)
} }
if (target) { if (target) {
if (inst->GetItemElementalFlag(true) && inst->GetItemElementalDamage(true) && !RuleB(Combat, BackstabIgnoresElemental)) { if (inst->GetItemElementalFlag(true) && inst->GetItemElementalDamage(true) &&
!RuleB(Combat, BackstabIgnoresElemental)) {
base += target->ResistElementalWeaponDmg(inst); base += target->ResistElementalWeaponDmg(inst);
} }
if ((inst->GetItemBaneDamageBody(true) || inst->GetItemBaneDamageRace(true)) && !RuleB(Combat, BackstabIgnoresBane)) { if ((inst->GetItemBaneDamageBody(true) || inst->GetItemBaneDamageRace(true)) &&
!RuleB(Combat, BackstabIgnoresBane)) {
base += target->CheckBaneDamage(inst); base += target->CheckBaneDamage(inst);
} }
} }
@ -133,13 +187,18 @@ int Mob::GetBaseSkillDamage(EQ::skills::SkillType skill, Mob *target)
// or their mod is divided again, this is probably not the right mod, but it's better // or their mod is divided again, this is probably not the right mod, but it's better
skill_bonus /= 3.0f; skill_bonus /= 3.0f;
} }
// ahh lets make sure everything is casted right :P ugly but w/e
if (RuleB(Character, ItemExtraSkillDamageCalcAsPercent) && GetSkillDmgAmt(skill) > 0) {
return static_cast<int>(static_cast<float>(base) * (skill_bonus + 2.0f)) * std::abs(GetSkillDmgAmt(skill) / 100);
}
return static_cast<int>(static_cast<float>(base) * (skill_bonus + 2.0f)); return static_cast<int>(static_cast<float>(base) * (skill_bonus + 2.0f));
} }
default: default: {
return 0; return 0;
} }
} }
}
void Mob::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 base_damage, int32 min_damage, void Mob::DoSpecialAttackDamage(Mob *who, EQ::skills::SkillType skill, int32 base_damage, int32 min_damage,
int32 hate_override, int ReuseTime) int32 hate_override, int ReuseTime)