aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/Spell.cpp
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2018-03-10 03:55:14 -0300
committerariel- <ariel-@users.noreply.github.com>2018-03-10 03:55:14 -0300
commit0c2a6dee0781be56bdee81e4d155431d7e7634f1 (patch)
tree44c95a57f51536f513f7a17b1d47602c99b9bbde /src/server/game/Spells/Spell.cpp
parent4ca9d6469da435cb818e3b56840669775627e050 (diff)
Core/Spell: fix spell visual for other players
- Ported SMSG_SPELL_GO and SMSG_SPELL_START to new packet system
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
-rw-r--r--src/server/game/Spells/Spell.cpp191
1 files changed, 91 insertions, 100 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 6f8322332b8..bbd290df5a4 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -47,6 +47,7 @@
#include "SpellHistory.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
+#include "SpellPackets.h"
#include "SpellScript.h"
#include "TemporarySummon.h"
#include "TradeData.h"
@@ -175,41 +176,42 @@ void SpellCastTargets::Read(ByteBuffer& data, Unit* caster)
Update(caster);
}
-void SpellCastTargets::Write(ByteBuffer& data)
+void SpellCastTargets::Write(WorldPackets::Spells::SpellTargetData& data)
{
- data << uint32(m_targetMask);
+ data.Flags = m_targetMask;
if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_UNIT_MINIPET))
- data << m_objectTargetGUID.WriteAsPacked();
+ data.Unit = m_objectTargetGUID;
if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM))
{
+ data.Item = boost::in_place();
if (m_itemTarget)
- data << m_itemTarget->GetPackGUID();
- else
- data << uint8(0);
+ data.Item = m_itemTarget->GetGUID();
}
if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION)
{
- data << m_src._transportGUID.WriteAsPacked(); // relative position guid here - transport for example
- if (m_src._transportGUID)
- data << m_src._transportOffset.PositionXYZStream();
+ data.SrcLocation = boost::in_place();
+ data.SrcLocation->Transport = m_src._transportGUID;
+ if (!m_src._transportGUID.IsEmpty())
+ data.SrcLocation->Location = m_src._transportOffset;
else
- data << m_src._position.PositionXYZStream();
+ data.SrcLocation->Location = m_src._position;
}
if (m_targetMask & TARGET_FLAG_DEST_LOCATION)
{
- data << m_dst._transportGUID.WriteAsPacked(); // relative position guid here - transport for example
+ data.DstLocation = boost::in_place();
+ data.DstLocation->Transport = m_dst._transportGUID;
if (m_dst._transportGUID)
- data << m_dst._transportOffset.PositionXYZStream();
+ data.DstLocation->Location = m_dst._transportOffset;
else
- data << m_dst._position.PositionXYZStream();
+ data.DstLocation->Location = m_dst._position;
}
if (m_targetMask & TARGET_FLAG_STRING)
- data << m_strTarget;
+ data.Name = m_strTarget;
}
ObjectGuid SpellCastTargets::GetOrigUnitTargetGUID() const
@@ -4082,33 +4084,39 @@ void Spell::SendSpellStart()
if (m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNE)
castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it
- WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2));
+ WorldPackets::Spells::SpellStart packet;
+ WorldPackets::Spells::SpellCastData& castData = packet.Cast;
+
if (m_CastItem)
- data << m_CastItem->GetPackGUID();
+ castData.CasterGUID = m_CastItem->GetGUID();
else
- data << m_caster->GetPackGUID();
+ castData.CasterGUID = m_caster->GetGUID();
- data << m_caster->GetPackGUID();
- data << uint8(m_cast_count); // pending spell cast?
- data << uint32(m_spellInfo->Id); // spellId
- data << uint32(castFlags); // cast flags
- data << int32(m_timer); // delay?
+ castData.CasterUnit = m_caster->GetGUID();
+ castData.CastID = m_cast_count;
+ castData.SpellID = m_spellInfo->Id;
+ castData.CastFlags = castFlags;
+ castData.CastTime = m_timer;
- m_targets.Write(data);
+ m_targets.Write(castData.Target);
if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
- data << uint32(ASSERT_NOTNULL(m_caster->ToUnit())->GetPower((Powers)m_spellInfo->PowerType));
+ castData.RemainingPower = ASSERT_NOTNULL(m_caster->ToUnit())->GetPower(static_cast<Powers>(m_spellInfo->PowerType));
if (castFlags & CAST_FLAG_AMMO)
- WriteAmmoToPacket(&data);
+ {
+ castData.Ammo = boost::in_place();
+ UpdateSpellCastDataAmmo(*castData.Ammo);
+ }
if (castFlags & CAST_FLAG_IMMUNITY)
{
- data << uint32(schoolImmunityMask);
- data << uint32(mechanicImmunityMask);
+ castData.Immunities = boost::in_place();
+ castData.Immunities->School = schoolImmunityMask;
+ castData.Immunities->Value = mechanicImmunityMask;
}
- m_caster->SendMessageToSet(&data, true);
+ m_caster->SendMessageToSet(packet.Write(), true);
}
void Spell::SendSpellGo()
@@ -4117,8 +4125,6 @@ void Spell::SendSpellGo()
if (!IsNeedSendToClient())
return;
- //TC_LOG_DEBUG("spells", "Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id);
-
uint32 castFlags = CAST_FLAG_UNKNOWN_9;
// triggered spells with spell visual != 0
@@ -4152,78 +4158,82 @@ void Spell::SendSpellGo()
if (!m_spellInfo->StartRecoveryTime)
castFlags |= CAST_FLAG_NO_GCD;
- WorldPacket data(SMSG_SPELL_GO, 50); // guess size
+ WorldPackets::Spells::SpellGo packet;
+ WorldPackets::Spells::SpellCastData& castData = packet.Cast;
+
if (m_CastItem)
- data << m_CastItem->GetPackGUID();
+ castData.CasterGUID = m_CastItem->GetGUID();
else
- data << m_caster->GetPackGUID();
+ castData.CasterGUID = m_caster->GetGUID();
- data << m_caster->GetPackGUID();
- data << uint8(m_cast_count); // pending spell cast?
- data << uint32(m_spellInfo->Id); // spellId
- data << uint32(castFlags); // cast flags
- data << uint32(GameTime::GetGameTimeMS()); // timestamp
+ castData.CasterUnit = m_caster->GetGUID();
+ castData.CastID = m_cast_count;
+ castData.SpellID = m_spellInfo->Id;
+ castData.CastFlags = castFlags;
+ castData.CastTime = GameTime::GetGameTimeMS();
- WriteSpellGoTargets(&data);
+ UpdateSpellCastDataTargets(castData);
- m_targets.Write(data);
+ m_targets.Write(castData.Target);
if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
- data << uint32(ASSERT_NOTNULL(m_caster->ToUnit())->GetPower((Powers)m_spellInfo->PowerType));
+ castData.RemainingPower = ASSERT_NOTNULL(m_caster->ToUnit())->GetPower(static_cast<Powers>(m_spellInfo->PowerType));
if (castFlags & CAST_FLAG_RUNE_LIST) // rune cooldowns list
{
+ castData.RemainingRunes = boost::in_place();
+
/// @todo There is a crash caused by a spell with CAST_FLAG_RUNE_LIST cast by a creature
//The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster
if (Player* player = m_caster->ToPlayer())
{
uint8 runeMaskInitial = m_runesState;
uint8 runeMaskAfterCast = player->GetRunesState();
- data << uint8(runeMaskInitial); // runes state before
- data << uint8(runeMaskAfterCast); // runes state after
+ castData.RemainingRunes->Start = runeMaskInitial; // runes state before
+ castData.RemainingRunes->Count = runeMaskAfterCast; // runes state after
+
for (uint8 i = 0; i < MAX_RUNES; ++i)
{
uint8 mask = (1 << i);
- if (mask & runeMaskInitial && !(mask & runeMaskAfterCast)) // usable before andon cooldown now...
+ if ((mask & runeMaskInitial) && !(mask & runeMaskAfterCast)) // usable before and on cooldown now...
{
// float casts ensure the division is performed on floats as we need float result
float baseCd = float(player->GetRuneBaseCooldown(i));
- data << uint8((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed
+ castData.RemainingRunes->Cooldowns.push_back(uint8((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255));
}
}
}
}
+
if (castFlags & CAST_FLAG_ADJUST_MISSILE)
{
- data << m_targets.GetElevation();
- data << uint32(m_delayMoment);
+ castData.MissileTrajectory = boost::in_place();
+ castData.MissileTrajectory->Pitch = m_targets.GetElevation();
+ castData.MissileTrajectory->TravelTime = m_delayMoment;
}
if (castFlags & CAST_FLAG_AMMO)
- WriteAmmoToPacket(&data);
-
- if (castFlags & CAST_FLAG_VISUAL_CHAIN)
{
- data << uint32(0);
- data << uint32(0);
- }
-
- if (m_targets.GetTargetMask() & TARGET_FLAG_DEST_LOCATION)
- {
- data << uint8(0);
+ castData.Ammo = boost::in_place();
+ UpdateSpellCastDataAmmo(*castData.Ammo);
}
// should be sent to self only
if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
{
if (Player* player = m_caster->GetAffectingPlayer())
- player->SendDirectMessage(&data);
+ player->SendDirectMessage(packet.Write());
+
+ // update nearby players (remove flag)
+ castData.CastFlags &= ~CAST_FLAG_POWER_LEFT_SELF;
+ castData.RemainingPower = boost::none;
+ m_caster->SendMessageToSet(packet.Write(), false);
}
else
- m_caster->SendMessageToSet(&data, true);
+ m_caster->SendMessageToSet(packet.Write(), true);
}
-void Spell::WriteAmmoToPacket(WorldPacket* data)
+void Spell::UpdateSpellCastDataAmmo(WorldPackets::Spells::SpellAmmo& ammo)
{
uint32 ammoInventoryType = 0;
uint32 ammoDisplayID = 0;
@@ -4291,13 +4301,16 @@ void Spell::WriteAmmoToPacket(WorldPacket* data)
}
}
- *data << uint32(ammoDisplayID);
- *data << uint32(ammoInventoryType);
+ ammo.DisplayID = ammoDisplayID;
+ ammo.InventoryType = ammoInventoryType;
}
/// Writes miss and hit targets for a SMSG_SPELL_GO packet
-void Spell::WriteSpellGoTargets(WorldPacket* data)
+void Spell::UpdateSpellCastDataTargets(WorldPackets::Spells::SpellCastData& data)
{
+ data.HitTargets = boost::in_place();
+ data.MissStatus = boost::in_place();
+
// This function also fill data for channeled spells:
// m_needAliveTargetMask req for stop channelig if one target die
for (TargetInfo& targetInfo : m_UniqueTargetInfo)
@@ -4305,53 +4318,31 @@ void Spell::WriteSpellGoTargets(WorldPacket* data)
if (targetInfo.EffectMask == 0) // No effect apply - all immuned add state
// possibly SPELL_MISS_IMMUNE2 for this??
targetInfo.MissCondition = SPELL_MISS_IMMUNE2;
- }
- // Hit and miss target counts are both uint8, that limits us to 255 targets for each
- // sending more than 255 targets crashes the client (since count sent would be wrong)
- // Spells like 40647 (with a huge radius) can easily reach this limit (spell might need
- // target conditions but we still need to limit the number of targets sent and keeping
- // correct count for both hit and miss).
+ if (targetInfo.MissCondition == SPELL_MISS_NONE) // Add only hits
+ {
+ data.HitTargets->push_back(targetInfo.TargetGUID);
- uint32 hit = 0;
- size_t hitPos = data->wpos();
- *data << (uint8)0; // placeholder
- for (auto ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end() && hit < 255; ++ihit)
- {
- if (ihit->MissCondition == SPELL_MISS_NONE) // Add only hits
+ m_channelTargetEffectMask |= targetInfo.EffectMask;
+ }
+ else // misses
{
- *data << uint64(ihit->TargetGUID);
- m_channelTargetEffectMask |= ihit->EffectMask;
- ++hit;
+ WorldPackets::Spells::SpellMissStatus missStatus;
+ missStatus.TargetGUID = targetInfo.TargetGUID;
+ missStatus.Reason = targetInfo.MissCondition;
+ if (targetInfo.MissCondition == SPELL_MISS_REFLECT)
+ missStatus.ReflectStatus = targetInfo.ReflectResult;
+
+ data.MissStatus->push_back(missStatus);
}
}
- for (auto ighit = m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end() && hit < 255; ++ighit)
- {
- *data << uint64(ighit->TargetGUID); // Always hits
- ++hit;
- }
+ for (GOTargetInfo const& targetInfo : m_UniqueGOTargetInfo)
+ data.HitTargets->push_back(targetInfo.TargetGUID); // Always hits
- uint32 miss = 0;
- size_t missPos = data->wpos();
- *data << (uint8)0; // placeholder
- for (auto ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end() && miss < 255; ++ihit)
- {
- if (ihit->MissCondition != SPELL_MISS_NONE) // Add only miss
- {
- *data << uint64(ihit->TargetGUID);
- *data << uint8(ihit->MissCondition);
- if (ihit->MissCondition == SPELL_MISS_REFLECT)
- *data << uint8(ihit->ReflectResult);
- ++miss;
- }
- }
// Reset m_needAliveTargetMask for non channeled spell
if (!m_spellInfo->IsChanneled())
m_channelTargetEffectMask = 0;
-
- data->put<uint8>(hitPos, (uint8)hit);
- data->put<uint8>(missPos, (uint8)miss);
}
void Spell::SendLogExecute()