diff options
20 files changed, 974 insertions, 621 deletions
diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h index e770a8b34a3..000028ef852 100644 --- a/src/server/game/Entities/Object/ObjectGuid.h +++ b/src/server/game/Entities/Object/ObjectGuid.h @@ -181,7 +181,7 @@ GUID_TRAIT_MAP_SPECIFIC(HighGuid::CallForHelp) GUID_TRAIT_MAP_SPECIFIC(HighGuid::AIResource) GUID_TRAIT_MAP_SPECIFIC(HighGuid::AILock) GUID_TRAIT_MAP_SPECIFIC(HighGuid::AILockTicket) -GUID_TRAIT_MAP_SPECIFIC(HighGuid::Cast) // Guessed +GUID_TRAIT_MAP_SPECIFIC(HighGuid::Cast) class ObjectGuid; class PackedGuid; @@ -209,6 +209,9 @@ class TC_GAME_API ObjectGuid template<HighGuid type> static typename std::enable_if<ObjectGuidTraits<type>::MapSpecific, ObjectGuid>::type Create(uint16 mapId, uint32 entry, LowType counter) { return MapSpecific(type, 0, mapId, 0, entry, counter); } + template<HighGuid type> + static typename std::enable_if<ObjectGuidTraits<type>::MapSpecific, ObjectGuid>::type Create(uint8 subType, uint16 mapId, uint32 entry, LowType counter) { return MapSpecific(type, subType, mapId, 0, entry, counter); } + ObjectGuid() : _low(0), _high(0) { } std::vector<uint8> GetRawValue() const; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 332924c0ea0..fb7ba8f22b7 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -1239,7 +1239,8 @@ void Pet::_LoadAuras(uint32 timediff) remainCharges = 0; AuraLoadEffectInfo& info = effectInfo[key]; - if (Aura* aura = Aura::TryCreate(spellInfo, key.EffectMask, this, NULL, info.BaseAmounts.data(), NULL, casterGuid)) + ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellInfo->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()); + if (Aura* aura = Aura::TryCreate(spellInfo, castId, key.EffectMask, this, NULL, info.BaseAmounts.data(), NULL, casterGuid)) { if (!aura->CanBeSaved()) { diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index b0b661b1393..2f626fc39ea 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -7790,8 +7790,13 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, Objec } Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE); + + WorldPackets::Spells::SpellPrepare spellPrepare; + spellPrepare.ClientCastID = castCount; + spellPrepare.ServerCastID = spell->m_castId; + SendDirectMessage(spellPrepare.Write()); + spell->m_CastItem = item; - spell->m_cast_count = castCount; //set count of casts spell->SetSpellValue(SPELLVALUE_BASE_POINT0, learning_spell_id); spell->prepare(&targets); return; @@ -7815,8 +7820,13 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, Objec } Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE); + + WorldPackets::Spells::SpellPrepare spellPrepare; + spellPrepare.ClientCastID = castCount; + spellPrepare.ServerCastID = spell->m_castId; + SendDirectMessage(spellPrepare.Write()); + spell->m_CastItem = item; - spell->m_cast_count = castCount; // set count of casts spell->m_misc.Raw.Data[0] = misc[0]; spell->m_misc.Raw.Data[1] = misc[1]; spell->prepare(&targets); @@ -7843,8 +7853,13 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, Objec } Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE); + + WorldPackets::Spells::SpellPrepare spellPrepare; + spellPrepare.ClientCastID = castCount; + spellPrepare.ServerCastID = spell->m_castId; + SendDirectMessage(spellPrepare.Write()); + spell->m_CastItem = item; - spell->m_cast_count = castCount; // set count of casts spell->m_misc.Raw.Data[0] = misc[0]; spell->m_misc.Raw.Data[1] = misc[1]; spell->prepare(&targets); @@ -17214,7 +17229,8 @@ void Player::_LoadAuras(PreparedQueryResult auraResult, PreparedQueryResult effe remainCharges = 0; AuraLoadEffectInfo& info = effectInfo[key]; - if (Aura* aura = Aura::TryCreate(spellInfo, key.EffectMask, this, nullptr, info.BaseAmounts.data(), nullptr, casterGuid, castItemLevel)) + ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellInfo->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()); + if (Aura* aura = Aura::TryCreate(spellInfo, castId, key.EffectMask, this, nullptr, info.BaseAmounts.data(), nullptr, casterGuid, castItemLevel)) { if (!aura->CanBeSaved()) { @@ -24123,8 +24139,27 @@ void Runes::SetRuneState(uint8 index, bool set /*= true*/) void Player::ResyncRunes() const { WorldPackets::Spells::ResyncRunes data(MAX_RUNES); + data.Runes.Start = 0; + data.Runes.Count = GetRunesState(); + for (uint32 i = 0; i < MAX_RUNES; ++i) - data.Runes.push_back(uint8(255 - (GetRuneCooldown(i) * 51))); + data.Runes.Cooldowns.push_back(uint8(255 - (GetRuneCooldown(i) * 51))); + + // calculate mask of recharging runes + uint32 regeneratedRunes = 0; + uint32 regenIndex = 0; + while (regeneratedRunes < MAX_RECHARGING_RUNES && !m_runes->CooldownOrder.empty()) + { + uint8 runeToRegen = m_runes->CooldownOrder[regenIndex++]; + uint32 runeCooldown = GetRuneCooldown(runeToRegen); + if (runeCooldown > m_regenTimer) + { + data.Runes.Start |= 1 << runeToRegen; + ++regenIndex; + } + + ++regeneratedRunes; + } GetSession()->SendPacket(data.Write()); } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 6a886ef3f62..4106beb6862 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3308,7 +3308,7 @@ void Unit::_RemoveNoStackAurasDueToAura(Aura* aura) { Unit* caster = aura->GetCaster(); if (caster && caster->GetTypeId() == TYPEID_PLAYER) - Spell::SendCastResult(caster->ToPlayer(), aura->GetSpellInfo(), ObjectGuid::Create<HighGuid::Cast>(GetMapId(), 0, 1), SPELL_FAILED_AURA_BOUNCED); + Spell::SendCastResult(caster->ToPlayer(), aura->GetSpellInfo(), aura->GetSpellInfo()->GetSpellXSpellVisualId(caster->GetMap()->GetDifficultyID()), aura->GetCastGUID(), SPELL_FAILED_AURA_BOUNCED); } aura->Remove(); @@ -3673,7 +3673,7 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, U if (aura->IsSingleTarget()) aura->UnregisterSingleTarget(); - if (Aura* newAura = Aura::TryRefreshStackOrCreate(aura->GetSpellInfo(), effMask, stealer, NULL, &baseDamage[0], NULL, aura->GetCasterGUID())) + if (Aura* newAura = Aura::TryRefreshStackOrCreate(aura->GetSpellInfo(), aura->GetCastGUID(), effMask, stealer, NULL, &baseDamage[0], NULL, aura->GetCasterGUID())) { // created aura must not be single target aura,, so stealer won't loose it on recast if (newAura->IsSingleTarget()) @@ -13968,7 +13968,8 @@ Aura* Unit::AddAura(SpellInfo const* spellInfo, uint32 effMask, Unit* target) effMask &= ~(1<<i); } - if (Aura* aura = Aura::TryRefreshStackOrCreate(spellInfo, effMask, target, this)) + ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellInfo->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()); + if (Aura* aura = Aura::TryRefreshStackOrCreate(spellInfo, castId, effMask, target, this)) { aura->ApplyForTargets(); return aura; @@ -14702,7 +14703,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) bp0[effect->EffectIndex] = effect->BasePoints; bp0[i] = seatId; - Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, bp0, NULL, origCasterGUID); + Aura::TryRefreshStackOrCreate(spellEntry, ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellEntry->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()), MAX_EFFECT_MASK, this, clicker, bp0, NULL, origCasterGUID); } } else @@ -14710,7 +14711,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) if (IsInMap(caster)) caster->CastSpell(target, spellEntry, GetVehicleKit() ? TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE : TRIGGERED_NONE, NULL, NULL, origCasterGUID); else - Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, NULL, NULL, origCasterGUID); + Aura::TryRefreshStackOrCreate(spellEntry, ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, GetMapId(), spellEntry->Id, GetMap()->GenerateLowGuid<HighGuid::Cast>()), MAX_EFFECT_MASK, this, clicker, NULL, NULL, origCasterGUID); } result = true; diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index c3a57893bfc..faf13940eff 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -380,7 +380,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe else { if (pet->isPossessed() || pet->IsVehicle()) /// @todo: confirm this check - Spell::SendCastResult(GetPlayer(), spellInfo, ObjectGuid::Create<HighGuid::Cast>(GetPlayer()->GetMapId(), 0, 0), result); + Spell::SendCastResult(GetPlayer(), spellInfo, spell->m_SpellVisual, spell->m_castId, result); else spell->SendPetCastResult(result); @@ -677,7 +677,6 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPackets::Spells::PetCastSpell& caster->ClearUnitState(UNIT_STATE_FOLLOW); Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE); - spell->m_cast_count = petCastSpell.Cast.CastID; spell->m_misc.Raw.Data[0] = petCastSpell.Cast.Misc[0]; spell->m_misc.Raw.Data[1] = petCastSpell.Cast.Misc[1]; spell->m_targets = targets; @@ -698,6 +697,11 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPackets::Spells::PetCastSpell& } } + WorldPackets::Spells::SpellPrepare spellPrepare; + spellPrepare.ClientCastID = petCastSpell.Cast.CastID; + spellPrepare.ServerCastID = spell->m_castId; + SendPacket(spellPrepare.Write()); + spell->prepare(&targets); } else diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 12dcfcb77df..323dec31e5a 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -300,7 +300,12 @@ void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::CastSpell& cast) } Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE, ObjectGuid::Empty, false); - spell->m_cast_count = cast.Cast.CastID; // set count of casts + + WorldPackets::Spells::SpellPrepare spellPrepare; + spellPrepare.ClientCastID = cast.Cast.CastID; + spellPrepare.ServerCastID = spell->m_castId; + SendPacket(spellPrepare.Write()); + spell->m_misc.Raw.Data[0] = cast.Cast.Misc[0]; spell->m_misc.Raw.Data[1] = cast.Cast.Misc[1]; spell->prepare(&targets); @@ -509,6 +514,8 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPackets::Spells::GetMirrorI mirrorImageComponentedData.HairVariation = player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID); mirrorImageComponentedData.HairColor = player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID); mirrorImageComponentedData.BeardVariation = player->GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE); + for (uint32 i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) + mirrorImageComponentedData.CustomDisplay[i] = player->GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_CUSTOM_DISPLAY_OPTION + i); mirrorImageComponentedData.GuildGUID = (guild ? guild->GetGUID() : ObjectGuid::Empty); mirrorImageComponentedData.ItemDisplayID.reserve(11); @@ -530,7 +537,7 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPackets::Spells::GetMirrorI }; // Display items in visible slots - for (auto const& slot : itemSlots) + for (EquipmentSlots slot : itemSlots) { uint32 itemDisplayId; if ((slot == EQUIPMENT_SLOT_HEAD && player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM)) || diff --git a/src/server/game/Handlers/ToyHandler.cpp b/src/server/game/Handlers/ToyHandler.cpp index 27edf4905ad..2e894438bf6 100644 --- a/src/server/game/Handlers/ToyHandler.cpp +++ b/src/server/game/Handlers/ToyHandler.cpp @@ -75,8 +75,13 @@ void WorldSession::HandleUseToy(WorldPackets::Toy::UseToy& packet) SpellCastTargets targets(_player, packet.Cast); Spell* spell = new Spell(_player, spellInfo, TRIGGERED_NONE, ObjectGuid::Empty, false); + + WorldPackets::Spells::SpellPrepare spellPrepare; + spellPrepare.ClientCastID = packet.Cast.CastID; + spellPrepare.ServerCastID = spell->m_castId; + SendPacket(spellPrepare.Write()); + spell->m_castItemEntry = packet.ItemID; - spell->m_cast_count = packet.Cast.CastID; 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; diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index cc87bf7ac08..dbabbf5a486 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -1270,7 +1270,7 @@ enum SpellEffectName TOTAL_SPELL_EFFECTS = 256, }; -enum SpellCastResult // 21355 +enum SpellCastResult { SPELL_FAILED_SUCCESS = 0, SPELL_FAILED_AFFECTING_COMBAT = 1, @@ -1324,51 +1324,51 @@ enum SpellCastResult // 21355 SPELL_FAILED_GARRISON_FOLLOWER_NOT_MAX_LEVEL = 49, SPELL_FAILED_GARRISON_FOLLOWER_HAS_ABILITY = 50, SPELL_FAILED_GARRISON_FOLLOWER_HAS_SINGLE_MISSION_ABILITY = 51, - SPELL_FAILED_GARRISON_MISSION_NOT_IN_PROGRESS = 52, - SPELL_FAILED_GARRISON_MISSION_COMPLETE = 53, - SPELL_FAILED_GARRISON_NO_MISSIONS_AVAILABLE = 54, - SPELL_FAILED_HIGHLEVEL = 55, - SPELL_FAILED_HUNGER_SATIATED = 56, - SPELL_FAILED_IMMUNE = 57, - SPELL_FAILED_INCORRECT_AREA = 58, - SPELL_FAILED_INTERRUPTED = 59, - SPELL_FAILED_INTERRUPTED_COMBAT = 60, - SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 61, - SPELL_FAILED_ITEM_GONE = 62, - SPELL_FAILED_ITEM_NOT_FOUND = 63, - SPELL_FAILED_ITEM_NOT_READY = 64, - SPELL_FAILED_LEVEL_REQUIREMENT = 65, - SPELL_FAILED_LINE_OF_SIGHT = 66, - SPELL_FAILED_LOWLEVEL = 67, - SPELL_FAILED_LOW_CASTLEVEL = 68, - SPELL_FAILED_MAINHAND_EMPTY = 69, - SPELL_FAILED_MOVING = 70, - SPELL_FAILED_NEED_AMMO = 71, - SPELL_FAILED_NEED_AMMO_POUCH = 72, - SPELL_FAILED_NEED_EXOTIC_AMMO = 73, - SPELL_FAILED_NEED_MORE_ITEMS = 74, - SPELL_FAILED_NOPATH = 75, - SPELL_FAILED_NOT_BEHIND = 76, - SPELL_FAILED_NOT_FISHABLE = 77, - SPELL_FAILED_NOT_FLYING = 78, - SPELL_FAILED_NOT_HERE = 79, - SPELL_FAILED_NOT_INFRONT = 80, - SPELL_FAILED_NOT_IN_CONTROL = 81, - SPELL_FAILED_NOT_KNOWN = 82, - SPELL_FAILED_NOT_MOUNTED = 83, - SPELL_FAILED_NOT_ON_TAXI = 84, - SPELL_FAILED_NOT_ON_TRANSPORT = 85, - SPELL_FAILED_NOT_READY = 86, - SPELL_FAILED_NOT_SHAPESHIFT = 87, - SPELL_FAILED_NOT_STANDING = 88, - SPELL_FAILED_NOT_TRADEABLE = 89, - SPELL_FAILED_NOT_TRADING = 90, - SPELL_FAILED_NOT_UNSHEATHED = 91, - SPELL_FAILED_NOT_WHILE_GHOST = 92, - SPELL_FAILED_NOT_WHILE_LOOTING = 93, - SPELL_FAILED_NO_AMMO = 94, - SPELL_FAILED_NO_CHARGES_REMAIN = 95, - SPELL_FAILED_NO_CHAMPION = 96, + SPELL_FAILED_GARRISON_FOLLOWER_REQUIRES_EPIC = 52, + SPELL_FAILED_GARRISON_MISSION_NOT_IN_PROGRESS = 53, + SPELL_FAILED_GARRISON_MISSION_COMPLETE = 54, + SPELL_FAILED_GARRISON_NO_MISSIONS_AVAILABLE = 55, + SPELL_FAILED_HIGHLEVEL = 56, + SPELL_FAILED_HUNGER_SATIATED = 57, + SPELL_FAILED_IMMUNE = 58, + SPELL_FAILED_INCORRECT_AREA = 59, + SPELL_FAILED_INTERRUPTED = 60, + SPELL_FAILED_INTERRUPTED_COMBAT = 61, + SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 62, + SPELL_FAILED_ITEM_GONE = 63, + SPELL_FAILED_ITEM_NOT_FOUND = 64, + SPELL_FAILED_ITEM_NOT_READY = 65, + SPELL_FAILED_LEVEL_REQUIREMENT = 66, + SPELL_FAILED_LINE_OF_SIGHT = 67, + SPELL_FAILED_LOWLEVEL = 68, + SPELL_FAILED_LOW_CASTLEVEL = 69, + SPELL_FAILED_MAINHAND_EMPTY = 70, + SPELL_FAILED_MOVING = 71, + SPELL_FAILED_NEED_AMMO = 72, + SPELL_FAILED_NEED_AMMO_POUCH = 73, + SPELL_FAILED_NEED_EXOTIC_AMMO = 74, + SPELL_FAILED_NEED_MORE_ITEMS = 75, + SPELL_FAILED_NOPATH = 76, + SPELL_FAILED_NOT_BEHIND = 77, + SPELL_FAILED_NOT_FISHABLE = 78, + SPELL_FAILED_NOT_FLYING = 79, + SPELL_FAILED_NOT_HERE = 80, + SPELL_FAILED_NOT_INFRONT = 81, + SPELL_FAILED_NOT_IN_CONTROL = 82, + SPELL_FAILED_NOT_KNOWN = 83, + SPELL_FAILED_NOT_MOUNTED = 84, + SPELL_FAILED_NOT_ON_TAXI = 85, + SPELL_FAILED_NOT_ON_TRANSPORT = 86, + SPELL_FAILED_NOT_READY = 87, + SPELL_FAILED_NOT_SHAPESHIFT = 88, + SPELL_FAILED_NOT_STANDING = 89, + SPELL_FAILED_NOT_TRADEABLE = 90, + SPELL_FAILED_NOT_TRADING = 91, + SPELL_FAILED_NOT_UNSHEATHED = 92, + SPELL_FAILED_NOT_WHILE_GHOST = 93, + SPELL_FAILED_NOT_WHILE_LOOTING = 94, + SPELL_FAILED_NO_AMMO = 95, + SPELL_FAILED_NO_CHARGES_REMAIN = 96, SPELL_FAILED_NO_COMBO_POINTS = 97, SPELL_FAILED_NO_DUELING = 98, SPELL_FAILED_NO_ENDURANCE = 99, @@ -1380,316 +1380,499 @@ enum SpellCastResult // 21355 SPELL_FAILED_NOTHING_TO_DISPEL = 105, SPELL_FAILED_NOTHING_TO_STEAL = 106, SPELL_FAILED_ONLY_ABOVEWATER = 107, - SPELL_FAILED_ONLY_DAYTIME = 108, - SPELL_FAILED_ONLY_INDOORS = 109, - SPELL_FAILED_ONLY_MOUNTED = 110, - SPELL_FAILED_ONLY_NIGHTTIME = 111, - SPELL_FAILED_ONLY_OUTDOORS = 112, - SPELL_FAILED_ONLY_SHAPESHIFT = 113, - SPELL_FAILED_ONLY_STEALTHED = 114, - SPELL_FAILED_ONLY_UNDERWATER = 115, - SPELL_FAILED_OUT_OF_RANGE = 116, - SPELL_FAILED_PACIFIED = 117, - SPELL_FAILED_POSSESSED = 118, - SPELL_FAILED_REAGENTS = 119, - SPELL_FAILED_REQUIRES_AREA = 120, - SPELL_FAILED_REQUIRES_SPELL_FOCUS = 121, - SPELL_FAILED_ROOTED = 122, - SPELL_FAILED_SILENCED = 123, - SPELL_FAILED_SPELL_IN_PROGRESS = 124, - SPELL_FAILED_SPELL_LEARNED = 125, - SPELL_FAILED_SPELL_UNAVAILABLE = 126, - SPELL_FAILED_STUNNED = 127, - SPELL_FAILED_TARGETS_DEAD = 128, - SPELL_FAILED_TARGET_AFFECTING_COMBAT = 129, - SPELL_FAILED_TARGET_AURASTATE = 130, - SPELL_FAILED_TARGET_DUELING = 131, - SPELL_FAILED_TARGET_ENEMY = 132, - SPELL_FAILED_TARGET_ENRAGED = 133, - SPELL_FAILED_TARGET_FRIENDLY = 134, - SPELL_FAILED_TARGET_IN_COMBAT = 135, - SPELL_FAILED_TARGET_IN_PET_BATTLE = 136, - SPELL_FAILED_TARGET_IS_PLAYER = 137, - SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 138, - SPELL_FAILED_TARGET_NOT_DEAD = 139, - SPELL_FAILED_TARGET_NOT_IN_PARTY = 140, - SPELL_FAILED_TARGET_NOT_LOOTED = 141, - SPELL_FAILED_TARGET_NOT_PLAYER = 142, - SPELL_FAILED_TARGET_NO_POCKETS = 143, - SPELL_FAILED_TARGET_NO_WEAPONS = 144, - SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 145, - SPELL_FAILED_TARGET_UNSKINNABLE = 146, - SPELL_FAILED_THIRST_SATIATED = 147, - SPELL_FAILED_TOO_CLOSE = 148, - SPELL_FAILED_TOO_MANY_OF_ITEM = 149, - SPELL_FAILED_TOTEM_CATEGORY = 150, - SPELL_FAILED_TOTEMS = 151, - SPELL_FAILED_TRY_AGAIN = 152, - SPELL_FAILED_UNIT_NOT_BEHIND = 153, - SPELL_FAILED_UNIT_NOT_INFRONT = 154, - SPELL_FAILED_VISION_OBSCURED = 155, - SPELL_FAILED_WRONG_PET_FOOD = 156, - SPELL_FAILED_NOT_WHILE_FATIGUED = 157, - SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 158, - SPELL_FAILED_NOT_WHILE_TRADING = 159, - SPELL_FAILED_TARGET_NOT_IN_RAID = 160, - SPELL_FAILED_TARGET_FREEFORALL = 161, - SPELL_FAILED_NO_EDIBLE_CORPSES = 162, - SPELL_FAILED_ONLY_BATTLEGROUNDS = 163, - SPELL_FAILED_TARGET_NOT_GHOST = 164, - SPELL_FAILED_TRANSFORM_UNUSABLE = 165, - SPELL_FAILED_WRONG_WEATHER = 166, - SPELL_FAILED_DAMAGE_IMMUNE = 167, - SPELL_FAILED_PREVENTED_BY_MECHANIC = 168, - SPELL_FAILED_PLAY_TIME = 169, - SPELL_FAILED_REPUTATION = 170, - SPELL_FAILED_MIN_SKILL = 171, - SPELL_FAILED_NOT_IN_RATED_BATTLEGROUND = 172, - SPELL_FAILED_NOT_ON_SHAPESHIFT = 173, - SPELL_FAILED_NOT_ON_STEALTHED = 174, - SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 175, - SPELL_FAILED_NOT_ON_MOUNTED = 176, - SPELL_FAILED_TOO_SHALLOW = 177, - SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 178, - SPELL_FAILED_TARGET_IS_TRIVIAL = 179, - SPELL_FAILED_BM_OR_INVISGOD = 180, - SPELL_FAILED_GROUND_MOUNT_NOT_ALLOWED = 181, - SPELL_FAILED_FLOATING_MOUNT_NOT_ALLOWED = 182, - SPELL_FAILED_UNDERWATER_MOUNT_NOT_ALLOWED = 183, - SPELL_FAILED_FLYING_MOUNT_NOT_ALLOWED = 184, - SPELL_FAILED_APPRENTICE_RIDING_REQUIREMENT = 185, - SPELL_FAILED_JOURNEYMAN_RIDING_REQUIREMENT = 186, - SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 187, - SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 188, - SPELL_FAILED_MASTER_RIDING_REQUIREMENT = 189, - SPELL_FAILED_COLD_RIDING_REQUIREMENT = 190, - SPELL_FAILED_FLIGHT_MASTER_RIDING_REQUIREMENT = 191, - SPELL_FAILED_CS_RIDING_REQUIREMENT = 192, - SPELL_FAILED_PANDA_RIDING_REQUIREMENT = 193, - SPELL_FAILED_DRAENOR_RIDING_REQUIREMENT = 194, - SPELL_FAILED_MOUNT_NO_FLOAT_HERE = 195, - SPELL_FAILED_MOUNT_NO_UNDERWATER_HERE = 196, - SPELL_FAILED_MOUNT_ABOVE_WATER_HERE = 197, - SPELL_FAILED_MOUNT_COLLECTED_ON_OTHER_CHAR = 198, - SPELL_FAILED_NOT_IDLE = 199, - SPELL_FAILED_NOT_INACTIVE = 200, - SPELL_FAILED_PARTIAL_PLAYTIME = 201, - SPELL_FAILED_NO_PLAYTIME = 202, - SPELL_FAILED_NOT_IN_BATTLEGROUND = 203, - SPELL_FAILED_NOT_IN_RAID_INSTANCE = 204, - SPELL_FAILED_ONLY_IN_ARENA = 205, - SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 206, - SPELL_FAILED_ON_USE_ENCHANT = 207, - SPELL_FAILED_NOT_ON_GROUND = 208, - SPELL_FAILED_CUSTOM_ERROR = 209, - SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 210, - SPELL_FAILED_TOO_MANY_SOCKETS = 211, - SPELL_FAILED_INVALID_GLYPH = 212, - SPELL_FAILED_UNIQUE_GLYPH = 213, - SPELL_FAILED_GLYPH_SOCKET_LOCKED = 214, - SPELL_FAILED_GLYPH_EXCLUSIVE_CATEGORY = 215, - SPELL_FAILED_GLYPH_INVALID_SPEC = 216, - SPELL_FAILED_GLYPH_NO_SPEC = 217, - SPELL_FAILED_NO_VALID_TARGETS = 218, - SPELL_FAILED_ITEM_AT_MAX_CHARGES = 219, - SPELL_FAILED_NOT_IN_BARBERSHOP = 220, - SPELL_FAILED_FISHING_TOO_LOW = 221, - SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 222, - SPELL_FAILED_SUMMON_PENDING = 223, - SPELL_FAILED_MAX_SOCKETS = 224, - SPELL_FAILED_PET_CAN_RENAME = 225, - SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED = 226, - SPELL_FAILED_TARGET_HAS_RESURRECT_PENDING = 227, - SPELL_FAILED_NO_ACTIONS = 228, - SPELL_FAILED_CURRENCY_WEIGHT_MISMATCH = 229, - SPELL_FAILED_WEIGHT_NOT_ENOUGH = 230, - SPELL_FAILED_WEIGHT_TOO_MUCH = 231, - SPELL_FAILED_NO_VACANT_SEAT = 232, - SPELL_FAILED_NO_LIQUID = 233, - SPELL_FAILED_ONLY_NOT_SWIMMING = 234, - SPELL_FAILED_BY_NOT_MOVING = 235, - SPELL_FAILED_IN_COMBAT_RES_LIMIT_REACHED = 236, - SPELL_FAILED_NOT_IN_ARENA = 237, - SPELL_FAILED_TARGET_NOT_GROUNDED = 238, - SPELL_FAILED_EXCEEDED_WEEKLY_USAGE = 239, - SPELL_FAILED_NOT_IN_LFG_DUNGEON = 240, - SPELL_FAILED_BAD_TARGET_FILTER = 241, - SPELL_FAILED_NOT_ENOUGH_TARGETS = 242, - SPELL_FAILED_NO_SPEC = 243, - SPELL_FAILED_CANT_ADD_BATTLE_PET = 244, - SPELL_FAILED_CANT_UPGRADE_BATTLE_PET = 245, - SPELL_FAILED_WRONG_BATTLE_PET_TYPE = 246, - SPELL_FAILED_NO_DUNGEON_ENCOUNTER = 247, - SPELL_FAILED_NO_TELEPORT_FROM_DUNGEON = 248, - SPELL_FAILED_MAX_LEVEL_TOO_LOW = 249, - SPELL_FAILED_CANT_REPLACE_ITEM_BONUS = 250, - GRANT_PET_LEVEL_FAIL = 251, - SPELL_FAILED_SKILL_LINE_NOT_KNOWN = 252, - SPELL_FAILED_BLUEPRINT_KNOWN = 253, - SPELL_FAILED_FOLLOWER_KNOWN = 254, - SPELL_FAILED_CANT_OVERRIDE_ENCHANT_VISUAL = 255, - SPELL_FAILED_ITEM_NOT_A_WEAPON = 256, - SPELL_FAILED_SAME_ENCHANT_VISUAL = 257, - SPELL_FAILED_TOY_USE_LIMIT_REACHED = 258, - SPELL_FAILED_TOY_ALREADY_KNOWN = 259, - SPELL_FAILED_SHIPMENTS_FULL = 260, - SPELL_FAILED_NO_SHIPMENTS_FOR_CONTAINER = 261, - SPELL_FAILED_NO_BUILDING_FOR_SHIPMENT = 262, - SPELL_FAILED_NOT_ENOUGH_SHIPMENTS_FOR_CONTAINER = 263, - SPELL_FAILED_HAS_MISSION = 264, - SPELL_FAILED_BUILDING_ACTIVATE_NOT_READY = 265, - SPELL_FAILED_NOT_SOULBOUND = 266, - SPELL_FAILED_RIDING_VEHICLE = 267, - SPELL_FAILED_VETERAN_TRIAL_ABOVE_SKILL_RANK_MAX = 268, - SPELL_FAILED_NOT_WHILE_MERCENARY = 269, - SPELL_FAILED_UNKNOWN = 270, - SPELL_CAST_OK = 0xFFFF // custom value, must not be sent to client + SPELL_FAILED_ONLY_INDOORS = 108, + SPELL_FAILED_ONLY_MOUNTED = 109, + SPELL_FAILED_ONLY_OUTDOORS = 110, + SPELL_FAILED_ONLY_SHAPESHIFT = 111, + SPELL_FAILED_ONLY_STEALTHED = 112, + SPELL_FAILED_ONLY_UNDERWATER = 113, + SPELL_FAILED_OUT_OF_RANGE = 114, + SPELL_FAILED_PACIFIED = 115, + SPELL_FAILED_POSSESSED = 116, + SPELL_FAILED_REAGENTS = 117, + SPELL_FAILED_REQUIRES_AREA = 118, + SPELL_FAILED_REQUIRES_SPELL_FOCUS = 119, + SPELL_FAILED_ROOTED = 120, + SPELL_FAILED_SILENCED = 121, + SPELL_FAILED_SPELL_IN_PROGRESS = 122, + SPELL_FAILED_SPELL_LEARNED = 123, + SPELL_FAILED_SPELL_UNAVAILABLE = 124, + SPELL_FAILED_STUNNED = 125, + SPELL_FAILED_TARGETS_DEAD = 126, + SPELL_FAILED_TARGET_AFFECTING_COMBAT = 127, + SPELL_FAILED_TARGET_AURASTATE = 128, + SPELL_FAILED_TARGET_DUELING = 129, + SPELL_FAILED_TARGET_ENEMY = 130, + SPELL_FAILED_TARGET_ENRAGED = 131, + SPELL_FAILED_TARGET_FRIENDLY = 132, + SPELL_FAILED_TARGET_IN_COMBAT = 133, + SPELL_FAILED_TARGET_IN_PET_BATTLE = 134, + SPELL_FAILED_TARGET_IS_PLAYER = 135, + SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 136, + SPELL_FAILED_TARGET_NOT_DEAD = 137, + SPELL_FAILED_TARGET_NOT_IN_PARTY = 138, + SPELL_FAILED_TARGET_NOT_LOOTED = 139, + SPELL_FAILED_TARGET_NOT_PLAYER = 140, + SPELL_FAILED_TARGET_NO_POCKETS = 141, + SPELL_FAILED_TARGET_NO_WEAPONS = 142, + SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 143, + SPELL_FAILED_TARGET_UNSKINNABLE = 144, + SPELL_FAILED_THIRST_SATIATED = 145, + SPELL_FAILED_TOO_CLOSE = 146, + SPELL_FAILED_TOO_MANY_OF_ITEM = 147, + SPELL_FAILED_TOTEM_CATEGORY = 148, + SPELL_FAILED_TOTEMS = 149, + SPELL_FAILED_TRY_AGAIN = 150, + SPELL_FAILED_UNIT_NOT_BEHIND = 151, + SPELL_FAILED_UNIT_NOT_INFRONT = 152, + SPELL_FAILED_VISION_OBSCURED = 153, + SPELL_FAILED_WRONG_PET_FOOD = 154, + SPELL_FAILED_NOT_WHILE_FATIGUED = 155, + SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 156, + SPELL_FAILED_NOT_WHILE_TRADING = 157, + SPELL_FAILED_TARGET_NOT_IN_RAID = 158, + SPELL_FAILED_TARGET_FREEFORALL = 159, + SPELL_FAILED_NO_EDIBLE_CORPSES = 160, + SPELL_FAILED_ONLY_BATTLEGROUNDS = 161, + SPELL_FAILED_TARGET_NOT_GHOST = 162, + SPELL_FAILED_TRANSFORM_UNUSABLE = 163, + SPELL_FAILED_WRONG_WEATHER = 164, + SPELL_FAILED_DAMAGE_IMMUNE = 165, + SPELL_FAILED_PREVENTED_BY_MECHANIC = 166, + SPELL_FAILED_PLAY_TIME = 167, + SPELL_FAILED_REPUTATION = 168, + SPELL_FAILED_MIN_SKILL = 169, + SPELL_FAILED_NOT_IN_RATED_BATTLEGROUND = 170, + SPELL_FAILED_NOT_ON_SHAPESHIFT = 171, + SPELL_FAILED_NOT_ON_STEALTHED = 172, + SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 173, + SPELL_FAILED_NOT_ON_MOUNTED = 174, + SPELL_FAILED_TOO_SHALLOW = 175, + SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 176, + SPELL_FAILED_TARGET_IS_TRIVIAL = 177, + SPELL_FAILED_BM_OR_INVISGOD = 178, + SPELL_FAILED_GROUND_MOUNT_NOT_ALLOWED = 179, + SPELL_FAILED_FLOATING_MOUNT_NOT_ALLOWED = 180, + SPELL_FAILED_UNDERWATER_MOUNT_NOT_ALLOWED = 181, + SPELL_FAILED_FLYING_MOUNT_NOT_ALLOWED = 182, + SPELL_FAILED_APPRENTICE_RIDING_REQUIREMENT = 183, + SPELL_FAILED_JOURNEYMAN_RIDING_REQUIREMENT = 184, + SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 185, + SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 186, + SPELL_FAILED_MASTER_RIDING_REQUIREMENT = 187, + SPELL_FAILED_COLD_RIDING_REQUIREMENT = 188, + SPELL_FAILED_FLIGHT_MASTER_RIDING_REQUIREMENT = 189, + SPELL_FAILED_CS_RIDING_REQUIREMENT = 190, + SPELL_FAILED_PANDA_RIDING_REQUIREMENT = 191, + SPELL_FAILED_DRAENOR_RIDING_REQUIREMENT = 192, + SPELL_FAILED_MOUNT_NO_FLOAT_HERE = 193, + SPELL_FAILED_MOUNT_NO_UNDERWATER_HERE = 194, + SPELL_FAILED_MOUNT_ABOVE_WATER_HERE = 195, + SPELL_FAILED_MOUNT_COLLECTED_ON_OTHER_CHAR = 196, + SPELL_FAILED_NOT_IDLE = 197, + SPELL_FAILED_NOT_INACTIVE = 198, + SPELL_FAILED_PARTIAL_PLAYTIME = 199, + SPELL_FAILED_NO_PLAYTIME = 200, + SPELL_FAILED_NOT_IN_BATTLEGROUND = 201, + SPELL_FAILED_NOT_IN_RAID_INSTANCE = 202, + SPELL_FAILED_ONLY_IN_ARENA = 203, + SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 204, + SPELL_FAILED_ON_USE_ENCHANT = 205, + SPELL_FAILED_NOT_ON_GROUND = 206, + SPELL_FAILED_CUSTOM_ERROR = 207, + SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 208, + SPELL_FAILED_TOO_MANY_SOCKETS = 209, + SPELL_FAILED_INVALID_GLYPH = 210, + SPELL_FAILED_UNIQUE_GLYPH = 211, + SPELL_FAILED_GLYPH_SOCKET_LOCKED = 212, + SPELL_FAILED_GLYPH_EXCLUSIVE_CATEGORY = 213, + SPELL_FAILED_GLYPH_INVALID_SPEC = 214, + SPELL_FAILED_GLYPH_NO_SPEC = 215, + SPELL_FAILED_NO_VALID_TARGETS = 216, + SPELL_FAILED_ITEM_AT_MAX_CHARGES = 217, + SPELL_FAILED_NOT_IN_BARBERSHOP = 218, + SPELL_FAILED_FISHING_TOO_LOW = 219, + SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 220, + SPELL_FAILED_SUMMON_PENDING = 221, + SPELL_FAILED_MAX_SOCKETS = 222, + SPELL_FAILED_PET_CAN_RENAME = 223, + SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED = 224, + SPELL_FAILED_TARGET_HAS_RESURRECT_PENDING = 225, + SPELL_FAILED_NO_ACTIONS = 226, + SPELL_FAILED_CURRENCY_WEIGHT_MISMATCH = 227, + SPELL_FAILED_WEIGHT_NOT_ENOUGH = 228, + SPELL_FAILED_WEIGHT_TOO_MUCH = 229, + SPELL_FAILED_NO_VACANT_SEAT = 230, + SPELL_FAILED_NO_LIQUID = 231, + SPELL_FAILED_ONLY_NOT_SWIMMING = 232, + SPELL_FAILED_BY_NOT_MOVING = 233, + SPELL_FAILED_IN_COMBAT_RES_LIMIT_REACHED = 234, + SPELL_FAILED_NOT_IN_ARENA = 235, + SPELL_FAILED_TARGET_NOT_GROUNDED = 236, + SPELL_FAILED_EXCEEDED_WEEKLY_USAGE = 237, + SPELL_FAILED_NOT_IN_LFG_DUNGEON = 238, + SPELL_FAILED_BAD_TARGET_FILTER = 239, + SPELL_FAILED_NOT_ENOUGH_TARGETS = 240, + SPELL_FAILED_NO_SPEC = 241, + SPELL_FAILED_CANT_ADD_BATTLE_PET = 242, + SPELL_FAILED_CANT_UPGRADE_BATTLE_PET = 243, + SPELL_FAILED_WRONG_BATTLE_PET_TYPE = 244, + SPELL_FAILED_NO_DUNGEON_ENCOUNTER = 245, + SPELL_FAILED_NO_TELEPORT_FROM_DUNGEON = 246, + SPELL_FAILED_MAX_LEVEL_TOO_LOW = 247, + SPELL_FAILED_CANT_REPLACE_ITEM_BONUS = 248, + GRANT_PET_LEVEL_FAIL = 249, + SPELL_FAILED_SKILL_LINE_NOT_KNOWN = 250, + SPELL_FAILED_BLUEPRINT_KNOWN = 251, + SPELL_FAILED_FOLLOWER_KNOWN = 252, + SPELL_FAILED_CANT_OVERRIDE_ENCHANT_VISUAL = 253, + SPELL_FAILED_ITEM_NOT_A_WEAPON = 254, + SPELL_FAILED_SAME_ENCHANT_VISUAL = 255, + SPELL_FAILED_TOY_USE_LIMIT_REACHED = 256, + SPELL_FAILED_TOY_ALREADY_KNOWN = 257, + SPELL_FAILED_SHIPMENTS_FULL = 258, + SPELL_FAILED_NO_SHIPMENTS_FOR_CONTAINER = 259, + SPELL_FAILED_NO_BUILDING_FOR_SHIPMENT = 260, + SPELL_FAILED_NOT_ENOUGH_SHIPMENTS_FOR_CONTAINER = 261, + SPELL_FAILED_HAS_MISSION = 262, + SPELL_FAILED_BUILDING_ACTIVATE_NOT_READY = 263, + SPELL_FAILED_NOT_SOULBOUND = 264, + SPELL_FAILED_RIDING_VEHICLE = 265, + SPELL_FAILED_VETERAN_TRIAL_ABOVE_SKILL_RANK_MAX = 266, + SPELL_FAILED_NOT_WHILE_MERCENARY = 267, + SPELL_FAILED_SPEC_DISABLED = 268, + SPELL_FAILED_CANT_BE_OBLITERATED = 269, + SPELL_FAILED_FOLLOWER_CLASS_SPEC_CAP = 270, + SPELL_FAILED_TRANSPORT_NOT_READY = 271, + SPELL_FAILED_TRANSMOG_SET_ALREADY_KNOWN = 272, + SPELL_FAILED_DISABLED_BY_AURA_LABEL = 273, + SPELL_FAILED_DISABLED_BY_MAX_USABLE_LEVEL = 274, + SPELL_FAILED_SPELL_ALREADY_KNOWN = 275, + SPELL_FAILED_MUST_KNOW_SUPERCEDING_SPELL = 276, + SPELL_FAILED_YOU_CANNOT_USE_THAT_IN_PVP_INSTANCE = 277, + SPELL_FAILED_UNKNOWN = 278, + + // ok cast value - here in case a future version removes SPELL_FAILED_SUCCESS and we need to use a custom value (not sent to client either way) + SPELL_CAST_OK = SPELL_FAILED_SUCCESS }; enum SpellCustomErrors { - SPELL_CUSTOM_ERROR_NONE = 0, - SPELL_CUSTOM_ERROR_CUSTOM_MSG = 1, // Something bad happened, and we want to display a custom message! - SPELL_CUSTOM_ERROR_ALEX_BROKE_QUEST = 2, // Alex broke your quest! Thank him later! - SPELL_CUSTOM_ERROR_NEED_HELPLESS_VILLAGER = 3, // This spell may only be used on Helpless Wintergarde Villagers that have not been rescued. - SPELL_CUSTOM_ERROR_NEED_WARSONG_DISGUISE = 4, // Requires that you be wearing the Warsong Orc Disguise. - SPELL_CUSTOM_ERROR_REQUIRES_PLAGUE_WAGON = 5, // You must be closer to a plague wagon in order to drop off your 7th Legion Siege Engineer. - SPELL_CUSTOM_ERROR_CANT_TARGET_FRIENDLY_NONPARTY = 6, // You cannot target friendly units outside your party. - SPELL_CUSTOM_ERROR_NEED_CHILL_NYMPH = 7, // You must target a weakened chill nymph. - SPELL_CUSTOM_ERROR_MUST_BE_IN_ENKILAH = 8, // The Imbued Scourge Shroud will only work when equipped in the Temple City of En'kilah. - SPELL_CUSTOM_ERROR_REQUIRES_CORPSE_DUST = 9, // Requires Corpse Dust - SPELL_CUSTOM_ERROR_CANT_SUMMON_GARGOYLE = 10, // You cannot summon another gargoyle yet. - SPELL_CUSTOM_ERROR_NEED_CORPSE_DUST_IF_NO_TARGET = 11, // Requires Corpse Dust if the target is not dead and humanoid. - SPELL_CUSTOM_ERROR_MUST_BE_AT_SHATTERHORN = 12, // Can only be placed near Shatterhorn - SPELL_CUSTOM_ERROR_MUST_TARGET_PROTO_DRAKE_EGG = 13, // You must first select a Proto-Drake Egg. - SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_TREE = 14, // You must be close to a marked tree. - SPELL_CUSTOM_ERROR_MUST_TARGET_TURKEY = 15, // You must target a Fjord Turkey. - SPELL_CUSTOM_ERROR_MUST_TARGET_HAWK = 16, // You must target a Fjord Hawk. - SPELL_CUSTOM_ERROR_TOO_FAR_FROM_BOUY = 17, // You are too far from the bouy. - SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_OIL_SLICK = 18, // Must be used near an oil slick. - SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_BOUY = 19, // You must be closer to the buoy! - SPELL_CUSTOM_ERROR_WYRMREST_VANQUISHER = 20, // You may only call for the aid of a Wyrmrest Vanquisher in Wyrmrest Temple, The Dragon Wastes, Galakrond's Rest or The Wicked Coil. - SPELL_CUSTOM_ERROR_MUST_TARGET_ICE_HEART_JORMUNGAR = 21, // That can only be used on a Ice Heart Jormungar Spawn. - SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_SINKHOLE = 22, // You must be closer to a sinkhole to use your map. - SPELL_CUSTOM_ERROR_REQUIRES_HAROLD_LANE = 23, // You may only call down a stampede on Harold Lane. - SPELL_CUSTOM_ERROR_REQUIRES_GAMMOTH_MAGNATAUR = 24, // You may only use the Pouch of Crushed Bloodspore on Gammothra or other magnataur in the Bloodspore Plains and Gammoth. - SPELL_CUSTOM_ERROR_MUST_BE_IN_RESURRECTION_CHAMBER = 25, // Requires the magmawyrm resurrection chamber in the back of the Maw of Neltharion. - SPELL_CUSTOM_ERROR_CANT_CALL_WINTERGARDE_HERE = 26, // You may only call down a Wintergarde Gryphon in Wintergarde Keep or the Carrion Fields. - SPELL_CUSTOM_ERROR_MUST_TARGET_WILHELM = 27, // What are you doing? Only aim that thing at Wilhelm! - SPELL_CUSTOM_ERROR_NOT_ENOUGH_HEALTH = 28, // Not enough health! - SPELL_CUSTOM_ERROR_NO_NEARBY_CORPSES = 29, // There are no nearby corpses to use - SPELL_CUSTOM_ERROR_TOO_MANY_GHOULS = 30, // You've created enough ghouls. Return to Gothik the Harvester at Death's Breach. - SPELL_CUSTOM_ERROR_GO_FURTHER_FROM_SUNDERED_SHARD = 31, // Your companion does not want to come here. Go further from the Sundered Shard. - SPELL_CUSTOM_ERROR_MUST_BE_IN_CAT_FORM = 32, // Must be in Cat Form - SPELL_CUSTOM_ERROR_MUST_BE_DEATH_KNIGHT = 33, // Only Death Knights may enter Ebon Hold. - SPELL_CUSTOM_ERROR_MUST_BE_IN_FERAL_FORM = 34, // Must be in Cat Form, Bear Form, or Dire Bear Form - SPELL_CUSTOM_ERROR_MUST_BE_NEAR_HELPLESS_VILLAGER = 35, // You must be within range of a Helpless Wintergarde Villager. - SPELL_CUSTOM_ERROR_CANT_TARGET_ELEMENTAL_MECHANICAL = 36, // You cannot target an elemental or mechanical corpse. - SPELL_CUSTOM_ERROR_MUST_HAVE_USED_DALARAN_CRYSTAL = 37, // This teleport crystal cannot be used until the teleport crystal in Dalaran has been used at least once. - SPELL_CUSTOM_ERROR_YOU_ALREADY_HOLD_SOMETHING = 38, // You are already holding something in your hand. You must throw the creature in your hand before picking up another. - SPELL_CUSTOM_ERROR_YOU_DONT_HOLD_ANYTHING = 39, // You don't have anything to throw! Find a Vargul and use Gymer Grab to pick one up! - SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_VALDURAN = 40, // Bouldercrag's War Horn can only be used within 10 yards of Valduran the Stormborn. - SPELL_CUSTOM_ERROR_NO_PASSENGER = 41, // You are not carrying a passenger. There is nobody to drop off. - SPELL_CUSTOM_ERROR_CANT_BUILD_MORE_VEHICLES = 42, // You cannot build any more siege vehicles. - SPELL_CUSTOM_ERROR_ALREADY_CARRYING_CRUSADER = 43, // You are already carrying a captured Argent Crusader. You must return to the Argent Vanguard infirmary and drop off your passenger before you may pick up another. - SPELL_CUSTOM_ERROR_CANT_DO_WHILE_ROOTED = 44, // You can't do that while rooted. - SPELL_CUSTOM_ERROR_REQUIRES_NEARBY_TARGET = 45, // Requires a nearby target. - SPELL_CUSTOM_ERROR_NOTHING_TO_DISCOVER = 46, // Nothing left to discover. - SPELL_CUSTOM_ERROR_NOT_ENOUGH_TARGETS = 47, // No targets close enough to bluff. - SPELL_CUSTOM_ERROR_CONSTRUCT_TOO_FAR = 48, // Your Iron Rune Construct is out of range. - SPELL_CUSTOM_ERROR_REQUIRES_GRAND_MASTER_ENGINEER = 49, // Requires Grand Master Engineer - SPELL_CUSTOM_ERROR_CANT_USE_THAT_MOUNT = 50, // You can't use that mount. - SPELL_CUSTOM_ERROR_NOONE_TO_EJECT = 51, // There is nobody to eject! - SPELL_CUSTOM_ERROR_TARGET_MUST_BE_BOUND = 52, // The target must be bound to you. - SPELL_CUSTOM_ERROR_TARGET_MUST_BE_UNDEAD = 53, // Target must be undead. - SPELL_CUSTOM_ERROR_TARGET_TOO_FAR = 54, // You have no target or your target is too far away. - SPELL_CUSTOM_ERROR_MISSING_DARK_MATTER = 55, // Missing Reagents: Dark Matter - SPELL_CUSTOM_ERROR_CANT_USE_THAT_ITEM = 56, // You can't use that item - SPELL_CUSTOM_ERROR_CANT_DO_WHILE_CYCYLONED = 57, // You can't do that while Cycloned - SPELL_CUSTOM_ERROR_TARGET_HAS_SCROLL = 58, // Target is already affected by a scroll - SPELL_CUSTOM_ERROR_POISON_TOO_STRONG = 59, // That anti-venom is not strong enough to dispel that poison - SPELL_CUSTOM_ERROR_MUST_HAVE_LANCE_EQUIPPED = 60, // You must have a lance equipped. - SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_MAIDEN = 61, // You must be near the Maiden of Winter's Breath Lake. - SPELL_CUSTOM_ERROR_LEARNED_EVERYTHING = 62, // You have learned everything from that book - SPELL_CUSTOM_ERROR_PET_IS_DEAD = 63, // Your pet is dead - SPELL_CUSTOM_ERROR_NO_VALID_TARGETS = 64, // There are no valid targets within range. - SPELL_CUSTOM_ERROR_GM_ONLY = 65, // Only GMs may use that. Your account has been reported for investigation. - SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_58 = 66, // You must reach level 58 to use this portal. - SPELL_CUSTOM_ERROR_AT_HONOR_CAP = 67, // You already have the maximum amount of honor. - SPELL_CUSTOM_ERROR_HAVE_HOT_ROD = 68, // You already have a Hot Rod. - SPELL_CUSTOM_ERROR_PARTYGOER_MORE_BUBBLY = 69, // This partygoer wants some more bubbly - SPELL_CUSTOM_ERROR_PARTYGOER_NEED_BUCKET = 70, // This partygoer needs a bucket! - SPELL_CUSTOM_ERROR_PARTYGOER_WANT_TO_DANCE = 71, // This partygoer wants to dance with you. - SPELL_CUSTOM_ERROR_PARTYGOER_WANT_FIREWORKS = 72, // This partygoer wants to see some fireworks. - SPELL_CUSTOM_ERROR_PARTYGOER_WANT_APPETIZER = 73, // This partygoer wants some more hors d'oeuvres. - SPELL_CUSTOM_ERROR_GOBLIN_BATTERY_DEPLETED = 74, // The Goblin All-In-1-Der Belt's battery is depleted. - SPELL_CUSTOM_ERROR_MUST_HAVE_DEMONIC_CIRCLE = 75, // You must have a demonic circle active. - SPELL_CUSTOM_ERROR_AT_MAX_RAGE = 76, // You already have maximum rage - SPELL_CUSTOM_ERROR_REQUIRES_350_ENGINEERING = 77, // Requires Engineering (350) - SPELL_CUSTOM_ERROR_SOUL_BELONGS_TO_LICH_KING = 78, // Your soul belongs to the Lich King - SPELL_CUSTOM_ERROR_ATTENDANT_HAS_PONY = 79, // Your attendant already has an Argent Pony - SPELL_CUSTOM_ERROR_GOBLIN_STARTING_MISSION = 80, // First, Overload the Defective Generator, Activate the Leaky Stove, and Drop a Cigar on the Flammable Bed. - SPELL_CUSTOM_ERROR_GASBOT_ALREADY_SENT = 81, // You've already sent in the Gasbot and destroyed headquarters! - SPELL_CUSTOM_ERROR_GOBLIN_IS_PARTIED_OUT = 82, // This goblin is all partied out! - SPELL_CUSTOM_ERROR_MUST_HAVE_FIRE_TOTEM = 83, // You must have a Fire Totem active. - SPELL_CUSTOM_ERROR_CANT_TARGET_VAMPIRES = 84, // You may not bite other vampires. - SPELL_CUSTOM_ERROR_PET_ALREADY_AT_YOUR_LEVEL = 85, // Your pet is already at your level. - SPELL_CUSTOM_ERROR_MISSING_ITEM_REQUIREMENS = 86, // You do not meet the level requirements for this item. - SPELL_CUSTOM_ERROR_TOO_MANY_ABOMINATIONS = 87, // There are too many Mutated Abominations. - SPELL_CUSTOM_ERROR_ALL_POTIONS_USED = 88, // The potions have all been depleted by Professor Putricide. - SPELL_CUSTOM_ERROR_DEFEATED_ENOUGH_ALREADY = 89, // You have already defeated enough of them. - SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_65 = 90, // Requires level 65 - SPELL_CUSTOM_ERROR_DESTROYED_KTC_OIL_PLATFORM = 91, // You have already destroyed the KTC Oil Platform. - SPELL_CUSTOM_ERROR_LAUNCHED_ENOUGH_CAGES = 92, // You have already launched enough cages. - SPELL_CUSTOM_ERROR_REQUIRES_BOOSTER_ROCKETS = 93, // Requires Single-Stage Booster Rockets. Return to Hobart Grapplehammer to get more. - SPELL_CUSTOM_ERROR_ENOUGH_WILD_CLUCKERS = 94, // You have already captured enough wild cluckers. - SPELL_CUSTOM_ERROR_REQUIRES_CONTROL_FIREWORKS = 95, // Requires Remote Control Fireworks. Return to Hobart Grapplehammer to get more. - SPELL_CUSTOM_ERROR_MAX_NUMBER_OF_RECRUITS = 96, // You already have the max number of recruits. - SPELL_CUSTOM_ERROR_MAX_NUMBER_OF_VOLUNTEERS = 97, // You already have the max number of volunteers. - SPELL_CUSTOM_ERROR_FROSTMOURNE_RENDERED_RESURRECT = 98, // Frostmourne has rendered you unable to resurrect. - SPELL_CUSTOM_ERROR_CANT_MOUNT_WITH_SHAPESHIFT = 99, // You can't mount while affected by that shapeshift. - SPELL_CUSTOM_ERROR_FAWNS_ALREADY_FOLLOWING = 100, // Three fawns are already following you! - SPELL_CUSTOM_ERROR_ALREADY_HAVE_RIVER_BOAT = 101, // You already have a River Boat. - SPELL_CUSTOM_ERROR_NO_ACTIVE_ENCHANTMENT = 102, // You have no active enchantment to unleash. - SPELL_CUSTOM_ERROR_ENOUGH_HIGHBOURNE_SOULS = 103, // You have bound enough Highborne souls. Return to Arcanist Valdurian. - SPELL_CUSTOM_ERROR_ATLEAST_40YD_FROM_OIL_DRILLING = 104, // You must be at least 40 yards away from all other Oil Drilling Rigs. - SPELL_CUSTOM_ERROR_ABOVE_ENSLAVED_PEARL_MINER = 106, // You must be above the Enslaved Pearl Miner. - SPELL_CUSTOM_ERROR_MUST_TARGET_CORPSE_SPECIAL_1 = 107, // You must target the corpse of a Seabrush Terrapin, Scourgut Remora, or Spinescale Hammerhead. - SPELL_CUSTOM_ERROR_SLAGHAMMER_ALREADY_PRISONER = 108, // Ambassador Slaghammer is already your prisoner. - SPELL_CUSTOM_ERROR_REQUIRE_ATTUNED_LOCATION_1 = 109, // Requires a location that is attuned with the Naz'jar Battlemaiden. - SPELL_CUSTOM_ERROR_NEED_TO_FREE_DRAKE_FIRST = 110, // Free the Drake from the net first! - SPELL_CUSTOM_ERROR_DRAGONMAW_ALLIES_ALREADY_FOLLOW = 111, // You already have three Dragonmaw allies following you. - SPELL_CUSTOM_ERROR_REQUIRE_OPPOSABLE_THUMBS = 112, // Requires Opposable Thumbs. - SPELL_CUSTOM_ERROR_NOT_ENOUGH_HEALTH_2 = 113, // Not enough health - SPELL_CUSTOM_ERROR_ENOUGH_FORSAKEN_TROOPERS = 114, // You already have enough Forsaken Troopers. - SPELL_CUSTOM_ERROR_CANNOT_JUMP_TO_BOULDER = 115, // You cannot jump to another boulder yet. - SPELL_CUSTOM_ERROR_SKILL_TOO_HIGH = 116, // Skill too high. - SPELL_CUSTOM_ERROR_ALREADY_6_SURVIVORS_RESCUED = 117, // You have already rescued 6 Survivors. - SPELL_CUSTOM_ERROR_MUST_FACE_SHIPS_FROM_BALLOON = 118, // You need to be facing the ships from the rescue balloon. - SPELL_CUSTOM_ERROR_CANNOT_SUPERVISE_MORE_CULTISTS = 119, // You cannot supervise more than 5 Arrested Cultists at a time. - SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_85 = 120, // You must reach level 85 to use this portal. - SPELL_CUSTOM_ERROR_MUST_BE_BELOW_35_HEALTH = 121, // Your target must be below 35% health. - SPELL_CUSTOM_ERROR_MUST_SELECT_TALENT_SPECIAL = 122, // You must select a talent specialization first. - SPELL_CUSTOM_ERROR_TOO_WISE_AND_POWERFUL = 123, // You are too wise and powerful to gain any benefit from that item. - SPELL_CUSTOM_ERROR_TOO_CLOSE_ARGENT_LIGHTWELL = 124, // You are within 10 yards of another Argent Lightwell. - SPELL_CUSTOM_ERROR_NOT_WHILE_SHAPESHIFTED = 125, // You can't do that while shapeshifted. - SPELL_CUSTOM_ERROR_MANA_GEM_IN_BANK = 126, // You already have a Mana Gem in your bank. - SPELL_CUSTOM_ERROR_FLAME_SHOCK_NOT_ACTIVE = 127, // You must have at least one Flame Shock active. - SPELL_CUSTOM_ERROR_CANT_TRANSFORM = 128, // You cannot transform right now - SPELL_CUSTOM_ERROR_PET_MUST_BE_ATTACKING = 129, // Your pet must be attacking a target. - SPELL_CUSTOM_ERROR_GNOMISH_ENGINEERING = 130, // Requires Gnomish Engineering - SPELL_CUSTOM_ERROR_GOBLIN_ENGINEERING = 131, // Requires Goblin Engineering - SPELL_CUSTOM_ERROR_NO_TARGET = 132, // You have no target. - SPELL_CUSTOM_ERROR_PET_OUT_OF_RANGE = 133, // Your Pet is out of range of the target. - SPELL_CUSTOM_ERROR_HOLDING_FLAG = 134, // You can't do that while holding the flag. - SPELL_CUSTOM_ERROR_TARGET_HOLDING_FLAG = 135, // You can't do that to targets holding the flag. - SPELL_CUSTOM_ERROR_PORTAL_NOT_OPEN = 136, // The portal is not yet open. Continue helping the druids at the Sanctuary of Malorne. - SPELL_CUSTOM_ERROR_AGGRA_AIR_TOTEM = 137, // You need to be closer to Aggra's Air Totem, in the west. - SPELL_CUSTOM_ERROR_AGGRA_WATER_TOTEM = 138, // You need to be closer to Aggra's Water Totem, in the north. - SPELL_CUSTOM_ERROR_AGGRA_EARTH_TOTEM = 139, // You need to be closer to Aggra's Earth Totem, in the east. - SPELL_CUSTOM_ERROR_AGGRA_FIRE_TOTEM = 140, // You need to be closer to Aggra's Fire Totem, near Thrall. - SPELL_CUSTOM_ERROR_TARGET_HAS_STARTDUST_2 = 148, // Target is already affected by Stardust No. 2. - SPELL_CUSTOM_ERROR_ELEMENTIUM_GEM_CLUSTERS = 149 // You cannot deconstruct Elementium Gem Clusters while collecting them! + SPELL_CUSTOM_ERROR_NONE = 0, + SPELL_CUSTOM_ERROR_CUSTOM_MSG = 1, // Something bad happened, and we want to display a custom message! + SPELL_CUSTOM_ERROR_ALEX_BROKE_QUEST = 2, // Alex broke your quest! Thank him later! + SPELL_CUSTOM_ERROR_NEED_HELPLESS_VILLAGER = 3, // This spell may only be used on Helpless Wintergarde Villagers that have not been rescued. + SPELL_CUSTOM_ERROR_NEED_WARSONG_DISGUISE = 4, // Requires that you be wearing the Warsong Orc Disguise. + SPELL_CUSTOM_ERROR_REQUIRES_PLAGUE_WAGON = 5, // You must be closer to a plague wagon in order to drop off your 7th Legion Siege Engineer. + SPELL_CUSTOM_ERROR_CANT_TARGET_FRIENDLY_NONPARTY = 6, // You cannot target friendly units outside your party. + SPELL_CUSTOM_ERROR_NEED_CHILL_NYMPH = 7, // You must target a weakened chill nymph. + SPELL_CUSTOM_ERROR_MUST_BE_IN_ENKILAH = 8, // The Imbued Scourge Shroud will only work when equipped in the Temple City of En'kilah. + SPELL_CUSTOM_ERROR_REQUIRES_CORPSE_DUST = 9, // Requires Corpse Dust + SPELL_CUSTOM_ERROR_CANT_SUMMON_GARGOYLE = 10, // You cannot summon another gargoyle yet. + SPELL_CUSTOM_ERROR_NEED_CORPSE_DUST_IF_NO_TARGET = 11, // Requires Corpse Dust if the target is not dead and humanoid. + SPELL_CUSTOM_ERROR_MUST_BE_AT_SHATTERHORN = 12, // Can only be placed near Shatterhorn + SPELL_CUSTOM_ERROR_MUST_TARGET_PROTO_DRAKE_EGG = 13, // You must first select a Proto-Drake Egg. + SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_TREE = 14, // You must be close to a marked tree. + SPELL_CUSTOM_ERROR_MUST_TARGET_TURKEY = 15, // You must target a Fjord Turkey. + SPELL_CUSTOM_ERROR_MUST_TARGET_HAWK = 16, // You must target a Fjord Hawk. + SPELL_CUSTOM_ERROR_TOO_FAR_FROM_BOUY = 17, // You are too far from the bouy. + SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_OIL_SLICK = 18, // Must be used near an oil slick. + SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_BOUY = 19, // You must be closer to the buoy! + SPELL_CUSTOM_ERROR_WYRMREST_VANQUISHER = 20, // You may only call for the aid of a Wyrmrest Vanquisher in Wyrmrest Temple, The Dragon Wastes, Galakrond's Rest or The Wicked Coil. + SPELL_CUSTOM_ERROR_MUST_TARGET_ICE_HEART_JORMUNGAR = 21, // That can only be used on a Ice Heart Jormungar Spawn. + SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_SINKHOLE = 22, // You must be closer to a sinkhole to use your map. + SPELL_CUSTOM_ERROR_REQUIRES_HAROLD_LANE = 23, // You may only call down a stampede on Harold Lane. + SPELL_CUSTOM_ERROR_REQUIRES_GAMMOTH_MAGNATAUR = 24, // You may only use the Pouch of Crushed Bloodspore on Gammothra or other magnataur in the Bloodspore Plains and Gammoth. + SPELL_CUSTOM_ERROR_MUST_BE_IN_RESURRECTION_CHAMBER = 25, // Requires the magmawyrm resurrection chamber in the back of the Maw of Neltharion. + SPELL_CUSTOM_ERROR_CANT_CALL_WINTERGARDE_HERE = 26, // You may only call down a Wintergarde Gryphon in Wintergarde Keep or the Carrion Fields. + SPELL_CUSTOM_ERROR_MUST_TARGET_WILHELM = 27, // What are you doing? Only aim that thing at Wilhelm! + SPELL_CUSTOM_ERROR_NOT_ENOUGH_HEALTH = 28, // Not enough health! + SPELL_CUSTOM_ERROR_NO_NEARBY_CORPSES = 29, // There are no nearby corpses to use. + SPELL_CUSTOM_ERROR_TOO_MANY_GHOULS = 30, // You've created enough ghouls. Return to Gothik the Harvester at Death's Breach. + SPELL_CUSTOM_ERROR_GO_FURTHER_FROM_SUNDERED_SHARD = 31, // Your companion does not want to come here. Go further from the Sundered Shard. + SPELL_CUSTOM_ERROR_MUST_BE_IN_CAT_FORM = 32, // Must be in Cat Form + SPELL_CUSTOM_ERROR_MUST_BE_DEATH_KNIGHT = 33, // Only Death Knights may enter Ebon Hold. + SPELL_CUSTOM_ERROR_MUST_BE_IN_BEAR_FORM = 34, // Must be in Bear Form + SPELL_CUSTOM_ERROR_MUST_BE_NEAR_HELPLESS_VILLAGER = 35, // You must be within range of a Helpless Wintergarde Villager. + SPELL_CUSTOM_ERROR_CANT_TARGET_ELEMENTAL_MECHANICAL = 36, // You cannot target an elemental or mechanical corpse. + SPELL_CUSTOM_ERROR_MUST_HAVE_USED_DALARAN_CRYSTAL = 37, // This teleport crystal cannot be used until the teleport crystal in Dalaran has been used at least once. + SPELL_CUSTOM_ERROR_YOU_ALREADY_HOLD_SOMETHING = 38, // You are already holding something in your hand. You must throw the creature in your hand before picking up another. + SPELL_CUSTOM_ERROR_YOU_DONT_HOLD_ANYTHING = 39, // You don't have anything to throw! Find a Vargul and use Gymer Grab to pick one up! + SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_VALDURAN = 40, // Bouldercrag's War Horn can only be used within 10 yards of Valduran the Stormborn. + SPELL_CUSTOM_ERROR_NO_PASSENGER = 41, // You are not carrying a passenger. There is nobody to drop off. + SPELL_CUSTOM_ERROR_CANT_BUILD_MORE_VEHICLES = 42, // You cannot build any more siege vehicles. + SPELL_CUSTOM_ERROR_ALREADY_CARRYING_CRUSADER = 43, // You are already carrying a captured Argent Crusader. You must return to the Argent Vanguard infirmary and drop off your passenger before you may pick up another. + SPELL_CUSTOM_ERROR_CANT_DO_WHILE_ROOTED = 44, // You can't do that while rooted. + SPELL_CUSTOM_ERROR_REQUIRES_NEARBY_TARGET = 45, // Requires a nearby target. + SPELL_CUSTOM_ERROR_NOTHING_TO_DISCOVER = 46, // Nothing left to discover. + SPELL_CUSTOM_ERROR_NOT_ENOUGH_TARGETS = 47, // No targets close enough to bluff. + SPELL_CUSTOM_ERROR_CONSTRUCT_TOO_FAR = 48, // Your Iron Rune Construct is out of range. + SPELL_CUSTOM_ERROR_REQUIRES_GRAND_MASTER_ENGINEER = 49, // Requires Engineering (350) + SPELL_CUSTOM_ERROR_CANT_USE_THAT_MOUNT = 50, // You can't use that mount. + SPELL_CUSTOM_ERROR_NOONE_TO_EJECT = 51, // There is nobody to eject! + SPELL_CUSTOM_ERROR_TARGET_MUST_BE_BOUND = 52, // The target must be bound to you. + SPELL_CUSTOM_ERROR_TARGET_MUST_BE_UNDEAD = 53, // Target must be undead. + SPELL_CUSTOM_ERROR_TARGET_TOO_FAR = 54, // You have no target or your target is too far away. + SPELL_CUSTOM_ERROR_MISSING_DARK_MATTER = 55, // Missing Reagents: Dark Matter + SPELL_CUSTOM_ERROR_CANT_USE_THAT_ITEM = 56, // You can't use that item + SPELL_CUSTOM_ERROR_CANT_DO_WHILE_CYCYLONED = 57, // You can't do that while Cycloned + SPELL_CUSTOM_ERROR_TARGET_HAS_SCROLL = 58, // Target is already affected by a similar effect + SPELL_CUSTOM_ERROR_POISON_TOO_STRONG = 59, // That anti-venom is not strong enough to dispel that poison + SPELL_CUSTOM_ERROR_MUST_HAVE_LANCE_EQUIPPED = 60, // You must have a lance equipped. + SPELL_CUSTOM_ERROR_MUST_BE_CLOSE_TO_MAIDEN = 61, // You must be near the Maiden of Winter's Breath Lake. + SPELL_CUSTOM_ERROR_LEARNED_EVERYTHING = 62, // You have learned everything from that book + SPELL_CUSTOM_ERROR_PET_IS_DEAD = 63, // Your pet is dead + SPELL_CUSTOM_ERROR_NO_VALID_TARGETS = 64, // There are no valid targets within range. + SPELL_CUSTOM_ERROR_GM_ONLY = 65, // Only GMs may use that. Your account has been reported for investigation. + SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_58 = 66, // You must reach level 58 to use this portal. + SPELL_CUSTOM_ERROR_AT_HONOR_CAP = 67, // You already have the maximum amount of honor. + SPELL_CUSTOM_ERROR_HAVE_HOT_ROD = 68, // You already have a Hot Rod. + SPELL_CUSTOM_ERROR_PARTYGOER_MORE_BUBBLY = 69, // This partygoer wants some more bubbly. + SPELL_CUSTOM_ERROR_PARTYGOER_NEED_BUCKET = 70, // This partygoer needs a bucket! + SPELL_CUSTOM_ERROR_PARTYGOER_WANT_TO_DANCE = 71, // This partygoer wants to dance with you. + SPELL_CUSTOM_ERROR_PARTYGOER_WANT_FIREWORKS = 72, // This partygoer wants to see some fireworks. + SPELL_CUSTOM_ERROR_PARTYGOER_WANT_APPETIZER = 73, // This partygoer wants some more hors d'oeuvres. + SPELL_CUSTOM_ERROR_GOBLIN_BATTERY_DEPLETED = 74, // The Goblin All-In-1-Der Belt's battery is depleted. + SPELL_CUSTOM_ERROR_MUST_HAVE_DEMONIC_CIRCLE = 75, // You must have a demonic circle active. + SPELL_CUSTOM_ERROR_AT_MAX_RAGE = 76, // You already have maximum rage + SPELL_CUSTOM_ERROR_REQUIRES_350_ENGINEERING = 77, // Requires Engineering (350) + SPELL_CUSTOM_ERROR_SOUL_BELONGS_TO_LICH_KING = 78, // Your soul belongs to the Lich King + SPELL_CUSTOM_ERROR_ATTENDANT_HAS_PONY = 79, // Your attendant already has an Argent Pony + SPELL_CUSTOM_ERROR_GOBLIN_STARTING_MISSION = 80, // First, Overload the Defective Generator, Activate the Leaky Stove, and Drop a Cigar on the Flammable Bed. + SPELL_CUSTOM_ERROR_GASBOT_ALREADY_SENT = 81, // You've already sent in the Gasbot and destroyed headquarters! + SPELL_CUSTOM_ERROR_GOBLIN_IS_PARTIED_OUT = 82, // This goblin is all partied out! + SPELL_CUSTOM_ERROR_MUST_HAVE_FIRE_TOTEM = 83, // You must have a Magma, Flametongue, or Fire Elemental Totem active. + SPELL_CUSTOM_ERROR_CANT_TARGET_VAMPIRES = 84, // You may not bite other vampires. + SPELL_CUSTOM_ERROR_PET_ALREADY_AT_YOUR_LEVEL = 85, // Your pet is already at your level. + SPELL_CUSTOM_ERROR_MISSING_ITEM_REQUIREMENS = 86, // You do not meet the level requirements for this item. + SPELL_CUSTOM_ERROR_TOO_MANY_ABOMINATIONS = 87, // There are too many Mutated Abominations. + SPELL_CUSTOM_ERROR_ALL_POTIONS_USED = 88, // The potions have all been depleted by Professor Putricide. + SPELL_CUSTOM_ERROR_DEFEATED_ENOUGH_ALREADY = 89, // You have already defeated enough of them. + SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_65 = 90, // Requires level 65 + SPELL_CUSTOM_ERROR_DESTROYED_KTC_OIL_PLATFORM = 91, // You have already destroyed the KTC Oil Platform. + SPELL_CUSTOM_ERROR_LAUNCHED_ENOUGH_CAGES = 92, // You have already launched enough cages. + SPELL_CUSTOM_ERROR_REQUIRES_BOOSTER_ROCKETS = 93, // Requires Single-Stage Booster Rockets. Return to Hobart Grapplehammer to get more. + SPELL_CUSTOM_ERROR_ENOUGH_WILD_CLUCKERS = 94, // You have already captured enough wild cluckers. + SPELL_CUSTOM_ERROR_REQUIRES_CONTROL_FIREWORKS = 95, // Requires Remote Control Fireworks. Return to Hobart Grapplehammer to get more. + SPELL_CUSTOM_ERROR_MAX_NUMBER_OF_RECRUITS = 96, // You already have the max number of recruits. + SPELL_CUSTOM_ERROR_MAX_NUMBER_OF_VOLUNTEERS = 97, // You already have the max number of volunteers. + SPELL_CUSTOM_ERROR_FROSTMOURNE_RENDERED_RESURRECT = 98, // Frostmourne has rendered you unable to resurrect. + SPELL_CUSTOM_ERROR_CANT_MOUNT_WITH_SHAPESHIFT = 99, // You can't mount while affected by that shapeshift. + SPELL_CUSTOM_ERROR_FAWNS_ALREADY_FOLLOWING = 100, // Three fawns are already following you! + SPELL_CUSTOM_ERROR_ALREADY_HAVE_RIVER_BOAT = 101, // You already have a River Boat. + SPELL_CUSTOM_ERROR_NO_ACTIVE_ENCHANTMENT = 102, // You have no active enchantment to unleash. + SPELL_CUSTOM_ERROR_ENOUGH_HIGHBOURNE_SOULS = 103, // You have bound enough Highborne souls. Return to Arcanist Valdurian. + SPELL_CUSTOM_ERROR_ATLEAST_40YD_FROM_OIL_DRILLING = 104, // You must be at least 40 yards away from all other Oil Drilling Rigs. + SPELL_CUSTOM_ERROR_ABOVE_ENSLAVED_PEARL_MINER = 106, // You must be above the Enslaved Pearl Miner. + SPELL_CUSTOM_ERROR_MUST_TARGET_CORPSE_SPECIAL_1 = 107, // You must target the corpse of a Seabrush Terrapin, Scourgut Remora, or Spinescale Hammerhead. + SPELL_CUSTOM_ERROR_SLAGHAMMER_ALREADY_PRISONER = 108, // Ambassador Slaghammer is already your prisoner. + SPELL_CUSTOM_ERROR_REQUIRE_ATTUNED_LOCATION_1 = 109, // Requires a location that is attuned with the Naz'jar Battlemaiden. + SPELL_CUSTOM_ERROR_NEED_TO_FREE_DRAKE_FIRST = 110, // Free the Drake from the net first! + SPELL_CUSTOM_ERROR_DRAGONMAW_ALLIES_ALREADY_FOLLOW = 111, // You already have three Dragonmaw allies following you. + SPELL_CUSTOM_ERROR_REQUIRE_OPPOSABLE_THUMBS = 112, // Requires Opposable Thumbs. + SPELL_CUSTOM_ERROR_NOT_ENOUGH_HEALTH_2 = 113, // Not enough health + SPELL_CUSTOM_ERROR_ENOUGH_FORSAKEN_TROOPERS = 114, // You already have enough Forsaken Troopers. + SPELL_CUSTOM_ERROR_CANNOT_JUMP_TO_BOULDER = 115, // You cannot jump to another boulder yet. + SPELL_CUSTOM_ERROR_SKILL_TOO_HIGH = 116, // Skill too high. + SPELL_CUSTOM_ERROR_ALREADY_6_SURVIVORS_RESCUED = 117, // You have already rescued 6 Survivors. + SPELL_CUSTOM_ERROR_MUST_FACE_SHIPS_FROM_BALLOON = 118, // You need to be facing the ships from the rescue balloon. + SPELL_CUSTOM_ERROR_CANNOT_SUPERVISE_MORE_CULTISTS = 119, // You cannot supervise more than 5 Arrested Cultists at a time. + SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_85 = 120, // You must reach level 85 to use this portal. + SPELL_CUSTOM_ERROR_MUST_BE_BELOW_35_HEALTH = 121, // Your target must be below 35% health. + SPELL_CUSTOM_ERROR_MUST_SELECT_SPECIALIZATION = 122, // You must select a specialization first. + SPELL_CUSTOM_ERROR_TOO_WISE_AND_POWERFUL = 123, // You are too wise and powerful to gain any benefit from that item. + SPELL_CUSTOM_ERROR_TOO_CLOSE_ARGENT_LIGHTWELL = 124, // You are within 10 yards of another Argent Lightwell. + SPELL_CUSTOM_ERROR_NOT_WHILE_SHAPESHIFTED = 125, // You can't do that while shapeshifted. + SPELL_CUSTOM_ERROR_MANA_GEM_IN_BANK = 126, // You already have a Mana Gem in your bank. + SPELL_CUSTOM_ERROR_FLAME_SHOCK_NOT_ACTIVE = 127, // You must have at least one Flame Shock active. + SPELL_CUSTOM_ERROR_CANT_TRANSFORM = 128, // You cannot transform right now + SPELL_CUSTOM_ERROR_PET_MUST_BE_ATTACKING = 129, // Your pet must be attacking a target. + SPELL_CUSTOM_ERROR_GNOMISH_ENGINEERING = 130, // Requires Gnomish Engineering + SPELL_CUSTOM_ERROR_GOBLIN_ENGINEERING = 131, // Requires Goblin Engineering + SPELL_CUSTOM_ERROR_NO_TARGET = 132, // You have no target. + SPELL_CUSTOM_ERROR_PET_OUT_OF_RANGE = 133, // Your Pet is out of range of the target. + SPELL_CUSTOM_ERROR_HOLDING_FLAG = 134, // You can't do that while holding the flag. + SPELL_CUSTOM_ERROR_TARGET_HOLDING_FLAG = 135, // You can't do that to targets holding the flag. + SPELL_CUSTOM_ERROR_PORTAL_NOT_OPEN = 136, // The portal is not yet open. Continue helping the druids at the Sanctuary of Malorne. + SPELL_CUSTOM_ERROR_AGGRA_AIR_TOTEM = 137, // You need to be closer to Aggra's Air Totem, in the west. + SPELL_CUSTOM_ERROR_AGGRA_WATER_TOTEM = 138, // You need to be closer to Aggra's Water Totem, in the north. + SPELL_CUSTOM_ERROR_AGGRA_EARTH_TOTEM = 139, // You need to be closer to Aggra's Earth Totem, in the east. + SPELL_CUSTOM_ERROR_AGGRA_FIRE_TOTEM = 140, // You need to be closer to Aggra's Fire Totem, near Thrall. + SPELL_CUSTOM_ERROR_FACING_WRONG_WAY = 141, // You are facing the wrong way. + SPELL_CUSTOM_ERROR_TOO_CLOSE_TO_MAKESHIFT_DYNAMITE = 142, // You are within 10 yards of another Makeshift Dynamite. + SPELL_CUSTOM_ERROR_NOT_NEAR_SAPPHIRE_SUNKEN_SHIP = 143, // You must be near the sunken ship at Sapphire's End in the Jade Forest. + SPELL_CUSTOM_ERROR_DEMONS_HEALTH_FULL = 144, // That demon's health is already full. + SPELL_CUSTOM_ERROR_ONYX_SERPENT_NOT_OVERHEAD = 145, // Wait until the Onyx Serpent is directly overhead. + SPELL_CUSTOM_ERROR_OBJECTIVE_ALREADY_COMPLETE = 146, // Your objective is already complete. + SPELL_CUSTOM_ERROR_PUSH_SAD_PANDA_TOWARDS_TOWN = 147, // You can only push Sad Panda towards Sad Panda Town! + SPELL_CUSTOM_ERROR_TARGET_HAS_STARTDUST_2 = 148, // Target is already affected by Stardust No. 2. + SPELL_CUSTOM_ERROR_ELEMENTIUM_GEM_CLUSTERS = 149, // You cannot deconstruct Elementium Gem Clusters while collecting them! + SPELL_CUSTOM_ERROR_YOU_DONT_HAVE_ENOUGH_HEALTH = 150, // You don't have enough health. + SPELL_CUSTOM_ERROR_YOU_CANNOT_USE_THE_GATEWAY_YET = 151, // You cannot use the gateway yet. + SPELL_CUSTOM_ERROR_CHOOSE_SPEC_FOR_ASCENDANCE = 152, // You must choose a specialization to use Ascendance. + SPELL_CUSTOM_ERROR_INSUFFICIENT_BLOOD_CHARGES = 153, // You have insufficient Blood Charges. + SPELL_CUSTOM_ERROR_NO_FULLY_DEPLETED_RUNES = 154, // No fully depleted runes. + SPELL_CUSTOM_ERROR_NO_MORE_CHARGES = 155, // No more charges. + SPELL_CUSTOM_ERROR_STATUE_IS_OUT_OF_RANGE_OF_TARGET = 156, // Statue is out of range of the target. + SPELL_CUSTOM_ERROR_YOU_DONT_HAVE_A_STATUE_SUMMONED = 157, // You don't have a statue summoned. + SPELL_CUSTOM_ERROR_YOU_HAVE_NO_SPIRIT_ACTIVE = 158, // You have no spirit active. + SPELL_CUSTOM_ERROR_BOTH_DISESASES_MUST_BE_ON_TARGET = 159, // Both Frost Fever and Blood Plague must be present on the target. + SPELL_CUSTOM_ERROR_CANT_DO_THAT_WITH_ORB_OF_POWER = 160, // You can't do that while holding an Orb of Power. + SPELL_CUSTOM_ERROR_CANT_DO_THAT_WHILE_JUMPING_OR_FALLING = 161, // You can't do that while jumping or falling. + SPELL_CUSTOM_ERROR_MUST_BE_TRANSFORMED_BY_POLYFORMIC_ACID = 162, // You must be transformed by Polyformic Acid. + SPELL_CUSTOM_ERROR_NOT_ENOUGH_ACID_TO_STORE_TRANSFORMATION = 163, // There isn't enough acid left to store this transformation. + SPELL_CUSTOM_ERROR_MUST_HAVE_FLIGHT_MASTERS_LICENSE = 164, // You must obtain a Flight Master's License before using this spell. + SPELL_CUSTOM_ERROR_ALREADY_SAMPLED_SAP_FROM_FEEDER = 165, // You have already sampled sap from this Feeder. + SPELL_CUSTOM_ERROR_MUST_BE_NEWR_MANTID_FEEDER = 166, // Requires you to be near a Mantid Feeder in the Heart of Fear. + SPELL_CUSTOM_ERROR_TARGET_MUST_BE_IN_DIRECTLY_FRONT = 167, // Target must be directly in front of you. + SPELL_CUSTOM_ERROR_CANT_DO_THAT_WHILE_MYTHIC_KEYSTONE_IS_ACTIVE = 168, // You can't do that while a Mythic Keystone is active. + SPELL_CUSTOM_ERROR_WRONG_CLASS_FOR_MOUNT = 169, // You are not the correct class for that mount. + SPELL_CUSTOM_ERROR_NOTHING_LEFT_TO_DISCOVER = 170, // Nothing left to discover. + SPELL_CUSTOM_ERROR_NO_EXPLOSIVES_AVAILABLE = 171, // There are no explosives available. + SPELL_CUSTOM_ERROR_YOU_MUST_BE_FLAGGED_FOR_PVP = 172, // You must be flagged for PvP. + SPELL_CUSTOM_ERROR_REQUIRES_BATTLE_RATIONS = 173, // Requires Battle Rations or Meaty Haunch + SPELL_CUSTOM_ERROR_REQUIRES_BRITTLE_ROOT = 174, // Requires Brittle Root + SPELL_CUSTOM_ERROR_REQUIRES_LABORERS_TOOL = 175, // Requires Laborer's Tool + SPELL_CUSTOM_ERROR_REQUIRES_UNEXPLODED_CANNONBALL = 176, // Requires Unexploded Cannonball + SPELL_CUSTOM_ERROR_REQUIRES_MISPLACED_KEG = 177, // Requires Misplaced Keg + SPELL_CUSTOM_ERROR_REQUIRES_LIQUID_FIRE = 178, // Requires Liquid Fire, Jungle Hops, or Spirit-kissed Water + SPELL_CUSTOM_ERROR_REQUIRES_KRASARI_IRON = 179, // Requires Krasari Iron + SPELL_CUSTOM_ERROR_REQUIRES_SPIRIT_KISSED_WATER = 180, // Requires Spirit-Kissed Water + SPELL_CUSTOM_ERROR_REQUIRES_SNAKE_OIL = 181, // Requires Snake Oil + SPELL_CUSTOM_ERROR_SCENARIO_IS_IN_PROGRESS = 182, // You can't do that while a Scenario is in progress. + SPELL_CUSTOM_ERROR_REQUIRES_DARKMOON_FAIRE_OPEN = 183, // Requires the Darkmoon Faire to be open. + SPELL_CUSTOM_ERROR_ALREADY_AT_VALOR_CAP = 184, // Already at Valor cap + SPELL_CUSTOM_ERROR_ALREADY_COMMENDED_BY_THIS_FACTION = 185, // Already commended by this faction + SPELL_CUSTOM_ERROR_OUT_OF_COINS = 186, // Out of coins! Pickpocket humanoids to get more. + SPELL_CUSTOM_ERROR_ONLY_ONE_ELEMENTAL_SPIRIT = 187, // Only one elemental spirit on a target at a time. + SPELL_CUSTOM_ERROR_DONT_KNOW_HOW_TO_TAME_DIREHORNS = 188, // You do not know how to tame Direhorns. + SPELL_CUSTOM_ERROR_MUST_BE_NEAR_BLOODIED_COURT_GATE = 189, // You must be near the Bloodied Court gate. + SPELL_CUSTOM_ERROR_YOU_ARE_NOT_ELECTRIFIED = 190, // You are not Electrified. + SPELL_CUSTOM_ERROR_THERE_IS_NOTHING_TO_BE_FETCHED = 191, // There is nothing to be fetched. + SPELL_CUSTOM_ERROR_REQUIRES_THE_THUNDER_FORGE = 192, // Requires The Thunder Forge. + SPELL_CUSTOM_ERROR_CANNOT_USE_THE_DICE_AGAIN_YET = 193, // You cannot use the dice again yet. + SPELL_CUSTOM_ERROR_ALREADY_MEMBER_OF_BRAWLERS_GUILD = 194, // You are already a member of the Brawler's Guild. + SPELL_CUSTOM_ERROR_CANT_CHANGE_SPEC_IN_CELESTIAL_CHALLENGE = 195, // You may not change talent specializations during a celestial challenge. + SPELL_CUSTOM_ERROR_SPEC_DOES_MATCH_CHALLENGE = 196, // Your talent specialization does not match the selected challenge. + SPELL_CUSTOM_ERROR_YOU_DONT_HAVE_ENOUGH_CURRENCY = 197, // You don't have enough currency to do that. + SPELL_CUSTOM_ERROR_TARGET_CANNOT_BENEFIT_FROM_SPELL = 198, // Target cannot benefit from that spell + SPELL_CUSTOM_ERROR_YOU_CAN_ONLY_HAVE_ONE_HEALING_RAIN = 199, // You can only have one Healing Rain active at a time. + SPELL_CUSTOM_ERROR_THE_DOOR_IS_LOCKED = 200, // The door is locked. + SPELL_CUSTOM_ERROR_YOU_NEED_TO_SELECT_WAITING_CUSTOMER = 201, // You need to select a customer who is waiting in line first. + SPELL_CUSTOM_ERROR_CANT_CHANGE_SPEC_DURING_TRIAL = 202, // You may not change specialization while a trial is in progress. + SPELL_CUSTOM_ERROR_CUSTOMER_NEED_TO_GET_IN_LINE = 203, // You must wait for customers to get in line before you can select them to be seated. + SPELL_CUSTOM_ERROR_MUST_BE_CLOSER_TO_GAZLOWE_OBJECTIVE = 204, // Must be closer to one of Gazlowe's objectives to deploy! + SPELL_CUSTOM_ERROR_MUST_BE_CLOSER_TO_THAELIN_OBJECTIVE = 205, // Must be closer to one of Thaelin's objectives to deploy! + SPELL_CUSTOM_ERROR_YOUR_PACK_OF_VOLEN_IS_FULL = 206, // Your pack of volen is already full! + SPELL_CUSTOM_ERROR_REQUIRES_600_MINING_OR_BLACKSMITHING = 207, // Requires 600 Mining or Blacksmithing + SPELL_CUSTOM_ERROR_ARKONITE_PROTECTOR_NOT_IN_RANGE = 208, // The Arkonite Protector is not in range. + SPELL_CUSTOM_ERROR_TARGET_CANNOT_HAVE_BOTH_BEACONS = 209, // You are unable to have both Beacon of Light and Beacon of Faith on the same target. + SPELL_CUSTOM_ERROR_CAN_ONLY_USE_ON_AFK_PLAYER = 210, // Can only be used on AFK players. + SPELL_CUSTOM_ERROR_NO_LOOTABLE_CORPSES_IN_RANGE = 211, // No lootable corpse in range + SPELL_CUSTOM_ERROR_CHIMAERON_TOO_CALM_TO_TAME = 212, // Chimaeron is too calm to tame right now. + SPELL_CUSTOM_ERROR_CAN_ONLY_CARRY_ONE_TYPE_OF_MUNITIONS = 213, // You may only carry one type of Blackrock Munitions. + SPELL_CUSTOM_ERROR_OUT_OF_BLACKROCK_MUNITIONS = 214, // You have run out of Blackrock Munitions. + SPELL_CUSTOM_ERROR_CARRYING_MAX_AMOUNT_OF_MUNITIONS = 215, // You are carrying the maximum amount of Blackrock Munitions. + SPELL_CUSTOM_ERROR_TARGET_IS_TOO_FAR_AWAY = 216, // Target is too far away. + SPELL_CUSTOM_ERROR_CANNOT_USE_DURING_BOSS_ENCOUNTER = 217, // Cannot use during a boss encounter. + SPELL_CUSTOM_ERROR_MUST_HAVE_MELEE_WEAPON_IN_BOTH_HANDS = 218, // Must have a Melee Weapon equipped in both hands + SPELL_CUSTOM_ERROR_YOUR_WEAPON_HAS_OVERHEATED = 219, // Your weapon has overheated. + SPELL_CUSTOM_ERROR_MUST_BE_PARTY_LEADER_TO_QUEUE = 220, // You must be a party leader to queue your group. + SPELL_CUSTOM_ERROR_NOT_ENOUGH_FUEL = 221, // Not enough fuel + SPELL_CUSTOM_ERROR_YOU_ARE_ALREADY_DISGUISED = 222, // You are already disguised! + SPELL_CUSTOM_ERROR_YOU_NEED_TO_BE_IN_SHREDDER = 223, // You need to be in a Shredder to chop this up! + SPELL_CUSTOM_ERROR_FOOD_CANNOT_EAT_FOOD = 224, // Food cannot eat food + SPELL_CUSTOM_ERROR_MYSTERIOUS_FORCE_PREVENTS_OPENING_CHEST = 225, // A mysterious force prevents you from opening the chest. + SPELL_CUSTOM_ERROR_CANT_DO_THAT_WHILE_HOLDING_EMPOWERED_ORE = 226, // You can't do that while holding Empowered Ore. + SPELL_CUSTOM_ERROR_NOT_ENOUGH_AMMUNITION = 227, // Not enough Ammunition! + SPELL_CUSTOM_ERROR_YOU_NEED_BEATFACE_THE_GLADIATOR = 228, // You need Beatface the Sparring Arena gladiator to break this! + SPELL_CUSTOM_ERROR_YOU_CAN_ONLY_HAVE_ONE_WAYGATE = 229, // You can only have one waygate open. Disable an activated waygate first. + SPELL_CUSTOM_ERROR_YOU_CAN_ONLY_HAVE_TWO_WAYGATES = 230, // You can only have two waygates open. Disable an activated waygate first. + SPELL_CUSTOM_ERROR_YOU_CAN_ONLY_HAVE_THREE_WAYGATES = 231, // You can only have three waygates open. Disable an activated waygate first. + SPELL_CUSTOM_ERROR_REQUIRES_MAGE_TOWER = 232, // Requires Mage Tower + SPELL_CUSTOM_ERROR_REQUIRES_SPIRIT_LODGE = 233, // Requires Spirit Lodge + SPELL_CUSTOM_ERROR_FROST_WYRM_ALREADY_ACTIVE = 234, // A Frost Wyrm is already active. + SPELL_CUSTOM_ERROR_NOT_ENOUGH_RUNIC_POWER = 235, // Not enough Runic Power + SPELL_CUSTOM_ERROR_YOU_ARE_THE_PARTY_LEADER = 236, // You are the Party Leader. + SPELL_CUSTOM_ERROR_YULON_IS_ALREADY_ACTIVE = 237, // Yu'lon is already active. + SPELL_CUSTOM_ERROR_A_STAMPEDE_IS_ALREADY_ACTIVE = 238, // A Stampede is already active. + SPELL_CUSTOM_ERROR_YOU_ARE_ALREADY_WELL_FED = 239, // You are already Well Fed. + SPELL_CUSTOM_ERROR_CANT_DO_THAT_UNDER_SUPPRESSIVE_FIRE = 240, // You cannot do that while under Suppressive Fire. + SPELL_CUSTOM_ERROR_YOU_ALREADY_HAVE_MURLOC_SLOP = 241, // You already have a piece of Murloc Slop. + SPELL_CUSTOM_ERROR_YOU_DONT_HAVE_ARTIFACT_FRAGMENTS = 242, // You don't have any Artifact Fragments. + SPELL_CUSTOM_ERROR_YOU_ARENT_IN_A_PARTY = 243, // You aren't in a Party. + SPELL_CUSTOM_ERROR_REQUIRES_20_AMMUNITION = 244, // Requires 30 Ammunition! + SPELL_CUSTOM_ERROR_REQUIRES_30_AMMUNITION = 245, // Requires 20 Ammunition! + SPELL_CUSTOM_ERROR_YOU_ALREADY_HAVE_MAX_OUTCAST_FOLLOWERS = 246, // You already have the maximum amount of Outcasts following you. + SPELL_CUSTOM_ERROR_NOT_IN_WORLD_PVP_ZONE = 247, // Not in World PvP zone. + SPELL_CUSTOM_ERROR_ALREADY_AT_RESOURCE_CAP = 248, // Already at Resource cap + SPELL_CUSTOM_ERROR_APEXIS_SENTINEL_REQUIRES_ENERGY = 249, // This Apexis Sentinel requires energy from a nearby Apexis Pylon to be powered up. + SPELL_CUSTOM_ERROR_YOU_MUST_HAVE_3_OR_FEWER_PLAYER = 250, // You must have 3 or fewer players. + SPELL_CUSTOM_ERROR_YOU_ALREADY_READ_TREASURE_MAP = 251, // You have already read that treasure map. + SPELL_CUSTOM_ERROR_MAY_ONLY_USE_WHILE_GARRISON_UNDER_ATTACK = 252, // You may only use this item while your garrison is under attack. + SPELL_CUSTOM_ERROR_REQUIRES_ACTIVE_MUSHROOMS = 253, // This spell requires active mushrooms for you to detonate. + SPELL_CUSTOM_ERROR_REQUIRES_FASTER_TIME_WITH_RACER = 254, // Requires a faster time with the basic racer + SPELL_CUSTOM_ERROR_REQUIRES_INFERNO_SHOT_AMMO = 255, // Requires Inferno Shot Ammo! + SPELL_CUSTOM_ERROR_YOU_CANNOT_DO_THAT_RIGHT_NOW = 256, // You cannot do that right now. + SPELL_CUSTOM_ERROR_A_TRAP_IS_ALREADY_PLACED_THERE = 257, // A trap is already placed there. + SPELL_CUSTOM_ERROR_YOU_ARE_ALREADY_ON_THAT_QUEST = 258, // You are already on that quest. + SPELL_CUSTOM_ERROR_REQUIRES_FELFORGED_CUDGEL = 259, // Requires a Felforged Cudgel! + SPELL_CUSTOM_ERROR_CANT_TAKE_WHILE_BEING_DAMAGED = 260, // Can't take while being damaged! + SPELL_CUSTOM_ERROR_YOU_ARE_BOUND_TO_DRAENOR = 261, // You are bound to Draenor by Archimonde's magic. + SPELL_CUSTOM_ERROR_ALREAY_HAVE_MAX_NUMBER_OF_SHIPS = 262, // You already have the maximum number of ships your shipyard can support. + SPELL_CUSTOM_ERROR_MUST_BE_AT_SHIPYARD = 263, // You must be at your shipyard. + SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_3_MAGE_TOWER = 264, // Requires a level 3 Mage Tower. + SPELL_CUSTOM_ERROR_REQUIRES_LEVEL_3_SPIRIT_LODGE = 265, // Requires a level 3 Spirit Lodge. + SPELL_CUSTOM_ERROR_YOU_DO_NOT_LIKE_FEL_EGGS_AND_HAM = 266, // You do not like Fel Eggs and Ham. + SPELL_CUSTOM_ERROR_ALREADY_ENTERED_IN_THIS_AGREEMENT = 267, // You have already entered in to this trade agreement. + SPELL_CUSTOM_ERROR_CANNOT_STEAL_THAT_WHILE_GUARDS_ARE_ON_DUTY = 268, // You cannot steal that while guards are on duty. + SPELL_CUSTOM_ERROR_YOU_ALREADY_USED_VANTUS_RUNE = 269, // You have already used a Vantus Rune this week. + SPELL_CUSTOM_ERROR_THAT_ITEM_CANNOT_BE_OBLITERATED = 270, // That item cannot be obliterated. + SPELL_CUSTOM_ERROR_NO_SKINNABLE_CORPSE_IN_RANGE = 271, // No skinnable corpse in range + SPELL_CUSTOM_ERROR_MUST_BE_MERCENARY_TO_USE_TRINKET = 272, // You must be a Mercenary to use this trinket. + SPELL_CUSTOM_ERROR_YOU_MUST_BE_IN_COMBAT = 273, // You must be in combat. + SPELL_CUSTOM_ERROR_NO_ENEMIES_NEAR_TARGET = 274, // No enemies near target. + SPELL_CUSTOM_ERROR_REQUIRES_LEYSPINE_MISSILE = 275, // Requires a Leyspine Missile + SPELL_CUSTOM_ERROR_REQUIRES_BOTH_CURRENTS_CONNECTED = 276, // Requires both currents connected. + SPELL_CUSTOM_ERROR_CANT_DO_THAT_IN_DEMON_FORM = 277, // Can't do that while in demon form (yet) + SPELL_CUSTOM_ERROR_YOU_DONT_KNOW_HOW_TO_TAME_MECHS = 278, // You do not know how to tame or obtain lore about Mechs. + SPELL_CUSTOM_ERROR_CANNOT_CHARM_ANY_MORE_WITHERED = 279, // You cannot charm any more withered. + SPELL_CUSTOM_ERROR_REQUIRES_ACTIVE_HEALING_RAIN = 280, // Requires an active Healing Rain. + SPELL_CUSTOM_ERROR_ALREADY_COLLECTED_APPEARANCES = 281, // You've already collected these appearances + SPELL_CUSTOM_ERROR_CANNOT_RESURRECT_SURRENDERED_TO_MADNESS = 282, // Cannot resurrect someone who has surrendered to madness + SPELL_CUSTOM_ERROR_YOU_MUST_BE_IN_CAT_FORM = 283, // You must be in Cat Form. + SPELL_CUSTOM_ERROR_YOU_CANNOT_RELEASE_SPIRIT_YET = 284, // You cannot Release Spirit yet. + SPELL_CUSTOM_ERROR_NO_FISHING_NODES_NEARBY = 285, // No fishing nodes nearby. + SPELL_CUSTOM_ERROR_YOU_ARE_NOT_IN_CORRECT_SPEC = 286, // You are not the correct specialization. + SPELL_CUSTOM_ERROR_ULTHALESH_HAS_NO_POWER_WITHOUT_SOULS = 287, // Ulthalesh has no power without souls. + SPELL_CUSTOM_ERROR_CANNOT_CAST_THAT_WITH_VOODOO_TOTEM = 288, // You cannot cast that while talented into Voodoo Totem. + SPELL_CUSTOM_ERROR_ALREADY_COLLECTED_THIS_APPEARANCE = 289, // You've already collected this appearance. + SPELL_CUSTOM_ERROR_YOUR_PET_MAXIMUM_IS_ALREADY_HIGH = 290, // Your total pet maximum is already this high. + SPELL_CUSTOM_ERROR_YOU_DONT_HAVE_ENOUGH_WITHERED = 291, // You do not have enough withered to do that. + SPELL_CUSTOM_ERROR_REQUIRES_NEARBY_SOUL_FRAGMENT = 292, // Requires a nearby Soul Fragment. + SPELL_CUSTOM_ERROR_REQUIRES_AT_LEAST_10_WITHERED = 293, // Requires at least 10 living withered + SPELL_CUSTOM_ERROR_REQUIRES_AT_LEAST_14_WITHERED = 294, // Requires at least 14 living withered + SPELL_CUSTOM_ERROR_REQUIRES_AT_LEAST_18_WITHERED = 295, // Requires at least 18 living withered + SPELL_CUSTOM_ERROR_REQUIRES_2_WITHERED_MANA_RAGERS = 296, // Requires 2 Withered Mana-Ragers + SPELL_CUSTOM_ERROR_REQUIRES_1_WITHERED_BERSERKE = 297, // Requires 1 Withered Berserker + SPELL_CUSTOM_ERROR_REQUIRES_2_WITHERED_BERSERKER = 298, // Requires 2 Withered Berserkers + SPELL_CUSTOM_ERROR_TARGET_HEALTH_IS_TOO_LOW = 299, // Target's health is too low + SPELL_CUSTOM_ERROR_CANNOT_SHAPESHIFT_WHILE_RIDING_STORMTALON = 300, // You cannot shapeshift while riding Stormtalon + SPELL_CUSTOM_ERROR_CANNOT_CHANGE_SPEC_IN_COMBAT_TRAINING = 301, // You can not change specializations while in Combat Training. + SPELL_CUSTOM_ERROR_UNKNOWN_PHENOMENON_PREVENTS_LEYLINE_CONNECTION = 302, // Unknown phenomenon is preventing a connection to the Leyline. + SPELL_CUSTOM_ERROR_THE_NIGHTMARE_OBSCURES_YOUR_VISION = 303, // The Nightmare obscures your vision. + SPELL_CUSTOM_ERROR_YOU_ARE_IN_WRONG_CLASS_SPEC = 304, // You are in the wrong class specialization. + SPELL_CUSTOM_ERROR_THERE_ARE_NO_VALID_CORPSES_NEARBY = 305, // There are no valid corpses nearby. + SPELL_CUSTOM_ERROR_CANT_CAST_THAT_RIGHT_NOW = 306, // Can't cast that right now. + SPELL_CUSTOM_ERROR_NOT_ENOUGH_ANCIENT_MAN = 307, // Not enough Ancient Mana. + SPELL_CUSTOM_ERROR_REQUIRES_SONG_SCROLL = 308, // Requires a Song Scroll to function. + SPELL_CUSTOM_ERROR_MUST_HAVE_ARTIFACT_EQUIPPED = 309, // You must have an artifact weapon equipped. + SPELL_CUSTOM_ERROR_REQUIRES_CAT_FORM = 310, // Requires Cat Form. + SPELL_CUSTOM_ERROR_REQUIRES_BEAR_FORM = 311, // Requires Bear Form. + SPELL_CUSTOM_ERROR_REQUIRES_CONJURED_FOOD = 312, // Requires either a Conjured Mana Pudding or Conjured Mana Fritter. + SPELL_CUSTOM_ERROR_REQUIRES_ARTIFACT_WEAPON = 313, // Requires an artifact weapon. + SPELL_CUSTOM_ERROR_YOU_CANT_CAST_THAT_HERE = 314, // You can't cast that here + SPELL_CUSTOM_ERROR_CANT_DO_THAT_ON_CLASS_TRIAL = 315, // You cannot do that while on a Class Trial. }; enum StealthType diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp index 209aab0af00..fde1b1bf875 100644 --- a/src/server/game/Server/Packets/MovementPackets.cpp +++ b/src/server/game/Server/Packets/MovementPackets.cpp @@ -89,11 +89,11 @@ ByteBuffer& operator>>(ByteBuffer& data, MovementInfo& movementInfo) data >> movementInfo.pitch; data >> movementInfo.splineElevation; - uint32 removeMovementForcesCount = 0; + uint32 removeMovementForcesCount; data >> removeMovementForcesCount; - uint32 int168; - data >> int168; + uint32 moveIndex; + data >> moveIndex; for (uint32 i = 0; i < removeMovementForcesCount; ++i) { diff --git a/src/server/game/Server/Packets/SpellPackets.cpp b/src/server/game/Server/Packets/SpellPackets.cpp index 59d39183cea..36ce28478f0 100644 --- a/src/server/game/Server/Packets/SpellPackets.cpp +++ b/src/server/game/Server/Packets/SpellPackets.cpp @@ -52,7 +52,7 @@ WorldPacket const* WorldPackets::Spells::CategoryCooldown::Write() WorldPacket const* WorldPackets::Spells::SendKnownSpells::Write() { - _worldPacket.reserve(1 + 4 * KnownSpells.size()); + _worldPacket.reserve(1 + 4 * KnownSpells.size() + 4 * FavoriteSpells.size()); _worldPacket.WriteBit(InitialLogin); _worldPacket << uint32(KnownSpells.size()); @@ -102,64 +102,95 @@ void WorldPackets::Spells::SpellCastLogData::Initialize(Unit const* unit) ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastLogData const& spellCastLogData) { - data << spellCastLogData.Health; - data << spellCastLogData.AttackPower; - data << spellCastLogData.SpellPower; - data << int32(spellCastLogData.PowerData.size()); + data << int64(spellCastLogData.Health); + data << int32(spellCastLogData.AttackPower); + data << int32(spellCastLogData.SpellPower); + data.WriteBits(spellCastLogData.PowerData.size(), 9); + data.FlushBits(); + for (WorldPackets::Spells::SpellLogPowerData const& powerData : spellCastLogData.PowerData) { - data << powerData.PowerType; - data << powerData.Amount; + data << int32(powerData.PowerType); + data << int32(powerData.Amount); } - data.WriteBit(false); - // data << float // Unk data if bit is true + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SandboxScalingData const& unknown) +{ + data.WriteBits(unknown.Type, 3); + data << int16(unknown.PlayerLevelDelta); + data << uint8(unknown.TargetLevel); + data << uint8(unknown.Expansion); + data << uint8(unknown.Class); + data << uint8(unknown.TargetMinScalingLevel); + data << uint8(unknown.TargetMaxScalingLevel); + data << int8(unknown.TargetScalingLevelDelta); + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::AuraDataInfo const& auraData) +{ + data << auraData.CastID; + data << int32(auraData.SpellID); + data << int32(auraData.SpellXSpellVisualID); + data << uint8(auraData.Flags); + data << uint32(auraData.ActiveFlags); + data << uint16(auraData.CastLevel); + data << uint8(auraData.Applications); + data.WriteBit(auraData.CastUnit.is_initialized()); + data.WriteBit(auraData.Duration.is_initialized()); + data.WriteBit(auraData.Remaining.is_initialized()); + data.WriteBit(auraData.TimeMod.is_initialized()); + data.WriteBits(auraData.Points.size(), 6); + data.WriteBits(auraData.EstimatedPoints.size(), 6); + data.WriteBit(auraData.SandboxScaling.is_initialized()); + + if (auraData.CastUnit) + data << *auraData.CastUnit; + + if (auraData.Duration) + data << uint32(*auraData.Duration); + + if (auraData.Remaining) + data << uint32(*auraData.Remaining); + + if (auraData.TimeMod) + data << float(*auraData.TimeMod); + + if (!auraData.Points.empty()) + data.append(auraData.Points.data(), auraData.Points.size()); + + if (!auraData.EstimatedPoints.empty()) + data.append(auraData.EstimatedPoints.data(), auraData.EstimatedPoints.size()); + + if (auraData.SandboxScaling) + data << *auraData.SandboxScaling; + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::AuraInfo const& aura) +{ + data << aura.Slot; + data.WriteBit(aura.AuraData.is_initialized()); data.FlushBits(); + if (aura.AuraData) + data << *aura.AuraData; + return data; } WorldPacket const* WorldPackets::Spells::AuraUpdate::Write() { _worldPacket.WriteBit(UpdateAll); + _worldPacket.WriteBits(Auras.size(), 9); + for (AuraInfo const& aura : Auras) + _worldPacket << aura; + _worldPacket << UnitGUID; - _worldPacket << uint32(Auras.size()); - for (auto& aura : Auras) - { - _worldPacket << aura.Slot; - if (_worldPacket.WriteBit(aura.AuraData.is_initialized())) - { - AuraDataInfo const& data = *aura.AuraData; - _worldPacket << uint32(data.SpellID); - _worldPacket << uint32(data.SpellXSpellVisualID); - _worldPacket << uint8(data.Flags); - _worldPacket << uint32(data.ActiveFlags); - _worldPacket << uint16(data.CastLevel); - _worldPacket << uint8(data.Applications); - _worldPacket << uint32(data.Points.size()); - _worldPacket << uint32(data.EstimatedPoints.size()); - - if (!data.Points.empty()) - _worldPacket.append(data.Points.data(), data.Points.size()); - - if (!data.EstimatedPoints.empty()) - _worldPacket.append(data.EstimatedPoints.data(), data.EstimatedPoints.size()); - - _worldPacket.WriteBit(data.CastUnit.is_initialized()); - _worldPacket.WriteBit(data.Duration.is_initialized()); - _worldPacket.WriteBit(data.Remaining.is_initialized()); - - if (data.CastUnit) - _worldPacket << *data.CastUnit; - - if (data.Duration) - _worldPacket << uint32(*data.Duration); - - if (data.Remaining) - _worldPacket << uint32(*data.Remaining); - } - - _worldPacket.FlushBits(); - } return &_worldPacket; } @@ -178,10 +209,11 @@ ByteBuffer& operator>>(ByteBuffer& buffer, WorldPackets::Spells::SpellTargetData { buffer.ResetBitPos(); - targetData.Flags = buffer.ReadBits(23); - bool const hasSrcLocation = buffer.ReadBit(); - bool const hasDstLocation = buffer.ReadBit(); - bool const hasOrientation = buffer.ReadBit(); + targetData.Flags = buffer.ReadBits(25); + bool hasSrcLocation = buffer.ReadBit(); + bool hasDstLocation = buffer.ReadBit(); + bool hasOrientation = buffer.ReadBit(); + bool hasMapID = buffer.ReadBit(); uint32 nameLength = buffer.ReadBits(7); buffer >> targetData.Unit; @@ -196,6 +228,9 @@ ByteBuffer& operator>>(ByteBuffer& buffer, WorldPackets::Spells::SpellTargetData if (hasOrientation) targetData.Orientation = buffer.read<float>(); + if (hasMapID) + targetData.MapID = buffer.read<int32>(); + targetData.Name = buffer.ReadString(nameLength); return buffer; @@ -215,20 +250,17 @@ ByteBuffer& operator>>(ByteBuffer& buffer, WorldPackets::Spells::SpellCastReques buffer >> request.Misc[1]; buffer >> request.SpellID; buffer >> request.SpellXSpellVisualID; - buffer >> request.Target; buffer >> request.MissileTrajectory; buffer >> request.Charmer; - - buffer.ResetBitPos(); request.SendCastFlags = buffer.ReadBits(5); - bool const hasMoveUpdate = buffer.ReadBit(); + bool hasMoveUpdate = buffer.ReadBit(); request.Weight.resize(buffer.ReadBits(2)); + buffer >> request.Target; if (hasMoveUpdate) { - MovementInfo movementInfo; - buffer >> movementInfo; - request.MoveUpdate = movementInfo; + request.MoveUpdate = boost::in_place(); + buffer >> *request.MoveUpdate; } for (WorldPackets::Spells::SpellWeight& weight : request.Weight) @@ -261,6 +293,14 @@ void WorldPackets::Spells::UseItem::Read() _worldPacket >> Cast; } +WorldPacket const* WorldPackets::Spells::SpellPrepare::Write() +{ + _worldPacket << ClientCastID; + _worldPacket << ServerCastID; + + return &_worldPacket; +} + ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::TargetLocation const& targetLocation) { data << targetLocation.Transport; @@ -272,10 +312,11 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::TargetLocation co ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellTargetData const& spellTargetData) { - data.WriteBits(spellTargetData.Flags, 23); + data.WriteBits(spellTargetData.Flags, 25); data.WriteBit(spellTargetData.SrcLocation.is_initialized()); data.WriteBit(spellTargetData.DstLocation.is_initialized()); data.WriteBit(spellTargetData.Orientation.is_initialized()); + data.WriteBit(spellTargetData.MapID.is_initialized()); data.WriteBits(spellTargetData.Name.size(), 7); data.FlushBits(); @@ -291,6 +332,9 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellTargetData c if (spellTargetData.Orientation) data << *spellTargetData.Orientation; + if (spellTargetData.MapID) + data << *spellTargetData.MapID; + data.WriteString(spellTargetData.Name); return data; @@ -299,8 +343,10 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellTargetData c ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellMissStatus const& spellMissStatus) { data.WriteBits(spellMissStatus.Reason, 4); - data.WriteBits(spellMissStatus.ReflectStatus, 4); - // No need to flush bits as we written exactly 8 bits (1 byte) + if (spellMissStatus.Reason == SPELL_MISS_REFLECT) + data.WriteBits(spellMissStatus.ReflectStatus, 4); + + data.FlushBits(); return data; } @@ -315,12 +361,9 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::RuneData const& r { data << uint8(runeData.Start); data << uint8(runeData.Count); - - data.WriteBits(runeData.Cooldowns.size(), 3); - data.FlushBits(); - - for (uint8 cd : runeData.Cooldowns) - data << cd; + data << uint32(runeData.Cooldowns.size()); + if (!runeData.Cooldowns.empty()) + data.append(runeData.Cooldowns.data(), runeData.Cooldowns.size()); return data; } @@ -359,21 +402,29 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastData con data << spellCastData.CasterGUID; data << spellCastData.CasterUnit; data << spellCastData.CastID; + data << spellCastData.OriginalCastID; data << int32(spellCastData.SpellID); data << uint32(spellCastData.SpellXSpellVisualID); data << uint32(spellCastData.CastFlags); data << uint32(spellCastData.CastTime); - data << uint32(spellCastData.HitTargets.size()); - data << uint32(spellCastData.MissTargets.size()); - data << uint32(spellCastData.MissStatus.size()); - data << spellCastData.Target; - data << uint32(spellCastData.RemainingPower.size()); data << spellCastData.MissileTrajectory; - data << spellCastData.Ammo; + data << int32(spellCastData.Ammo.DisplayID); data << uint8(spellCastData.DestLocSpellCastIndex); - data << uint32(spellCastData.TargetPoints.size()); data << spellCastData.Immunities; data << spellCastData.Predict; + data.WriteBits(spellCastData.CastFlagsEx, 22); + data.WriteBits(spellCastData.HitTargets.size(), 16); + data.WriteBits(spellCastData.MissTargets.size(), 16); + data.WriteBits(spellCastData.MissStatus.size(), 16); + data.WriteBits(spellCastData.RemainingPower.size(), 9); + data.WriteBit(spellCastData.RemainingRunes.is_initialized()); + data.WriteBits(spellCastData.TargetPoints.size(), 16); + data.FlushBits(); + + for (WorldPackets::Spells::SpellMissStatus const& status : spellCastData.MissStatus) + data << status; + + data << spellCastData.Target; for (ObjectGuid const& target : spellCastData.HitTargets) data << target; @@ -381,22 +432,15 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastData con for (ObjectGuid const& target : spellCastData.MissTargets) data << target; - for (WorldPackets::Spells::SpellMissStatus const& status : spellCastData.MissStatus) - data << status; - for (WorldPackets::Spells::SpellPowerData const& power : spellCastData.RemainingPower) data << power; - for (WorldPackets::Spells::TargetLocation const& targetLoc : spellCastData.TargetPoints) - data << targetLoc; - - data.WriteBits(spellCastData.CastFlagsEx, 20); - data.WriteBit(spellCastData.RemainingRunes.is_initialized()); - data.FlushBits(); - if (spellCastData.RemainingRunes) data << *spellCastData.RemainingRunes; + for (WorldPackets::Spells::TargetLocation const& targetLoc : spellCastData.TargetPoints) + data << targetLoc; + return data; } @@ -423,9 +467,13 @@ WorldPacket const* WorldPackets::Spells::SpellGo::Write() WorldPacket const* WorldPackets::Spells::LearnedSpells::Write() { _worldPacket << uint32(SpellID.size()); + _worldPacket << uint32(FavoriteSpellID.size()); for (int32 spell : SpellID) _worldPacket << spell; + for (int32 spell : FavoriteSpellID) + _worldPacket << spell; + _worldPacket.WriteBit(SuppressMessaging); _worldPacket.FlushBits(); @@ -448,6 +496,7 @@ WorldPacket const* WorldPackets::Spells::SpellFailedOther::Write() _worldPacket << CasterUnit; _worldPacket << CastID; _worldPacket << uint32(SpellID); + _worldPacket << uint32(SpelXSpellVisualID); _worldPacket << uint8(Reason); return &_worldPacket; @@ -465,6 +514,17 @@ WorldPacket const* WorldPackets::Spells::CastFailed::Write() return &_worldPacket; } +WorldPacket const* WorldPackets::Spells::PetCastFailed::Write() +{ + _worldPacket << CastID; + _worldPacket << int32(SpellID); + _worldPacket << int32(Reason); + _worldPacket << int32(FailedArg1); + _worldPacket << int32(FailedArg2); + + return &_worldPacket; +} + ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellModifierData const& spellModifierData) { data << float(spellModifierData.ModifierValue); @@ -670,8 +730,8 @@ WorldPacket const* WorldPackets::Spells::PlaySpellVisualKit::Write() void WorldPackets::Spells::CancelCast::Read() { - _worldPacket >> SpellID; _worldPacket >> CastID; + _worldPacket >> SpellID; } void WorldPackets::Spells::OpenItem::Read() @@ -722,15 +782,12 @@ WorldPacket const* WorldPackets::Spells::SpellChannelUpdate::Write() WorldPacket const* WorldPackets::Spells::ResurrectRequest::Write() { _worldPacket << ResurrectOffererGUID; - _worldPacket << ResurrectOffererVirtualRealmAddress; - - _worldPacket << PetNumber; - _worldPacket << SpellID; - + _worldPacket << uint32(ResurrectOffererVirtualRealmAddress); + _worldPacket << uint32(PetNumber); + _worldPacket << int32(SpellID); _worldPacket.WriteBits(Name.length(), 6); _worldPacket.WriteBit(UseTimer); _worldPacket.WriteBit(Sickness); - _worldPacket.FlushBits(); _worldPacket.WriteString(Name); @@ -752,21 +809,21 @@ void WorldPackets::Spells::GetMirrorImageData::Read() WorldPacket const* WorldPackets::Spells::MirrorImageComponentedData::Write() { _worldPacket << UnitGUID; - _worldPacket << DisplayID; - _worldPacket << RaceID; - _worldPacket << Gender; - _worldPacket << ClassID; - _worldPacket << SkinColor; - _worldPacket << FaceVariation; - _worldPacket << HairVariation; - _worldPacket << HairColor; - _worldPacket << BeardVariation; + _worldPacket << int32(DisplayID); + _worldPacket << uint8(RaceID); + _worldPacket << uint8(Gender); + _worldPacket << uint8(ClassID); + _worldPacket << uint8(SkinColor); + _worldPacket << uint8(FaceVariation); + _worldPacket << uint8(HairVariation); + _worldPacket << uint8(HairColor); + _worldPacket << uint8(BeardVariation); + _worldPacket.append(CustomDisplay.data(), CustomDisplay.size()); _worldPacket << GuildGUID; - _worldPacket << uint32(ItemDisplayID.size()); - for (auto const& itemDisplayId : ItemDisplayID) - _worldPacket << itemDisplayId; + for (int32 itemDisplayId : ItemDisplayID) + _worldPacket << int32(itemDisplayId); return &_worldPacket; } @@ -774,7 +831,7 @@ WorldPacket const* WorldPackets::Spells::MirrorImageComponentedData::Write() WorldPacket const* WorldPackets::Spells::MirrorImageCreatureData::Write() { _worldPacket << UnitGUID; - _worldPacket << DisplayID; + _worldPacket << int32(DisplayID); return &_worldPacket; } @@ -787,9 +844,7 @@ void WorldPackets::Spells::SpellClick::Read() WorldPacket const* WorldPackets::Spells::ResyncRunes::Write() { - _worldPacket << uint32(Runes.size()); - if (!Runes.empty()) - _worldPacket.append(Runes.data(), Runes.size()); + _worldPacket << Runes; return &_worldPacket; } @@ -825,9 +880,8 @@ void WorldPackets::Spells::UpdateMissileTrajectory::Read() _worldPacket.ResetBitPos(); if (hasStatus) { - MovementInfo info; - _worldPacket >> info; - Status = info; + Status = boost::in_place(); + _worldPacket >> *Status; } } diff --git a/src/server/game/Server/Packets/SpellPackets.h b/src/server/game/Server/Packets/SpellPackets.h index 8e9835f4009..901ebdd6b87 100644 --- a/src/server/game/Server/Packets/SpellPackets.h +++ b/src/server/game/Server/Packets/SpellPackets.h @@ -174,7 +174,7 @@ namespace WorldPackets struct SpellCastLogData { - int32 Health = 0; + int64 Health = 0; int32 AttackPower = 0; int32 SpellPower = 0; std::vector<SpellLogPowerData> PowerData; @@ -182,10 +182,23 @@ namespace WorldPackets void Initialize(Unit const* unit); }; + struct SandboxScalingData + { + uint32 Type = 0; + int16 PlayerLevelDelta = 0; + uint8 TargetLevel = 0; + uint8 Expansion = 0; + uint8 Class = 1; + uint8 TargetMinScalingLevel = 1; + uint8 TargetMaxScalingLevel = 1; + int8 TargetScalingLevelDelta = 1; + }; + struct AuraDataInfo { + ObjectGuid CastID; int32 SpellID = 0; - uint32 SpellXSpellVisualID = 0; + int32 SpellXSpellVisualID = 0; uint8 Flags = 0; uint32 ActiveFlags = 0; uint16 CastLevel = 1; @@ -193,8 +206,10 @@ namespace WorldPackets Optional<ObjectGuid> CastUnit; Optional<int32> Duration; Optional<int32> Remaining; + Optional<float> TimeMod; std::vector<float> Points; std::vector<float> EstimatedPoints; + Optional<SandboxScalingData> SandboxScaling; }; struct AuraInfo @@ -229,6 +244,7 @@ namespace WorldPackets Optional<TargetLocation> SrcLocation; Optional<TargetLocation> DstLocation; Optional<float> Orientation; + Optional<int32> MapID; std::string Name; }; @@ -293,6 +309,17 @@ namespace WorldPackets SpellCastRequest Cast; }; + class SpellPrepare final : public ServerPacket + { + public: + SpellPrepare() : ServerPacket(SMSG_SPELL_PREPARE, 16 + 16) { } + + WorldPacket const* Write() override; + + ObjectGuid ClientCastID; + ObjectGuid ServerCastID; + }; + struct SpellMissStatus { uint8 Reason = 0; @@ -342,6 +369,7 @@ namespace WorldPackets ObjectGuid CasterGUID; ObjectGuid CasterUnit; ObjectGuid CastID; + ObjectGuid OriginalCastID; int32 SpellID = 0; uint32 SpellXSpellVisualID = 0; uint32 CastFlags = 0; @@ -390,6 +418,7 @@ namespace WorldPackets WorldPacket const* Write() override; std::vector<int32> SpellID; + std::vector<int32> FavoriteSpellID; bool SuppressMessaging = false; }; @@ -416,6 +445,7 @@ namespace WorldPackets ObjectGuid CasterUnit; uint32 SpellID = 0; + uint32 SpelXSpellVisualID = 0; uint8 Reason = 0; ObjectGuid CastID; }; @@ -423,16 +453,30 @@ namespace WorldPackets class TC_GAME_API CastFailed final : public ServerPacket { public: - CastFailed(OpcodeServer opcode) : ServerPacket(opcode, 4+4+4+4+1) { } + CastFailed() : ServerPacket(SMSG_CAST_FAILED, 4 + 4 + 4 + 4 + 1) { } WorldPacket const* Write() override; ObjectGuid CastID; - int32 Reason = 0; + int32 SpellID = 0; int32 SpellXSpellVisualID = 0; + int32 Reason = 0; int32 FailedArg1 = -1; int32 FailedArg2 = -1; - int32 SpellID = 0; + }; + + class TC_GAME_API PetCastFailed final : public ServerPacket + { + public: + PetCastFailed() : ServerPacket(SMSG_PET_CAST_FAILED, 4 + 4 + 4 + 1) { } + + WorldPacket const* Write() override; + + ObjectGuid CastID; + int32 SpellID = 0; + int32 Reason = 0; + int32 FailedArg1 = -1; + int32 FailedArg2 = -1; }; struct SpellModifierData @@ -765,7 +809,7 @@ namespace WorldPackets WorldPacket const* Write() override; ObjectGuid UnitGUID; - uint32 DisplayID = 0; + int32 DisplayID = 0; uint8 RaceID = 0; uint8 Gender = 0; uint8 ClassID = 0; @@ -774,9 +818,10 @@ namespace WorldPackets uint8 HairVariation = 0; uint8 HairColor = 0; uint8 BeardVariation = 0; + std::array<uint8, PLAYER_CUSTOM_DISPLAY_SIZE> CustomDisplay; ObjectGuid GuildGUID; - std::vector<uint32> ItemDisplayID; + std::vector<int32> ItemDisplayID; }; class MirrorImageCreatureData final : public ServerPacket @@ -787,7 +832,7 @@ namespace WorldPackets WorldPacket const* Write() override; ObjectGuid UnitGUID; - uint32 DisplayID = 0; + int32 DisplayID = 0; }; class SpellClick final : public ClientPacket @@ -804,11 +849,11 @@ namespace WorldPackets class ResyncRunes final : public ServerPacket { public: - ResyncRunes(size_t size) : ServerPacket(SMSG_RESYNC_RUNES, 4 + 2 * size) { } + ResyncRunes(size_t size) : ServerPacket(SMSG_RESYNC_RUNES, 1 + 1 + 4 + size) { } WorldPacket const* Write() override; - std::vector<uint8> Runes; + RuneData Runes; }; class MissileTrajectoryCollision final : public ClientPacket diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 0cf2a510660..d04bda1a0d9 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -211,7 +211,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_CALENDAR_UPDATE_EVENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Calendar::CalendarUpdateEvent, &WorldSession::HandleCalendarUpdateEvent); DEFINE_HANDLER(CMSG_CANCEL_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::CancelAura, &WorldSession::HandleCancelAuraOpcode); DEFINE_HANDLER(CMSG_CANCEL_AUTO_REPEAT_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::CancelAutoRepeatSpell, &WorldSession::HandleCancelAutoRepeatSpellOpcode); - DEFINE_HANDLER(CMSG_CANCEL_CAST, STATUS_UNHANDLED, PROCESS_THREADSAFE, WorldPackets::Spells::CancelCast, &WorldSession::HandleCancelCastOpcode); + DEFINE_HANDLER(CMSG_CANCEL_CAST, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Spells::CancelCast, &WorldSession::HandleCancelCastOpcode); DEFINE_HANDLER(CMSG_CANCEL_CHANNELLING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::CancelChannelling, &WorldSession::HandleCancelChanneling); DEFINE_HANDLER(CMSG_CANCEL_GROWTH_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::CancelGrowthAura, &WorldSession::HandleCancelGrowthAuraOpcode); DEFINE_HANDLER(CMSG_CANCEL_MASTER_LOOT_ROLL, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); @@ -221,7 +221,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_CANCEL_TEMP_ENCHANTMENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::CancelTempEnchantment, &WorldSession::HandleCancelTempEnchantmentOpcode); DEFINE_HANDLER(CMSG_CANCEL_TRADE, STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, WorldPackets::Trade::CancelTrade, &WorldSession::HandleCancelTradeOpcode); DEFINE_HANDLER(CMSG_CAN_DUEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Duel::CanDuel, &WorldSession::HandleCanDuel); - DEFINE_HANDLER(CMSG_CAST_SPELL, STATUS_UNHANDLED, PROCESS_THREADSAFE, WorldPackets::Spells::CastSpell, &WorldSession::HandleCastSpellOpcode); + DEFINE_HANDLER(CMSG_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Spells::CastSpell, &WorldSession::HandleCastSpellOpcode); DEFINE_HANDLER(CMSG_CHALLENGE_MODE_REQUEST_LEADERS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_CHALLENGE_MODE_REQUEST_MAP_STATS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_CHANGE_BAG_SLOT_FLAG, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); @@ -473,7 +473,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_MAIL_TAKE_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailTakeMoney, &WorldSession::HandleMailTakeMoney); DEFINE_OPCODE_HANDLER_OLD(CMSG_MASTER_LOOT_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLootMasterGiveOpcode ); DEFINE_HANDLER(CMSG_MINIMAP_PING, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::MinimapPingClient, &WorldSession::HandleMinimapPingOpcode); - DEFINE_HANDLER(CMSG_MISSILE_TRAJECTORY_COLLISION, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Spells::MissileTrajectoryCollision, &WorldSession::HandleMissileTrajectoryCollision); + DEFINE_HANDLER(CMSG_MISSILE_TRAJECTORY_COLLISION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::MissileTrajectoryCollision, &WorldSession::HandleMissileTrajectoryCollision); DEFINE_HANDLER(CMSG_MOUNT_SET_FAVORITE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_MOUNT_SPECIAL_ANIM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::MountSpecial, &WorldSession::HandleMountSpecialAnimOpcode); DEFINE_HANDLER(CMSG_MOVE_APPLY_MOVEMENT_FORCE_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); @@ -568,7 +568,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_PET_BATTLE_REQUEST_WILD, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_PET_BATTLE_SCRIPT_ERROR_NOTIFY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_PET_CANCEL_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::PetCancelAura, &WorldSession::HandlePetCancelAuraOpcode); - DEFINE_HANDLER(CMSG_PET_CAST_SPELL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Spells::PetCastSpell, &WorldSession::HandlePetCastSpellOpcode); + DEFINE_HANDLER(CMSG_PET_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::PetCastSpell, &WorldSession::HandlePetCastSpellOpcode); DEFINE_HANDLER(CMSG_PET_RENAME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Pet::PetRename, &WorldSession::HandlePetRename); DEFINE_HANDLER(CMSG_PET_SET_ACTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Pet::PetSetAction, &WorldSession::HandlePetSetAction ); DEFINE_HANDLER(CMSG_PET_SPELL_AUTOCAST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Pet::PetSpellAutocast, &WorldSession::HandlePetSpellAutocastOpcode); @@ -763,7 +763,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_UNLOCK_VOID_STORAGE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::VoidStorage::UnlockVoidStorage, &WorldSession::HandleVoidStorageUnlock); DEFINE_HANDLER(CMSG_UPDATE_ACCOUNT_DATA, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::ClientConfig::UserClientUpdateAccountData, &WorldSession::HandleUpdateAccountData); DEFINE_HANDLER(CMSG_UPDATE_CLIENT_SETTINGS, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_UPDATE_MISSILE_TRAJECTORY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Spells::UpdateMissileTrajectory, &WorldSession::HandleUpdateMissileTrajectory); + DEFINE_HANDLER(CMSG_UPDATE_MISSILE_TRAJECTORY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::UpdateMissileTrajectory, &WorldSession::HandleUpdateMissileTrajectory); DEFINE_HANDLER(CMSG_UPDATE_RAID_TARGET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::UpdateRaidTarget, &WorldSession::HandleUpdateRaidTargetOpcode); DEFINE_HANDLER(CMSG_UPDATE_VAS_PURCHASE_STATES, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_UPDATE_WOW_TOKEN_AUCTIONABLE_LIST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Token::UpdateListedAuctionableTokens, &WorldSession::HandleUpdateListedAuctionableTokens); @@ -773,8 +773,8 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_USED_FOLLOW, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_USE_CRITTER_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::UseCritterItem, &WorldSession::HandleUseCritterItem); DEFINE_HANDLER(CMSG_USE_EQUIPMENT_SET, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::EquipmentSet::UseEquipmentSet, &WorldSession::HandleUseEquipmentSet); - DEFINE_HANDLER(CMSG_USE_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Spells::UseItem, &WorldSession::HandleUseItemOpcode); - DEFINE_HANDLER(CMSG_USE_TOY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Toy::UseToy, &WorldSession::HandleUseToy); + DEFINE_HANDLER(CMSG_USE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::UseItem, &WorldSession::HandleUseItemOpcode); + DEFINE_HANDLER(CMSG_USE_TOY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Toy::UseToy, &WorldSession::HandleUseToy); DEFINE_HANDLER(CMSG_VIOLENCE_LEVEL, STATUS_AUTHED, PROCESS_INPLACE, WorldPackets::Misc::ViolenceLevel, &WorldSession::HandleViolenceLevel); DEFINE_HANDLER(CMSG_VOICE_ADD_IGNORE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_VOICE_DEL_IGNORE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); @@ -844,7 +844,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_REPLICATE_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_WON_NOTIFICATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AURA_POINTS_DEPLETED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_AURA_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_AURA_UPDATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUTH_CHALLENGE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUTH_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AVAILABLE_VOICE_CHANNEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -941,12 +941,12 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_CAMERA_SHAKE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_AUTO_REPEAT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_COMBAT, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_ORPHAN_SPELL_VISUAL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_ORPHAN_SPELL_VISUAL, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_SCENE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_SPELL_VISUAL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_SPELL_VISUAL, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_SPELL_VISUAL_KIT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CAN_DUEL_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CAST_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CAST_FAILED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CATEGORY_COOLDOWN, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHALLEGE_MODE_REWARDS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHALLENGE_MODE_ALL_MAP_STATS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1233,7 +1233,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_PUSH_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_TIME_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_KICK_REASON, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARNED_SPELLS, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARNED_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARN_PVP_TALENT_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARN_TALENT_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEVEL_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1299,7 +1299,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_MASTER_LOOT_CANDIDATE_LIST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MESSAGE_BOX, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MINIMAP_PING, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_MIRROR_IMAGE_COMPONENTED_DATA, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_MIRROR_IMAGE_COMPONENTED_DATA, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MIRROR_IMAGE_CREATURE_DATA, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MISSILE_CANCEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MODIFY_COOLDOWN, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); @@ -1390,7 +1390,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEW_TAXI_PATH, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEW_WORLD, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_DEST_LOC_SPELL_CAST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_MISSILE_TRAJECTORY_COLLISION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_MISSILE_TRAJECTORY_COLLISION, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_MONEY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_RECEIVED_MAIL, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_OFFER_PETITION_ERROR, STATUS_NEVER, CONNECTION_TYPE_REALM); @@ -1432,7 +1432,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_BATTLE_REQUEST_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_BATTLE_ROUND_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_BATTLE_SLOT_UPDATES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_CAST_FAILED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_CAST_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_CLEAR_SPELLS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_DISMISS_SOUND, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_GOD_MODE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1548,7 +1548,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_COMMS, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_TOKEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESURRECT_REQUEST, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESYNC_RUNES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESYNC_RUNES, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHANGED_INFORM, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHOSEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_POLL_INFORM, STATUS_NEVER, CONNECTION_TYPE_REALM); @@ -1626,10 +1626,10 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_DELAYED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_DISPELL_LOG, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_ENERGIZE_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_EXECUTE_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILED_OTHER, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILURE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_GO, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_EXECUTE_LOG, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILED_OTHER, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILURE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_GO, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_HEAL_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_INSTAKILL_LOG, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_INTERRUPT_LOG, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); @@ -1637,7 +1637,8 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_NON_MELEE_DAMAGE_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_OR_DAMAGE_IMMUNE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_PERIODIC_AURA_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_START, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_PREPARE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_START, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_UPDATE_CHAIN_TARGETS, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPIRIT_HEALER_CONFIRM, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_STAND_STATE_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index 9a15ca951e2..571a1473aa1 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -1575,6 +1575,7 @@ enum OpcodeServer : uint32 SMSG_SPELL_NON_MELEE_DAMAGE_LOG = 0x2C31, SMSG_SPELL_OR_DAMAGE_IMMUNE = 0x2C2E, SMSG_SPELL_PERIODIC_AURA_LOG = 0x2C1B, + SMSG_SPELL_PREPARE = 0x2C38, SMSG_SPELL_START = 0x2C3A, SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x2C33, SMSG_SPIRIT_HEALER_CONFIRM = 0x2750, diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index af22d2fa496..ec060f253b9 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -198,9 +198,12 @@ void AuraApplication::BuildUpdatePacket(WorldPackets::Spells::AuraInfo& auraInfo if (remove) return; + auraInfo.AuraData = boost::in_place(); + Aura const* aura = GetBase(); - WorldPackets::Spells::AuraDataInfo auraData; + WorldPackets::Spells::AuraDataInfo& auraData = auraInfo.AuraData.get(); + auraData.CastID = aura->GetCastGUID(); auraData.SpellID = aura->GetId(); auraData.SpellXSpellVisualID = aura->GetSpellInfo()->GetSpellXSpellVisualId(_target->GetMap()->GetDifficultyID()); auraData.Flags = GetFlags(); @@ -232,8 +235,6 @@ void AuraApplication::BuildUpdatePacket(WorldPackets::Spells::AuraInfo& auraInfo if (effect && HasEffect(effect->GetEffIndex())) // Not all of aura's effects have to be applied on every target auraData.Points[effect->GetEffIndex()] = float(effect->GetAmount()); } - - auraInfo.AuraData = auraData; } void AuraApplication::ClientUpdate(bool remove) @@ -279,7 +280,7 @@ uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 avalibl return effMask & avalibleEffectMask; } -Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool* refresh /*= NULL*/, int32 castItemLevel /*= -1*/) +Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool* refresh /*= NULL*/, int32 castItemLevel /*= -1*/) { ASSERT(spellproto); ASSERT(owner); @@ -303,10 +304,10 @@ Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, uint32 tryEffMa return foundAura; } else - return Create(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemLevel); + return Create(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemLevel); } -Aura* Aura::TryCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, int32 castItemLevel /*= -1*/) +Aura* Aura::TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, int32 castItemLevel /*= -1*/) { ASSERT(spellproto); ASSERT(owner); @@ -315,10 +316,10 @@ Aura* Aura::TryCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObjec uint32 effMask = Aura::BuildEffectMaskForOwner(spellproto, tryEffMask, owner); if (!effMask) return NULL; - return Create(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemLevel); + return Create(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemLevel); } -Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel) +Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel) { ASSERT(effMask); ASSERT(spellproto); @@ -348,10 +349,10 @@ Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* own { case TYPEID_UNIT: case TYPEID_PLAYER: - aura = new UnitAura(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemLevel); + aura = new UnitAura(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemLevel); break; case TYPEID_DYNAMICOBJECT: - aura = new DynObjAura(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemLevel); + aura = new DynObjAura(spellproto, castId, effMask, owner, caster, baseAmount, castItem, casterGUID, castItemLevel); break; default: ABORT(); @@ -363,8 +364,8 @@ Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* own return aura; } -Aura::Aura(SpellInfo const* spellproto, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel) : -m_spellInfo(spellproto), m_casterGuid(!casterGUID.IsEmpty() ? casterGUID : caster->GetGUID()), +Aura::Aura(SpellInfo const* spellproto, ObjectGuid castId, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel) : +m_spellInfo(spellproto), m_castGuid(castId), m_casterGuid(!casterGUID.IsEmpty() ? casterGUID : caster->GetGUID()), m_castItemGuid(castItem ? castItem->GetGUID() : ObjectGuid::Empty), m_castItemLevel(castItemLevel), m_applyTime(time(NULL)), m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0), m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1), @@ -2320,8 +2321,8 @@ void Aura::CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraAppli } } -UnitAura::UnitAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel) - : Aura(spellproto, owner, caster, castItem, casterGUID, castItemLevel) +UnitAura::UnitAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel) + : Aura(spellproto, castId, owner, caster, castItem, casterGUID, castItemLevel) { m_AuraDRGroup = DIMINISHING_NONE; LoadScripts(); @@ -2423,8 +2424,8 @@ void UnitAura::FillTargetMap(std::map<Unit*, uint32> & targets, Unit* caster) } } -DynObjAura::DynObjAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel) - : Aura(spellproto, owner, caster, castItem, casterGUID, castItemLevel) +DynObjAura::DynObjAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel) + : Aura(spellproto, castId, owner, caster, castItem, casterGUID, castItemLevel) { LoadScripts(); ASSERT(GetDynobjOwner()); diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 27e2333bd97..253b07768f0 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -120,19 +120,20 @@ class TC_GAME_API Aura typedef std::map<ObjectGuid, AuraApplication*> ApplicationMap; static uint32 BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 avalibleEffectMask, WorldObject* owner); - static Aura* TryRefreshStackOrCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount = NULL, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty, bool* refresh = NULL, int32 castItemLevel = -1); - static Aura* TryCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty, int32 castItemLevel = -1); - static Aura* Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); - Aura(SpellInfo const* spellproto, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); + static Aura* TryRefreshStackOrCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount = NULL, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty, bool* refresh = NULL, int32 castItemLevel = -1); + static Aura* TryCreate(SpellInfo const* spellproto, ObjectGuid castId, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty, int32 castItemLevel = -1); + static Aura* Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); + Aura(SpellInfo const* spellproto, ObjectGuid castId, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); void _InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount); virtual ~Aura(); SpellInfo const* GetSpellInfo() const { return m_spellInfo; } uint32 GetId() const{ return GetSpellInfo()->Id; } + ObjectGuid GetCastGUID() const { return m_castGuid; } + ObjectGuid GetCasterGUID() const { return m_casterGuid; } ObjectGuid GetCastItemGUID() const { return m_castItemGuid; } int32 GetCastItemLevel() const { return m_castItemLevel; } - ObjectGuid GetCasterGUID() const { return m_casterGuid; } Unit* GetCaster() const; WorldObject* GetOwner() const { return m_owner; } Unit* GetUnitOwner() const { ASSERT(GetType() == UNIT_AURA_TYPE); return (Unit*)m_owner; } @@ -297,6 +298,7 @@ class TC_GAME_API Aura void _DeleteRemovedApplications(); protected: SpellInfo const* const m_spellInfo; + ObjectGuid const m_castGuid; ObjectGuid const m_casterGuid; ObjectGuid const m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted int32 m_castItemLevel; @@ -334,9 +336,9 @@ class TC_GAME_API Aura class TC_GAME_API UnitAura : public Aura { - friend Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); + friend Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); public: - UnitAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); + UnitAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); void _ApplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp) override; void _UnapplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp) override; @@ -355,9 +357,9 @@ class TC_GAME_API UnitAura : public Aura class TC_GAME_API DynObjAura : public Aura { - friend Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); + friend Aura* Aura::Create(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); public: - DynObjAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); + DynObjAura(SpellInfo const* spellproto, ObjectGuid castId, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID, int32 castItemLevel); void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) override; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 84cfabf4e8f..c0746016ff1 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -589,7 +589,7 @@ m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)), m_procVictim = 0; m_procEx = 0; focusObject = NULL; - m_cast_count = ObjectGuid::Empty; + m_castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, m_caster->GetMapId(), m_spellInfo->Id, m_caster->GetMap()->GenerateLowGuid<HighGuid::Cast>()); memset(m_misc.Raw.Data, 0, sizeof(m_misc.Raw.Data)); m_SpellVisual = m_spellInfo->GetSpellXSpellVisualId(caster->GetMap()->GetDifficultyID()); m_preCastSpell = 0; @@ -616,7 +616,6 @@ m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)), && !m_spellInfo->IsPassive() && !m_spellInfo->IsPositive(); CleanupTargetList(); - CleanupExecuteLogList(); for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) m_destTargets[i] = SpellDestination(*m_caster); @@ -645,7 +644,6 @@ Spell::~Spell() ASSERT(m_caster->ToPlayer()->m_spellModTakingSpell != this); delete m_spellValue; - CleanupExecuteLogList(); } void Spell::InitExplicitTargets(SpellCastTargets const& targets) @@ -2619,7 +2617,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA if (m_originalCaster) { bool refresh = false; - m_spellAura = Aura::TryRefreshStackOrCreate(aurSpellInfo, effectMask, unit, + m_spellAura = Aura::TryRefreshStackOrCreate(aurSpellInfo, m_castId, effectMask, unit, m_originalCaster, (aurSpellInfo == m_spellInfo) ? m_spellValue->EffectBasePoints : basePoints, m_CastItem, ObjectGuid::Empty, &refresh, m_castItemLevel); if (m_spellAura) @@ -2925,7 +2923,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered m_caster->m_Events.AddEvent(Event, m_caster->m_Events.CalculateTime(1)); //Prevent casting at cast another spell (ServerSide check) - if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_IN_PROGRESS) && m_caster->IsNonMeleeSpellCast(false, true, true) && !m_cast_count.IsEmpty()) + if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_IN_PROGRESS) && m_caster->IsNonMeleeSpellCast(false, true, true) && !m_castId.IsEmpty()) { SendCastResult(SPELL_FAILED_SPELL_IN_PROGRESS); finish(false); @@ -3716,39 +3714,10 @@ void Spell::finish(bool ok) m_caster->AttackStop(); } -void Spell::SendCastResult(SpellCastResult result) -{ - if (result == SPELL_CAST_OK) - return; - - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return; - - if (m_caster->ToPlayer()->GetSession()->PlayerLoading()) // don't send cast results at loading time - return; - - SendCastResult(m_caster->ToPlayer(), m_spellInfo, m_cast_count, result, m_customError, SMSG_CAST_FAILED, m_misc.Raw.Data); -} - -void Spell::SendPetCastResult(SpellCastResult result) +template<class T> +inline void FillSpellCastFailedArgs(T& packet, ObjectGuid castId, SpellInfo const* spellInfo, SpellCastResult result, SpellCustomErrors customError, uint32* misc, Player* caster) { - if (result == SPELL_CAST_OK) - return; - - Unit* owner = m_caster->GetCharmerOrOwner(); - if (!owner || owner->GetTypeId() != TYPEID_PLAYER) - return; - - SendCastResult(owner->ToPlayer(), m_spellInfo, m_cast_count, result, SPELL_CUSTOM_ERROR_NONE, SMSG_PET_CAST_FAILED, m_misc.Raw.Data); -} - -void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, ObjectGuid cast_count, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/, OpcodeServer opcode /*= SMSG_CAST_FAILED*/, uint32* misc /*= nullptr*/) -{ - if (result == SPELL_CAST_OK) - return; - - WorldPackets::Spells::CastFailed packet(opcode); - packet.CastID = cast_count; + packet.CastID = castId; packet.SpellID = spellInfo->Id; packet.Reason = result; @@ -3864,7 +3833,47 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, ObjectGui default: break; } +} + +void Spell::SendCastResult(SpellCastResult result) +{ + if (result == SPELL_CAST_OK) + return; + if (m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + if (m_caster->ToPlayer()->GetSession()->PlayerLoading()) // don't send cast results at loading time + return; + + WorldPackets::Spells::CastFailed castFailed; + castFailed.SpellXSpellVisualID = m_SpellVisual; + FillSpellCastFailedArgs(castFailed, m_castId, m_spellInfo, result, m_customError, m_misc.Raw.Data, m_caster->ToPlayer()); + m_caster->ToPlayer()->SendDirectMessage(castFailed.Write()); +} + +void Spell::SendPetCastResult(SpellCastResult result) +{ + if (result == SPELL_CAST_OK) + return; + + Unit* owner = m_caster->GetCharmerOrOwner(); + if (!owner || owner->GetTypeId() != TYPEID_PLAYER) + return; + + WorldPackets::Spells::PetCastFailed petCastFailed; + FillSpellCastFailedArgs(petCastFailed, m_castId, m_spellInfo, result, SPELL_CUSTOM_ERROR_NONE, m_misc.Raw.Data, owner->ToPlayer()); + owner->ToPlayer()->SendDirectMessage(petCastFailed.Write()); +} + +void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint32 spellVisual, ObjectGuid cast_count, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/, uint32* misc /*= nullptr*/) +{ + if (result == SPELL_CAST_OK) + return; + + WorldPackets::Spells::CastFailed packet; + packet.SpellXSpellVisualID = spellVisual; + FillSpellCastFailedArgs(packet, cast_count, spellInfo, result, customError, misc, caster); caster->GetSession()->SendPacket(packet.Write()); } @@ -3904,7 +3913,8 @@ void Spell::SendSpellStart() castData.CasterGUID = m_caster->GetGUID(); castData.CasterUnit = m_caster->GetGUID(); - castData.CastID = m_cast_count; // pending spell cast? + castData.CastID = m_castId; + castData.OriginalCastID = m_originalCastId; castData.SpellID = m_spellInfo->Id; castData.SpellXSpellVisualID = m_SpellVisual; castData.CastFlags = castFlags; @@ -4019,7 +4029,8 @@ void Spell::SendSpellGo() castData.CasterGUID = m_caster->GetGUID(); castData.CasterUnit = m_caster->GetGUID(); - castData.CastID = m_cast_count; // pending spell cast? + castData.CastID = m_castId; + castData.OriginalCastID = m_originalCastId; castData.SpellID = m_spellInfo->Id; castData.SpellXSpellVisualID = m_SpellVisual; castData.CastFlags = castFlags; @@ -4180,41 +4191,30 @@ void Spell::SendSpellExecuteLog() spellExecuteLog.Caster = m_caster->GetGUID(); spellExecuteLog.SpellID = m_spellInfo->Id; - if (_powerDrainTargets->empty() && _extraAttacksTargets->empty() && - _durabilityDamageTargets->empty() && _genericVictimTargets->empty() && - _tradeSkillTargets->empty() && _feedPetTargets->empty()) - return; - for (SpellEffectInfo const* effect : GetEffects()) { WorldPackets::CombatLog::SpellExecuteLog::SpellLogEffect spellLogEffect; if (!effect) continue; - spellLogEffect.Effect = effect->Effect; - - for (SpellLogEffectPowerDrainParams const& powerDrainParam : _powerDrainTargets[effect->EffectIndex]) - spellLogEffect.PowerDrainTargets.push_back(powerDrainParam); - - for (SpellLogEffectExtraAttacksParams const& extraAttacksTarget : _extraAttacksTargets[effect->EffectIndex]) - spellLogEffect.ExtraAttacksTargets.push_back(extraAttacksTarget); - - for (SpellLogEffectDurabilityDamageParams const& durabilityDamageTarget : _durabilityDamageTargets[effect->EffectIndex]) - spellLogEffect.DurabilityDamageTargets.push_back(durabilityDamageTarget); - - for (SpellLogEffectGenericVictimParams const& genericVictimTarget : _genericVictimTargets[effect->EffectIndex]) - spellLogEffect.GenericVictimTargets.push_back(genericVictimTarget); - - for (SpellLogEffectTradeSkillItemParams const& tradeSkillTarget : _tradeSkillTargets[effect->EffectIndex]) - spellLogEffect.TradeSkillTargets.push_back(tradeSkillTarget); + if (_powerDrainTargets[effect->EffectIndex].empty() && _extraAttacksTargets[effect->EffectIndex].empty() && + _durabilityDamageTargets[effect->EffectIndex].empty() && _genericVictimTargets[effect->EffectIndex].empty() && + _tradeSkillTargets[effect->EffectIndex].empty() && _feedPetTargets[effect->EffectIndex].empty()) + continue; - for (SpellLogEffectFeedPetParams const& feedPetTarget : _feedPetTargets[effect->EffectIndex]) - spellLogEffect.FeedPetTargets.push_back(feedPetTarget); + spellLogEffect.Effect = effect->Effect; + spellLogEffect.PowerDrainTargets = std::move(_powerDrainTargets[effect->EffectIndex]); + spellLogEffect.ExtraAttacksTargets = std::move(_extraAttacksTargets[effect->EffectIndex]); + spellLogEffect.DurabilityDamageTargets = std::move(_durabilityDamageTargets[effect->EffectIndex]); + spellLogEffect.GenericVictimTargets = std::move(_genericVictimTargets[effect->EffectIndex]); + spellLogEffect.TradeSkillTargets = std::move(_tradeSkillTargets[effect->EffectIndex]); + spellLogEffect.FeedPetTargets = std::move(_feedPetTargets[effect->EffectIndex]); spellExecuteLog.Effects.push_back(spellLogEffect); } - m_caster->SendCombatLogMessage(&spellExecuteLog); + if (!spellExecuteLog.Effects.empty()) + m_caster->SendCombatLogMessage(&spellExecuteLog); } void Spell::ExecuteLogEffectTakeTargetPower(uint8 effIndex, Unit* target, uint32 powerType, uint32 points, float amplitude) @@ -4307,21 +4307,11 @@ void Spell::ExecuteLogEffectResurrect(uint8 effect, Unit* target) _genericVictimTargets[effect].push_back(spellLogEffectGenericVictimParams); } -void Spell::CleanupExecuteLogList() -{ - _durabilityDamageTargets->clear(); - _extraAttacksTargets->clear(); - _feedPetTargets->clear(); - _genericVictimTargets->clear(); - _powerDrainTargets->clear(); - _tradeSkillTargets->clear(); -} - void Spell::SendInterrupted(uint8 result) { WorldPackets::Spells::SpellFailure failurePacket; failurePacket.CasterUnit = m_caster->GetGUID(); - failurePacket.CastID = m_cast_count; + failurePacket.CastID = m_castId; failurePacket.SpellID = m_spellInfo->Id; failurePacket.SpelXSpellVisualID = m_SpellVisual; failurePacket.Reason = result; @@ -4329,7 +4319,7 @@ void Spell::SendInterrupted(uint8 result) WorldPackets::Spells::SpellFailedOther failedPacket; failedPacket.CasterUnit = m_caster->GetGUID(); - failedPacket.CastID = m_cast_count; + failedPacket.CastID = m_castId; failedPacket.SpellID = m_spellInfo->Id; failedPacket.Reason = result; m_caster->SendMessageToSet(failedPacket.Write(), true); diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 7dda7451e48..523796eb56d 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -109,6 +109,17 @@ enum SpellCastFlagsEx CAST_FLAG_EX_UNKNOWN_20 = 0x80000 }; +enum SpellCastSource : uint8 +{ + SPELL_CAST_SOURCE_PLAYER = 2, + SPELL_CAST_SOURCE_NORMAL = 3, + SPELL_CAST_SOURCE_ITEM = 4, + SPELL_CAST_SOURCE_PASSIVE = 7, + SPELL_CAST_SOURCE_PET = 9, + SPELL_CAST_SOURCE_AURA = 13, + SPELL_CAST_SOURCE_SPELL = 16, +}; + enum SpellRangeFlag { SPELL_RANGE_DEFAULT = 0, @@ -522,7 +533,7 @@ class TC_GAME_API Spell void CheckSrc() { if (!m_targets.HasSrc()) m_targets.SetSrc(*m_caster); } void CheckDst() { if (!m_targets.HasDst()) m_targets.SetDst(*m_caster); } - static void SendCastResult(Player* caster, SpellInfo const* spellInfo, ObjectGuid cast_count, SpellCastResult result, SpellCustomErrors customError = SPELL_CUSTOM_ERROR_NONE, OpcodeServer opcode = SMSG_CAST_FAILED, uint32* misc = nullptr); + static void SendCastResult(Player* caster, SpellInfo const* spellInfo, uint32 spellVisual, ObjectGuid cast_count, SpellCastResult result, SpellCustomErrors customError = SPELL_CUSTOM_ERROR_NONE, uint32* misc = nullptr); void SendCastResult(SpellCastResult result); void SendPetCastResult(SpellCastResult result); void SendSpellStart(); @@ -539,7 +550,6 @@ class TC_GAME_API Spell void ExecuteLogEffectSummonObject(uint8 effIndex, WorldObject* obj); void ExecuteLogEffectUnsummonObject(uint8 effIndex, WorldObject* obj); void ExecuteLogEffectResurrect(uint8 effIndex, Unit* target); - void CleanupExecuteLogList(); void SendInterrupted(uint8 result); void SendChannelUpdate(uint32 time); void SendChannelStart(uint32 duration); @@ -553,7 +563,8 @@ class TC_GAME_API Spell ObjectGuid m_castItemGUID; uint32 m_castItemEntry; int32 m_castItemLevel; - ObjectGuid m_cast_count; + ObjectGuid m_castId; + ObjectGuid m_originalCastId; uint32 m_castFlagsEx; union { diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 1d9f6fc4c14..d7aa6769b8b 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1552,7 +1552,7 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex) return; } - if (Aura* aura = Aura::TryCreate(m_spellInfo, MAX_EFFECT_MASK, dynObj, caster, &m_spellValue->EffectBasePoints[0], nullptr, ObjectGuid::Empty, m_castItemLevel)) + if (Aura* aura = Aura::TryCreate(m_spellInfo, m_castId, MAX_EFFECT_MASK, dynObj, caster, &m_spellValue->EffectBasePoints[0], nullptr, ObjectGuid::Empty, m_castItemLevel)) { m_spellAura = aura; m_spellAura->_RegisterForTargets(); diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index f0e5ba81f58..0956b25dcdc 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -214,7 +214,7 @@ public: char* fail2 = strtok(NULL, " "); uint8 failArg2 = fail2 ? (uint8)atoi(fail2) : 0; - WorldPackets::Spells::CastFailed castFailed(SMSG_CAST_FAILED); + WorldPackets::Spells::CastFailed castFailed; castFailed.CastID = ObjectGuid::Empty; castFailed.SpellID = 133; castFailed.Reason = failNum; diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 0e20efb0eaf..dafe9a214d5 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -286,7 +286,10 @@ public: uint32 spellId = handler->extractSpellIdFromLink((char*)args); if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId)) - Aura::TryRefreshStackOrCreate(spellInfo, MAX_EFFECT_MASK, target, target); + { + ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, target->GetMapId(), spellId, target->GetMap()->GenerateLowGuid<HighGuid::Cast>()); + Aura::TryRefreshStackOrCreate(spellInfo, castId, MAX_EFFECT_MASK, target, target); + } return true; } @@ -918,12 +921,18 @@ public: if (player->IsInFlight() || player->IsInCombat()) { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(7355); +#define SPELL_UNSTUCK_ID 7355 +#define SPELL_UNSTUCK_VISUAL 2683 + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_UNSTUCK_ID); if (!spellInfo) return false; if (Player* caster = handler->GetSession()->GetPlayer()) - Spell::SendCastResult(caster, spellInfo, ObjectGuid::Empty, SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW); + { + ObjectGuid castId = ObjectGuid::Create<HighGuid::Cast>(SPELL_CAST_SOURCE_NORMAL, player->GetMapId(), SPELL_UNSTUCK_ID, player->GetMap()->GenerateLowGuid<HighGuid::Cast>()); + Spell::SendCastResult(caster, spellInfo, SPELL_UNSTUCK_VISUAL, castId, SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW); + } return false; } |