diff options
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 8 | ||||
| -rw-r--r-- | src/server/game/Handlers/PetHandler.cpp | 6 | ||||
| -rw-r--r-- | src/server/game/Handlers/SpellHandler.cpp | 43 | ||||
| -rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 64 | ||||
| -rw-r--r-- | src/server/game/Server/Packets/CombatPackets.h | 2 | ||||
| -rw-r--r-- | src/server/game/Server/Packets/SpellPackets.cpp | 267 | ||||
| -rw-r--r-- | src/server/game/Server/Packets/SpellPackets.h | 48 | ||||
| -rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 6 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.h | 9 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraDefines.h | 109 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 32 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.h | 6 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellInfo.h | 5 |
14 files changed, 545 insertions, 62 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index cfc7e233458..5bc6a53f6a5 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -3163,7 +3163,7 @@ void Player::InitStatsForLevel(bool reapplyMods) void Player::SendKnownSpells() { - WorldPackets::Spell::SendKnownSpells knownSpells; + WorldPackets::Spells::SendKnownSpells knownSpells; knownSpells.InitialLogin = false; /// @todo knownSpells.KnownSpells.reserve(m_spells.size()); @@ -6201,7 +6201,7 @@ int16 Player::GetSkillTempBonusValue(uint32 skill) const void Player::SendActionButtons(uint32 state) const { - WorldPackets::Spell::UpdateActionButtons packet; + WorldPackets::Spells::UpdateActionButtons packet; for (uint8 button = 0; button < MAX_ACTION_BUTTONS; ++button) { @@ -22994,7 +22994,7 @@ void Player::SendInitialPacketsBeforeAddToMap() SendKnownSpells(); /// SMSG_SEND_UNLEARN_SPELLS - SendDirectMessage(WorldPackets::Spell::SendUnlearnSpells().Write()); + SendDirectMessage(WorldPackets::Spells::SendUnlearnSpells().Write()); /// @todo: SMSG_SEND_SPELL_HISTORY /// @todo: SMSG_SEND_SPELL_CHARGES @@ -23476,7 +23476,7 @@ void Player::SendAurasForTarget(Unit* target) Unit::VisibleAuraMap const* visibleAuras = target->GetVisibleAuras(); - WorldPackets::Spell::SendAuraUpdate update; + WorldPackets::Spells::SendAuraUpdate update; update.Init(true, GetGUID(), visibleAuras->size()); for (Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin(); itr != visibleAuras->end(); ++itr) diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index f2518c2735a..652b548b3a2 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -752,10 +752,10 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) charmInfo->SetSpellAutocast(spellInfo, state != 0); } -void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) +void WorldSession::HandlePetCastSpellOpcode(WorldPackets::Spells::SpellCastRequest& castRequest) { TC_LOG_DEBUG("network", "WORLD: CMSG_PET_CAST_SPELL"); - + /* ObjectGuid guid; uint8 castCount; uint32 spellId; @@ -835,7 +835,7 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) spell->finish(false); delete spell; - } + }*/ } void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName) diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 79b213e2829..12a8c6320fa 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -329,58 +329,46 @@ void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket) _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT, go->GetEntry()); } -void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) +void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::SpellCastRequest& castRequest) { - uint32 spellId, glyphIndex; - uint8 castCount, castFlags; - recvPacket >> castCount; - recvPacket >> spellId; - recvPacket >> glyphIndex; - recvPacket >> castFlags; - - TC_LOG_DEBUG("network", "WORLD: got cast spell packet, castCount: %u, spellId: %u, castFlags: %u, data length = %u", castCount, spellId, castFlags, (uint32)recvPacket.size()); + TC_LOG_DEBUG("network", "WORLD: got cast spell packet, castCount: %u, spellId: %u, castFlags: %u", castRequest.CastID, castRequest.SpellID, castRequest.SendCastFlags); // ignore for remote control state (for player case) Unit* mover = _player->m_mover; if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) { - recvPacket.rfinish(); // prevent spam at ignore packet return; } - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(castRequest.SpellID); if (!spellInfo) { - TC_LOG_ERROR("network", "WORLD: unknown spell id %u", spellId); - recvPacket.rfinish(); // prevent spam at ignore packet + TC_LOG_ERROR("network", "WORLD: unknown spell id %u", castRequest.SpellID); return; } if (spellInfo->IsPassive()) { - recvPacket.rfinish(); // prevent spam at ignore packet return; } Unit* caster = mover; - if (caster->GetTypeId() == TYPEID_UNIT && !caster->ToCreature()->HasSpell(spellId)) + if (caster->GetTypeId() == TYPEID_UNIT && !caster->ToCreature()->HasSpell(castRequest.SpellID)) { // If the vehicle creature does not have the spell but it allows the passenger to cast own spells // change caster to player and let him cast if (!_player->IsOnVehicle(caster) || spellInfo->CheckVehicle(_player) != SPELL_CAST_OK) { - recvPacket.rfinish(); // prevent spam at ignore packet return; } caster = _player; } - if (caster->GetTypeId() == TYPEID_PLAYER && !caster->ToPlayer()->HasActiveSpell(spellId)) + if (caster->GetTypeId() == TYPEID_PLAYER && !caster->ToPlayer()->HasActiveSpell(castRequest.SpellID)) { // not have spell in spellbook - recvPacket.rfinish(); // prevent spam at ignore packet return; } @@ -398,7 +386,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) if (SpellInfo const* newInfo = sSpellMgr->GetSpellInfo((*itr)->GetAmount())) { spellInfo = newInfo; - spellId = newInfo->Id; + castRequest.SpellID = newInfo->Id; } break; } @@ -410,21 +398,20 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) if (spellInfo->IsAutoRepeatRangedSpell() && caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) && caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo == spellInfo) { - recvPacket.rfinish(); return; } // can't use our own spells when we're in possession of another unit, if (_player->isPossessing()) { - recvPacket.rfinish(); // prevent spam at ignore packet return; } // client provided targets - SpellCastTargets targets; - targets.Read(recvPacket, caster); - HandleClientCastFlags(recvPacket, castFlags, targets); + SpellCastTargets targets(caster, castRequest.TargetFlags, castRequest.UnitGuid, castRequest.ItemGuid, castRequest.SrcTransportGuid, castRequest.DstTransportGuid, castRequest.SrcPos, castRequest.DstPos, castRequest.Pitch, castRequest.Speed, castRequest.Name); + + + //HandleClientCastFlags(recvPacket, castFlags, targets); // auto-selection buff level base at target level (in spellInfo) if (targets.GetUnitTarget()) @@ -437,8 +424,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) } Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE, ObjectGuid::Empty, false); - spell->m_cast_count = castCount; // set count of casts - spell->m_glyphIndex = glyphIndex; + spell->m_cast_count = castRequest.CastID; // set count of casts + spell->m_glyphIndex = castRequest.Misc; // 6.x Misc is just a guess spell->prepare(&targets); } @@ -764,14 +751,14 @@ void WorldSession::HandleRequestCategoryCooldowns(WorldPacket& /*recvPacket*/) void WorldSession::SendSpellCategoryCooldowns() { - WorldPackets::Spell::CategoryCooldown cooldowns; + WorldPackets::Spells::CategoryCooldown cooldowns; Unit::AuraEffectList const& categoryCooldownAuras = _player->GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN); for (AuraEffect* aurEff : categoryCooldownAuras) { uint32 categoryId = aurEff->GetMiscValue(); auto cItr = std::find_if(cooldowns.CategoryCooldowns.begin(), cooldowns.CategoryCooldowns.end(), - [categoryId](WorldPackets::Spell::CategoryCooldown::CategoryCooldownInfo const& cooldown) + [categoryId](WorldPackets::Spells::CategoryCooldown::CategoryCooldownInfo const& cooldown) { return cooldown.Category == categoryId; }); diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 7d32555e651..ab1c85bbefe 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -1188,7 +1188,69 @@ enum SpellEffectName SPELL_EFFECT_180 = 180, // Unused (4.3.4) SPELL_EFFECT_181 = 181, // Unused (4.3.4) SPELL_EFFECT_182 = 182, - TOTAL_SPELL_EFFECTS = 183, + SPELL_EFFECT_183 = 183, + SPELL_EFFECT_184 = 184, + SPELL_EFFECT_185 = 185, + SPELL_EFFECT_186 = 186, + SPELL_EFFECT_187 = 187, + SPELL_EFFECT_188 = 188, + SPELL_EFFECT_189 = 189, + SPELL_EFFECT_190 = 190, + SPELL_EFFECT_191 = 191, + SPELL_EFFECT_192 = 192, + SPELL_EFFECT_193 = 193, + SPELL_EFFECT_194 = 194, + SPELL_EFFECT_195 = 195, + SPELL_EFFECT_196 = 196, + SPELL_EFFECT_197 = 197, + SPELL_EFFECT_198 = 198, + SPELL_EFFECT_199 = 199, + SPELL_EFFECT_200 = 200, + SPELL_EFFECT_201 = 201, + SPELL_EFFECT_202 = 202, + SPELL_EFFECT_203 = 203, + SPELL_EFFECT_204 = 204, + SPELL_EFFECT_205 = 205, + SPELL_EFFECT_206 = 206, + SPELL_EFFECT_207 = 207, + SPELL_EFFECT_208 = 208, + SPELL_EFFECT_209 = 209, + SPELL_EFFECT_210 = 210, + SPELL_EFFECT_211 = 211, + SPELL_EFFECT_212 = 212, + SPELL_EFFECT_213 = 213, + SPELL_EFFECT_214 = 214, + SPELL_EFFECT_215 = 215, + SPELL_EFFECT_216 = 216, + SPELL_EFFECT_217 = 217, + SPELL_EFFECT_218 = 218, + SPELL_EFFECT_219 = 219, + SPELL_EFFECT_220 = 220, + SPELL_EFFECT_221 = 221, + SPELL_EFFECT_222 = 222, + SPELL_EFFECT_223 = 223, + SPELL_EFFECT_224 = 224, + SPELL_EFFECT_225 = 225, + SPELL_EFFECT_226 = 226, + SPELL_EFFECT_227 = 227, + SPELL_EFFECT_228 = 228, + SPELL_EFFECT_229 = 229, + SPELL_EFFECT_230 = 230, + SPELL_EFFECT_231 = 231, + SPELL_EFFECT_232 = 232, + SPELL_EFFECT_233 = 233, + SPELL_EFFECT_234 = 234, + SPELL_EFFECT_235 = 235, + SPELL_EFFECT_236 = 236, + SPELL_EFFECT_237 = 237, + SPELL_EFFECT_238 = 238, + SPELL_EFFECT_239 = 239, + SPELL_EFFECT_240 = 240, + SPELL_EFFECT_241 = 241, + SPELL_EFFECT_242 = 242, + SPELL_EFFECT_243 = 243, + SPELL_EFFECT_244 = 244, + TOTAL_SPELL_EFFECTS = 245, }; enum SpellCastResult // (6.0) diff --git a/src/server/game/Server/Packets/CombatPackets.h b/src/server/game/Server/Packets/CombatPackets.h index 14648297342..5b2347e3edb 100644 --- a/src/server/game/Server/Packets/CombatPackets.h +++ b/src/server/game/Server/Packets/CombatPackets.h @@ -150,7 +150,7 @@ namespace WorldPackets WorldPacket const* Write() override; - Optional<WorldPackets::Spell::SpellCastLogData> LogData; + Optional<WorldPackets::Spells::SpellCastLogData> LogData; uint32 HitInfo = 0; // Flags ObjectGuid AttackerGUID; ObjectGuid VictimGUID; diff --git a/src/server/game/Server/Packets/SpellPackets.cpp b/src/server/game/Server/Packets/SpellPackets.cpp index e56e73fb036..1094dd7640e 100644 --- a/src/server/game/Server/Packets/SpellPackets.cpp +++ b/src/server/game/Server/Packets/SpellPackets.cpp @@ -17,8 +17,9 @@ #include "SpellPackets.h" #include "SpellAuraEffects.h" +#include "MovementPackets.h" -WorldPacket const* WorldPackets::Spell::CategoryCooldown::Write() +WorldPacket const* WorldPackets::Spells::CategoryCooldown::Write() { _worldPacket.reserve(4 + 8 * CategoryCooldowns.size()); @@ -33,7 +34,7 @@ WorldPacket const* WorldPackets::Spell::CategoryCooldown::Write() return &_worldPacket; } -WorldPacket const* WorldPackets::Spell::SendKnownSpells::Write() +WorldPacket const* WorldPackets::Spells::SendKnownSpells::Write() { _worldPacket.reserve(1 + 4 * KnownSpells.size()); @@ -46,7 +47,7 @@ WorldPacket const* WorldPackets::Spell::SendKnownSpells::Write() return &_worldPacket; } -WorldPacket const* WorldPackets::Spell::UpdateActionButtons::Write() +WorldPacket const* WorldPackets::Spells::UpdateActionButtons::Write() { for (uint32 i = 0; i < MAX_ACTION_BUTTONS; ++i) _worldPacket << ActionButtons[i]; @@ -56,7 +57,7 @@ WorldPacket const* WorldPackets::Spell::UpdateActionButtons::Write() return &_worldPacket; } -WorldPacket const* WorldPackets::Spell::SendUnlearnSpells::Write() +WorldPacket const* WorldPackets::Spells::SendUnlearnSpells::Write() { _worldPacket << uint32(Spells.size()); for (uint32 spellId : Spells) @@ -65,13 +66,13 @@ WorldPacket const* WorldPackets::Spell::SendUnlearnSpells::Write() return &_worldPacket; } -ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spell::SpellCastLogData& spellCastLogData) +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastLogData& spellCastLogData) { data << spellCastLogData.Health; data << spellCastLogData.AttackPower; data << spellCastLogData.SpellPower; data << int32(spellCastLogData.PowerData.size()); - for (WorldPackets::Spell::SpellLogPowerData const& powerData : spellCastLogData.PowerData) + for (WorldPackets::Spells::SpellLogPowerData const& powerData : spellCastLogData.PowerData) { data << powerData.PowerType; data << powerData.Amount; @@ -83,27 +84,29 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spell::SpellCastLogData& return data; } -WorldPacket const* WorldPackets::Spell::SendAuraUpdate::Write() +WorldPacket const* WorldPackets::Spells::SendAuraUpdate::Write() { return &_worldPacket; } -void WorldPackets::Spell::SendAuraUpdate::Init(bool IsFullUpdate, ObjectGuid Target, uint32 Count) +void WorldPackets::Spells::SendAuraUpdate::Init(bool IsFullUpdate, ObjectGuid Target, uint32 Count) { _worldPacket.WriteBit(IsFullUpdate); _worldPacket << Target; _worldPacket << uint32(Count); } -void WorldPackets::Spell::SendAuraUpdate::BuildUpdatePacket(AuraApplication* aurApp, bool remove, uint16 level) +void WorldPackets::Spells::SendAuraUpdate::BuildUpdatePacket(AuraApplication* aurApp, bool remove, uint16 level) { _worldPacket << uint8(aurApp->GetSlot()); _worldPacket.ResetBitPos(); _worldPacket.WriteBit(!remove); if (remove) + { + _worldPacket.FlushBits(); return; - + } Aura const* aura = aurApp->GetBase(); _worldPacket << uint32(aura->GetId()); @@ -111,7 +114,7 @@ void WorldPackets::Spell::SendAuraUpdate::BuildUpdatePacket(AuraApplication* aur if (aura->GetMaxDuration() > 0 && !(aura->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_HIDE_DURATION)) flags |= AFLAG_DURATION; _worldPacket << uint8(flags); - + _worldPacket << uint32(aurApp->GetEffectMask()); _worldPacket << uint16(level); @@ -119,7 +122,7 @@ void WorldPackets::Spell::SendAuraUpdate::BuildUpdatePacket(AuraApplication* aur // send stack amount for aura which could be stacked (never 0 - causes incorrect display) or charges // stack amount has priority over charges (checked on retail with spell 50262) _worldPacket << uint8(aura->GetSpellInfo()->StackAmount ? aura->GetStackAmount() : aura->GetCharges()); - + uint32 int72 = 0; _worldPacket << int72; @@ -145,7 +148,7 @@ void WorldPackets::Spell::SendAuraUpdate::BuildUpdatePacket(AuraApplication* aur _worldPacket.put<uint32>(pos, count); _worldPacket.ResetBitPos(); - + _worldPacket.WriteBit(!(flags & AFLAG_NOCASTER)); _worldPacket.WriteBit(aura->GetDuration()); _worldPacket.WriteBit(aura->GetMaxDuration()); @@ -163,3 +166,241 @@ void WorldPackets::Spell::SendAuraUpdate::BuildUpdatePacket(AuraApplication* aur _worldPacket << uint32(aura->GetMaxDuration()); } } + +void WorldPackets::Spells::SpellCastRequest::Read() +{ + if (_worldPacket.GetOpcode() == CMSG_PET_CAST_SPELL) + _worldPacket >> PetGuid; + + _worldPacket >> CastID; + _worldPacket >> SpellID; + _worldPacket >> Misc; + + TC_LOG_ERROR("spells", "SpellID %u Misc %u", SpellID, Misc); + + _worldPacket.ResetBitPos(); + + TargetFlags = _worldPacket.ReadBits(21); + bool HasSrcLocation = _worldPacket.ReadBit(); + bool HasDstLocation = _worldPacket.ReadBit(); + bool HasOrientation = _worldPacket.ReadBit(); + uint32 NameLen = _worldPacket.ReadBits(7); + + _worldPacket >> UnitGuid; + _worldPacket >> ItemGuid; + + if (HasSrcLocation) + { + _worldPacket >> SrcTransportGuid; + _worldPacket >> SrcPos.m_positionX; + _worldPacket >> SrcPos.m_positionY; + _worldPacket >> SrcPos.m_positionZ; + } + + if (HasDstLocation) + { + _worldPacket >> DstTransportGuid; + _worldPacket >> DstPos.m_positionX; + _worldPacket >> DstPos.m_positionY; + _worldPacket >> DstPos.m_positionZ; + } + + if (HasOrientation) + _worldPacket >> Orientation; + + Name = _worldPacket.ReadString(NameLen); + + _worldPacket >> Pitch; + _worldPacket >> Speed; + + _worldPacket >> Guid; + + _worldPacket.ResetBitPos(); + + SendCastFlags = _worldPacket.ReadBits(5); + + bool HasMoveUpdate = _worldPacket.ReadBit(); + uint32 SpellWeightCount = _worldPacket.ReadBits(2); + + if (HasMoveUpdate) + { + _worldPacket >> movementInfo; + } + + // SpellWeight + for (uint32 i = 0; i < SpellWeightCount; ++i) + { + _worldPacket.ResetBitPos(); + uint32 Type = _worldPacket.ReadBits(2); + uint32 ID; + _worldPacket >> ID; + uint32 Quantity; + _worldPacket >> Quantity; + } +} + +WorldPacket const* WorldPackets::Spells::SendSpellStart::Write() +{ + uint32 castFlags = CAST_FLAG_HAS_TRAJECTORY; + + if ((spell->IsTriggered() && !spell->m_spellInfo->IsAutoRepeatRangedSpell()) || spell->GetTriggeredByAuraSpell()) + castFlags |= CAST_FLAG_PENDING; + + if ((spell->GetCaster()->GetTypeId() == TYPEID_PLAYER || + (spell->GetCaster()->GetTypeId() == TYPEID_UNIT && spell->GetCaster()->ToCreature()->IsPet())) + && spell->m_spellInfo->PowerType != POWER_HEALTH) + castFlags |= CAST_FLAG_POWER_LEFT_SELF; + + if (spell->m_spellInfo->RuneCostID && spell->m_spellInfo->PowerType == POWER_RUNES) + castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it + + + if (spell->m_CastItem) + _worldPacket << spell->m_CastItem->GetGUID(); + else + _worldPacket << spell->GetCaster()->GetGUID(); + _worldPacket << spell->GetCaster()->GetGUID(); + _worldPacket << uint8(spell->m_cast_count); + _worldPacket << uint32(spell->m_spellInfo->Id); + _worldPacket << uint32(castFlags); + _worldPacket << uint32(spell->GetCastTime()); + + uint32 HitTargets = 0; + _worldPacket << HitTargets; + uint32 MissTargets = 0; + _worldPacket << MissTargets; + uint32 MissStatus = 0; + _worldPacket << MissStatus; + + _worldPacket.ResetBitPos(); + + _worldPacket.WriteBits(spell->m_targets.GetTargetMask(), 21); + + bool HasSourceLocation = (spell->m_targets.GetTargetMask() & TARGET_FLAG_SOURCE_LOCATION) && spell->m_targets.GetSrc(); + bool HasDestLocation = (spell->m_targets.GetTargetMask() & TARGET_FLAG_DEST_LOCATION) && spell->m_targets.GetDst(); + bool HasOrientation = false; + uint32 NameLen = spell->m_targets.GetTargetString().length(); + + _worldPacket.WriteBit(HasSourceLocation); + _worldPacket.WriteBit(HasDestLocation); + _worldPacket.WriteBit(HasOrientation); + _worldPacket.WriteBits(NameLen, 7); + + ObjectGuid targetGuid = spell->m_targets.GetObjectTargetGUID(); + ObjectGuid itemTargetGuid = spell->m_targets.GetItemTargetGUID(); + + _worldPacket << targetGuid; + _worldPacket << itemTargetGuid; + + if (HasSourceLocation) + { + _worldPacket << spell->m_targets.GetSrc()->_transportGUID; + float x, y, z; + spell->m_targets.GetSrc()->_transportOffset.GetPosition(x, y, z); + _worldPacket << x; + _worldPacket << y; + _worldPacket << z; + } + + if (HasDestLocation) + { + _worldPacket << spell->m_targets.GetDst()->_transportGUID; + float x, y, z; + spell->m_targets.GetDst()->_transportOffset.GetPosition(x, y, z); + _worldPacket << x; + _worldPacket << y; + _worldPacket << z; + } + + //if (HasOrientation) + // _worldPacket << float(0); + + _worldPacket.WriteString(spell->m_targets.GetTargetString()); + + uint32 SpellPowerData = 0; + _worldPacket << SpellPowerData; + + + _worldPacket << uint32(0); // TravelTime + _worldPacket << spell->m_targets.GetElevation(); + + _worldPacket << uint32(0); // Ammo DisplayID + _worldPacket << uint8(0); // Ammo InventoryType + + _worldPacket << uint8(0); // DestLocSpellCastIndex + + uint32 TargetPoints = 0; + _worldPacket << TargetPoints; + + _worldPacket << uint32(0); // CreatureImmunities School + _worldPacket << uint32(0); // CreatureImmunities Value + + _worldPacket << uint32(0); // SpellHealPrediction Points + _worldPacket << uint8(0); // SpellHealPrediction Type + ObjectGuid BeaconGUID; + _worldPacket << BeaconGUID; // SpellHealPrediction BeaconGUID + + /*for (uint32 i = 0; i < HitTargets; ++i) + { + ObjectGuid HitTargetGUID; + _worldPacket << HitTargetGUID; + } + for (uint32 i = 0; i < MissTargets; ++i) + { + ObjectGuid MissTargetGUID; + _worldPacket << MissTargetGUID; + } + for (uint32 i = 0; i < MissStatus; ++i) + { + _worldPacket.ResetBitPos(); + uint32 MissReason = 0; + _worldPacket.WriteBits(MissReason, 4); + uint32 ReflectStatus = 0; + if (MissReason == 11) + _worldPacket.WriteBits(ReflectStatus, 4); + } + for (uint32 i = 0; i < SpellPowerData; ++i) + { + //uint32 Cost + //uint8 PowerType + } + for (uint32 i = 0; i < TargetPoints; ++i) + { + //Transport Guid + //XYZ + }*/ + + _worldPacket.ResetBitPos(); + + _worldPacket.WriteBits(0, 18); // CastFlagsEx + + bool HasRuneData = false; + bool HasProjectileVisual = false; + + _worldPacket.WriteBit(HasRuneData); + _worldPacket.WriteBit(HasProjectileVisual); + + /*if (HasRuneData) + { + _worldPacket << uint8(0); // Start + _worldPacket << uint8(0); // Count + _worldPacket.ResetBitPos(); + + uint32 CooldownCount = 0; + _worldPacket.WriteBits(CooldownCount, 3); + for (uint32 i = 0; i < CooldownCount; ++i) + { + _worldPacket << uint8(0); // Cooldowns + } + }*/ + + /*if (HasProjectileVisual) + { + for (uint32 i = 0; i < 2; ++i) + { + _worldPacket << uint32(0); // Id + } + }*/ + + return &_worldPacket; +}
\ No newline at end of file diff --git a/src/server/game/Server/Packets/SpellPackets.h b/src/server/game/Server/Packets/SpellPackets.h index 8aee276021c..77825067693 100644 --- a/src/server/game/Server/Packets/SpellPackets.h +++ b/src/server/game/Server/Packets/SpellPackets.h @@ -21,10 +21,11 @@ #include "Packet.h" #include "Player.h" #include "SpellAuras.h" +#include "Spell.h" namespace WorldPackets { - namespace Spell + namespace Spells { class CategoryCooldown final : public ServerPacket { @@ -109,9 +110,52 @@ namespace WorldPackets void Init(bool IsFullUpdate, ObjectGuid Target, uint32 Count); void BuildUpdatePacket(AuraApplication* aurApp, bool remove, uint16 level); }; + + class SpellCastRequest final : public ClientPacket + { + public: + SpellCastRequest(WorldPacket&& packet) : ClientPacket(std::move(packet)) + { + ASSERT(packet.GetOpcode() == CMSG_CAST_SPELL || packet.GetOpcode() == CMSG_PET_CAST_SPELL); + } + + void Read() override; + + ObjectGuid PetGuid; + uint8 CastID; + uint32 SpellID; + uint32 Misc; + uint32 TargetFlags; + ObjectGuid UnitGuid; + ObjectGuid ItemGuid; + + ObjectGuid SrcTransportGuid; + ObjectGuid DstTransportGuid; + Position SrcPos; + Position DstPos; + float Orientation; + + std::string Name; + float Pitch; + float Speed; + ObjectGuid Guid; + uint32 SendCastFlags; + + MovementInfo movementInfo; + }; + + class SendSpellStart final : public ServerPacket + { + public: + SendSpellStart() : ServerPacket(SMSG_SPELL_START) { } + + WorldPacket const* Write() override; + + Spell* spell; + }; } } -ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spell::SpellCastLogData& spellCastLogData); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastLogData& spellCastLogData); #endif // SpellPackets_h__ diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 1ca8938b4eb..8fb7ca21acd 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_OPCODE_HANDLER_OLD(CMSG_CANCEL_QUEUED_SPELL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_TEMP_ENCHANTMENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTempEnchantmentOpcode); DEFINE_HANDLER(CMSG_CANCEL_TRADE, STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, WorldPackets::Trade::CancelTrade, &WorldSession::HandleCancelTradeOpcode); - DEFINE_OPCODE_HANDLER_OLD(CMSG_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleCastSpellOpcode ); + DEFINE_HANDLER(CMSG_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Spells::SpellCastRequest, &WorldSession::HandleCastSpellOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANGEPLAYER_DIFFICULTY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle); DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANNEL_ANNOUNCEMENTS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelAnnouncements ); @@ -498,7 +498,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_ABANDON, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetAbandon ); DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_ACTION, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetAction ); DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_CANCEL_AURA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCancelAuraOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_CAST_SPELL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCastSpellOpcode ); + DEFINE_HANDLER(CMSG_PET_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::SpellCastRequest, &WorldSession::HandlePetCastSpellOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_LEARN_TALENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetLearnTalent ); DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_NAME_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetNameQuery ); DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_RENAME, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetRename ); @@ -1318,7 +1318,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILED_OTHER, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILURE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_GO, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_START, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_START, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_UPDATE_CHAIN_TARGETS, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPIRIT_HEALER_CONFIRM, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPLINE_MOVE_COLLISION_DISABLE, STATUS_UNHANDLED); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index baeace23b40..1442bf2576d 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -138,6 +138,11 @@ namespace WorldPackets class QueryGuildInfo; } + namespace Spells + { + class SpellCastRequest; + } + namespace Talent { class SetSpecialization; @@ -863,7 +868,7 @@ class WorldSession void HandleUseItemOpcode(WorldPacket& recvPacket); void HandleOpenItemOpcode(WorldPacket& recvPacket); - void HandleCastSpellOpcode(WorldPacket& recvPacket); + void HandleCastSpellOpcode(WorldPackets::Spells::SpellCastRequest& castRequest); void HandleCancelCastOpcode(WorldPacket& recvPacket); void HandleCancelAuraOpcode(WorldPacket& recvPacket); void HandleCancelGrowthAuraOpcode(WorldPacket& recvPacket); @@ -955,7 +960,7 @@ class WorldSession void HandlePetRename(WorldPacket& recvData); void HandlePetCancelAuraOpcode(WorldPacket& recvPacket); void HandlePetSpellAutocastOpcode(WorldPacket& recvPacket); - void HandlePetCastSpellOpcode(WorldPacket& recvPacket); + void HandlePetCastSpellOpcode(WorldPackets::Spells::SpellCastRequest& castRequest); void HandlePetLearnTalent(WorldPacket& recvPacket); void HandleLearnPreviewTalentsPet(WorldPacket& recvPacket); diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 3c05c15a57d..e75a3424c2f 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -428,7 +428,114 @@ enum AuraType SPELL_AURA_368 = 368, // Not used in 4.3.4 SPELL_AURA_ENABLE_POWER_BAR_TIMER = 369, SPELL_AURA_SET_FAIR_FAR_CLIP = 370, // Overrides client's View Distance setting to max("Fair", current_setting) - TOTAL_AURAS = 371 // 4.3.4 + SPELL_AURA_371 = 371, + SPELL_AURA_372 = 372, + SPELL_AURA_373 = 373, + SPELL_AURA_374 = 374, + SPELL_AURA_375 = 375, + SPELL_AURA_376 = 376, + SPELL_AURA_377 = 377, + SPELL_AURA_378 = 378, + SPELL_AURA_379 = 379, + SPELL_AURA_380 = 380, + SPELL_AURA_381 = 381, + SPELL_AURA_382 = 382, + SPELL_AURA_383 = 383, + SPELL_AURA_384 = 384, + SPELL_AURA_385 = 385, + SPELL_AURA_386 = 386, + SPELL_AURA_387 = 387, + SPELL_AURA_388 = 388, + SPELL_AURA_389 = 389, + SPELL_AURA_390 = 390, + SPELL_AURA_391 = 391, + SPELL_AURA_392 = 392, + SPELL_AURA_393 = 393, + SPELL_AURA_394 = 394, + SPELL_AURA_395 = 395, + SPELL_AURA_396 = 396, + SPELL_AURA_397 = 397, + SPELL_AURA_398 = 398, + SPELL_AURA_399 = 399, + SPELL_AURA_400 = 400, + SPELL_AURA_401 = 401, + SPELL_AURA_402 = 402, + SPELL_AURA_403 = 403, + SPELL_AURA_404 = 404, + SPELL_AURA_405 = 405, + SPELL_AURA_406 = 406, + SPELL_AURA_407 = 407, + SPELL_AURA_408 = 408, + SPELL_AURA_409 = 409, + SPELL_AURA_410 = 410, + SPELL_AURA_411 = 411, + SPELL_AURA_412 = 412, + SPELL_AURA_413 = 413, + SPELL_AURA_414 = 414, + SPELL_AURA_415 = 415, + SPELL_AURA_416 = 416, + SPELL_AURA_417 = 417, + SPELL_AURA_418 = 418, + SPELL_AURA_419 = 419, + SPELL_AURA_420 = 420, + SPELL_AURA_421 = 421, + SPELL_AURA_422 = 422, + SPELL_AURA_423 = 423, + SPELL_AURA_424 = 424, + SPELL_AURA_425 = 425, + SPELL_AURA_426 = 426, + SPELL_AURA_427 = 427, + SPELL_AURA_428 = 428, + SPELL_AURA_429 = 429, + SPELL_AURA_430 = 430, + SPELL_AURA_431 = 431, + SPELL_AURA_432 = 432, + SPELL_AURA_433 = 433, + SPELL_AURA_434 = 434, + SPELL_AURA_435 = 435, + SPELL_AURA_436 = 436, + SPELL_AURA_437 = 437, + SPELL_AURA_438 = 438, + SPELL_AURA_439 = 439, + SPELL_AURA_440 = 440, + SPELL_AURA_441 = 441, + SPELL_AURA_442 = 442, + SPELL_AURA_443 = 443, + SPELL_AURA_444 = 444, + SPELL_AURA_445 = 445, + SPELL_AURA_446 = 446, + SPELL_AURA_447 = 447, + SPELL_AURA_448 = 448, + SPELL_AURA_449 = 449, + SPELL_AURA_450 = 450, + SPELL_AURA_451 = 451, + SPELL_AURA_452 = 452, + SPELL_AURA_453 = 453, + SPELL_AURA_454 = 454, + SPELL_AURA_455 = 455, + SPELL_AURA_456 = 456, + SPELL_AURA_457 = 457, + SPELL_AURA_458 = 458, + SPELL_AURA_459 = 459, + SPELL_AURA_460 = 460, + SPELL_AURA_461 = 461, + SPELL_AURA_462 = 462, + SPELL_AURA_463 = 463, + SPELL_AURA_464 = 464, + SPELL_AURA_465 = 465, + SPELL_AURA_466 = 466, + SPELL_AURA_467 = 467, + SPELL_AURA_468 = 468, + SPELL_AURA_469 = 469, + SPELL_AURA_471 = 471, + SPELL_AURA_472 = 472, + SPELL_AURA_473 = 473, + SPELL_AURA_474 = 474, + SPELL_AURA_475 = 475, + SPELL_AURA_476 = 476, + SPELL_AURA_477 = 477, + SPELL_AURA_478 = 478, + TOTAL_AURAS = 479 // 4.3.4 }; enum AuraObjectType diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 6451111d0b8..1acddcc5523 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -227,7 +227,7 @@ void AuraApplication::ClientUpdate(bool remove) { _needClientUpdate = false; - WorldPackets::Spell::SendAuraUpdate update; + WorldPackets::Spells::SendAuraUpdate update; update.Init(false, GetTarget()->GetGUID(), 1); update.BuildUpdatePacket(this, remove, GetTarget()->getLevel()); // TODO 6.x should be caster's level diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index bc386f0ba65..0a55735eae5 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -57,6 +57,7 @@ #include "DB2Stores.h" #include "Battlefield.h" #include "BattlefieldMgr.h" +#include "SpellPackets.h" extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS]; @@ -118,6 +119,28 @@ SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0), m_strTarget() m_targetMask = 0; } +SpellCastTargets::SpellCastTargets(Unit* caster, uint32 targetMask, ObjectGuid targetGuid, ObjectGuid itemTargetGuid, ObjectGuid srcTransportGuid, ObjectGuid destTransportGuid, Position srcPos, Position destPos, float elevation, float missileSpeed, std::string targetString) : + m_targetMask(targetMask), m_objectTargetGUID(targetGuid), m_itemTargetGUID(itemTargetGuid), m_elevation(elevation), m_speed(missileSpeed), m_strTarget(targetString) +{ + m_objectTarget = NULL; + m_itemTarget = NULL; + m_itemTargetEntry = 0; + + m_src._transportGUID = srcTransportGuid; + if (m_src._transportGUID != ObjectGuid::Empty) + m_src._transportOffset.Relocate(srcPos); + else + m_src._position.Relocate(srcPos); + + m_dst._transportGUID = destTransportGuid; + if (m_dst._transportGUID != ObjectGuid::Empty) + m_dst._transportOffset.Relocate(destPos); + else + m_dst._position.Relocate(destPos); + + Update(caster); +} + SpellCastTargets::~SpellCastTargets() { } void SpellCastTargets::Read(ByteBuffer& data, Unit* caster) @@ -3841,7 +3864,10 @@ void Spell::SendSpellStart() if (m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNES) castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it - WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2)); + WorldPackets::Spells::SendSpellStart spellStart; + spellStart.spell = this; + + /*WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2)); if (m_CastItem) data << m_CastItem->GetPackGUID(); else @@ -3901,9 +3927,9 @@ void Spell::SendSpellStart() data << uint8(0); // unkByte // if (unkByte == 2) // data.append(0); - } + }*/ - m_caster->SendMessageToSet(&data, true); + m_caster->SendMessageToSet(spellStart.Write(), true); } void Spell::SendSpellGo() diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 890ebdf4081..8accaf896d0 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -99,6 +99,7 @@ class SpellCastTargets { public: SpellCastTargets(); + SpellCastTargets(Unit* caster, uint32 targetMask, ObjectGuid targetGuid, ObjectGuid itemTargetGuid, ObjectGuid srcTransportGuid, ObjectGuid destTransportGuid, Position srcPos, Position destPos, float elevation, float missileSpeed, std::string targetString); ~SpellCastTargets(); void Read(ByteBuffer& data, Unit* caster); @@ -168,6 +169,7 @@ class SpellCastTargets void Update(Unit* caster); void OutDebug() const; + std::string GetTargetString() const { return m_strTarget; } private: uint32 m_targetMask; @@ -516,6 +518,10 @@ class Spell Spell** m_selfContainer; // pointer to our spell container (if applicable) + SpellInfo const* GetTriggeredByAuraSpell() const { return m_triggeredByAuraSpell; } + + int32 GetTimer() const { return m_timer; } + protected: bool HasGlobalCooldown() const; void TriggerGlobalCooldown(); diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index a49f956bc57..413eb9d39a5 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -65,6 +65,11 @@ enum SpellCastTargetFlags TARGET_FLAG_DEST_TARGET = 0x00040000, // sometimes appears with DEST_TARGET spells (may appear or not for a given spell) TARGET_FLAG_EXTRA_TARGETS = 0x00080000, // uint32 counter, loop { vec3 - screen position (?), guid }, not used so far TARGET_FLAG_UNIT_PASSENGER = 0x00100000, // guessed, used to validate target (if vehicle passenger) + TARGET_FLAG_UNK400000 = 0X00400000, + TARGET_FLAG_UNK1000000 = 0X01000000, + TARGET_FLAG_UNK4000000 = 0X04000000, + TARGET_FLAG_UNK10000000 = 0X10000000, + TARGET_FLAG_UNK40000000 = 0X40000000, TARGET_FLAG_UNIT_MASK = TARGET_FLAG_UNIT | TARGET_FLAG_UNIT_RAID | TARGET_FLAG_UNIT_PARTY | TARGET_FLAG_UNIT_ENEMY | TARGET_FLAG_UNIT_ALLY | TARGET_FLAG_UNIT_DEAD | TARGET_FLAG_UNIT_MINIPET | TARGET_FLAG_UNIT_PASSENGER, |
