diff options
| author | Treeston <treeston.mmoc@gmail.com> | 2017-12-30 20:28:41 +0100 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2021-04-16 15:22:42 +0200 |
| commit | 9b141207d170e4b2b4e6d9290d5f921f76cbcea0 (patch) | |
| tree | 47d65d966a66699f6de7e308047e408bdb255bff /src/server/game | |
| parent | 2ea8f5e6fced094f28c45ac84123c85477122567 (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
(cherry picked from commit d507a7e3388382960108b24143da48e5f912b4a7)
Diffstat (limited to 'src/server/game')
26 files changed, 470 insertions, 528 deletions
diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp index 2463f57f694..331267d1f19 100644 --- a/src/server/game/AI/CoreAI/PassiveAI.cpp +++ b/src/server/game/AI/CoreAI/PassiveAI.cpp @@ -98,7 +98,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 25c43525da2..2a2b8c62bd3 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 ccdb4097323..87277f7bfbf 100644 --- a/src/server/game/AI/CoreAI/UnitAI.cpp +++ b/src/server/game/AI/CoreAI/UnitAI.cpp @@ -96,7 +96,7 @@ bool UnitAI::DoSpellAttackIfReady(uint32 spellId) { if (me->IsWithinCombatRange(me->GetVictim(), spellInfo->GetMaxRange(false))) { - me->CastSpell(me->GetVictim(), spellInfo, TRIGGERED_NONE); + me->CastSpell(me->GetVictim(), spellId, me->GetMap()->GetDifficultyID()); me->resetAttackTimer(); return true; } @@ -167,28 +167,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); } #define UPDATE_TARGET(a) {if (AIInfo->target<a) AIInfo->target=a;} diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index 91f8a820189..a290c8ec402 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -298,10 +298,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); } virtual bool ShouldSparWith(Unit const* /*target*/) const { return false; } diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp index 695975fa177..be52282a482 100644 --- a/src/server/game/AI/PlayerAI/PlayerAI.cpp +++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp @@ -575,7 +575,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 ae30dcca730..965fd290a1d 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -176,7 +176,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/Battlefield/Zones/BattlefieldTB.cpp b/src/server/game/Battlefield/Zones/BattlefieldTB.cpp index a5ddeb42526..81ac01277e9 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldTB.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldTB.cpp @@ -212,7 +212,7 @@ void BattlefieldTB::OnPlayerJoinWar(Player* player) // Bonus damage buff for attackers if (player->GetTeamId() == GetAttackerTeam() && GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED) > 0) - player->CastCustomSpell(SPELL_TOWER_ATTACK_BONUS, SPELLVALUE_AURA_STACK, GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED), player, TRIGGERED_FULL_MASK); + player->CastSpell(player, SPELL_TOWER_ATTACK_BONUS, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_AURA_STACK, GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED))); } @@ -759,7 +759,7 @@ void BattlefieldTB::TowerDestroyed(TBTowerId tbTowerId) // Attack bonus buff for (ObjectGuid const& guid : m_PlayersInWar[GetAttackerTeam()]) if (Player* player = ObjectAccessor::FindPlayer(guid)) - player->CastCustomSpell(SPELL_TOWER_ATTACK_BONUS, SPELLVALUE_AURA_STACK, GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED), player, TRIGGERED_FULL_MASK); + player->CastSpell(player, SPELL_TOWER_ATTACK_BONUS, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellMod(SPELLVALUE_AURA_STACK, GetData(BATTLEFIELD_TB_DATA_TOWERS_DESTROYED))); // Honor reward TeamCastSpell(GetAttackerTeam(), SPELL_REWARD_TOWER_DESTROYED); diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 13ecb688257..e6f90796b89 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -2123,8 +2123,7 @@ void GameObject::Use(Unit* user) if (!spellId) return; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID()); - if (!spellInfo) + if (!sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID())) { 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()); @@ -2137,7 +2136,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); } @@ -2166,7 +2165,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; } @@ -2179,6 +2178,8 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, TriggerCastFlags trigge trigger->SetImmuneToAll(false); PhasingHandler::InheritPhaseShift(trigger, this); + CastSpellExtraArgs args; + args.TriggerFlags = triggered; if (Unit* owner = GetOwner()) { trigger->SetFaction(owner->GetFaction()); @@ -2188,14 +2189,17 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, TriggerCastFlags trigge trigger->SetPvpFlags(owner->GetPvpFlags()); // 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 d66e0b859e6..0e32be435b4 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -1702,13 +1702,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 71005da4166..0cf360516ac 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -7862,7 +7862,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); @@ -7994,7 +7994,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 { @@ -8103,13 +8103,15 @@ void Player::ApplyArtifactPowerRank(Item* artifact, ArtifactPowerRankEntry const } else if (apply) { - CustomSpellValues csv; + CastSpellExtraArgs args; + args.TriggerFlags = TRIGGERED_FULL_MASK; + args.CastItem = artifact; if (artifactPowerRank->AuraPointsOverride) for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (spellInfo->GetEffect(i)) - csv.AddSpellMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + i), artifactPowerRank->AuraPointsOverride); + args.AddSpellMod(SpellValueMod(SPELLVALUE_BASE_POINT0 + i), artifactPowerRank->AuraPointsOverride); - CastCustomSpell(artifactPowerRank->SpellID, csv, this, TRIGGERED_FULL_MASK, artifact); + CastSpell(this, artifactPowerRank->SpellID, args); } } else @@ -8166,7 +8168,7 @@ void Player::ApplyAzeriteItemMilestonePower(AzeriteItem* item, AzeriteItemMilest if (AzeritePowerEntry const* azeritePower = sAzeritePowerStore.LookupEntry(azeriteItemMilestonePower->AzeritePowerID)) { if (apply) - CastSpell(this, azeritePower->SpellID, true, item); + CastSpell(this, azeritePower->SpellID, item); else RemoveAurasDueToItemSpell(azeritePower->SpellID, item->GetGUID()); } @@ -8183,7 +8185,7 @@ void Player::ApplyAzeriteEssence(AzeriteItem* item, uint32 azeriteEssenceId, uin if (major && currentRank == 1) { if (apply) - CastCustomSpell(SPELL_ID_HEART_ESSENCE_ACTION_BAR_OVERRIDE, SPELLVALUE_BASE_POINT0, azeriteEssencePower->MajorPowerDescription, this, TRIGGERED_FULL_MASK); + CastSpell(this, SPELL_ID_HEART_ESSENCE_ACTION_BAR_OVERRIDE, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellBP0(azeriteEssencePower->MajorPowerDescription)); else RemoveAurasDueToSpell(SPELL_ID_HEART_ESSENCE_ACTION_BAR_OVERRIDE); } @@ -8196,7 +8198,7 @@ void Player::ApplyAzeriteEssencePower(AzeriteItem* item, AzeriteEssencePowerEntr if (SpellInfo const* powerSpell = sSpellMgr->GetSpellInfo(azeriteEssencePower->MinorPowerDescription, DIFFICULTY_NONE)) { if (apply) - CastSpell(this, powerSpell, true, item); + CastSpell(this, powerSpell->Id, item); else RemoveAurasDueToItemSpell(powerSpell->Id, item->GetGUID()); } @@ -8208,7 +8210,7 @@ void Player::ApplyAzeriteEssencePower(AzeriteItem* item, AzeriteEssencePowerEntr if (powerSpell->IsPassive()) { if (apply) - CastSpell(this, powerSpell, true, item); + CastSpell(this, powerSpell->Id, item); else RemoveAurasDueToItemSpell(powerSpell->Id, item->GetGUID()); } @@ -8228,7 +8230,7 @@ void Player::ApplyAzeritePower(AzeriteEmpoweredItem* item, AzeritePowerEntry con if (apply) { if (!azeritePower->SpecSetID || sDB2Manager.IsSpecSetMember(azeritePower->SpecSetID, GetPrimarySpecialization())) - CastSpell(this, azeritePower->SpellID, true, item); + CastSpell(this, azeritePower->SpellID, item); } else RemoveAurasDueToItemSpell(azeritePower->SpellID, item->GetGUID()); @@ -8320,7 +8322,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); } } @@ -8384,17 +8386,17 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT if (roll_chance_f(chance)) { if (spellInfo->IsPositive()) - CastSpell(this, spellInfo, true, item); + CastSpell(this, spellInfo->Id, item); else - CastSpell(damageInfo.GetVictim(), spellInfo, true, item); + CastSpell(damageInfo.GetVictim(), spellInfo->Id, item); } if (roll_chance_f(chance)) { 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->GetLevelForTarget(this) > 60) { int32 const lvlDifference = target->GetLevelForTarget(this) - 60; @@ -8405,11 +8407,10 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (spellInfo->GetEffect(i)->IsEffect()) - values.AddSpellMod(static_cast<SpellValueMod>(SPELLVALUE_BASE_POINT0 + i), CalculatePct(spellInfo->GetEffect(i)->CalcValue(this), effectPct)); + args.SpellValueOverrides.AddMod(static_cast<SpellValueMod>(SPELLVALUE_BASE_POINT0 + i), CalculatePct(spellInfo->GetEffect(i)->CalcValue(this), effectPct)); } } - - CastCustomSpell(spellInfo->Id, values, target, TRIGGERED_FULL_MASK, item); + CastSpell(target, spellInfo->Id, args); } } } @@ -8443,7 +8444,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, Objec spell->m_fromClient = true; spell->m_CastItem = item; spell->SetSpellValue(SPELLVALUE_BASE_POINT0, learning_spell_id); - spell->prepare(&targets); + spell->prepare(targets); return; } } @@ -8473,7 +8474,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, Objec spell->m_CastItem = item; spell->m_misc.Raw.Data[0] = misc[0]; spell->m_misc.Raw.Data[1] = misc[1]; - spell->prepare(&targets); + spell->prepare(targets); return; } @@ -8507,7 +8508,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, Objec spell->m_CastItem = item; spell->m_misc.Raw.Data[0] = misc[0]; spell->m_misc.Raw.Data[1] = misc[1]; - spell->prepare(&targets); + spell->prepare(targets); return; } } @@ -14301,7 +14302,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool if (enchant_spell_id) { if (apply) - CastSpell(this, enchant_spell_id, true, item); + CastSpell(this, enchant_spell_id, item); else RemoveAurasDueToItemSpell(enchant_spell_id, item->GetGUID()); } @@ -14918,7 +14919,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 optionIndex, uint32 menu 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); @@ -15604,7 +15605,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver) if (Unit* unit = questGiver->ToUnit()) caster = unit; - caster->CastSpell(this, spellInfo, true); + caster->CastSpell(this, spellInfo->Id, CastSpellExtraArgs(TRIGGERED_FULL_MASK).SetCastDifficulty(spellInfo->Difficulty)); } SetQuestSlot(log_slot, quest_id, qtime); @@ -15941,7 +15942,7 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew if (Unit* unit = questGiver->ToUnit()) caster = unit; - caster->CastSpell(this, spellInfo, true); + caster->CastSpell(this, spellInfo->Id, CastSpellExtraArgs(TRIGGERED_FULL_MASK).SetCastDifficulty(spellInfo->Difficulty)); } else { @@ -15957,7 +15958,7 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew if (Unit* unit = questGiver->ToUnit()) caster = unit; - caster->CastSpell(this, spellInfo, true); + caster->CastSpell(this, spellInfo->Id, CastSpellExtraArgs(TRIGGERED_FULL_MASK).SetCastDifficulty(spellInfo->Difficulty)); } } @@ -22449,7 +22450,7 @@ void Player::VehicleSpellInitialize() } if (spellInfo->IsPassive()) - vehicle->CastSpell(vehicle, spellInfo, true); + vehicle->CastSpell(vehicle, spellInfo->Id, true); petSpells.ActionButtons[i] = MAKE_UNIT_ACTION_BUTTON(spellId, i + 8); } @@ -25794,7 +25795,7 @@ bool Player::IsAtRecruitAFriendDistance(WorldObject const* pOther) const void Player::ResurrectUsingRequestData() { - /// 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()) @@ -25825,7 +25826,7 @@ void Player::ResurrectUsingRequestDataImpl() SetPower(POWER_LUNAR_POWER, 0); if (uint32 aura = resurrectAura) - CastSpell(this, aura, true, nullptr, nullptr, resurrectGUID); + CastSpell(this, aura, resurrectGUID); SpawnCorpseBones(); } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index d69a54935e9..0121c59f71d 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1001,147 +1001,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) - { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell by caster: %s", 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, GetMap()->GetDifficultyID()); - if (!spellInfo) - { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s", spellId, GetGUID().ToString().c_str()); - 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, GetMap()->GetDifficultyID()); - if (!spellInfo) + SpellInfo const* info = sSpellMgr->GetSpellInfo(spellId, args.CastDifficulty != DIFFICULTY_NONE ? args.CastDifficulty : GetMap()->GetDifficultyID()); + if (!info) { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s", spellId, GetGUID().ToString().c_str()); + TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell %u by caster %s", spellId, GetGUID().ToString().c_str()); return; } - SpellCastTargets targets; - targets.SetUnitTarget(victim); - CastSpell(targets, spellInfo, &value, triggerFlags, castItem, triggeredByAura, originalCaster); -} + Spell* spell = new Spell(this, info, args.TriggerFlags, args.OriginalCaster); + for (auto const& pair : args.SpellValueOverrides) + spell->SetSpellValue(pair.first, pair.second); -void Unit::CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) -{ - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID()); - if (!spellInfo) - { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s", spellId, GetGUID().ToString().c_str()); - return; - } - SpellCastTargets targets; - targets.SetDst(x, y, z, GetOrientation()); - - CastSpell(targets, spellInfo, nullptr, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster); + spell->m_CastItem = args.CastItem; + spell->prepare(targets, args.TriggeringAura); } -void Unit::CastSpell(float x, float y, float z, uint32 spellId, TriggerCastFlags triggerFlags, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) +void Unit::CastSpell(WorldObject* target, uint32 spellId, CastSpellExtraArgs const& args) { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID()); - if (!spellInfo) - { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s", spellId, GetGUID().ToString().c_str()); - return; - } SpellCastTargets targets; - targets.SetDst(x, y, z, GetOrientation()); - - CastSpell(targets, spellInfo, nullptr, triggerFlags, castItem, triggeredByAura, originalCaster); -} - -void Unit::CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) -{ - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID()); - if (!spellInfo) + if (target) { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s", spellId, GetGUID().ToString().c_str()); - 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.SetGOTarget(go); - - CastSpell(targets, spellInfo, nullptr, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster); + CastSpell(targets, spellId, args); } -void Unit::CastSpell(Item* target, uint32 spellId, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster) +void Unit::CastSpell(Position const& dest, uint32 spellId, CastSpellExtraArgs const& args) { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetMap()->GetDifficultyID()); - if (!spellInfo) - { - TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell id %u by caster: %s", spellId, GetGUID().ToString().c_str()); - return; - } SpellCastTargets targets; - targets.SetItemTarget(target); - - 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) @@ -2125,7 +2024,10 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr } else { - CastSpell(victim, meleeAttackSpellId, true, nullptr, meleeAttackAuraEffect); + CastSpellExtraArgs args; + args.TriggerFlags = TRIGGERED_FULL_MASK; + args.TriggeringAura = meleeAttackAuraEffect; + CastSpell(victim, meleeAttackSpellId, args); uint32 hitInfo = HITINFO_AFFECTS_VICTIM | HITINFO_NO_ANIMATION; if (attType == OFF_ATTACK) @@ -2996,7 +2898,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); @@ -5991,7 +5893,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()) @@ -6004,7 +5906,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); } } } @@ -10181,7 +10083,10 @@ void Unit::TriggerOnPowerChangeAuras(Powers power, int32 oldVal, int32 newVal) break; } - CastSpell(this, triggerSpell, true, nullptr, effect); + CastSpellExtraArgs args; + args.TriggerFlags = TRIGGERED_FULL_MASK; + args.TriggeringAura = effect; + CastSpell(this, triggerSpell, args); } } } @@ -10452,7 +10357,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); } @@ -10485,7 +10390,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 @@ -13012,7 +12917,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]; @@ -13027,7 +12937,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, ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellEntry->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()), MAX_EFFECT_MASK, this, clicker, GetMap()->GetDifficultyID(), nullptr, nullptr, origCasterGUID); } @@ -13044,7 +12954,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 0a1f3c72686..92da6ccbb20 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -39,125 +39,6 @@ #define SPELL_DH_DOUBLE_JUMP 196055 #define DISPLAYID_HIDDEN_MOUNT 73200 -enum class SpellModOp : uint8 -{ - HealingAndDamage = 0, - Duration = 1, - Hate = 2, - PointsIndex0 = 3, - ProcCharges = 4, - Range = 5, - Radius = 6, - CritChance = 7, - Points = 8, - ResistPushback = 9, - ChangeCastTime = 10, - Cooldown = 11, - PointsIndex1 = 12, - TargetResistance = 13, - PowerCost0 = 14, // Used when SpellPowerEntry::PowerIndex == 0 - CritDamageAndHealing = 15, - HitChance = 16, - ChainTargets = 17, - ProcChance = 18, - Period = 19, - ChainAmplitude = 20, - StartCooldown = 21, - PeriodicHealingAndDamage = 22, - PointsIndex2 = 23, - BonusCoefficient = 24, - TriggerDamage = 25, // NYI - ProcFrequency = 26, - Amplitude = 27, - DispelResistance = 28, - CrowdDamage = 29, // NYI - PowerCostOnMiss = 30, - Doses = 31, - PointsIndex3 = 32, - PointsIndex4 = 33, - PowerCost1 = 34, // Used when SpellPowerEntry::PowerIndex == 1 - ChainJumpDistance = 35, - AreaTriggerMaxSummons = 36, // NYI - MaxAuraStacks = 37, - ProcCooldown = 38, - PowerCost2 = 39, // Used when SpellPowerEntry::PowerIndex == 2 -}; - -#define MAX_SPELLMOD 40 - -enum SpellValueMod : uint8 -{ - SPELLVALUE_BASE_POINT0, - SPELLVALUE_BASE_POINT1, - SPELLVALUE_BASE_POINT2, - SPELLVALUE_BASE_POINT3, - SPELLVALUE_BASE_POINT4, - SPELLVALUE_BASE_POINT5, - SPELLVALUE_BASE_POINT6, - SPELLVALUE_BASE_POINT7, - SPELLVALUE_BASE_POINT8, - SPELLVALUE_BASE_POINT9, - SPELLVALUE_BASE_POINT10, - SPELLVALUE_BASE_POINT11, - SPELLVALUE_BASE_POINT12, - SPELLVALUE_BASE_POINT13, - SPELLVALUE_BASE_POINT14, - SPELLVALUE_BASE_POINT15, - SPELLVALUE_BASE_POINT16, - SPELLVALUE_BASE_POINT17, - SPELLVALUE_BASE_POINT18, - SPELLVALUE_BASE_POINT19, - SPELLVALUE_BASE_POINT20, - SPELLVALUE_BASE_POINT21, - SPELLVALUE_BASE_POINT22, - SPELLVALUE_BASE_POINT23, - SPELLVALUE_BASE_POINT24, - SPELLVALUE_BASE_POINT25, - SPELLVALUE_BASE_POINT26, - SPELLVALUE_BASE_POINT27, - SPELLVALUE_BASE_POINT28, - SPELLVALUE_BASE_POINT29, - SPELLVALUE_BASE_POINT30, - SPELLVALUE_BASE_POINT31, - SPELLVALUE_BASE_POINT_END, - 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 -}; - #define MAX_SPELL_CHARM 4 #define MAX_SPELL_VEHICLE 6 #define MAX_SPELL_POSSESS 8 @@ -284,36 +165,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_IGNORE_TARGET_CHECK = 0x00100000, //! Will ignore most target checks (mostly DBC target checks) - TRIGGERED_FULL_DEBUG_MASK = 0xFFFFFFFF -}; - enum UnitMods { UNIT_MOD_STAT_STRENGTH, // UNIT_MOD_STAT_STRENGTH..UNIT_MOD_STAT_INTELLECT must be in existed order, it's accessed by index values of Stats enum. @@ -1326,21 +1177,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 const* 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 const* 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 const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); - void CastSpell(Item* target, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect const* 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, uint32 effMask, Unit* target); void SetAuraStack(uint32 spellId, Unit* target, uint32 stack); diff --git a/src/server/game/Entities/Unit/UnitDefines.h b/src/server/game/Entities/Unit/UnitDefines.h index f12b41498d8..b0191780ae8 100644 --- a/src/server/game/Entities/Unit/UnitDefines.h +++ b/src/server/game/Entities/Unit/UnitDefines.h @@ -98,54 +98,6 @@ enum UnitPetFlag : uint8 UNIT_PET_FLAG_CAN_BE_ABANDONED = 0x02 }; -// high byte (3 from 0..3) of UNIT_FIELD_BYTES_2 -enum ShapeshiftForm -{ - FORM_NONE = 0, - FORM_CAT_FORM = 1, - FORM_TREE_OF_LIFE = 2, - FORM_TRAVEL_FORM = 3, - FORM_AQUATIC_FORM = 4, - FORM_BEAR_FORM = 5, - FORM_AMBIENT = 6, - FORM_GHOUL = 7, - FORM_DIRE_BEAR_FORM = 8, - FORM_CRANE_STANCE = 9, - FORM_THARONJA_SKELETON = 10, - FORM_DARKMOON_TEST_OF_STRENGTH = 11, - FORM_BLB_PLAYER = 12, - FORM_SHADOW_DANCE = 13, - FORM_CREATURE_BEAR = 14, - FORM_CREATURE_CAT = 15, - FORM_GHOST_WOLF = 16, - FORM_BATTLE_STANCE = 17, - FORM_DEFENSIVE_STANCE = 18, - FORM_BERSERKER_STANCE = 19, - FORM_SERPENT_STANCE = 20, - FORM_ZOMBIE = 21, - FORM_METAMORPHOSIS = 22, - FORM_OX_STANCE = 23, - FORM_TIGER_STANCE = 24, - FORM_UNDEAD = 25, - FORM_FRENZY = 26, - FORM_FLIGHT_FORM_EPIC = 27, - FORM_SHADOWFORM = 28, - FORM_FLIGHT_FORM = 29, - FORM_STEALTH = 30, - FORM_MOONKIN_FORM = 31, - FORM_SPIRIT_OF_REDEMPTION = 32, - FORM_GLADIATOR_STANCE = 33, - FORM_METAMORPHOSIS_2 = 34, - FORM_MOONKIN_FORM_RESTORATION = 35, - FORM_TREANT_FORM = 36, - FORM_SPIRIT_OWL_FORM = 37, - FORM_SPIRIT_OWL_FORM_2 = 38, - FORM_WISP_FORM = 39, - FORM_WISP_FORM_2 = 40, - FORM_SOULSHAPE = 41, - FORM_FORGEBORNE_REVERIES = 42 -}; - enum UnitMoveType { MOVE_WALK = 0, diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 66275e774bd..caae1003ccd 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1217,10 +1217,10 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) { // not blizz like, we must correctly save and load player instead... if (pCurrChar->getRace() == RACE_NIGHTELF && !pCurrChar->HasAura(20584)) - 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, 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) if (!pCurrChar->HasAura(8326)) - pCurrChar->CastSpell(pCurrChar, 8326, true, nullptr); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) + pCurrChar->CastSpell(pCurrChar, 8326, true); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) pCurrChar->SetWaterWalking(true); } diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index ee05f6918c2..9a2863ae12c 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -387,7 +387,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe } } - spell->prepare(&(spell->m_targets)); + spell->prepare(spell->m_targets); } else { @@ -713,7 +713,7 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPackets::Spells::PetCastSpell& spellPrepare.ServerCastID = spell->m_castId; SendPacket(spellPrepare.Write()); - spell->prepare(&targets); + spell->prepare(targets); } else { diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 11db09e1013..ad2a073a4a4 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -342,7 +342,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::CastSpell& cast) spell->m_fromClient = true; spell->m_misc.Raw.Data[0] = cast.Cast.Misc[0]; spell->m_misc.Raw.Data[1] = cast.Cast.Misc[1]; - spell->prepare(&targets); + spell->prepare(targets); } void WorldSession::HandleCancelCastOpcode(WorldPackets::Spells::CancelCast& packet) @@ -489,14 +489,10 @@ void WorldSession::HandleSelfResOpcode(WorldPackets::Spells::SelfRes& selfRes) if (_player->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) return; // silent return, client should display error by itself and not send this opcode - auto const& selfResSpells = _player->m_activePlayerData->SelfResSpells; - if (std::find(selfResSpells.begin(), selfResSpells.end(), selfRes.SpellID) == selfResSpells.end()) + if (_player->m_activePlayerData->SelfResSpells.FindIndex(selfRes.SpellID) < 0) return; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(selfRes.SpellID, _player->GetMap()->GetDifficultyID()); - if (spellInfo) - _player->CastSpell(_player, spellInfo, false, nullptr); - + _player->CastSpell(_player, selfRes.SpellID, _player->GetMap()->GetDifficultyID()); _player->RemoveSelfResSpell(selfRes.SpellID); } diff --git a/src/server/game/Handlers/ToyHandler.cpp b/src/server/game/Handlers/ToyHandler.cpp index 42a0408b6e3..7f310325047 100644 --- a/src/server/game/Handlers/ToyHandler.cpp +++ b/src/server/game/Handlers/ToyHandler.cpp @@ -93,7 +93,7 @@ void WorldSession::HandleUseToy(WorldPackets::Toy::UseToy& packet) spell->m_misc.Raw.Data[0] = packet.Cast.Misc[0]; spell->m_misc.Raw.Data[1] = packet.Cast.Misc[1]; spell->m_castFlagsEx |= CAST_FLAG_EX_USE_TOY_SPELL; - spell->prepare(&targets); + spell->prepare(targets); } void WorldSession::HandleToyClearFanfare(WorldPackets::Toy::ToyClearFanfare& toyClearFanfare) diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index c53c68ce681..69791345e3f 100644 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -509,10 +509,10 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPackets::Trade::AcceptTrade& acc 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 ec87dc3eb3e..7c9944a1929 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -591,4 +591,52 @@ enum AuraObjectType DYNOBJ_AURA_TYPE }; +// high byte (3 from 0..3) of UNIT_FIELD_BYTES_2 +enum ShapeshiftForm +{ + FORM_NONE = 0, + FORM_CAT_FORM = 1, + FORM_TREE_OF_LIFE = 2, + FORM_TRAVEL_FORM = 3, + FORM_AQUATIC_FORM = 4, + FORM_BEAR_FORM = 5, + FORM_AMBIENT = 6, + FORM_GHOUL = 7, + FORM_DIRE_BEAR_FORM = 8, + FORM_CRANE_STANCE = 9, + FORM_THARONJA_SKELETON = 10, + FORM_DARKMOON_TEST_OF_STRENGTH = 11, + FORM_BLB_PLAYER = 12, + FORM_SHADOW_DANCE = 13, + FORM_CREATURE_BEAR = 14, + FORM_CREATURE_CAT = 15, + FORM_GHOST_WOLF = 16, + FORM_BATTLE_STANCE = 17, + FORM_DEFENSIVE_STANCE = 18, + FORM_BERSERKER_STANCE = 19, + FORM_SERPENT_STANCE = 20, + FORM_ZOMBIE = 21, + FORM_METAMORPHOSIS = 22, + FORM_OX_STANCE = 23, + FORM_TIGER_STANCE = 24, + FORM_UNDEAD = 25, + FORM_FRENZY = 26, + FORM_FLIGHT_FORM_EPIC = 27, + FORM_SHADOWFORM = 28, + FORM_FLIGHT_FORM = 29, + FORM_STEALTH = 30, + FORM_MOONKIN_FORM = 31, + FORM_SPIRIT_OF_REDEMPTION = 32, + FORM_GLADIATOR_STANCE = 33, + FORM_METAMORPHOSIS_2 = 34, + FORM_MOONKIN_FORM_RESTORATION = 35, + FORM_TREANT_FORM = 36, + FORM_SPIRIT_OWL_FORM = 37, + FORM_SPIRIT_OWL_FORM_2 = 38, + FORM_WISP_FORM = 39, + FORM_WISP_FORM_2 = 40, + FORM_SOULSHAPE = 41, + FORM_FORGEBORNE_REVERIES = 42 +}; + #endif diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 515badef5aa..cf5ed8a765d 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1234,16 +1234,16 @@ 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 (spellId3) - target->CastSpell(target, spellId3, true, nullptr, this); + target->CastSpell(target, spellId3, this); if (spellId4) - target->CastSpell(target, spellId4, true, nullptr, this); + target->CastSpell(target, spellId4, this); if (target->GetTypeId() == TYPEID_PLAYER) { @@ -1267,7 +1267,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); } } } @@ -1703,12 +1703,12 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo case FORM_BEAR_FORM: case FORM_CAT_FORM: 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_FORM: if (AuraEffect* dummy = target->GetAuraEffect(37324, 0)) - target->CastSpell(target, 37325, true, nullptr, dummy); + target->CastSpell(target, 37325, dummy); break; default: break; @@ -4382,7 +4382,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 { @@ -4390,7 +4390,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()); @@ -4411,15 +4411,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 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); @@ -4428,9 +4428,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 @@ -4468,7 +4468,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) @@ -4488,7 +4488,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 @@ -4497,7 +4497,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; } @@ -4511,14 +4511,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 91604: // Restricted Flight Area if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) @@ -4558,9 +4558,13 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool if (apply && caster) { SpellInfo const* spell = sSpellMgr->AssertSpellInfo(spellId, GetBase()->GetCastDifficulty()); + CastSpellExtraArgs args; + args.TriggerFlags = TRIGGERED_FULL_MASK; + args.OriginalCaster = GetCasterGUID(); + args.CastDifficulty = spell->Difficulty; for (uint32 i = 0; i < spell->StackAmount; ++i) - caster->CastSpell(target, spell, true, nullptr, nullptr, GetCasterGUID()); + caster->CastSpell(target, spell->Id, args); break; } target->RemoveAurasDueToSpell(spellId); @@ -4573,8 +4577,13 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool if (apply && caster) { SpellInfo const* spell = sSpellMgr->AssertSpellInfo(spellId, GetBase()->GetCastDifficulty()); + CastSpellExtraArgs args; + args.TriggerFlags = TRIGGERED_FULL_MASK; + args.OriginalCaster = GetCasterGUID(); + args.CastDifficulty = spell->Difficulty; + for (uint32 i = 0; i < spell->StackAmount; ++i) - caster->CastSpell(target, spell, true, nullptr, nullptr, GetCasterGUID()); + caster->CastSpell(target, spell->Id, args); break; } target->RemoveAurasDueToSpell(spellId); @@ -4860,11 +4869,13 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo { if (apply) { - // 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 { @@ -5081,12 +5092,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 @@ -5096,13 +5107,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 @@ -5152,7 +5165,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000)) { if (caster->GetTypeId() == TYPEID_PLAYER && caster->ToPlayer()->isHonorOrXPTarget(target)) - caster->CastSpell(caster, 95810, true, nullptr, this); + caster->CastSpell(caster, 95810, this); } if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_GENERIC) { @@ -5515,7 +5528,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); } } @@ -5654,7 +5670,7 @@ void AuraEffect::HandleProcTriggerSpellAuraProc(AuraApplication* aurApp, ProcEve if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty())) { 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 if (triggerSpellId && GetAuraType() != SPELL_AURA_DUMMY) 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()); @@ -5668,9 +5684,10 @@ void AuraEffect::HandleProcTriggerSpellWithValueAuraProc(AuraApplication* aurApp uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId, GetBase()->GetCastDifficulty())) { - 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()); @@ -5853,7 +5870,13 @@ void AuraEffect::HandleLinkedSummon(AuraApplication const* aurApp, uint8 mode, b // on apply cast summon spell if (apply) - target->CastSpell(target, triggerSpellInfo, true, nullptr, this); + { + CastSpellExtraArgs args; + args.TriggerFlags = TRIGGERED_FULL_MASK; + args.TriggeringAura = this; + args.CastDifficulty = triggerSpellInfo->Difficulty; + target->CastSpell(target, triggerSpellInfo->Id, args); + } // on unapply we need to search for and remove the summoned creature else { diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index dfe0ef6276a..8f9d716a304 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -1249,7 +1249,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)) @@ -1311,8 +1311,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; @@ -1329,7 +1330,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: @@ -1363,8 +1364,9 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b if (AuraEffect const* aurEff = aura->GetEffect(0)) { float multiplier = float(aurEff->GetAmount()); - 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); } } } @@ -1391,7 +1393,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b if (owner->HasAura(34692)) { if (apply) - owner->CastSpell(owner, 34471, true, nullptr, 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 0e897c3b109..25e0e56bdf5 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2767,7 +2767,7 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint32 effMask) { if (CanExecuteTriggersOnHit(effMask, i->triggeredByAura) && roll_chance_i(i->chance)) { - m_caster->CastSpell(unit, i->triggeredSpell, TRIGGERED_FULL_MASK); + m_caster->CastSpell(unit, i->triggeredSpell->Id, CastSpellExtraArgs(TRIGGERED_FULL_MASK).SetCastDifficulty(i->triggeredSpell->Difficulty)); 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 @@ -2798,7 +2798,7 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint32 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()); } } } @@ -2916,7 +2916,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) { @@ -2935,7 +2935,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered } } - InitExplicitTargets(*targets); + InitExplicitTargets(targets); m_spellState = SPELL_STATE_PREPARING; @@ -5597,7 +5597,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 811a3c55159..8253062a290 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -522,7 +522,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 index c330b2b1aa8..0b81f9ced5c 100644 --- a/src/server/game/Spells/SpellDefines.h +++ b/src/server/game/Spells/SpellDefines.h @@ -20,6 +20,12 @@ #include "Define.h" #include "EnumFlag.h" +#include "ObjectGuid.h" +#include <vector> + +class Item; +class AuraEffect; +enum Difficulty : uint8; namespace UF { @@ -122,6 +128,168 @@ enum class SpellAuraInterruptFlags2 : uint32 DEFINE_ENUM_FLAG(SpellAuraInterruptFlags2); +enum class SpellModOp : uint8 +{ + HealingAndDamage = 0, + Duration = 1, + Hate = 2, + PointsIndex0 = 3, + ProcCharges = 4, + Range = 5, + Radius = 6, + CritChance = 7, + Points = 8, + ResistPushback = 9, + ChangeCastTime = 10, + Cooldown = 11, + PointsIndex1 = 12, + TargetResistance = 13, + PowerCost0 = 14, // Used when SpellPowerEntry::PowerIndex == 0 + CritDamageAndHealing = 15, + HitChance = 16, + ChainTargets = 17, + ProcChance = 18, + Period = 19, + ChainAmplitude = 20, + StartCooldown = 21, + PeriodicHealingAndDamage = 22, + PointsIndex2 = 23, + BonusCoefficient = 24, + TriggerDamage = 25, // NYI + ProcFrequency = 26, + Amplitude = 27, + DispelResistance = 28, + CrowdDamage = 29, // NYI + PowerCostOnMiss = 30, + Doses = 31, + PointsIndex3 = 32, + PointsIndex4 = 33, + PowerCost1 = 34, // Used when SpellPowerEntry::PowerIndex == 1 + ChainJumpDistance = 35, + AreaTriggerMaxSummons = 36, // NYI + MaxAuraStacks = 37, + ProcCooldown = 38, + PowerCost2 = 39, // Used when SpellPowerEntry::PowerIndex == 2 +}; + +#define MAX_SPELLMOD 40 + +enum SpellValueMod : uint8 +{ + SPELLVALUE_BASE_POINT0, + SPELLVALUE_BASE_POINT1, + SPELLVALUE_BASE_POINT2, + SPELLVALUE_BASE_POINT3, + SPELLVALUE_BASE_POINT4, + SPELLVALUE_BASE_POINT5, + SPELLVALUE_BASE_POINT6, + SPELLVALUE_BASE_POINT7, + SPELLVALUE_BASE_POINT8, + SPELLVALUE_BASE_POINT9, + SPELLVALUE_BASE_POINT10, + SPELLVALUE_BASE_POINT11, + SPELLVALUE_BASE_POINT12, + SPELLVALUE_BASE_POINT13, + SPELLVALUE_BASE_POINT14, + SPELLVALUE_BASE_POINT15, + SPELLVALUE_BASE_POINT16, + SPELLVALUE_BASE_POINT17, + SPELLVALUE_BASE_POINT18, + SPELLVALUE_BASE_POINT19, + SPELLVALUE_BASE_POINT20, + SPELLVALUE_BASE_POINT21, + SPELLVALUE_BASE_POINT22, + SPELLVALUE_BASE_POINT23, + SPELLVALUE_BASE_POINT24, + SPELLVALUE_BASE_POINT25, + SPELLVALUE_BASE_POINT26, + SPELLVALUE_BASE_POINT27, + SPELLVALUE_BASE_POINT28, + SPELLVALUE_BASE_POINT29, + SPELLVALUE_BASE_POINT30, + SPELLVALUE_BASE_POINT31, + SPELLVALUE_BASE_POINT_END, + 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_IGNORE_TARGET_CHECK = 0x00100000, //! Will ignore most target checks (mostly DBC target checks) + TRIGGERED_FULL_DEBUG_MASK = 0xFFFFFFFF +}; + +struct TC_GAME_API CastSpellExtraArgs +{ + CastSpellExtraArgs() = default; + 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(Difficulty castDifficulty) : CastDifficulty(castDifficulty) {} + 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& SetCastDifficulty(Difficulty castDifficulty) { CastDifficulty = castDifficulty; 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; + Difficulty CastDifficulty = Difficulty(0); + struct + { + public: + void AddMod(SpellValueMod mod, int32 val) { data.emplace_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; +}; + struct SpellCastVisual { uint32 SpellXSpellVisualID = 0; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index d39479ccd5a..d7cfda76147 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -714,17 +714,14 @@ void Spell::EffectTriggerSpell(SpellEffIndex /*effIndex*/) targets.SetUnitTarget(m_caster); } - CustomSpellValues values; + CastSpellExtraArgs args(m_originalCasterGUID); // set basepoints for trigger with value effect if (effectInfo->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*/) @@ -761,18 +758,14 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex /*effIndex*/) targets.SetUnitTarget(m_caster); } - CustomSpellValues values; + CastSpellExtraArgs args(m_originalCasterGUID); // set basepoints for trigger with value effect if (effectInfo->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*/) @@ -804,32 +797,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 (effectInfo->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*/) @@ -848,7 +837,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*/) @@ -2048,11 +2037,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) @@ -2809,7 +2800,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: @@ -3076,7 +3067,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 @@ -3281,7 +3272,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; } @@ -3386,7 +3377,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(); } @@ -3405,7 +3396,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) { @@ -3415,7 +3405,9 @@ 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); } } break; @@ -3808,7 +3800,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, effectInfo->TriggerSpell, &benefit, nullptr, nullptr, true); + CastSpellExtraArgs args(TRIGGERED_FULL_MASK); + args.SpellValueOverrides.AddMod(SPELLVALUE_BASE_POINT0, benefit); + m_caster->CastSpell(pet, effectInfo->TriggerSpell, args); } void Spell::EffectDismissPet(SpellEffIndex effIndex) @@ -4172,7 +4166,7 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/) m_caster->Attack(unitTarget, true); if (effectInfo->TriggerSpell) - m_caster->CastSpell(unitTarget, effectInfo->TriggerSpell, true, nullptr, nullptr, m_originalCasterGUID); + m_caster->CastSpell(unitTarget, effectInfo->TriggerSpell, m_originalCasterGUID); } } @@ -4197,7 +4191,7 @@ void Spell::EffectChargeDest(SpellEffIndex /*effIndex*/) else if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT) { if (effectInfo->TriggerSpell) - m_caster->CastSpell(destTarget->GetPositionX(), destTarget->GetPositionY(), destTarget->GetPositionZ(), effectInfo->TriggerSpell, true, nullptr, nullptr, m_originalCasterGUID); + m_caster->CastSpell(*destTarget, effectInfo->TriggerSpell, m_originalCasterGUID); } } @@ -4485,7 +4479,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) @@ -5276,8 +5274,10 @@ void Spell::EffectCastButtons(SpellEffIndex /*effIndex*/) if (!spellInfo->HasAttribute(SPELL_ATTR9_SUMMON_PLAYER_TOTEM)) continue; - TriggerCastFlags triggerFlags = TriggerCastFlags(TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_CAST_DIRECTLY | TRIGGERED_DONT_REPORT_CAST_ERROR); - m_caster->CastSpell(m_caster, spellInfo, triggerFlags); + CastSpellExtraArgs args; + args.TriggerFlags = TriggerCastFlags(TRIGGERED_IGNORE_GCD | TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_CAST_DIRECTLY | TRIGGERED_DONT_REPORT_CAST_ERROR); + args.CastDifficulty = GetCastDifficulty(); + m_caster->CastSpell(m_caster, spellInfo->Id, args); } } diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 206e5a35cac..76b7aa34161 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3455,14 +3455,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; }); |
