feat(Core/Unit): New helper IsClass and script hook OnPlayerIsClass (#18243)

* Class Comparison Logic Encapsulation - Parity

* Add Context to IsClass

* Add Unit IsClass script hook

* Replace additional getClass with IsClass

* Update CanUseItem to replace getClass with IsClass

* Add separate context for pet vs ability

* Change Create to Init since not all referenced contexts are creation

* Align spacing in ClassContext

* Drop context on LFGManager max power

* Update IsClass context that wraps around Missle Barrage

* Rename context for swapping weapons

* Be more specific than CLASS_CONTEXT_TALENT

* Remove duplicate context

* Moved IsClass Hook to Player

* Removed unused parameter in virtual base function

* Added maybe_unused to IsClass virtual in order to compile

To match the override signature, the virtual base needs to include the parameter in question, so using [maybe_unused] to signal to the compiler to allow it

* Remove extra blank line

* Add ABILITY_REACTIVE context

* Add context for PET_CHARM

* Remove explicit nullopt check per review

* Code Readability - Change if to if else in pet

Due to the return pattern, this doesn't change functionality in any way

* Add OnPlayer to disambiguate

---------

Co-authored-by: NathanHandley <nathanhandley@protonmail.com>
This commit is contained in:
Nathan Handley
2024-02-10 09:25:00 -06:00
committed by GitHub
parent c47c945aa4
commit df33a57b78
33 changed files with 344 additions and 280 deletions

View File

@@ -346,134 +346,127 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS;
index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
switch (getClass())
if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS))
{
case CLASS_HUNTER:
val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f;
break;
case CLASS_ROGUE:
case CLASS_WARRIOR:
val2 = level + GetStat(STAT_AGILITY) - 10.0f;
break;
case CLASS_DRUID:
switch (GetShapeshiftForm())
{
case FORM_CAT:
case FORM_BEAR:
case FORM_DIREBEAR:
val2 = 0.0f;
break;
default:
val2 = GetStat(STAT_AGILITY) - 10.0f;
break;
}
val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f;
}
else if (IsClass(CLASS_ROGUE, CLASS_CONTEXT_STATS) || IsClass(CLASS_WARRIOR, CLASS_CONTEXT_STATS))
{
val2 = level + GetStat(STAT_AGILITY) - 10.0f;
}
else if (IsClass(CLASS_DRUID, CLASS_CONTEXT_STATS))
{
switch (GetShapeshiftForm())
{
case FORM_CAT:
case FORM_BEAR:
case FORM_DIREBEAR:
val2 = 0.0f;
break;
default:
val2 = GetStat(STAT_AGILITY) - 10.0f;
break;
}
}
else
{
val2 = GetStat(STAT_AGILITY) - 10.0f;
}
}
else
{
switch (getClass())
if (IsClass(CLASS_PALADIN, CLASS_CONTEXT_STATS) || IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_STATS) || IsClass(CLASS_WARRIOR, CLASS_CONTEXT_STATS))
{
case CLASS_PALADIN:
case CLASS_DEATH_KNIGHT:
case CLASS_WARRIOR:
val2 = level * 3.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
break;
case CLASS_HUNTER:
case CLASS_SHAMAN:
case CLASS_ROGUE:
val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f;
break;
case CLASS_DRUID:
val2 = level * 3.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
}
else if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS) || IsClass(CLASS_SHAMAN, CLASS_CONTEXT_STATS) || IsClass(CLASS_ROGUE, CLASS_CONTEXT_STATS))
{
val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f;
}
else if (IsClass(CLASS_DRUID, CLASS_CONTEXT_STATS))
{
// Check if Predatory Strikes is skilled
float mLevelMult = 0.0f;
float weapon_bonus = 0.0f;
if (IsInFeralForm())
{
Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_DUMMY);
for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
{
// Check if Predatory Strikes is skilled
float mLevelMult = 0.0f;
float weapon_bonus = 0.0f;
if (IsInFeralForm())
AuraEffect* aurEff = *itr;
if (aurEff->GetSpellInfo()->SpellIconID == 1563)
{
Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_DUMMY);
for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
switch (aurEff->GetEffIndex())
{
AuraEffect* aurEff = *itr;
if (aurEff->GetSpellInfo()->SpellIconID == 1563)
case 0: // Predatory Strikes (effect 0)
mLevelMult = CalculatePct(1.0f, aurEff->GetAmount());
break;
case 1: // Predatory Strikes (effect 1)
if (Item* mainHand = m_items[EQUIPMENT_SLOT_MAINHAND])
{
switch (aurEff->GetEffIndex())
// also gains % attack power from equipped weapon
ItemTemplate const* proto = mainHand->GetTemplate();
if (!proto)
continue;
uint32 ap = proto->getFeralBonus();
// Get AP Bonuses from weapon
for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
{
case 0: // Predatory Strikes (effect 0)
mLevelMult = CalculatePct(1.0f, aurEff->GetAmount());
if (i >= proto->StatsCount)
break;
case 1: // Predatory Strikes (effect 1)
if (Item* mainHand = m_items[EQUIPMENT_SLOT_MAINHAND])
{
// also gains % attack power from equipped weapon
ItemTemplate const* proto = mainHand->GetTemplate();
if (!proto)
continue;
uint32 ap = proto->getFeralBonus();
// Get AP Bonuses from weapon
for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
{
if (i >= proto->StatsCount)
break;
if (proto->ItemStat[i].ItemStatType == ITEM_MOD_ATTACK_POWER)
ap += proto->ItemStat[i].ItemStatValue;
}
// Get AP Bonuses from weapon spells
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
{
// no spell
if (!proto->Spells[i].SpellId || proto->Spells[i].SpellTrigger != ITEM_SPELLTRIGGER_ON_EQUIP)
continue;
// check if it is valid spell
SpellInfo const* spellproto = sSpellMgr->GetSpellInfo(proto->Spells[i].SpellId);
if (!spellproto)
continue;
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
if (spellproto->Effects[j].ApplyAuraName == SPELL_AURA_MOD_ATTACK_POWER)
ap += spellproto->Effects[j].CalcValue();
}
weapon_bonus = CalculatePct(float(ap), aurEff->GetAmount());
}
break;
default:
break;
if (proto->ItemStat[i].ItemStatType == ITEM_MOD_ATTACK_POWER)
ap += proto->ItemStat[i].ItemStatValue;
}
}
}
}
switch (GetShapeshiftForm())
{
case FORM_CAT:
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f + GetStat(STAT_AGILITY) - 20.0f + weapon_bonus + m_baseFeralAP;
break;
case FORM_BEAR:
case FORM_DIREBEAR:
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + weapon_bonus + m_baseFeralAP;
break;
case FORM_MOONKIN:
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + m_baseFeralAP;
// Get AP Bonuses from weapon spells
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
{
// no spell
if (!proto->Spells[i].SpellId || proto->Spells[i].SpellTrigger != ITEM_SPELLTRIGGER_ON_EQUIP)
continue;
// check if it is valid spell
SpellInfo const* spellproto = sSpellMgr->GetSpellInfo(proto->Spells[i].SpellId);
if (!spellproto)
continue;
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
if (spellproto->Effects[j].ApplyAuraName == SPELL_AURA_MOD_ATTACK_POWER)
ap += spellproto->Effects[j].CalcValue();
}
weapon_bonus = CalculatePct(float(ap), aurEff->GetAmount());
}
break;
default:
val2 = GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
break;
}
}
break;
}
case CLASS_MAGE:
case CLASS_PRIEST:
case CLASS_WARLOCK:
val2 = GetStat(STAT_STRENGTH) - 10.0f;
}
switch (GetShapeshiftForm())
{
case FORM_CAT:
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f + GetStat(STAT_AGILITY) - 20.0f + weapon_bonus + m_baseFeralAP;
break;
case FORM_BEAR:
case FORM_DIREBEAR:
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + weapon_bonus + m_baseFeralAP;
break;
case FORM_MOONKIN:
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + m_baseFeralAP;
break;
default:
val2 = GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
break;
}
}
else if (IsClass(CLASS_MAGE, CLASS_CONTEXT_STATS) || IsClass(CLASS_PRIEST, CLASS_CONTEXT_STATS) || IsClass(CLASS_WARLOCK, CLASS_CONTEXT_STATS))
{
val2 = GetStat(STAT_STRENGTH) - 10.0f;
}
}
@@ -521,7 +514,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
UpdateDamagePhysical(BASE_ATTACK);
if (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon
UpdateDamagePhysical(OFF_ATTACK);
if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness
if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_STATS) || IsClass(CLASS_PALADIN, CLASS_CONTEXT_STATS)) // mental quickness
UpdateSpellDamageAndHealingBonus();
}
}