refactor(Core/Spells): Implement QAston Proc System (#11079)

* .

* sql

* .

* .

* 1

* 2

* 3

* 4

* 5

* 6

* 7

* 8

* 9

* 10

* 11

* 12

* 13

* 14

* 15

* Update spell_item.cpp

* Update Unit.cpp

* 16

* 17

* 18

* 19

* 20

* 21

* Update Unit.cpp

* REVERT UltraNIX Commit

* 22

* 23

* .

* .

* .

* warrior

* warlock

* shaman rogue priest paladin mage

* spell item

* hunter

* druid

* dk

* war

* error style

* Update rev_1647677899565690722.sql

* Update rev_1647677899565690722.sql

* Update rev_1647677899565690722.sql

* .

* DOND DEL ME WAD DO DO

* error 2

* .

* .

* .

* FIX

* Update SpellInfoCorrections.cpp

* Update SpellInfoCorrections.cpp

* .

* ja genau

* Update .gitignore

* .

* .

* .,

* .

* .

* .

* .

* Update Unit.cpp
This commit is contained in:
IntelligentQuantum
2022-10-02 21:09:34 +03:30
committed by GitHub
parent 5189b43a28
commit cbd3fd0967
54 changed files with 9126 additions and 5957 deletions

View File

@@ -89,10 +89,10 @@ typedef void(*bgZoneRef)(Battleground*, WorldPacket&);
#define MAKE_SKILL_BONUS(t, p) MAKE_PAIR32(t, p)
// Note: SPELLMOD_* values is aura types in fact
enum SpellModType
enum SpellModType : uint8
{
SPELLMOD_FLAT = 107, // SPELL_AURA_ADD_FLAT_MODIFIER
SPELLMOD_PCT = 108 // SPELL_AURA_ADD_PCT_MODIFIER
SPELLMOD_FLAT = SPELL_AURA_ADD_FLAT_MODIFIER,
SPELLMOD_PCT = SPELL_AURA_ADD_PCT_MODIFIER
};
// 2^n values, Player::m_isunderwater is a bitmask. These are Trinity internal values, they are never send to any client
@@ -180,10 +180,9 @@ enum TalentTree // talent tabs
// Spell modifier (used for modify other spells)
struct SpellModifier
{
SpellModifier(Aura* _ownerAura = nullptr) : op(SPELLMOD_DAMAGE), type(SPELLMOD_FLAT), charges(0), mask(), ownerAura(_ownerAura) {}
SpellModOp op : 8;
SpellModType type : 8;
int16 charges : 16;
SpellModifier(Aura* _ownerAura = nullptr) : op(SPELLMOD_DAMAGE), type(SPELLMOD_FLAT), mask(), ownerAura(_ownerAura) {}
SpellModOp op;
SpellModType type;
int32 value{0};
flag96 mask;
uint32 spellId{0};
@@ -192,7 +191,7 @@ struct SpellModifier
typedef std::unordered_map<uint32, PlayerTalent*> PlayerTalentMap;
typedef std::unordered_map<uint32, PlayerSpell*> PlayerSpellMap;
typedef std::list<SpellModifier*> SpellModList;
typedef std::unordered_set<SpellModifier*> SpellModContainer;
typedef GuidList WhisperListContainer;
@@ -1730,13 +1729,14 @@ public:
SpellCooldowns& GetSpellCooldownMap() { return m_spellCooldowns; }
void AddSpellMod(SpellModifier* mod, bool apply);
bool IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod, Spell* spell = nullptr);
static bool IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod, Spell* spell = nullptr);
bool HasSpellMod(SpellModifier* mod, Spell* spell);
template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* spell = nullptr, bool temporaryPet = false);
void RemoveSpellMods(Spell* spell);
template <SpellModOp op, class T>
void ApplySpellMod(uint32 spellId, T& basevalue, Spell* spell = nullptr) const;
void RestoreSpellMods(Spell* spell, uint32 ownerAuraId = 0, Aura* aura = nullptr);
void RestoreAllSpellMods(uint32 ownerAuraId = 0, Aura* aura = nullptr);
void DropModCharge(SpellModifier* mod, Spell* spell);
static void ApplyModToSpell(SpellModifier* mod, Spell* spell);
static bool HasSpellModApplied(SpellModifier* mod, Spell* spell);
void SetSpellModTakingSpell(Spell* spell, bool apply);
[[nodiscard]] bool HasSpellCooldown(uint32 spell_id) const override;
@@ -2166,9 +2166,9 @@ public:
void ApplyItemEquipSpell(Item* item, bool apply, bool form_change = false);
void ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, bool form_change = false);
void UpdateEquipSpellsAtFormChange();
void CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx);
void CastItemCombatSpell(DamageInfo const& damageInfo);
void CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemTemplate const* proto);
void CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex);
void CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto);
void SendEquipmentSetList();
void SetEquipmentSet(uint32 index, EquipmentSet eqset);
@@ -2551,7 +2551,7 @@ public:
// mt maps
[[nodiscard]] const PlayerTalentMap& GetTalentMap() const { return m_talents; }
[[nodiscard]] uint32 GetNextSave() const { return m_nextSave; }
[[nodiscard]] SpellModList const& GetSpellModList(uint32 type) const { return m_spellMods[type]; }
[[nodiscard]] SpellModContainer const& GetSpellModContainer(uint32 type) const { return m_spellMods[type]; }
void SetServerSideVisibility(ServerSideVisibilityType type, AccountTypes sec);
void SetServerSideVisibilityDetect(ServerSideVisibilityType type, AccountTypes sec);
@@ -2756,7 +2756,7 @@ public:
uint32 m_baseHealthRegen;
int32 m_spellPenetrationItemMod;
SpellModList m_spellMods[MAX_SPELLMOD];
SpellModContainer m_spellMods[MAX_SPELLMOD];
//uint32 m_pad;
// Spell* m_spellModTakingSpell; // Spell for which charges are dropped in spell::finish
@@ -2940,130 +2940,132 @@ void AddItemsSetItem(Player* player, Item* item);
void RemoveItemsSetItem(Player* player, ItemTemplate const* proto);
// "the bodies of template functions must be made available in a header file"
template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* spell, bool temporaryPet)
template <SpellModOp op, class T>
void Player::ApplySpellMod(uint32 spellId, T& basevalue, Spell* spell) const
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
{
return 0;
}
return;
float totalmul = 1.0f;
float totalmul = 1.f;
int32 totalflat = 0;
auto calculateSpellMod = [&](SpellModifier* mod)
{
// xinef: temporary pets cannot use charged mods of owner, needed for mirror image QQ they should use their own auras
if (temporaryPet && mod->charges != 0)
{
return;
}
if (mod->type == SPELLMOD_FLAT)
{
// xinef: do not allow to consume more than one 100% crit increasing spell
if (mod->op == SPELLMOD_CRITICAL_CHANCE && totalflat >= 100)
{
return;
}
int32 flatValue = mod->value;
// SPELL_MOD_THREAT - divide by 100 (in packets we send threat * 100)
if (mod->op == SPELLMOD_THREAT)
{
flatValue /= 100;
}
totalflat += flatValue;
}
else if (mod->type == SPELLMOD_PCT)
{
// skip percent mods for null basevalue (most important for spell mods with charges)
if (basevalue == T(0) || totalmul == 0.0f)
{
return;
}
// special case (skip > 10sec spell casts for instant cast setting)
if (mod->op == SPELLMOD_CASTING_TIME && basevalue >= T(10000) && mod->value <= -100)
{
return;
}
// xinef: special exception for surge of light, dont affect crit chance if previous mods were not applied
else if (mod->op == SPELLMOD_CRITICAL_CHANCE && spell && !HasSpellMod(mod, spell))
{
return;
}
// xinef: special case for backdraft gcd reduce with backlast time reduction, dont affect gcd if cast time was not applied
else if (mod->op == SPELLMOD_GLOBAL_COOLDOWN && spell && !HasSpellMod(mod, spell))
{
return;
}
// xinef: those two mods should be multiplicative (Glyph of Renew)
if (mod->op == SPELLMOD_DAMAGE || mod->op == SPELLMOD_DOT)
{
totalmul *= CalculatePct(1.0f, 100.0f + mod->value);
}
else
{
totalmul += CalculatePct(1.0f, mod->value);
}
}
DropModCharge(mod, spell);
};
// Drop charges for triggering spells instead of triggered ones
if (m_spellModTakingSpell)
{
spell = m_spellModTakingSpell;
}
SpellModifier* chargedMod = nullptr;
for (auto mod : m_spellMods[op])
switch (op)
{
// Charges can be set only for mods with auras
if (!mod->ownerAura)
// special case, if a mod makes spell instant, only consume that mod
case SPELLMOD_CASTING_TIME:
{
ASSERT(!mod->charges);
}
if (!IsAffectedBySpellmod(spellInfo, mod, spell))
{
continue;
}
if (mod->ownerAura->IsUsingCharges())
{
if (!chargedMod || (chargedMod->ownerAura->GetSpellInfo()->SpellPriority < mod->ownerAura->GetSpellInfo()->SpellPriority))
SpellModifier* modInstantSpell = nullptr;
for (SpellModifier* mod : m_spellMods[SPELLMOD_CASTING_TIME])
{
chargedMod = mod;
if (!IsAffectedBySpellmod(spellInfo, mod, spell))
{
continue;
}
if (mod->type == SPELLMOD_PCT && basevalue < T(10000) && mod->value <= -100)
{
modInstantSpell = mod;
break;
}
}
continue;
if (modInstantSpell)
{
Player::ApplyModToSpell(modInstantSpell, spell);
basevalue = T(0);
return;
}
break;
}
calculateSpellMod(mod);
// special case if two mods apply 100% critical chance, only consume one
case SPELLMOD_CRITICAL_CHANCE:
{
SpellModifier* modCritical = nullptr;
for (auto mod : m_spellMods[SPELLMOD_CRITICAL_CHANCE])
{
if (!IsAffectedBySpellmod(spellInfo, mod, spell))
{
continue;
}
if (mod->type == SPELLMOD_FLAT && mod->value >= 100)
{
modCritical = mod;
break;
}
}
if (modCritical)
{
Player::ApplyModToSpell(modCritical, spell);
basevalue = T(100);
return;
}
break;
}
default:
break;
}
if (chargedMod)
for (auto mod : m_spellMods[op])
{
calculateSpellMod(chargedMod);
}
if (!IsAffectedBySpellmod(spellInfo, mod, spell))
continue;
switch (mod->type)
{
case SPELLMOD_FLAT:
totalflat += mod->value;
break;
case SPELLMOD_PCT:
{
// skip percent mods for null basevalue (most important for spell mods with charges)
if (basevalue == T(0))
{
continue;
}
// special case (skip > 10s spell casts for instant cast setting)
if (op == SPELLMOD_CASTING_TIME)
{
if (mod->value <= -100 && basevalue >= T(10000))
{
continue;
}
}
totalmul += CalculatePct(1.f, mod->value);
break;
}
}
/*// xinef: special exception for surge of light, dont affect crit chance if previous mods were not applied
else if (mod->op == SPELLMOD_CRITICAL_CHANCE && spell && !HasSpellMod(mod, spell))
continue;
// xinef: special case for backdraft gcd reduce with backlast time reduction, dont affect gcd if cast time was not applied
else if (mod->op == SPELLMOD_GLOBAL_COOLDOWN && spell && !HasSpellMod(mod, spell))
continue;
// xinef: those two mods should be multiplicative (Glyph of Renew)
if (mod->op == SPELLMOD_DAMAGE || mod->op == SPELLMOD_DOT)
totalmul *= CalculatePct(1.0f, 100.0f + mod->value);
else
totalmul += CalculatePct(1.0f, mod->value);*/
Player::ApplyModToSpell(mod, spell);
}
float diff = 0.0f;
if (op == SPELLMOD_CASTING_TIME || op == SPELLMOD_DURATION)
{
diff = ((float)basevalue + totalflat) * (totalmul - 1.0f) + (float)totalflat;
}
else
{
diff = (float)basevalue * (totalmul - 1.0f) + (float)totalflat;
}
basevalue = T((float)basevalue + diff);
return T(diff);
}
#endif