mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-31 16:01:29 +00:00
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:
parent
8bce7893ed
commit
69612b44d4
@ -1556,7 +1556,7 @@ struct DeleteItem_Struct {
|
||||
/*0012*/
|
||||
};
|
||||
|
||||
struct MoveItem_Struct
|
||||
struct MoveItemOld_Struct
|
||||
{
|
||||
/*0000*/ uint32 from_slot;
|
||||
/*0004*/ uint32 to_slot;
|
||||
@ -1564,6 +1564,19 @@ struct MoveItem_Struct
|
||||
/*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
|
||||
// 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)
|
||||
|
||||
@ -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()));
|
||||
}
|
||||
|
||||
//Verify item can be put into the slot requested
|
||||
|
||||
auto &container = impl_->containers_[slot.type_];
|
||||
if(slot.bag_index_ > -1) {
|
||||
auto item = container.Get(slot.slot_);
|
||||
@ -92,10 +94,64 @@ bool EQEmu::Inventory::Put(const InventorySlot &slot, std::shared_ptr<ItemInstan
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
buf.SetWritePosition(0);
|
||||
buf.SetReadPosition(0);
|
||||
|
||||
@ -51,6 +51,44 @@ namespace EQEmu
|
||||
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
|
||||
{
|
||||
public:
|
||||
@ -59,8 +97,11 @@ namespace EQEmu
|
||||
|
||||
std::shared_ptr<ItemInstance> Get(const InventorySlot &slot);
|
||||
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);
|
||||
private:
|
||||
struct impl;
|
||||
|
||||
@ -192,14 +192,56 @@ void EQEmu::ItemInstance::SetCustomData(const std::string &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) {
|
||||
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) {
|
||||
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) {
|
||||
impl_->ornament_hero_model_ = ornament_hero_model;
|
||||
}
|
||||
|
||||
@ -53,8 +53,17 @@ namespace EQEmu
|
||||
void SetAttuned(const bool attuned);
|
||||
|
||||
void SetCustomData(const std::string &custom_data);
|
||||
|
||||
uint32 GetOrnamentIDFile();
|
||||
uint32 GetOrnamentIDFile() const;
|
||||
void SetOrnamentIDFile(const uint32 ornament_idfile);
|
||||
|
||||
uint32 GetOrnamentIcon();
|
||||
uint32 GetOrnamentIcon() const;
|
||||
void SetOrnamentIcon(const uint32 ornament_icon);
|
||||
|
||||
uint32 GetOrnamentHeroModel(int material_slot);
|
||||
uint32 GetOrnamentHeroModel(int material_slot) const;
|
||||
void SetOrnamentHeroModel(const uint32 ornament_hero_model);
|
||||
|
||||
const char* GetTrackingID();
|
||||
|
||||
@ -32,20 +32,30 @@ EQEmu::MemoryBuffer::MemoryBuffer(const MemoryBuffer &other) {
|
||||
}
|
||||
|
||||
EQEmu::MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) {
|
||||
buffer_ = other.buffer_;
|
||||
size_ = other.size_;
|
||||
capacity_ = other.capacity_;
|
||||
write_pos_ = other.write_pos_;
|
||||
read_pos_ = other.read_pos_;
|
||||
uchar *tbuf = other.buffer_;
|
||||
size_t tsz = other.size_;
|
||||
size_t tcapacity = other.capacity_;
|
||||
size_t twrite_pos = other.write_pos_;
|
||||
size_t tread_pos = other.read_pos_;
|
||||
|
||||
other.buffer_ = nullptr;
|
||||
other.size_ = 0;
|
||||
other.capacity_ = 0;
|
||||
other.read_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) {
|
||||
if(buffer_) {
|
||||
delete[] buffer_;
|
||||
}
|
||||
|
||||
if(other.capacity_) {
|
||||
buffer_ = new uchar[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) {
|
||||
buffer_ = other.buffer_;
|
||||
size_ = other.size_;
|
||||
capacity_ = other.capacity_;
|
||||
write_pos_ = other.write_pos_;
|
||||
read_pos_ = other.read_pos_;
|
||||
uchar *tbuf = other.buffer_;
|
||||
size_t tsz = other.size_;
|
||||
size_t tcapacity = other.capacity_;
|
||||
size_t twrite_pos = other.write_pos_;
|
||||
size_t tread_pos = other.read_pos_;
|
||||
|
||||
other.buffer_ = nullptr;
|
||||
other.size_ = 0;
|
||||
other.capacity_ = 0;
|
||||
other.read_pos_ = 0;
|
||||
other.write_pos_ = 0;
|
||||
|
||||
buffer_ = tbuf;
|
||||
size_ = tsz;
|
||||
capacity_ = tcapacity;
|
||||
write_pos_ = twrite_pos;
|
||||
read_pos_ = tread_pos;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@ -10,19 +10,19 @@
|
||||
#include "rof2.h"
|
||||
|
||||
void RegisterAllPatches(EQStreamIdentifier &into) {
|
||||
Titanium::Register(into);
|
||||
SoF::Register(into);
|
||||
SoD::Register(into);
|
||||
UF::Register(into);
|
||||
RoF::Register(into);
|
||||
//Titanium::Register(into);
|
||||
//SoF::Register(into);
|
||||
//SoD::Register(into);
|
||||
//UF::Register(into);
|
||||
//RoF::Register(into);
|
||||
RoF2::Register(into);
|
||||
}
|
||||
|
||||
void ReloadAllPatches() {
|
||||
Titanium::Reload();
|
||||
SoF::Reload();
|
||||
SoD::Reload();
|
||||
UF::Reload();
|
||||
RoF::Reload();
|
||||
//Titanium::Reload();
|
||||
//SoF::Reload();
|
||||
//SoD::Reload();
|
||||
//UF::Reload();
|
||||
//RoF::Reload();
|
||||
RoF2::Reload();
|
||||
}
|
||||
|
||||
@ -1707,14 +1707,14 @@ namespace RoF
|
||||
|
||||
ENCODE(OP_MoveItem)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
eq->from_slot = ServerToRoFSlot(emu->from_slot);
|
||||
eq->to_slot = ServerToRoFSlot(emu->to_slot);
|
||||
OUT(number_in_stack);
|
||||
|
||||
FINISH_ENCODE();
|
||||
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//eq->from_slot = ServerToRoFSlot(emu->from_slot);
|
||||
//eq->to_slot = ServerToRoFSlot(emu->to_slot);
|
||||
//OUT(number_in_stack);
|
||||
//
|
||||
//FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
|
||||
@ -4684,16 +4684,16 @@ namespace RoF
|
||||
|
||||
DECODE(OP_MoveItem)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(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.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->to_slot = RoFToServerSlot(eq->to_slot);
|
||||
IN(number_in_stack);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
//DECODE_LENGTH_EXACT(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.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->to_slot = RoFToServerSlot(eq->to_slot);
|
||||
//IN(number_in_stack);
|
||||
//
|
||||
//FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_PetCommands)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1265,14 +1265,14 @@ namespace SoD
|
||||
|
||||
ENCODE(OP_MoveItem)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
eq->from_slot = ServerToSoDSlot(emu->from_slot);
|
||||
eq->to_slot = ServerToSoDSlot(emu->to_slot);
|
||||
OUT(number_in_stack);
|
||||
|
||||
FINISH_ENCODE();
|
||||
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//eq->from_slot = ServerToSoDSlot(emu->from_slot);
|
||||
//eq->to_slot = ServerToSoDSlot(emu->to_slot);
|
||||
//OUT(number_in_stack);
|
||||
//
|
||||
//FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
|
||||
@ -3260,16 +3260,16 @@ namespace SoD
|
||||
|
||||
DECODE(OP_MoveItem)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(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);
|
||||
|
||||
emu->from_slot = SoDToServerSlot(eq->from_slot);
|
||||
emu->to_slot = SoDToServerSlot(eq->to_slot);
|
||||
IN(number_in_stack);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
//DECODE_LENGTH_EXACT(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);
|
||||
//
|
||||
//emu->from_slot = SoDToServerSlot(eq->from_slot);
|
||||
//emu->to_slot = SoDToServerSlot(eq->to_slot);
|
||||
//IN(number_in_stack);
|
||||
//
|
||||
//FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_PetCommands)
|
||||
|
||||
@ -930,14 +930,14 @@ namespace SoF
|
||||
|
||||
ENCODE(OP_MoveItem)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
eq->from_slot = ServerToSoFSlot(emu->from_slot);
|
||||
eq->to_slot = ServerToSoFSlot(emu->to_slot);
|
||||
OUT(number_in_stack);
|
||||
|
||||
FINISH_ENCODE();
|
||||
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//eq->from_slot = ServerToSoFSlot(emu->from_slot);
|
||||
//eq->to_slot = ServerToSoFSlot(emu->to_slot);
|
||||
//OUT(number_in_stack);
|
||||
//
|
||||
//FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
|
||||
@ -2598,16 +2598,16 @@ namespace SoF
|
||||
|
||||
DECODE(OP_MoveItem)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(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);
|
||||
|
||||
emu->from_slot = SoFToServerSlot(eq->from_slot);
|
||||
emu->to_slot = SoFToServerSlot(eq->to_slot);
|
||||
IN(number_in_stack);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
//DECODE_LENGTH_EXACT(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);
|
||||
//
|
||||
//emu->from_slot = SoFToServerSlot(eq->from_slot);
|
||||
//emu->to_slot = SoFToServerSlot(eq->to_slot);
|
||||
//IN(number_in_stack);
|
||||
//
|
||||
//FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_PetCommands)
|
||||
|
||||
@ -778,14 +778,14 @@ namespace Titanium
|
||||
|
||||
ENCODE(OP_MoveItem)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
eq->from_slot = ServerToTitaniumSlot(emu->from_slot);
|
||||
eq->to_slot = ServerToTitaniumSlot(emu->to_slot);
|
||||
OUT(number_in_stack);
|
||||
|
||||
FINISH_ENCODE();
|
||||
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//eq->from_slot = ServerToTitaniumSlot(emu->from_slot);
|
||||
//eq->to_slot = ServerToTitaniumSlot(emu->to_slot);
|
||||
//OUT(number_in_stack);
|
||||
//
|
||||
//FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
|
||||
@ -1854,16 +1854,16 @@ namespace Titanium
|
||||
|
||||
DECODE(OP_MoveItem)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(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);
|
||||
|
||||
emu->from_slot = TitaniumToServerSlot(eq->from_slot);
|
||||
emu->to_slot = TitaniumToServerSlot(eq->to_slot);
|
||||
IN(number_in_stack);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
//DECODE_LENGTH_EXACT(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);
|
||||
//
|
||||
//emu->from_slot = TitaniumToServerSlot(eq->from_slot);
|
||||
//emu->to_slot = TitaniumToServerSlot(eq->to_slot);
|
||||
//IN(number_in_stack);
|
||||
//
|
||||
//FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_PetCommands)
|
||||
|
||||
@ -1504,14 +1504,14 @@ namespace UF
|
||||
|
||||
ENCODE(OP_MoveItem)
|
||||
{
|
||||
ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
|
||||
eq->from_slot = ServerToUFSlot(emu->from_slot);
|
||||
eq->to_slot = ServerToUFSlot(emu->to_slot);
|
||||
OUT(number_in_stack);
|
||||
|
||||
FINISH_ENCODE();
|
||||
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
|
||||
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
|
||||
//
|
||||
//eq->from_slot = ServerToUFSlot(emu->from_slot);
|
||||
//eq->to_slot = ServerToUFSlot(emu->to_slot);
|
||||
//OUT(number_in_stack);
|
||||
//
|
||||
//FINISH_ENCODE();
|
||||
}
|
||||
|
||||
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
|
||||
@ -3582,16 +3582,16 @@ namespace UF
|
||||
|
||||
DECODE(OP_MoveItem)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(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);
|
||||
|
||||
emu->from_slot = UFToServerSlot(eq->from_slot);
|
||||
emu->to_slot = UFToServerSlot(eq->to_slot);
|
||||
IN(number_in_stack);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
//DECODE_LENGTH_EXACT(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);
|
||||
//
|
||||
//emu->from_slot = UFToServerSlot(eq->from_slot);
|
||||
//emu->to_slot = UFToServerSlot(eq->to_slot);
|
||||
//IN(number_in_stack);
|
||||
//
|
||||
//FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
DECODE(OP_PetCommands)
|
||||
|
||||
@ -175,7 +175,7 @@ private:
|
||||
|
||||
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);
|
||||
|
||||
auto m_bag = inv.Get(EQEmu::InventorySlot(0, 24));
|
||||
|
||||
@ -33,6 +33,7 @@ public:
|
||||
TEST_ADD(MemoryBufferTest::CopyTest);
|
||||
TEST_ADD(MemoryBufferTest::AssignTest);
|
||||
TEST_ADD(MemoryBufferTest::MoveTest);
|
||||
TEST_ADD(MemoryBufferTest::SelfTest);
|
||||
TEST_ADD(MemoryBufferTest::ZeroTest);
|
||||
TEST_ADD(MemoryBufferTest::ClearTest);
|
||||
TEST_ADD(MemoryBufferTest::AddTest)
|
||||
@ -449,6 +450,22 @@ private:
|
||||
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()
|
||||
{
|
||||
mb.Zero();
|
||||
|
||||
@ -813,9 +813,9 @@ public:
|
||||
bool PushItemOnCursor(const ItemInst& inst, bool client_update = false);
|
||||
void SendCursorBuffer();
|
||||
void DeleteItemInInventory(int16 slot_id, int8 quantity = 0, bool client_update = false, bool update_db = true);
|
||||
bool SwapItem(MoveItem_Struct* move_in);
|
||||
void SwapItemResync(MoveItem_Struct* move_slots);
|
||||
void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false);
|
||||
bool SwapItem(MoveItemOld_Struct* move_in);
|
||||
void SwapItemResync(MoveItemOld_Struct* move_slots);
|
||||
void QSSwapItemAuditor(MoveItemOld_Struct* move_in, bool postaction_call = false);
|
||||
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 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);
|
||||
|
||||
@ -9586,68 +9586,77 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
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));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
MoveItem_Struct* mi = (MoveItem_Struct*)app->pBuffer;
|
||||
if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id))
|
||||
{
|
||||
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))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
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),
|
||||
mi->number_in_stack);
|
||||
|
||||
// Illegal bagslot usage checks. Currently, user only receives a message if this check is triggered.
|
||||
bool mi_hack = false;
|
||||
//printf("%i %i %i %i --> %i %i %i %i (%u)\n",
|
||||
// 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 (mi->from_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; }
|
||||
else {
|
||||
int16 from_parent = m_inv.CalcSlotId(mi->from_slot);
|
||||
if (!m_inv[from_parent]) { mi_hack = true; }
|
||||
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; }
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
//if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id))
|
||||
//{
|
||||
// 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))
|
||||
// {
|
||||
// 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.
|
||||
//bool mi_hack = false;
|
||||
//
|
||||
//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; }
|
||||
// else {
|
||||
// int16 from_parent = m_inv.CalcSlotId(mi->from_slot);
|
||||
// if (!m_inv[from_parent]) { mi_hack = true; }
|
||||
// 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; }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//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)
|
||||
|
||||
142
zone/command.cpp
142
zone/command.cpp
@ -3119,77 +3119,77 @@ void command_listpetition(Client *c, const Seperator *sep)
|
||||
|
||||
void command_equipitem(Client *c, const Seperator *sep)
|
||||
{
|
||||
uint32 slot_id = atoi(sep->arg[1]);
|
||||
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* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack)
|
||||
bool partialmove = false;
|
||||
int16 movecount;
|
||||
|
||||
if (from_inst && from_inst->IsType(ItemClassCommon)) {
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct));
|
||||
MoveItem_Struct* mi = (MoveItem_Struct*)outapp->pBuffer;
|
||||
mi->from_slot = MainCursor;
|
||||
mi->to_slot = slot_id;
|
||||
// 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
|
||||
if (to_inst && to_inst->IsStackable() &&
|
||||
(to_inst->GetItem()->ID == from_inst->GetItem()->ID) &&
|
||||
(to_inst->GetCharges() < to_inst->GetItem()->StackSize) &&
|
||||
(from_inst->GetCharges() > to_inst->GetItem()->StackSize - to_inst->GetCharges())) {
|
||||
movecount = to_inst->GetItem()->StackSize - to_inst->GetCharges();
|
||||
mi->number_in_stack = (uint32)movecount;
|
||||
partialmove = true;
|
||||
}
|
||||
else
|
||||
mi->number_in_stack = from_inst->GetCharges();
|
||||
|
||||
// Save move changes
|
||||
// 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
|
||||
// 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");
|
||||
return;
|
||||
}
|
||||
else if(c->SwapItem(mi)) {
|
||||
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
|
||||
|
||||
// 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)
|
||||
//if (partialmove) {
|
||||
// EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct));
|
||||
// DeleteItem_Struct* di = (DeleteItem_Struct*)outapp2->pBuffer;
|
||||
// di->from_slot = SLOT_CURSOR;
|
||||
// di->to_slot = 0xFFFFFFFF;
|
||||
// di->number_in_stack = 0xFFFFFFFF;
|
||||
|
||||
// c->Message(0, "Deleting %i charges from stack", movecount); // debug line..delete
|
||||
|
||||
// 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...)
|
||||
// c->QueuePacket(outapp2);
|
||||
|
||||
// safe_delete(outapp2);
|
||||
//}
|
||||
}
|
||||
else {
|
||||
c->Message(13, "Error: Unable to equip current item");
|
||||
}
|
||||
safe_delete(outapp);
|
||||
|
||||
// also send out a wear change packet?
|
||||
}
|
||||
else if (from_inst == nullptr)
|
||||
c->Message(13, "Error: There is no item on your cursor");
|
||||
else
|
||||
c->Message(13, "Error: Item on your cursor cannot be equipped");
|
||||
}
|
||||
else
|
||||
c->Message(0, "Usage: #equipitem slotid[0-21] - equips the item on your cursor to the position");
|
||||
// uint32 slot_id = atoi(sep->arg[1]);
|
||||
// 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* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack)
|
||||
// bool partialmove = false;
|
||||
// int16 movecount;
|
||||
//
|
||||
// if (from_inst && from_inst->IsType(ItemClassCommon)) {
|
||||
// EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct));
|
||||
// MoveItem_Struct* mi = (MoveItem_Struct*)outapp->pBuffer;
|
||||
// mi->from_slot = MainCursor;
|
||||
// mi->to_slot = slot_id;
|
||||
// // 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
|
||||
// if (to_inst && to_inst->IsStackable() &&
|
||||
// (to_inst->GetItem()->ID == from_inst->GetItem()->ID) &&
|
||||
// (to_inst->GetCharges() < to_inst->GetItem()->StackSize) &&
|
||||
// (from_inst->GetCharges() > to_inst->GetItem()->StackSize - to_inst->GetCharges())) {
|
||||
// movecount = to_inst->GetItem()->StackSize - to_inst->GetCharges();
|
||||
// mi->number_in_stack = (uint32)movecount;
|
||||
// partialmove = true;
|
||||
// }
|
||||
// else
|
||||
// mi->number_in_stack = from_inst->GetCharges();
|
||||
//
|
||||
// // Save move changes
|
||||
// // 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
|
||||
// // 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");
|
||||
// return;
|
||||
// }
|
||||
// else if(c->SwapItem(mi)) {
|
||||
// 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
|
||||
//
|
||||
// // 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)
|
||||
// //if (partialmove) {
|
||||
// // EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct));
|
||||
// // DeleteItem_Struct* di = (DeleteItem_Struct*)outapp2->pBuffer;
|
||||
// // di->from_slot = SLOT_CURSOR;
|
||||
// // di->to_slot = 0xFFFFFFFF;
|
||||
// // di->number_in_stack = 0xFFFFFFFF;
|
||||
//
|
||||
// // c->Message(0, "Deleting %i charges from stack", movecount); // debug line..delete
|
||||
//
|
||||
// // 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...)
|
||||
// // c->QueuePacket(outapp2);
|
||||
//
|
||||
// // safe_delete(outapp2);
|
||||
// //}
|
||||
// }
|
||||
// else {
|
||||
// c->Message(13, "Error: Unable to equip current item");
|
||||
// }
|
||||
// safe_delete(outapp);
|
||||
//
|
||||
// // also send out a wear change packet?
|
||||
// }
|
||||
// else if (from_inst == nullptr)
|
||||
// c->Message(13, "Error: There is no item on your cursor");
|
||||
// else
|
||||
// c->Message(13, "Error: Item on your cursor cannot be equipped");
|
||||
// }
|
||||
// else
|
||||
// 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)
|
||||
|
||||
@ -716,122 +716,122 @@ void Client::SendCursorBuffer()
|
||||
|
||||
// Remove item from inventory
|
||||
void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_update, bool update_db) {
|
||||
#if (EQDEBUG >= 5)
|
||||
Log.Out(Logs::General, Logs::None, "DeleteItemInInventory(%i, %i, %s)", slot_id, quantity, (client_update) ? "true":"false");
|
||||
#endif
|
||||
|
||||
// Added 'IsSlotValid(slot_id)' check to both segments of client packet processing.
|
||||
// - cursor queue slots were slipping through and crashing client
|
||||
if(!m_inv[slot_id]) {
|
||||
// Make sure the client deletes anything in this slot to match the server.
|
||||
if(client_update && IsValidSlot(slot_id)) {
|
||||
EQApplicationPacket* outapp;
|
||||
outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct));
|
||||
DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer;
|
||||
delitem->from_slot = slot_id;
|
||||
delitem->to_slot = 0xFFFFFFFF;
|
||||
delitem->number_in_stack = 0xFFFFFFFF;
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// start QS code
|
||||
if(RuleB(QueryServ, PlayerLogDeletes)) {
|
||||
uint16 delete_count = 0;
|
||||
|
||||
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));
|
||||
QSPlayerLogDelete_Struct* qsaudit = (QSPlayerLogDelete_Struct*)qspack->pBuffer;
|
||||
uint16 parent_offset = 0;
|
||||
|
||||
qsaudit->char_id = character_id;
|
||||
qsaudit->stack_size = quantity;
|
||||
qsaudit->char_count = delete_count;
|
||||
|
||||
qsaudit->items[parent_offset].char_slot = slot_id;
|
||||
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].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_3 = m_inv[slot_id]->GetAugmentItemID(3);
|
||||
qsaudit->items[parent_offset].aug_4 = m_inv[slot_id]->GetAugmentItemID(4);
|
||||
qsaudit->items[parent_offset].aug_5 = m_inv[slot_id]->GetAugmentItemID(5);
|
||||
|
||||
if(m_inv[slot_id]->IsType(ItemClassContainer)) {
|
||||
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);
|
||||
|
||||
if(bagitem) {
|
||||
int16 bagslot_id = InventoryOld::CalcSlotId(slot_id, bag_idx);
|
||||
|
||||
qsaudit->items[++parent_offset].char_slot = bagslot_id;
|
||||
qsaudit->items[parent_offset].item_id = bagitem->GetID();
|
||||
qsaudit->items[parent_offset].charges = bagitem->GetCharges();
|
||||
qsaudit->items[parent_offset].aug_1 = bagitem->GetAugmentItemID(1);
|
||||
qsaudit->items[parent_offset].aug_2 = bagitem->GetAugmentItemID(2);
|
||||
qsaudit->items[parent_offset].aug_3 = bagitem->GetAugmentItemID(3);
|
||||
qsaudit->items[parent_offset].aug_4 = bagitem->GetAugmentItemID(4);
|
||||
qsaudit->items[parent_offset].aug_5 = bagitem->GetAugmentItemID(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qspack->Deflate();
|
||||
if(worldserver.Connected()) { worldserver.SendPacket(qspack); }
|
||||
safe_delete(qspack);
|
||||
}
|
||||
// end QS code
|
||||
|
||||
bool isDeleted = m_inv.DeleteItem(slot_id, quantity);
|
||||
|
||||
const ItemInst* inst = nullptr;
|
||||
if (slot_id == MainCursor) {
|
||||
auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
|
||||
if(update_db)
|
||||
database.SaveCursor(character_id, s, e);
|
||||
}
|
||||
else {
|
||||
// Save change to database
|
||||
inst = m_inv[slot_id];
|
||||
if(update_db)
|
||||
database.SaveInventory(character_id, inst, slot_id);
|
||||
}
|
||||
|
||||
if(client_update && IsValidSlot(slot_id)) {
|
||||
EQApplicationPacket* outapp = nullptr;
|
||||
if(inst) {
|
||||
if (!inst->IsStackable() && !isDeleted) {
|
||||
// Non stackable item with charges = Item with clicky spell effect ? Delete a charge.
|
||||
outapp = new EQApplicationPacket(OP_DeleteCharge, sizeof(MoveItem_Struct));
|
||||
}
|
||||
else {
|
||||
// Stackable, arrows, etc ? Delete one from the stack
|
||||
outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(MoveItem_Struct));
|
||||
}
|
||||
|
||||
DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer;
|
||||
delitem->from_slot = slot_id;
|
||||
delitem->to_slot = 0xFFFFFFFF;
|
||||
delitem->number_in_stack = 0xFFFFFFFF;
|
||||
|
||||
for(int loop=0;loop<quantity;loop++)
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
else {
|
||||
outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct));
|
||||
MoveItem_Struct* delitem = (MoveItem_Struct*)outapp->pBuffer;
|
||||
delitem->from_slot = slot_id;
|
||||
delitem->to_slot = 0xFFFFFFFF;
|
||||
delitem->number_in_stack = 0xFFFFFFFF;
|
||||
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
// #if (EQDEBUG >= 5)
|
||||
// Log.Out(Logs::General, Logs::None, "DeleteItemInInventory(%i, %i, %s)", slot_id, quantity, (client_update) ? "true":"false");
|
||||
// #endif
|
||||
//
|
||||
// // Added 'IsSlotValid(slot_id)' check to both segments of client packet processing.
|
||||
// // - cursor queue slots were slipping through and crashing client
|
||||
// if(!m_inv[slot_id]) {
|
||||
// // Make sure the client deletes anything in this slot to match the server.
|
||||
// if(client_update && IsValidSlot(slot_id)) {
|
||||
// EQApplicationPacket* outapp;
|
||||
// outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct));
|
||||
// DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer;
|
||||
// delitem->from_slot = slot_id;
|
||||
// delitem->to_slot = 0xFFFFFFFF;
|
||||
// delitem->number_in_stack = 0xFFFFFFFF;
|
||||
// QueuePacket(outapp);
|
||||
// safe_delete(outapp);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // start QS code
|
||||
// if(RuleB(QueryServ, PlayerLogDeletes)) {
|
||||
// uint16 delete_count = 0;
|
||||
//
|
||||
// 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));
|
||||
// QSPlayerLogDelete_Struct* qsaudit = (QSPlayerLogDelete_Struct*)qspack->pBuffer;
|
||||
// uint16 parent_offset = 0;
|
||||
//
|
||||
// qsaudit->char_id = character_id;
|
||||
// qsaudit->stack_size = quantity;
|
||||
// qsaudit->char_count = delete_count;
|
||||
//
|
||||
// qsaudit->items[parent_offset].char_slot = slot_id;
|
||||
// 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].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_3 = m_inv[slot_id]->GetAugmentItemID(3);
|
||||
// qsaudit->items[parent_offset].aug_4 = m_inv[slot_id]->GetAugmentItemID(4);
|
||||
// qsaudit->items[parent_offset].aug_5 = m_inv[slot_id]->GetAugmentItemID(5);
|
||||
//
|
||||
// if(m_inv[slot_id]->IsType(ItemClassContainer)) {
|
||||
// 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);
|
||||
//
|
||||
// if(bagitem) {
|
||||
// int16 bagslot_id = InventoryOld::CalcSlotId(slot_id, bag_idx);
|
||||
//
|
||||
// qsaudit->items[++parent_offset].char_slot = bagslot_id;
|
||||
// qsaudit->items[parent_offset].item_id = bagitem->GetID();
|
||||
// qsaudit->items[parent_offset].charges = bagitem->GetCharges();
|
||||
// qsaudit->items[parent_offset].aug_1 = bagitem->GetAugmentItemID(1);
|
||||
// qsaudit->items[parent_offset].aug_2 = bagitem->GetAugmentItemID(2);
|
||||
// qsaudit->items[parent_offset].aug_3 = bagitem->GetAugmentItemID(3);
|
||||
// qsaudit->items[parent_offset].aug_4 = bagitem->GetAugmentItemID(4);
|
||||
// qsaudit->items[parent_offset].aug_5 = bagitem->GetAugmentItemID(5);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// qspack->Deflate();
|
||||
// if(worldserver.Connected()) { worldserver.SendPacket(qspack); }
|
||||
// safe_delete(qspack);
|
||||
// }
|
||||
// // end QS code
|
||||
//
|
||||
// bool isDeleted = m_inv.DeleteItem(slot_id, quantity);
|
||||
//
|
||||
// const ItemInst* inst = nullptr;
|
||||
// if (slot_id == MainCursor) {
|
||||
// auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
|
||||
// if(update_db)
|
||||
// database.SaveCursor(character_id, s, e);
|
||||
// }
|
||||
// else {
|
||||
// // Save change to database
|
||||
// inst = m_inv[slot_id];
|
||||
// if(update_db)
|
||||
// database.SaveInventory(character_id, inst, slot_id);
|
||||
// }
|
||||
//
|
||||
// if(client_update && IsValidSlot(slot_id)) {
|
||||
// EQApplicationPacket* outapp = nullptr;
|
||||
// if(inst) {
|
||||
// if (!inst->IsStackable() && !isDeleted) {
|
||||
// // Non stackable item with charges = Item with clicky spell effect ? Delete a charge.
|
||||
// outapp = new EQApplicationPacket(OP_DeleteCharge, sizeof(MoveItem_Struct));
|
||||
// }
|
||||
// else {
|
||||
// // Stackable, arrows, etc ? Delete one from the stack
|
||||
// outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(MoveItem_Struct));
|
||||
// }
|
||||
//
|
||||
// DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer;
|
||||
// delitem->from_slot = slot_id;
|
||||
// delitem->to_slot = 0xFFFFFFFF;
|
||||
// delitem->number_in_stack = 0xFFFFFFFF;
|
||||
//
|
||||
// for(int loop=0;loop<quantity;loop++)
|
||||
// QueuePacket(outapp);
|
||||
// safe_delete(outapp);
|
||||
// }
|
||||
// else {
|
||||
// outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct));
|
||||
// MoveItem_Struct* delitem = (MoveItem_Struct*)outapp->pBuffer;
|
||||
// delitem->from_slot = slot_id;
|
||||
// delitem->to_slot = 0xFFFFFFFF;
|
||||
// delitem->number_in_stack = 0xFFFFFFFF;
|
||||
//
|
||||
// QueuePacket(outapp);
|
||||
// safe_delete(outapp);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
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
|
||||
// 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 dst_slot_check = move_in->to_slot;
|
||||
@ -1788,7 +1788,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Client::SwapItemResync(MoveItem_Struct* move_slots) {
|
||||
void Client::SwapItemResync(MoveItemOld_Struct* move_slots) {
|
||||
// wow..this thing created a helluva memory leak...
|
||||
// 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 to_slot_id = static_cast<int16>(move_in->to_slot);
|
||||
int16 move_amount = static_cast<int16>(move_in->number_in_stack);
|
||||
|
||||
806
zone/trading.cpp
806
zone/trading.cpp
@ -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) {
|
||||
|
||||
if(!Customer)
|
||||
return;
|
||||
|
||||
Log.Out(Logs::Detail, Logs::Trading, "NukeTraderItem(Slot %i, Charges %i, Quantity %i", Slot, Charges, Quantity);
|
||||
|
||||
if(Quantity < Charges)
|
||||
{
|
||||
Customer->SendSingleTraderItem(this->CharacterID(), SerialNumber);
|
||||
m_inv.DeleteItem(Slot, Quantity);
|
||||
}
|
||||
else
|
||||
{
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderDelItem,sizeof(TraderDelItem_Struct));
|
||||
TraderDelItem_Struct* tdis = (TraderDelItem_Struct*)outapp->pBuffer;
|
||||
|
||||
tdis->Unknown000 = 0;
|
||||
tdis->TraderID = Customer->GetID();
|
||||
if (Customer->GetClientVersion() >= ClientVersion::RoF)
|
||||
{
|
||||
// RoF+ use Item IDs for now
|
||||
tdis->ItemID = itemid;
|
||||
}
|
||||
else
|
||||
{
|
||||
tdis->ItemID = SerialNumber;
|
||||
}
|
||||
tdis->Unknown012 = 0;
|
||||
|
||||
|
||||
Customer->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
m_inv.DeleteItem(Slot);
|
||||
}
|
||||
// This updates the trader. Removes it from his trading bags.
|
||||
//
|
||||
const ItemInst* Inst = m_inv[Slot];
|
||||
|
||||
database.SaveInventory(CharacterID(), Inst, Slot);
|
||||
|
||||
EQApplicationPacket* outapp2;
|
||||
|
||||
if(Quantity < Charges)
|
||||
outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct));
|
||||
else
|
||||
outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct));
|
||||
|
||||
MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer;
|
||||
mis->from_slot = Slot;
|
||||
mis->to_slot = 0xFFFFFFFF;
|
||||
mis->number_in_stack = 0xFFFFFFFF;
|
||||
|
||||
if(Quantity >= Charges)
|
||||
Quantity = 1;
|
||||
|
||||
for(int i = 0; i < Quantity; i++) {
|
||||
|
||||
this->QueuePacket(outapp2);
|
||||
}
|
||||
safe_delete(outapp2);
|
||||
|
||||
//
|
||||
// if(!Customer)
|
||||
// return;
|
||||
//
|
||||
// Log.Out(Logs::Detail, Logs::Trading, "NukeTraderItem(Slot %i, Charges %i, Quantity %i", Slot, Charges, Quantity);
|
||||
//
|
||||
// if(Quantity < Charges)
|
||||
// {
|
||||
// Customer->SendSingleTraderItem(this->CharacterID(), SerialNumber);
|
||||
// m_inv.DeleteItem(Slot, Quantity);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderDelItem,sizeof(TraderDelItem_Struct));
|
||||
// TraderDelItem_Struct* tdis = (TraderDelItem_Struct*)outapp->pBuffer;
|
||||
//
|
||||
// tdis->Unknown000 = 0;
|
||||
// tdis->TraderID = Customer->GetID();
|
||||
// if (Customer->GetClientVersion() >= ClientVersion::RoF)
|
||||
// {
|
||||
// // RoF+ use Item IDs for now
|
||||
// tdis->ItemID = itemid;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// tdis->ItemID = SerialNumber;
|
||||
// }
|
||||
// tdis->Unknown012 = 0;
|
||||
//
|
||||
//
|
||||
// Customer->QueuePacket(outapp);
|
||||
// safe_delete(outapp);
|
||||
//
|
||||
// m_inv.DeleteItem(Slot);
|
||||
// }
|
||||
// // This updates the trader. Removes it from his trading bags.
|
||||
// //
|
||||
// const ItemInst* Inst = m_inv[Slot];
|
||||
//
|
||||
// database.SaveInventory(CharacterID(), Inst, Slot);
|
||||
//
|
||||
// EQApplicationPacket* outapp2;
|
||||
//
|
||||
// if(Quantity < Charges)
|
||||
// outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct));
|
||||
// else
|
||||
// outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct));
|
||||
//
|
||||
// MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer;
|
||||
// mis->from_slot = Slot;
|
||||
// mis->to_slot = 0xFFFFFFFF;
|
||||
// mis->number_in_stack = 0xFFFFFFFF;
|
||||
//
|
||||
// if(Quantity >= Charges)
|
||||
// Quantity = 1;
|
||||
//
|
||||
// for(int i = 0; i < Quantity; i++) {
|
||||
//
|
||||
// this->QueuePacket(outapp2);
|
||||
// }
|
||||
// safe_delete(outapp2);
|
||||
//
|
||||
}
|
||||
void Client::TraderUpdate(uint16 SlotID,uint32 TraderID){
|
||||
// This method is no longer used.
|
||||
@ -2507,347 +2507,347 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) {
|
||||
}
|
||||
|
||||
void Client::SellToBuyer(const EQApplicationPacket *app) {
|
||||
|
||||
char* Buf = (char *)app->pBuffer;
|
||||
|
||||
char ItemName[64];
|
||||
|
||||
/*uint32 Action =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused
|
||||
uint32 Quantity = VARSTRUCT_DECODE_TYPE(uint32, Buf);
|
||||
uint32 BuyerID = VARSTRUCT_DECODE_TYPE(uint32, Buf);
|
||||
uint32 BuySlot = VARSTRUCT_DECODE_TYPE(uint32, Buf);
|
||||
uint32 UnknownByte = VARSTRUCT_DECODE_TYPE(uint8, Buf);
|
||||
uint32 ItemID = VARSTRUCT_DECODE_TYPE(uint32, Buf);
|
||||
/* ItemName */ VARSTRUCT_DECODE_STRING(ItemName, Buf);
|
||||
/*uint32 Unknown2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused
|
||||
uint32 QtyBuyerWants = VARSTRUCT_DECODE_TYPE(uint32, Buf);
|
||||
UnknownByte = VARSTRUCT_DECODE_TYPE(uint8, Buf);
|
||||
uint32 Price = VARSTRUCT_DECODE_TYPE(uint32, Buf);
|
||||
/*uint32 BuyerID2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused
|
||||
/*uint32 Unknown3 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused
|
||||
|
||||
const ItemData *item = database.GetItem(ItemID);
|
||||
|
||||
if(!item || !Quantity || !Price || !QtyBuyerWants) return;
|
||||
|
||||
if (m_inv.HasItem(ItemID, Quantity, invWhereWorn | invWherePersonal | invWhereCursor) == INVALID_INDEX) {
|
||||
Message(13, "You do not have %i %s on you.", Quantity, item->Name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Client *Buyer = entity_list.GetClientByID(BuyerID);
|
||||
|
||||
if(!Buyer || !Buyer->IsBuyer()) {
|
||||
Message(13, "The Buyer has gone away.");
|
||||
return;
|
||||
}
|
||||
|
||||
// For Stackable items, HasSpaceForItem will try check if there is space to stack with existing stacks in
|
||||
// the buyer inventory.
|
||||
if(!(Buyer->GetInv().HasSpaceForItem(item, Quantity))) {
|
||||
Message(13, "The Buyer does not have space for %i %s", Quantity, item->Name);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!Buyer->HasMoney(Quantity * Price)) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
if(Buyer->CheckLoreConflict(item)) {
|
||||
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.",
|
||||
GetName(), item->Name);
|
||||
return;
|
||||
}
|
||||
|
||||
if(item->NoDrop == 0) {
|
||||
Message(13, "That item is NODROP.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!item->Stackable) {
|
||||
|
||||
for(uint32 i = 0; i < Quantity; i++) {
|
||||
|
||||
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
|
||||
if (SellerSlot == INVALID_INDEX) {
|
||||
|
||||
if(i > 0) {
|
||||
// Set the Quantity to the actual number we successfully transferred.
|
||||
Quantity = i;
|
||||
break;
|
||||
}
|
||||
Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
|
||||
Message(13, "Internal error while processing transaction.");
|
||||
return;
|
||||
}
|
||||
|
||||
ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot);
|
||||
|
||||
if(!ItemToTransfer || !Buyer->MoveItemToInventory(ItemToTransfer, true)) {
|
||||
Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
|
||||
Message(13, "Internal error while processing transaction.");
|
||||
|
||||
if(ItemToTransfer)
|
||||
safe_delete(ItemToTransfer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
database.SaveInventory(CharacterID(), 0, SellerSlot);
|
||||
|
||||
safe_delete(ItemToTransfer);
|
||||
|
||||
// Remove the item from inventory, clientside
|
||||
//
|
||||
EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct));
|
||||
|
||||
MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer;
|
||||
mis->from_slot = SellerSlot;
|
||||
mis->to_slot = 0xFFFFFFFF;
|
||||
mis->number_in_stack = 0xFFFFFFFF;
|
||||
|
||||
QueuePacket(outapp2);
|
||||
safe_delete(outapp2);
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Stackable
|
||||
//
|
||||
uint32 QuantityMoved = 0;
|
||||
|
||||
while(QuantityMoved < Quantity) {
|
||||
|
||||
// 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);
|
||||
|
||||
if (SellerSlot == INVALID_INDEX) {
|
||||
Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
|
||||
Message(13, "Internal error while processing transaction.");
|
||||
return;
|
||||
}
|
||||
|
||||
ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot);
|
||||
|
||||
if(!ItemToTransfer) {
|
||||
Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
|
||||
Message(13, "Internal error while processing transaction.");
|
||||
return;
|
||||
}
|
||||
|
||||
// If the stack we found has less than the quantity we are selling ...
|
||||
if(ItemToTransfer->GetCharges() <= (Quantity - QuantityMoved)) {
|
||||
// Transfer the entire stack
|
||||
|
||||
QuantityMoved += ItemToTransfer->GetCharges();
|
||||
|
||||
if(!Buyer->MoveItemToInventory(ItemToTransfer, true)) {
|
||||
Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
|
||||
Message(13, "Internal error while processing transaction.");
|
||||
safe_delete(ItemToTransfer);
|
||||
return;
|
||||
}
|
||||
// Delete the entire stack from the seller's inventory
|
||||
database.SaveInventory(CharacterID(), 0, SellerSlot);
|
||||
|
||||
safe_delete(ItemToTransfer);
|
||||
|
||||
// and tell the client to do the same.
|
||||
EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct));
|
||||
|
||||
MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer;
|
||||
mis->from_slot = SellerSlot;
|
||||
mis->to_slot = 0xFFFFFFFF;
|
||||
mis->number_in_stack = 0xFFFFFFFF;
|
||||
|
||||
QueuePacket(outapp2);
|
||||
safe_delete(outapp2);
|
||||
}
|
||||
else {
|
||||
//Move the amount we need, and put the rest of the stack back in the seller's inventory
|
||||
//
|
||||
int QuantityToRemoveFromStack = Quantity - QuantityMoved;
|
||||
|
||||
ItemToTransfer->SetCharges(ItemToTransfer->GetCharges() - QuantityToRemoveFromStack);
|
||||
|
||||
m_inv.PutItem(SellerSlot, *ItemToTransfer);
|
||||
|
||||
database.SaveInventory(CharacterID(), ItemToTransfer, SellerSlot);
|
||||
|
||||
ItemToTransfer->SetCharges(QuantityToRemoveFromStack);
|
||||
|
||||
if(!Buyer->MoveItemToInventory(ItemToTransfer, true)) {
|
||||
Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
|
||||
Message(13, "Internal error while processing transaction.");
|
||||
safe_delete(ItemToTransfer);
|
||||
return;
|
||||
}
|
||||
|
||||
safe_delete(ItemToTransfer);
|
||||
|
||||
EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct));
|
||||
|
||||
MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer;
|
||||
mis->from_slot = SellerSlot;
|
||||
mis->to_slot = 0xFFFFFFFF;
|
||||
mis->number_in_stack = 0xFFFFFFFF;
|
||||
|
||||
for(int i = 0; i < QuantityToRemoveFromStack; i++)
|
||||
QueuePacket(outapp2);
|
||||
|
||||
safe_delete(outapp2);
|
||||
|
||||
QuantityMoved = Quantity;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Buyer->TakeMoneyFromPP(Quantity * Price);
|
||||
|
||||
AddMoneyToPP(Quantity * Price, false);
|
||||
|
||||
if(RuleB(Bazaar, AuditTrail))
|
||||
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>'
|
||||
//
|
||||
// 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
|
||||
// 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.
|
||||
//
|
||||
uint32 PacketLength = 1016;
|
||||
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, PacketLength);
|
||||
|
||||
Buf = (char *)outapp->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_SellerTransactionComplete);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price);
|
||||
|
||||
if(GetClientVersion() >= ClientVersion::SoD)
|
||||
{
|
||||
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;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00);
|
||||
|
||||
sprintf(Buf, "%s", ItemName); Buf += 64;
|
||||
|
||||
QueuePacket(outapp);
|
||||
|
||||
// This next packet goes to the Buyer and produces the 'You've bought <Qty> <Item> from <Seller> for <money>'
|
||||
//
|
||||
|
||||
Buf = (char *)outapp->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerTransactionComplete);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price);
|
||||
|
||||
if(Buyer->GetClientVersion() >= ClientVersion::SoD)
|
||||
{
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Think this is the upper 32 bits of a 64 bit price
|
||||
}
|
||||
|
||||
sprintf(Buf, "%s", GetName()); Buf += 64;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00);
|
||||
|
||||
sprintf(Buf, "%s", ItemName); Buf += 64;
|
||||
|
||||
Buyer->QueuePacket(outapp);
|
||||
|
||||
safe_delete(outapp);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
Buf = (char *)outapp3->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerInspectWindow);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf,ItemID);
|
||||
VARSTRUCT_ENCODE_STRING(Buf, ItemName);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, QtyBuyerWants - Quantity);
|
||||
|
||||
// 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.
|
||||
//
|
||||
if(QtyBuyerWants - Quantity > 0) {
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // 0 = Toggle Off, 1 = Toggle On
|
||||
}
|
||||
else {
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0); // 0 = Toggle Off, 1 = Toggle On
|
||||
}
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Buyer->GetID());
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0);
|
||||
|
||||
VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName());
|
||||
|
||||
QueuePacket(outapp3);
|
||||
safe_delete(outapp3);
|
||||
|
||||
// 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.
|
||||
//
|
||||
EQApplicationPacket* outapp4 = new EQApplicationPacket(OP_Barter, 936);
|
||||
|
||||
Buf = (char*)outapp4->pBuffer;
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerItemUpdate);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot);
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, ItemID);
|
||||
VARSTRUCT_ENCODE_STRING(Buf, ItemName);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, QtyBuyerWants - Quantity);
|
||||
|
||||
if((QtyBuyerWants - Quantity) > 0) {
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // 0 = Toggle Off, 1 = Toggle On
|
||||
}
|
||||
else {
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0); // 0 = Toggle Off, 1 = Toggle On
|
||||
}
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x08f4); // Unknown
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0);
|
||||
VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName());
|
||||
|
||||
Buyer->QueuePacket(outapp4);
|
||||
safe_delete(outapp4);
|
||||
|
||||
return;
|
||||
//
|
||||
// char* Buf = (char *)app->pBuffer;
|
||||
//
|
||||
// char ItemName[64];
|
||||
//
|
||||
// /*uint32 Action =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused
|
||||
// uint32 Quantity = VARSTRUCT_DECODE_TYPE(uint32, Buf);
|
||||
// uint32 BuyerID = VARSTRUCT_DECODE_TYPE(uint32, Buf);
|
||||
// uint32 BuySlot = VARSTRUCT_DECODE_TYPE(uint32, Buf);
|
||||
// uint32 UnknownByte = VARSTRUCT_DECODE_TYPE(uint8, Buf);
|
||||
// uint32 ItemID = VARSTRUCT_DECODE_TYPE(uint32, Buf);
|
||||
// /* ItemName */ VARSTRUCT_DECODE_STRING(ItemName, Buf);
|
||||
// /*uint32 Unknown2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused
|
||||
// uint32 QtyBuyerWants = VARSTRUCT_DECODE_TYPE(uint32, Buf);
|
||||
// UnknownByte = VARSTRUCT_DECODE_TYPE(uint8, Buf);
|
||||
// uint32 Price = VARSTRUCT_DECODE_TYPE(uint32, Buf);
|
||||
// /*uint32 BuyerID2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused
|
||||
// /*uint32 Unknown3 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused
|
||||
//
|
||||
// const ItemData *item = database.GetItem(ItemID);
|
||||
//
|
||||
// if(!item || !Quantity || !Price || !QtyBuyerWants) return;
|
||||
//
|
||||
// if (m_inv.HasItem(ItemID, Quantity, invWhereWorn | invWherePersonal | invWhereCursor) == INVALID_INDEX) {
|
||||
// Message(13, "You do not have %i %s on you.", Quantity, item->Name);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// Client *Buyer = entity_list.GetClientByID(BuyerID);
|
||||
//
|
||||
// if(!Buyer || !Buyer->IsBuyer()) {
|
||||
// Message(13, "The Buyer has gone away.");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // For Stackable items, HasSpaceForItem will try check if there is space to stack with existing stacks in
|
||||
// // the buyer inventory.
|
||||
// if(!(Buyer->GetInv().HasSpaceForItem(item, Quantity))) {
|
||||
// Message(13, "The Buyer does not have space for %i %s", Quantity, item->Name);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// 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);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if(!Buyer->HasMoney(Quantity * Price)) {
|
||||
// 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);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if(Buyer->CheckLoreConflict(item)) {
|
||||
// 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.",
|
||||
// GetName(), item->Name);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if(item->NoDrop == 0) {
|
||||
// Message(13, "That item is NODROP.");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if(!item->Stackable) {
|
||||
//
|
||||
// for(uint32 i = 0; i < Quantity; i++) {
|
||||
//
|
||||
// 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
|
||||
// if (SellerSlot == INVALID_INDEX) {
|
||||
//
|
||||
// if(i > 0) {
|
||||
// // Set the Quantity to the actual number we successfully transferred.
|
||||
// Quantity = i;
|
||||
// break;
|
||||
// }
|
||||
// Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
|
||||
// Message(13, "Internal error while processing transaction.");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot);
|
||||
//
|
||||
// if(!ItemToTransfer || !Buyer->MoveItemToInventory(ItemToTransfer, true)) {
|
||||
// Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
|
||||
// Message(13, "Internal error while processing transaction.");
|
||||
//
|
||||
// if(ItemToTransfer)
|
||||
// safe_delete(ItemToTransfer);
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// database.SaveInventory(CharacterID(), 0, SellerSlot);
|
||||
//
|
||||
// safe_delete(ItemToTransfer);
|
||||
//
|
||||
// // Remove the item from inventory, clientside
|
||||
// //
|
||||
// EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct));
|
||||
//
|
||||
// MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer;
|
||||
// mis->from_slot = SellerSlot;
|
||||
// mis->to_slot = 0xFFFFFFFF;
|
||||
// mis->number_in_stack = 0xFFFFFFFF;
|
||||
//
|
||||
// QueuePacket(outapp2);
|
||||
// safe_delete(outapp2);
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// // Stackable
|
||||
// //
|
||||
// uint32 QuantityMoved = 0;
|
||||
//
|
||||
// while(QuantityMoved < Quantity) {
|
||||
//
|
||||
// // 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);
|
||||
//
|
||||
// if (SellerSlot == INVALID_INDEX) {
|
||||
// Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
|
||||
// Message(13, "Internal error while processing transaction.");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot);
|
||||
//
|
||||
// if(!ItemToTransfer) {
|
||||
// Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
|
||||
// Message(13, "Internal error while processing transaction.");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // If the stack we found has less than the quantity we are selling ...
|
||||
// if(ItemToTransfer->GetCharges() <= (Quantity - QuantityMoved)) {
|
||||
// // Transfer the entire stack
|
||||
//
|
||||
// QuantityMoved += ItemToTransfer->GetCharges();
|
||||
//
|
||||
// if(!Buyer->MoveItemToInventory(ItemToTransfer, true)) {
|
||||
// Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
|
||||
// Message(13, "Internal error while processing transaction.");
|
||||
// safe_delete(ItemToTransfer);
|
||||
// return;
|
||||
// }
|
||||
// // Delete the entire stack from the seller's inventory
|
||||
// database.SaveInventory(CharacterID(), 0, SellerSlot);
|
||||
//
|
||||
// safe_delete(ItemToTransfer);
|
||||
//
|
||||
// // and tell the client to do the same.
|
||||
// EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct));
|
||||
//
|
||||
// MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer;
|
||||
// mis->from_slot = SellerSlot;
|
||||
// mis->to_slot = 0xFFFFFFFF;
|
||||
// mis->number_in_stack = 0xFFFFFFFF;
|
||||
//
|
||||
// QueuePacket(outapp2);
|
||||
// safe_delete(outapp2);
|
||||
// }
|
||||
// else {
|
||||
// //Move the amount we need, and put the rest of the stack back in the seller's inventory
|
||||
// //
|
||||
// int QuantityToRemoveFromStack = Quantity - QuantityMoved;
|
||||
//
|
||||
// ItemToTransfer->SetCharges(ItemToTransfer->GetCharges() - QuantityToRemoveFromStack);
|
||||
//
|
||||
// m_inv.PutItem(SellerSlot, *ItemToTransfer);
|
||||
//
|
||||
// database.SaveInventory(CharacterID(), ItemToTransfer, SellerSlot);
|
||||
//
|
||||
// ItemToTransfer->SetCharges(QuantityToRemoveFromStack);
|
||||
//
|
||||
// if(!Buyer->MoveItemToInventory(ItemToTransfer, true)) {
|
||||
// Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer.");
|
||||
// Message(13, "Internal error while processing transaction.");
|
||||
// safe_delete(ItemToTransfer);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// safe_delete(ItemToTransfer);
|
||||
//
|
||||
// EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct));
|
||||
//
|
||||
// MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer;
|
||||
// mis->from_slot = SellerSlot;
|
||||
// mis->to_slot = 0xFFFFFFFF;
|
||||
// mis->number_in_stack = 0xFFFFFFFF;
|
||||
//
|
||||
// for(int i = 0; i < QuantityToRemoveFromStack; i++)
|
||||
// QueuePacket(outapp2);
|
||||
//
|
||||
// safe_delete(outapp2);
|
||||
//
|
||||
// QuantityMoved = Quantity;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// Buyer->TakeMoneyFromPP(Quantity * Price);
|
||||
//
|
||||
// AddMoneyToPP(Quantity * Price, false);
|
||||
//
|
||||
// if(RuleB(Bazaar, AuditTrail))
|
||||
// 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>'
|
||||
// //
|
||||
// // 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
|
||||
// // 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.
|
||||
// //
|
||||
// uint32 PacketLength = 1016;
|
||||
//
|
||||
// EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, PacketLength);
|
||||
//
|
||||
// Buf = (char *)outapp->pBuffer;
|
||||
//
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_SellerTransactionComplete);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price);
|
||||
//
|
||||
// if(GetClientVersion() >= ClientVersion::SoD)
|
||||
// {
|
||||
// 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;
|
||||
//
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00);
|
||||
//
|
||||
// sprintf(Buf, "%s", ItemName); Buf += 64;
|
||||
//
|
||||
// QueuePacket(outapp);
|
||||
//
|
||||
// // This next packet goes to the Buyer and produces the 'You've bought <Qty> <Item> from <Seller> for <money>'
|
||||
// //
|
||||
//
|
||||
// Buf = (char *)outapp->pBuffer;
|
||||
//
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerTransactionComplete);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price);
|
||||
//
|
||||
// if(Buyer->GetClientVersion() >= ClientVersion::SoD)
|
||||
// {
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Think this is the upper 32 bits of a 64 bit price
|
||||
// }
|
||||
//
|
||||
// sprintf(Buf, "%s", GetName()); Buf += 64;
|
||||
//
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00);
|
||||
//
|
||||
// sprintf(Buf, "%s", ItemName); Buf += 64;
|
||||
//
|
||||
// Buyer->QueuePacket(outapp);
|
||||
//
|
||||
// safe_delete(outapp);
|
||||
//
|
||||
// // 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);
|
||||
//
|
||||
// // 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);
|
||||
//
|
||||
// Buf = (char *)outapp3->pBuffer;
|
||||
//
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerInspectWindow);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // Unknown
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf,ItemID);
|
||||
// VARSTRUCT_ENCODE_STRING(Buf, ItemName);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, QtyBuyerWants - Quantity);
|
||||
//
|
||||
// // 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.
|
||||
// //
|
||||
// if(QtyBuyerWants - Quantity > 0) {
|
||||
// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // 0 = Toggle Off, 1 = Toggle On
|
||||
// }
|
||||
// else {
|
||||
// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0); // 0 = Toggle Off, 1 = Toggle On
|
||||
// }
|
||||
//
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Buyer->GetID());
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0);
|
||||
//
|
||||
// VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName());
|
||||
//
|
||||
// QueuePacket(outapp3);
|
||||
// safe_delete(outapp3);
|
||||
//
|
||||
// // 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.
|
||||
// //
|
||||
// EQApplicationPacket* outapp4 = new EQApplicationPacket(OP_Barter, 936);
|
||||
//
|
||||
// Buf = (char*)outapp4->pBuffer;
|
||||
//
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerItemUpdate);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, ItemID);
|
||||
// VARSTRUCT_ENCODE_STRING(Buf, ItemName);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, QtyBuyerWants - Quantity);
|
||||
//
|
||||
// if((QtyBuyerWants - Quantity) > 0) {
|
||||
//
|
||||
// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // 0 = Toggle Off, 1 = Toggle On
|
||||
// }
|
||||
// else {
|
||||
// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0); // 0 = Toggle Off, 1 = Toggle On
|
||||
// }
|
||||
//
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price);
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x08f4); // Unknown
|
||||
// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0);
|
||||
// VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName());
|
||||
//
|
||||
// Buyer->QueuePacket(outapp4);
|
||||
// safe_delete(outapp4);
|
||||
//
|
||||
// return;
|
||||
}
|
||||
|
||||
void Client::SendBuyerPacket(Client* Buyer) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user