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

@@ -764,7 +764,7 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
case DAMAGE_LAVA:
case DAMAGE_SLIME:
{
DamageInfo dmgInfo(this, this, damage, nullptr, type == DAMAGE_LAVA ? SPELL_SCHOOL_MASK_FIRE : SPELL_SCHOOL_MASK_NATURE, DIRECT_DAMAGE);
DamageInfo dmgInfo(this, this, damage, nullptr, type == DAMAGE_LAVA ? SPELL_SCHOOL_MASK_FIRE : SPELL_SCHOOL_MASK_NATURE, DIRECT_DAMAGE, BASE_ATTACK);
Unit::CalcAbsorbResist(dmgInfo);
absorb = dmgInfo.GetAbsorb();
resist = dmgInfo.GetResist();
@@ -7058,21 +7058,22 @@ void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply,
}
}
void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx)
void Player::CastItemCombatSpell(DamageInfo const& damageInfo)
{
Unit* target = damageInfo.GetVictim();
if (!target || !target->IsAlive() || target == this)
return;
// Xinef: do not use disarmed weapons, special exception - shaman ghost wolf form
// Xinef: normal forms proc on hit enchants / built in item bonuses
if (!CanUseAttackType(attType) || GetShapeshiftForm() == FORM_GHOSTWOLF)
if (!CanUseAttackType(damageInfo.GetAttackType()) || GetShapeshiftForm() == FORM_GHOSTWOLF)
return;
for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
{
// If usable, try to cast item spell
if (Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
if (!item->IsBroken())
if (!item->IsBroken() && CanUseAttackType(damageInfo.GetAttackType()))
if (ItemTemplate const* proto = item->GetTemplate())
{
// Additional check for weapons
@@ -7080,7 +7081,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
{
// offhand item cannot proc from main hand hit etc
EquipmentSlots slot;
switch (attType)
switch (damageInfo.GetAttackType())
{
case BASE_ATTACK:
slot = EQUIPMENT_SLOT_MAINHAND;
@@ -7099,19 +7100,20 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
continue;
}
CastItemCombatSpell(target, attType, procVictim, procEx, item, proto);
CastItemCombatSpell(damageInfo, item, proto);
}
}
}
void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto)
void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemTemplate const* proto)
{
if (!sScriptMgr->CanCastItemCombatSpell(this, target, attType, procVictim, procEx, item, proto))
return;
// if (!sScriptMgr->CanCastItemCombatSpell(this, target, attType, procVictim, procEx, item, proto))
// return;
// Can do effect if any damage done to target
if (procVictim & PROC_FLAG_TAKEN_DAMAGE)
//if (damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE)
// for done procs allow normal + critical + absorbs by default
bool canTrigger = (damageInfo.GetHitMask() & (PROC_HIT_NORMAL | PROC_HIT_CRITICAL | PROC_HIT_ABSORB)) != 0;
if (canTrigger)
{
for (uint8 i = 0; i < MAX_ITEM_SPELLS; ++i)
{
@@ -7132,11 +7134,15 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
continue;
}
// not allow proc extra attack spell at extra attack
if (m_extraAttacks && spellInfo->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
return;
float chance = (float)spellInfo->ProcChance;
if (spellData.SpellPPMRate)
{
uint32 WeaponSpeed = GetAttackTime(attType);
uint32 WeaponSpeed = GetAttackTime(damageInfo.GetAttackType());
chance = GetPPMProcChance(WeaponSpeed, spellData.SpellPPMRate, spellInfo);
}
else if (chance > 100.0f)
@@ -7144,8 +7150,8 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
chance = GetWeaponProcChance();
}
if (roll_chance_f(chance) && sScriptMgr->OnCastItemCombatSpell(this, target, spellInfo, item))
CastSpell(target, spellInfo->Id, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD), item);
if (roll_chance_f(chance)/* && sScriptMgr->OnCastItemCombatSpell(this, target, spellInfo, item)*/)
CastSpell(damageInfo.GetVictim(), spellInfo->Id, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD), item);
}
}
@@ -7167,14 +7173,14 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
if (entry && entry->procEx)
{
// Check hit/crit/dodge/parry requirement
if ((entry->procEx & procEx) == 0)
if ((entry->procEx & damageInfo.GetHitMask()) == 0)
continue;
}
else
{
// Can do effect if any damage done to target
if (!(procVictim & PROC_FLAG_TAKEN_DAMAGE))
//if (!(damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE))
// for done procs allow normal + critical + absorbs by default
if (!canTrigger)
continue;
}
@@ -7197,7 +7203,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
}
// Apply spell mods
ApplySpellMod(pEnchant->spellid[s], SPELLMOD_CHANCE_OF_SUCCESS, chance);
ApplySpellMod<SPELLMOD_CHANCE_OF_SUCCESS>(pEnchant->spellid[s], chance);
// Shiv has 100% chance to apply the poison
if (FindCurrentSpellBySpellId(5938) && e_slot == TEMP_ENCHANTMENT_SLOT)
@@ -7220,7 +7226,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
if (spellInfo->IsPositive())
CastSpell(this, spellInfo, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD), item);
else
CastSpell(target, spellInfo, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD), item);
CastSpell(damageInfo.GetVictim(), spellInfo, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD), item);
}
}
}
@@ -9565,9 +9571,11 @@ bool Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod
if (!mod || !spellInfo)
return false;
// Mod out of charges
if (spell && mod->charges == -1 && spell->m_appliedMods.find(mod->ownerAura) == spell->m_appliedMods.end())
// First time this aura applies a mod to us and is out of charges
if (spell && mod->ownerAura->IsUsingCharges() && !mod->ownerAura->GetCharges() && !spell->m_appliedMods.count(mod->ownerAura))
{
return false;
}
// +duration to infinite duration spells making them limited
if (mod->op == SPELLMOD_DURATION && spellInfo->GetDuration() == -1)
@@ -9609,50 +9617,46 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
LOG_DEBUG("spells.aura", "Player::AddSpellMod {}", mod->spellId);
uint16 Opcode = (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER;
int i = 0;
flag96 _mask = 0;
for (int eff = 0; eff < 96; ++eff)
flag96 modMask;
for (uint8 i = 0; i < 3; ++i)
{
if (eff != 0 && eff % 32 == 0)
_mask[i++] = 0;
_mask[i] = uint32(1) << (eff - (32 * i));
if (mod->mask & _mask)
for (uint32 eff = 0; eff < 32; ++eff)
{
int32 val = 0;
for (SpellModList::iterator itr = m_spellMods[mod->op].begin(); itr != m_spellMods[mod->op].end(); ++itr)
modMask[i] = uint32(1) << eff;
if ((mod->mask & modMask))
{
if ((*itr)->type == mod->type && (*itr)->mask & _mask)
val += (*itr)->value;
int32 val = 0;
for (SpellModifier* spellMod : m_spellMods[mod->op])
{
if (spellMod->type == mod->type && (spellMod->mask & modMask))
{
val += spellMod->value;
}
}
val += apply ? mod->value : -(mod->value);
WorldPacket data(Opcode, (1 + 1 + 4));
data << uint8(eff + 32 * i);
data << uint8(mod->op);
data << int32(val);
SendDirectMessage(&data);
}
val += apply ? mod->value : -(mod->value);
WorldPacket data(Opcode, (1 + 1 + 4));
data << uint8(eff);
data << uint8(mod->op);
data << int32(val);
SendDirectMessage(&data);
}
modMask[i] = 0;
}
if (apply)
{
m_spellMods[mod->op].push_back(mod);
if (getClass() == CLASS_MAGE)
m_spellMods[mod->op].sort(MageSpellModPred());
else
m_spellMods[mod->op].sort(SpellModPred());
m_spellMods[mod->op].insert(mod);
}
else
{
m_spellMods[mod->op].remove(mod);
// mods bound to aura will be removed in AuraEffect::~AuraEffect
if (!mod->ownerAura)
delete mod;
m_spellMods[mod->op].erase(mod);
}
}
// Restore spellmods in case of failed cast
void Player::RestoreSpellMods(Spell* spell, uint32 ownerAuraId, Aura* aura)
void Player::RestoreSpellMods(Spell* spell, uint32 ownerAuraId /*= 0*/, Aura* aura /*= nullptr*/)
{
if (!spell || spell->m_appliedMods.empty())
return;
@@ -9661,16 +9665,16 @@ void Player::RestoreSpellMods(Spell* spell, uint32 ownerAuraId, Aura* aura)
for (uint8 i = 0; i < MAX_SPELLMOD; ++i)
{
for (SpellModList::iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end(); ++itr)
for (auto itr = m_spellMods[i].begin(); itr != m_spellMods[i].end(); ++itr)
{
SpellModifier* mod = *itr;
// Spellmods without aura set cannot be charged
if (!mod->ownerAura || !mod->ownerAura->IsUsingCharges())
// Spellmods without charged aura set cannot be charged
if (!mod->ownerAura->IsUsingCharges())
continue;
// Restore only specific owner aura mods
if (ownerAuraId && (ownerAuraId != mod->ownerAura->GetSpellInfo()->Id))
if (ownerAuraId && mod->spellId != ownerAuraId)
continue;
if (aura && mod->ownerAura != aura)
@@ -9691,27 +9695,14 @@ void Player::RestoreSpellMods(Spell* spell, uint32 ownerAuraId, Aura* aura)
// only see the first of its modifier restored)
aurasQueue.push_back(mod->ownerAura);
// add mod charges back to mod
if (mod->charges == -1)
mod->charges = 1;
else
mod->charges++;
// Do not set more spellmods than available
if (mod->ownerAura->GetCharges() < mod->charges)
mod->charges = mod->ownerAura->GetCharges();
// Skip this check for now - aura charges may change due to various reason
/// @todo track these changes correctly
//ASSERT (mod->ownerAura->GetCharges() <= mod->charges);
// add charges back to aura
mod->ownerAura->ModCharges(1);
}
}
for (std::list<Aura*>::iterator itr = aurasQueue.begin(); itr != aurasQueue.end(); ++itr)
for (Aura* aura : aurasQueue)
{
Spell::UsedSpellMods::iterator iterMod = spell->m_appliedMods.find(*itr);
if (iterMod != spell->m_appliedMods.end())
spell->m_appliedMods.erase(iterMod);
spell->m_appliedMods.erase(aura);
}
// Xinef: clear the list just do be sure
@@ -9719,77 +9710,32 @@ void Player::RestoreSpellMods(Spell* spell, uint32 ownerAuraId, Aura* aura)
spell->m_appliedMods.clear();
}
void Player::RestoreAllSpellMods(uint32 ownerAuraId, Aura* aura)
void Player::RestoreAllSpellMods(uint32 ownerAuraId /*= 0*/, Aura* aura /*= nullptr*/)
{
for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i)
if (m_currentSpells[i])
RestoreSpellMods(m_currentSpells[i], ownerAuraId, aura);
if (Spell* spell = m_currentSpells[i])
RestoreSpellMods(spell, ownerAuraId, aura);
}
void Player::RemoveSpellMods(Spell* spell)
void Player::ApplyModToSpell(SpellModifier* mod, Spell* spell)
{
if (!spell)
return;
if (spell->m_appliedMods.empty())
// don't do anything with no charges
if (mod->ownerAura->IsUsingCharges() && !mod->ownerAura->GetCharges())
return;
SpellInfo const* const spellInfo = spell->m_spellInfo;
for (uint8 i = 0; i < MAX_SPELLMOD; ++i)
{
for (SpellModList::const_iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end();)
{
SpellModifier* mod = *itr;
++itr;
// spellmods without aura set cannot be charged
if (!mod->ownerAura || !mod->ownerAura->IsUsingCharges())
continue;
// check if mod affected this spell
Spell::UsedSpellMods::iterator iterMod = spell->m_appliedMods.find(mod->ownerAura);
if (iterMod == spell->m_appliedMods.end())
continue;
// remove from list
// leave this here, if spell have two mods it will remove 2 charges - wrong
spell->m_appliedMods.erase(iterMod);
// MAGE T8P4 BONUS
if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE )
{
SpellInfo const* sp = mod->ownerAura->GetSpellInfo();
// Missile Barrage, Hot Streak, Brain Freeze (trigger spell - Fireball!)
if( sp->SpellIconID == 3261 || sp->SpellIconID == 2999 || sp->SpellIconID == 2938 )
if( AuraEffect* aurEff = GetAuraEffectDummy(64869) )
if( roll_chance_i(aurEff->GetAmount()) )
{
mod->charges = 1;
continue;
}
}
if (mod->ownerAura->DropCharge(AURA_REMOVE_BY_EXPIRE))
itr = m_spellMods[i].begin();
}
}
// register inside spell, proc system uses this to drop charges
spell->m_appliedMods.insert(mod->ownerAura);
}
void Player::DropModCharge(SpellModifier* mod, Spell* spell)
bool Player::HasSpellModApplied(SpellModifier* mod, Spell* spell)
{
// don't handle spells with proc_event entry defined
// this is a temporary workaround, because all spellmods should be handled like that
if (sSpellMgr->GetSpellProcEvent(mod->spellId))
return;
if (!spell)
return false;
if (spell && mod->ownerAura && mod->charges > 0)
{
if (--mod->charges == 0)
mod->charges = -1;
spell->m_appliedMods.insert(mod->ownerAura);
}
return spell->m_appliedMods.count(mod->ownerAura) != 0;
}
void Player::SetSpellModTakingSpell(Spell* spell, bool apply)
@@ -10687,7 +10633,7 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite
if (rec > 0)
{
int32 oldRec = rec;
ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, rec, spell);
ApplySpellMod<SPELLMOD_COOLDOWN>(spellInfo->Id, rec, spell);
if (oldRec != rec)
{
useSpellCooldown = true;
@@ -10696,7 +10642,7 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite
if (catrec > 0 && !spellInfo->HasAttribute(SPELL_ATTR6_NO_CATEGORY_COOLDOWN_MODS))
{
ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, catrec, spell);
ApplySpellMod<SPELLMOD_COOLDOWN>(spellInfo->Id, catrec, spell);
}
if (int32 cooldownMod = GetTotalAuraModifier(SPELL_AURA_MOD_COOLDOWN))
@@ -11472,6 +11418,7 @@ void Player::ApplyEquipCooldown(Item* pItem)
if (pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_NO_EQUIP_COOLDOWN))
return;
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
{
_Spell const& spellData = pItem->GetTemplate()->Spells[i];
@@ -11480,11 +11427,15 @@ void Player::ApplyEquipCooldown(Item* pItem)
if (!spellData.SpellId)
continue;
// xinef: apply hidden cooldown for procs
// apply proc cooldown to equip auras if we have any
if (spellData.SpellTrigger == ITEM_SPELLTRIGGER_ON_EQUIP)
{
// xinef: uint32(-1) special marker for proc cooldowns
AddSpellCooldown(spellData.SpellId, uint32(-1), 30 * IN_MILLISECONDS);
SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(spellData.SpellId);
if (!procEntry)
continue;
if (Aura* itemAura = GetAura(spellData.SpellId, GetGUID(), pItem->GetGUID()))
itemAura->AddProcCooldown(now + procEntry->Cooldown);
continue;
}