OP_MoveItem encode/decode for RoF2, disabled other patches for now (until i get rof2 packets and mechanics working well enough to go back and fix those)

This commit is contained in:
KimLS 2015-02-23 22:45:50 -08:00
parent 8bce7893ed
commit 69612b44d4
20 changed files with 1560 additions and 1352 deletions

View File

@ -1556,7 +1556,7 @@ struct DeleteItem_Struct {
/*0012*/ /*0012*/
}; };
struct MoveItem_Struct struct MoveItemOld_Struct
{ {
/*0000*/ uint32 from_slot; /*0000*/ uint32 from_slot;
/*0004*/ uint32 to_slot; /*0004*/ uint32 to_slot;
@ -1564,6 +1564,19 @@ struct MoveItem_Struct
/*0012*/ /*0012*/
}; };
struct MoveItem_Struct
{
int16 from_type;
int16 from_slot;
int16 from_bag_slot;
int16 from_aug_slot;
int16 to_type;
int16 to_slot;
int16 to_bag_slot;
int16 to_aug_slot;
uint32 number_in_stack;
};
// both MoveItem_Struct/DeleteItem_Struct server structures will be changing to a structure-based slot format..this will // both MoveItem_Struct/DeleteItem_Struct server structures will be changing to a structure-based slot format..this will
// be used for handling SoF/SoD/etc... time stamps sent using the MoveItem_Struct format. (nothing will be done with this // be used for handling SoF/SoD/etc... time stamps sent using the MoveItem_Struct format. (nothing will be done with this
// info at the moment..but, it is forwarded on to the server for handling/future use) // info at the moment..but, it is forwarded on to the server for handling/future use)

View File

@ -61,6 +61,8 @@ bool EQEmu::Inventory::Put(const InventorySlot &slot, std::shared_ptr<ItemInstan
impl_->containers_.insert(std::pair<int, ItemContainer>(slot.type_, ItemContainer())); impl_->containers_.insert(std::pair<int, ItemContainer>(slot.type_, ItemContainer()));
} }
//Verify item can be put into the slot requested
auto &container = impl_->containers_[slot.type_]; auto &container = impl_->containers_[slot.type_];
if(slot.bag_index_ > -1) { if(slot.bag_index_ > -1) {
auto item = container.Get(slot.slot_); auto item = container.Get(slot.slot_);
@ -92,10 +94,64 @@ bool EQEmu::Inventory::Put(const InventorySlot &slot, std::shared_ptr<ItemInstan
return false; return false;
} }
bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest) { bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest, int charges) {
return false; return false;
} }
int EQEmu::Inventory::CalcMaterialFromSlot(const InventorySlot &slot) {
if(slot.type_ != 0)
return _MaterialInvalid;
switch(slot.slot_) {
case PersonalSlotHead:
return MaterialHead;
case PersonalSlotChest:
return MaterialChest;
case PersonalSlotArms:
return MaterialArms;
case PersonalSlotWrist1:
return MaterialWrist;
case PersonalSlotHands:
return MaterialHands;
case PersonalSlotLegs:
return MaterialLegs;
case PersonalSlotFeet:
return MaterialFeet;
case PersonalSlotPrimary:
return MaterialPrimary;
case PersonalSlotSecondary:
return MaterialSecondary;
default:
return _MaterialInvalid;
}
}
EQEmu::InventorySlot EQEmu::Inventory::CalcSlotFromMaterial(int material) {
switch(material)
{
case MaterialHead:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotHead);
case MaterialChest:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotChest);
case MaterialArms:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotArms);
case MaterialWrist:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotWrist1);
case MaterialHands:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotHands);
case MaterialLegs:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotLegs);
case MaterialFeet:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotFeet);
case MaterialPrimary:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotPrimary);
case MaterialSecondary:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotSecondary);
default:
return EQEmu::InventorySlot(-1, -1);
}
}
bool EQEmu::Inventory::Serialize(MemoryBuffer &buf) { bool EQEmu::Inventory::Serialize(MemoryBuffer &buf) {
buf.SetWritePosition(0); buf.SetWritePosition(0);
buf.SetReadPosition(0); buf.SetReadPosition(0);

View File

@ -51,6 +51,44 @@ namespace EQEmu
InvTypeGuildTribute InvTypeGuildTribute
}; };
enum PersonaInventorylSlot : int
{
PersonalSlotCharm = 0,
PersonalSlotEar1,
PersonalSlotHead,
PersonalSlotFace,
PersonalSlotEar2,
PersonalSlotNeck,
PersonalSlotShoulders,
PersonalSlotArms,
PersonalSlotBack,
PersonalSlotWrist1,
PersonalSlotWrist2,
PersonalSlotRange,
PersonalSlotHands,
PersonalSlotPrimary,
PersonalSlotSecondary,
PersonalSlotFinger1,
PersonalSlotFinger2,
PersonalSlotChest,
PersonalSlotLegs,
PersonalSlotFeet,
PersonalSlotWaist,
PersonalSlotPowerSource,
PersonalSlotAmmo,
PersonalSlotGeneral1,
PersonalSlotGeneral2,
PersonalSlotGeneral3,
PersonalSlotGeneral4,
PersonalSlotGeneral5,
PersonalSlotGeneral6,
PersonalSlotGeneral7,
PersonalSlotGeneral8,
PersonalSlotGeneral9,
PersonalSlotGeneral10,
PersonalSlotCursor
};
class Inventory class Inventory
{ {
public: public:
@ -59,8 +97,11 @@ namespace EQEmu
std::shared_ptr<ItemInstance> Get(const InventorySlot &slot); std::shared_ptr<ItemInstance> Get(const InventorySlot &slot);
bool Put(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst); bool Put(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst);
bool Swap(const InventorySlot &src, const InventorySlot &dest); bool Swap(const InventorySlot &src, const InventorySlot &dest, int charges);
//utility
static int CalcMaterialFromSlot(const InventorySlot &slot);
static InventorySlot CalcSlotFromMaterial(int material);
bool Serialize(MemoryBuffer &buf); bool Serialize(MemoryBuffer &buf);
private: private:
struct impl; struct impl;

View File

@ -192,14 +192,56 @@ void EQEmu::ItemInstance::SetCustomData(const std::string &custom_data) {
impl_->custom_data_ = custom_data; impl_->custom_data_ = custom_data;
} }
uint32 EQEmu::ItemInstance::GetOrnamentIDFile() {
return impl_->ornament_idfile_;
}
uint32 EQEmu::ItemInstance::GetOrnamentIDFile() const {
return impl_->ornament_idfile_;
}
void EQEmu::ItemInstance::SetOrnamentIDFile(const uint32 ornament_idfile) { void EQEmu::ItemInstance::SetOrnamentIDFile(const uint32 ornament_idfile) {
impl_->ornament_idfile_ = ornament_idfile; impl_->ornament_idfile_ = ornament_idfile;
} }
uint32 EQEmu::ItemInstance::GetOrnamentIcon() {
return impl_->ornament_icon_;
}
uint32 EQEmu::ItemInstance::GetOrnamentIcon() const {
return impl_->ornament_icon_;
}
void EQEmu::ItemInstance::SetOrnamentIcon(const uint32 ornament_icon) { void EQEmu::ItemInstance::SetOrnamentIcon(const uint32 ornament_icon) {
impl_->ornament_icon_ = ornament_icon; impl_->ornament_icon_ = ornament_icon;
} }
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int material_slot) {
uint32 hero_model = 0;
if(impl_->ornament_hero_model_ > 0)
{
hero_model = impl_->ornament_hero_model_;
if(material_slot >= 0)
{
hero_model = (impl_->ornament_hero_model_ * 100) + material_slot;
}
}
return hero_model;
}
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int material_slot) const {
uint32 hero_model = 0;
if(impl_->ornament_hero_model_ > 0)
{
hero_model = impl_->ornament_hero_model_;
if(material_slot >= 0)
{
hero_model = (impl_->ornament_hero_model_ * 100) + material_slot;
}
}
return hero_model;
}
void EQEmu::ItemInstance::SetOrnamentHeroModel(const uint32 ornament_hero_model) { void EQEmu::ItemInstance::SetOrnamentHeroModel(const uint32 ornament_hero_model) {
impl_->ornament_hero_model_ = ornament_hero_model; impl_->ornament_hero_model_ = ornament_hero_model;
} }

View File

@ -53,8 +53,17 @@ namespace EQEmu
void SetAttuned(const bool attuned); void SetAttuned(const bool attuned);
void SetCustomData(const std::string &custom_data); void SetCustomData(const std::string &custom_data);
uint32 GetOrnamentIDFile();
uint32 GetOrnamentIDFile() const;
void SetOrnamentIDFile(const uint32 ornament_idfile); void SetOrnamentIDFile(const uint32 ornament_idfile);
uint32 GetOrnamentIcon();
uint32 GetOrnamentIcon() const;
void SetOrnamentIcon(const uint32 ornament_icon); void SetOrnamentIcon(const uint32 ornament_icon);
uint32 GetOrnamentHeroModel(int material_slot);
uint32 GetOrnamentHeroModel(int material_slot) const;
void SetOrnamentHeroModel(const uint32 ornament_hero_model); void SetOrnamentHeroModel(const uint32 ornament_hero_model);
const char* GetTrackingID(); const char* GetTrackingID();

View File

@ -32,20 +32,30 @@ EQEmu::MemoryBuffer::MemoryBuffer(const MemoryBuffer &other) {
} }
EQEmu::MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) { EQEmu::MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) {
buffer_ = other.buffer_; uchar *tbuf = other.buffer_;
size_ = other.size_; size_t tsz = other.size_;
capacity_ = other.capacity_; size_t tcapacity = other.capacity_;
write_pos_ = other.write_pos_; size_t twrite_pos = other.write_pos_;
read_pos_ = other.read_pos_; size_t tread_pos = other.read_pos_;
other.buffer_ = nullptr; other.buffer_ = nullptr;
other.size_ = 0; other.size_ = 0;
other.capacity_ = 0; other.capacity_ = 0;
other.read_pos_ = 0; other.read_pos_ = 0;
other.write_pos_ = 0; other.write_pos_ = 0;
buffer_ = tbuf;
size_ = tsz;
capacity_ = tcapacity;
write_pos_ = twrite_pos;
read_pos_ = tread_pos;
} }
EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(const MemoryBuffer &other) { EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(const MemoryBuffer &other) {
if(buffer_) {
delete[] buffer_;
}
if(other.capacity_) { if(other.capacity_) {
buffer_ = new uchar[other.capacity_]; buffer_ = new uchar[other.capacity_];
memcpy(buffer_, other.buffer_, other.capacity_); memcpy(buffer_, other.buffer_, other.capacity_);
@ -62,17 +72,23 @@ EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(const MemoryBuffer &other) {
} }
EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(MemoryBuffer &&other) { EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(MemoryBuffer &&other) {
buffer_ = other.buffer_; uchar *tbuf = other.buffer_;
size_ = other.size_; size_t tsz = other.size_;
capacity_ = other.capacity_; size_t tcapacity = other.capacity_;
write_pos_ = other.write_pos_; size_t twrite_pos = other.write_pos_;
read_pos_ = other.read_pos_; size_t tread_pos = other.read_pos_;
other.buffer_ = nullptr; other.buffer_ = nullptr;
other.size_ = 0; other.size_ = 0;
other.capacity_ = 0; other.capacity_ = 0;
other.read_pos_ = 0; other.read_pos_ = 0;
other.write_pos_ = 0; other.write_pos_ = 0;
buffer_ = tbuf;
size_ = tsz;
capacity_ = tcapacity;
write_pos_ = twrite_pos;
read_pos_ = tread_pos;
return *this; return *this;
} }

View File

@ -10,19 +10,19 @@
#include "rof2.h" #include "rof2.h"
void RegisterAllPatches(EQStreamIdentifier &into) { void RegisterAllPatches(EQStreamIdentifier &into) {
Titanium::Register(into); //Titanium::Register(into);
SoF::Register(into); //SoF::Register(into);
SoD::Register(into); //SoD::Register(into);
UF::Register(into); //UF::Register(into);
RoF::Register(into); //RoF::Register(into);
RoF2::Register(into); RoF2::Register(into);
} }
void ReloadAllPatches() { void ReloadAllPatches() {
Titanium::Reload(); //Titanium::Reload();
SoF::Reload(); //SoF::Reload();
SoD::Reload(); //SoD::Reload();
UF::Reload(); //UF::Reload();
RoF::Reload(); //RoF::Reload();
RoF2::Reload(); RoF2::Reload();
} }

View File

@ -1707,14 +1707,14 @@ namespace RoF
ENCODE(OP_MoveItem) ENCODE(OP_MoveItem)
{ {
ENCODE_LENGTH_EXACT(MoveItem_Struct); //ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); //SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
eq->from_slot = ServerToRoFSlot(emu->from_slot); //eq->from_slot = ServerToRoFSlot(emu->from_slot);
eq->to_slot = ServerToRoFSlot(emu->to_slot); //eq->to_slot = ServerToRoFSlot(emu->to_slot);
OUT(number_in_stack); //OUT(number_in_stack);
//
FINISH_ENCODE(); //FINISH_ENCODE();
} }
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@ -4684,16 +4684,16 @@ namespace RoF
DECODE(OP_MoveItem) DECODE(OP_MoveItem)
{ {
DECODE_LENGTH_EXACT(structs::MoveItem_Struct); //DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); //SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot); ////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot);
Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); //Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack);
emu->from_slot = RoFToServerSlot(eq->from_slot); //emu->from_slot = RoFToServerSlot(eq->from_slot);
emu->to_slot = RoFToServerSlot(eq->to_slot); //emu->to_slot = RoFToServerSlot(eq->to_slot);
IN(number_in_stack); //IN(number_in_stack);
//
FINISH_DIRECT_DECODE(); //FINISH_DIRECT_DECODE();
} }
DECODE(OP_PetCommands) DECODE(OP_PetCommands)

File diff suppressed because it is too large Load Diff

View File

@ -1265,14 +1265,14 @@ namespace SoD
ENCODE(OP_MoveItem) ENCODE(OP_MoveItem)
{ {
ENCODE_LENGTH_EXACT(MoveItem_Struct); //ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); //SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
eq->from_slot = ServerToSoDSlot(emu->from_slot); //eq->from_slot = ServerToSoDSlot(emu->from_slot);
eq->to_slot = ServerToSoDSlot(emu->to_slot); //eq->to_slot = ServerToSoDSlot(emu->to_slot);
OUT(number_in_stack); //OUT(number_in_stack);
//
FINISH_ENCODE(); //FINISH_ENCODE();
} }
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@ -3260,16 +3260,16 @@ namespace SoD
DECODE(OP_MoveItem) DECODE(OP_MoveItem)
{ {
DECODE_LENGTH_EXACT(structs::MoveItem_Struct); //DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); //SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
Log.Out(Logs::General, Logs::Netcode, "[SoD] Moved item from %u to %u", eq->from_slot, eq->to_slot); //Log.Out(Logs::General, Logs::Netcode, "[SoD] Moved item from %u to %u", eq->from_slot, eq->to_slot);
//
emu->from_slot = SoDToServerSlot(eq->from_slot); //emu->from_slot = SoDToServerSlot(eq->from_slot);
emu->to_slot = SoDToServerSlot(eq->to_slot); //emu->to_slot = SoDToServerSlot(eq->to_slot);
IN(number_in_stack); //IN(number_in_stack);
//
FINISH_DIRECT_DECODE(); //FINISH_DIRECT_DECODE();
} }
DECODE(OP_PetCommands) DECODE(OP_PetCommands)

View File

@ -930,14 +930,14 @@ namespace SoF
ENCODE(OP_MoveItem) ENCODE(OP_MoveItem)
{ {
ENCODE_LENGTH_EXACT(MoveItem_Struct); //ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); //SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
eq->from_slot = ServerToSoFSlot(emu->from_slot); //eq->from_slot = ServerToSoFSlot(emu->from_slot);
eq->to_slot = ServerToSoFSlot(emu->to_slot); //eq->to_slot = ServerToSoFSlot(emu->to_slot);
OUT(number_in_stack); //OUT(number_in_stack);
//
FINISH_ENCODE(); //FINISH_ENCODE();
} }
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@ -2598,16 +2598,16 @@ namespace SoF
DECODE(OP_MoveItem) DECODE(OP_MoveItem)
{ {
DECODE_LENGTH_EXACT(structs::MoveItem_Struct); //DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); //SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
Log.Out(Logs::General, Logs::Netcode, "[SoF] Moved item from %u to %u", eq->from_slot, eq->to_slot); //Log.Out(Logs::General, Logs::Netcode, "[SoF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
//
emu->from_slot = SoFToServerSlot(eq->from_slot); //emu->from_slot = SoFToServerSlot(eq->from_slot);
emu->to_slot = SoFToServerSlot(eq->to_slot); //emu->to_slot = SoFToServerSlot(eq->to_slot);
IN(number_in_stack); //IN(number_in_stack);
//
FINISH_DIRECT_DECODE(); //FINISH_DIRECT_DECODE();
} }
DECODE(OP_PetCommands) DECODE(OP_PetCommands)

View File

@ -778,14 +778,14 @@ namespace Titanium
ENCODE(OP_MoveItem) ENCODE(OP_MoveItem)
{ {
ENCODE_LENGTH_EXACT(MoveItem_Struct); //ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); //SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
eq->from_slot = ServerToTitaniumSlot(emu->from_slot); //eq->from_slot = ServerToTitaniumSlot(emu->from_slot);
eq->to_slot = ServerToTitaniumSlot(emu->to_slot); //eq->to_slot = ServerToTitaniumSlot(emu->to_slot);
OUT(number_in_stack); //OUT(number_in_stack);
//
FINISH_ENCODE(); //FINISH_ENCODE();
} }
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@ -1854,16 +1854,16 @@ namespace Titanium
DECODE(OP_MoveItem) DECODE(OP_MoveItem)
{ {
DECODE_LENGTH_EXACT(structs::MoveItem_Struct); //DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); //SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
Log.Out(Logs::General, Logs::Netcode, "[Titanium] Moved item from %u to %u", eq->from_slot, eq->to_slot); //Log.Out(Logs::General, Logs::Netcode, "[Titanium] Moved item from %u to %u", eq->from_slot, eq->to_slot);
//
emu->from_slot = TitaniumToServerSlot(eq->from_slot); //emu->from_slot = TitaniumToServerSlot(eq->from_slot);
emu->to_slot = TitaniumToServerSlot(eq->to_slot); //emu->to_slot = TitaniumToServerSlot(eq->to_slot);
IN(number_in_stack); //IN(number_in_stack);
//
FINISH_DIRECT_DECODE(); //FINISH_DIRECT_DECODE();
} }
DECODE(OP_PetCommands) DECODE(OP_PetCommands)

View File

@ -1504,14 +1504,14 @@ namespace UF
ENCODE(OP_MoveItem) ENCODE(OP_MoveItem)
{ {
ENCODE_LENGTH_EXACT(MoveItem_Struct); //ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); //SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
eq->from_slot = ServerToUFSlot(emu->from_slot); //eq->from_slot = ServerToUFSlot(emu->from_slot);
eq->to_slot = ServerToUFSlot(emu->to_slot); //eq->to_slot = ServerToUFSlot(emu->to_slot);
OUT(number_in_stack); //OUT(number_in_stack);
//
FINISH_ENCODE(); //FINISH_ENCODE();
} }
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@ -3582,16 +3582,16 @@ namespace UF
DECODE(OP_MoveItem) DECODE(OP_MoveItem)
{ {
DECODE_LENGTH_EXACT(structs::MoveItem_Struct); //DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); //SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
Log.Out(Logs::General, Logs::Netcode, "[UF] Moved item from %u to %u", eq->from_slot, eq->to_slot); //Log.Out(Logs::General, Logs::Netcode, "[UF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
//
emu->from_slot = UFToServerSlot(eq->from_slot); //emu->from_slot = UFToServerSlot(eq->from_slot);
emu->to_slot = UFToServerSlot(eq->to_slot); //emu->to_slot = UFToServerSlot(eq->to_slot);
IN(number_in_stack); //IN(number_in_stack);
//
FINISH_DIRECT_DECODE(); //FINISH_DIRECT_DECODE();
} }
DECODE(OP_PetCommands) DECODE(OP_PetCommands)

View File

@ -175,7 +175,7 @@ private:
void InventorySwapItemsTest() void InventorySwapItemsTest()
{ {
auto swap_result = inv.Swap(EQEmu::InventorySlot(0, 23), EQEmu::InventorySlot(0, 24)); auto swap_result = inv.Swap(EQEmu::InventorySlot(0, 23), EQEmu::InventorySlot(0, 24), 0);
TEST_ASSERT(swap_result == true); TEST_ASSERT(swap_result == true);
auto m_bag = inv.Get(EQEmu::InventorySlot(0, 24)); auto m_bag = inv.Get(EQEmu::InventorySlot(0, 24));

View File

@ -33,6 +33,7 @@ public:
TEST_ADD(MemoryBufferTest::CopyTest); TEST_ADD(MemoryBufferTest::CopyTest);
TEST_ADD(MemoryBufferTest::AssignTest); TEST_ADD(MemoryBufferTest::AssignTest);
TEST_ADD(MemoryBufferTest::MoveTest); TEST_ADD(MemoryBufferTest::MoveTest);
TEST_ADD(MemoryBufferTest::SelfTest);
TEST_ADD(MemoryBufferTest::ZeroTest); TEST_ADD(MemoryBufferTest::ZeroTest);
TEST_ADD(MemoryBufferTest::ClearTest); TEST_ADD(MemoryBufferTest::ClearTest);
TEST_ADD(MemoryBufferTest::AddTest) TEST_ADD(MemoryBufferTest::AddTest)
@ -449,6 +450,22 @@ private:
TEST_ASSERT(data[26] == 0); TEST_ASSERT(data[26] == 0);
} }
void SelfTest()
{
EQEmu::MemoryBuffer mb2(mb);
void *addr = (void*)mb2;
mb2 = mb2;
void *addr2 = (void*)mb2;
TEST_ASSERT(addr != addr2);
mb2 = std::move(mb2);
addr2 = (void*)mb2;
TEST_ASSERT(addr2 != nullptr);
}
void ZeroTest() void ZeroTest()
{ {
mb.Zero(); mb.Zero();

View File

@ -813,9 +813,9 @@ public:
bool PushItemOnCursor(const ItemInst& inst, bool client_update = false); bool PushItemOnCursor(const ItemInst& inst, bool client_update = false);
void SendCursorBuffer(); void SendCursorBuffer();
void DeleteItemInInventory(int16 slot_id, int8 quantity = 0, bool client_update = false, bool update_db = true); void DeleteItemInInventory(int16 slot_id, int8 quantity = 0, bool client_update = false, bool update_db = true);
bool SwapItem(MoveItem_Struct* move_in); bool SwapItem(MoveItemOld_Struct* move_in);
void SwapItemResync(MoveItem_Struct* move_slots); void SwapItemResync(MoveItemOld_Struct* move_slots);
void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false); void QSSwapItemAuditor(MoveItemOld_Struct* move_in, bool postaction_call = false);
void PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootItem_Struct** bag_item_data = 0); void PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootItem_Struct** bag_item_data = 0);
bool AutoPutLootInInventory(ItemInst& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0); bool AutoPutLootInInventory(ItemInst& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0);
bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = MainCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = MainCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0);

View File

@ -9586,68 +9586,77 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
{ {
return; return;
} }
if (app->size != sizeof(MoveItem_Struct)) { if (app->size != sizeof(MoveItem_Struct)) {
Log.Out(Logs::General, Logs::Error, "Wrong size: OP_MoveItem, size=%i, expected %i", app->size, sizeof(MoveItem_Struct)); Log.Out(Logs::General, Logs::Error, "Wrong size: OP_MoveItem, size=%i, expected %i", app->size, sizeof(MoveItem_Struct));
return; return;
} }
MoveItem_Struct* mi = (MoveItem_Struct*)app->pBuffer; MoveItem_Struct* mi = (MoveItem_Struct*)app->pBuffer;
if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id)) auto res = m_inventory.Swap(EQEmu::InventorySlot(mi->from_type, mi->from_slot, mi->from_bag_slot, mi->from_aug_slot),
{ EQEmu::InventorySlot(mi->to_type, mi->to_slot, mi->to_bag_slot, mi->to_aug_slot),
if (mi->from_slot != mi->to_slot && (mi->from_slot <= EmuConstants::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) mi->number_in_stack);
{
char *detect = nullptr;
const ItemInst *itm_from = GetInv().GetItem(mi->from_slot);
const ItemInst *itm_to = GetInv().GetItem(mi->to_slot);
MakeAnyLenString(&detect, "Player issued a move item from %u(item id %u) to %u(item id %u) while casting %u.",
mi->from_slot,
itm_from ? itm_from->GetID() : 0,
mi->to_slot,
itm_to ? itm_to->GetID() : 0,
casting_spell_id);
database.SetMQDetectionFlag(AccountName(), GetName(), detect, zone->GetShortName());
safe_delete_array(detect);
Kick(); // Kick client to prevent client and server from getting out-of-sync inventory slots
return;
}
}
// Illegal bagslot usage checks. Currently, user only receives a message if this check is triggered. //printf("%i %i %i %i --> %i %i %i %i (%u)\n",
bool mi_hack = false; // mi->from_type, mi->from_slot, mi->from_bag_slot, mi->from_aug_slot,
// mi->to_type, mi->to_slot, mi->to_bag_slot, mi->to_aug_slot,
// mi->number_in_stack);
if (mi->from_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->from_slot <= EmuConstants::CURSOR_BAG_END) { //if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id))
if (mi->from_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; } //{
else { // if (mi->from_slot != mi->to_slot && (mi->from_slot <= EmuConstants::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot))
int16 from_parent = m_inv.CalcSlotId(mi->from_slot); // {
if (!m_inv[from_parent]) { mi_hack = true; } // char *detect = nullptr;
else if (!m_inv[from_parent]->IsType(ItemClassContainer)) { mi_hack = true; } // const ItemInst *itm_from = GetInv().GetItem(mi->from_slot);
else if (m_inv.CalcBagIdx(mi->from_slot) >= m_inv[from_parent]->GetItem()->BagSlots) { mi_hack = true; } // const ItemInst *itm_to = GetInv().GetItem(mi->to_slot);
} // MakeAnyLenString(&detect, "Player issued a move item from %u(item id %u) to %u(item id %u) while casting %u.",
} // mi->from_slot,
// itm_from ? itm_from->GetID() : 0,
if (mi->to_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->to_slot <= EmuConstants::CURSOR_BAG_END) { // mi->to_slot,
if (mi->to_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; } // itm_to ? itm_to->GetID() : 0,
else { // casting_spell_id);
int16 to_parent = m_inv.CalcSlotId(mi->to_slot); // database.SetMQDetectionFlag(AccountName(), GetName(), detect, zone->GetShortName());
if (!m_inv[to_parent]) { mi_hack = true; } // safe_delete_array(detect);
else if (!m_inv[to_parent]->IsType(ItemClassContainer)) { mi_hack = true; } // Kick(); // Kick client to prevent client and server from getting out-of-sync inventory slots
else if (m_inv.CalcBagIdx(mi->to_slot) >= m_inv[to_parent]->GetItem()->BagSlots) { mi_hack = true; } // return;
} // }
} //}
//
if (mi_hack) { Message(15, "Caution: Illegal use of inaccessible bag slots!"); } //// Illegal bagslot usage checks. Currently, user only receives a message if this check is triggered.
//bool mi_hack = false;
if (!SwapItem(mi) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) { //
SwapItemResync(mi); //if (mi->from_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->from_slot <= EmuConstants::CURSOR_BAG_END) {
// if (mi->from_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; }
bool error = false; // else {
InterrogateInventory(this, false, true, false, error, false); // int16 from_parent = m_inv.CalcSlotId(mi->from_slot);
if (error) // if (!m_inv[from_parent]) { mi_hack = true; }
InterrogateInventory(this, true, false, true, error); // else if (!m_inv[from_parent]->IsType(ItemClassContainer)) { mi_hack = true; }
} // else if (m_inv.CalcBagIdx(mi->from_slot) >= m_inv[from_parent]->GetItem()->BagSlots) { mi_hack = true; }
// }
return; //}
//
//if (mi->to_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->to_slot <= EmuConstants::CURSOR_BAG_END) {
// if (mi->to_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; }
// else {
// int16 to_parent = m_inv.CalcSlotId(mi->to_slot);
// if (!m_inv[to_parent]) { mi_hack = true; }
// else if (!m_inv[to_parent]->IsType(ItemClassContainer)) { mi_hack = true; }
// else if (m_inv.CalcBagIdx(mi->to_slot) >= m_inv[to_parent]->GetItem()->BagSlots) { mi_hack = true; }
// }
//}
//
//if (mi_hack) { Message(15, "Caution: Illegal use of inaccessible bag slots!"); }
//
//if (!SwapItem(mi) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) {
// SwapItemResync(mi);
//
// bool error = false;
// InterrogateInventory(this, false, true, false, error, false);
// if (error)
// InterrogateInventory(this, true, false, true, error);
//}
//
//return;
} }
void Client::Handle_OP_OpenContainer(const EQApplicationPacket *app) void Client::Handle_OP_OpenContainer(const EQApplicationPacket *app)

View File

@ -3119,77 +3119,77 @@ void command_listpetition(Client *c, const Seperator *sep)
void command_equipitem(Client *c, const Seperator *sep) void command_equipitem(Client *c, const Seperator *sep)
{ {
uint32 slot_id = atoi(sep->arg[1]); // uint32 slot_id = atoi(sep->arg[1]);
if (sep->IsNumber(1) && ((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || (slot_id == MainPowerSource))) { // if (sep->IsNumber(1) && ((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || (slot_id == MainPowerSource))) {
const ItemInst* from_inst = c->GetInv().GetItem(MainCursor); // const ItemInst* from_inst = c->GetInv().GetItem(MainCursor);
const ItemInst* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack) // const ItemInst* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack)
bool partialmove = false; // bool partialmove = false;
int16 movecount; // int16 movecount;
//
if (from_inst && from_inst->IsType(ItemClassCommon)) { // if (from_inst && from_inst->IsType(ItemClassCommon)) {
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); // EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct));
MoveItem_Struct* mi = (MoveItem_Struct*)outapp->pBuffer; // MoveItem_Struct* mi = (MoveItem_Struct*)outapp->pBuffer;
mi->from_slot = MainCursor; // mi->from_slot = MainCursor;
mi->to_slot = slot_id; // mi->to_slot = slot_id;
// mi->number_in_stack = from_inst->GetCharges(); // replaced with con check for stacking // // mi->number_in_stack = from_inst->GetCharges(); // replaced with con check for stacking
//
// crude stackable check to only 'move' the difference count on client instead of entire stack when applicable // // crude stackable check to only 'move' the difference count on client instead of entire stack when applicable
if (to_inst && to_inst->IsStackable() && // if (to_inst && to_inst->IsStackable() &&
(to_inst->GetItem()->ID == from_inst->GetItem()->ID) && // (to_inst->GetItem()->ID == from_inst->GetItem()->ID) &&
(to_inst->GetCharges() < to_inst->GetItem()->StackSize) && // (to_inst->GetCharges() < to_inst->GetItem()->StackSize) &&
(from_inst->GetCharges() > to_inst->GetItem()->StackSize - to_inst->GetCharges())) { // (from_inst->GetCharges() > to_inst->GetItem()->StackSize - to_inst->GetCharges())) {
movecount = to_inst->GetItem()->StackSize - to_inst->GetCharges(); // movecount = to_inst->GetItem()->StackSize - to_inst->GetCharges();
mi->number_in_stack = (uint32)movecount; // mi->number_in_stack = (uint32)movecount;
partialmove = true; // partialmove = true;
} // }
else // else
mi->number_in_stack = from_inst->GetCharges(); // mi->number_in_stack = from_inst->GetCharges();
//
// Save move changes // // Save move changes
// Added conditional check to packet send..would have sent change even on a swap failure..whoops! // // Added conditional check to packet send..would have sent change even on a swap failure..whoops!
//
if (partialmove) { // remove this con check if someone can figure out removing charges from cursor stack issue below // if (partialmove) { // remove this con check if someone can figure out removing charges from cursor stack issue below
// mi->number_in_stack is always from_inst->GetCharges() when partialmove is false // // mi->number_in_stack is always from_inst->GetCharges() when partialmove is false
c->Message(13, "Error: Partial stack added to existing stack exceeds allowable stacksize"); // c->Message(13, "Error: Partial stack added to existing stack exceeds allowable stacksize");
return; // return;
} // }
else if(c->SwapItem(mi)) { // else if(c->SwapItem(mi)) {
c->FastQueuePacket(&outapp); // c->FastQueuePacket(&outapp);
//
// if the below code is still needed..just send an an item trade packet to each slot..it should overwrite the client instance // // if the below code is still needed..just send an an item trade packet to each slot..it should overwrite the client instance
//
// below code has proper logic, but client does not like to have cursor charges changed // // below code has proper logic, but client does not like to have cursor charges changed
// (we could delete the cursor item and resend, but issues would arise if there are queued items) // // (we could delete the cursor item and resend, but issues would arise if there are queued items)
//if (partialmove) { // //if (partialmove) {
// EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct)); // // EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct));
// DeleteItem_Struct* di = (DeleteItem_Struct*)outapp2->pBuffer; // // DeleteItem_Struct* di = (DeleteItem_Struct*)outapp2->pBuffer;
// di->from_slot = SLOT_CURSOR; // // di->from_slot = SLOT_CURSOR;
// di->to_slot = 0xFFFFFFFF; // // di->to_slot = 0xFFFFFFFF;
// di->number_in_stack = 0xFFFFFFFF; // // di->number_in_stack = 0xFFFFFFFF;
//
// c->Message(0, "Deleting %i charges from stack", movecount); // debug line..delete // // c->Message(0, "Deleting %i charges from stack", movecount); // debug line..delete
//
// for (int16 deletecount=0; deletecount < movecount; deletecount++) // // for (int16 deletecount=0; deletecount < movecount; deletecount++)
// have to use 'movecount' because mi->number_in_stack is 'ENCODED' at this point (i.e., 99 charges returns 22...) // // have to use 'movecount' because mi->number_in_stack is 'ENCODED' at this point (i.e., 99 charges returns 22...)
// c->QueuePacket(outapp2); // // c->QueuePacket(outapp2);
//
// safe_delete(outapp2); // // safe_delete(outapp2);
//} // //}
} // }
else { // else {
c->Message(13, "Error: Unable to equip current item"); // c->Message(13, "Error: Unable to equip current item");
} // }
safe_delete(outapp); // safe_delete(outapp);
//
// also send out a wear change packet? // // also send out a wear change packet?
} // }
else if (from_inst == nullptr) // else if (from_inst == nullptr)
c->Message(13, "Error: There is no item on your cursor"); // c->Message(13, "Error: There is no item on your cursor");
else // else
c->Message(13, "Error: Item on your cursor cannot be equipped"); // c->Message(13, "Error: Item on your cursor cannot be equipped");
} // }
else // else
c->Message(0, "Usage: #equipitem slotid[0-21] - equips the item on your cursor to the position"); // c->Message(0, "Usage: #equipitem slotid[0-21] - equips the item on your cursor to the position");
} }
void command_zonelock(Client *c, const Seperator *sep) void command_zonelock(Client *c, const Seperator *sep)

View File

@ -716,122 +716,122 @@ void Client::SendCursorBuffer()
// Remove item from inventory // Remove item from inventory
void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_update, bool update_db) { void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_update, bool update_db) {
#if (EQDEBUG >= 5) // #if (EQDEBUG >= 5)
Log.Out(Logs::General, Logs::None, "DeleteItemInInventory(%i, %i, %s)", slot_id, quantity, (client_update) ? "true":"false"); // Log.Out(Logs::General, Logs::None, "DeleteItemInInventory(%i, %i, %s)", slot_id, quantity, (client_update) ? "true":"false");
#endif // #endif
//
// Added 'IsSlotValid(slot_id)' check to both segments of client packet processing. // // Added 'IsSlotValid(slot_id)' check to both segments of client packet processing.
// - cursor queue slots were slipping through and crashing client // // - cursor queue slots were slipping through and crashing client
if(!m_inv[slot_id]) { // if(!m_inv[slot_id]) {
// Make sure the client deletes anything in this slot to match the server. // // Make sure the client deletes anything in this slot to match the server.
if(client_update && IsValidSlot(slot_id)) { // if(client_update && IsValidSlot(slot_id)) {
EQApplicationPacket* outapp; // EQApplicationPacket* outapp;
outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct)); // outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct));
DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer; // DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer;
delitem->from_slot = slot_id; // delitem->from_slot = slot_id;
delitem->to_slot = 0xFFFFFFFF; // delitem->to_slot = 0xFFFFFFFF;
delitem->number_in_stack = 0xFFFFFFFF; // delitem->number_in_stack = 0xFFFFFFFF;
QueuePacket(outapp); // QueuePacket(outapp);
safe_delete(outapp); // safe_delete(outapp);
} // }
return; // return;
} // }
//
// start QS code // // start QS code
if(RuleB(QueryServ, PlayerLogDeletes)) { // if(RuleB(QueryServ, PlayerLogDeletes)) {
uint16 delete_count = 0; // uint16 delete_count = 0;
//
if(m_inv[slot_id]) { delete_count += m_inv.GetItem(slot_id)->GetTotalItemCount(); } // if(m_inv[slot_id]) { delete_count += m_inv.GetItem(slot_id)->GetTotalItemCount(); }
//
ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogDeletes, sizeof(QSPlayerLogDelete_Struct) + (sizeof(QSDeleteItems_Struct) * delete_count)); // ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogDeletes, sizeof(QSPlayerLogDelete_Struct) + (sizeof(QSDeleteItems_Struct) * delete_count));
QSPlayerLogDelete_Struct* qsaudit = (QSPlayerLogDelete_Struct*)qspack->pBuffer; // QSPlayerLogDelete_Struct* qsaudit = (QSPlayerLogDelete_Struct*)qspack->pBuffer;
uint16 parent_offset = 0; // uint16 parent_offset = 0;
//
qsaudit->char_id = character_id; // qsaudit->char_id = character_id;
qsaudit->stack_size = quantity; // qsaudit->stack_size = quantity;
qsaudit->char_count = delete_count; // qsaudit->char_count = delete_count;
//
qsaudit->items[parent_offset].char_slot = slot_id; // qsaudit->items[parent_offset].char_slot = slot_id;
qsaudit->items[parent_offset].item_id = m_inv[slot_id]->GetID(); // qsaudit->items[parent_offset].item_id = m_inv[slot_id]->GetID();
qsaudit->items[parent_offset].charges = m_inv[slot_id]->GetCharges(); // qsaudit->items[parent_offset].charges = m_inv[slot_id]->GetCharges();
qsaudit->items[parent_offset].aug_1 = m_inv[slot_id]->GetAugmentItemID(1); // qsaudit->items[parent_offset].aug_1 = m_inv[slot_id]->GetAugmentItemID(1);
qsaudit->items[parent_offset].aug_2 = m_inv[slot_id]->GetAugmentItemID(2); // qsaudit->items[parent_offset].aug_2 = m_inv[slot_id]->GetAugmentItemID(2);
qsaudit->items[parent_offset].aug_3 = m_inv[slot_id]->GetAugmentItemID(3); // qsaudit->items[parent_offset].aug_3 = m_inv[slot_id]->GetAugmentItemID(3);
qsaudit->items[parent_offset].aug_4 = m_inv[slot_id]->GetAugmentItemID(4); // qsaudit->items[parent_offset].aug_4 = m_inv[slot_id]->GetAugmentItemID(4);
qsaudit->items[parent_offset].aug_5 = m_inv[slot_id]->GetAugmentItemID(5); // qsaudit->items[parent_offset].aug_5 = m_inv[slot_id]->GetAugmentItemID(5);
//
if(m_inv[slot_id]->IsType(ItemClassContainer)) { // if(m_inv[slot_id]->IsType(ItemClassContainer)) {
for(uint8 bag_idx = SUB_BEGIN; bag_idx < m_inv[slot_id]->GetItem()->BagSlots; bag_idx++) { // for(uint8 bag_idx = SUB_BEGIN; bag_idx < m_inv[slot_id]->GetItem()->BagSlots; bag_idx++) {
ItemInst* bagitem = m_inv[slot_id]->GetItem(bag_idx); // ItemInst* bagitem = m_inv[slot_id]->GetItem(bag_idx);
//
if(bagitem) { // if(bagitem) {
int16 bagslot_id = InventoryOld::CalcSlotId(slot_id, bag_idx); // int16 bagslot_id = InventoryOld::CalcSlotId(slot_id, bag_idx);
//
qsaudit->items[++parent_offset].char_slot = bagslot_id; // qsaudit->items[++parent_offset].char_slot = bagslot_id;
qsaudit->items[parent_offset].item_id = bagitem->GetID(); // qsaudit->items[parent_offset].item_id = bagitem->GetID();
qsaudit->items[parent_offset].charges = bagitem->GetCharges(); // qsaudit->items[parent_offset].charges = bagitem->GetCharges();
qsaudit->items[parent_offset].aug_1 = bagitem->GetAugmentItemID(1); // qsaudit->items[parent_offset].aug_1 = bagitem->GetAugmentItemID(1);
qsaudit->items[parent_offset].aug_2 = bagitem->GetAugmentItemID(2); // qsaudit->items[parent_offset].aug_2 = bagitem->GetAugmentItemID(2);
qsaudit->items[parent_offset].aug_3 = bagitem->GetAugmentItemID(3); // qsaudit->items[parent_offset].aug_3 = bagitem->GetAugmentItemID(3);
qsaudit->items[parent_offset].aug_4 = bagitem->GetAugmentItemID(4); // qsaudit->items[parent_offset].aug_4 = bagitem->GetAugmentItemID(4);
qsaudit->items[parent_offset].aug_5 = bagitem->GetAugmentItemID(5); // qsaudit->items[parent_offset].aug_5 = bagitem->GetAugmentItemID(5);
} // }
} // }
} // }
//
qspack->Deflate(); // qspack->Deflate();
if(worldserver.Connected()) { worldserver.SendPacket(qspack); } // if(worldserver.Connected()) { worldserver.SendPacket(qspack); }
safe_delete(qspack); // safe_delete(qspack);
} // }
// end QS code // // end QS code
//
bool isDeleted = m_inv.DeleteItem(slot_id, quantity); // bool isDeleted = m_inv.DeleteItem(slot_id, quantity);
//
const ItemInst* inst = nullptr; // const ItemInst* inst = nullptr;
if (slot_id == MainCursor) { // if (slot_id == MainCursor) {
auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); // auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
if(update_db) // if(update_db)
database.SaveCursor(character_id, s, e); // database.SaveCursor(character_id, s, e);
} // }
else { // else {
// Save change to database // // Save change to database
inst = m_inv[slot_id]; // inst = m_inv[slot_id];
if(update_db) // if(update_db)
database.SaveInventory(character_id, inst, slot_id); // database.SaveInventory(character_id, inst, slot_id);
} // }
//
if(client_update && IsValidSlot(slot_id)) { // if(client_update && IsValidSlot(slot_id)) {
EQApplicationPacket* outapp = nullptr; // EQApplicationPacket* outapp = nullptr;
if(inst) { // if(inst) {
if (!inst->IsStackable() && !isDeleted) { // if (!inst->IsStackable() && !isDeleted) {
// Non stackable item with charges = Item with clicky spell effect ? Delete a charge. // // Non stackable item with charges = Item with clicky spell effect ? Delete a charge.
outapp = new EQApplicationPacket(OP_DeleteCharge, sizeof(MoveItem_Struct)); // outapp = new EQApplicationPacket(OP_DeleteCharge, sizeof(MoveItem_Struct));
} // }
else { // else {
// Stackable, arrows, etc ? Delete one from the stack // // Stackable, arrows, etc ? Delete one from the stack
outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(MoveItem_Struct)); // outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(MoveItem_Struct));
} // }
//
DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer; // DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer;
delitem->from_slot = slot_id; // delitem->from_slot = slot_id;
delitem->to_slot = 0xFFFFFFFF; // delitem->to_slot = 0xFFFFFFFF;
delitem->number_in_stack = 0xFFFFFFFF; // delitem->number_in_stack = 0xFFFFFFFF;
//
for(int loop=0;loop<quantity;loop++) // for(int loop=0;loop<quantity;loop++)
QueuePacket(outapp); // QueuePacket(outapp);
safe_delete(outapp); // safe_delete(outapp);
} // }
else { // else {
outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); // outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct));
MoveItem_Struct* delitem = (MoveItem_Struct*)outapp->pBuffer; // MoveItem_Struct* delitem = (MoveItem_Struct*)outapp->pBuffer;
delitem->from_slot = slot_id; // delitem->from_slot = slot_id;
delitem->to_slot = 0xFFFFFFFF; // delitem->to_slot = 0xFFFFFFFF;
delitem->number_in_stack = 0xFFFFFFFF; // delitem->number_in_stack = 0xFFFFFFFF;
//
QueuePacket(outapp); // QueuePacket(outapp);
safe_delete(outapp); // safe_delete(outapp);
} // }
} // }
} }
bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update) bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update)
@ -1315,7 +1315,7 @@ bool Client::IsBankSlot(uint32 slot)
// Moves items around both internally and in the database // Moves items around both internally and in the database
// In the future, this can be optimized by pushing all changes through one database REPLACE call // In the future, this can be optimized by pushing all changes through one database REPLACE call
bool Client::SwapItem(MoveItem_Struct* move_in) { bool Client::SwapItem(MoveItemOld_Struct* move_in) {
uint32 src_slot_check = move_in->from_slot; uint32 src_slot_check = move_in->from_slot;
uint32 dst_slot_check = move_in->to_slot; uint32 dst_slot_check = move_in->to_slot;
@ -1788,7 +1788,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
return true; return true;
} }
void Client::SwapItemResync(MoveItem_Struct* move_slots) { void Client::SwapItemResync(MoveItemOld_Struct* move_slots) {
// wow..this thing created a helluva memory leak... // wow..this thing created a helluva memory leak...
// with any luck..this won't be needed in the future // with any luck..this won't be needed in the future
@ -1883,7 +1883,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) {
} }
} }
void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { void Client::QSSwapItemAuditor(MoveItemOld_Struct* move_in, bool postaction_call) {
int16 from_slot_id = static_cast<int16>(move_in->from_slot); int16 from_slot_id = static_cast<int16>(move_in->from_slot);
int16 to_slot_id = static_cast<int16>(move_in->to_slot); int16 to_slot_id = static_cast<int16>(move_in->to_slot);
int16 move_amount = static_cast<int16>(move_in->number_in_stack); int16 move_amount = static_cast<int16>(move_in->number_in_stack);

View File

@ -1333,68 +1333,68 @@ uint16 Client::FindTraderItem(int32 SerialNumber, uint16 Quantity){
} }
void Client::NukeTraderItem(uint16 Slot,int16 Charges,uint16 Quantity,Client* Customer,uint16 TraderSlot, int32 SerialNumber, int32 itemid) { void Client::NukeTraderItem(uint16 Slot,int16 Charges,uint16 Quantity,Client* Customer,uint16 TraderSlot, int32 SerialNumber, int32 itemid) {
//
if(!Customer) // if(!Customer)
return; // return;
//
Log.Out(Logs::Detail, Logs::Trading, "NukeTraderItem(Slot %i, Charges %i, Quantity %i", Slot, Charges, Quantity); // Log.Out(Logs::Detail, Logs::Trading, "NukeTraderItem(Slot %i, Charges %i, Quantity %i", Slot, Charges, Quantity);
//
if(Quantity < Charges) // if(Quantity < Charges)
{ // {
Customer->SendSingleTraderItem(this->CharacterID(), SerialNumber); // Customer->SendSingleTraderItem(this->CharacterID(), SerialNumber);
m_inv.DeleteItem(Slot, Quantity); // m_inv.DeleteItem(Slot, Quantity);
} // }
else // else
{ // {
EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderDelItem,sizeof(TraderDelItem_Struct)); // EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderDelItem,sizeof(TraderDelItem_Struct));
TraderDelItem_Struct* tdis = (TraderDelItem_Struct*)outapp->pBuffer; // TraderDelItem_Struct* tdis = (TraderDelItem_Struct*)outapp->pBuffer;
//
tdis->Unknown000 = 0; // tdis->Unknown000 = 0;
tdis->TraderID = Customer->GetID(); // tdis->TraderID = Customer->GetID();
if (Customer->GetClientVersion() >= ClientVersion::RoF) // if (Customer->GetClientVersion() >= ClientVersion::RoF)
{ // {
// RoF+ use Item IDs for now // // RoF+ use Item IDs for now
tdis->ItemID = itemid; // tdis->ItemID = itemid;
} // }
else // else
{ // {
tdis->ItemID = SerialNumber; // tdis->ItemID = SerialNumber;
} // }
tdis->Unknown012 = 0; // tdis->Unknown012 = 0;
//
//
Customer->QueuePacket(outapp); // Customer->QueuePacket(outapp);
safe_delete(outapp); // safe_delete(outapp);
//
m_inv.DeleteItem(Slot); // m_inv.DeleteItem(Slot);
} // }
// This updates the trader. Removes it from his trading bags. // // This updates the trader. Removes it from his trading bags.
// // //
const ItemInst* Inst = m_inv[Slot]; // const ItemInst* Inst = m_inv[Slot];
//
database.SaveInventory(CharacterID(), Inst, Slot); // database.SaveInventory(CharacterID(), Inst, Slot);
//
EQApplicationPacket* outapp2; // EQApplicationPacket* outapp2;
//
if(Quantity < Charges) // if(Quantity < Charges)
outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct)); // outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct));
else // else
outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct)); // outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct));
//
MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; // MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer;
mis->from_slot = Slot; // mis->from_slot = Slot;
mis->to_slot = 0xFFFFFFFF; // mis->to_slot = 0xFFFFFFFF;
mis->number_in_stack = 0xFFFFFFFF; // mis->number_in_stack = 0xFFFFFFFF;
//
if(Quantity >= Charges) // if(Quantity >= Charges)
Quantity = 1; // Quantity = 1;
//
for(int i = 0; i < Quantity; i++) { // for(int i = 0; i < Quantity; i++) {
//
this->QueuePacket(outapp2); // this->QueuePacket(outapp2);
} // }
safe_delete(outapp2); // safe_delete(outapp2);
//
} }
void Client::TraderUpdate(uint16 SlotID,uint32 TraderID){ void Client::TraderUpdate(uint16 SlotID,uint32 TraderID){
// This method is no longer used. // This method is no longer used.
@ -2507,347 +2507,347 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) {
} }
void Client::SellToBuyer(const EQApplicationPacket *app) { void Client::SellToBuyer(const EQApplicationPacket *app) {
//
char* Buf = (char *)app->pBuffer; // char* Buf = (char *)app->pBuffer;
//
char ItemName[64]; // char ItemName[64];
//
/*uint32 Action =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused // /*uint32 Action =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused
uint32 Quantity = VARSTRUCT_DECODE_TYPE(uint32, Buf); // uint32 Quantity = VARSTRUCT_DECODE_TYPE(uint32, Buf);
uint32 BuyerID = VARSTRUCT_DECODE_TYPE(uint32, Buf); // uint32 BuyerID = VARSTRUCT_DECODE_TYPE(uint32, Buf);
uint32 BuySlot = VARSTRUCT_DECODE_TYPE(uint32, Buf); // uint32 BuySlot = VARSTRUCT_DECODE_TYPE(uint32, Buf);
uint32 UnknownByte = VARSTRUCT_DECODE_TYPE(uint8, Buf); // uint32 UnknownByte = VARSTRUCT_DECODE_TYPE(uint8, Buf);
uint32 ItemID = VARSTRUCT_DECODE_TYPE(uint32, Buf); // uint32 ItemID = VARSTRUCT_DECODE_TYPE(uint32, Buf);
/* ItemName */ VARSTRUCT_DECODE_STRING(ItemName, Buf); // /* ItemName */ VARSTRUCT_DECODE_STRING(ItemName, Buf);
/*uint32 Unknown2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused // /*uint32 Unknown2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused
uint32 QtyBuyerWants = VARSTRUCT_DECODE_TYPE(uint32, Buf); // uint32 QtyBuyerWants = VARSTRUCT_DECODE_TYPE(uint32, Buf);
UnknownByte = VARSTRUCT_DECODE_TYPE(uint8, Buf); // UnknownByte = VARSTRUCT_DECODE_TYPE(uint8, Buf);
uint32 Price = VARSTRUCT_DECODE_TYPE(uint32, Buf); // uint32 Price = VARSTRUCT_DECODE_TYPE(uint32, Buf);
/*uint32 BuyerID2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused // /*uint32 BuyerID2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused
/*uint32 Unknown3 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused // /*uint32 Unknown3 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused
//
const ItemData *item = database.GetItem(ItemID); // const ItemData *item = database.GetItem(ItemID);
//
if(!item || !Quantity || !Price || !QtyBuyerWants) return; // if(!item || !Quantity || !Price || !QtyBuyerWants) return;
//
if (m_inv.HasItem(ItemID, Quantity, invWhereWorn | invWherePersonal | invWhereCursor) == INVALID_INDEX) { // if (m_inv.HasItem(ItemID, Quantity, invWhereWorn | invWherePersonal | invWhereCursor) == INVALID_INDEX) {
Message(13, "You do not have %i %s on you.", Quantity, item->Name); // Message(13, "You do not have %i %s on you.", Quantity, item->Name);
return; // return;
} // }
//
//
Client *Buyer = entity_list.GetClientByID(BuyerID); // Client *Buyer = entity_list.GetClientByID(BuyerID);
//
if(!Buyer || !Buyer->IsBuyer()) { // if(!Buyer || !Buyer->IsBuyer()) {
Message(13, "The Buyer has gone away."); // Message(13, "The Buyer has gone away.");
return; // return;
} // }
//
// For Stackable items, HasSpaceForItem will try check if there is space to stack with existing stacks in // // For Stackable items, HasSpaceForItem will try check if there is space to stack with existing stacks in
// the buyer inventory. // // the buyer inventory.
if(!(Buyer->GetInv().HasSpaceForItem(item, Quantity))) { // if(!(Buyer->GetInv().HasSpaceForItem(item, Quantity))) {
Message(13, "The Buyer does not have space for %i %s", Quantity, item->Name); // Message(13, "The Buyer does not have space for %i %s", Quantity, item->Name);
return; // return;
} // }
//
if((static_cast<uint64>(Quantity) * static_cast<uint64>(Price)) > MAX_TRANSACTION_VALUE) { // if((static_cast<uint64>(Quantity) * static_cast<uint64>(Price)) > MAX_TRANSACTION_VALUE) {
Message(13, "That would exceed the single transaction limit of %u platinum.", MAX_TRANSACTION_VALUE / 1000); // Message(13, "That would exceed the single transaction limit of %u platinum.", MAX_TRANSACTION_VALUE / 1000);
return; // return;
} // }
//
if(!Buyer->HasMoney(Quantity * Price)) { // if(!Buyer->HasMoney(Quantity * Price)) {
Message(13, "The Buyer does not have sufficient money to purchase that quantity of %s.", item->Name); // Message(13, "The Buyer does not have sufficient money to purchase that quantity of %s.", item->Name);
Buyer->Message(13, "%s tried to sell you %i %s, but you have insufficient funds.", GetName(), Quantity, item->Name); // Buyer->Message(13, "%s tried to sell you %i %s, but you have insufficient funds.", GetName(), Quantity, item->Name);
return; // return;
} // }
//
if(Buyer->CheckLoreConflict(item)) { // if(Buyer->CheckLoreConflict(item)) {
Message(13, "That item is LORE and the Buyer already has one."); // Message(13, "That item is LORE and the Buyer already has one.");
Buyer->Message(13, "%s tried to sell you %s but this item is LORE and you already have one.", // Buyer->Message(13, "%s tried to sell you %s but this item is LORE and you already have one.",
GetName(), item->Name); // GetName(), item->Name);
return; // return;
} // }
//
if(item->NoDrop == 0) { // if(item->NoDrop == 0) {
Message(13, "That item is NODROP."); // Message(13, "That item is NODROP.");
return; // return;
} // }
//
if(!item->Stackable) { // if(!item->Stackable) {
//
for(uint32 i = 0; i < Quantity; i++) { // for(uint32 i = 0; i < Quantity; i++) {
//
int16 SellerSlot = m_inv.HasItem(ItemID, 1, invWhereWorn|invWherePersonal|invWhereCursor); // int16 SellerSlot = m_inv.HasItem(ItemID, 1, invWhereWorn|invWherePersonal|invWhereCursor);
//
// This shouldn't happen, as we already checked there was space in the Buyer's inventory // // This shouldn't happen, as we already checked there was space in the Buyer's inventory
if (SellerSlot == INVALID_INDEX) { // if (SellerSlot == INVALID_INDEX) {
//
if(i > 0) { // if(i > 0) {
// Set the Quantity to the actual number we successfully transferred. // // Set the Quantity to the actual number we successfully transferred.
Quantity = i; // Quantity = i;
break; // break;
} // }
Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); // Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
Message(13, "Internal error while processing transaction."); // Message(13, "Internal error while processing transaction.");
return; // return;
} // }
//
ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot); // ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot);
//
if(!ItemToTransfer || !Buyer->MoveItemToInventory(ItemToTransfer, true)) { // if(!ItemToTransfer || !Buyer->MoveItemToInventory(ItemToTransfer, true)) {
Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); // Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
Message(13, "Internal error while processing transaction."); // Message(13, "Internal error while processing transaction.");
//
if(ItemToTransfer) // if(ItemToTransfer)
safe_delete(ItemToTransfer); // safe_delete(ItemToTransfer);
//
return; // return;
} // }
//
database.SaveInventory(CharacterID(), 0, SellerSlot); // database.SaveInventory(CharacterID(), 0, SellerSlot);
//
safe_delete(ItemToTransfer); // safe_delete(ItemToTransfer);
//
// Remove the item from inventory, clientside // // Remove the item from inventory, clientside
// // //
EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct)); // EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct));
//
MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; // MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer;
mis->from_slot = SellerSlot; // mis->from_slot = SellerSlot;
mis->to_slot = 0xFFFFFFFF; // mis->to_slot = 0xFFFFFFFF;
mis->number_in_stack = 0xFFFFFFFF; // mis->number_in_stack = 0xFFFFFFFF;
//
QueuePacket(outapp2); // QueuePacket(outapp2);
safe_delete(outapp2); // safe_delete(outapp2);
//
} // }
} // }
else { // else {
// Stackable // // Stackable
// // //
uint32 QuantityMoved = 0; // uint32 QuantityMoved = 0;
//
while(QuantityMoved < Quantity) { // while(QuantityMoved < Quantity) {
//
// Find the slot on the seller that has a stack of at least 1 of the item // // Find the slot on the seller that has a stack of at least 1 of the item
int16 SellerSlot = m_inv.HasItem(ItemID, 1, invWhereWorn|invWherePersonal|invWhereCursor); // int16 SellerSlot = m_inv.HasItem(ItemID, 1, invWhereWorn|invWherePersonal|invWhereCursor);
//
if (SellerSlot == INVALID_INDEX) { // if (SellerSlot == INVALID_INDEX) {
Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); // Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
Message(13, "Internal error while processing transaction."); // Message(13, "Internal error while processing transaction.");
return; // return;
} // }
//
ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot); // ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot);
//
if(!ItemToTransfer) { // if(!ItemToTransfer) {
Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); // Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
Message(13, "Internal error while processing transaction."); // Message(13, "Internal error while processing transaction.");
return; // return;
} // }
//
// If the stack we found has less than the quantity we are selling ... // // If the stack we found has less than the quantity we are selling ...
if(ItemToTransfer->GetCharges() <= (Quantity - QuantityMoved)) { // if(ItemToTransfer->GetCharges() <= (Quantity - QuantityMoved)) {
// Transfer the entire stack // // Transfer the entire stack
//
QuantityMoved += ItemToTransfer->GetCharges(); // QuantityMoved += ItemToTransfer->GetCharges();
//
if(!Buyer->MoveItemToInventory(ItemToTransfer, true)) { // if(!Buyer->MoveItemToInventory(ItemToTransfer, true)) {
Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); // Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
Message(13, "Internal error while processing transaction."); // Message(13, "Internal error while processing transaction.");
safe_delete(ItemToTransfer); // safe_delete(ItemToTransfer);
return; // return;
} // }
// Delete the entire stack from the seller's inventory // // Delete the entire stack from the seller's inventory
database.SaveInventory(CharacterID(), 0, SellerSlot); // database.SaveInventory(CharacterID(), 0, SellerSlot);
//
safe_delete(ItemToTransfer); // safe_delete(ItemToTransfer);
//
// and tell the client to do the same. // // and tell the client to do the same.
EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct)); // EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct));
//
MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; // MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer;
mis->from_slot = SellerSlot; // mis->from_slot = SellerSlot;
mis->to_slot = 0xFFFFFFFF; // mis->to_slot = 0xFFFFFFFF;
mis->number_in_stack = 0xFFFFFFFF; // mis->number_in_stack = 0xFFFFFFFF;
//
QueuePacket(outapp2); // QueuePacket(outapp2);
safe_delete(outapp2); // safe_delete(outapp2);
} // }
else { // else {
//Move the amount we need, and put the rest of the stack back in the seller's inventory // //Move the amount we need, and put the rest of the stack back in the seller's inventory
// // //
int QuantityToRemoveFromStack = Quantity - QuantityMoved; // int QuantityToRemoveFromStack = Quantity - QuantityMoved;
//
ItemToTransfer->SetCharges(ItemToTransfer->GetCharges() - QuantityToRemoveFromStack); // ItemToTransfer->SetCharges(ItemToTransfer->GetCharges() - QuantityToRemoveFromStack);
//
m_inv.PutItem(SellerSlot, *ItemToTransfer); // m_inv.PutItem(SellerSlot, *ItemToTransfer);
//
database.SaveInventory(CharacterID(), ItemToTransfer, SellerSlot); // database.SaveInventory(CharacterID(), ItemToTransfer, SellerSlot);
//
ItemToTransfer->SetCharges(QuantityToRemoveFromStack); // ItemToTransfer->SetCharges(QuantityToRemoveFromStack);
//
if(!Buyer->MoveItemToInventory(ItemToTransfer, true)) { // if(!Buyer->MoveItemToInventory(ItemToTransfer, true)) {
Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); // Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
Message(13, "Internal error while processing transaction."); // Message(13, "Internal error while processing transaction.");
safe_delete(ItemToTransfer); // safe_delete(ItemToTransfer);
return; // return;
} // }
//
safe_delete(ItemToTransfer); // safe_delete(ItemToTransfer);
//
EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct)); // EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct));
//
MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; // MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer;
mis->from_slot = SellerSlot; // mis->from_slot = SellerSlot;
mis->to_slot = 0xFFFFFFFF; // mis->to_slot = 0xFFFFFFFF;
mis->number_in_stack = 0xFFFFFFFF; // mis->number_in_stack = 0xFFFFFFFF;
//
for(int i = 0; i < QuantityToRemoveFromStack; i++) // for(int i = 0; i < QuantityToRemoveFromStack; i++)
QueuePacket(outapp2); // QueuePacket(outapp2);
//
safe_delete(outapp2); // safe_delete(outapp2);
//
QuantityMoved = Quantity; // QuantityMoved = Quantity;
} // }
} // }
//
} // }
//
Buyer->TakeMoneyFromPP(Quantity * Price); // Buyer->TakeMoneyFromPP(Quantity * Price);
//
AddMoneyToPP(Quantity * Price, false); // AddMoneyToPP(Quantity * Price, false);
//
if(RuleB(Bazaar, AuditTrail)) // if(RuleB(Bazaar, AuditTrail))
BazaarAuditTrail(GetName(), Buyer->GetName(), ItemName, Quantity, Quantity * Price, 1); // BazaarAuditTrail(GetName(), Buyer->GetName(), ItemName, Quantity, Quantity * Price, 1);
//
// We now send a packet to the Seller, which causes it to display 'You have sold <Qty> <Item> to <Player> for <money>' // // We now send a packet to the Seller, which causes it to display 'You have sold <Qty> <Item> to <Player> for <money>'
// // //
// The PacketLength of 1016 is from the only instance of this packet I have seen, which is from Live, November 2008 // // The PacketLength of 1016 is from the only instance of this packet I have seen, which is from Live, November 2008
// The Titanium/6.2 struct is slightly different in that it appears to use fixed length strings instead of variable // // The Titanium/6.2 struct is slightly different in that it appears to use fixed length strings instead of variable
// length as used on Live. The extra space in the packet is also likely to be used for Item compensation, if we ever // // length as used on Live. The extra space in the packet is also likely to be used for Item compensation, if we ever
// implement that. // // implement that.
// // //
uint32 PacketLength = 1016; // uint32 PacketLength = 1016;
//
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, PacketLength); // EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, PacketLength);
//
Buf = (char *)outapp->pBuffer; // Buf = (char *)outapp->pBuffer;
//
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_SellerTransactionComplete); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_SellerTransactionComplete);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price);
//
if(GetClientVersion() >= ClientVersion::SoD) // if(GetClientVersion() >= ClientVersion::SoD)
{ // {
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Think this is the upper 32 bits of a 64 bit price // VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Think this is the upper 32 bits of a 64 bit price
} // }
//
sprintf(Buf, "%s", Buyer->GetName()); Buf += 64; // sprintf(Buf, "%s", Buyer->GetName()); Buf += 64;
//
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00);
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01); // VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00);
//
sprintf(Buf, "%s", ItemName); Buf += 64; // sprintf(Buf, "%s", ItemName); Buf += 64;
//
QueuePacket(outapp); // QueuePacket(outapp);
//
// This next packet goes to the Buyer and produces the 'You've bought <Qty> <Item> from <Seller> for <money>' // // This next packet goes to the Buyer and produces the 'You've bought <Qty> <Item> from <Seller> for <money>'
// // //
//
Buf = (char *)outapp->pBuffer; // Buf = (char *)outapp->pBuffer;
//
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerTransactionComplete); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerTransactionComplete);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price);
//
if(Buyer->GetClientVersion() >= ClientVersion::SoD) // if(Buyer->GetClientVersion() >= ClientVersion::SoD)
{ // {
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Think this is the upper 32 bits of a 64 bit price // VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Think this is the upper 32 bits of a 64 bit price
} // }
//
sprintf(Buf, "%s", GetName()); Buf += 64; // sprintf(Buf, "%s", GetName()); Buf += 64;
//
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00);
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01); // VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00);
//
sprintf(Buf, "%s", ItemName); Buf += 64; // sprintf(Buf, "%s", ItemName); Buf += 64;
//
Buyer->QueuePacket(outapp); // Buyer->QueuePacket(outapp);
//
safe_delete(outapp); // safe_delete(outapp);
//
// Next we update the buyer table in the database to reflect the reduced quantity the Buyer wants to buy. // // Next we update the buyer table in the database to reflect the reduced quantity the Buyer wants to buy.
// // //
database.UpdateBuyLine(Buyer->CharacterID(), BuySlot, QtyBuyerWants - Quantity); // database.UpdateBuyLine(Buyer->CharacterID(), BuySlot, QtyBuyerWants - Quantity);
//
// Next we update the Seller's Barter Window to reflect the reduced quantity the Buyer is now looking to buy. // // Next we update the Seller's Barter Window to reflect the reduced quantity the Buyer is now looking to buy.
// // //
EQApplicationPacket* outapp3 = new EQApplicationPacket(OP_Barter, 936); // EQApplicationPacket* outapp3 = new EQApplicationPacket(OP_Barter, 936);
//
Buf = (char *)outapp3->pBuffer; // Buf = (char *)outapp3->pBuffer;
//
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerInspectWindow); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerInspectWindow);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot);
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // Unknown // VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // Unknown
VARSTRUCT_ENCODE_TYPE(uint32, Buf,ItemID); // VARSTRUCT_ENCODE_TYPE(uint32, Buf,ItemID);
VARSTRUCT_ENCODE_STRING(Buf, ItemName); // VARSTRUCT_ENCODE_STRING(Buf, ItemName);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, QtyBuyerWants - Quantity); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, QtyBuyerWants - Quantity);
//
// If the amount we have just sold completely satisfies the quantity the Buyer was looking for, // // If the amount we have just sold completely satisfies the quantity the Buyer was looking for,
// setting the next byte to 0 will remove the item from the Barter Window. // // setting the next byte to 0 will remove the item from the Barter Window.
// // //
if(QtyBuyerWants - Quantity > 0) { // if(QtyBuyerWants - Quantity > 0) {
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // 0 = Toggle Off, 1 = Toggle On // VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // 0 = Toggle Off, 1 = Toggle On
} // }
else { // else {
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0); // 0 = Toggle Off, 1 = Toggle On // VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0); // 0 = Toggle Off, 1 = Toggle On
} // }
//
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Buyer->GetID()); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, Buyer->GetID());
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0);
//
VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName()); // VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName());
//
QueuePacket(outapp3); // QueuePacket(outapp3);
safe_delete(outapp3); // safe_delete(outapp3);
//
// The next packet updates the /buyer window with the reduced quantity, and toggles the buy line off if the // // The next packet updates the /buyer window with the reduced quantity, and toggles the buy line off if the
// quantity they wanted to buy has been met. // // quantity they wanted to buy has been met.
// // //
EQApplicationPacket* outapp4 = new EQApplicationPacket(OP_Barter, 936); // EQApplicationPacket* outapp4 = new EQApplicationPacket(OP_Barter, 936);
//
Buf = (char*)outapp4->pBuffer; // Buf = (char*)outapp4->pBuffer;
//
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerItemUpdate); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerItemUpdate);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot);
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, ItemID); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, ItemID);
VARSTRUCT_ENCODE_STRING(Buf, ItemName); // VARSTRUCT_ENCODE_STRING(Buf, ItemName);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, QtyBuyerWants - Quantity); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, QtyBuyerWants - Quantity);
//
if((QtyBuyerWants - Quantity) > 0) { // if((QtyBuyerWants - Quantity) > 0) {
//
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // 0 = Toggle Off, 1 = Toggle On // VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // 0 = Toggle Off, 1 = Toggle On
} // }
else { // else {
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0); // 0 = Toggle Off, 1 = Toggle On // VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0); // 0 = Toggle Off, 1 = Toggle On
} // }
//
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price);
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x08f4); // Unknown // VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x08f4); // Unknown
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0);
VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName()); // VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName());
//
Buyer->QueuePacket(outapp4); // Buyer->QueuePacket(outapp4);
safe_delete(outapp4); // safe_delete(outapp4);
//
return; // return;
} }
void Client::SendBuyerPacket(Client* Buyer) { void Client::SendBuyerPacket(Client* Buyer) {