aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIntel <chemicstry@gmail.com>2014-12-02 00:07:36 +0200
committerIntel <chemicstry@gmail.com>2014-12-02 00:07:36 +0200
commit713488596f9cf726f6927c2a98a750b1ab3b1ee1 (patch)
treeef11200a51db3743acc59bc349e8e55521c39ad6 /src
parentdf2514f0444a1b39f07ed63208f5db3ea4eb5c6d (diff)
Core/Packets: Convert SMSG_SPELL_START and SMSG_SPELL_GO to JAM structures
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Server/Packets/SpellPackets.cpp280
-rw-r--r--src/server/game/Server/Packets/SpellPackets.h118
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/Spells/Spell.cpp206
-rw-r--r--src/server/game/Spells/Spell.h10
5 files changed, 451 insertions, 165 deletions
diff --git a/src/server/game/Server/Packets/SpellPackets.cpp b/src/server/game/Server/Packets/SpellPackets.cpp
index 7c536363335..97c98e5e145 100644
--- a/src/server/game/Server/Packets/SpellPackets.cpp
+++ b/src/server/game/Server/Packets/SpellPackets.cpp
@@ -245,168 +245,170 @@ void WorldPackets::Spells::SpellCastRequest::Read()
}
}
-WorldPacket const* WorldPackets::Spells::SendSpellStart::Write()
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::TargetLocation const& targetLocation)
{
- uint32 castFlags = CAST_FLAG_HAS_TRAJECTORY;
+ data << targetLocation.Transport;
+ // data << targetLocation.Location.PositionXYZStream();
+ data << targetLocation.Location.m_positionX;
+ data << targetLocation.Location.m_positionY;
+ data << targetLocation.Location.m_positionZ;
+ return data;
+}
- if ((spell->IsTriggered() && !spell->m_spellInfo->IsAutoRepeatRangedSpell()) || spell->GetTriggeredByAuraSpell())
- castFlags |= CAST_FLAG_PENDING;
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellTargetData const& spellTargetData)
+{
+ data.WriteBits(spellTargetData.Flags, 21);
+ data.WriteBit(spellTargetData.SrcLocation.HasValue);
+ data.WriteBit(spellTargetData.DstLocation.HasValue);
+ data.WriteBit(spellTargetData.Orientation.HasValue);
+ data.WriteBits(spellTargetData.Name.size(), 7);
+ data.FlushBits();
- 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;
+ data << spellTargetData.Unit;
+ data << spellTargetData.Item;
- if (spell->m_spellInfo->RuneCostID && spell->m_spellInfo->PowerType == POWER_RUNES)
- castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it
+ if (spellTargetData.SrcLocation.HasValue)
+ data << spellTargetData.SrcLocation.Value;
+ if (spellTargetData.DstLocation.HasValue)
+ data << spellTargetData.DstLocation.Value;
- 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());
+ if (spellTargetData.Orientation.HasValue)
+ data << spellTargetData.Orientation.Value;
- uint32 HitTargets = 0;
- _worldPacket << HitTargets;
- uint32 MissTargets = 0;
- _worldPacket << MissTargets;
- uint32 MissStatus = 0;
- _worldPacket << MissStatus;
+ data.WriteString(spellTargetData.Name);
- _worldPacket.ResetBitPos();
+ return data;
+}
- _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;
- }
+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)
+ return data;
+}
- //if (HasOrientation)
- // _worldPacket << float(0);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellPowerData const& spellPowerData)
+{
+ data << spellPowerData.Cost;
+ data << spellPowerData.Type;
+ return data;
+}
- _worldPacket.WriteString(spell->m_targets.GetTargetString());
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::RuneData const& runeData)
+{
+ data << runeData.Start;
+ data << runeData.Count;
- uint32 SpellPowerData = 0;
- _worldPacket << SpellPowerData;
+ data.WriteBits(runeData.Cooldowns.size(), 3);
+ data.FlushBits();
-
- _worldPacket << uint32(0); // TravelTime
- _worldPacket << spell->m_targets.GetElevation();
+ for (uint8 cd : runeData.Cooldowns)
+ data << cd;
- _worldPacket << uint32(0); // Ammo DisplayID
- _worldPacket << uint8(0); // Ammo InventoryType
-
- _worldPacket << uint8(0); // DestLocSpellCastIndex
+ return data;
+}
- uint32 TargetPoints = 0;
- _worldPacket << TargetPoints;
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::MissileTrajectoryResult const& missileTrajectory)
+{
+ data << missileTrajectory.TravelTime;
+ data << missileTrajectory.Pitch;
+ return data;
+}
- _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
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellAmmo const& spellAmmo)
+{
+ data << spellAmmo.DisplayID;
+ data << spellAmmo.InventoryType;
+ return data;
+}
- /*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
- }*/
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::ProjectileVisualData const& projectileVisual)
+{
+ data << projectileVisual.ID[0];
+ data << projectileVisual.ID[1];
+ return data;
+}
- _worldPacket.ResetBitPos();
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::CreatureImmunities const& immunities)
+{
+ data << immunities.School;
+ data << immunities.Value;
+ return data;
+}
- _worldPacket.WriteBits(0, 18); // CastFlagsEx
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellHealPrediction const& spellPred)
+{
+ data << spellPred.Points;
+ data << spellPred.Type;
+ data << spellPred.BeaconGUID;
+ return data;
+}
- bool HasRuneData = false;
- bool HasProjectileVisual = false;
-
- _worldPacket.WriteBit(HasRuneData);
- _worldPacket.WriteBit(HasProjectileVisual);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastData const& spellCastData)
+{
+ data << spellCastData.CasterGUID;
+ data << spellCastData.CasterUnit;
+ data << spellCastData.CastID;
+ data << spellCastData.SpellID;
+ data << spellCastData.CastFlags;
+ data << 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 << spellCastData.DestLocSpellCastIndex;
+ data << uint32(spellCastData.TargetPoints.size());
+ data << spellCastData.Immunities;
+ data << spellCastData.Predict;
+
+ for (ObjectGuid const& target : spellCastData.HitTargets)
+ data << target;
+
+ 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, 18);
+ data.WriteBit(spellCastData.RemainingRunes.HasValue);
+ data.WriteBit(spellCastData.ProjectileVisual.HasValue);
+ data.FlushBits();
- /*if (HasRuneData)
- {
- _worldPacket << uint8(0); // Start
- _worldPacket << uint8(0); // Count
- _worldPacket.ResetBitPos();
+ if (spellCastData.RemainingRunes.HasValue)
+ data << spellCastData.RemainingRunes.Value;
- uint32 CooldownCount = 0;
- _worldPacket.WriteBits(CooldownCount, 3);
- for (uint32 i = 0; i < CooldownCount; ++i)
- {
- _worldPacket << uint8(0); // Cooldowns
- }
- }*/
+ if (spellCastData.ProjectileVisual.HasValue)
+ data << spellCastData.ProjectileVisual.Value;
+}
- /*if (HasProjectileVisual)
- {
- for (uint32 i = 0; i < 2; ++i)
- {
- _worldPacket << uint32(0); // Id
- }
- }*/
+WorldPacket const* WorldPackets::Spells::SpellStart::Write()
+{
+ _worldPacket << Cast;
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Spells::SpellGo::Write()
+{
+ _worldPacket << Cast;
+
+ _worldPacket.WriteBit(LogData.HasValue);
+ _worldPacket.FlushBits();
+
+ if (LogData.HasValue)
+ _worldPacket << LogData.Value;
return &_worldPacket;
}
diff --git a/src/server/game/Server/Packets/SpellPackets.h b/src/server/game/Server/Packets/SpellPackets.h
index e9ae7ada77b..6e95efd63f2 100644
--- a/src/server/game/Server/Packets/SpellPackets.h
+++ b/src/server/game/Server/Packets/SpellPackets.h
@@ -154,15 +154,116 @@ namespace WorldPackets
MovementInfo movementInfo;
};
+
+ struct TargetLocation
+ {
+ ObjectGuid Transport;
+ Position Location;
+ };
+
+ struct SpellTargetData
+ {
+ uint32 Flags = 0;
+ ObjectGuid Unit;
+ ObjectGuid Item;
+ Optional<TargetLocation> SrcLocation;
+ Optional<TargetLocation> DstLocation;
+ Optional<float> Orientation; // Not found in JAM structures
+ std::string Name;
+ };
+
+ struct SpellMissStatus
+ {
+ uint8 Reason = 0;
+ uint8 ReflectStatus = 0;
+ };
+
+ struct SpellPowerData
+ {
+ int32 Cost = 0;
+ int8 Type = 0;
+ };
+
+ struct RuneData
+ {
+ uint8 Start = 0;
+ uint8 Count = 0;
+ std::vector<uint8> Cooldowns;
+ };
+
+ struct MissileTrajectoryResult
+ {
+ uint32 TravelTime = 0;
+ float Pitch = 0.0f;
+ };
+
+ struct SpellAmmo
+ {
+ int32 DisplayID = 0;
+ int8 InventoryType = 0;
+ };
+
+ struct ProjectileVisualData
+ {
+ int32 ID[2];
+ };
+
+ struct CreatureImmunities
+ {
+ uint32 School = 0;
+ uint32 Value = 0;
+ };
+
+ struct SpellHealPrediction
+ {
+ ObjectGuid BeaconGUID;
+ uint32 Points = 0;
+ uint8 Type = 0;
+ };
+
+ struct SpellCastData
+ {
+ ObjectGuid CasterGUID;
+ ObjectGuid CasterUnit;
+ uint8 CastID = 0;
+ int32 SpellID = 0;
+ uint32 CastFlags = 0;
+ uint32 CastFlagsEx = 0;
+ uint32 CastTime = 0;
+ std::vector<ObjectGuid> HitTargets;
+ std::vector<ObjectGuid> MissTargets;
+ std::vector<SpellMissStatus> MissStatus;
+ SpellTargetData Target;
+ std::vector<SpellPowerData> RemainingPower;
+ Optional<RuneData> RemainingRunes;
+ MissileTrajectoryResult MissileTrajectory;
+ SpellAmmo Ammo;
+ Optional<ProjectileVisualData> ProjectileVisual;
+ uint8 DestLocSpellCastIndex = 0;
+ std::vector<TargetLocation> TargetPoints;
+ CreatureImmunities Immunities;
+ SpellHealPrediction Predict;
+ };
+
+ class SpellGo final : public ServerPacket
+ {
+ public:
+ SpellGo() : ServerPacket(SMSG_SPELL_GO) { }
+
+ WorldPacket const* Write() override;
+
+ Optional<SpellCastLogData> LogData;
+ SpellCastData Cast;
+ };
- class SendSpellStart final : public ServerPacket
+ class SpellStart final : public ServerPacket
{
public:
- SendSpellStart() : ServerPacket(SMSG_SPELL_START) { }
+ SpellStart() : ServerPacket(SMSG_SPELL_START) { }
WorldPacket const* Write() override;
- Spell* spell;
+ SpellCastData Cast;
};
class LearnedSpells final : public ServerPacket
@@ -227,6 +328,17 @@ namespace WorldPackets
}
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastLogData const& spellCastLogData);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::TargetLocation const& targetLocation);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellTargetData const& spellTargetData);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellMissStatus const& spellMissStatus);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellPowerData const& spellPowerData);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::RuneData const& runeData);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::MissileTrajectoryResult const& missileTrajectory);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellAmmo const& spellAmmo);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::ProjectileVisualData const& projectileVisual);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::CreatureImmunities const& immunities);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellHealPrediction const& spellPred);
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastData const& spellCastData);
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellModifierData const& spellModifierData);
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellModifier const& spellModifier);
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 79671b85892..f8df17eb3f7 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -1315,7 +1315,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_DELAYED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILED_OTHER, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILURE, STATUS_NEVER);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_GO, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_GO, STATUS_NEVER);
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);
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 303a885c39c..a056ca958fd 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -196,9 +196,41 @@ 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.Unit = m_objectTargetGUID;
+
+ if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM) && m_itemTarget)
+ data.Item = m_itemTarget->GetGUID();
+
+ if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION)
+ {
+ WorldPackets::Spells::TargetLocation& target = data.SrcLocation.Value;
+ target.Transport = m_src._transportGUID; // relative position guid here - transport for example
+ if (!m_src._transportGUID.IsEmpty())
+ target.Location = m_src._transportOffset;
+ else
+ target.Location = m_src._position;
+ data.SrcLocation.HasValue = true;
+ }
+
+ if (m_targetMask & TARGET_FLAG_DEST_LOCATION)
+ {
+ WorldPackets::Spells::TargetLocation& target = data.DstLocation.Value;
+ target.Transport = m_dst._transportGUID; // relative position guid here - transport for example
+ if (!m_dst._transportGUID.IsEmpty())
+ target.Location = m_dst._transportOffset;
+ else
+ target.Location = m_dst._position;
+ data.DstLocation.HasValue = true;
+ }
+
+ if (m_targetMask & TARGET_FLAG_STRING)
+ data.Name = m_strTarget;
+ /*data << uint32(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();
@@ -230,7 +262,7 @@ void SpellCastTargets::Write(ByteBuffer& data)
}
if (m_targetMask & TARGET_FLAG_STRING)
- data << m_strTarget;
+ data << m_strTarget;*/
}
ObjectGuid SpellCastTargets::GetOrigUnitTargetGUID() const
@@ -3849,7 +3881,7 @@ void Spell::SendSpellStart()
if (!IsNeedSendToClient())
return;
- //TC_LOG_DEBUG("spells", "Sending SMSG_SPELL_START id=%u", m_spellInfo->Id);
+ TC_LOG_DEBUG("spells", "Sending SMSG_SPELL_START id=%u", m_spellInfo->Id);
uint32 castFlags = CAST_FLAG_HAS_TRAJECTORY;
@@ -3864,9 +3896,80 @@ void Spell::SendSpellStart()
if (m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNES)
castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it
- WorldPackets::Spells::SendSpellStart spellStart;
- spellStart.spell = this;
+ WorldPackets::Spells::SpellStart packet;
+ WorldPackets::Spells::SpellCastData& castData = packet.Cast;
+
+ if (m_CastItem)
+ castData.CasterGUID = m_CastItem->GetGUID();
+ else
+ castData.CasterGUID = m_caster->GetGUID();
+
+ castData.CasterUnit = m_caster->GetGUID();
+ castData.CastID = m_cast_count; // pending spell cast?
+ castData.SpellID = m_spellInfo->Id;
+ castData.CastFlags = castFlags;
+ castData.CastTime = m_casttime;
+
+ m_targets.Write(castData.Target);
+
+ if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
+ {
+ /// @todo Implement multiple power types
+ WorldPackets::Spells::SpellPowerData powerData;
+ powerData.Type = m_spellInfo->PowerType;
+ powerData.Cost = m_caster->GetPower((Powers)m_spellInfo->PowerType);
+ castData.RemainingPower.push_back(powerData);
+ }
+
+ if (castFlags & CAST_FLAG_RUNE_LIST) // rune cooldowns list
+ {
+ WorldPackets::Spells::RuneData& runeData = castData.RemainingRunes.Value;
+ //TODO: There is a crash caused by a spell with CAST_FLAG_RUNE_LIST casted by a creature
+ //The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster
+ if (Player* player = m_caster->ToPlayer())
+ {
+ runeData.Start = m_runesState; // runes state before
+ runeData.Count = player->GetRunesState(); // runes state after
+ for (uint8 i = 0; i < MAX_RUNES; ++i)
+ {
+ // float casts ensure the division is performed on floats as we need float result
+ float baseCd = float(player->GetRuneBaseCooldown(i));
+ runeData.Cooldowns.push_back((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed
+ }
+ }
+ else
+ {
+ runeData.Start = 0;
+ runeData.Count = 0;
+ for (uint8 i = 0; i < MAX_RUNES; ++i)
+ runeData.Cooldowns.push_back(0);
+ }
+
+ castData.RemainingRunes.HasValue = true;
+ }
+
+ /** @todo implement spell ammo packet data
+ if (castFlags & CAST_FLAG_PROJECTILE)
+ {
+ castData.Ammo.DisplayID = 0;
+ castData.Ammo.InventoryType = 0;
+ }**/
+
+ /** @todo implement spell immunity packet data
+ if (castFlags & CAST_FLAG_IMMUNITY)
+ {
+ castData.Immunities.School = 0;
+ castData.Immunities.Value = 0;
+ }**/
+ /** @todo implement heal prediction packet data
+ if (castFlags & CAST_FLAG_HEAL_PREDICTION)
+ {
+ castData.Predict.BeconGUID = ??
+ castData.Predict.Points = 0;
+ castData.Predict.Type = 0;
+ }**/
+
/*WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2));
if (m_CastItem)
data << m_CastItem->GetPackGUID();
@@ -3929,7 +4032,7 @@ void Spell::SendSpellStart()
// data.append(0);
}*/
- m_caster->SendMessageToSet(spellStart.Write(), true);
+ m_caster->SendMessageToSet(packet.Write(), true);
}
void Spell::SendSpellGo()
@@ -3938,7 +4041,7 @@ void Spell::SendSpellGo()
if (!IsNeedSendToClient())
return;
- //TC_LOG_DEBUG("spells", "Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id);
+ TC_LOG_DEBUG("spells", "Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id);
uint32 castFlags = CAST_FLAG_UNKNOWN_9;
@@ -3970,7 +4073,68 @@ 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)
+ castData.CasterGUID = m_CastItem->GetGUID();
+ else
+ castData.CasterGUID = m_caster->GetGUID();
+
+ castData.CasterUnit = m_caster->GetGUID();
+ castData.CastID = m_cast_count; // pending spell cast?
+ castData.SpellID = m_spellInfo->Id;
+ castData.CastFlags = castFlags;
+ castData.CastTime = getMSTime();
+
+ /// @todo implement multiple targets
+ if (m_targets.GetUnitTarget())
+ castData.HitTargets.push_back(m_targets.GetUnitTargetGUID());
+
+ m_targets.Write(castData.Target);
+
+ if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
+ {
+ /// @todo Implement multiple power types
+ WorldPackets::Spells::SpellPowerData powerData;
+ powerData.Type = m_spellInfo->PowerType;
+ powerData.Cost = m_caster->GetPower((Powers)m_spellInfo->PowerType);
+ castData.RemainingPower.push_back(powerData);
+ }
+
+ if (castFlags & CAST_FLAG_RUNE_LIST) // rune cooldowns list
+ {
+ WorldPackets::Spells::RuneData& runeData = castData.RemainingRunes.Value;
+ //TODO: There is a crash caused by a spell with CAST_FLAG_RUNE_LIST casted by a creature
+ //The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster
+ if (Player* player = m_caster->ToPlayer())
+ {
+ runeData.Start = m_runesState; // runes state before
+ runeData.Count = player->GetRunesState(); // runes state after
+ for (uint8 i = 0; i < MAX_RUNES; ++i)
+ {
+ // float casts ensure the division is performed on floats as we need float result
+ float baseCd = float(player->GetRuneBaseCooldown(i));
+ runeData.Cooldowns.push_back((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed
+ }
+ }
+ else
+ {
+ runeData.Start = 0;
+ runeData.Count = 0;
+ for (uint8 i = 0; i < MAX_RUNES; ++i)
+ runeData.Cooldowns.push_back(0);
+ }
+
+ castData.RemainingRunes.HasValue = true;
+ }
+
+ if (castFlags & CAST_FLAG_ADJUST_MISSILE)
+ {
+ castData.MissileTrajectory.TravelTime = m_delayMoment;
+ castData.MissileTrajectory.Pitch = m_targets.GetElevation();
+ }
+ /*WorldPacket data(SMSG_SPELL_GO, 50); // guess size
if (m_CastItem)
data << m_CastItem->GetPackGUID();
@@ -3986,7 +4150,7 @@ void Spell::SendSpellGo()
WriteSpellGoTargets(&data);
- m_targets.Write(data);
+ //m_targets.Write(data);
if (castFlags & CAST_FLAG_POWER_LEFT_SELF)
data << uint32(m_caster->GetPower((Powers)m_spellInfo->PowerType));
@@ -4034,7 +4198,7 @@ void Spell::SendSpellGo()
if (m_targets.GetTargetMask() & TARGET_FLAG_EXTRA_TARGETS)
{
data << uint32(0); // Extra targets count
- /*
+
for (uint8 i = 0; i < count; ++i)
{
data << float(0); // Target Position X
@@ -4042,10 +4206,10 @@ void Spell::SendSpellGo()
data << float(0); // Target Position Z
data << uint64(0); // Target Guid
}
- */
- }
+
+ }*/
- m_caster->SendMessageToSet(&data, true);
+ m_caster->SendMessageToSet(packet.Write(), true);
}
/// Writes miss and hit targets for a SMSG_SPELL_GO packet
@@ -4365,7 +4529,7 @@ void Spell::TakeCastItem()
bool expendable = false;
bool withoutCharges = false;
- for (uint32 i = 0; i < proto->Effects.size(); ++i)
+ for (int i = 0; i < proto->Effects.size(); ++i)
{
// item has limited charges
if (proto->Effects[i].Charges)
@@ -4607,7 +4771,7 @@ void Spell::TakeReagents()
// if CastItem is also spell reagent
if (castItemTemplate && castItemTemplate->ItemId == itemid)
{
- for (uint32 s = 0; s < castItemTemplate->Effects.size(); ++s)
+ for (int s = 0; s < castItemTemplate->Effects.size(); ++s)
{
// CastItem will be used up and does not count as reagent
int32 charges = m_CastItem->GetSpellCharges(s);
@@ -6343,15 +6507,15 @@ SpellCastResult Spell::CheckItems()
case SPELL_EFFECT_CREATE_MANA_GEM:
{
uint32 item_id = effect->ItemType;
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item_id);
+ ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item_id);
- if (!proto)
+ if (!pProto)
return SPELL_FAILED_ITEM_AT_MAX_CHARGES;
- if (Item* item = player->GetItemByEntry(item_id))
+ if (Item* pitem = player->GetItemByEntry(item_id))
{
- for (uint32 x = 0; x < proto->Effects.size(); ++x)
- if (proto->Effects[x].Charges != 0 && item->GetSpellCharges(x) == proto->Effects[x].Charges)
+ for (int x = 0; x < pProto->Effects.size(); ++x)
+ if (pProto->Effects[x].Charges != 0 && pitem->GetSpellCharges(x) == pProto->Effects[x].Charges)
return SPELL_FAILED_ITEM_AT_MAX_CHARGES;
}
break;
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 8accaf896d0..33e4923d2f1 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -25,6 +25,14 @@
#include "SpellInfo.h"
#include "PathGenerator.h"
+namespace WorldPackets
+{
+ namespace Spells
+ {
+ struct SpellTargetData;
+ }
+}
+
class Unit;
class Player;
class GameObject;
@@ -103,7 +111,7 @@ class SpellCastTargets
~SpellCastTargets();
void Read(ByteBuffer& data, Unit* caster);
- void Write(ByteBuffer& data);
+ void Write(WorldPackets::Spells::SpellTargetData& data);
uint32 GetTargetMask() const { return m_targetMask; }
void SetTargetMask(uint32 newMask) { m_targetMask = newMask; }