diff options
| author | Treeston <treeston.mmoc@gmail.com> | 2017-12-30 20:28:41 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-12-30 20:28:41 +0100 |
| commit | d507a7e3388382960108b24143da48e5f912b4a7 (patch) | |
| tree | b4e3e62094e853cc8551126de438815779411cb7 /src/server/game | |
| parent | 671a34a966aefa409966f6eb86f88ce671be9b36 (diff) | |
[3.3.5] CastSpell unclusterfucking (that's a word now) (#21123)
Core/Spell: The giant CastSpell unclusterfucking (that's a word now) of this generation.
- CastSpell now always takes three arguments - target, spellId, and a struct containing extra arguments
- This struct (CastSpellExtraArgs, see SpellDefines.h) serves as a conglomerate of every previous combination of the 20 billion different CastSpell overloads, all merged into one
- It has some great utility constructors - check them out! All of these can be used to implicitly construct the ExtraArgs object.
- A gajillion refactors to make everything behave the way it always has
Diffstat (limited to 'src/server/game')
23 files changed, 557 insertions, 575 deletions
diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp index abbff7a870b..3f979c5dbe3 100644 --- a/src/server/game/AI/CoreAI/PassiveAI.cpp +++ b/src/server/game/AI/CoreAI/PassiveAI.cpp @@ -99,7 +99,11 @@ int32 CritterAI::Permissible(Creature const* creature) void TriggerAI::IsSummonedBy(Unit* summoner) { if (me->m_spells[0]) - me->CastSpell(me, me->m_spells[0], false, nullptr, nullptr, summoner->GetGUID()); + { + CastSpellExtraArgs extra; + extra.OriginalCaster = summoner->GetGUID(); + me->CastSpell(me, me->m_spells[0], extra); + } } int32 TriggerAI::Permissible(Creature const* creature) diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 98841effb3b..95c6c0dd026 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -243,7 +243,7 @@ void PetAI::UpdateAI(uint32 diff) SpellCastTargets targets; targets.SetUnitTarget(target); - spell->prepare(&targets); + spell->prepare(targets); } // deleted cached Spell objects diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp index 244b0b5e047..a4b2e28dfd6 100644 --- a/src/server/game/AI/CoreAI/UnitAI.cpp +++ b/src/server/game/AI/CoreAI/UnitAI.cpp @@ -169,28 +169,18 @@ void UnitAI::DoCast(uint32 spellId) me->CastSpell(target, spellId, false); } -void UnitAI::DoCast(Unit* victim, uint32 spellId, bool triggered) +void UnitAI::DoCast(Unit* victim, uint32 spellId, CastSpellExtraArgs const& args) { - if (!victim || (me->HasUnitState(UNIT_STATE_CASTING) && !triggered)) + if (me->HasUnitState(UNIT_STATE_CASTING) && !(args.TriggerFlags & TRIGGERED_IGNORE_CAST_IN_PROGRESS)) return; - me->CastSpell(victim, spellId, triggered); + me->CastSpell(victim, spellId, args); } -void UnitAI::DoCastVictim(uint32 spellId, bool triggered) +void UnitAI::DoCastVictim(uint32 spellId, CastSpellExtraArgs const& args) { - if (!me->GetVictim() || (me->HasUnitState(UNIT_STATE_CASTING) && !triggered)) - return; - - me->CastSpell(me->GetVictim(), spellId, triggered); -} - -void UnitAI::DoCastAOE(uint32 spellId, bool triggered) -{ - if (!triggered && me->HasUnitState(UNIT_STATE_CASTING)) - return; - - me->CastSpell(nullptr, spellId, triggered); + if (Unit* victim = me->GetVictim()) + DoCast(victim, spellId, args); } uint32 UnitAI::GetDialogStatus(Player* /*player*/) diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index 345495579e1..9bd9836fe44 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -22,6 +22,7 @@ #include "Containers.h" #include "EventMap.h" #include "ObjectGuid.h" +#include "SpellDefines.h" #include "ThreatManager.h" #define CAST_AI(a, b) (dynamic_cast<a*>(b)) @@ -294,10 +295,10 @@ class TC_GAME_API UnitAI void AttackStartCaster(Unit* victim, float dist); void DoCast(uint32 spellId); - void DoCast(Unit* victim, uint32 spellId, bool triggered = false); - void DoCastSelf(uint32 spellId, bool triggered = false) { DoCast(me, spellId, triggered); } - void DoCastVictim(uint32 spellId, bool triggered = false); - void DoCastAOE(uint32 spellId, bool triggered = false); + void DoCast(Unit* victim, uint32 spellId, CastSpellExtraArgs const& args = {}); + void DoCastSelf(uint32 spellId, CastSpellExtraArgs const& args = {}) { DoCast(me, spellId, args); } + void DoCastVictim(uint32 spellId, CastSpellExtraArgs const& args = {}); + void DoCastAOE(uint32 spellId, CastSpellExtraArgs const& args = {}) { DoCast(nullptr, spellId, args); } float DoGetSpellMaxRange(uint32 spellId, bool positive = false); diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp index a103b34ff56..ded7a97122e 100644 --- a/src/server/game/AI/PlayerAI/PlayerAI.cpp +++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp @@ -690,7 +690,7 @@ void PlayerAI::DoCastAtTarget(TargetedSpell spell) { SpellCastTargets targets; targets.SetUnitTarget(spell.second); - spell.first->prepare(&targets); + spell.first->prepare(targets); } void PlayerAI::DoRangedAttackIfReady() diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index afa7e789b7a..8b2d0b0e410 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -183,7 +183,7 @@ void ScriptedAI::DoCastSpell(Unit* target, SpellInfo const* spellInfo, bool trig return; me->StopMoving(); - me->CastSpell(target, spellInfo, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE); + me->CastSpell(target, spellInfo->Id, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE); } void ScriptedAI::DoPlaySoundToSet(WorldObject* source, uint32 soundId) diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 9b1878b24d4..24f3a510859 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1908,8 +1908,7 @@ void GameObject::Use(Unit* user) if (!spellId) return; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) + if (!sSpellMgr->GetSpellInfo(spellId)) { if (user->GetTypeId() != TYPEID_PLAYER || !sOutdoorPvPMgr->HandleCustomSpell(user->ToPlayer(), spellId, this)) TC_LOG_ERROR("misc", "WORLD: unknown spell id %u at use action for gameobject (Entry: %u GoType: %u)", spellId, GetEntry(), GetGoType()); @@ -1922,7 +1921,7 @@ void GameObject::Use(Unit* user) sOutdoorPvPMgr->HandleCustomSpell(player, spellId, this); if (spellCaster) - spellCaster->CastSpell(user, spellInfo, triggered); + spellCaster->CastSpell(user, spellId, triggered); else CastSpell(user, spellId); } @@ -1951,7 +1950,7 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, TriggerCastFlags trigge if (self) { if (target) - target->CastSpell(target, spellInfo, triggered); + target->CastSpell(target, spellInfo->Id, triggered); return; } @@ -1963,6 +1962,8 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, TriggerCastFlags trigge // remove immunity flags, to allow spell to target anything trigger->SetImmuneToAll(false); + CastSpellExtraArgs args; + args.TriggerFlags = triggered; if (Unit* owner = GetOwner()) { trigger->SetFaction(owner->GetFaction()); @@ -1972,14 +1973,17 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, TriggerCastFlags trigge trigger->SetByteValue(UNIT_FIELD_BYTES_2, 1, owner->GetByteValue(UNIT_FIELD_BYTES_2, 1)); // needed for GO casts for proper target validation checks trigger->SetOwnerGUID(owner->GetGUID()); - trigger->CastSpell(target ? target : trigger, spellInfo, triggered, nullptr, nullptr, owner->GetGUID()); + + args.OriginalCaster = owner->GetGUID(); + trigger->CastSpell(target ? target : trigger, spellInfo->Id, args); } else { trigger->SetFaction(spellInfo->IsPositive() ? FACTION_FRIENDLY : FACTION_MONSTER); // Set owner guid for target if no owner available - needed by trigger auras // - trigger gets despawned and there's no caster avalible (see AuraEffect::TriggerSpell()) - trigger->CastSpell(target ? target : trigger, spellInfo, triggered, nullptr, nullptr, target ? target->GetGUID() : ObjectGuid::Empty); + args.OriginalCaster = target ? target->GetGUID() : ObjectGuid::Empty; + trigger->CastSpell(target ? target : trigger, spellInfo->Id, args); } } diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 96e9746bbbe..797762867ca 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -1870,13 +1870,13 @@ void Pet::CastPetAura(PetAura const* aura) if (!auraId) return; + CastSpellExtraArgs args; + args.TriggerFlags = TRIGGERED_FULL_MASK; + if (auraId == 35696) // Demonic Knowledge - { - int32 basePoints = CalculatePct(aura->GetDamage(), GetStat(STAT_STAMINA) + GetStat(STAT_INTELLECT)); - CastCustomSpell(this, auraId, &basePoints, nullptr, nullptr, true); - } - else - CastSpell(this, auraId, true); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, CalculatePct(aura->GetDamage(), GetStat(STAT_STAMINA) + GetStat(STAT_INTELLECT))); + + CastSpell(this, auraId, args); } bool Pet::IsPetAura(Aura const* aura) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 26ea8582f23..ab5f4618d7a 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -7679,7 +7679,7 @@ void Player::ApplyItemObtainSpells(Item* item, bool apply) if (apply) { if (!HasAura(spellId)) - CastSpell(this, spellId, true, item); + CastSpell(this, spellId, item); } else RemoveAurasDueToSpell(spellId); @@ -7813,7 +7813,7 @@ void Player::ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, TC_LOG_DEBUG("entities.player", "Player::ApplyEquipSpell: Player '%s' (%s) cast %s equip spell (ID: %i)", GetName().c_str(), GetGUID().ToString().c_str(), (item ? "item" : "itemset"), spellInfo->Id); - CastSpell(this, spellInfo, true, item); + CastSpell(this, spellInfo->Id, item); } else { @@ -7953,7 +7953,7 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT chance = GetWeaponProcChance(); if (roll_chance_f(chance) && sScriptMgr->OnCastItemCombatSpell(this, damageInfo.GetVictim(), spellInfo, item)) - CastSpell(damageInfo.GetVictim(), spellInfo->Id, true, item); + CastSpell(damageInfo.GetVictim(), spellInfo->Id, item); } } @@ -8017,8 +8017,8 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT { Unit* target = spellInfo->IsPositive() ? this : damageInfo.GetVictim(); + CastSpellExtraArgs args(item); // reduce effect values if enchant is limited - CustomSpellValues values; if (entry && (entry->AttributesMask & ENCHANT_PROC_ATTR_LIMIT_60) && target->getLevel() > 60) { int32 const lvlDifference = target->getLevel() - 60; @@ -8029,11 +8029,10 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (spellInfo->Effects[i].IsEffect()) - values.AddSpellMod(static_cast<SpellValueMod>(SPELLVALUE_BASE_POINT0 + i), CalculatePct(spellInfo->Effects[i].CalcValue(this), effectPct)); + args.SpellValueOverrides.AddMod(static_cast<SpellValueMod>(SPELLVALUE_BASE_POINT0 + i), CalculatePct(spellInfo->Effects[i].CalcValue(this), effectPct)); } } - - CastCustomSpell(spellInfo->Id, values, target, TRIGGERED_FULL_MASK, item); + CastSpell(target, spellInfo->Id, args); } } } @@ -8060,7 +8059,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 spell->m_CastItem = item; spell->m_cast_count = cast_count; //set count of casts spell->SetSpellValue(SPELLVALUE_BASE_POINT0, learning_spell_id); - spell->prepare(&targets); + spell->prepare(targets); return; } @@ -8088,7 +8087,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 spell->m_CastItem = item; spell->m_cast_count = cast_count; // set count of casts spell->m_glyphIndex = glyphIndex; // glyph index - spell->prepare(&targets); + spell->prepare(targets); return; } @@ -8115,7 +8114,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 spell->m_CastItem = item; spell->m_cast_count = cast_count; // set count of casts spell->m_glyphIndex = glyphIndex; // glyph index - spell->prepare(&targets); + spell->prepare(targets); return; } } @@ -13664,11 +13663,14 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool } } } + + CastSpellExtraArgs args(item); // Cast custom spell vs all equal basepoints got from enchant_amount if (basepoints) - CastCustomSpell(this, enchant_spell_id, &basepoints, &basepoints, &basepoints, true, item); - else - CastSpell(this, enchant_spell_id, true, item); + for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + args.SpellValueOverrides.AddMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + i), basepoints); + + CastSpell(this, enchant_spell_id, args); } else RemoveAurasDueToItemSpell(enchant_spell_id, item->GetGUID()); @@ -14291,7 +14293,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men break; case GOSSIP_OPTION_SPIRITHEALER: if (isDead()) - source->ToCreature()->CastSpell(source->ToCreature(), 17251, true, nullptr, nullptr, GetGUID()); + source->ToCreature()->CastSpell(source->ToCreature(), 17251, GetGUID()); break; case GOSSIP_OPTION_QUESTGIVER: PrepareQuestMenu(guid); @@ -14312,8 +14314,8 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men { // Cast spells that teach dual spec // Both are also ImplicitTarget self and must be cast by player - CastSpell(this, 63680, true, nullptr, nullptr, GetGUID()); - CastSpell(this, 63624, true, nullptr, nullptr, GetGUID()); + CastSpell(this, 63680, GetGUID()); + CastSpell(this, 63624, GetGUID()); PrepareGossipMenu(source, menuItemData->GossipActionMenuId); SendPreparedGossip(source); @@ -23744,11 +23746,11 @@ void Player::ResurrectUsingRequestData() if (uint32 aura = _resurrectionData->Aura) { - CastSpell(this, aura, true, nullptr, nullptr, _resurrectionData->GUID); + CastSpell(this, aura, _resurrectionData->GUID); return; } - /// Teleport before resurrecting by player, otherwise the player might get attacked from creatures near his corpse + // Teleport before resurrecting by player, otherwise the player might get attacked from creatures near his corpse TeleportTo(_resurrectionData->Location); if (IsBeingTeleported()) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index b67406eba74..a3332fe5ca0 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -958,133 +958,46 @@ void Unit::CastStop(uint32 except_spellid) InterruptSpell(CurrentSpellTypes(i), false); } -void Unit::CastSpell(SpellCastTargets const& targets, SpellInfo const* spellInfo, CustomSpellValues const* value, TriggerCastFlags triggerFlags, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) +void Unit::CastSpell(SpellCastTargets const& targets, uint32 spellId, CastSpellExtraArgs const& args) { - if (!spellInfo) + SpellInfo const* info = sSpellMgr->GetSpellInfo(spellId); + if (!info) { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell by caster: %s %u)", (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUID().GetCounter() : GetEntry())); + TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell %u by caster %s", spellId, GetGUID().ToString().c_str()); return; } - Spell* spell = new Spell(this, spellInfo, triggerFlags, originalCaster); - - if (value) - for (CustomSpellValues::const_iterator itr = value->begin(); itr != value->end(); ++itr) - spell->SetSpellValue(itr->first, itr->second); - - spell->m_CastItem = castItem; - spell->prepare(&targets, triggeredByAura); -} - -void Unit::CastSpell(Unit* victim, uint32 spellId, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) -{ - CastSpell(victim, spellId, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster); -} - -void Unit::CastSpell(Unit* victim, uint32 spellId, TriggerCastFlags triggerFlags /*= TRIGGER_NONE*/, Item* castItem /*= nullptr*/, AuraEffect const* triggeredByAura /*= nullptr*/, ObjectGuid originalCaster /*= ObjectGuid::Empty*/) -{ - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) - { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUID().GetCounter() : GetEntry())); - return; - } - - CastSpell(victim, spellInfo, triggerFlags, castItem, triggeredByAura, originalCaster); -} - -void Unit::CastSpell(Unit* victim, SpellInfo const* spellInfo, bool triggered, Item* castItem/*= nullptr*/, AuraEffect const* triggeredByAura /*= nullptr*/, ObjectGuid originalCaster /*= ObjectGuid::Empty*/) -{ - CastSpell(victim, spellInfo, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster); -} - -void Unit::CastSpell(Unit* victim, SpellInfo const* spellInfo, TriggerCastFlags triggerFlags, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) -{ - SpellCastTargets targets; - targets.SetUnitTarget(victim); - CastSpell(targets, spellInfo, nullptr, triggerFlags, castItem, triggeredByAura, originalCaster); -} - -void Unit::CastCustomSpell(Unit* target, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) -{ - CustomSpellValues values; - if (bp0) - values.AddSpellMod(SPELLVALUE_BASE_POINT0, *bp0); - if (bp1) - values.AddSpellMod(SPELLVALUE_BASE_POINT1, *bp1); - if (bp2) - values.AddSpellMod(SPELLVALUE_BASE_POINT2, *bp2); - CastCustomSpell(spellId, values, target, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster); -} - -void Unit::CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* target, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) -{ - CustomSpellValues values; - values.AddSpellMod(mod, value); - CastCustomSpell(spellId, values, target, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster); -} - -void Unit::CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* target, TriggerCastFlags triggerFlags, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) -{ - CustomSpellValues values; - values.AddSpellMod(mod, value); - CastCustomSpell(spellId, values, target, triggerFlags, castItem, triggeredByAura, originalCaster); -} - -void Unit::CastCustomSpell(uint32 spellId, CustomSpellValues const& value, Unit* victim, TriggerCastFlags triggerFlags, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) -{ - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) - { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUID().GetCounter() : GetEntry())); - return; - } - SpellCastTargets targets; - targets.SetUnitTarget(victim); + Spell* spell = new Spell(this, info, args.TriggerFlags, args.OriginalCaster); + for (auto const& pair : args.SpellValueOverrides) + spell->SetSpellValue(pair.first, pair.second); - CastSpell(targets, spellInfo, &value, triggerFlags, castItem, triggeredByAura, originalCaster); + spell->m_CastItem = args.CastItem; + spell->prepare(targets, args.TriggeringAura); } -void Unit::CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) +void Unit::CastSpell(WorldObject* target, uint32 spellId, CastSpellExtraArgs const& args) { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) - { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUID().GetCounter() : GetEntry())); - return; - } SpellCastTargets targets; - targets.SetDst(x, y, z, GetOrientation()); - - CastSpell(targets, spellInfo, nullptr, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster); -} - -void Unit::CastSpell(float x, float y, float z, uint32 spellId, TriggerCastFlags triggerFlags, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) -{ - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) + if (target) { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUID().GetCounter() : GetEntry())); - return; + if (Unit* unitTarget = target->ToUnit()) + targets.SetUnitTarget(unitTarget); + else if (GameObject* goTarget = target->ToGameObject()) + targets.SetGOTarget(goTarget); + else + { + TC_LOG_ERROR("entities.unit", "CastSpell: Invalid target %s passed to spell cast by %s", target->GetGUID().ToString().c_str(), GetGUID().ToString().c_str()); + return; + } } - SpellCastTargets targets; - targets.SetDst(x, y, z, GetOrientation()); - - CastSpell(targets, spellInfo, nullptr, triggerFlags, castItem, triggeredByAura, originalCaster); + CastSpell(targets, spellId, args); } -void Unit::CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castItem, AuraEffect* triggeredByAura, ObjectGuid originalCaster) +void Unit::CastSpell(Position const& dest, uint32 spellId, CastSpellExtraArgs const& args) { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) - { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUID().GetCounter() : GetEntry())); - return; - } SpellCastTargets targets; - targets.SetGOTarget(go); - - CastSpell(targets, spellInfo, nullptr, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster); + targets.SetDst(dest); + CastSpell(targets, spellId, args); } void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType, bool crit) @@ -3133,7 +3046,7 @@ void Unit::_UpdateAutoRepeatSpell() // we want to shoot Spell* spell = new Spell(this, autoRepeatSpellInfo, TRIGGERED_FULL_MASK); - spell->prepare(&(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_targets)); + spell->prepare(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_targets); // all went good, reset attack resetAttackTimer(RANGED_ATTACK); @@ -6033,7 +5946,7 @@ void Unit::ModifyAuraState(AuraStateType flag, bool apply) if (!spellInfo || !spellInfo->IsPassive()) continue; if (spellInfo->CasterAuraState == uint32(flag)) - CastSpell(this, itr->first, true, nullptr); + CastSpell(this, itr->first, true); } } else if (Pet* pet = ToCreature()->ToPet()) @@ -6046,7 +5959,7 @@ void Unit::ModifyAuraState(AuraStateType flag, bool apply) if (!spellInfo || !spellInfo->IsPassive()) continue; if (spellInfo->CasterAuraState == uint32(flag)) - CastSpell(this, itr->first, true, nullptr); + CastSpell(this, itr->first, true); } } } @@ -10861,7 +10774,7 @@ void CharmInfo::InitPossessCreateSpells() if (spellInfo) { if (spellInfo->IsPassive()) - _unit->CastSpell(_unit, spellInfo, true); + _unit->CastSpell(_unit, spellInfo->Id, true); else AddSpellToActionBar(spellInfo, ACT_PASSIVE, i % MAX_UNIT_ACTION_BAR_INDEX); } @@ -10894,7 +10807,7 @@ void CharmInfo::InitCharmCreateSpells() if (spellInfo->IsPassive()) { - _unit->CastSpell(_unit, spellInfo, true); + _unit->CastSpell(_unit, spellInfo->Id, true); _charmspells[x].SetActionAndType(spellId, ACT_PASSIVE); } else @@ -12125,7 +12038,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) victim->SetUInt32Value(PLAYER_SELF_RES_SPELL, ressSpellId); // FORM_SPIRITOFREDEMPTION and related auras - victim->CastSpell(victim, 27827, true, nullptr, aurEff); + victim->CastSpell(victim, 27827, aurEff); spiritOfRedemption = true; break; } @@ -13656,7 +13569,12 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) } if (IsInMap(caster)) - caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId + 1, target, flags, nullptr, nullptr, origCasterGUID); + { + CastSpellExtraArgs args(flags); + args.OriginalCaster = origCasterGUID; + args.SpellValueOverrides.AddMod(SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1); + caster->CastSpell(target, itr->second.spellId, args); + } else // This can happen during Player::_LoadAuras { int32 bp0[MAX_SPELL_EFFECTS]; @@ -13670,7 +13588,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) else { if (IsInMap(caster)) - caster->CastSpell(target, spellEntry, flags, nullptr, nullptr, origCasterGUID); + caster->CastSpell(target, spellEntry->Id, CastSpellExtraArgs().SetOriginalCaster(origCasterGUID)); else Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, nullptr, nullptr, origCasterGUID); } @@ -13687,7 +13605,9 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) void Unit::EnterVehicle(Unit* base, int8 seatId) { - CastCustomSpell(VEHICLE_SPELL_RIDE_HARDCODED, SPELLVALUE_BASE_POINT0, seatId + 1, base, TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE); + CastSpellExtraArgs args(TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE); + args.SpellValueOverrides.AddBP0(seatId + 1); + CastSpell(base, VEHICLE_SPELL_RIDE_HARDCODED, args); } void Unit::_EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* aurApp) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index af0676ad2af..9659677282a 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -26,6 +26,7 @@ #include "HostileRefManager.h" #include "OptionalFwd.h" #include "SpellAuraDefines.h" +#include "SpellDefines.h" #include "ThreatManager.h" #include "Timer.h" #include "UnitDefines.h" @@ -34,172 +35,6 @@ #define WORLD_TRIGGER 12999 -enum SpellInterruptFlags -{ - SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, // why need this for instant? - SPELL_INTERRUPT_FLAG_PUSH_BACK = 0x02, // push back - SPELL_INTERRUPT_FLAG_UNK3 = 0x04, // any info? - SPELL_INTERRUPT_FLAG_INTERRUPT = 0x08, // interrupt - SPELL_INTERRUPT_FLAG_ABORT_ON_DMG = 0x10 // _complete_ interrupt on direct damage - //SPELL_INTERRUPT_UNK = 0x20 // unk, 564 of 727 spells having this spell start with "Glyph" -}; - -// See SpellAuraInterruptFlags for other values definitions -enum SpellChannelInterruptFlags -{ - CHANNEL_INTERRUPT_FLAG_INTERRUPT = 0x08, // interrupt - CHANNEL_FLAG_DELAY = 0x4000 -}; - -enum SpellAuraInterruptFlags -{ - AURA_INTERRUPT_FLAG_HITBYSPELL = 0x00000001, // 0 removed when getting hit by a negative spell? - AURA_INTERRUPT_FLAG_TAKE_DAMAGE = 0x00000002, // 1 removed by any damage - AURA_INTERRUPT_FLAG_CAST = 0x00000004, // 2 cast any spells - AURA_INTERRUPT_FLAG_MOVE = 0x00000008, // 3 removed by any movement - AURA_INTERRUPT_FLAG_TURNING = 0x00000010, // 4 removed by any turning - AURA_INTERRUPT_FLAG_JUMP = 0x00000020, // 5 removed by entering combat - AURA_INTERRUPT_FLAG_NOT_MOUNTED = 0x00000040, // 6 removed by dismounting - AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7 removed by entering water - AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8 removed by leaving water - AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing - AURA_INTERRUPT_FLAG_TALK = 0x00000400, // 10 talk to npc / loot? action on creature - AURA_INTERRUPT_FLAG_USE = 0x00000800, // 11 mine/use/open action on gameobject - AURA_INTERRUPT_FLAG_MELEE_ATTACK = 0x00001000, // 12 removed by attacking - AURA_INTERRUPT_FLAG_SPELL_ATTACK = 0x00002000, // 13 ??? - AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14 - AURA_INTERRUPT_FLAG_TRANSFORM = 0x00008000, // 15 removed by transform? - AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16 - AURA_INTERRUPT_FLAG_MOUNT = 0x00020000, // 17 misdirect, aspect, swim speed - AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up (used by food and drink mostly and sleep/Fake Death like) - AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported - AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION = 0x00100000, // 20 removed by auras that make you invulnerable, or make other to lose selection on you - AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21 - AURA_INTERRUPT_FLAG_TELEPORTED = 0x00400000, // 22 - AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat - AURA_INTERRUPT_FLAG_DIRECT_DAMAGE = 0x01000000, // 24 removed by any direct damage - AURA_INTERRUPT_FLAG_LANDING = 0x02000000, // 25 removed by hitting the ground - AURA_INTERRUPT_FLAG_LEAVE_COMBAT = 0x80000000, // 31 removed by leaving combat - - AURA_INTERRUPT_FLAG_NOT_VICTIM = (AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE | AURA_INTERRUPT_FLAG_DIRECT_DAMAGE) -}; - -enum SpellModOp : uint8 -{ - SPELLMOD_DAMAGE = 0, - SPELLMOD_DURATION = 1, - SPELLMOD_THREAT = 2, - SPELLMOD_EFFECT1 = 3, - SPELLMOD_CHARGES = 4, - SPELLMOD_RANGE = 5, - SPELLMOD_RADIUS = 6, - SPELLMOD_CRITICAL_CHANCE = 7, - SPELLMOD_ALL_EFFECTS = 8, - SPELLMOD_NOT_LOSE_CASTING_TIME = 9, - SPELLMOD_CASTING_TIME = 10, - SPELLMOD_COOLDOWN = 11, - SPELLMOD_EFFECT2 = 12, - SPELLMOD_IGNORE_ARMOR = 13, - SPELLMOD_COST = 14, - SPELLMOD_CRIT_DAMAGE_BONUS = 15, - SPELLMOD_RESIST_MISS_CHANCE = 16, - SPELLMOD_JUMP_TARGETS = 17, - SPELLMOD_CHANCE_OF_SUCCESS = 18, - SPELLMOD_ACTIVATION_TIME = 19, - SPELLMOD_DAMAGE_MULTIPLIER = 20, - SPELLMOD_GLOBAL_COOLDOWN = 21, - SPELLMOD_DOT = 22, - SPELLMOD_EFFECT3 = 23, - SPELLMOD_BONUS_MULTIPLIER = 24, - // spellmod 25 - SPELLMOD_PROC_PER_MINUTE = 26, - SPELLMOD_VALUE_MULTIPLIER = 27, - SPELLMOD_RESIST_DISPEL_CHANCE = 28, - SPELLMOD_CRIT_DAMAGE_BONUS_2 = 29, //one not used spell - SPELLMOD_SPELL_COST_REFUND_ON_FAIL = 30, - - MAX_SPELLMOD -}; - -enum SpellValueMod : uint8 -{ - SPELLVALUE_BASE_POINT0, - SPELLVALUE_BASE_POINT1, - SPELLVALUE_BASE_POINT2, - SPELLVALUE_RADIUS_MOD, - SPELLVALUE_MAX_TARGETS, - SPELLVALUE_AURA_STACK -}; - -class CustomSpellValues -{ - typedef std::pair<SpellValueMod, int32> CustomSpellValueMod; - typedef std::vector<CustomSpellValueMod> StorageType; - -public: - typedef StorageType::const_iterator const_iterator; - -public: - void AddSpellMod(SpellValueMod mod, int32 value) - { - storage_.push_back(CustomSpellValueMod(mod, value)); - } - - const_iterator begin() const - { - return storage_.begin(); - } - - const_iterator end() const - { - return storage_.end(); - } - -private: - StorageType storage_; -}; - -enum SpellFacingFlags -{ - SPELL_FACING_FLAG_INFRONT = 0x0001 -}; - -// high byte (3 from 0..3) of UNIT_FIELD_BYTES_2 -enum ShapeshiftForm -{ - FORM_NONE = 0x00, - FORM_CAT = 0x01, - FORM_TREE = 0x02, - FORM_TRAVEL = 0x03, - FORM_AQUA = 0x04, - FORM_BEAR = 0x05, - FORM_AMBIENT = 0x06, - FORM_GHOUL = 0x07, - FORM_DIREBEAR = 0x08, - FORM_STEVES_GHOUL = 0x09, - FORM_THARONJA_SKELETON = 0x0A, - FORM_TEST_OF_STRENGTH = 0x0B, - FORM_BLB_PLAYER = 0x0C, - FORM_SHADOW_DANCE = 0x0D, - FORM_CREATUREBEAR = 0x0E, - FORM_CREATURECAT = 0x0F, - FORM_GHOSTWOLF = 0x10, - FORM_BATTLESTANCE = 0x11, - FORM_DEFENSIVESTANCE = 0x12, - FORM_BERSERKERSTANCE = 0x13, - FORM_TEST = 0x14, - FORM_ZOMBIE = 0x15, - FORM_METAMORPHOSIS = 0x16, - FORM_UNDEAD = 0x19, - FORM_MASTER_ANGLER = 0x1A, - FORM_FLIGHT_EPIC = 0x1B, - FORM_SHADOW = 0x1C, - FORM_FLIGHT = 0x1D, - FORM_STEALTH = 0x1E, - FORM_MOONKIN = 0x1F, - FORM_SPIRITOFREDEMPTION = 0x20 -}; - #define MAX_SPELL_CHARM 4 #define MAX_SPELL_VEHICLE 6 #define MAX_SPELL_POSSESS 8 @@ -310,35 +145,6 @@ enum WeaponDamageRange MAXDAMAGE }; -enum TriggerCastFlags : uint32 -{ - TRIGGERED_NONE = 0x00000000, //! Not triggered - TRIGGERED_IGNORE_GCD = 0x00000001, //! Will ignore GCD - TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD = 0x00000002, //! Will ignore Spell and Category cooldowns - TRIGGERED_IGNORE_POWER_AND_REAGENT_COST = 0x00000004, //! Will ignore power and reagent cost - TRIGGERED_IGNORE_CAST_ITEM = 0x00000008, //! Will not take away cast item or update related achievement criteria - TRIGGERED_IGNORE_AURA_SCALING = 0x00000010, //! Will ignore aura scaling - TRIGGERED_IGNORE_CAST_IN_PROGRESS = 0x00000020, //! Will not check if a current cast is in progress - TRIGGERED_IGNORE_COMBO_POINTS = 0x00000040, //! Will ignore combo point requirement - TRIGGERED_CAST_DIRECTLY = 0x00000080, //! In Spell::prepare, will be cast directly without setting containers for executed spell - TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS = 0x00000100, //! Will ignore interruptible aura's at cast - TRIGGERED_IGNORE_SET_FACING = 0x00000200, //! Will not adjust facing to target (if any) - TRIGGERED_IGNORE_SHAPESHIFT = 0x00000400, //! Will ignore shapeshift checks - TRIGGERED_IGNORE_CASTER_AURASTATE = 0x00000800, //! Will ignore caster aura states including combat requirements and death state - TRIGGERED_DISALLOW_PROC_EVENTS = 0x00001000, //! Disallows proc events from triggered spell (default) - TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE = 0x00002000, //! Will ignore mounted/on vehicle restrictions - // reuse = 0x00004000, - // reuse = 0x00008000, - TRIGGERED_IGNORE_CASTER_AURAS = 0x00010000, //! Will ignore caster aura restrictions or requirements - TRIGGERED_DONT_RESET_PERIODIC_TIMER = 0x00020000, //! Will allow periodic aura timers to keep ticking (instead of resetting) - TRIGGERED_DONT_REPORT_CAST_ERROR = 0x00040000, //! Will return SPELL_FAILED_DONT_REPORT in CheckCast functions - TRIGGERED_FULL_MASK = 0x0007FFFF, //! Used when doing CastSpell with triggered == true - - // debug flags (used with .cast triggered commands) - TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT = 0x00080000, //! Will ignore equipped item requirements - TRIGGERED_FULL_DEBUG_MASK = 0xFFFFFFFF -}; - enum UnitMods { UNIT_MOD_STAT_STRENGTH, // UNIT_MOD_STAT_STRENGTH..UNIT_MOD_STAT_SPIRIT must be in existed order, it's accessed by index values of Stats enum. @@ -1278,20 +1084,10 @@ class TC_GAME_API Unit : public WorldObject void EnergizeBySpell(Unit* victim, uint32 spellId, int32 damage, Powers powerType); void EnergizeBySpell(Unit* victim, SpellInfo const* spellInfo, int32 damage, Powers powerType); - void CastSpell(SpellCastTargets const& targets, SpellInfo const* spellInfo, CustomSpellValues const* value, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); - void CastSpell(Unit* victim, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); - void CastSpell(std::nullptr_t, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty) { CastSpell((Unit*)nullptr, spellId, triggered, castItem, triggeredByAura, originalCaster); } - void CastSpell(Unit* victim, uint32 spellId, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); - void CastSpell(std::nullptr_t, uint32 spellId, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty) { CastSpell((Unit*)nullptr, spellId, triggerFlags, castItem, triggeredByAura, originalCaster); } - void CastSpell(Unit* victim, SpellInfo const* spellInfo, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); - void CastSpell(Unit* victim, SpellInfo const* spellInfo, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); - void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); - void CastSpell(float x, float y, float z, uint32 spellId, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); - void CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); - void CastCustomSpell(Unit* victim, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); - void CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* victim, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); - void CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* victim = nullptr, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); - void CastCustomSpell(uint32 spellId, CustomSpellValues const& value, Unit* victim = nullptr, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); + // CastSpell's third arg can be a variety of things - check out CastSpellExtraArgs' constructors! + void CastSpell(SpellCastTargets const& targets, uint32 spellId, CastSpellExtraArgs const& args = {}); + void CastSpell(WorldObject* target, uint32 spellId, CastSpellExtraArgs const& args = {}); + void CastSpell(Position const& dest, uint32 spellId, CastSpellExtraArgs const& args = {}); Aura* AddAura(uint32 spellId, Unit* target); Aura* AddAura(SpellInfo const* spellInfo, uint8 effMask, Unit* target); void SetAuraStack(uint32 spellId, Unit* target, uint32 stack); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 1bab6418e6c..249303f8e14 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -854,8 +854,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) { // not blizz like, we must correctly save and load player instead... if (pCurrChar->getRace() == RACE_NIGHTELF) - pCurrChar->CastSpell(pCurrChar, 20584, true, nullptr);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) - pCurrChar->CastSpell(pCurrChar, 8326, true, nullptr); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) + pCurrChar->CastSpell(pCurrChar, 20584, true);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) + pCurrChar->CastSpell(pCurrChar, 8326, true); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) pCurrChar->SetMovement(MOVE_WATER_WALK); } diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index d285681fa9f..77ae7ce0847 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -382,7 +382,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe } } - spell->prepare(&(spell->m_targets)); + spell->prepare(spell->m_targets); } else { @@ -812,7 +812,7 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) } } - spell->prepare(&(spell->m_targets)); + spell->prepare(spell->m_targets); } else { diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index e5336d4af21..fc43628ace5 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -409,7 +409,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE, ObjectGuid::Empty, false); spell->m_cast_count = castCount; // set count of casts - spell->prepare(&targets); + spell->prepare(targets); } void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket) @@ -562,12 +562,9 @@ void WorldSession::HandleSelfResOpcode(WorldPacket & /*recvData*/) if (_player->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) return; // silent return, client should display error by itself and not send this opcode - if (_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)) + if (uint32 spellId = _player->GetUInt32Value(PLAYER_SELF_RES_SPELL)) { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)); - if (spellInfo) - _player->CastSpell(_player, spellInfo, false, nullptr); - + _player->CastSpell(_player, spellId); _player->SetUInt32Value(PLAYER_SELF_RES_SPELL, 0); } } diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index 3490e6da98d..4fcf90a6577 100644 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -521,10 +521,10 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) trader->ModifyMoney(my_trade->GetMoney()); if (my_spell) - my_spell->prepare(&my_targets); + my_spell->prepare(my_targets); if (his_spell) - his_spell->prepare(&his_targets); + his_spell->prepare(his_targets); // cleanup clearAcceptTradeMode(my_trade, his_trade); diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 4fac4728b6c..e287a5d97cf 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -398,4 +398,40 @@ enum AuraObjectType DYNOBJ_AURA_TYPE }; +// high byte (3 from 0..3) of UNIT_FIELD_BYTES_2 +enum ShapeshiftForm +{ + FORM_NONE = 0x00, + FORM_CAT = 0x01, + FORM_TREE = 0x02, + FORM_TRAVEL = 0x03, + FORM_AQUA = 0x04, + FORM_BEAR = 0x05, + FORM_AMBIENT = 0x06, + FORM_GHOUL = 0x07, + FORM_DIREBEAR = 0x08, + FORM_STEVES_GHOUL = 0x09, + FORM_THARONJA_SKELETON = 0x0A, + FORM_TEST_OF_STRENGTH = 0x0B, + FORM_BLB_PLAYER = 0x0C, + FORM_SHADOW_DANCE = 0x0D, + FORM_CREATUREBEAR = 0x0E, + FORM_CREATURECAT = 0x0F, + FORM_GHOSTWOLF = 0x10, + FORM_BATTLESTANCE = 0x11, + FORM_DEFENSIVESTANCE = 0x12, + FORM_BERSERKERSTANCE = 0x13, + FORM_TEST = 0x14, + FORM_ZOMBIE = 0x15, + FORM_METAMORPHOSIS = 0x16, + FORM_UNDEAD = 0x19, + FORM_MASTER_ANGLER = 0x1A, + FORM_FLIGHT_EPIC = 0x1B, + FORM_SHADOW = 0x1C, + FORM_FLIGHT = 0x1D, + FORM_STEALTH = 0x1E, + FORM_MOONKIN = 0x1F, + FORM_SPIRITOFREDEMPTION = 0x20 +}; + #endif diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 41014b55e72..2541f14acdf 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1100,10 +1100,10 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const if (apply) { if (spellId) - target->CastSpell(target, spellId, true, nullptr, this); + target->CastSpell(target, spellId, this); if (spellId2) - target->CastSpell(target, spellId2, true, nullptr, this); + target->CastSpell(target, spellId2, this); if (target->GetTypeId() == TYPEID_PLAYER) { @@ -1121,7 +1121,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const continue; if (spellInfo->Stances & (UI64LIT(1) << (GetMiscValue() - 1))) - target->CastSpell(target, itr->first, true, nullptr, this); + target->CastSpell(target, itr->first, this); } // Also do it for Glyphs @@ -1136,7 +1136,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const continue; if (spellInfo->Stances & (UI64LIT(1) << (GetMiscValue() - 1))) - target->CastSpell(target, glyph->SpellId, true, nullptr, this); + target->CastSpell(target, glyph->SpellId, this); } } } @@ -1146,7 +1146,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(24932); if (spellInfo && spellInfo->Stances & (UI64LIT(1) << (GetMiscValue() - 1))) - target->CastSpell(target, 24932, true, nullptr, this); + target->CastSpell(target, 24932, this); } // Improved Barkskin - apply/remove armor bonus due to shapeshift if (target->ToPlayer()->HasSpell(63410) || target->ToPlayer()->HasSpell(63411)) @@ -1164,9 +1164,10 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const // Heart of the Wild if (aurEff->GetSpellInfo()->SpellIconID == 240 && aurEff->GetMiscValue() == 3) { - int32 HotWMod = aurEff->GetAmount() / 2; // For each 2% Intelligence, you get 1% stamina and 1% attack power. + CastSpellExtraArgs args(this); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount() / 2); // For each 2% Intelligence, you get 1% stamina and 1% attack power. - target->CastCustomSpell(HotWSpellId, SPELLVALUE_BASE_POINT0, HotWMod, target, true, nullptr, this); + target->CastSpell(target, HotWSpellId, args); break; } } @@ -1190,46 +1191,51 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const spellId3 = 47180; break; } - target->CastSpell(target, spellId3, true, nullptr, this); + target->CastSpell(target, spellId3, this); } // Master Shapeshifter - Cat if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0)) { - int32 bp = aurEff->GetAmount(); - target->CastCustomSpell(48420, SPELLVALUE_BASE_POINT0, bp, target, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount()); + target->CastSpell(target, 48420, args); } - break; + break; case FORM_DIREBEAR: case FORM_BEAR: // Master Shapeshifter - Bear if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0)) { - int32 bp = aurEff->GetAmount(); - target->CastCustomSpell(48418, SPELLVALUE_BASE_POINT0, bp, target, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount()); + target->CastSpell(target, 48418, args); } // Survival of the Fittest if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DRUID, 961, 0)) { - int32 bp = aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue(); - target->CastCustomSpell(62069, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, this); + CastSpellExtraArgs args(this); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue()); + target->CastSpell(target, 62069, args); } - break; + break; case FORM_MOONKIN: // Master Shapeshifter - Moonkin if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0)) { - int32 bp = aurEff->GetAmount(); - target->CastCustomSpell(48421, SPELLVALUE_BASE_POINT0, bp, target, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount()); + target->CastSpell(target, 48421, args); } - break; - // Master Shapeshifter - Tree of Life + break; case FORM_TREE: + // Master Shapeshifter - Tree of Life if (AuraEffect const* aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0)) { - int32 bp = aurEff->GetAmount(); - target->CastCustomSpell(48422, SPELLVALUE_BASE_POINT0, bp, target, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount()); + target->CastSpell(target, 48422, args); } - break; + break; } } } @@ -1705,9 +1711,10 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo { case FORM_CAT: { - int32 basePoints = int32(std::min(oldPower, FurorChance)); + CastSpellExtraArgs args(this); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, std::min(oldPower, FurorChance)); target->SetPower(POWER_ENERGY, 0); - target->CastCustomSpell(target, 17099, &basePoints, nullptr, nullptr, true, nullptr, this); + target->CastSpell(target, 17099, args); break; } case FORM_BEAR: @@ -1770,12 +1777,12 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo case FORM_DIREBEAR: case FORM_CAT: if (AuraEffect* dummy = target->GetAuraEffect(37315, 0)) - target->CastSpell(target, 37316, true, nullptr, dummy); + target->CastSpell(target, 37316, dummy); break; // Nordrassil Regalia - bonus case FORM_MOONKIN: if (AuraEffect* dummy = target->GetAuraEffect(37324, 0)) - target->CastSpell(target, 37325, true, nullptr, dummy); + target->CastSpell(target, 37325, dummy); break; case FORM_BATTLESTANCE: case FORM_DEFENSIVESTANCE: @@ -4304,7 +4311,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool case 13139: // net-o-matic // root to self part of (root_target->charge->root_self sequence if (caster) - caster->CastSpell(caster, 13138, true, nullptr, this); + caster->CastSpell(caster, 13138, this); break; case 34026: // kill command { @@ -4312,7 +4319,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool if (!pet) break; - target->CastSpell(target, 34027, true, nullptr, this); + target->CastSpell(target, 34027, this); // set 3 stacks and 3 charges (to make all auras not disappear at once) Aura* owner_aura = target->GetAura(34027, GetCasterGUID()); @@ -4333,15 +4340,15 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool if (caster) { if (caster->getGender() == GENDER_FEMALE) - caster->CastSpell(target, 37095, true, nullptr, this); // Blood Elf Disguise + caster->CastSpell(target, 37095, this); // Blood Elf Disguise else - caster->CastSpell(target, 37093, true, nullptr, this); + caster->CastSpell(target, 37093, this); } break; } case 55198: // Tidal Force { - target->CastSpell(target, 55166, true, nullptr, this); + target->CastSpell(target, 55166, this); // set 3 stacks and 3 charges (to make all auras not disappear at once) Aura* owner_aura = target->GetAura(55166, GetCasterGUID()); if (owner_aura) @@ -4357,7 +4364,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool } case 39850: // Rocket Blast if (roll_chance_i(20)) // backfire stun - target->CastSpell(target, 51581, true, nullptr, this); + target->CastSpell(target, 51581, this); break; case 43873: // Headless Horseman Laugh target->PlayDistanceSound(11965); @@ -4366,9 +4373,9 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool if (caster) { if (caster->getGender() == GENDER_FEMALE) - caster->CastSpell(target, 46356, true, nullptr, this); + caster->CastSpell(target, 46356, this); else - caster->CastSpell(target, 46355, true, nullptr, this); + caster->CastSpell(target, 46355, this); } break; case 46361: // Reinforced Net @@ -4410,7 +4417,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool } if (finalSpelId) - caster->CastSpell(target, finalSpelId, true, nullptr, this); + caster->CastSpell(target, finalSpelId, this); } switch (m_spellInfo->SpellFamilyName) @@ -4430,7 +4437,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool break; case 36730: // Flame Strike { - target->CastSpell(target, 36731, true, nullptr, this); + target->CastSpell(target, 36731, this); break; } case 44191: // Flame Strike @@ -4439,7 +4446,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool { uint32 spellId = target->GetMap()->IsHeroic() ? 46163 : 44190; - target->CastSpell(target, spellId, true, nullptr, this); + target->CastSpell(target, spellId, this); } break; } @@ -4453,14 +4460,14 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool break; } case 42783: // Wrath of the Astromancer - target->CastSpell(target, GetAmount(), true, nullptr, this); + target->CastSpell(target, GetAmount(), this); break; case 46308: // Burning Winds cast only at creatures at spawn - target->CastSpell(target, 47287, true, nullptr, this); + target->CastSpell(target, 47287, this); break; case 52172: // Coyote Spirit Despawn Aura case 60244: // Blood Parrot Despawn Aura - target->CastSpell(nullptr, GetAmount(), true, nullptr, this); + target->CastSpell(nullptr, GetAmount(), this); break; case 58600: // Restricted Flight Area case 58730: // Restricted Flight Area @@ -4503,7 +4510,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool SpellInfo const* spell = sSpellMgr->AssertSpellInfo(spellId); for (uint32 i = 0; i < spell->StackAmount; ++i) - caster->CastSpell(target, spell->Id, true, nullptr, nullptr, GetCasterGUID()); + caster->CastSpell(target, spell->Id, GetCasterGUID()); break; } target->RemoveAurasDueToSpell(spellId); @@ -4517,7 +4524,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool { SpellInfo const* spell = sSpellMgr->AssertSpellInfo(spellId); for (uint32 i = 0; i < spell->StackAmount; ++i) - caster->CastSpell(target, spell->Id, true, nullptr, nullptr, GetCasterGUID()); + caster->CastSpell(target, spell->Id, GetCasterGUID()); break; } target->RemoveAurasDueToSpell(spellId); @@ -4678,7 +4685,7 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod // Glyph of Drain Soul - chance to create an additional Soul Shard if (AuraEffect* aur = caster->GetAuraEffect(58070, 0)) if (roll_chance_i(aur->GetMiscValue())) - caster->CastSpell(caster, 58068, true, nullptr, aur); // We _could_ simply do ++count here, but Blizz does it this way :) + caster->CastSpell(caster, 58068, aur); // We _could_ simply do ++count here, but Blizz does it this way :) } } @@ -4848,11 +4855,13 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo if (!caster) return; - // If amount avalible cast with basepoints (Crypt Fever for example) - if (GetAmount()) - caster->CastCustomSpell(target, triggeredSpellId, &m_amount, nullptr, nullptr, true, nullptr, this); - else - caster->CastSpell(target, triggeredSpellId, true, nullptr, this); + + CastSpellExtraArgs args(this); + + if (GetAmount()) // If amount avalible cast with basepoints (Crypt Fever for example) + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, GetAmount()); + + caster->CastSpell(target, triggeredSpellId, args); } else { @@ -5006,12 +5015,12 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) { if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target) { - triggerCaster->CastSpell(target, triggeredSpellInfo, true, nullptr, this); + triggerCaster->CastSpell(target, triggerSpellId, this); TC_LOG_DEBUG("spells", "AuraEffect::HandlePeriodicTriggerSpellAuraTick: Spell %u Trigger %u", GetId(), triggeredSpellInfo->Id); } } else - TC_LOG_DEBUG("spells", "AuraEffect::HandlePeriodicTriggerSpellAuraTick: Spell %u has non-existent spell %u in EffectTriggered[%d] and is therefor not triggered.", GetId(), triggerSpellId, GetEffIndex()); + TC_LOG_WARN("spells", "AuraEffect::HandlePeriodicTriggerSpellAuraTick: Spell %u has non-existent spell %u in EffectTriggered[%d] and is therefore not triggered.", GetId(), triggerSpellId, GetEffIndex()); } void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* caster) const @@ -5021,13 +5030,15 @@ void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* { if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target) { - int32 basepoints = GetAmount(); - triggerCaster->CastCustomSpell(target, triggerSpellId, &basepoints, &basepoints, &basepoints, true, nullptr, this); + CastSpellExtraArgs args(this); + for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + args.SpellValueOverrides.AddMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + i), GetAmount()); + triggerCaster->CastSpell(target, triggerSpellId, args); TC_LOG_DEBUG("spells", "AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick: Spell %u Trigger %u", GetId(), triggeredSpellInfo->Id); } } else - TC_LOG_DEBUG("spells","AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick: Spell %u has non-existent spell %u in EffectTriggered[%d] and is therefor not triggered.", GetId(), triggerSpellId, GetEffIndex()); + TC_LOG_WARN("spells","AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick: Spell %u has non-existent spell %u in EffectTriggered[%d] and is therefore not triggered.", GetId(), triggerSpellId, GetEffIndex()); } void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const @@ -5095,11 +5106,11 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const { if (roll_chance_i(20)) { - caster->CastSpell(caster, 43836, true, nullptr, this); + caster->CastSpell(caster, 43836, this); // Glyph of Drain Soul - chance to create an additional Soul Shard if (AuraEffect* aur = caster->GetAuraEffect(58070, 0)) if (roll_chance_i(aur->GetMiscValue())) - caster->CastSpell(caster, 58068, true, nullptr, aur); + caster->CastSpell(caster, 58068, aur); } } } @@ -5501,7 +5512,10 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con if (manaFeedVal > 0) { int32 feedAmount = CalculatePct(gainedAmount, manaFeedVal); - caster->CastCustomSpell(caster, 32554, &feedAmount, nullptr, nullptr, true, nullptr, this); + + CastSpellExtraArgs args(this); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, feedAmount); + caster->CastSpell(caster, 32554, args); } } } @@ -5655,7 +5669,7 @@ void AuraEffect::HandleProcTriggerSpellAuraProc(AuraApplication* aurApp, ProcEve if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId)) { TC_LOG_DEBUG("spells", "AuraEffect::HandleProcTriggerSpellAuraProc: Triggering spell %u from aura %u proc", triggeredSpellInfo->Id, GetId()); - triggerCaster->CastSpell(triggerTarget, triggeredSpellInfo, true, nullptr, this); + triggerCaster->CastSpell(triggerTarget, triggeredSpellInfo->Id, this); } else TC_LOG_ERROR("spells","AuraEffect::HandleProcTriggerSpellAuraProc: Could not trigger spell %u from aura %u proc, because the spell does not have an entry in Spell.dbc.", triggerSpellId, GetId()); @@ -5669,9 +5683,10 @@ void AuraEffect::HandleProcTriggerSpellWithValueAuraProc(AuraApplication* aurApp uint32 triggerSpellId = GetSpellInfo()->Effects[m_effIndex].TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId)) { - int32 basepoints0 = GetAmount(); - TC_LOG_DEBUG("spells", "AuraEffect::HandleProcTriggerSpellWithValueAuraProc: Triggering spell %u with value %d from aura %u proc", triggeredSpellInfo->Id, basepoints0, GetId()); - triggerCaster->CastCustomSpell(triggerTarget, triggerSpellId, &basepoints0, nullptr, nullptr, true, nullptr, this); + CastSpellExtraArgs args(this); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, GetAmount()); + triggerCaster->CastSpell(triggerTarget, triggerSpellId, args); + TC_LOG_DEBUG("spells", "AuraEffect::HandleProcTriggerSpellWithValueAuraProc: Triggering spell %u with value %d from aura %u proc", triggeredSpellInfo->Id, GetAmount(), GetId()); } else TC_LOG_ERROR("spells","AuraEffect::HandleProcTriggerSpellWithValueAuraProc: Could not trigger spell %u from aura %u proc, because the spell does not have an entry in Spell.dbc.", triggerSpellId, GetId()); @@ -5737,7 +5752,7 @@ void AuraEffect::HandleRaidProcFromChargeAuraProc(AuraApplication* aurApp, ProcE if (Unit* triggerTarget = target->GetNextRandomRaidMemberOrPet(radius)) { - target->CastSpell(triggerTarget, GetSpellInfo(), true, nullptr, this, GetCasterGUID()); + target->CastSpell(triggerTarget, GetId(), { this, GetCasterGUID() }); if (Aura* aura = triggerTarget->GetAura(GetId(), GetCasterGUID())) aura->SetCharges(jumps); } @@ -5745,7 +5760,7 @@ void AuraEffect::HandleRaidProcFromChargeAuraProc(AuraApplication* aurApp, ProcE } TC_LOG_DEBUG("spells", "AuraEffect::HandleRaidProcFromChargeAuraProc: Triggering spell %u from aura %u proc", triggerSpellId, GetId()); - target->CastSpell(target, triggerSpellId, true, nullptr, this, GetCasterGUID()); + target->CastSpell(target, triggerSpellId, { this, GetCasterGUID() }); } @@ -5761,14 +5776,16 @@ void AuraEffect::HandleRaidProcFromChargeWithValueAuraProc(AuraApplication* aurA } uint32 triggerSpellId = 33110; - int32 value = GetAmount(); - int32 jumps = GetBase()->GetCharges(); // current aura expire on proc finish GetBase()->SetCharges(0); GetBase()->SetUsingCharges(true); + CastSpellExtraArgs args(this); + args.OriginalCaster = GetCasterGUID(); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, GetAmount()); + // next target selection if (jumps > 0) { @@ -5778,7 +5795,7 @@ void AuraEffect::HandleRaidProcFromChargeWithValueAuraProc(AuraApplication* aurA if (Unit* triggerTarget = target->GetNextRandomRaidMemberOrPet(radius)) { - target->CastCustomSpell(triggerTarget, GetId(), &value, nullptr, nullptr, true, nullptr, this, GetCasterGUID()); + target->CastSpell(triggerTarget, GetId(), args); if (Aura* aura = triggerTarget->GetAura(GetId(), GetCasterGUID())) aura->SetCharges(jumps); } @@ -5786,7 +5803,7 @@ void AuraEffect::HandleRaidProcFromChargeWithValueAuraProc(AuraApplication* aurA } TC_LOG_DEBUG("spells", "AuraEffect::HandleRaidProcFromChargeWithValueAuraProc: Triggering spell %u from aura %u proc", triggerSpellId, GetId()); - target->CastCustomSpell(target, triggerSpellId, &value, nullptr, nullptr, true, nullptr, this, GetCasterGUID()); + target->CastSpell(target, triggerSpellId, args); } template TC_GAME_API void AuraEffect::GetTargetList(std::list<Unit*>&) const; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index a6213736961..e6e81038d75 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -1183,7 +1183,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b if (*itr < 0) target->RemoveAurasDueToSpell(-(*itr)); else if (removeMode != AURA_REMOVE_BY_DEATH) - target->CastSpell(target, *itr, true, nullptr, nullptr, GetCasterGUID()); + target->CastSpell(target, *itr, GetCasterGUID()); } } if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(GetId() + SPELL_LINK_AURA)) @@ -1245,8 +1245,9 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b // Druid T8 Restoration 4P Bonus if (caster->HasAura(64760)) { - int32 heal = GetEffect(EFFECT_0)->GetAmount(); - caster->CastCustomSpell(target, 64801, &heal, nullptr, nullptr, true, nullptr, GetEffect(EFFECT_0)); + CastSpellExtraArgs args(GetEffect(EFFECT_0)); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, GetEffect(EFFECT_0)->GetAmount()); + caster->CastSpell(target, 64801, args); } } break; @@ -1281,9 +1282,13 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b switch (GetId()) { case 44544: // Fingers of Frost + { // Refresh or add visual aura - target->CastCustomSpell(74396, SPELLVALUE_AURA_STACK, sSpellMgr->AssertSpellInfo(74396)->StackAmount, (Unit*)nullptr, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddMod(SPELLVALUE_AURA_STACK, sSpellMgr->AssertSpellInfo(74396)->StackAmount); + target->CastSpell(nullptr, 74396, args); break; + } default: break; } @@ -1308,10 +1313,12 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT); + CastSpellExtraArgs args(devouringPlague), args2(devouringPlague); int32 basepoints0 = CalculatePct(devouringPlague->GetTotalTicks() * static_cast<int32>(damage), aurEff->GetAmount()); - int32 heal = CalculatePct(basepoints0, 15); - caster->CastCustomSpell(63675, SPELLVALUE_BASE_POINT0, basepoints0, target, true, nullptr, devouringPlague); - caster->CastCustomSpell(75999, SPELLVALUE_BASE_POINT0, heal, (Unit*)nullptr, true, nullptr, devouringPlague); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, basepoints0); + args2.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, CalculatePct(basepoints0, 15)); + caster->CastSpell(target, 63675, args); + caster->CastSpell(nullptr, 75999, args2); } } // Power Word: Shield @@ -1322,7 +1329,9 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b { // instantly heal m_amount% of the absorb-value int32 heal = glyph->GetAmount() * GetEffect(0)->GetAmount()/100; - caster->CastCustomSpell(GetUnitOwner(), 56160, &heal, nullptr, nullptr, true, nullptr, GetEffect(0)); + CastSpellExtraArgs args(GetEffect(0)); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, heal); + caster->CastSpell(GetUnitOwner(), 56160, args); } } break; @@ -1372,7 +1381,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b default: TC_LOG_ERROR("spells", "Aura::HandleAuraSpecificMods: Unknown rank of Crypt Fever/Ebon Plague (%d) found", aurEff->GetId()); } - caster->CastSpell(target, spellId, true, 0, GetEffect(0)); + caster->CastSpell(target, spellId, GetEffect(0)); } } break; @@ -1401,7 +1410,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b case 66: // Invisibility if (removeMode != AURA_REMOVE_BY_EXPIRE) break; - target->CastSpell(target, 32612, true, nullptr, GetEffect(1)); + target->CastSpell(target, 32612, GetEffect(1)); target->CombatStop(); break; default: @@ -1462,7 +1471,9 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 178, 1)) { int32 basepoints0 = aurEff->GetAmount() * caster->GetCreateMana() / 100; - caster->CastCustomSpell(caster, 64103, &basepoints0, nullptr, nullptr, true, nullptr, GetEffect(0)); + CastSpellExtraArgs args(GetEffect(0)); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, basepoints0); + caster->CastSpell(caster, 64103, args); } } // Power word: shield @@ -1494,8 +1505,9 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b else if (aurEff->GetId() == 47537) multiplier += 0.5f; - int32 basepoints0 = int32(CalculatePct(caster->GetMaxPower(POWER_MANA), multiplier)); - caster->CastCustomSpell(caster, 47755, &basepoints0, nullptr, nullptr, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddBP0(CalculatePct(caster->GetMaxPower(POWER_MANA), multiplier)); + caster->CastSpell(caster, 47755, args); } // effect on aura target if (AuraEffect const* aurEff = aura->GetEffect(1)) @@ -1508,8 +1520,9 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b { case POWER_MANA: { - int32 basepoints0 = int32(CalculatePct(target->GetMaxPower(POWER_MANA), 2)); - caster->CastCustomSpell(target, 63654, &basepoints0, nullptr, nullptr, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddBP0(CalculatePct(target->GetMaxPower(POWER_MANA), 2)); + caster->CastSpell(target, 63654, args); break; } case POWER_RAGE: triggeredSpellId = 63653; break; @@ -1601,8 +1614,9 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b // Remove counter aura target->RemoveAurasDueToSpell(31666); - int32 basepoints0 = aurEff->GetAmount(); - target->CastCustomSpell(target, 31665, &basepoints0, nullptr, nullptr, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddBP0(aurEff->GetAmount()); + target->CastSpell(target, 31665, args); } } // Overkill @@ -1632,7 +1646,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b if (owner->HasAura(34692)) { if (apply) - owner->CastSpell(owner, 34471, true, 0, GetEffect(0)); + owner->CastSpell(owner, 34471, GetEffect(0)); else owner->RemoveAurasDueToSpell(34471); } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 17a2bb9ad16..d103a281c46 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2740,7 +2740,7 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint8 effMask) { if (CanExecuteTriggersOnHit(effMask, i->triggeredByAura) && roll_chance_i(i->chance)) { - m_caster->CastSpell(unit, i->triggeredSpell, true); + m_caster->CastSpell(unit, i->triggeredSpell->Id, true); TC_LOG_DEBUG("spells", "Spell %d triggered spell %d by SPELL_AURA_ADD_TARGET_TRIGGER aura", m_spellInfo->Id, i->triggeredSpell->Id); // SPELL_AURA_ADD_TARGET_TRIGGER auras shouldn't trigger auras without duration @@ -2771,7 +2771,7 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint8 effMask) if (*i < 0) unit->RemoveAurasDueToSpell(-(*i)); else - unit->CastSpell(unit, *i, true, nullptr, nullptr, m_caster->GetGUID()); + unit->CastSpell(unit, *i, m_caster->GetGUID()); } } } @@ -2882,7 +2882,7 @@ bool Spell::UpdateChanneledTargetList() return channelTargetEffectMask == 0; } -void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggeredByAura) +void Spell::prepare(SpellCastTargets const& targets, AuraEffect const* triggeredByAura) { if (m_CastItem) { @@ -2895,7 +2895,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered m_castItemEntry = 0; } - InitExplicitTargets(*targets); + InitExplicitTargets(targets); // Fill aura scaling information if (m_caster->IsControlledByPlayer() && !m_spellInfo->IsPassive() && m_spellInfo->SpellLevel && !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_SCALING)) @@ -5495,7 +5495,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint { if (strict) //starting cast, trigger pet stun (cast by pet so it doesn't attack player) if (Pet* pet = m_caster->ToPlayer()->GetPet()) - pet->CastSpell(pet, 32752, true, nullptr, nullptr, pet->GetGUID()); + pet->CastSpell(pet, 32752, pet->GetGUID()); } else if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET)) return SPELL_FAILED_ALREADY_HAVE_SUMMON; diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 25ba9cd23a1..adf2619781a 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -405,7 +405,7 @@ class TC_GAME_API Spell GameObject* SearchSpellFocus(); - void prepare(SpellCastTargets const* targets, AuraEffect const* triggeredByAura = nullptr); + void prepare(SpellCastTargets const& targets, AuraEffect const* triggeredByAura = nullptr); void cancel(); void update(uint32 difftime); void cast(bool skipCheck = false); diff --git a/src/server/game/Spells/SpellDefines.h b/src/server/game/Spells/SpellDefines.h new file mode 100644 index 00000000000..aa5f893e777 --- /dev/null +++ b/src/server/game/Spells/SpellDefines.h @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2008-2018 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TRINITY_SPELLDEFINES_H +#define TRINITY_SPELLDEFINES_H + +#include "Define.h" +#include "ObjectGuid.h" +#include <vector> + +class Item; +class AuraEffect; + +enum SpellInterruptFlags +{ + SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, // why need this for instant? + SPELL_INTERRUPT_FLAG_PUSH_BACK = 0x02, // push back + SPELL_INTERRUPT_FLAG_UNK3 = 0x04, // any info? + SPELL_INTERRUPT_FLAG_INTERRUPT = 0x08, // interrupt + SPELL_INTERRUPT_FLAG_ABORT_ON_DMG = 0x10 // _complete_ interrupt on direct damage + //SPELL_INTERRUPT_UNK = 0x20 // unk, 564 of 727 spells having this spell start with "Glyph" +}; + +// See SpellAuraInterruptFlags for other values definitions +enum SpellChannelInterruptFlags +{ + CHANNEL_INTERRUPT_FLAG_INTERRUPT = 0x0008, // interrupt + CHANNEL_FLAG_DELAY = 0x4000 +}; + +enum SpellAuraInterruptFlags +{ + AURA_INTERRUPT_FLAG_HITBYSPELL = 0x00000001, // 0 removed when getting hit by a negative spell? + AURA_INTERRUPT_FLAG_TAKE_DAMAGE = 0x00000002, // 1 removed by any damage + AURA_INTERRUPT_FLAG_CAST = 0x00000004, // 2 cast any spells + AURA_INTERRUPT_FLAG_MOVE = 0x00000008, // 3 removed by any movement + AURA_INTERRUPT_FLAG_TURNING = 0x00000010, // 4 removed by any turning + AURA_INTERRUPT_FLAG_JUMP = 0x00000020, // 5 removed by entering combat + AURA_INTERRUPT_FLAG_NOT_MOUNTED = 0x00000040, // 6 removed by dismounting + AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7 removed by entering water + AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8 removed by leaving water + AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing + AURA_INTERRUPT_FLAG_TALK = 0x00000400, // 10 talk to npc / loot? action on creature + AURA_INTERRUPT_FLAG_USE = 0x00000800, // 11 mine/use/open action on gameobject + AURA_INTERRUPT_FLAG_MELEE_ATTACK = 0x00001000, // 12 removed by attacking + AURA_INTERRUPT_FLAG_SPELL_ATTACK = 0x00002000, // 13 ??? + AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14 + AURA_INTERRUPT_FLAG_TRANSFORM = 0x00008000, // 15 removed by transform? + AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16 + AURA_INTERRUPT_FLAG_MOUNT = 0x00020000, // 17 misdirect, aspect, swim speed + AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up (used by food and drink mostly and sleep/Fake Death like) + AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported + AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION = 0x00100000, // 20 removed by auras that make you invulnerable, or make other to lose selection on you + AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21 + AURA_INTERRUPT_FLAG_TELEPORTED = 0x00400000, // 22 + AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat + AURA_INTERRUPT_FLAG_DIRECT_DAMAGE = 0x01000000, // 24 removed by any direct damage + AURA_INTERRUPT_FLAG_LANDING = 0x02000000, // 25 removed by hitting the ground + AURA_INTERRUPT_FLAG_LEAVE_COMBAT = 0x80000000, // 31 removed by leaving combat + + AURA_INTERRUPT_FLAG_NOT_VICTIM = (AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE | AURA_INTERRUPT_FLAG_DIRECT_DAMAGE) +}; + +enum SpellModOp : uint8 +{ + SPELLMOD_DAMAGE = 0, + SPELLMOD_DURATION = 1, + SPELLMOD_THREAT = 2, + SPELLMOD_EFFECT1 = 3, + SPELLMOD_CHARGES = 4, + SPELLMOD_RANGE = 5, + SPELLMOD_RADIUS = 6, + SPELLMOD_CRITICAL_CHANCE = 7, + SPELLMOD_ALL_EFFECTS = 8, + SPELLMOD_NOT_LOSE_CASTING_TIME = 9, + SPELLMOD_CASTING_TIME = 10, + SPELLMOD_COOLDOWN = 11, + SPELLMOD_EFFECT2 = 12, + SPELLMOD_IGNORE_ARMOR = 13, + SPELLMOD_COST = 14, + SPELLMOD_CRIT_DAMAGE_BONUS = 15, + SPELLMOD_RESIST_MISS_CHANCE = 16, + SPELLMOD_JUMP_TARGETS = 17, + SPELLMOD_CHANCE_OF_SUCCESS = 18, + SPELLMOD_ACTIVATION_TIME = 19, + SPELLMOD_DAMAGE_MULTIPLIER = 20, + SPELLMOD_GLOBAL_COOLDOWN = 21, + SPELLMOD_DOT = 22, + SPELLMOD_EFFECT3 = 23, + SPELLMOD_BONUS_MULTIPLIER = 24, + // spellmod 25 + SPELLMOD_PROC_PER_MINUTE = 26, + SPELLMOD_VALUE_MULTIPLIER = 27, + SPELLMOD_RESIST_DISPEL_CHANCE = 28, + SPELLMOD_CRIT_DAMAGE_BONUS_2 = 29, //one not used spell + SPELLMOD_SPELL_COST_REFUND_ON_FAIL = 30, + + MAX_SPELLMOD +}; + +enum SpellValueMod : uint8 +{ + SPELLVALUE_BASE_POINT0, + SPELLVALUE_BASE_POINT1, + SPELLVALUE_BASE_POINT2, + SPELLVALUE_RADIUS_MOD, + SPELLVALUE_MAX_TARGETS, + SPELLVALUE_AURA_STACK +}; + +enum SpellFacingFlags +{ + SPELL_FACING_FLAG_INFRONT = 0x0001 +}; + +enum TriggerCastFlags : uint32 +{ + TRIGGERED_NONE = 0x00000000, //! Not triggered + TRIGGERED_IGNORE_GCD = 0x00000001, //! Will ignore GCD + TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD = 0x00000002, //! Will ignore Spell and Category cooldowns + TRIGGERED_IGNORE_POWER_AND_REAGENT_COST = 0x00000004, //! Will ignore power and reagent cost + TRIGGERED_IGNORE_CAST_ITEM = 0x00000008, //! Will not take away cast item or update related achievement criteria + TRIGGERED_IGNORE_AURA_SCALING = 0x00000010, //! Will ignore aura scaling + TRIGGERED_IGNORE_CAST_IN_PROGRESS = 0x00000020, //! Will not check if a current cast is in progress + TRIGGERED_IGNORE_COMBO_POINTS = 0x00000040, //! Will ignore combo point requirement + TRIGGERED_CAST_DIRECTLY = 0x00000080, //! In Spell::prepare, will be cast directly without setting containers for executed spell + TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS = 0x00000100, //! Will ignore interruptible aura's at cast + TRIGGERED_IGNORE_SET_FACING = 0x00000200, //! Will not adjust facing to target (if any) + TRIGGERED_IGNORE_SHAPESHIFT = 0x00000400, //! Will ignore shapeshift checks + TRIGGERED_IGNORE_CASTER_AURASTATE = 0x00000800, //! Will ignore caster aura states including combat requirements and death state + TRIGGERED_DISALLOW_PROC_EVENTS = 0x00001000, //! Disallows proc events from triggered spell (default) + TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE = 0x00002000, //! Will ignore mounted/on vehicle restrictions + // reuse = 0x00004000, + // reuse = 0x00008000, + TRIGGERED_IGNORE_CASTER_AURAS = 0x00010000, //! Will ignore caster aura restrictions or requirements + TRIGGERED_DONT_RESET_PERIODIC_TIMER = 0x00020000, //! Will allow periodic aura timers to keep ticking (instead of resetting) + TRIGGERED_DONT_REPORT_CAST_ERROR = 0x00040000, //! Will return SPELL_FAILED_DONT_REPORT in CheckCast functions + TRIGGERED_FULL_MASK = 0x0007FFFF, //! Used when doing CastSpell with triggered == true + + // debug flags (used with .cast triggered commands) + TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT = 0x00080000, //! Will ignore equipped item requirements + TRIGGERED_FULL_DEBUG_MASK = 0xFFFFFFFF +}; + +struct TC_GAME_API CastSpellExtraArgs +{ + CastSpellExtraArgs() {} + CastSpellExtraArgs(bool triggered) : TriggerFlags(triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE) {} + CastSpellExtraArgs(TriggerCastFlags trigger) : TriggerFlags(trigger) {} + CastSpellExtraArgs(Item* item) : TriggerFlags(TRIGGERED_FULL_MASK), CastItem(item) {} + CastSpellExtraArgs(AuraEffect const* eff) : TriggerFlags(TRIGGERED_FULL_MASK), TriggeringAura(eff) {} + CastSpellExtraArgs(ObjectGuid const& origCaster) : TriggerFlags(TRIGGERED_FULL_MASK), OriginalCaster(origCaster) {} + CastSpellExtraArgs(AuraEffect const* eff, ObjectGuid const& origCaster) : TriggerFlags(TRIGGERED_FULL_MASK), TriggeringAura(eff), OriginalCaster(origCaster) {} + CastSpellExtraArgs(SpellValueMod mod, int32 val) { SpellValueOverrides.AddMod(mod, val); } + + CastSpellExtraArgs& SetTriggerFlags(TriggerCastFlags flag) { TriggerFlags = flag; return *this; } + CastSpellExtraArgs& SetCastItem(Item* item) { CastItem = item; return *this; } + CastSpellExtraArgs& SetTriggeringAura(AuraEffect const* triggeringAura) { TriggeringAura = triggeringAura; return *this; } + CastSpellExtraArgs& SetOriginalCaster(ObjectGuid const& guid) { OriginalCaster = guid; return *this; } + CastSpellExtraArgs& AddSpellMod(SpellValueMod mod, int32 val) { SpellValueOverrides.AddMod(mod, val); return *this; } + CastSpellExtraArgs& AddSpellBP0(int32 val) { SpellValueOverrides.AddBP0(val); return *this; } + + TriggerCastFlags TriggerFlags = TRIGGERED_NONE; + Item* CastItem = nullptr; + AuraEffect const* TriggeringAura = nullptr; + ObjectGuid OriginalCaster = ObjectGuid::Empty; + struct + { + public: + void AddMod(SpellValueMod mod, int32 val) { data.push_back({ mod, val }); } + void AddBP0(int32 bp0) { AddMod(SPELLVALUE_BASE_POINT0, bp0); } // because i don't want to type SPELLVALUE_BASE_POINT0 300 times + + private: + auto begin() const { return data.cbegin(); } + auto end() const { return data.cend(); } + + std::vector<std::pair<SpellValueMod, int32>> data; + + friend class Unit; + } SpellValueOverrides; +}; + +#endif diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index f726fd3590b..1077a07e106 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -466,7 +466,9 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) if (AuraEffect* aurEff = owner->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARLOCK, 214, 0)) { int32 bp0 = aurEff->GetId() == 54037 ? 4 : 8; - m_caster->CastCustomSpell(m_caster, 54425, &bp0, nullptr, nullptr, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, bp0); + m_caster->CastSpell(m_caster, 54425, args); } } } @@ -487,7 +489,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) int chance = (*i)->GetSpellInfo()->Effects[EFFECT_1].CalcValue(m_caster); if (roll_chance_i(chance)) // Mind Trauma - m_caster->CastSpell(unitTarget, 48301, true, nullptr); + m_caster->CastSpell(unitTarget, 48301, true); break; } } @@ -855,17 +857,14 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) targets.SetUnitTarget(m_caster); } - CustomSpellValues values; + CastSpellExtraArgs args(m_originalCasterGUID); // set basepoints for trigger with value effect if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE) - { - values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage); - values.AddSpellMod(SPELLVALUE_BASE_POINT1, damage); - values.AddSpellMod(SPELLVALUE_BASE_POINT2, damage); - } + for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + args.SpellValueOverrides.AddMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + i), damage); // original caster guid only for GO cast - m_caster->CastSpell(targets, spellInfo, &values, TRIGGERED_FULL_MASK, nullptr, nullptr, m_originalCasterGUID); + m_caster->CastSpell(targets, spellInfo->Id, args); } void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex) @@ -902,18 +901,14 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex) targets.SetUnitTarget(m_caster); } - CustomSpellValues values; + CastSpellExtraArgs args(m_originalCasterGUID); // set basepoints for trigger with value effect if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE) - { - // maybe need to set value only when basepoints == 0? - values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage); - values.AddSpellMod(SPELLVALUE_BASE_POINT1, damage); - values.AddSpellMod(SPELLVALUE_BASE_POINT2, damage); - } + for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + args.SpellValueOverrides.AddMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + i), damage); // original caster guid only for GO cast - m_caster->CastSpell(targets, spellInfo, &values, TRIGGERED_FULL_MASK, nullptr, nullptr, m_originalCasterGUID); + m_caster->CastSpell(targets, spellInfo->Id, args); } void Spell::EffectForceCast(SpellEffIndex effIndex) @@ -945,32 +940,28 @@ void Spell::EffectForceCast(SpellEffIndex effIndex) break; case 52463: // Hide In Mine Car case 52349: // Overtake - unitTarget->CastCustomSpell(unitTarget, spellInfo->Id, &damage, nullptr, nullptr, true, nullptr, nullptr, m_originalCasterGUID); + { + CastSpellExtraArgs args(m_originalCasterGUID); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, damage); + unitTarget->CastSpell(unitTarget, spellInfo->Id, args); return; + } } } switch (spellInfo->Id) { case 72298: // Malleable Goo Summon - unitTarget->CastSpell(unitTarget, spellInfo->Id, true, nullptr, nullptr, m_originalCasterGUID); + unitTarget->CastSpell(unitTarget, spellInfo->Id, m_originalCasterGUID); return; } - CustomSpellValues values; - // set basepoints for trigger with value effect + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_FORCE_CAST_WITH_VALUE) - { - // maybe need to set value only when basepoints == 0? - values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage); - values.AddSpellMod(SPELLVALUE_BASE_POINT1, damage); - values.AddSpellMod(SPELLVALUE_BASE_POINT2, damage); - } - - SpellCastTargets targets; - targets.SetUnitTarget(m_caster); + for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + args.SpellValueOverrides.AddMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + i), damage); - unitTarget->CastSpell(targets, spellInfo, &values, TRIGGERED_FULL_MASK); + unitTarget->CastSpell(m_caster, spellInfo->Id, args); } void Spell::EffectTriggerRitualOfSummoning(SpellEffIndex effIndex) @@ -989,7 +980,7 @@ void Spell::EffectTriggerRitualOfSummoning(SpellEffIndex effIndex) finish(); - m_caster->CastSpell(nullptr, spellInfo, false); + m_caster->CastSpell(nullptr, spellInfo->Id, false); } void Spell::EffectJump(SpellEffIndex effIndex) @@ -2292,11 +2283,13 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) spellId = spellInfo->Id; } + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + // if we have small value, it indicates seat position if (basePoints > 0 && basePoints < MAX_VEHICLE_SEATS) - m_originalCaster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, basePoints, summon, true); - else - m_originalCaster->CastSpell(summon, spellId, true); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, basePoints); + + m_originalCaster->CastSpell(summon, spellId, args); uint32 faction = properties->Faction; if (!faction) @@ -2430,12 +2423,13 @@ void Spell::EffectDispel(SpellEffIndex effIndex) // Devour Magic if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->GetCategory() == SPELLCATEGORY_DEVOUR_MAGIC) { - int32 heal_amount = m_spellInfo->Effects[EFFECT_1].CalcValue(); - m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, nullptr, nullptr, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, m_spellInfo->Effects[EFFECT_1].CalcValue()); + m_caster->CastSpell(m_caster, 19658, args); // Glyph of Felhunter if (Unit* owner = m_caster->GetOwner()) if (owner->GetAura(56249)) - owner->CastCustomSpell(owner, 19658, &heal_amount, nullptr, nullptr, true); + owner->CastSpell(owner, 19658, args); } } @@ -2796,7 +2790,7 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex) Spell* spell = new Spell(m_caster, spellInfo, TRIGGERED_FULL_MASK); SpellCastTargets targets; targets.SetItemTarget(item); - spell->prepare(&targets); + spell->prepare(targets); } } } @@ -3183,7 +3177,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) // Skyshatter Harness item set bonus // Stormstrike if (AuraEffect* aurEff = m_caster->IsScriptOverriden(m_spellInfo, 5634)) - m_caster->CastSpell(m_caster, 38430, true, nullptr, aurEff); + m_caster->CastSpell(m_caster, 38430, aurEff); break; } case SPELLFAMILY_DRUID: @@ -3532,7 +3526,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) uint32 spell_id = roll_chance_i(20) ? 8854 : 8855; - m_caster->CastSpell(m_caster, spell_id, true, nullptr); + m_caster->CastSpell(m_caster, spell_id, true); return; } // Brittle Armor - need remove one 24575 Brittle Armor aura @@ -3737,7 +3731,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) for (uint8 i = 0; i < 15; ++i) { m_caster->GetRandomPoint(*destTarget, radius, x, y, z); - m_caster->CastSpell(x, y, z, 54522, true); + m_caster->CastSpell({x, y, z}, 54522, true); } break; } @@ -3841,7 +3835,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) // proc a spellcast if (Aura* chargesAura = m_caster->GetAura(59907)) { - m_caster->CastSpell(unitTarget, spell_heal, true, nullptr, nullptr, m_caster->ToTempSummon()->GetSummonerGUID()); + m_caster->CastSpell(unitTarget, spell_heal, m_caster->ToTempSummon()->GetSummonerGUID()); if (chargesAura->ModCharges(-1)) m_caster->ToTempSummon()->UnSummon(); } @@ -3860,7 +3854,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) case 58590: // Rank 9 case 58591: // Rank 10 { - int32 basepoints0 = damage; // Cast Absorb on totems for (uint8 slot = SUMMON_SLOT_TOTEM; slot < MAX_TOTEM_SLOT; ++slot) { @@ -3870,14 +3863,17 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) Creature* totem = unitTarget->GetMap()->GetCreature(unitTarget->m_SummonSlot[slot]); if (totem && totem->IsTotem()) { - m_caster->CastCustomSpell(totem, 55277, &basepoints0, nullptr, nullptr, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, damage); + m_caster->CastSpell(totem, 55277, args); } } // Glyph of Stoneclaw Totem if (AuraEffect* aur = unitTarget->GetAuraEffect(63298, 0)) { - basepoints0 *= aur->GetAmount(); - m_caster->CastCustomSpell(unitTarget, 55277, &basepoints0, nullptr, nullptr, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, damage * aur->GetAmount()); + m_caster->CastSpell(unitTarget, 55277, args); } break; } @@ -4305,7 +4301,9 @@ void Spell::EffectFeedPet(SpellEffIndex effIndex) player->DestroyItemCount(foodItem, count, true); /// @todo fix crash when a spell has two effects, both pointed at the same item target - m_caster->CastCustomSpell(pet, m_spellInfo->Effects[effIndex].TriggerSpell, &benefit, nullptr, nullptr, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, benefit); + m_caster->CastSpell(pet, m_spellInfo->Effects[effIndex].TriggerSpell, args); } void Spell::EffectDismissPet(SpellEffIndex effIndex) @@ -4899,7 +4897,11 @@ void Spell::EffectDestroyAllTotems(SpellEffIndex /*effIndex*/) } ApplyPct(mana, damage); if (mana) - m_caster->CastCustomSpell(m_caster, 39104, &mana, nullptr, nullptr, true); + { + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, mana); + m_caster->CastSpell(m_caster, 39104, args); + } } void Spell::EffectDurabilityDamage(SpellEffIndex effIndex) diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 0eb8a31ad10..02ba482bf7b 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3205,14 +3205,16 @@ void SpellMgr::LoadSpellInfoCorrections() 52438, // Summon Skittering Swarmer (Force Cast) 52449, // Summon Skittering Infector (Force Cast) 53609, // Summon Anub'ar Assassin (Force Cast) - 53457 // Summon Impale Trigger (AoE) + 53457, // Summon Impale Trigger (AoE) + 45907 // Torch Target Picker }, [](SpellInfo* spellInfo) { spellInfo->MaxAffectedTargets = 1; }); - // Skartax Purple Beam - ApplySpellFix({ 36384 }, [](SpellInfo* spellInfo) + ApplySpellFix({ + 36384 // Skartax Purple Beam + }, [](SpellInfo* spellInfo) { spellInfo->MaxAffectedTargets = 2; }); @@ -3245,6 +3247,44 @@ void SpellMgr::LoadSpellInfoCorrections() }); ApplySpellFix({ + 42005, // Bloodboil + 38296, // Spitfire Totem + 37676, // Insidious Whisper + 46008, // Negative Energy + 45641, // Fire Bloom + 55665, // Life Drain - Sapphiron (H) + 28796 // Poison Bolt Volly - Faerlina + }, [](SpellInfo* spellInfo) + { + spellInfo->MaxAffectedTargets = 5; + }); + + ApplySpellFix({ + 54835 // Curse of the Plaguebringer - Noth (H) + }, [](SpellInfo* spellInfo) + { + spellInfo->MaxAffectedTargets = 8; + }); + + ApplySpellFix({ + 40827, // Sinful Beam + 40859, // Sinister Beam + 40860, // Vile Beam + 40861, // Wicked Beam + 54098 // Poison Bolt Volly - Faerlina (H) + }, [](SpellInfo* spellInfo) + { + spellInfo->MaxAffectedTargets = 10; + }); + + ApplySpellFix({ + 50312 // Unholy Frenzy + }, [](SpellInfo* spellInfo) + { + spellInfo->MaxAffectedTargets = 15; + }); + + ApplySpellFix({ 47977, // Magic Broom 48025, // Headless Horseman's Mount 54729, // Winged Steed of the Ebon Blade @@ -3281,43 +3321,6 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_1].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ALLY); }); - ApplySpellFix({ - 42005, // Bloodboil - 38296, // Spitfire Totem - 37676, // Insidious Whisper - 46008, // Negative Energy - 45641, // Fire Bloom - 55665, // Life Drain - Sapphiron (H) - 28796 // Poison Bolt Volly - Faerlina - }, [](SpellInfo* spellInfo) - { - spellInfo->MaxAffectedTargets = 5; - }); - - - // Curse of the Plaguebringer - Noth (H) - ApplySpellFix({ 54835 }, [](SpellInfo* spellInfo) - { - spellInfo->MaxAffectedTargets = 8; - }); - - ApplySpellFix({ - 40827, // Sinful Beam - 40859, // Sinister Beam - 40860, // Vile Beam - 40861, // Wicked Beam - 54098 // Poison Bolt Volly - Faerlina (H) - }, [](SpellInfo* spellInfo) - { - spellInfo->MaxAffectedTargets = 10; - }); - - // Unholy Frenzy - ApplySpellFix({ 50312 }, [](SpellInfo* spellInfo) - { - spellInfo->MaxAffectedTargets = 15; - }); - // Murmur's Touch ApplySpellFix({ 33711, 38794 }, [](SpellInfo* spellInfo) { |
