Core/Packets: Update and enable CMSG_USE_ITEM

Ref #14115
This commit is contained in:
Duarte Duarte
2015-02-12 02:37:42 +00:00
parent 6678635cc7
commit 20aa605485
10 changed files with 93 additions and 128 deletions
+6 -6
View File
@@ -8316,7 +8316,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
}
}
void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex)
void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 castCount, uint32 misc)
{
ItemTemplate const* proto = item->GetTemplate();
// special learning case
@@ -8337,7 +8337,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE);
spell->m_CastItem = item;
spell->m_cast_count = cast_count; //set count of casts
spell->m_cast_count = castCount; //set count of casts
spell->SetSpellValue(SPELLVALUE_BASE_POINT0, learning_spell_id);
spell->prepare(&targets);
return;
@@ -8365,8 +8365,8 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
Spell* spell = new Spell(this, spellInfo, (count > 0) ? TRIGGERED_FULL_MASK : TRIGGERED_NONE);
spell->m_CastItem = item;
spell->m_cast_count = cast_count; // set count of casts
spell->m_misc.Data = glyphIndex; // glyph index
spell->m_cast_count = castCount; // set count of casts
spell->m_misc.Data = misc;
spell->prepare(&targets);
++count;
@@ -8393,8 +8393,8 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
Spell* spell = new Spell(this, spellInfo, (count > 0) ? TRIGGERED_FULL_MASK : TRIGGERED_NONE);
spell->m_CastItem = item;
spell->m_cast_count = cast_count; // set count of casts
spell->m_misc.Data = glyphIndex; // glyph index
spell->m_cast_count = castCount; // set count of casts
spell->m_misc.Data = misc; // glyph index
spell->prepare(&targets);
++count;
+1 -1
View File
@@ -2313,7 +2313,7 @@ class Player : public Unit, public GridObject<Player>
void ApplyEquipSpell(SpellInfo const* spellInfo, Item* item, bool apply, bool form_change = false);
void UpdateEquipSpellsAtFormChange();
void CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx);
void CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex);
void CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 castCount, uint32 misc);
void CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 procVictim, uint32 procEx, Item* item, ItemTemplate const* proto);
void SendEquipmentSetList();
+3 -3
View File
@@ -1578,12 +1578,12 @@ void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket)
ObjectGuid guid;
uint32 spellId;
float elevation, speed;
float pitch, speed;
float curX, curY, curZ;
float targetX, targetY, targetZ;
uint8 moveStop;
recvPacket >> guid >> spellId >> elevation >> speed;
recvPacket >> guid >> spellId >> pitch >> speed;
recvPacket >> curX >> curY >> curZ;
recvPacket >> targetX >> targetY >> targetZ;
recvPacket >> moveStop;
@@ -1604,7 +1604,7 @@ void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket)
pos.Relocate(targetX, targetY, targetZ);
spell->m_targets.ModDst(pos);
spell->m_targets.SetElevation(elevation);
spell->m_targets.SetPitch(pitch);
spell->m_targets.SetSpeed(speed);
if (moveStop)
+28 -88
View File
@@ -38,121 +38,63 @@
#include "SpellPackets.h"
#include "GameObjectPackets.h"
void WorldSession::HandleClientCastFlags(WorldPacket& recvPacket, uint8 castFlags, SpellCastTargets& targets)
void WorldSession::HandleUseItemOpcode(WorldPackets::Spells::UseItem& packet)
{
// some spell cast packet including more data (for projectiles?)
if (castFlags & 0x02)
{
// not sure about these two
float elevation, speed;
recvPacket >> elevation;
recvPacket >> speed;
targets.SetElevation(elevation);
targets.SetSpeed(speed);
uint8 hasMovementData;
recvPacket >> hasMovementData;
//if (hasMovementData)
// HandleMovementOpcodes(recvPacket);
}
else if (castFlags & 0x8) // Archaeology
{
uint32 count, entry, usedCount;
uint8 type;
recvPacket >> count;
for (uint32 i = 0; i < count; ++i)
{
recvPacket >> type;
switch (type)
{
case 2: // Keystones
recvPacket >> entry; // Item id
recvPacket >> usedCount; // Item count
break;
case 1: // Fragments
recvPacket >> entry; // Currency id
recvPacket >> usedCount; // Currency count
break;
}
}
}
}
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
{
/// @todo add targets.read() check
Player* pUser = _player;
Player* user = _player;
// ignore for remote control state
if (pUser->m_mover != pUser)
if (user->m_mover != user)
return;
uint8 bagIndex, slot, castFlags;
uint8 castCount; // next cast if exists (single or not)
ObjectGuid itemGUID;
uint32 glyphIndex; // something to do with glyphs?
uint32 spellId; // cast spell id
recvPacket >> bagIndex >> slot >> castCount >> spellId >> itemGUID >> glyphIndex >> castFlags;
if (glyphIndex >= MAX_GLYPH_SLOT_INDEX)
Item* item = user->GetUseableItemByPos(packet.PackSlot, packet.Slot);
if (!item)
{
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
user->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
return;
}
Item* pItem = pUser->GetUseableItemByPos(bagIndex, slot);
if (!pItem)
if (item->GetGUID() != packet.CastItem)
{
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
user->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
return;
}
if (pItem->GetGUID() != itemGUID)
{
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
return;
}
TC_LOG_DEBUG("network", "WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, castCount: %u, spellId: %u, Item: %u, glyphIndex: %u, data length = %i", bagIndex, slot, castCount, spellId, pItem->GetEntry(), glyphIndex, (uint32)recvPacket.size());
ItemTemplate const* proto = pItem->GetTemplate();
ItemTemplate const* proto = item->GetTemplate();
if (!proto)
{
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL);
user->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, item, NULL);
return;
}
// some item classes can be used only in equipped state
if (proto->GetInventoryType() != INVTYPE_NON_EQUIP && !pItem->IsEquipped())
if (proto->GetInventoryType() != INVTYPE_NON_EQUIP && !item->IsEquipped())
{
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL);
user->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, item, NULL);
return;
}
InventoryResult msg = pUser->CanUseItem(pItem);
InventoryResult msg = user->CanUseItem(item);
if (msg != EQUIP_ERR_OK)
{
pUser->SendEquipError(msg, pItem, NULL);
user->SendEquipError(msg, item, NULL);
return;
}
// only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB)
if (proto->GetClass() == ITEM_CLASS_CONSUMABLE && !(proto->GetFlags() & ITEM_PROTO_FLAG_USEABLE_IN_ARENA) && pUser->InArena())
if (proto->GetClass() == ITEM_CLASS_CONSUMABLE && !(proto->GetFlags() & ITEM_PROTO_FLAG_USEABLE_IN_ARENA) && user->InArena())
{
pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, pItem, NULL);
user->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, item, NULL);
return;
}
// don't allow items banned in arena
if (proto->GetFlags() & ITEM_PROTO_FLAG_NOT_USEABLE_IN_ARENA && pUser->InArena())
if (proto->GetFlags() & ITEM_PROTO_FLAG_NOT_USEABLE_IN_ARENA && user->InArena())
{
pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, pItem, NULL);
user->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH, item, NULL);
return;
}
if (pUser->IsInCombat())
if (user->IsInCombat())
{
for (uint32 i = 0; i < proto->Effects.size(); ++i)
{
@@ -160,7 +102,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
{
if (!spellInfo->CanBeUsedInCombat())
{
pUser->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT, pItem, NULL);
user->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT, item, NULL);
return;
}
}
@@ -168,24 +110,22 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
}
// check also BIND_WHEN_PICKED_UP and BIND_QUEST_ITEM for .additem or .additemset case by GM (not binded at adding to inventory)
if (pItem->GetTemplate()->GetBonding() == BIND_WHEN_USE || pItem->GetTemplate()->GetBonding() == BIND_WHEN_PICKED_UP || pItem->GetTemplate()->GetBonding() == BIND_QUEST_ITEM)
if (item->GetTemplate()->GetBonding() == BIND_WHEN_USE || item->GetTemplate()->GetBonding() == BIND_WHEN_PICKED_UP || item->GetTemplate()->GetBonding() == BIND_QUEST_ITEM)
{
if (!pItem->IsSoulBound())
if (!item->IsSoulBound())
{
pItem->SetState(ITEM_CHANGED, pUser);
pItem->SetBinding(true);
item->SetState(ITEM_CHANGED, user);
item->SetBinding(true);
}
}
SpellCastTargets targets;
targets.Read(recvPacket, pUser);
HandleClientCastFlags(recvPacket, castFlags, targets);
SpellCastTargets targets(user, packet.Cast);
// Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state.
if (!sScriptMgr->OnItemUse(pUser, pItem, targets))
if (!sScriptMgr->OnItemUse(user, item, targets))
{
// no script or script not process request by self
pUser->CastItemUseSpell(pItem, targets, castCount, glyphIndex);
user->CastItemUseSpell(item, targets, packet.Cast.CastID, packet.Cast.Misc);
}
}
@@ -366,7 +306,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::CastSpell& cast)
return;
// client provided targets
SpellCastTargets targets(caster, cast.Cast.Target);
SpellCastTargets targets(caster, cast.Cast);
// auto-selection buff level base at target level (in spellInfo)
if (targets.GetUnitTarget())
@@ -223,6 +223,15 @@ void WorldPackets::Spells::PetCastSpell::Read()
_worldPacket >> Cast;
}
void WorldPackets::Spells::UseItem::Read()
{
_worldPacket >> PackSlot;
_worldPacket >> Slot;
_worldPacket >> CastItem;
_worldPacket >> Cast;
}
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::TargetLocation const& targetLocation)
{
data << targetLocation.Transport;
+15 -4
View File
@@ -188,8 +188,8 @@ namespace WorldPackets
struct SpellCastRequest
{
uint8 CastID = 0;
uint32 SpellID = 0;
uint32 Misc = 0;
int32 SpellID = 0;
int32 Misc = 0;
uint8 SendCastFlags = 0;
SpellTargetData Target;
MissileTrajectoryRequest MissileTrajectory;
@@ -201,7 +201,6 @@ namespace WorldPackets
class CastSpell final : public ClientPacket
{
public:
CastSpell(WorldPacket&& packet) : ClientPacket(CMSG_CAST_SPELL, std::move(packet)) { }
void Read() override;
@@ -212,7 +211,6 @@ namespace WorldPackets
class PetCastSpell final : public ClientPacket
{
public:
PetCastSpell(WorldPacket&& packet) : ClientPacket(CMSG_PET_CAST_SPELL, std::move(packet)) { }
void Read() override;
@@ -221,6 +219,19 @@ namespace WorldPackets
SpellCastRequest Cast;
};
class UseItem final : public ClientPacket
{
public:
UseItem(WorldPacket&& packet) : ClientPacket(CMSG_USE_ITEM, std::move(packet)) { }
void Read() override;
uint8 PackSlot;
uint8 Slot;
ObjectGuid CastItem;
SpellCastRequest Cast;
};
struct SpellMissStatus
{
uint8 Reason = 0;
+1 -1
View File
@@ -886,7 +886,7 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_USED_FOLLOW, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_USE_CRITTER_ITEM, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_USE_EQUIPMENT_SET, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleEquipmentSetUse );
DEFINE_OPCODE_HANDLER_OLD(CMSG_USE_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUseItemOpcode );
DEFINE_HANDLER(CMSG_USE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::UseItem, &WorldSession::HandleUseItemOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_USE_TOY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_HANDLER(CMSG_VIOLENCE_LEVEL, STATUS_AUTHED, PROCESS_INPLACE, WorldPackets::Misc::ViolenceLevel, &WorldSession::HandleViolenceLevel);
DEFINE_OPCODE_HANDLER_OLD(CMSG_VOICE_ADD_IGNORE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+2 -1
View File
@@ -281,6 +281,7 @@ namespace WorldPackets
class CancelAura;
class CastSpell;
class PetCastSpell;
class UseItem;
class SetActionButton;
}
@@ -997,7 +998,7 @@ class WorldSession
void HandleAttackStopOpcode(WorldPackets::Combat::AttackStop& packet);
void HandleSetSheathedOpcode(WorldPacket& recvPacket);
void HandleUseItemOpcode(WorldPacket& recvPacket);
void HandleUseItemOpcode(WorldPackets::Spells::UseItem& packet);
void HandleOpenItemOpcode(WorldPacket& recvPacket);
void HandleCastSpellOpcode(WorldPackets::Spells::CastSpell& castRequest);
void HandleCancelCastOpcode(WorldPacket& recvPacket);
+21 -18
View File
@@ -110,43 +110,46 @@ void SpellDestination::RelocateOffset(Position const& offset)
}
SpellCastTargets::SpellCastTargets() : m_targetMask(0), m_objectTarget(nullptr), m_itemTarget(nullptr),
m_itemTargetEntry(0), m_elevation(0.0f), m_speed(0.0f)
m_itemTargetEntry(0), m_pitch(0.0f), m_speed(0.0f)
{
}
SpellCastTargets::SpellCastTargets(Unit* caster, WorldPackets::Spells::SpellTargetData const& spellTargetData) :
m_targetMask(spellTargetData.Flags), m_objectTarget(nullptr), m_itemTarget(nullptr),
m_objectTargetGUID(spellTargetData.Unit), m_itemTargetGUID(spellTargetData.Item),
m_itemTargetEntry(0), m_elevation(0.0f), m_speed(0.0f), m_strTarget(spellTargetData.Name)
SpellCastTargets::SpellCastTargets(Unit* caster, WorldPackets::Spells::SpellCastRequest const& spellCastRequest) :
m_targetMask(spellCastRequest.Target.Flags), m_objectTarget(nullptr), m_itemTarget(nullptr),
m_objectTargetGUID(spellCastRequest.Target.Unit), m_itemTargetGUID(spellCastRequest.Target.Item),
m_itemTargetEntry(0), m_pitch(0.0f), m_speed(0.0f), m_strTarget(spellCastRequest.Target.Name)
{
if (spellTargetData.SrcLocation.HasValue)
if (spellCastRequest.Target.SrcLocation.HasValue)
{
m_src._transportGUID = spellTargetData.SrcLocation.Value.Transport;
m_src._transportGUID = spellCastRequest.Target.SrcLocation.Value.Transport;
Position* pos;
if (!m_src._transportGUID.IsEmpty())
pos = &m_src._transportOffset;
else
pos = &m_src._position;
pos->Relocate(spellTargetData.SrcLocation.Value.Location);
if (spellTargetData.Orientation.HasValue)
pos->SetOrientation(spellTargetData.Orientation.Value);
pos->Relocate(spellCastRequest.Target.SrcLocation.Value.Location);
if (spellCastRequest.Target.Orientation.HasValue)
pos->SetOrientation(spellCastRequest.Target.Orientation.Value);
}
if (spellTargetData.DstLocation.HasValue)
if (spellCastRequest.Target.DstLocation.HasValue)
{
m_dst._transportGUID = spellTargetData.DstLocation.Value.Transport;
m_dst._transportGUID = spellCastRequest.Target.DstLocation.Value.Transport;
Position* pos;
if (!m_dst._transportGUID.IsEmpty())
pos = &m_dst._transportOffset;
else
pos = &m_dst._position;
pos->Relocate(spellTargetData.DstLocation.Value.Location);
if (spellTargetData.Orientation.HasValue)
pos->SetOrientation(spellTargetData.Orientation.Value);
pos->Relocate(spellCastRequest.Target.DstLocation.Value.Location);
if (spellCastRequest.Target.Orientation.HasValue)
pos->SetOrientation(spellCastRequest.Target.Orientation.Value);
}
SetPitch(spellCastRequest.MissileTrajectory.Pitch);
SetSpeed(spellCastRequest.MissileTrajectory.Speed);
Update(caster);
}
@@ -535,7 +538,7 @@ void SpellCastTargets::OutDebug() const
if (m_targetMask & TARGET_FLAG_STRING)
TC_LOG_INFO("spells", "String: %s", m_strTarget.c_str());
TC_LOG_INFO("spells", "speed: %f", m_speed);
TC_LOG_INFO("spells", "elevation: %f", m_elevation);
TC_LOG_INFO("spells", "pitch: %f", m_pitch);
}
SpellValue::SpellValue(Difficulty diff, SpellInfo const* proto)
@@ -1582,7 +1585,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex)
targets.sort(Trinity::ObjectDistanceOrderPred(m_caster));
float b = tangent(m_targets.GetElevation());
float b = tangent(m_targets.GetPitch());
float a = (srcToDestDelta - dist2d * b) / (dist2d * dist2d);
if (a > -0.0001f)
a = 0;
@@ -4117,7 +4120,7 @@ void Spell::SendSpellGo()
if (castFlags & CAST_FLAG_ADJUST_MISSILE)
{
castData.MissileTrajectory.TravelTime = m_delayMoment;
castData.MissileTrajectory.Pitch = m_targets.GetElevation();
castData.MissileTrajectory.Pitch = m_targets.GetPitch();
}
/*WorldPacket data(SMSG_SPELL_GO, 50); // guess size
+7 -6
View File
@@ -29,6 +29,7 @@ namespace WorldPackets
{
namespace Spells
{
struct SpellCastRequest;
struct SpellTargetData;
}
}
@@ -107,7 +108,7 @@ class SpellCastTargets
{
public:
SpellCastTargets();
SpellCastTargets(Unit* caster, WorldPackets::Spells::SpellTargetData const& spellTargetData);
SpellCastTargets(Unit* caster, WorldPackets::Spells::SpellCastRequest const& spellCastRequest);
~SpellCastTargets();
void Read(ByteBuffer& data, Unit* caster);
@@ -166,14 +167,14 @@ class SpellCastTargets
bool HasDst() const { return (GetTargetMask() & TARGET_FLAG_DEST_LOCATION) != 0; }
bool HasTraj() const { return m_speed != 0; }
float GetElevation() const { return m_elevation; }
void SetElevation(float elevation) { m_elevation = elevation; }
float GetPitch() const { return m_pitch; }
void SetPitch(float pitch) { m_pitch = pitch; }
float GetSpeed() const { return m_speed; }
void SetSpeed(float speed) { m_speed = speed; }
float GetDist2d() const { return m_src._position.GetExactDist2d(&m_dst._position); }
float GetSpeedXY() const { return m_speed * std::cos(m_elevation); }
float GetSpeedZ() const { return m_speed * std::sin(m_elevation); }
float GetSpeedXY() const { return m_speed * std::cos(m_pitch); }
float GetSpeedZ() const { return m_speed * std::sin(m_pitch); }
void Update(Unit* caster);
void OutDebug() const;
@@ -195,7 +196,7 @@ class SpellCastTargets
SpellDestination m_src;
SpellDestination m_dst;
float m_elevation, m_speed;
float m_pitch, m_speed;
std::string m_strTarget;
};