diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index f847957db..292d1032b 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -30,9 +30,16 @@ SET(common_sources faction.cpp guild_base.cpp guilds.cpp + inventory.cpp + inventory_db_data_model.cpp ipc_mutex.cpp item.cpp + item_container.cpp + item_container_default_serialization.cpp + item_container_personal_serialization.cpp + item_instance.cpp md5.cpp + memory_buffer.cpp memory_mapped_file.cpp misc.cpp misc_functions.cpp @@ -135,15 +142,25 @@ SET(common_headers global_define.h guild_base.h guilds.h + inventory.h + inventory_data_model.h + inventory_db_data_model.h + inventory_null_data_model.h ipc_mutex.h item.h + item_container.h + item_container_default_serialization.h + item_container_personal_serialization.h + item_container_serialization_strategy.h + item_data.h item_fieldlist.h - item_struct.h + item_instance.h languages.h linked_list.h loottable.h mail_oplist.h md5.h + memory_buffer.h memory_mapped_file.h misc.h misc_functions.h diff --git a/common/data_verification.h b/common/data_verification.h index 9da85a579..aa44df7bc 100644 --- a/common/data_verification.h +++ b/common/data_verification.h @@ -23,23 +23,23 @@ namespace EQEmu { -template -T Clamp(const T& value, const T& lower, const T& upper) { - return std::max(lower, std::min(value, upper)); +template +T Clamp(const T& value, const U& lower, const V& upper) { + return std::max(static_cast(lower), std::min(value, static_cast(upper))); } -template -T ClampLower(const T& value, const T& lower) { - return std::max(lower, value); +template +T ClampLower(const T& value, const U& lower) { + return std::max(static_cast(lower), value); } -template -T ClampUpper(const T& value, const T& upper) { - return std::min(value, upper); +template +T ClampUpper(const T& value, const U& upper) { + return std::min(value, static_cast(upper)); } -template -bool ValueWithin(const T& value, const T& lower, const T& upper) { +template +bool ValueWithin(const T& value, const U& lower, const V& upper) { return value >= lower && value <= upper; } diff --git a/common/database.cpp b/common/database.cpp index 31566d82f..9b64c79f3 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -677,7 +677,7 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe } /* This only for new Character creation storing */ -bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv) { +bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, InventoryOld* inv) { uint32 charid = 0; char zone[50]; float x, y, z; diff --git a/common/database.h b/common/database.h index f3b8ba8c1..c71d767df 100644 --- a/common/database.h +++ b/common/database.h @@ -27,6 +27,7 @@ #include "dbcore.h" #include "linked_list.h" #include "eq_packet_structs.h" +#include "inventory.h" #include #include @@ -36,7 +37,7 @@ //atoi is not uint32 or uint32 safe!!!! #define atoul(str) strtoul(str, nullptr, 10) -class Inventory; +class InventoryOld; class MySQLRequestResult; class Client; @@ -102,7 +103,7 @@ public: bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); bool SetHackerFlag(const char* accountname, const char* charactername, const char* hacked); bool SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone); - bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv); + bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, InventoryOld* inv); bool UpdateName(const char* oldname, const char* newname); /* General Information Queries */ diff --git a/common/eq_constants.h b/common/eq_constants.h index 0fec1f223..6922d133a 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -306,7 +306,7 @@ enum AugmentationRestrictionTypes : uint8 { /* ** Container use types ** -** This correlates to world 'object.type' (object.h/Object.cpp) as well as Item_Struct.BagType +** This correlates to world 'object.type' (object.h/Object.cpp) as well as ItemData.BagType ** ** (ref: database, web forums and eqstr_us.txt) */ diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index f9f75838f..162f9b016 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -25,7 +25,7 @@ #include #include #include "../common/version.h" -//#include "../common/item_struct.h" +//#include "../common/item_data.h" static const uint32 BUFF_COUNT = 25; static const uint32 MAX_MERC = 100; @@ -126,6 +126,14 @@ struct LDoNTrapTemplate // All clients translate the character select information to some degree +struct Inventory_Slot_Struct +{ + int16 type; + int16 slot; + int16 bag; + int16 aug; +}; + struct Color_Struct { union { @@ -1558,7 +1566,7 @@ struct DeleteItem_Struct { /*0012*/ }; -struct MoveItem_Struct +struct MoveItemOld_Struct { /*0000*/ uint32 from_slot; /*0004*/ uint32 to_slot; @@ -1566,6 +1574,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) @@ -1957,13 +1978,11 @@ Unknowns: struct Merchant_Sell_Struct { -/*000*/ uint32 npcid; // Merchant NPC's entity id -/*004*/ uint32 playerid; // Player's entity id -/*008*/ uint32 itemslot; - uint32 unknown12; -/*016*/ uint8 quantity; // Already sold -/*017*/ uint8 Unknown016[3]; -/*020*/ uint32 price; + uint32 npcid; + uint32 playerid; + uint32 itemslot; + int32 quantity; + uint32 price; }; struct Merchant_Purchase_Struct { /*000*/ uint32 npcid; // Merchant NPC's entity id @@ -2099,7 +2118,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - Item_Struct item; + ItemData item; uint8 iss_unknown001[6]; };*/ diff --git a/common/inventory.cpp b/common/inventory.cpp new file mode 100644 index 000000000..12dd8840c --- /dev/null +++ b/common/inventory.cpp @@ -0,0 +1,782 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "inventory.h" +#include "inventory_null_data_model.h" +#include "item_container_personal_serialization.h" +#include "data_verification.h" +#include "string_util.h" +#include + +bool EQEmu::InventorySlot::IsValid() const { + if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotCharm, PersonalSlotCursor)) { + return true; + } + + if(type_ == InvTypeBank && EQEmu::ValueWithin(slot_, 0, 23)) { + return true; + } + + if(type_ == InvTypeSharedBank && EQEmu::ValueWithin(slot_, 0, 1)) { + return true; + } + + if(type_ == InvTypeTribute && EQEmu::ValueWithin(slot_, 0, 4)) { + return true; + } + + if(type_ == InvTypeTrade && EQEmu::ValueWithin(slot_, 0, 7)) { + return true; + } + + if(type_ == InvTypeWorld && EQEmu::ValueWithin(slot_, 0, 255)) { + return true; + } + + + return false; +} + +bool EQEmu::InventorySlot::IsDelete() const { + return type_ == -1 && slot_ == -1 && bag_index_ == -1 && aug_index_ == -1; +} + +bool EQEmu::InventorySlot::IsBank() const { + if(type_ == InvTypeBank && EQEmu::ValueWithin(slot_, 0, 23)) { + return true; + } + + if(type_ == InvTypeSharedBank && EQEmu::ValueWithin(slot_, 0, 1)) { + return true; + } + + return false; +} + +bool EQEmu::InventorySlot::IsCursor() const { + if(type_ == InvTypePersonal && slot_ == PersonalSlotCursor) { + return true; + } + + if(type_ == InvTypeCursorBuffer) { + return true; + } + + return false; +} + +bool EQEmu::InventorySlot::IsEquipment() const { + if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotCharm, PersonalSlotAmmo)) { + return true; + } + + return false; +} + +bool EQEmu::InventorySlot::IsGeneral() const { + if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotGeneral1, PersonalSlotGeneral10)) { + return true; + } + + return false; +} + +bool EQEmu::InventorySlot::IsWeapon() const { + if(type_ == InvTypePersonal && + (EQEmu::ValueWithin(slot_, PersonalSlotPrimary, PersonalSlotSecondary) || slot_ == PersonalSlotRange)) + { + return true; + } + + return false; +} + +bool EQEmu::InventorySlot::IsTrade() const { + if(type_ == InvTypeTrade) { + return true; + } + + return false; +} + +const std::string EQEmu::InventorySlot::ToString() const { + return StringFormat("(%i, %i, %i, %i)", type_, slot_, bag_index_, aug_index_); +} + +struct EQEmu::Inventory::impl +{ + std::map containers_; + int race_; + int class_; + int deity_; + std::unique_ptr data_model_; +}; + +EQEmu::Inventory::Inventory(int race, int class_, int deity) { + impl_ = new impl; + impl_->race_ = race; + impl_->class_ = class_; + impl_->deity_ = deity; + impl_->data_model_ = std::unique_ptr(new InventoryNullDataModel()); +} + +EQEmu::Inventory::~Inventory() { + delete impl_; +} + +void EQEmu::Inventory::SetRace(int race) { + impl_->race_ = race; +} + +void EQEmu::Inventory::SetClass(int class_) { + impl_->class_ = class_; +} + +void EQEmu::Inventory::SetDeity(int deity) { + impl_->deity_ = deity; +} + +void EQEmu::Inventory::SetDataModel(InventoryDataModel *dm) { + impl_->data_model_ = std::unique_ptr(dm); +} + +EQEmu::ItemInstance::pointer EQEmu::Inventory::Get(const InventorySlot &slot) { + auto iter = impl_->containers_.find(slot.Type()); + if(iter != impl_->containers_.end()) { + auto item = iter->second.Get(slot.Slot()); + if(item) { + if(slot.BagIndex() > -1) { + auto sub_item = item->Get(slot.BagIndex()); + if(sub_item) { + if(slot.AugIndex() > -1) { + return sub_item->Get(slot.AugIndex()); + } else { + return sub_item; + } + } + } else { + return item; + } + } + } + + return ItemInstance::pointer(nullptr); +} + +bool EQEmu::Inventory::Put(const InventorySlot &slot, ItemInstance::pointer &inst) { + if(impl_->containers_.count(slot.Type()) == 0) { + if(slot.Type() == 0) { + impl_->containers_.insert(std::pair(slot.Type(), ItemContainer(new ItemContainerPersonalSerialization()))); + } else { + impl_->containers_.insert(std::pair(slot.Type(), ItemContainer())); + } + } + + //Verify item can be put into the slot requested + + auto &container = impl_->containers_[slot.Type()]; + if(slot.BagIndex() > -1) { + auto item = container.Get(slot.Slot()); + if(!item) + return false; + + if(slot.AugIndex() > -1) { + auto bag_item = item->Get(slot.BagIndex()); + if(!bag_item) { + return false; + } + + return bag_item->Put(slot.AugIndex(), inst); + } else { + return item->Put(slot.BagIndex(), inst); + } + } else { + if(slot.AugIndex() > -1) { + auto item = container.Get(slot.Slot()); + if(!item) + return false; + + return item->Put(slot.AugIndex(), inst); + } + + return container.Put(slot.Slot(), inst); + } + + return false; +} + +bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest, int charges) { + if(src == dest) { + return true; + } + + if(!src.IsValid()) { + return false; + } + + if(src.Type() == InvTypeCursorBuffer || dest.Type() == InvTypeCursorBuffer) { + return true; + } + + if(dest.IsDelete()) { + impl_->data_model_->Begin(); + bool v = _destroy(src); + if(v) { + impl_->data_model_->Commit(); + } + else { + impl_->data_model_->Rollback(); + } + + return v; + } + + if(!dest.IsValid()) { + return false; + } + + auto i_src = Get(src); + auto i_dest = Get(dest); + + if(!i_src) { + return false; + } + + if(i_src->GetBaseItem()->ItemClass == ItemClassContainer && dest.BagIndex() > -1) { + if(i_src->GetContainer()->Size() > 0) { + return false; + } + } + + if(dest.IsEquipment() && !CanEquip(i_src, dest)) { + return false; + } + + //Check this -> trade no drop + if(dest.IsTrade() && i_src->IsNoDrop()) { + return false; + } + + impl_->data_model_->Begin(); + if(i_src->IsStackable()) { + //move # charges from src to dest + + //0 means *all* the charges + if(charges == 0) { + charges = i_src->GetCharges(); + } + + //src needs to have that many charges + if(i_src->GetCharges() < charges) { + impl_->data_model_->Rollback(); + return false; + } + + //if dest exists it needs to not only be the same item id but also be able to hold enough charges to combine + //we can also swap if src id != dest id + if(i_dest) { + uint32 src_id = i_src->GetBaseItem()->ID; + uint32 dest_id = i_dest->GetBaseItem()->ID; + if(src_id != dest_id) { + bool v = _swap(src, dest); + if(v) { + impl_->data_model_->Commit(); + } + else { + impl_->data_model_->Rollback(); + } + + return v; + } + + int charges_avail = i_dest->GetBaseItem()->StackSize - i_dest->GetCharges(); + if(charges_avail < charges) { + impl_->data_model_->Rollback(); + return false; + } + + if(i_src->GetCharges() == charges) { + if(!_destroy(src)) { + impl_->data_model_->Rollback(); + return false; + } + } else { + i_src->SetCharges(i_src->GetCharges() - charges); + impl_->data_model_->Insert(src, i_src); + } + + i_dest->SetCharges(i_dest->GetCharges() + charges); + impl_->data_model_->Delete(dest); + impl_->data_model_->Insert(dest, i_dest); + impl_->data_model_->Commit(); + return true; + } else { + //if dest does not exist and src charges > # charges then we need to create a new item with # charges in dest + //if dest does not exist and src charges == # charges then we need to swap src to dest + if(i_src->GetCharges() > charges) { + auto split = i_src->Split(charges); + if(!split) { + impl_->data_model_->Rollback(); + return false; + } + + Put(dest, split); + impl_->data_model_->Delete(src); + impl_->data_model_->Delete(dest); + impl_->data_model_->Insert(src, i_src); + impl_->data_model_->Insert(dest, split); + impl_->data_model_->Commit(); + return true; + } else { + bool v = _swap(src, dest); + if(v) { + impl_->data_model_->Commit(); + } else { + impl_->data_model_->Rollback(); + } + + return v; + } + } + } else { + bool v = _swap(src, dest); + if(v) { + impl_->data_model_->Commit(); + } + else { + impl_->data_model_->Rollback(); + } + + return v; + } + + impl_->data_model_->Commit(); + return true; +} + +bool EQEmu::Inventory::Summon(const InventorySlot &slot, ItemInstance::pointer &inst) { + if(!inst) + return false; + + if(CheckLoreConflict(inst->GetBaseItem())) { + return false; + } + + auto cur = Get(slot); + if(cur) { + if(slot.IsCursor()) { + PushToCursorBuffer(inst); + } + + return false; + } + + impl_->data_model_->Begin(); + bool v = Put(slot, inst); + if(v) { + impl_->data_model_->Insert(slot, inst); + impl_->data_model_->Commit(); + } else { + impl_->data_model_->Rollback(); + } + + return v; +} + +bool EQEmu::Inventory::PushToCursorBuffer(ItemInstance::pointer &inst) { + if(impl_->containers_.count(InvTypeCursorBuffer) == 0) { + impl_->containers_.insert(std::pair(InvTypeCursorBuffer, ItemContainer())); + } + + int32 top = 0; + auto &container = impl_->containers_[InvTypeCursorBuffer]; + auto iter = container.Begin(); + while(iter != container.End()) { + top = iter->first; + ++iter; + } + + InventorySlot slot(InvTypeCursorBuffer, top + 1); + impl_->data_model_->Begin(); + bool v = Put(slot, inst); + if(v) { + impl_->data_model_->Insert(slot, inst); + impl_->data_model_->Commit(); + } + else { + impl_->data_model_->Rollback(); + } + + return v; +} + +bool EQEmu::Inventory::PopFromCursorBuffer() { + InventorySlot cursor(InvTypePersonal, PersonalSlotCursor); + auto inst = Get(cursor); + if(inst) { + return false; + } + + if(impl_->containers_.count(InvTypeCursorBuffer) == 0) { + return false; + } + + int32 top = 0; + auto &container = impl_->containers_[InvTypeCursorBuffer]; + auto iter = container.Begin(); + while(iter != container.End()) { + top = iter->first; + ++iter; + } + + InventorySlot slot(InvTypeCursorBuffer, top); + inst = Get(slot); + + if(inst) { + impl_->data_model_->Begin(); + + bool v = _destroy(slot); + impl_->data_model_->Delete(slot); + + if(!v) { + impl_->data_model_->Rollback(); + return false; + } + + v = Put(cursor, inst); + impl_->data_model_->Insert(cursor, inst); + if(!v) { + impl_->data_model_->Rollback(); + return false; + } + + impl_->data_model_->Commit(); + return true; + } + + return false; +} + +EQEmu::InventorySlot EQEmu::Inventory::FindFreeSlot(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end) { + bool for_bag = inst->GetItem()->ItemClass == ItemClassContainer; + int min_size = inst->GetItem()->Size; + bool is_arrow = inst->GetItem()->ItemType == ItemTypeArrow; + + //check upper level inventory + for(int i = slot_id_start; i <= slot_id_end; ++i) { + EQEmu::InventorySlot slot(container_id, i); + if(!Get(slot)) { + return slot; + } + } + + //if not for a bag then check inside bags + if (!for_bag) { + for(int i = slot_id_start; i <= slot_id_end; ++i) { + EQEmu::InventorySlot slot(container_id, i); + auto inst = Get(slot); + + if(inst && inst->GetBaseItem()->ItemClass == ItemClassContainer && inst->GetBaseItem()->BagSize >= min_size) + { + if(inst->GetBaseItem()->BagType == BagTypeQuiver && !is_arrow) + { + continue; + } + + int slots = inst->GetBaseItem()->BagSlots; + for(int b_i = 0; b_i < slots; ++b_i) { + EQEmu::InventorySlot bag_slot(container_id, i, b_i); + + if(!Get(bag_slot)) { + return bag_slot; + } + } + } + } + } + + return EQEmu::InventorySlot(); +} + +int EQEmu::Inventory::FindFreeStackSlots(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end) { + if(!inst->IsStackable()) { + return 0; + } + + bool is_arrow = inst->GetItem()->ItemType == ItemTypeArrow; + int item_id = inst->GetItem()->ID; + + int charges_to_check = inst->GetCharges(); + int charges = 0; + + auto iter = impl_->containers_.find(container_id); + if(iter == impl_->containers_.end()) { + return 0; + } + + auto &container = iter->second; + for(int i = slot_id_start; i <= slot_id_end; ++i) { + auto current = container.Get(i); + if(!current) { + continue; + } + + if(current->GetItem()->ID == item_id) { + int free_charges = current->GetItem()->StackSize - current->GetCharges(); + if(free_charges) + charges += free_charges; + + if(charges >= charges_to_check) { + return charges_to_check; + } + } else if(current->GetItem()->ItemClass == ItemClassContainer) { + int sz = current->GetItem()->BagSlots; + for(int i = 0; i < sz; ++i) { + auto sub_item = current->Get(i); + if(!sub_item) { + continue; + } + + if(sub_item->GetItem()->ID == item_id) { + int free_charges = sub_item->GetItem()->StackSize - sub_item->GetCharges(); + if(free_charges) + charges += free_charges; + + if(charges >= charges_to_check) { + return charges_to_check; + } + } + } + } + } + + if(charges >= charges_to_check) { + return charges_to_check; + } + + return charges; +} + +void EQEmu::Inventory::UpdateSlot(const InventorySlot &slot, ItemInstance::pointer &inst) { + impl_->data_model_->Begin(); + + impl_->data_model_->Delete(slot); + if(inst) { + impl_->data_model_->Insert(slot, inst); + } + + impl_->data_model_->Commit(); +} + +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::CanEquip(EQEmu::ItemInstance::pointer &inst, const EQEmu::InventorySlot &slot) { + if(!inst) { + return false; + } + + if(slot.Type() != 0) { + return false; + } + + if(!EQEmu::ValueWithin(slot.Slot(), EQEmu::PersonalSlotCharm, EQEmu::PersonalSlotAmmo)) { + return false; + } + + auto item = inst->GetItem(); + //check slot + + int use_slot = -1; + if(slot.Slot() == EQEmu::PersonalSlotPowerSource) { + use_slot = EQEmu::PersonalSlotAmmo; + } + else if(slot.Slot() == EQEmu::PersonalSlotAmmo) { + use_slot = EQEmu::PersonalSlotPowerSource; + } + else { + use_slot = slot.Slot(); + } + + if(!(item->Slots & (1 << use_slot))) { + return false; + } + + //todo: check deity + if(!item->IsEquipable(impl_->race_, impl_->class_)) { + return false; + } + + //Checking augments + auto iter = inst->GetContainer()->Begin(); + auto end = inst->GetContainer()->End(); + while(iter != end) { + EQEmu::ItemInstance::pointer itm = iter->second; + if(!CanEquip(itm, InventorySlot(slot.Type(), slot.Slot(), slot.BagIndex(), iter->first))) { + return false; + } + ++iter; + } + + return true; +} + +bool EQEmu::Inventory::CheckLoreConflict(const ItemData *item) { + if(!item) + return false; + + if(!item->LoreFlag) + return false; + + if(item->LoreGroup == 0) + return false; + + if(item->LoreGroup == 0xFFFFFFFF) { + //look everywhere except shared bank + for(auto &container : impl_->containers_) { + if(container.first != InvTypeSharedBank && container.second.HasItem(item->ID)) { + return true; + } + } + } + else { + //look everywhere except shared bank + for(auto &container : impl_->containers_) { + if(container.first != InvTypeSharedBank && container.second.HasItemByLoreGroup(item->LoreGroup)) { + return true; + } + } + } + + return false; +} + +bool EQEmu::Inventory::Serialize(MemoryBuffer &buf) { + buf.SetWritePosition(0); + buf.SetReadPosition(0); + buf.Resize(0); + buf.Write(105); + + bool value = false; + for(auto &iter : impl_->containers_) { + bool v = iter.second.Serialize(buf, iter.first); + if(v && !value) { + value = true; + } + } + + return value; +} + +void EQEmu::Inventory::Interrogate() { + printf("Inventory:\n"); + printf("Class: %u, Race: %u, Deity: %u\n", impl_->class_, impl_->race_, impl_->deity_); + for(auto &iter : impl_->containers_) { + printf("Container: %u\n", iter.first); + iter.second.Interrogate(1); + } + printf("\n"); +} + +bool EQEmu::Inventory::_swap(const InventorySlot &src, const InventorySlot &dest) { + auto src_i = Get(src); + auto dest_i = Get(dest); + + if(src_i) { + if(!_destroy(src)) { + return false; + } + } + + if(dest_i) { + if(!_destroy(dest)) { + return false; + } + + impl_->data_model_->Insert(src, dest_i); + if(!Put(src, dest_i)) { + return false; + } + } + + if(src_i) { + impl_->data_model_->Insert(dest, src_i); + if(!Put(dest, src_i)) { + return false; + } + } + + return true; +} + +bool EQEmu::Inventory::_destroy(const InventorySlot &slot) { + bool v = Put(slot, EQEmu::ItemInstance::pointer(nullptr)); + impl_->data_model_->Delete(slot); + return v; +} diff --git a/common/inventory.h b/common/inventory.h new file mode 100644 index 000000000..345edb7fb --- /dev/null +++ b/common/inventory.h @@ -0,0 +1,165 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_INVENTORY_H +#define COMMON_INVENTORY_H + +#include "item_container.h" +#include + +namespace EQEmu +{ + enum InventoryType : int + { + InvTypePersonal = 0, + InvTypeBank, + InvTypeSharedBank, + InvTypeTrade, + InvTypeWorld, + InvTypeCursorBuffer, + InvTypeTribute, + InvTypeTrophyTribute, + InvTypeGuildTribute, + InvTypeMerchant + }; + + enum PersonaInventorySlot : 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 InventorySlot + { + public: + InventorySlot() : type_(-1), slot_(-1), bag_index_(-1), aug_index_(-1) { } + InventorySlot(int type, int slot) + : type_(type), slot_(slot), bag_index_(-1), aug_index_(-1) { } + InventorySlot(int type, int slot, int bag_index) + : type_(type), slot_(slot), bag_index_(bag_index), aug_index_(-1) { } + InventorySlot(int type, int slot, int bag_index, int aug_index) + : type_(type), slot_(slot), bag_index_(bag_index), aug_index_(aug_index) { } + + bool IsValid() const; + bool IsDelete() const; + bool IsBank() const; + bool IsCursor() const; + bool IsEquipment() const; + bool IsGeneral() const; + bool IsWeapon() const; + bool IsTrade() const; + + const std::string ToString() const; + + inline int Type() { return type_; } + inline int Type() const { return type_; } + inline int Slot() { return slot_; } + inline int Slot() const { return slot_; } + inline int BagIndex() { return bag_index_; } + inline int BagIndex() const { return bag_index_; } + inline int AugIndex() { return aug_index_; } + inline int AugIndex() const { return aug_index_; } + + private: + int type_; + int slot_; + int bag_index_; + int aug_index_; + }; + + inline bool operator==(const InventorySlot &lhs, const InventorySlot &rhs) { + return lhs.Type() == rhs.Type() && + lhs.Slot() == rhs.Slot() && + lhs.BagIndex() == rhs.BagIndex() && + lhs.AugIndex() == rhs.AugIndex(); } + inline bool operator!=(const InventorySlot &lhs, const InventorySlot &rhs) { return !(lhs == rhs); } + + class InventoryDataModel; + class Inventory + { + public: + Inventory(int race, int class_, int deity); + ~Inventory(); + + void SetRace(int race); + void SetClass(int class_); + void SetDeity(int deity); + void SetDataModel(InventoryDataModel *dm); + + ItemInstance::pointer Get(const InventorySlot &slot); + bool Put(const InventorySlot &slot, ItemInstance::pointer &inst); + bool Swap(const InventorySlot &src, const InventorySlot &dest, int charges); + bool Summon(const InventorySlot &slot, ItemInstance::pointer &inst); + bool PushToCursorBuffer(ItemInstance::pointer &inst); + bool PopFromCursorBuffer(); + InventorySlot FindFreeSlot(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end); + int FindFreeStackSlots(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end); + void UpdateSlot(const InventorySlot &slot, ItemInstance::pointer &inst); + + //utility + static int CalcMaterialFromSlot(const InventorySlot &slot); + static InventorySlot CalcSlotFromMaterial(int material); + bool CanEquip(EQEmu::ItemInstance::pointer &inst, const EQEmu::InventorySlot &slot); + bool CheckLoreConflict(const ItemData *item); + bool Serialize(MemoryBuffer &buf); + + //testing + void Interrogate(); + private: + bool _swap(const InventorySlot &src, const InventorySlot &dest); + bool _destroy(const InventorySlot &slot); + + struct impl; + impl *impl_; + }; + +} // EQEmu + +#endif diff --git a/common/inventory_data_model.h b/common/inventory_data_model.h new file mode 100644 index 000000000..8679e1112 --- /dev/null +++ b/common/inventory_data_model.h @@ -0,0 +1,40 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_INVENTORY_DATA_MODEL_H +#define COMMON_INVENTORY_DATA_MODEL_H + +#include "inventory.h" + +namespace EQEmu +{ + class InventoryDataModel + { + public: + InventoryDataModel() { } + virtual ~InventoryDataModel() { } + + virtual void Begin() = 0; + virtual bool Commit() = 0; + virtual void Rollback() = 0; + virtual void Insert(const InventorySlot &slot, ItemInstance::pointer &inst) = 0; + virtual void Delete(const InventorySlot &slot) = 0; + }; +} // EQEmu + +#endif diff --git a/common/inventory_db_data_model.cpp b/common/inventory_db_data_model.cpp new file mode 100644 index 000000000..2465ef9f3 --- /dev/null +++ b/common/inventory_db_data_model.cpp @@ -0,0 +1,212 @@ +#include "inventory_db_data_model.h" +#include "shareddb.h" +#include "string_util.h" +#include +#include + +enum DataEventTypes +{ + DB_Insert, + DB_Delete +}; + +struct DataEvent +{ + DataEventTypes evt; + EQEmu::InventorySlot slot; + EQEmu::ItemInstance::pointer inst; +}; + +struct EQEmu::InventoryDatabaseDataModel::impl { + SharedDatabase *db_; + std::list events_; + uint32 char_id_; +}; + +EQEmu::InventoryDatabaseDataModel::InventoryDatabaseDataModel(SharedDatabase *db, uint32 char_id) { + impl_ = new impl; + impl_->db_ = db; + impl_->char_id_ = char_id; +} + +EQEmu::InventoryDatabaseDataModel::~InventoryDatabaseDataModel() { + delete impl_; +} + +void EQEmu::InventoryDatabaseDataModel::Begin() { + impl_->db_->TransactionBegin(); + impl_->events_.clear(); +} + +bool EQEmu::InventoryDatabaseDataModel::Commit() { + std::string base_insert = "INSERT INTO character_inventory(id, type, slot, bag_index, aug_index, " + "item_id, charges, color, attuned, custom_data, ornament_icon, ornament_idfile, ornament_hero_model" + ", tracking_id) VALUES"; + + std::string current_insert = base_insert; + bool insert = false; + for(auto iter : impl_->events_) { + if(iter.evt == DB_Delete) { + if(insert) { + insert = false; + + //commit the current_insert + auto res = impl_->db_->QueryDatabase(current_insert); + if(!res.Success()) { + Rollback(); + return false; + } + + current_insert = base_insert; + } + + std::string current_delete; + if(iter.slot.BagIndex() > -1) { + if(iter.slot.AugIndex() > -1) { + current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND bag_index=%u AND aug_index=%u", + impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.BagIndex(), iter.slot.AugIndex()); + } + else { + current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND bag_index=%u", + impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.BagIndex()); + } + } + else if(iter.slot.AugIndex() > -1) { + current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND aug_index=%u", + impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.AugIndex()); + } + else { + current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u", + impl_->char_id_, iter.slot.Type(), iter.slot.Slot()); + } + + auto res = impl_->db_->QueryDatabase(current_delete); + if(!res.Success()) { + Rollback(); + return false; + } + + } else { + //insert + if(!insert) { + insert = true; + } else { + current_insert += ","; + } + + current_insert += StringFormat("(%u, %i, %i, %i, %i, %u, %i, %u, %u, '%s', %u, %u, %u, %llu)", + impl_->char_id_, + iter.slot.Type(), + iter.slot.Slot(), + iter.slot.BagIndex(), + iter.slot.AugIndex(), + iter.inst->GetBaseItem()->ID, + iter.inst->GetCharges(), + iter.inst->GetColor(), + iter.inst->GetAttuned(), + EscapeString(iter.inst->GetCustomData()).c_str(), + iter.inst->GetOrnamentIcon(), + iter.inst->GetOrnamentIDFile(), + iter.inst->GetOrnamentHeroModel(), + iter.inst->GetTrackingID()); + } + } + + if(insert) { + insert = false; + + //commit the current_insert + auto res = impl_->db_->QueryDatabase(current_insert); + if(!res.Success()) { + Rollback(); + return false; + } + + current_insert = base_insert; + } + + impl_->db_->TransactionCommit(); + impl_->events_.clear(); + return true; +} + +void EQEmu::InventoryDatabaseDataModel::Rollback() { + impl_->db_->TransactionRollback(); + impl_->events_.clear(); +} + +void EQEmu::InventoryDatabaseDataModel::Insert(const InventorySlot &slot, ItemInstance::pointer &inst) { + DataEvent evt; + evt.evt = DB_Insert; + evt.inst = inst; + evt.slot = slot; + impl_->events_.push_back(evt); + + //insert current item + if(slot.BagIndex() < 0 && slot.AugIndex() < 0) { + //if bag put all bag contents in + //if common put all augment contents in + if(inst->GetBaseItem()->ItemClass == ItemClassContainer) { + auto container = inst->GetContainer(); + auto iter = container->Begin(); + while(iter != container->End()) { + DataEvent evt; + evt.evt = DB_Insert; + evt.inst = iter->second; + evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first, -1); + impl_->events_.push_back(evt); + + //do augments here + if(evt.inst->GetBaseItem()->ItemClass == ItemClassCommon) { + auto inst_container = evt.inst->GetContainer(); + auto inst_iter = inst_container->Begin(); + while(inst_iter != inst_container->End()) { + DataEvent evt; + evt.evt = DB_Insert; + evt.inst = inst_iter->second; + evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first, inst_iter->first); + impl_->events_.push_back(evt); + ++inst_iter; + } + } + + ++iter; + } + } + else if(inst->GetBaseItem()->ItemClass == ItemClassCommon) { + auto container = inst->GetContainer(); + auto iter = container->Begin(); + while(iter != container->End()) { + DataEvent evt; + evt.evt = DB_Insert; + evt.inst = iter->second; + evt.slot = InventorySlot(slot.Type(), slot.Slot(), -1, iter->first); + impl_->events_.push_back(evt); + + ++iter; + } + } + } + else if(slot.AugIndex() < 0 && inst->GetBaseItem()->ItemClass == ItemClassCommon) { + //bag item that can have augs + //if common put all augment contents in + auto container = inst->GetContainer(); + auto iter = container->Begin(); + while(iter != container->End()) { + DataEvent evt; + evt.evt = DB_Insert; + evt.inst = iter->second; + evt.slot = InventorySlot(slot.Type(), slot.Slot(), slot.BagIndex(), iter->first); + impl_->events_.push_back(evt); + + ++iter; + } + } +} + +void EQEmu::InventoryDatabaseDataModel::Delete(const InventorySlot &slot) { + DataEvent evt; + evt.evt = DB_Delete; + evt.slot = slot; + impl_->events_.push_back(evt); +} diff --git a/common/inventory_db_data_model.h b/common/inventory_db_data_model.h new file mode 100644 index 000000000..b26129095 --- /dev/null +++ b/common/inventory_db_data_model.h @@ -0,0 +1,45 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_INVENTORY_DB_DATA_MODEL_H +#define COMMON_INVENTORY_DB_DATA_MODEL_H + +#include "inventory_data_model.h" + +class SharedDatabase; + +namespace EQEmu +{ + class InventoryDatabaseDataModel : public InventoryDataModel + { + public: + InventoryDatabaseDataModel(SharedDatabase *db, uint32 char_id); + virtual ~InventoryDatabaseDataModel(); + + virtual void Begin(); + virtual bool Commit(); + virtual void Rollback(); + virtual void Insert(const InventorySlot &slot, ItemInstance::pointer &inst); + virtual void Delete(const InventorySlot &slot); + private: + struct impl; + impl *impl_; + }; +} // EQEmu + +#endif diff --git a/common/inventory_null_data_model.h b/common/inventory_null_data_model.h new file mode 100644 index 000000000..de7005e26 --- /dev/null +++ b/common/inventory_null_data_model.h @@ -0,0 +1,40 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_INVENTORY_NULL_DATA_MODEL_H +#define COMMON_INVENTORY_NULL_DATA_MODEL_H + +#include "inventory_data_model.h" + +namespace EQEmu +{ + class InventoryNullDataModel : public InventoryDataModel + { + public: + InventoryNullDataModel() { } + virtual ~InventoryNullDataModel() { } + + virtual void Begin() { } + virtual bool Commit() { return true; } + virtual void Rollback() { } + virtual void Insert(const InventorySlot &slot, ItemInstance::pointer &inst) { } + virtual void Delete(const InventorySlot &slot) { } + }; +} // EQEmu + +#endif diff --git a/common/item.cpp b/common/item.cpp index 3e8be66ca..67664ccc5 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -105,9 +105,9 @@ ItemInst* ItemInstQueue::peek_front() const // -// class Inventory +// class InventoryOld // -Inventory::~Inventory() +InventoryOld::~InventoryOld() { for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { safe_delete(iter->second); @@ -135,7 +135,7 @@ Inventory::~Inventory() m_trade.clear(); } -void Inventory::CleanDirty() { +void InventoryOld::CleanDirty() { auto iter = dirty_inst.begin(); while (iter != dirty_inst.end()) { delete (*iter); @@ -144,14 +144,14 @@ void Inventory::CleanDirty() { dirty_inst.clear(); } -void Inventory::MarkDirty(ItemInst *inst) { +void InventoryOld::MarkDirty(ItemInst *inst) { if (inst) { dirty_inst.push_back(inst); } } // Retrieve item at specified slot; returns false if item not found -ItemInst* Inventory::GetItem(int16 slot_id) const +ItemInst* InventoryOld::GetItem(int16 slot_id) const { ItemInst* result = nullptr; @@ -186,37 +186,37 @@ ItemInst* Inventory::GetItem(int16 slot_id) const // Inner bag slots else if (slot_id >= EmuConstants::TRADE_BAGS_BEGIN && slot_id <= EmuConstants::TRADE_BAGS_END) { // Trade bag slots - ItemInst* inst = _GetItem(m_trade, Inventory::CalcSlotId(slot_id)); + ItemInst* inst = _GetItem(m_trade, InventoryOld::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + result = inst->GetItem(InventoryOld::CalcBagIdx(slot_id)); } } else if (slot_id >= EmuConstants::SHARED_BANK_BAGS_BEGIN && slot_id <= EmuConstants::SHARED_BANK_BAGS_END) { // Shared Bank bag slots - ItemInst* inst = _GetItem(m_shbank, Inventory::CalcSlotId(slot_id)); + ItemInst* inst = _GetItem(m_shbank, InventoryOld::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + result = inst->GetItem(InventoryOld::CalcBagIdx(slot_id)); } } else if (slot_id >= EmuConstants::BANK_BAGS_BEGIN && slot_id <= EmuConstants::BANK_BAGS_END) { // Bank bag slots - ItemInst* inst = _GetItem(m_bank, Inventory::CalcSlotId(slot_id)); + ItemInst* inst = _GetItem(m_bank, InventoryOld::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + result = inst->GetItem(InventoryOld::CalcBagIdx(slot_id)); } } else if (slot_id >= EmuConstants::CURSOR_BAG_BEGIN && slot_id <= EmuConstants::CURSOR_BAG_END) { // Cursor bag slots ItemInst* inst = m_cursor.peek_front(); if (inst && inst->IsType(ItemClassContainer)) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + result = inst->GetItem(InventoryOld::CalcBagIdx(slot_id)); } } else if (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END) { // Personal inventory bag slots - ItemInst* inst = _GetItem(m_inv, Inventory::CalcSlotId(slot_id)); + ItemInst* inst = _GetItem(m_inv, InventoryOld::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + result = inst->GetItem(InventoryOld::CalcBagIdx(slot_id)); } } @@ -224,13 +224,13 @@ ItemInst* Inventory::GetItem(int16 slot_id) const } // Retrieve item at specified position within bag -ItemInst* Inventory::GetItem(int16 slot_id, uint8 bagidx) const +ItemInst* InventoryOld::GetItem(int16 slot_id, uint8 bagidx) const { - return GetItem(Inventory::CalcSlotId(slot_id, bagidx)); + return GetItem(InventoryOld::CalcSlotId(slot_id, bagidx)); } // Put an item snto specified slot -int16 Inventory::PutItem(int16 slot_id, const ItemInst& inst) +int16 InventoryOld::PutItem(int16 slot_id, const ItemInst& inst) { // Clean up item already in slot (if exists) DeleteItem(slot_id); @@ -245,19 +245,19 @@ int16 Inventory::PutItem(int16 slot_id, const ItemInst& inst) return _PutItem(slot_id, inst.Clone()); } -int16 Inventory::PushCursor(const ItemInst& inst) +int16 InventoryOld::PushCursor(const ItemInst& inst) { m_cursor.push(inst.Clone()); return MainCursor; } -ItemInst* Inventory::GetCursorItem() +ItemInst* InventoryOld::GetCursorItem() { return m_cursor.peek_front(); } // Swap items in inventory -bool Inventory::SwapItem(int16 slot_a, int16 slot_b) +bool InventoryOld::SwapItem(int16 slot_a, int16 slot_b) { // Temp holding areas for a and b ItemInst* inst_a = GetItem(slot_a); @@ -273,7 +273,7 @@ bool Inventory::SwapItem(int16 slot_a, int16 slot_b) } // Remove item from inventory (with memory delete) -bool Inventory::DeleteItem(int16 slot_id, uint8 quantity) +bool InventoryOld::DeleteItem(int16 slot_id, uint8 quantity) { // Pop item out of inventory map (or queue) ItemInst* item_to_delete = PopItem(slot_id); @@ -293,7 +293,7 @@ bool Inventory::DeleteItem(int16 slot_id, uint8 quantity) ((item_to_delete->GetItem()->MaxCharges == 0) || item_to_delete->IsExpendable())) ) { // Item can now be destroyed - Inventory::MarkDirty(item_to_delete); + InventoryOld::MarkDirty(item_to_delete); return true; } } @@ -303,19 +303,19 @@ bool Inventory::DeleteItem(int16 slot_id, uint8 quantity) return false; } - Inventory::MarkDirty(item_to_delete); + InventoryOld::MarkDirty(item_to_delete); return true; } // Checks All items in a bag for No Drop -bool Inventory::CheckNoDrop(int16 slot_id) { +bool InventoryOld::CheckNoDrop(int16 slot_id) { ItemInst* inst = GetItem(slot_id); if (!inst) return false; if (!inst->GetItem()->NoDrop) return true; if (inst->GetItem()->ItemClass == 1) { for (uint8 i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) { - ItemInst* bagitem = GetItem(Inventory::CalcSlotId(slot_id, i)); + ItemInst* bagitem = GetItem(InventoryOld::CalcSlotId(slot_id, i)); if (bagitem && !bagitem->GetItem()->NoDrop) return true; } @@ -325,7 +325,7 @@ bool Inventory::CheckNoDrop(int16 slot_id) { // Remove item from bucket without memory delete // Returns item pointer if full delete was successful -ItemInst* Inventory::PopItem(int16 slot_id) +ItemInst* InventoryOld::PopItem(int16 slot_id) { ItemInst* p = nullptr; @@ -358,9 +358,9 @@ ItemInst* Inventory::PopItem(int16 slot_id) } else { // Is slot inside bag? - ItemInst* baginst = GetItem(Inventory::CalcSlotId(slot_id)); + ItemInst* baginst = GetItem(InventoryOld::CalcSlotId(slot_id)); if (baginst != nullptr && baginst->IsType(ItemClassContainer)) { - p = baginst->PopItem(Inventory::CalcBagIdx(slot_id)); + p = baginst->PopItem(InventoryOld::CalcBagIdx(slot_id)); } } @@ -368,7 +368,7 @@ ItemInst* Inventory::PopItem(int16 slot_id) return p; } -bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { +bool InventoryOld::HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity) { if (ItemToTry->Stackable) { @@ -388,7 +388,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { } if (InvItem && InvItem->IsType(ItemClassContainer)) { - int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_BEGIN); + int16 BaseSlotID = InventoryOld::CalcSlotId(i, SUB_BEGIN); uint8 BagSize = InvItem->GetItem()->BagSlots; for (uint8 BagSlot = SUB_BEGIN; BagSlot < BagSize; BagSlot++) { @@ -432,7 +432,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { } else if (InvItem->IsType(ItemClassContainer) && CanItemFitInContainer(ItemToTry, InvItem->GetItem())) { - int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_BEGIN); + int16 BaseSlotID = InventoryOld::CalcSlotId(i, SUB_BEGIN); uint8 BagSize = InvItem->GetItem()->BagSlots; @@ -468,7 +468,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { //This function has a flaw in that it only returns the last stack that it looked at //when quantity is greater than 1 and not all of quantity can be found in 1 stack. -int16 Inventory::HasItem(uint32 item_id, uint8 quantity, uint8 where) +int16 InventoryOld::HasItem(uint32 item_id, uint8 quantity, uint8 where) { int16 slot_id = INVALID_INDEX; @@ -518,7 +518,7 @@ int16 Inventory::HasItem(uint32 item_id, uint8 quantity, uint8 where) } //this function has the same quantity flaw mentioned above in HasItem() -int16 Inventory::HasItemByUse(uint8 use, uint8 quantity, uint8 where) +int16 InventoryOld::HasItemByUse(uint8 use, uint8 quantity, uint8 where) { int16 slot_id = INVALID_INDEX; @@ -564,7 +564,7 @@ int16 Inventory::HasItemByUse(uint8 use, uint8 quantity, uint8 where) return slot_id; } -int16 Inventory::HasItemByLoreGroup(uint32 loregroup, uint8 where) +int16 InventoryOld::HasItemByLoreGroup(uint32 loregroup, uint8 where) { int16 slot_id = INVALID_INDEX; @@ -612,7 +612,7 @@ int16 Inventory::HasItemByLoreGroup(uint32 loregroup, uint8 where) // Locate an available inventory slot // Returns slot_id when there's one available, else SLOT_INVALID -int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow) +int16 InventoryOld::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow) { // Check basic inventory for (int16 i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) { @@ -631,7 +631,7 @@ int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, boo continue; } - int16 base_slot_id = Inventory::CalcSlotId(i, SUB_BEGIN); + int16 base_slot_id = InventoryOld::CalcSlotId(i, SUB_BEGIN); uint8 slots = inst->GetItem()->BagSlots; uint8 j; @@ -656,9 +656,9 @@ int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, boo } // This is a mix of HasSpaceForItem and FindFreeSlot..due to existing coding behavior, it was better to add a new helper function... -int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { +int16 InventoryOld::FindFreeSlotForTradeItem(const ItemInst* inst) { // Do not arbitrarily use this function..it is designed for use with Client::ResetTrade() and Client::FinishTrade(). - // If you have a need, use it..but, understand it is not a compatible replacement for Inventory::FindFreeSlot(). + // If you have a need, use it..but, understand it is not a compatible replacement for InventoryOld::FindFreeSlot(). // // I'll probably implement a bitmask in the new inventory system to avoid having to adjust stack bias @@ -701,7 +701,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { continue; if ((sub_inst->GetID() == inst->GetID()) && (sub_inst->GetCharges() < sub_inst->GetItem()->StackSize)) - return Inventory::CalcSlotId(free_slot, free_bag_slot); + return InventoryOld::CalcSlotId(free_slot, free_bag_slot); } } } @@ -717,7 +717,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) - return Inventory::CalcSlotId(free_slot, free_bag_slot); + return InventoryOld::CalcSlotId(free_slot, free_bag_slot); } } } @@ -732,7 +732,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) - return Inventory::CalcSlotId(free_slot, free_bag_slot); + return InventoryOld::CalcSlotId(free_slot, free_bag_slot); } } } @@ -754,7 +754,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) - return Inventory::CalcSlotId(free_slot, free_bag_slot); + return InventoryOld::CalcSlotId(free_slot, free_bag_slot); } } } @@ -764,7 +764,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { } // Opposite of below: Get parent bag slot_id from a slot inside of bag -int16 Inventory::CalcSlotId(int16 slot_id) { +int16 InventoryOld::CalcSlotId(int16 slot_id) { int16 parent_slot_id = INVALID_INDEX; // this is not a bag range... using this risks over-writing existing items @@ -792,8 +792,8 @@ int16 Inventory::CalcSlotId(int16 slot_id) { } // Calculate slot_id for an item within a bag -int16 Inventory::CalcSlotId(int16 bagslot_id, uint8 bagidx) { - if (!Inventory::SupportsContainers(bagslot_id)) +int16 InventoryOld::CalcSlotId(int16 bagslot_id, uint8 bagidx) { + if (!InventoryOld::SupportsContainers(bagslot_id)) return INVALID_INDEX; int16 slot_id = INVALID_INDEX; @@ -817,7 +817,7 @@ int16 Inventory::CalcSlotId(int16 bagslot_id, uint8 bagidx) { return slot_id; } -uint8 Inventory::CalcBagIdx(int16 slot_id) { +uint8 InventoryOld::CalcBagIdx(int16 slot_id) { uint8 index = 0; // this is not a bag range... using this risks over-writing existing items @@ -846,7 +846,7 @@ uint8 Inventory::CalcBagIdx(int16 slot_id) { return index; } -int16 Inventory::CalcSlotFromMaterial(uint8 material) +int16 InventoryOld::CalcSlotFromMaterial(uint8 material) { switch (material) { @@ -873,7 +873,7 @@ int16 Inventory::CalcSlotFromMaterial(uint8 material) } } -uint8 Inventory::CalcMaterialFromSlot(int16 equipslot) +uint8 InventoryOld::CalcMaterialFromSlot(int16 equipslot) { switch (equipslot) { @@ -901,7 +901,7 @@ uint8 Inventory::CalcMaterialFromSlot(int16 equipslot) } } -bool Inventory::CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_Struct *Container) { +bool InventoryOld::CanItemFitInContainer(const ItemData *ItemToTry, const ItemData *Container) { if (!ItemToTry || !Container) return false; @@ -918,7 +918,7 @@ bool Inventory::CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_S return true; } -bool Inventory::SupportsClickCasting(int16 slot_id) +bool InventoryOld::SupportsClickCasting(int16 slot_id) { // there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range if ((uint16)slot_id <= EmuConstants::GENERAL_END || slot_id == MainPowerSource) @@ -934,7 +934,7 @@ bool Inventory::SupportsClickCasting(int16 slot_id) return false; } -bool Inventory::SupportsPotionBeltCasting(int16 slot_id) +bool InventoryOld::SupportsPotionBeltCasting(int16 slot_id) { if ((uint16)slot_id <= EmuConstants::GENERAL_END || slot_id == MainPowerSource || (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END)) return true; @@ -943,7 +943,7 @@ bool Inventory::SupportsPotionBeltCasting(int16 slot_id) } // Test whether a given slot can support a container item -bool Inventory::SupportsContainers(int16 slot_id) +bool InventoryOld::SupportsContainers(int16 slot_id) { if ((slot_id == MainCursor) || (slot_id >= EmuConstants::GENERAL_BEGIN && slot_id <= EmuConstants::GENERAL_END) || @@ -957,7 +957,7 @@ bool Inventory::SupportsContainers(int16 slot_id) return false; } -int Inventory::GetSlotByItemInst(ItemInst *inst) { +int InventoryOld::GetSlotByItemInst(ItemInst *inst) { if (!inst) return INVALID_INDEX; @@ -993,7 +993,7 @@ int Inventory::GetSlotByItemInst(ItemInst *inst) { return INVALID_INDEX; } -uint8 Inventory::FindBrightestLightType() +uint8 InventoryOld::FindBrightestLightType() { uint8 brightest_light_type = 0; @@ -1032,7 +1032,7 @@ uint8 Inventory::FindBrightestLightType() return brightest_light_type; } -void Inventory::dumpEntireInventory() { +void InventoryOld::dumpEntireInventory() { dumpWornItems(); dumpInventory(); @@ -1042,29 +1042,29 @@ void Inventory::dumpEntireInventory() { std::cout << std::endl; } -void Inventory::dumpWornItems() { +void InventoryOld::dumpWornItems() { std::cout << "Worn items:" << std::endl; dumpItemCollection(m_worn); } -void Inventory::dumpInventory() { +void InventoryOld::dumpInventory() { std::cout << "Inventory items:" << std::endl; dumpItemCollection(m_inv); } -void Inventory::dumpBankItems() { +void InventoryOld::dumpBankItems() { std::cout << "Bank items:" << std::endl; dumpItemCollection(m_bank); } -void Inventory::dumpSharedBankItems() { +void InventoryOld::dumpSharedBankItems() { std::cout << "Shared Bank items:" << std::endl; dumpItemCollection(m_shbank); } -int Inventory::GetSlotByItemInstCollection(const std::map &collection, ItemInst *inst) { +int InventoryOld::GetSlotByItemInstCollection(const std::map &collection, ItemInst *inst) { for (auto iter = collection.begin(); iter != collection.end(); ++iter) { ItemInst *t_inst = iter->second; if (t_inst == inst) { @@ -1074,7 +1074,7 @@ int Inventory::GetSlotByItemInstCollection(const std::map &col if (t_inst && !t_inst->IsType(ItemClassContainer)) { for (auto b_iter = t_inst->_cbegin(); b_iter != t_inst->_cend(); ++b_iter) { if (b_iter->second == inst) { - return Inventory::CalcSlotId(iter->first, b_iter->first); + return InventoryOld::CalcSlotId(iter->first, b_iter->first); } } } @@ -1083,7 +1083,7 @@ int Inventory::GetSlotByItemInstCollection(const std::map &col return -1; } -void Inventory::dumpItemCollection(const std::map &collection) +void InventoryOld::dumpItemCollection(const std::map &collection) { for (auto it = collection.cbegin(); it != collection.cend(); ++it) { auto inst = it->second; @@ -1097,7 +1097,7 @@ void Inventory::dumpItemCollection(const std::map &collection) } } -void Inventory::dumpBagContents(ItemInst *inst, std::map::const_iterator *it) +void InventoryOld::dumpBagContents(ItemInst *inst, std::map::const_iterator *it) { if (!inst || !inst->IsType(ItemClassContainer)) return; @@ -1108,7 +1108,7 @@ void Inventory::dumpBagContents(ItemInst *inst, std::map::cons if (!baginst || !baginst->GetItem()) continue; - std::string subSlot = StringFormat(" Slot %d: %s (%d)", Inventory::CalcSlotId((*it)->first, itb->first), + std::string subSlot = StringFormat(" Slot %d: %s (%d)", InventoryOld::CalcSlotId((*it)->first, itb->first), baginst->GetItem()->Name, (baginst->GetCharges() <= 0) ? 1 : baginst->GetCharges()); std::cout << subSlot << std::endl; } @@ -1116,7 +1116,7 @@ void Inventory::dumpBagContents(ItemInst *inst, std::map::cons } // Internal Method: Retrieves item within an inventory bucket -ItemInst* Inventory::_GetItem(const std::map& bucket, int16 slot_id) const +ItemInst* InventoryOld::_GetItem(const std::map& bucket, int16 slot_id) const { auto it = bucket.find(slot_id); if (it != bucket.end()) { @@ -1129,7 +1129,7 @@ ItemInst* Inventory::_GetItem(const std::map& bucket, int16 sl // Internal Method: "put" item into bucket, without regard for what is currently in bucket // Assumes item has already been allocated -int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst) +int16 InventoryOld::_PutItem(int16 slot_id, ItemInst* inst) { // What happens here when we _PutItem(MainCursor)? Bad things..really bad things... // @@ -1175,25 +1175,25 @@ int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst) } else { // Slot must be within a bag - parentSlot = Inventory::CalcSlotId(slot_id); + parentSlot = InventoryOld::CalcSlotId(slot_id); ItemInst* baginst = GetItem(parentSlot); // Get parent bag if (baginst && baginst->IsType(ItemClassContainer)) { - baginst->_PutItem(Inventory::CalcBagIdx(slot_id), inst); + baginst->_PutItem(InventoryOld::CalcBagIdx(slot_id), inst); result = slot_id; } } if (result == INVALID_INDEX) { - Log.Out(Logs::General, Logs::Error, "Inventory::_PutItem: Invalid slot_id specified (%i) with parent slot id (%i)", slot_id, parentSlot); - Inventory::MarkDirty(inst); // Slot not found, clean up + Log.Out(Logs::General, Logs::Error, "InventoryOld::_PutItem: Invalid slot_id specified (%i) with parent slot id (%i)", slot_id, parentSlot); + InventoryOld::MarkDirty(inst); // Slot not found, clean up } return result; } // Internal Method: Checks an inventory bucket for a particular item -int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, uint8 quantity) +int16 InventoryOld::_HasItem(std::map& bucket, uint32 item_id, uint8 quantity) { uint8 quantity_found = 0; @@ -1221,7 +1221,7 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, ui if (bag_inst->GetID() == item_id) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(iter->first, bag_iter->first); + return InventoryOld::CalcSlotId(iter->first, bag_iter->first); } for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { @@ -1235,7 +1235,7 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, ui } // Internal Method: Checks an inventory queue type bucket for a particular item -int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) +int16 InventoryOld::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) { // The downfall of this (these) queue procedure is that callers presume that when an item is // found, it is presented as being available on the cursor. In cases of a parity check, this @@ -1269,7 +1269,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) if (bag_inst->GetID() == item_id) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(MainCursor, bag_iter->first); + return InventoryOld::CalcSlotId(MainCursor, bag_iter->first); } for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { @@ -1286,7 +1286,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) } // Internal Method: Checks an inventory bucket for a particular item -int16 Inventory::_HasItemByUse(std::map& bucket, uint8 use, uint8 quantity) +int16 InventoryOld::_HasItemByUse(std::map& bucket, uint8 use, uint8 quantity) { uint8 quantity_found = 0; @@ -1309,7 +1309,7 @@ int16 Inventory::_HasItemByUse(std::map& bucket, uint8 use, ui if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->ItemType == use) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(iter->first, bag_iter->first); + return InventoryOld::CalcSlotId(iter->first, bag_iter->first); } } } @@ -1318,7 +1318,7 @@ int16 Inventory::_HasItemByUse(std::map& bucket, uint8 use, ui } // Internal Method: Checks an inventory queue type bucket for a particular item -int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) +int16 InventoryOld::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) { uint8 quantity_found = 0; @@ -1341,7 +1341,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->ItemType == use) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(MainCursor, bag_iter->first); + return InventoryOld::CalcSlotId(MainCursor, bag_iter->first); } } @@ -1352,7 +1352,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) return INVALID_INDEX; } -int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 loregroup) +int16 InventoryOld::_HasItemByLoreGroup(std::map& bucket, uint32 loregroup) { for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { auto inst = iter->second; @@ -1376,7 +1376,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 if (bag_inst == nullptr) { continue; } if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->LoreGroup == loregroup) - return Inventory::CalcSlotId(iter->first, bag_iter->first); + return InventoryOld::CalcSlotId(iter->first, bag_iter->first); for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { auto aug_inst = bag_inst->GetAugment(index); @@ -1392,7 +1392,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 } // Internal Method: Checks an inventory queue type bucket for a particular item -int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) +int16 InventoryOld::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) { for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { auto inst = *iter; @@ -1416,7 +1416,7 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (bag_inst == nullptr) { continue; } if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->LoreGroup == loregroup) - return Inventory::CalcSlotId(MainCursor, bag_iter->first); + return InventoryOld::CalcSlotId(MainCursor, bag_iter->first); for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { auto aug_inst = bag_inst->GetAugment(index); @@ -1438,7 +1438,7 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) // // class ItemInst // -ItemInst::ItemInst(const Item_Struct* item, int16 charges) { +ItemInst::ItemInst(const ItemData* item, int16 charges) { m_use_type = ItemInstNormal; m_item = item; m_charges = charges; @@ -1548,7 +1548,7 @@ ItemInst::ItemInst(const ItemInst& copy) m_evolveLvl = copy.m_evolveLvl; m_activated = copy.m_activated; if (copy.m_scaledItem) - m_scaledItem = new Item_Struct(*copy.m_scaledItem); + m_scaledItem = new ItemData(*copy.m_scaledItem); else m_scaledItem = nullptr; @@ -1767,7 +1767,7 @@ void ItemInst::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent) continue; } - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); if (item == nullptr) { cur = m_contents.erase(cur); continue; @@ -1908,7 +1908,7 @@ bool ItemInst::UpdateOrnamentationInfo() { int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); if (GetOrnamentationAug(ornamentationAugtype)) { - const Item_Struct* ornamentItem; + const ItemData* ornamentItem; ornamentItem = GetOrnamentationAug(ornamentationAugtype)->GetItem(); if (ornamentItem != nullptr) { @@ -1935,7 +1935,7 @@ bool ItemInst::UpdateOrnamentationInfo() { return ornamentSet; } -bool ItemInst::CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll) { +bool ItemInst::CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll) { if (!ItemToTry || !Container) return false; if (ItemToTry->ItemType == ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0) @@ -2003,7 +2003,7 @@ void ItemInst::PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id) if (item_id == NO_ITEM) { return; } if (db == nullptr) { return; /* TODO: add log message for nullptr */ } - const ItemInst* aug = db->CreateItem(item_id); + const ItemInst* aug = db->CreateItemOld(item_id); if (aug) { PutAugment(slot, *aug); safe_delete(aug); @@ -2069,7 +2069,7 @@ bool ItemInst::IsAmmo() const } -const Item_Struct* ItemInst::GetItem() const +const ItemData* ItemInst::GetItem() const { if (!m_item) return nullptr; @@ -2080,7 +2080,7 @@ const Item_Struct* ItemInst::GetItem() const return m_item; } -const Item_Struct* ItemInst::GetUnscaledItem() const +const ItemData* ItemInst::GetUnscaledItem() const { // No operator calls and defaults to nullptr return m_item; @@ -2159,7 +2159,7 @@ ItemInst* ItemInst::Clone() const bool ItemInst::IsSlotAllowed(int16 slot_id) const { // 'SupportsContainers' and 'slot_id > 21' previously saw the reassigned PowerSource slot (9999 to 22) as valid if (!m_item) { return false; } - else if (Inventory::SupportsContainers(slot_id)) { return true; } + else if (InventoryOld::SupportsContainers(slot_id)) { return true; } else if (m_item->Slots & (1 << slot_id)) { return true; } else if (slot_id == MainPowerSource && (m_item->Slots & (1 << 22))) { return true; } // got lazy... else if (slot_id != MainPowerSource && slot_id > EmuConstants::EQUIPMENT_END) { return true; } @@ -2188,10 +2188,10 @@ void ItemInst::ScaleItem() { return; if (m_scaledItem) { - memcpy(m_scaledItem, m_item, sizeof(Item_Struct)); + memcpy(m_scaledItem, m_item, sizeof(ItemData)); } else { - m_scaledItem = new Item_Struct(*m_item); + m_scaledItem = new ItemData(*m_item); } float Mult = (float)(GetExp()) / 10000; // scaling is determined by exp, with 10,000 being full stats @@ -2335,9 +2335,9 @@ EvolveInfo::~EvolveInfo() { // -// struct Item_Struct +// struct ItemData // -bool Item_Struct::IsEquipable(uint16 Race, uint16 Class_) const +bool ItemData::IsEquipable(uint16 Race, uint16 Class_) const { bool IsRace = false; bool IsClass = false; diff --git a/common/item.h b/common/item.h index a5dd01f95..fe0b5ad1d 100644 --- a/common/item.h +++ b/common/item.h @@ -27,7 +27,7 @@ class ItemParse; // Parses item packets class EvolveInfo; // Stores information about an evolving item family #include "../common/eq_constants.h" -#include "../common/item_struct.h" +#include "../common/item_data.h" #include "../common/timer.h" #include @@ -104,9 +104,9 @@ protected: }; // ######################################## -// Class: Inventory +// Class: InventoryOld // Character inventory -class Inventory +class InventoryOld { friend class ItemInst; public: @@ -114,8 +114,8 @@ public: // Public Methods /////////////////////////////// - Inventory() { m_version = ClientVersion::Unknown; m_versionset = false; } - ~Inventory(); + InventoryOld() { m_version = ClientVersion::Unknown; m_versionset = false; } + ~InventoryOld(); // Inventory v2 creep bool SetInventoryVersion(ClientVersion version) { @@ -168,7 +168,7 @@ public: ItemInst* PopItem(int16 slot_id); // Check whether there is space for the specified number of the specified item. - bool HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity); + bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity); // Check whether item exists in inventory // where argument specifies OR'd list of invWhere constants to look @@ -193,7 +193,7 @@ public: static int16 CalcSlotFromMaterial(uint8 material); static uint8 CalcMaterialFromSlot(int16 equipslot); - static bool CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_Struct *Container); + static bool CanItemFitInContainer(const ItemData *ItemToTry, const ItemData *Container); // Test for valid inventory casting slot bool SupportsClickCasting(int16 slot_id); @@ -270,7 +270,7 @@ public: ///////////////////////// // Constructors/Destructor - ItemInst(const Item_Struct* item = nullptr, int16 charges = 0); + ItemInst(const ItemData* item = nullptr, int16 charges = 0); ItemInst(SharedDatabase *db, uint32 item_id, int16 charges = 0); @@ -331,7 +331,7 @@ public: bool IsAugmented(); ItemInst* GetOrnamentationAug(int32 ornamentationAugtype) const; bool UpdateOrnamentationInfo(); - static bool CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll = false); + static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false); // Has attack/delay? bool IsWeapon() const; @@ -340,8 +340,8 @@ public: // Accessors const uint32 GetID() const { return ((m_item) ? m_item->ID : NO_ITEM); } const uint32 GetItemScriptID() const { return ((m_item) ? m_item->ScriptFileID : NO_ITEM); } - const Item_Struct* GetItem() const; - const Item_Struct* GetUnscaledItem() const; + const ItemData* GetItem() const; + const ItemData* GetUnscaledItem() const; int16 GetCharges() const { return m_charges; } void SetCharges(int16 charges) { m_charges = charges; } @@ -376,7 +376,7 @@ public: // Allows treatment of this object as though it were a pointer to m_item operator bool() const { return (m_item != nullptr); } - // Compare inner Item_Struct of two ItemInst objects + // Compare inner ItemData of two ItemInst objects bool operator==(const ItemInst& right) const { return (this->m_item == right.m_item); } bool operator!=(const ItemInst& right) const { return (this->m_item != right.m_item); } @@ -425,13 +425,13 @@ protected: std::map::const_iterator _cbegin() { return m_contents.cbegin(); } std::map::const_iterator _cend() { return m_contents.cend(); } - friend class Inventory; + friend class InventoryOld; void _PutItem(uint8 index, ItemInst* inst) { m_contents[index] = inst; } ItemInstTypes m_use_type; // Usage type for item - const Item_Struct* m_item; // Ptr to item data + const ItemData* m_item; // Ptr to item data int16 m_charges; // # of charges for chargeable items uint32 m_price; // Bazaar /trader price uint32 m_color; @@ -443,7 +443,7 @@ protected: uint32 m_exp; int8 m_evolveLvl; bool m_activated; - Item_Struct* m_scaledItem; + ItemData* m_scaledItem; EvolveInfo* m_evolveInfo; bool m_scaling; uint32 m_ornamenticon; diff --git a/common/item_container.cpp b/common/item_container.cpp new file mode 100644 index 000000000..ecb7797bc --- /dev/null +++ b/common/item_container.cpp @@ -0,0 +1,135 @@ +#include "item_container.h" +#include "item_container_default_serialization.h" +#include + +struct EQEmu::ItemContainer::impl +{ + std::map items_; + ItemContainerSerializationStrategy *serialize_strat_; +}; + +EQEmu::ItemContainer::ItemContainer() +{ + impl_ = new impl(); + impl_->serialize_strat_ = new ItemContainerDefaultSerialization(); +} + +EQEmu::ItemContainer::ItemContainer(ItemContainerSerializationStrategy *strategy) { + impl_ = new impl(); + impl_->serialize_strat_ = strategy; +} + +EQEmu::ItemContainer::~ItemContainer() +{ + if(impl_) { + delete impl_->serialize_strat_; + delete impl_; + } +} + +EQEmu::ItemContainer::ItemContainer(ItemContainer &&other) { + impl_ = other.impl_; + other.impl_ = nullptr; +} + +EQEmu::ItemContainer& EQEmu::ItemContainer::operator=(ItemContainer &&other) { + if(this == &other) + return *this; + + impl_ = other.impl_; + other.impl_ = nullptr; + return *this; +} + +EQEmu::ItemInstance::pointer EQEmu::ItemContainer::Get(const int slot_id) { + auto iter = impl_->items_.find(slot_id); + if(iter != impl_->items_.end()) { + return iter->second; + } + + return EQEmu::ItemInstance::pointer(nullptr); +} + +bool EQEmu::ItemContainer::Put(const int slot_id, ItemInstance::pointer &inst) { + if(!inst) { + impl_->items_.erase(slot_id); + return true; + } else { + auto iter = impl_->items_.find(slot_id); + if(iter == impl_->items_.end()) { + impl_->items_[slot_id] = inst; + return true; + } + } + + return false; +} + +bool EQEmu::ItemContainer::HasItem(uint32 item_id) { + for(auto &item : impl_->items_) { + if(item.second->GetBaseItem()->ID == item_id) { + return true; + } + } + + return false; +} + +bool EQEmu::ItemContainer::HasItemByLoreGroup(uint32 loregroup) { + if(loregroup == 0xFFFFFFFF) + return false; + + for(auto &item : impl_->items_) { + if(item.second->GetBaseItem()->LoreGroup == loregroup) { + return true; + } + } + + return false; +} + +uint32 EQEmu::ItemContainer::Size() { + return (uint32)impl_->items_.size(); +} + +uint32 EQEmu::ItemContainer::Size() const { + return (uint32)impl_->items_.size(); +} + +bool EQEmu::ItemContainer::Delete(const int slot_id) { + auto iter = impl_->items_.find(slot_id); + if(iter == impl_->items_.end()) { + return false; + } else { + impl_->items_.erase(iter); + return true; + } +} + +bool EQEmu::ItemContainer::Serialize(MemoryBuffer &buf, int container_number) { + if(impl_->serialize_strat_) { + return impl_->serialize_strat_->Serialize(buf, container_number, impl_->items_); + } + + return false; +} + +EQEmu::ItemContainer::ItemContainerIter EQEmu::ItemContainer::Begin() { + return impl_->items_.begin(); +} + +EQEmu::ItemContainer::ItemContainerIter EQEmu::ItemContainer::End() { + return impl_->items_.end(); +} + +void EQEmu::ItemContainer::Interrogate(int level) { + char buffer[16] = { 0 }; + for(int i = 0; i < level; ++i) { + buffer[i] = '\t'; + } + + for(auto &iter : impl_->items_) { + printf("%s%u: (%u)%s (%u)\n", buffer, iter.first, iter.second->GetBaseItem()->ID, iter.second->GetBaseItem()->Name, iter.second->GetCharges()); + iter.second->Interrogate(level + 1); + } +} \ No newline at end of file diff --git a/common/item_container.h b/common/item_container.h new file mode 100644 index 000000000..14690bcfd --- /dev/null +++ b/common/item_container.h @@ -0,0 +1,70 @@ +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY except by those people which sell it, which +are required to give you total support for your newly bought product; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_ITEM_CONTAINER_H +#define COMMON_ITEM_CONTAINER_H + +#include "item_instance.h" +#include "item_container_serialization_strategy.h" +#include "memory_buffer.h" +#include +#include + +namespace EQEmu +{ + class ItemContainerSerializationStrategy; + class ItemContainer + { + public: + typedef std::map::const_iterator ItemContainerIter; + + ItemContainer(); + ItemContainer(ItemContainerSerializationStrategy *strategy); + ~ItemContainer(); + ItemContainer(ItemContainer &&other); + ItemContainer& operator=(ItemContainer &&other); + + ItemInstance::pointer Get(const int slot_id); + bool Put(const int slot_id, ItemInstance::pointer &inst); + bool Delete(const int slot_id); + + //Utility + bool HasItem(uint32 item_id); + bool HasItemByLoreGroup(uint32 loregroup); + + uint32 Size(); + uint32 Size() const; + + //Low level interface for encode/decode + bool Serialize(MemoryBuffer &buf, int container_number); + ItemContainerIter Begin(); + ItemContainerIter End(); + + //testing + void Interrogate(int level); + protected: + struct impl; + impl *impl_; + + private: + ItemContainer(const ItemContainer &other); + ItemContainer& operator=(const ItemContainer &other); + }; +} // EQEmu + +#endif diff --git a/common/item_container_default_serialization.cpp b/common/item_container_default_serialization.cpp new file mode 100644 index 000000000..017221bd6 --- /dev/null +++ b/common/item_container_default_serialization.cpp @@ -0,0 +1,19 @@ +#include "item_container_default_serialization.h" + +bool EQEmu::ItemContainerDefaultSerialization::Serialize(MemoryBuffer &buf, const int container_number, const std::map& items) { + if(items.size() == 0) { + return false; + } + + bool ret = false; + for(auto &iter : items) { + buf.Write(container_number); + buf.Write(iter.first); + buf.Write(-1); + buf.Write(-1); + buf.Write(iter.second.get()); + ret = true; + } + + return ret; +} diff --git a/common/item_container_default_serialization.h b/common/item_container_default_serialization.h new file mode 100644 index 000000000..b30f55879 --- /dev/null +++ b/common/item_container_default_serialization.h @@ -0,0 +1,35 @@ +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY except by those people which sell it, which +are required to give you total support for your newly bought product; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_ITEM_CONTAINER_DEFAULT_SERIALIZATION_H +#define COMMON_ITEM_CONTAINER_DEFAULT_SERIALIZATION_H + +#include "item_container_serialization_strategy.h" + +namespace EQEmu +{ + class ItemContainerDefaultSerialization : public ItemContainerSerializationStrategy + { + public: + ItemContainerDefaultSerialization() { } + virtual ~ItemContainerDefaultSerialization() { } + virtual bool Serialize(MemoryBuffer &buf, const int container_number, const std::map& items); + }; +} // EQEmu + +#endif diff --git a/common/item_container_personal_serialization.cpp b/common/item_container_personal_serialization.cpp new file mode 100644 index 000000000..61e877836 --- /dev/null +++ b/common/item_container_personal_serialization.cpp @@ -0,0 +1,21 @@ +#include "item_container_personal_serialization.h" + +bool EQEmu::ItemContainerPersonalSerialization::Serialize(MemoryBuffer &buf, const int container_number, const std::map& items) { + if(items.size() == 0) { + return false; + } + + bool ret = false; + for(auto &iter : items) { + if(iter.first < 33) { + buf.Write(container_number); + buf.Write(iter.first); + buf.Write(-1); + buf.Write(-1); + buf.Write(iter.second.get()); + ret = true; + } + } + + return ret; +} diff --git a/common/item_container_personal_serialization.h b/common/item_container_personal_serialization.h new file mode 100644 index 000000000..46ebe97ed --- /dev/null +++ b/common/item_container_personal_serialization.h @@ -0,0 +1,35 @@ +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY except by those people which sell it, which +are required to give you total support for your newly bought product; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_ITEM_CONTAINER_PERSONAL_SERIALIZATION_H +#define COMMON_ITEM_CONTAINER_PERSONAL_SERIALIZATION_H + +#include "item_container_serialization_strategy.h" + +namespace EQEmu +{ + class ItemContainerPersonalSerialization : public ItemContainerSerializationStrategy + { + public: + ItemContainerPersonalSerialization() { } + virtual ~ItemContainerPersonalSerialization() { } + virtual bool Serialize(MemoryBuffer &buf, const int container_number, const std::map& items); + }; +} // EQEmu + +#endif diff --git a/common/item_container_serialization_strategy.h b/common/item_container_serialization_strategy.h new file mode 100644 index 000000000..b9415915c --- /dev/null +++ b/common/item_container_serialization_strategy.h @@ -0,0 +1,37 @@ +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY except by those people which sell it, which +are required to give you total support for your newly bought product; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_ITEM_CONTAINER_SERIALIZATION_STRATEGY_H +#define COMMON_ITEM_CONTAINER_SERIALIZATION_STRATEGY_H + +#include "item_container.h" +#include "memory_buffer.h" +#include + +namespace EQEmu +{ + class ItemContainerSerializationStrategy + { + public: + ItemContainerSerializationStrategy() { } + virtual ~ItemContainerSerializationStrategy() { } + virtual bool Serialize(MemoryBuffer &buf, const int container_number, const std::map& items) = 0; + }; +} // EQEmu + +#endif diff --git a/common/item_struct.h b/common/item_data.h similarity index 94% rename from common/item_struct.h rename to common/item_data.h index 1fcb49f51..fbfdba93b 100644 --- a/common/item_struct.h +++ b/common/item_data.h @@ -16,8 +16,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA */ -#ifndef ITEM_STRUCT_H -#define ITEM_STRUCT_H +#ifndef COMMON_ITEM_DATA_H +#define COMMON_ITEM_DATA_H /* * Note: (Doodman) @@ -35,7 +35,7 @@ * * Note #3: (Doodman) * Please take care when adding new found data fields to add them - * to the appropriate structure. Item_Struct has elements that are + * to the appropriate structure. ItemData has elements that are * global to all types of items only. * * Note #4: (Doodman) @@ -46,7 +46,7 @@ #include "eq_dictionary.h" /* -** Child struct of Item_Struct: +** Child struct of ItemData: ** Effect data: Click, Proc, Focus, Worn, Scroll ** */ @@ -69,10 +69,18 @@ struct InternalSerializedItem_Struct { const void * inst; }; +struct SerializedItemInstance_Struct { + int32 container_id; + int32 slot_id; + int32 bag_id; + int32 aug_id; + void *inst; +}; + // use EmuConstants::ITEM_COMMON_SIZE //#define MAX_AUGMENT_SLOTS 5 -struct Item_Struct { +struct ItemData { bool IsEquipable(uint16 Race, uint16 Class) const; // Non packet based fields uint8 MinStatus; @@ -99,17 +107,10 @@ struct Item_Struct { uint32 Favor; // Individual favor uint32 GuildFavor; // Guild favor uint32 PointType; - - //uint32 Unk117; - //uint32 Unk118; - //uint32 Unk121; - //uint32 Unk124; - uint8 BagType; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types - uint8 BagSlots; // Number of slots: can only be 2, 4, 6, 8, or 10 + uint8 BagSlots; // Number of slots uint8 BagSize; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT uint8 BagWR; // 0->100 - bool BenefitFlag; bool Tradeskills; // Is this a tradeskill item? int8 CR; // Save vs Cold @@ -128,7 +129,6 @@ struct Item_Struct { int32 Mana; // Mana int32 AC; // AC uint32 Deity; // Bitmask of Deities that can equip this item - //uint32 Unk033 int32 SkillModValue; // % Mod to skill specified in SkillModType uint32 SkillModType; // Type of skill for SkillModValue to apply to uint32 BaneDmgRace; // Bane Damage Race @@ -150,13 +150,11 @@ struct Item_Struct { uint32 Color; // RR GG BB 00 <-- as it appears in pc uint32 Classes; // Bitfield of classes that can equip item (1 << class#) uint32 Races; // Bitfield of races that can equip item (1 << race#) - //uint32 Unk054; int16 MaxCharges; // Maximum charges items can hold: -1 if not a chargeable item uint8 ItemType; // Item Type/Skill (itemClass* from above) uint8 Material; // Item material type uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?) float SellRate; // Sell rate - //uint32 Unk059; union { uint32 Fulfilment; // Food fulfilment (How long it lasts) int16 CastTime; // Cast Time for clicky effects, in milliseconds @@ -211,7 +209,6 @@ struct Item_Struct { int16 StackSize; uint8 PotionBeltSlots; ItemEffect_Struct Click, Proc, Worn, Focus, Scroll, Bard; - uint8 Book; // 0=Not book, 1=Book uint32 BookType; char Filename[33]; // Filename for book data @@ -240,11 +237,11 @@ struct Item_Struct { uint32 ScriptFileID; uint16 ExpendableArrow; uint32 Clairvoyance; - char ClickName[65]; - char ProcName[65]; - char WornName[65]; - char FocusName[65]; - char ScrollName[65]; + char ClickName[65]; + char ProcName[65]; + char WornName[65]; + char FocusName[65]; + char ScrollName[65]; }; diff --git a/common/item_instance.cpp b/common/item_instance.cpp new file mode 100644 index 000000000..3e59d5f6b --- /dev/null +++ b/common/item_instance.cpp @@ -0,0 +1,389 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "item_instance.h" +#include "data_verification.h" +#include "item_container.h" + +uint32 ItemInstanceSerial = 1; +uint32 EQEmu::GetNextItemInstanceSerial() { + ItemInstanceSerial++; + return ItemInstanceSerial; +} + +struct EQEmu::ItemInstance::impl { + const ItemData *base_item_; + ItemData *modified_item_; + int16 charges_; + uint32 color_; + bool attuned_; + std::string custom_data_; + uint32 ornament_idfile_; + uint32 ornament_icon_; + uint32 ornament_hero_model_; + char tracking_id_[17]; + uint32 serial_id_; + uint32 recast_timestamp_; + uint32 merchant_slot_; + uint32 merchant_count_; + uint32 price_; + ItemContainer contents_; +}; + +EQEmu::ItemInstance::ItemInstance(const ItemData* idata) { + impl_ = new impl; + impl_->base_item_ = idata; + impl_->modified_item_ = nullptr; + impl_->charges_ = -1; + impl_->color_ = 0; + impl_->attuned_ = false; + impl_->ornament_idfile_ = 0; + impl_->ornament_icon_ = 0; + impl_->ornament_hero_model_ = 0; + impl_->serial_id_ = 0; + impl_->recast_timestamp_ = 0; + impl_->merchant_slot_ = 0; + impl_->merchant_count_ = 0; + impl_->price_ = 0; + memset(impl_->tracking_id_, 0, 17); +} + +EQEmu::ItemInstance::ItemInstance(const ItemData* idata, int16 charges) { + impl_ = new impl; + impl_->base_item_ = idata; + impl_->modified_item_ = nullptr; + impl_->charges_ = charges; + impl_->color_ = 0; + impl_->attuned_ = false; + impl_->ornament_idfile_ = 0; + impl_->ornament_icon_ = 0; + impl_->ornament_hero_model_ = 0; + impl_->recast_timestamp_ = 0; + impl_->serial_id_ = 0; + impl_->merchant_slot_ = 0; + impl_->merchant_count_ = 0; + impl_->price_ = 0; + memset(impl_->tracking_id_, 0, 17); +} + +EQEmu::ItemInstance::~ItemInstance() { + delete impl_; +} + + +EQEmu::ItemInstance::pointer EQEmu::ItemInstance::Split(int charges) { + if(!IsStackable()) { + //Can't split non stackable items! + return pointer(nullptr); + } + + if(charges >= GetCharges()) { + return pointer(nullptr); + } + + if(impl_->contents_.Size() > 0) { + return pointer(nullptr); + } + + pointer split = pointer(new EQEmu::ItemInstance(impl_->base_item_, charges)); + split->SetSerialNumber(EQEmu::GetNextItemInstanceSerial()); + //Set Tracking here + split->impl_->attuned_ = impl_->attuned_; + split->impl_->custom_data_ = impl_->custom_data_; + split->impl_->recast_timestamp_ = impl_->recast_timestamp_; + split->impl_->price_ = impl_->price_; + split->impl_->color_ = impl_->color_; + split->impl_->merchant_count_ = impl_->merchant_count_; + split->impl_->merchant_slot_ = impl_->merchant_slot_; + split->impl_->ornament_hero_model_ = impl_->ornament_hero_model_; + split->impl_->ornament_icon_ = impl_->ornament_icon_; + split->impl_->ornament_idfile_ = impl_->ornament_idfile_; + + SetCharges(GetCharges() - charges); + return split; +} + +const ItemData *EQEmu::ItemInstance::GetItem() { + return impl_->modified_item_ ? impl_->modified_item_ : impl_->base_item_; +} + +const ItemData *EQEmu::ItemInstance::GetBaseItem() { + return impl_->base_item_; +} + +const ItemData *EQEmu::ItemInstance::GetBaseItem() const { + return impl_->base_item_; +} + +EQEmu::ItemInstance::pointer EQEmu::ItemInstance::Get(const int index) { + if(EQEmu::ValueWithin(index, 0, 255)) { + return impl_->contents_.Get(index); + } + + return pointer(nullptr); +} + +bool EQEmu::ItemInstance::Put(const int index, pointer &inst) { + if(!impl_->base_item_) { + return false; + } + + auto item = impl_->base_item_; + if(item->ItemClass == ItemClassContainer) { // Bag + if(!EQEmu::ValueWithin(index, 0, item->BagSlots)) { + return false; + } + + return impl_->contents_.Put(index, inst); + } + else if(item->ItemClass == ItemClassCommon) { // Augment + if(!EQEmu::ValueWithin(index, 0, EmuConstants::ITEM_COMMON_SIZE)) { + return false; + } + + if(!item->AugSlotVisible[index]) { + return false; + } + + if(inst) { + auto *aug_item = inst->GetItem(); + int aug_type = aug_item->AugType; + if(aug_type == -1 || (1 << (item->AugSlotType[index] - 1)) & aug_type) { + return impl_->contents_.Put(index, inst); + } + } else { + return impl_->contents_.Put(index, inst); + } + + return false; + } + + return false; +} + +int16 EQEmu::ItemInstance::GetCharges() { + return impl_->charges_; +} + +int16 EQEmu::ItemInstance::GetCharges() const { + return impl_->charges_; +} + +void EQEmu::ItemInstance::SetCharges(const int16 charges) { + impl_->charges_ = charges; +} + +uint32 EQEmu::ItemInstance::GetColor() { + return impl_->color_; +} + +uint32 EQEmu::ItemInstance::GetColor() const { + return impl_->color_; +} + +void EQEmu::ItemInstance::SetColor(const uint32 color) { + impl_->color_ = color; +} + +bool EQEmu::ItemInstance::GetAttuned() { + return impl_->attuned_; +} + +bool EQEmu::ItemInstance::GetAttuned() const { + return impl_->attuned_; +} + +void EQEmu::ItemInstance::SetAttuned(const bool attuned) { + impl_->attuned_ = attuned; +} + +std::string EQEmu::ItemInstance::GetCustomData() { + return impl_->custom_data_; +} + +std::string EQEmu::ItemInstance::GetCustomData() const { + return impl_->custom_data_; +} + +void EQEmu::ItemInstance::SetCustomData(const std::string &custom_data) { + //We need to actually set the custom data stuff based on this string + 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() { + return impl_->ornament_hero_model_; +} + +uint32 EQEmu::ItemInstance::GetOrnamentHeroModel() const { + return impl_->ornament_hero_model_; +} + +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; +} + +const char* EQEmu::ItemInstance::GetTrackingID() { + return impl_->tracking_id_; +} + +const char* EQEmu::ItemInstance::GetTrackingID() const { + return impl_->tracking_id_; +} + +void EQEmu::ItemInstance::SetTrackingID(const char *tracking_id) { + size_t len = strlen(tracking_id); + if(len > 16) { + return; + } + + strncpy(impl_->tracking_id_, tracking_id, 16); +} + +uint32 EQEmu::ItemInstance::GetRecastTimestamp() { + return impl_->recast_timestamp_; +} + +uint32 EQEmu::ItemInstance::GetRecastTimestamp() const { + return impl_->recast_timestamp_; +} + +void EQEmu::ItemInstance::SetRecastTimestamp(const uint32 recast_timestamp) { + impl_->recast_timestamp_ = recast_timestamp; +} + +uint32 EQEmu::ItemInstance::GetMerchantSlot() { + return impl_->merchant_slot_; +} + +uint32 EQEmu::ItemInstance::GetMerchantSlot() const { + return impl_->merchant_slot_; +} + +void EQEmu::ItemInstance::SetMerchantSlot(uint32 slot) { + impl_->merchant_slot_ = slot; +} + +uint32 EQEmu::ItemInstance::GetMerchantCount() { + return impl_->merchant_count_; +} + +uint32 EQEmu::ItemInstance::GetMerchantCount() const { + return impl_->merchant_count_; +} + +void EQEmu::ItemInstance::SetMerchantCount(const uint32 cnt) { + impl_->merchant_count_ = cnt; +} + +uint32 EQEmu::ItemInstance::GetPrice() { + return impl_->price_; +} + +uint32 EQEmu::ItemInstance::GetPrice() const { + return impl_->price_; +} + +void EQEmu::ItemInstance::SetPrice(const uint32 p) { + impl_->price_ = p; +} + +uint32 EQEmu::ItemInstance::GetSerialNumber() { + return impl_->serial_id_; +} + +uint32 EQEmu::ItemInstance::GetSerialNumber() const { + return impl_->serial_id_; +} + +void EQEmu::ItemInstance::SetSerialNumber(const uint32 sn) { + impl_->serial_id_ = sn; +} + +bool EQEmu::ItemInstance::IsStackable() { + return impl_->base_item_->Stackable; +} + +bool EQEmu::ItemInstance::IsStackable() const { + return impl_->base_item_->Stackable; +} + +bool EQEmu::ItemInstance::IsNoDrop() { + return GetAttuned() || GetBaseItem()->NoDrop == 0; +} + +bool EQEmu::ItemInstance::IsNoDrop() const { + return GetAttuned() || GetBaseItem()->NoDrop == 0; +} + +EQEmu::ItemContainer *EQEmu::ItemInstance::GetContainer() { + return &(impl_->contents_); +} + +void EQEmu::ItemInstance::Interrogate(int level) { + impl_->contents_.Interrogate(level); +} diff --git a/common/item_instance.h b/common/item_instance.h new file mode 100644 index 000000000..08b6d14af --- /dev/null +++ b/common/item_instance.h @@ -0,0 +1,126 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_ITEM_INSTANCE_H +#define COMMON_ITEM_INSTANCE_H + +#include "item_data.h" +#include + +namespace EQEmu +{ + uint32 GetNextItemInstanceSerial(); + + class ItemContainer; + class ItemInstance + { + public: + typedef std::shared_ptr pointer; + ItemInstance(const ItemData* idata); + ItemInstance(const ItemData* idata, const int16 charges); + ~ItemInstance(); + + const ItemData *GetItem(); + const ItemData *GetBaseItem(); + const ItemData *GetBaseItem() const; + + pointer Split(int charges); + + //Container + pointer Get(const int index); + bool Put(const int index, pointer &inst); + + //Persistent State + int16 GetCharges(); + int16 GetCharges() const; + void SetCharges(const int16 charges); + + uint32 GetColor(); + uint32 GetColor() const; + void SetColor(const uint32 color); + + bool GetAttuned(); + bool GetAttuned() const; + void SetAttuned(const bool attuned); + + std::string GetCustomData(); + std::string GetCustomData() const; + 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(); + uint32 GetOrnamentHeroModel() const; + uint32 GetOrnamentHeroModel(int material_slot); + uint32 GetOrnamentHeroModel(int material_slot) const; + void SetOrnamentHeroModel(const uint32 ornament_hero_model); + + const char* GetTrackingID(); + const char* GetTrackingID() const; + void SetTrackingID(const char *tracking_id); + + uint32 GetRecastTimestamp(); + uint32 GetRecastTimestamp() const; + void SetRecastTimestamp(const uint32 recast_timestamp); + + //Merchant + uint32 GetMerchantSlot(); + uint32 GetMerchantSlot() const; + void SetMerchantSlot(const uint32 slot); + + uint32 GetMerchantCount(); + uint32 GetMerchantCount() const; + void SetMerchantCount(const uint32 cnt); + + uint32 GetPrice(); + uint32 GetPrice() const; + void SetPrice(const uint32 p); + + //Serial Number + uint32 GetSerialNumber(); + uint32 GetSerialNumber() const; + void SetSerialNumber(uint32 sn); + + //Basic Stats + bool IsStackable(); + bool IsStackable() const; + + bool IsNoDrop(); + bool IsNoDrop() const; + + void CheckStackRemaining(pointer &insert, int &charges); + + //Internal state + //Used for low level operations such as encode/decode + ItemContainer *GetContainer(); + + void Interrogate(int level); + private: + struct impl; + impl *impl_; + }; + +} // EQEmu + +#endif diff --git a/common/memory_buffer.cpp b/common/memory_buffer.cpp new file mode 100644 index 000000000..c762a1118 --- /dev/null +++ b/common/memory_buffer.cpp @@ -0,0 +1,212 @@ +#include "memory_buffer.h" + +EQEmu::MemoryBuffer::MemoryBuffer() { + buffer_ = nullptr; + size_ = 0; + capacity_ = 0; + read_pos_ = 0; + write_pos_ = 0; +} + +EQEmu::MemoryBuffer::MemoryBuffer(size_t sz) { + buffer_ = nullptr; + size_ = 0; + capacity_ = 0; + read_pos_ = 0; + write_pos_ = 0; + Resize(sz); +} + +EQEmu::MemoryBuffer::MemoryBuffer(const MemoryBuffer &other) { + if(other.capacity_) { + buffer_ = new uchar[other.capacity_]; + memcpy(buffer_, other.buffer_, other.capacity_); + } else { + buffer_ = nullptr; + } + + size_ = other.size_; + capacity_ = other.capacity_; + write_pos_ = other.write_pos_; + read_pos_ = other.read_pos_; +} + +EQEmu::MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) { + 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(this == &other) { + return *this; + } + + if(buffer_) { + delete[] buffer_; + } + + if(other.capacity_) { + buffer_ = new uchar[other.capacity_]; + memcpy(buffer_, other.buffer_, other.capacity_); + } + else { + buffer_ = nullptr; + } + + size_ = other.size_; + capacity_ = other.capacity_; + write_pos_ = other.write_pos_; + read_pos_ = other.read_pos_; + return *this; +} + +EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(MemoryBuffer &&other) { + 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; +} + +EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator+=(const MemoryBuffer &rhs) { + if(!rhs.buffer_) { + return *this; + } + + if(buffer_) { + size_t old_size = size_; + Resize(size_ + rhs.size_); + memcpy(&buffer_[old_size], rhs.buffer_, rhs.size_); + } else { + buffer_ = new uchar[rhs.capacity_]; + memcpy(buffer_, rhs.buffer_, rhs.capacity_); + size_ = rhs.size_; + capacity_ = rhs.capacity_; + } + + return *this; +} + +EQEmu::MemoryBuffer::~MemoryBuffer() { Clear(); } + +uchar& EQEmu::MemoryBuffer::operator[](size_t pos) { + return buffer_[pos]; +} + +const uchar& EQEmu::MemoryBuffer::operator[](size_t pos) const { + return buffer_[pos]; +} + +bool EQEmu::MemoryBuffer::Empty() { + return size_ == 0; +} + +bool EQEmu::MemoryBuffer::Empty() const { + return size_ == 0; +} + +size_t EQEmu::MemoryBuffer::Size() { + return size_; +} + +size_t EQEmu::MemoryBuffer::Size() const { + return size_; +} + +size_t EQEmu::MemoryBuffer::Capacity() { + return capacity_; +} + +size_t EQEmu::MemoryBuffer::Capacity() const { + return capacity_; +} + +void EQEmu::MemoryBuffer::Resize(size_t sz) { + if(!buffer_) { + size_t new_size = sz + 64; + buffer_ = new uchar[new_size]; + capacity_ = new_size; + size_ = sz; + memset(buffer_, 0, capacity_); + return; + } + + if(sz > capacity_) { + size_t new_size = sz + 32; + uchar *temp = new uchar[new_size]; + memcpy(temp, buffer_, capacity_); + delete[] buffer_; + buffer_ = temp; + + capacity_ = new_size; + size_ = sz; + } + else { + size_ = sz; + } +} + +void EQEmu::MemoryBuffer::Clear() { + if(buffer_) { + delete[] buffer_; + buffer_ = nullptr; + } + + size_ = 0; + capacity_ = 0; + write_pos_ = 0; + read_pos_ = 0; +} + +void EQEmu::MemoryBuffer::Zero() { + if(buffer_) { + memset(buffer_, 0, capacity_); + } +} + +void EQEmu::MemoryBuffer::Write(const char *val, size_t len) { + size_t size_needed = write_pos_ + len; + Resize(size_needed); + + memcpy(&buffer_[write_pos_], val, len); + write_pos_ += len; +} + +void EQEmu::MemoryBuffer::Read(uchar *buf, size_t len) { + memcpy(buf, &buffer_[read_pos_], len); + read_pos_ += len; +} + +void EQEmu::MemoryBuffer::Read(char *str) { + size_t len = strlen((const char*)&buffer_[read_pos_]); + memcpy(str, &buffer_[read_pos_], len); + read_pos_ += len; +} diff --git a/common/memory_buffer.h b/common/memory_buffer.h new file mode 100644 index 000000000..689ed81bd --- /dev/null +++ b/common/memory_buffer.h @@ -0,0 +1,124 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_MEMORY_BUFFER_H +#define COMMON_MEMORY_BUFFER_H + +#include "types.h" +#include +#include +#include + +namespace EQEmu +{ + class MemoryBuffer + { + public: + MemoryBuffer(); + MemoryBuffer(size_t sz); + MemoryBuffer(const MemoryBuffer &other); + MemoryBuffer(MemoryBuffer &&other); + MemoryBuffer& operator=(const MemoryBuffer &other); + MemoryBuffer& operator=(MemoryBuffer &&other); + MemoryBuffer& operator+=(const MemoryBuffer &rhs); + friend MemoryBuffer operator+(MemoryBuffer lhs, const MemoryBuffer& rhs) { return lhs += rhs; } + ~MemoryBuffer(); + + uchar& operator[](size_t pos); + const uchar& operator[](size_t pos) const; + + template + operator T*() { + return reinterpret_cast(buffer_); + } + + template + operator T*() const { + return reinterpret_cast(buffer_); + } + + operator bool() { return buffer_ != nullptr; } + operator bool() const { return buffer_ != nullptr; } + + bool Empty(); + bool Empty() const; + size_t Size(); + size_t Size() const; + size_t Capacity(); + size_t Capacity() const; + + void Resize(size_t sz); + void Clear(); + void Zero(); + + template + void Write(T val) { + static_assert(std::is_pod::value, "MemoryBuffer::Write(T val) only works on pod and string types."); + Write((const char*)&val, sizeof(T)); + } + + template + T Read() { + static_assert(std::is_pod::value, "MemoryBuffer::Read() only works on pod and string types."); + T temp; + Read((uchar*)&temp, sizeof(T)); + return temp; + } + + void Write(const std::string &val) { + Write(val.c_str(), val.length()); + Write((uint8)0); + } + + void Write(const char *val) { + size_t len = strlen(val); + Write(val, len); + Write((uint8)0); + } + + std::string ReadString() { + std::string ret; + size_t len = strlen((const char*)&buffer_[read_pos_]); + ret.resize(len); + memcpy(&ret[0], &buffer_[read_pos_], len); + read_pos_ += len + 1; + return ret; + } + + void Write(const char *val, size_t len); + void Read(uchar *buf, size_t len); + void Read(char *str); + + inline size_t GetWritePosition() { return write_pos_; } + inline void SetWritePosition(size_t wp) { write_pos_ = wp; } + inline void WriteSkipBytes(size_t skip) { write_pos_ += skip; } + inline size_t GetReadPosition() { return read_pos_; } + inline void SetReadPosition(size_t wp) { read_pos_ = wp; } + inline void ReadSkipBytes(size_t skip) { read_pos_ += skip; } + + private: + uchar *buffer_; + size_t size_; + size_t capacity_; + size_t write_pos_; + size_t read_pos_; + }; + +} // EQEmu + +#endif diff --git a/common/patches/patches.cpp b/common/patches/patches.cpp index 3147b89f6..37ff776bc 100644 --- a/common/patches/patches.cpp +++ b/common/patches/patches.cpp @@ -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(); } diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 8080bfce1..2f515bcf0 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -532,71 +532,72 @@ namespace RoF { //consume the packet EQApplicationPacket *in = *p; + delete in; - *p = nullptr; - - if (in->size == 0) { - - in->size = 4; - in->pBuffer = new uchar[in->size]; - - *((uint32 *)in->pBuffer) = 0; - - dest->FastQueuePacket(&in, ack_req); - return; - } - - //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - - int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); - - if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { - - Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", - opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); - - delete in; - - return; - } - - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; - - in->pBuffer = new uchar[4]; - *(uint32 *)in->pBuffer = ItemCount; - in->size = 4; - - for (int r = 0; r < ItemCount; r++, eq++) { - - uint32 Length = 0; - - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); - - if (Serialized) { - - uchar *OldBuffer = in->pBuffer; - in->pBuffer = new uchar[in->size + Length]; - memcpy(in->pBuffer, OldBuffer, in->size); - - safe_delete_array(OldBuffer); - - memcpy(in->pBuffer + in->size, Serialized, Length); - in->size += Length; - - safe_delete_array(Serialized); - } - else { - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - } - } - - delete[] __emu_buffer; - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); - //Log.Hex(Logs::Netcode, in->pBuffer, in->size); - - dest->FastQueuePacket(&in, ack_req); + //*p = nullptr; + // + //if (in->size == 0) { + // + // in->size = 4; + // in->pBuffer = new uchar[in->size]; + // + // *((uint32 *)in->pBuffer) = 0; + // + // dest->FastQueuePacket(&in, ack_req); + // return; + //} + // + ////store away the emu struct + //unsigned char *__emu_buffer = in->pBuffer; + // + //int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); + // + //if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + // + // Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", + // opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); + // + // delete in; + // + // return; + //} + // + //InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + // + //in->pBuffer = new uchar[4]; + //*(uint32 *)in->pBuffer = ItemCount; + //in->size = 4; + // + //for (int r = 0; r < ItemCount; r++, eq++) { + // + // uint32 Length = 0; + // + // char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); + // + // if (Serialized) { + // + // uchar *OldBuffer = in->pBuffer; + // in->pBuffer = new uchar[in->size + Length]; + // memcpy(in->pBuffer, OldBuffer, in->size); + // + // safe_delete_array(OldBuffer); + // + // memcpy(in->pBuffer + in->size, Serialized, Length); + // in->size += Length; + // + // safe_delete_array(Serialized); + // } + // else { + // Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); + // } + //} + // + //delete[] __emu_buffer; + // + ////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); + ////Log.Hex(Logs::Netcode, in->pBuffer, in->size); + // + //dest->FastQueuePacket(&in, ack_req); } ENCODE(OP_ClickObjectAction) @@ -1708,14 +1709,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); } @@ -3065,13 +3066,13 @@ namespace RoF { ENCODE_LENGTH_EXACT(Merchant_Sell_Struct); SETUP_DIRECT_ENCODE(Merchant_Sell_Struct, structs::Merchant_Sell_Struct); - + OUT(npcid); OUT(playerid); OUT(itemslot); OUT(quantity); OUT(price); - + FINISH_ENCODE(); } @@ -4703,16 +4704,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) @@ -4840,13 +4841,13 @@ namespace RoF { DECODE_LENGTH_EXACT(structs::Merchant_Sell_Struct); SETUP_DIRECT_DECODE(Merchant_Sell_Struct, structs::Merchant_Sell_Struct); - + IN(npcid); IN(playerid); IN(itemslot); IN(quantity); IN(price); - + FINISH_DIRECT_DECODE(); } @@ -5043,7 +5044,7 @@ namespace RoF std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - const Item_Struct *item = inst->GetUnscaledItem(); + const ItemData *item = inst->GetUnscaledItem(); //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name); RoF::structs::ItemSerializationHeader hdr; @@ -5102,7 +5103,7 @@ namespace RoF ss.write(tmp, strlen(tmp)); ss.write((const char*)&null_term, sizeof(uint8)); ornaIcon = inst->GetOrnamentationIcon(); - heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in)); + heroModel = inst->GetOrnamentHeroModel(InventoryOld::CalcMaterialFromSlot(slot_id_in)); } else { @@ -5545,7 +5546,7 @@ namespace RoF /* // TEST CODE: - SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); + SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x); */ SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 68ff8bf44..9dd4bdee5 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -12,6 +12,8 @@ #include "../item.h" #include "rof2_structs.h" #include "../rulesys.h" +#include "../memory_buffer.h" +#include "../inventory.h" #include #include @@ -24,7 +26,7 @@ namespace RoF2 static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth, ItemPacketType packet_type); + void SerializeItem(EQEmu::MemoryBuffer &packet_data, EQEmu::ItemInstance *inst, int container_id, int slot_id, int bag_id, int aug_id); // server to client inventory location converters static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType = ItemPacketInvalid); @@ -603,70 +605,39 @@ namespace RoF2 { //consume the packet EQApplicationPacket *in = *p; - *p = nullptr; - if (in->size == 0) { - - in->size = 4; - in->pBuffer = new uchar[in->size]; - - *((uint32 *)in->pBuffer) = 0; - - dest->FastQueuePacket(&in, ack_req); - return; - } - - //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - - int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); - - if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + size_t entry_size = sizeof(SerializedItemInstance_Struct); + size_t entries = (in->size - sizeof(int32)) / entry_size; + if(entries == 0 || (in->size - sizeof(int32)) % entry_size != 0) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", - opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); - + opcodes->EmuToName(in->GetOpcode()), (in->size - sizeof(int32)), entry_size); delete in; - return; } - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + unsigned char *__emu_buffer = in->pBuffer; + SerializedItemInstance_Struct *sis = (SerializedItemInstance_Struct*)(__emu_buffer + sizeof(int32)); + EQEmu::MemoryBuffer packet_data; + packet_data.Write(entries); + + for(size_t i = 0; i < entries; ++i) { + EQEmu::ItemInstance *inst = (EQEmu::ItemInstance*)sis[i].inst; - in->pBuffer = new uchar[4]; - *(uint32 *)in->pBuffer = ItemCount; - in->size = 4; - - for (int r = 0; r < ItemCount; r++, eq++) { - - uint32 Length = 0; - - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0, ItemPacketCharInventory); - - if (Serialized) { - - uchar *OldBuffer = in->pBuffer; - in->pBuffer = new uchar[in->size + Length]; - memcpy(in->pBuffer, OldBuffer, in->size); - - safe_delete_array(OldBuffer); - - memcpy(in->pBuffer + in->size, Serialized, Length); - in->size += Length; - - safe_delete_array(Serialized); - } - else { - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); + if(!inst) { + continue; } + + SerializeItem(packet_data, inst, sis[i].container_id, sis[i].slot_id, -1, -1); } + in->pBuffer = new uchar[packet_data.Size()]; + in->size = packet_data.Size(); + memcpy(in->pBuffer, packet_data, in->size); + + delete[] __emu_buffer; - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); - //Log.Hex(Logs::Netcode, in->pBuffer, in->size); - dest->FastQueuePacket(&in, ack_req); } @@ -1526,30 +1497,40 @@ namespace RoF2 ENCODE(OP_ItemPacket) { - //consume the packet EQApplicationPacket *in = *p; *p = nullptr; - unsigned char *__emu_buffer = in->pBuffer; - ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer; - InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem); + size_t entry_size = sizeof(SerializedItemInstance_Struct); + size_t entries = (in->size - sizeof(int32)) / entry_size; - uint32 length; - char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0, old_item_pkt->PacketType); - - if (!serialized) { - Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); + if(entries == 0 || entries > 1 || (in->size - sizeof(int32)) % entry_size != 0) { + Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", + opcodes->EmuToName(in->GetOpcode()), (in->size - sizeof(int32)), entry_size); delete in; return; } - in->size = length + 4; - in->pBuffer = new unsigned char[in->size]; - ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer; - new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(new_item_pkt->SerializedItem, serialized, length); + + unsigned char *__emu_buffer = in->pBuffer; + + int32 *packet_type = (int32*)(__emu_buffer); + SerializedItemInstance_Struct *sis = (SerializedItemInstance_Struct*)(__emu_buffer + sizeof(int32)); + EQEmu::MemoryBuffer packet_data; + packet_data.Write(*packet_type); + + EQEmu::ItemInstance *inst = (EQEmu::ItemInstance*)sis->inst; + if(!inst) { + delete in; + return; + } + + SerializeItem(packet_data, inst, sis->container_id, sis->slot_id, sis->bag_id, sis->slot_id); + + in->pBuffer = new uchar[packet_data.Size()]; + in->size = packet_data.Size(); + memcpy(in->pBuffer, packet_data, in->size); + delete[] __emu_buffer; - safe_delete_array(serialized); dest->FastQueuePacket(&in, ack_req); } @@ -1782,9 +1763,15 @@ namespace RoF2 ENCODE_LENGTH_EXACT(MoveItem_Struct); SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - eq->from_slot = ServerToRoF2Slot(emu->from_slot); - eq->to_slot = ServerToRoF2Slot(emu->to_slot); - OUT(number_in_stack); + eq->from_slot.SlotType = emu->from_type; + eq->from_slot.MainSlot = emu->from_slot; + eq->from_slot.SubSlot = emu->from_bag_slot; + eq->from_slot.AugSlot = emu->from_aug_slot; + eq->to_slot.SlotType = emu->to_type; + eq->to_slot.MainSlot = emu->to_slot; + eq->to_slot.SubSlot = emu->to_bag_slot; + eq->to_slot.AugSlot = emu->to_aug_slot; + eq->number_in_stack = emu->number_in_stack; FINISH_ENCODE(); } @@ -4854,11 +4841,16 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - Log.Out(Logs::General, Logs::Netcode, "[RoF2] 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 = RoF2ToServerSlot(eq->from_slot); - emu->to_slot = RoF2ToServerSlot(eq->to_slot); - IN(number_in_stack); - + emu->from_type = eq->from_slot.SlotType; + emu->from_slot = eq->from_slot.MainSlot; + emu->from_bag_slot = eq->from_slot.SubSlot; + emu->from_aug_slot = eq->from_slot.AugSlot; + emu->to_type = eq->to_slot.SlotType; + emu->to_slot = eq->to_slot.MainSlot; + emu->to_bag_slot = eq->to_slot.SubSlot; + emu->to_aug_slot = eq->to_slot.AugSlot; + emu->number_in_stack = eq->number_in_stack; + FINISH_DIRECT_DECODE(); } @@ -5233,51 +5225,43 @@ namespace RoF2 return NextItemInstSerialNumber; } - char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth, ItemPacketType packet_type) - { - int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); + void SerializeItem(EQEmu::MemoryBuffer &packet_data, EQEmu::ItemInstance *inst, int container_id, int slot_id, int bag_id, int aug_id) { + int ornamentation_augtype = RuleI(Character, OrnamentationAugmentType); uint8 null_term = 0; bool stackable = inst->IsStackable(); uint32 merchant_slot = inst->GetMerchantSlot(); uint32 charges = inst->GetCharges(); - if (!stackable && charges > 254) - charges = 0xFFFFFFFF; - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - - const Item_Struct *item = inst->GetUnscaledItem(); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name); + const ItemData *item = inst->GetBaseItem(); RoF2::structs::ItemSerializationHeader hdr; - //sprintf(hdr.unknown000, "06e0002Y1W00"); - - snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%016d", item->ID); + snprintf(hdr.tracking_id, sizeof(hdr.tracking_id), "%016d", inst->GetSerialNumber()); hdr.stacksize = stackable ? charges : 1; hdr.unknown004 = 0; - structs::ItemSlotStruct slot_id = ServerToRoF2Slot(slot_id_in, packet_type); + hdr.slot_type = (merchant_slot == 0) ? container_id : 9; // 9 is merchant 20 is reclaim items? + hdr.main_slot = (merchant_slot == 0) ? slot_id : merchant_slot; + hdr.sub_slot = (merchant_slot == 0) ? bag_id : 0xffff; + hdr.aug_slot = (merchant_slot == 0) ? aug_id : 0xffff; - hdr.slot_type = (merchant_slot == 0) ? slot_id.SlotType : 9; // 9 is merchant 20 is reclaim items? - hdr.main_slot = (merchant_slot == 0) ? slot_id.MainSlot : merchant_slot; - hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubSlot : 0xffff; - hdr.aug_slot = (merchant_slot == 0) ? slot_id.AugSlot : 0xffff; hdr.price = inst->GetPrice(); hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); - hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; + //hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; + hdr.scaled_value = 0; + hdr.instance_id = (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot; hdr.unknown028 = 0; hdr.last_cast_time = inst->GetRecastTimestamp(); hdr.charges = (stackable ? (item->MaxCharges ? 1 : 0) : charges); - hdr.inst_nodrop = inst->IsAttuned() ? 1 : 0; + hdr.inst_nodrop = inst->GetAttuned() ? 1 : 0; hdr.unknown044 = 0; hdr.unknown048 = 0; hdr.unknown052 = 0; hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0; - ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); + packet_data.Write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); - if (item->EvolvingLevel > 0) { + if(item->EvolvingLevel > 0) { RoF2::structs::EvolvingItem evotop; evotop.unknown001 = 0; evotop.unknown002 = 0; @@ -5287,74 +5271,75 @@ namespace RoF2 evotop.progress = 95.512; evotop.Activated = 1; evotop.evomaxlevel = 7; - ss.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); + packet_data.Write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); } - //ORNAMENT IDFILE / ICON - uint32 ornaIcon = 0; - uint32 heroModel = 0; - if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) + uint32 orn_icon = 0; + uint32 hero_model = 0; + + if(inst->GetOrnamentIDFile() && inst->GetOrnamentIcon()) { - char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); + char tmp[30] = { 0 }; + sprintf(tmp, "IT%d", inst->GetOrnamentIDFile()); //Mainhand - ss.write(tmp, strlen(tmp)); - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write(tmp, strlen(tmp)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); //Offhand - ss.write(tmp, strlen(tmp)); - ss.write((const char*)&null_term, sizeof(uint8)); - ornaIcon = inst->GetOrnamentationIcon(); - heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in)); + packet_data.Write(tmp, strlen(tmp)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); + orn_icon = inst->GetOrnamentIcon(); + hero_model = inst->GetOrnamentHeroModel(EQEmu::Inventory::CalcMaterialFromSlot(EQEmu::InventorySlot(container_id, slot_id))); } else { - ss.write((const char*)&null_term, sizeof(uint8)); // no main hand Ornamentation - ss.write((const char*)&null_term, sizeof(uint8)); // no off hand Ornamentation + packet_data.Write((const char*)&null_term, sizeof(uint8)); // no main hand Ornamentation + packet_data.Write((const char*)&null_term, sizeof(uint8)); // no off hand Ornamentation } RoF2::structs::ItemSerializationHeaderFinish hdrf; - hdrf.ornamentIcon = ornaIcon; + hdrf.ornamentIcon = orn_icon; hdrf.unknowna1 = 0xffffffff; - hdrf.ornamentHeroModel = heroModel; + hdrf.ornamentHeroModel = hero_model; hdrf.unknown063 = 0; hdrf.Copied = 0; hdrf.unknowna4 = 0xffffffff; hdrf.unknowna5 = 0; hdrf.ItemClass = item->ItemClass; - ss.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); + packet_data.Write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); - if (strlen(item->Name) > 0) + if(strlen(item->Name) > 0) { - ss.write(item->Name, strlen(item->Name)); - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write(item->Name, strlen(item->Name)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } else { - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } - if (strlen(item->Lore) > 0) + if(strlen(item->Lore) > 0) { - ss.write(item->Lore, strlen(item->Lore)); - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write(item->Lore, strlen(item->Lore)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } else { - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } - if (strlen(item->IDFile) > 0) + if(strlen(item->IDFile) > 0) { - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write(item->IDFile, strlen(item->IDFile)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } else { - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } - ss.write((const char*)&null_term, sizeof(uint8)); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody struct is %i bytes", sizeof(RoF2::structs::ItemBodyStruct)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); + RoF2::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(RoF2::structs::ItemBodyStruct)); @@ -5406,10 +5391,10 @@ namespace RoF2 ibs.Magic = item->Magic; ibs.CastTime_ = item->CastTime_; ibs.ReqLevel = item->ReqLevel; - if (item->ReqLevel > 100) + if(item->ReqLevel > 100) ibs.ReqLevel = 100; ibs.RecLevel = item->RecLevel; - if (item->RecLevel > 100) + if(item->RecLevel > 100) ibs.RecLevel = 100; ibs.RecSkill = item->RecSkill; ibs.BardType = item->BardType; @@ -5448,20 +5433,19 @@ namespace RoF2 ibs.FactionAmt4 = item->FactionAmt4; ibs.FactionMod4 = item->FactionMod4; - ss.write((const char*)&ibs, sizeof(RoF2::structs::ItemBodyStruct)); + packet_data.Write((const char*)&ibs, sizeof(RoF2::structs::ItemBodyStruct)); //charm text - if (strlen(item->CharmFile) > 0) + if(strlen(item->CharmFile) > 0) { - ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)item->CharmFile, strlen(item->CharmFile)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } else { - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody secondary struct is %i bytes", sizeof(RoF2::structs::ItemSecondaryBodyStruct)); RoF2::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); @@ -5469,7 +5453,7 @@ namespace RoF2 isbs.augrestrict2 = -1; isbs.augrestrict = item->AugRestrict; - for (int x = AUG_BEGIN; x < consts::ITEM_COMMON_SIZE; x++) + for(int x = AUG_BEGIN; x < consts::ITEM_COMMON_SIZE; x++) { isbs.augslots[x].type = item->AugSlotType[x]; isbs.augslots[x].visible = item->AugSlotVisible[x]; @@ -5490,19 +5474,18 @@ namespace RoF2 isbs.book = item->Book; isbs.booktype = item->BookType; - ss.write((const char*)&isbs, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); + packet_data.Write((const char*)&isbs, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); - if (strlen(item->Filename) > 0) + if(strlen(item->Filename) > 0) { - ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)item->Filename, strlen(item->Filename)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } else { - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody tertiary struct is %i bytes", sizeof(RoF2::structs::ItemTertiaryBodyStruct)); RoF2::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); @@ -5536,12 +5519,11 @@ namespace RoF2 itbs.unknown13 = 0; itbs.unknown14 = 0; - ss.write((const char*)&itbs, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); + packet_data.Write((const char*)&itbs, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody Click effect struct is %i bytes", sizeof(RoF2::structs::ClickEffectStruct)); RoF2::structs::ClickEffectStruct ices; memset(&ices, 0, sizeof(RoF2::structs::ClickEffectStruct)); @@ -5554,21 +5536,20 @@ namespace RoF2 ices.recast = item->RecastDelay; ices.recast_type = item->RecastType; - ss.write((const char*)&ices, sizeof(RoF2::structs::ClickEffectStruct)); + packet_data.Write((const char*)&ices, sizeof(RoF2::structs::ClickEffectStruct)); - if (strlen(item->ClickName) > 0) + if(strlen(item->ClickName) > 0) { - ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)item->ClickName, strlen(item->ClickName)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } else { - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + packet_data.Write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody proc effect struct is %i bytes", sizeof(RoF2::structs::ProcEffectStruct)); RoF2::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(RoF2::structs::ProcEffectStruct)); @@ -5578,21 +5559,20 @@ namespace RoF2 ipes.level = item->Proc.Level; ipes.procrate = item->ProcRate; - ss.write((const char*)&ipes, sizeof(RoF2::structs::ProcEffectStruct)); + packet_data.Write((const char*)&ipes, sizeof(RoF2::structs::ProcEffectStruct)); - if (strlen(item->ProcName) > 0) + if(strlen(item->ProcName) > 0) { - ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)item->ProcName, strlen(item->ProcName)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } else { - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + packet_data.Write((const char*)&effect_unknown, sizeof(int32)); // unknown5 - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody worn effect struct is %i bytes", sizeof(RoF2::structs::WornEffectStruct)); RoF2::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(RoF2::structs::WornEffectStruct)); @@ -5601,19 +5581,19 @@ namespace RoF2 iwes.type = item->Worn.Type; iwes.level = item->Worn.Level; - ss.write((const char*)&iwes, sizeof(RoF2::structs::WornEffectStruct)); + packet_data.Write((const char*)&iwes, sizeof(RoF2::structs::WornEffectStruct)); - if (strlen(item->WornName) > 0) + if(strlen(item->WornName) > 0) { - ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)item->WornName, strlen(item->WornName)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } else { - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + packet_data.Write((const char*)&effect_unknown, sizeof(int32)); // unknown6 RoF2::structs::WornEffectStruct ifes; memset(&ifes, 0, sizeof(RoF2::structs::WornEffectStruct)); @@ -5623,19 +5603,19 @@ namespace RoF2 ifes.type = item->Focus.Type; ifes.level = item->Focus.Level; - ss.write((const char*)&ifes, sizeof(RoF2::structs::WornEffectStruct)); + packet_data.Write((const char*)&ifes, sizeof(RoF2::structs::WornEffectStruct)); - if (strlen(item->FocusName) > 0) + if(strlen(item->FocusName) > 0) { - ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)item->FocusName, strlen(item->FocusName)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } else { - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + packet_data.Write((const char*)&effect_unknown, sizeof(int32)); // unknown6 RoF2::structs::WornEffectStruct ises; memset(&ises, 0, sizeof(RoF2::structs::WornEffectStruct)); @@ -5645,19 +5625,19 @@ namespace RoF2 ises.type = item->Scroll.Type; ises.level = item->Scroll.Level; - ss.write((const char*)&ises, sizeof(RoF2::structs::WornEffectStruct)); + packet_data.Write((const char*)&ises, sizeof(RoF2::structs::WornEffectStruct)); - if (strlen(item->ScrollName) > 0) + if(strlen(item->ScrollName) > 0) { - ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)item->ScrollName, strlen(item->ScrollName)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } else { - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); } - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + packet_data.Write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // Bard Effect? RoF2::structs::WornEffectStruct ibes; @@ -5669,21 +5649,13 @@ namespace RoF2 ibes.level = item->Bard.Level; //ibes.unknown6 = 0xffffffff; - ss.write((const char*)&ibes, sizeof(RoF2::structs::WornEffectStruct)); + packet_data.Write((const char*)&ibes, sizeof(RoF2::structs::WornEffectStruct)); - /* - if(strlen(item->BardName) > 0) - { - ss.write((const char*)item->BardName, strlen(item->BardName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else */ - ss.write((const char*)&null_term, sizeof(uint8)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + packet_data.Write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody Quaternary effect struct is %i bytes", sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); RoF2::structs::ItemQuaternaryBodyStruct iqbs; memset(&iqbs, 0, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); @@ -5727,65 +5699,26 @@ namespace RoF2 iqbs.unknown39 = 1; - iqbs.subitem_count = 0; + EQEmu::ItemContainer *container = inst->GetContainer(); + if(container) { + iqbs.subitem_count = container->Size(); + packet_data.Write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); - char *SubSerializations[10]; // - - uint32 SubLengths[10]; - - for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { - - SubSerializations[x] = nullptr; - - const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); - - if (subitem) { - - int SubSlotNumber; - - iqbs.subitem_count++; - - if (slot_id_in >= EmuConstants::GENERAL_BEGIN && slot_id_in <= EmuConstants::GENERAL_END) // (< 30) - no cursor? - //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EmuConstants::BANK_BEGIN && slot_id_in <= EmuConstants::BANK_END) - //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EmuConstants::SHARED_BANK_BEGIN && slot_id_in <= EmuConstants::SHARED_BANK_END) - //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::SHARED_BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::SHARED_BANK_BAGS_BEGIN + x); - else - SubSlotNumber = slot_id_in; // ??????? - - /* - // TEST CODE: - SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); - */ - - SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1, packet_type); + auto iter = container->Begin(); + auto end = container->End(); + while(iter != end) { + auto sub_inst = inst->Get(iter->first); + if(sub_inst) { + uint32 bag_slot = iter->first; + packet_data.Write((const char*)&bag_slot, sizeof(uint32)); + SerializeItem(packet_data, sub_inst.get(), container_id, slot_id, bag_slot, -1); + } + ++iter; } + } else { + iqbs.subitem_count = 0; + packet_data.Write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); } - - ss.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); - - for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { - - if (SubSerializations[x]) { - - ss.write((const char*)&x, sizeof(uint32)); - - ss.write(SubSerializations[x], SubLengths[x]); - - safe_delete_array(SubSerializations[x]); - } - } - - char* item_serial = new char[ss.tellp()]; - memset(item_serial, 0, ss.tellp()); - memcpy(item_serial, ss.str().c_str(), ss.tellp()); - - *length = ss.tellp(); - return item_serial; } static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 812e9c464..e472616b7 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -2310,7 +2310,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - Item_Struct item; + ItemData item; uint8 iss_unknown001[6]; };*/ @@ -4406,7 +4406,7 @@ struct RoF2SlotStruct struct ItemSerializationHeader { -/*000*/ char unknown000[17]; // New for HoT. Looks like a string. +/*000*/ char tracking_id[17]; // New for HoT. Looks like a string. /*017*/ uint32 stacksize; /*021*/ uint32 unknown004; /*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ? diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index a87b530c4..08c63ddf3 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -2338,7 +2338,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - Item_Struct item; + ItemData item; uint8 iss_unknown001[6]; };*/ diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 80201da1e..1ee7d4b6c 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -336,71 +336,72 @@ namespace SoD { //consume the packet EQApplicationPacket *in = *p; + delete in; - *p = nullptr; - - if (in->size == 0) { - - in->size = 4; - - in->pBuffer = new uchar[in->size]; - - *((uint32 *)in->pBuffer) = 0; - - dest->FastQueuePacket(&in, ack_req); - - return; - } - - //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - - int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); - - if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { - - Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", - opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); - - delete in; - return; - } - - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; - in->pBuffer = new uchar[4]; - *(uint32 *)in->pBuffer = ItemCount; - in->size = 4; - - for (int r = 0; r < ItemCount; r++, eq++) { - - uint32 Length = 0; - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); - - if (Serialized) { - - uchar *OldBuffer = in->pBuffer; - in->pBuffer = new uchar[in->size + Length]; - memcpy(in->pBuffer, OldBuffer, in->size); - - safe_delete_array(OldBuffer); - - memcpy(in->pBuffer + in->size, Serialized, Length); - in->size += Length; - - safe_delete_array(Serialized); - - } - else { - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - } - } - - delete[] __emu_buffer; - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); - //Log.Hex(Logs::Netcode, in->pBuffer, in->size); - - dest->FastQueuePacket(&in, ack_req); + //*p = nullptr; + // + //if (in->size == 0) { + // + // in->size = 4; + // + // in->pBuffer = new uchar[in->size]; + // + // *((uint32 *)in->pBuffer) = 0; + // + // dest->FastQueuePacket(&in, ack_req); + // + // return; + //} + // + ////store away the emu struct + //unsigned char *__emu_buffer = in->pBuffer; + // + //int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); + // + //if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + // + // Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", + // opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); + // + // delete in; + // return; + //} + // + //InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + //in->pBuffer = new uchar[4]; + //*(uint32 *)in->pBuffer = ItemCount; + //in->size = 4; + // + //for (int r = 0; r < ItemCount; r++, eq++) { + // + // uint32 Length = 0; + // char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); + // + // if (Serialized) { + // + // uchar *OldBuffer = in->pBuffer; + // in->pBuffer = new uchar[in->size + Length]; + // memcpy(in->pBuffer, OldBuffer, in->size); + // + // safe_delete_array(OldBuffer); + // + // memcpy(in->pBuffer + in->size, Serialized, Length); + // in->size += Length; + // + // safe_delete_array(Serialized); + // + // } + // else { + // Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); + // } + //} + // + //delete[] __emu_buffer; + // + ////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); + ////Log.Hex(Logs::Netcode, in->pBuffer, in->size); + // + //dest->FastQueuePacket(&in, ack_req); } ENCODE(OP_ClientUpdate) @@ -1266,14 +1267,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); } @@ -3264,16 +3265,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) @@ -3559,7 +3560,7 @@ namespace SoD std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - const Item_Struct *item = inst->GetUnscaledItem(); + const ItemData *item = inst->GetUnscaledItem(); //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name); SoD::structs::ItemSerializationHeader hdr; hdr.stacksize = stackable ? charges : 1; @@ -3957,7 +3958,7 @@ namespace SoD /* // TEST CODE: - SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); + SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x); */ SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 2f5d2c2db..ab70301da 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1973,7 +1973,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - Item_Struct item; + ItemData item; uint8 iss_unknown001[6]; };*/ diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 7b0e14c1c..5db53b64f 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -318,69 +318,70 @@ namespace SoF { //consume the packet EQApplicationPacket *in = *p; + delete in; - *p = nullptr; - - if (in->size == 0) { - in->size = 4; - in->pBuffer = new uchar[in->size]; - *((uint32 *)in->pBuffer) = 0; - - dest->FastQueuePacket(&in, ack_req); - return; - } - - //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - - int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); - - if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { - - Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", - opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); - - delete in; - return; - } - - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; - - in->pBuffer = new uchar[4]; - *(uint32 *)in->pBuffer = ItemCount; - in->size = 4; - - for (int r = 0; r < ItemCount; r++, eq++) { - - uint32 Length = 0; - - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); - - if (Serialized) { - uchar *OldBuffer = in->pBuffer; - - in->pBuffer = new uchar[in->size + Length]; - memcpy(in->pBuffer, OldBuffer, in->size); - - safe_delete_array(OldBuffer); - - memcpy(in->pBuffer + in->size, Serialized, Length); - in->size += Length; - - safe_delete_array(Serialized); - - } - else { - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - } - } - - delete[] __emu_buffer; - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); - //Log.Hex(Logs::Netcode, in->pBuffer, in->size); - - dest->FastQueuePacket(&in, ack_req); + //*p = nullptr; + // + //if (in->size == 0) { + // in->size = 4; + // in->pBuffer = new uchar[in->size]; + // *((uint32 *)in->pBuffer) = 0; + // + // dest->FastQueuePacket(&in, ack_req); + // return; + //} + // + ////store away the emu struct + //unsigned char *__emu_buffer = in->pBuffer; + // + //int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); + // + //if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + // + // Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", + // opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); + // + // delete in; + // return; + //} + // + //InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + // + //in->pBuffer = new uchar[4]; + //*(uint32 *)in->pBuffer = ItemCount; + //in->size = 4; + // + //for (int r = 0; r < ItemCount; r++, eq++) { + // + // uint32 Length = 0; + // + // char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); + // + // if (Serialized) { + // uchar *OldBuffer = in->pBuffer; + // + // in->pBuffer = new uchar[in->size + Length]; + // memcpy(in->pBuffer, OldBuffer, in->size); + // + // safe_delete_array(OldBuffer); + // + // memcpy(in->pBuffer + in->size, Serialized, Length); + // in->size += Length; + // + // safe_delete_array(Serialized); + // + // } + // else { + // Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); + // } + //} + // + //delete[] __emu_buffer; + // + ////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); + ////Log.Hex(Logs::Netcode, in->pBuffer, in->size); + // + //dest->FastQueuePacket(&in, ack_req); } ENCODE(OP_ClientUpdate) @@ -931,14 +932,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); } @@ -2603,16 +2604,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) @@ -2884,7 +2885,7 @@ namespace SoF std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - const Item_Struct *item = inst->GetUnscaledItem(); + const ItemData *item = inst->GetUnscaledItem(); //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name); SoF::structs::ItemSerializationHeader hdr; hdr.stacksize = stackable ? charges : 1; @@ -3280,7 +3281,7 @@ namespace SoF /* // TEST CODE: - SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); + SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x); */ SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index afd34ba68..55db16f4e 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -1948,7 +1948,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - Item_Struct item; + ItemData item; uint8 iss_unknown001[6]; };*/ diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 2fda4038a..c0bf50978 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -263,40 +263,42 @@ namespace Titanium EQApplicationPacket *in = *p; *p = nullptr; - //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; + delete in; - int itemcount = in->size / sizeof(InternalSerializedItem_Struct); - if (itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { - Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); - delete in; - return; - } - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; - - //do the transform... - int r; - std::string serial_string; - for (r = 0; r < itemcount; r++, eq++) { - uint32 length; - char *serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &length, 0); - if (serialized) { - serial_string.append(serialized, length + 1); - safe_delete_array(serialized); - } - else { - Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - } - - } - - in->size = serial_string.length(); - in->pBuffer = new unsigned char[in->size]; - memcpy(in->pBuffer, serial_string.c_str(), serial_string.length()); - - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); + ////store away the emu struct + //unsigned char *__emu_buffer = in->pBuffer; + // + //int itemcount = in->size / sizeof(InternalSerializedItem_Struct); + //if (itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + // Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); + // delete in; + // return; + //} + //InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + // + ////do the transform... + //int r; + //std::string serial_string; + //for (r = 0; r < itemcount; r++, eq++) { + // uint32 length; + // char *serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &length, 0); + // if (serialized) { + // serial_string.append(serialized, length + 1); + // safe_delete_array(serialized); + // } + // else { + // Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); + // } + // + //} + // + //in->size = serial_string.length(); + //in->pBuffer = new unsigned char[in->size]; + //memcpy(in->pBuffer, serial_string.c_str(), serial_string.length()); + // + //delete[] __emu_buffer; + // + //dest->FastQueuePacket(&in, ack_req); } ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); } @@ -776,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); } @@ -1852,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) @@ -2070,7 +2072,7 @@ namespace Titanium int16 slot_id = ServerToTitaniumSlot(slot_id_in); uint32 merchant_slot = inst->GetMerchantSlot(); int16 charges = inst->GetCharges(); - const Item_Struct *item = inst->GetUnscaledItem(); + const ItemData *item = inst->GetUnscaledItem(); int i; uint32 sub_length; diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index f836395c9..2fac68ed6 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -1700,7 +1700,7 @@ struct AdventureRequestResponse_Struct{ /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - Item_Struct item; + ItemData item; uint8 iss_unknown001[6]; };*/ diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index d63a1bc04..b14d1b8b0 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -474,68 +474,69 @@ namespace UF { //consume the packet EQApplicationPacket *in = *p; - - *p = nullptr; - - if (in->size == 0) { - - in->size = 4; - in->pBuffer = new uchar[in->size]; - *((uint32 *)in->pBuffer) = 0; - - dest->FastQueuePacket(&in, ack_req); - return; - } - - //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - - int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); - - if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { - - Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", - opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); - - delete in; - return; - } - - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; - - in->pBuffer = new uchar[4]; - *(uint32 *)in->pBuffer = ItemCount; - in->size = 4; - - for (int r = 0; r < ItemCount; r++, eq++) { - - uint32 Length = 0; - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); - - if (Serialized) { - - uchar *OldBuffer = in->pBuffer; - in->pBuffer = new uchar[in->size + Length]; - memcpy(in->pBuffer, OldBuffer, in->size); - - safe_delete_array(OldBuffer); - - memcpy(in->pBuffer + in->size, Serialized, Length); - in->size += Length; - - safe_delete_array(Serialized); - } - else { - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - } - } - - delete[] __emu_buffer; - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); - //Log.Hex(Logs::Netcode, in->pBuffer, in->size); - - dest->FastQueuePacket(&in, ack_req); + delete in; + + //*p = nullptr; + // + //if (in->size == 0) { + // + // in->size = 4; + // in->pBuffer = new uchar[in->size]; + // *((uint32 *)in->pBuffer) = 0; + // + // dest->FastQueuePacket(&in, ack_req); + // return; + //} + // + ////store away the emu struct + //unsigned char *__emu_buffer = in->pBuffer; + // + //int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); + // + //if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + // + // Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", + // opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); + // + // delete in; + // return; + //} + // + //InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + // + //in->pBuffer = new uchar[4]; + //*(uint32 *)in->pBuffer = ItemCount; + //in->size = 4; + // + //for (int r = 0; r < ItemCount; r++, eq++) { + // + // uint32 Length = 0; + // char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); + // + // if (Serialized) { + // + // uchar *OldBuffer = in->pBuffer; + // in->pBuffer = new uchar[in->size + Length]; + // memcpy(in->pBuffer, OldBuffer, in->size); + // + // safe_delete_array(OldBuffer); + // + // memcpy(in->pBuffer + in->size, Serialized, Length); + // in->size += Length; + // + // safe_delete_array(Serialized); + // } + // else { + // Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); + // } + //} + // + //delete[] __emu_buffer; + // + ////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); + ////Log.Hex(Logs::Netcode, in->pBuffer, in->size); + // + //dest->FastQueuePacket(&in, ack_req); } ENCODE(OP_ClientUpdate) @@ -1505,14 +1506,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); } @@ -3586,16 +3587,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) @@ -3811,7 +3812,7 @@ namespace UF std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - const Item_Struct *item = inst->GetUnscaledItem(); + const ItemData *item = inst->GetUnscaledItem(); //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name); UF::structs::ItemSerializationHeader hdr; hdr.stacksize = stackable ? charges : 1; @@ -3849,7 +3850,7 @@ namespace UF //ORNAMENT IDFILE / ICON - uint16 ornaIcon = 0; if (inst->GetOrnamentationAug(ornamentationAugtype)) { - const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + const ItemData *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); ss.write((const char*)&null_term, sizeof(uint8)); ornaIcon = aug_weap->Icon; @@ -4265,7 +4266,7 @@ namespace UF /* // TEST CODE: - SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); + SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x); */ SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index c943c6ea5..6508bce55 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -2032,7 +2032,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - Item_Struct item; + ItemData item; uint8 iss_unknown001[6]; };*/ diff --git a/common/ruletypes.h b/common/ruletypes.h index 1919c7168..37124281b 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -584,27 +584,6 @@ RULE_CATEGORY_END() RULE_CATEGORY(QueryServ) RULE_BOOL(QueryServ, PlayerLogChat, false) // Logs Player Chat -RULE_BOOL(QueryServ, PlayerLogTrades, false) // Logs Player Trades -RULE_BOOL(QueryServ, PlayerLogHandins, false) // Logs Player Handins -RULE_BOOL(QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills -RULE_BOOL(QueryServ, PlayerLogDeletes, false) // Logs Player Deletes -RULE_BOOL(QueryServ, PlayerLogMoves, false) // Logs Player Moves -RULE_BOOL(QueryServ, PlayerLogMerchantTransactions, false) // Logs Merchant Transactions -RULE_BOOL(QueryServ, PlayerLogPCCoordinates, false) // Logs Player Coordinates with certain events -RULE_BOOL(QueryServ, PlayerLogDropItem, false) // Logs Player Drop Item -RULE_BOOL(QueryServ, PlayerLogZone, false) // Logs Player Zone Events -RULE_BOOL(QueryServ, PlayerLogDeaths, false) // Logs Player Deaths -RULE_BOOL(QueryServ, PlayerLogConnectDisconnect, false) // Logs Player Connect Disconnect State -RULE_BOOL(QueryServ, PlayerLogLevels, false) // Logs Player Leveling/Deleveling -RULE_BOOL(QueryServ, PlayerLogAARate, false) // Logs Player AA Experience Rates -RULE_BOOL(QueryServ, PlayerLogQGlobalUpdate, false) // Logs Player QGlobal Updates -RULE_BOOL(QueryServ, PlayerLogTaskUpdates, false) // Logs Player Task Updates -RULE_BOOL(QueryServ, PlayerLogKeyringAddition, false) // Log PLayer Keyring additions -RULE_BOOL(QueryServ, PlayerLogAAPurchases, false) // Log Player AA Purchases -RULE_BOOL(QueryServ, PlayerLogTradeSkillEvents, false) // Log Player Tradeskill Transactions -RULE_BOOL(QueryServ, PlayerLogIssuedCommandes, false) // Log Player Issued Commands -RULE_BOOL(QueryServ, PlayerLogMoneyTransactions, false) // Log Player Money Transaction/Splits -RULE_BOOL(QueryServ, PlayerLogAlternateCurrencyTransactions, false) // Log Ploayer Alternate Currency Transactions RULE_CATEGORY_END() RULE_CATEGORY(Inventory) diff --git a/common/servertalk.h b/common/servertalk.h index af39bfaa4..a3fa488d5 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -181,14 +181,7 @@ #define ServerOP_CZMessagePlayer 0x4008 #define ServerOP_ReloadWorld 0x4009 #define ServerOP_ReloadLogs 0x4010 -/* Query Server OP Codes */ -#define ServerOP_QSPlayerLogTrades 0x5010 -#define ServerOP_QSPlayerLogHandins 0x5011 -#define ServerOP_QSPlayerLogNPCKills 0x5012 -#define ServerOP_QSPlayerLogDeletes 0x5013 -#define ServerOP_QSPlayerLogMoves 0x5014 -#define ServerOP_QSPlayerLogMerchantTransactions 0x5015 -#define ServerOP_QSSendQuery 0x5016 +#define ServerOP_QSSendQuery 0x5000 #define ServerOP_CZSignalNPC 0x5017 #define ServerOP_CZSetEntityVariableByNPCTypeID 0x5018 @@ -1113,132 +1106,6 @@ struct CZClientSignalByName_Struct { uint32 data; }; -struct QSTradeItems_Struct { - uint32 from_id; - uint16 from_slot; - uint32 to_id; - uint16 to_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSPlayerLogTrade_Struct { - uint32 char1_id; - MoneyUpdate_Struct char1_money; - uint16 char1_count; - uint32 char2_id; - MoneyUpdate_Struct char2_money; - uint16 char2_count; - uint16 _detail_count; - QSTradeItems_Struct items[0]; -}; - -struct QSHandinItems_Struct { - char action_type[7]; // handin, return or reward - uint16 char_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSPlayerLogHandin_Struct { - uint32 quest_id; - uint32 char_id; - MoneyUpdate_Struct char_money; - uint16 char_count; - uint32 npc_id; - MoneyUpdate_Struct npc_money; - uint16 npc_count; - uint16 _detail_count; - QSHandinItems_Struct items[0]; -}; - -struct QSPlayerLogNPCKillSub_Struct{ - uint32 NPCID; - uint32 ZoneID; - uint32 Type; -}; - -struct QSPlayerLogNPCKillsPlayers_Struct{ - uint32 char_id; -}; - -struct QSPlayerLogNPCKill_Struct{ - QSPlayerLogNPCKillSub_Struct s1; - QSPlayerLogNPCKillsPlayers_Struct Chars[0]; -}; - -struct QSDeleteItems_Struct { - uint16 char_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSPlayerLogDelete_Struct { - uint32 char_id; - uint16 stack_size; // '0' indicates full stack or non-stackable item move - uint16 char_count; - QSDeleteItems_Struct items[0]; -}; - -struct QSMoveItems_Struct { - uint16 from_slot; - uint16 to_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSPlayerLogMove_Struct { - uint32 char_id; - uint16 from_slot; - uint16 to_slot; - uint16 stack_size; // '0' indicates full stack or non-stackable item move - uint16 char_count; - bool postaction; - QSMoveItems_Struct items[0]; -}; - -struct QSTransactionItems_Struct { - uint16 char_slot; - uint32 item_id; - uint16 charges; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; -}; - -struct QSMerchantLogTransaction_Struct { - uint32 zone_id; - uint32 merchant_id; - MoneyUpdate_Struct merchant_money; - uint16 merchant_count; - uint32 char_id; - MoneyUpdate_Struct char_money; - uint16 char_count; - QSTransactionItems_Struct items[0]; -}; - struct QSGeneralQuery_Struct { char QueryString[0]; }; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index aa4924665..fac3d48de 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -151,79 +151,77 @@ bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const Ite bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 slot_id) { - //never save tribute slots: - if(slot_id >= EmuConstants::TRIBUTE_BEGIN && slot_id <= EmuConstants::TRIBUTE_END) - return true; - - if (slot_id >= EmuConstants::SHARED_BANK_BEGIN && slot_id <= EmuConstants::SHARED_BANK_BAGS_END) { - // Shared bank inventory - if (!inst) { - return DeleteSharedBankSlot(char_id, slot_id); - } - else { - // Needed to clear out bag slots that 'REPLACE' in UpdateSharedBankSlot does not overwrite..otherwise, duplication occurs - // (This requires that parent then child items be sent..which should be how they are currently passed) - if (Inventory::SupportsContainers(slot_id)) - DeleteSharedBankSlot(char_id, slot_id); - return UpdateSharedBankSlot(char_id, inst, slot_id); - } - } - else if (!inst) { // All other inventory - return DeleteInventorySlot(char_id, slot_id); - } - - // Needed to clear out bag slots that 'REPLACE' in UpdateInventorySlot does not overwrite..otherwise, duplication occurs - // (This requires that parent then child items be sent..which should be how they are currently passed) - if (Inventory::SupportsContainers(slot_id)) - DeleteInventorySlot(char_id, slot_id); - return UpdateInventorySlot(char_id, inst, slot_id); + return true; + //// If we never save tribute slots..how are we to ever benefit from them!!? The client + //// object is destroyed upon zoning - including its inventory object..and if tributes + //// don't exist in the database, then they will never be loaded when the new client + //// object is created in the new zone object... Something to consider... -U + //// + //// (we could add them to the 'NoRent' checks and dispose of after 30 minutes offline) + // + ////never save tribute slots: + //if(slot_id >= EmuConstants::TRIBUTE_BEGIN && slot_id <= EmuConstants::TRIBUTE_END) + // return true; + // + //if (slot_id >= EmuConstants::SHARED_BANK_BEGIN && slot_id <= EmuConstants::SHARED_BANK_BAGS_END) { + // // Shared bank inventory + // if (!inst) + // return DeleteSharedBankSlot(char_id, slot_id); + // else + // return UpdateSharedBankSlot(char_id, inst, slot_id); + //} + //else if (!inst) { // All other inventory + // return DeleteInventorySlot(char_id, slot_id); + //} + // + //return UpdateInventorySlot(char_id, inst, slot_id); } bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { - // need to check 'inst' argument for valid pointer - - uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; - if (inst->IsType(ItemClassCommon)) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { - ItemInst *auginst = inst->GetItem(i); - augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM; - } - } - - uint16 charges = 0; - if(inst->GetCharges() >= 0) - charges = inst->GetCharges(); - else - charges = 0x7FFF; - - // Update/Insert item - std::string query = StringFormat("REPLACE INTO inventory " - "(charid, slotid, itemid, charges, instnodrop, custom_data, color, " - "augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model) " - "VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, " - "%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)", - (unsigned long)char_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, - (unsigned long)charges, (unsigned long)(inst->IsAttuned()? 1: 0), - inst->GetCustomDataString().c_str(), (unsigned long)inst->GetColor(), - (unsigned long)augslot[0], (unsigned long)augslot[1], (unsigned long)augslot[2], - (unsigned long)augslot[3], (unsigned long)augslot[4], (unsigned long)augslot[5], (unsigned long)inst->GetOrnamentationIcon(), - (unsigned long)inst->GetOrnamentationIDFile(), (unsigned long)inst->GetOrnamentHeroModel()); - auto results = QueryDatabase(query); - - // Save bag contents, if slot supports bag contents - if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) - // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' - // messages through attrition (and the modded code in SaveInventory) - for (uint8 idx = SUB_BEGIN; idx < inst->GetItem()->BagSlots && idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) { - const ItemInst* baginst = inst->GetItem(idx); - SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); - } - - if (!results.Success()) { - return false; - } - return true; + + // need to check 'inst' argument for valid pointer + // + //uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; + //if (inst->IsType(ItemClassCommon)) { + // for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + // ItemInst *auginst = inst->GetItem(i); + // augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM; + // } + //} + // + //uint16 charges = 0; + //if(inst->GetCharges() >= 0) + // charges = inst->GetCharges(); + //else + // charges = 0x7FFF; + // + //// Update/Insert item + //std::string query = StringFormat("REPLACE INTO inventory " + // "(charid, slotid, itemid, charges, instnodrop, custom_data, color, " + // "augslot1, augslot2, augslot3, augslot4, augslot5, augslot6, ornamenticon, ornamentidfile, ornament_hero_model) " + // "VALUES( %lu, %lu, %lu, %lu, %lu, '%s', %lu, " + // "%lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu)", + // (unsigned long)char_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, + // (unsigned long)charges, (unsigned long)(inst->IsAttuned()? 1: 0), + // inst->GetCustomDataString().c_str(), (unsigned long)inst->GetColor(), + // (unsigned long)augslot[0], (unsigned long)augslot[1], (unsigned long)augslot[2], + // (unsigned long)augslot[3], (unsigned long)augslot[4], (unsigned long)augslot[5], (unsigned long)inst->GetOrnamentationIcon(), + // (unsigned long)inst->GetOrnamentationIDFile(), (unsigned long)inst->GetOrnamentHeroModel()); + //auto results = QueryDatabase(query); + // + //// Save bag contents, if slot supports bag contents + //if (inst->IsType(ItemClassContainer) && InventoryOld::SupportsContainers(slot_id)) + // for (uint8 idx = SUB_BEGIN; idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) { + // const ItemInst* baginst = inst->GetItem(idx); + // SaveInventory(char_id, baginst, InventoryOld::CalcSlotId(slot_id, idx)); + // } + // + //if (!results.Success()) { + // return false; + //} + // + //return true; } bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { @@ -257,12 +255,12 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, auto results = QueryDatabase(query); // Save bag contents, if slot supports bag contents - if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) { + if (inst->IsType(ItemClassContainer) && InventoryOld::SupportsContainers(slot_id)) { // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) for (uint8 idx = SUB_BEGIN; idx < inst->GetItem()->BagSlots && idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = inst->GetItem(idx); - SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); + SaveInventory(char_id, baginst, InventoryOld::CalcSlotId(slot_id, idx)); } } @@ -283,10 +281,10 @@ bool SharedDatabase::DeleteInventorySlot(uint32 char_id, int16 slot_id) { } // Delete bag slots, if need be - if (!Inventory::SupportsContainers(slot_id)) + if (!InventoryOld::SupportsContainers(slot_id)) return true; - int16 base_slot_id = Inventory::CalcSlotId(slot_id, SUB_BEGIN); + int16 base_slot_id = InventoryOld::CalcSlotId(slot_id, SUB_BEGIN); query = StringFormat("DELETE FROM inventory WHERE charid = %i AND slotid >= %i AND slotid < %i", char_id, base_slot_id, (base_slot_id+10)); results = QueryDatabase(query); @@ -309,10 +307,10 @@ bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) { } // Delete bag slots, if need be - if (!Inventory::SupportsContainers(slot_id)) + if (!InventoryOld::SupportsContainers(slot_id)) return true; - int16 base_slot_id = Inventory::CalcSlotId(slot_id, SUB_BEGIN); + int16 base_slot_id = InventoryOld::CalcSlotId(slot_id, SUB_BEGIN); query = StringFormat("DELETE FROM sharedbank WHERE acctid = %i " "AND slotid >= %i AND slotid < %i", account_id, base_slot_id, (base_slot_id+10)); @@ -352,9 +350,9 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) { return true; } -bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) { +bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, InventoryOld* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) { - const Item_Struct* myitem; + const ItemData* myitem; std::string query = StringFormat("SELECT itemid, item_charges, slot FROM starting_items " "WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND " @@ -375,7 +373,7 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, if(!myitem) continue; - ItemInst* myinst = CreateBaseItem(myitem, charges); + ItemInst* myinst = CreateBaseItemOld(myitem, charges); if(slot < 0) slot = inv->FindFreeSlot(0, 0); @@ -389,7 +387,7 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, // Retrieve shared bank inventory based on either account or character -bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) +bool SharedDatabase::GetSharedBank(uint32 id, InventoryOld *inv, bool is_charid) { std::string query; @@ -426,7 +424,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) aug[4] = (uint32)atoi(row[7]); aug[5] = (uint32)atoi(row[8]); - const Item_Struct *item = GetItem(item_id); + const ItemData *item = GetItem(item_id); if (!item) { Log.Out(Logs::General, Logs::Error, @@ -437,7 +435,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) int16 put_slot_id = INVALID_INDEX; - ItemInst *inst = CreateBaseItem(item, charges); + ItemInst *inst = CreateBaseItemOld(item, charges); if (inst && item->ItemClass == ItemClassCommon) { for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { if (aug[i]) @@ -489,150 +487,68 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) } // Overloaded: Retrieve character inventory based on character id -bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) +bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::Inventory *inv) { - // Retrieve character inventory - std::string query = - StringFormat("SELECT slotid, itemid, charges, color, augslot1, augslot2, augslot3, augslot4, augslot5, " - "augslot6, instnodrop, custom_data, ornamenticon, ornamentidfile, ornament_hero_model FROM " - "inventory WHERE charid = %i ORDER BY slotid", - char_id); + std::string query = StringFormat("SELECT type, slot, bag_index, aug_index, item_id, charges, color, attuned, " + "custom_data, ornament_icon, ornament_idfile, ornament_hero_model, tracking_id " + "FROM character_inventory WHERE id=%u ORDER BY type, slot, bag_index, aug_index", + char_id); + auto results = QueryDatabase(query); + if (!results.Success()) { - Log.Out(Logs::General, Logs::Error, "If you got an error related to the 'instnodrop' field, run the " - "following SQL Queries:\nalter table inventory add instnodrop " - "tinyint(1) unsigned default 0 not null;\n"); + Log.Out(Logs::General, Logs::Error, "Error with query in SharedDatabase::GetInventory, could not get inventory" + " for character %u", char_id); return false; } auto timestamps = GetItemRecastTimestamps(char_id); + for(auto row : results) { + int type = atoi(row[0]); + int slot = atoi(row[1]); + int bag_index = atoi(row[2]); + int aug_index = atoi(row[3]); + int item_id = atoi(row[4]); + int charges = atoi(row[5]); - for (auto row = results.begin(); row != results.end(); ++row) { - int16 slot_id = atoi(row[0]); - uint32 item_id = atoi(row[1]); - uint16 charges = atoi(row[2]); - uint32 color = atoul(row[3]); + auto inst = CreateItem(item_id, charges); + if(inst) { + uint32 color = (uint32)std::stoul(row[6]); + int attuned = atoi(row[7]); + uint32 ornament_icon = (uint32)std::stoul(row[9]); + uint32 ornament_idfile = (uint32)std::stoul(row[10]); + uint32 ornament_hero_model = (uint32)std::stoul(row[11]); - uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; - - aug[0] = (uint32)atoul(row[4]); - aug[1] = (uint32)atoul(row[5]); - aug[2] = (uint32)atoul(row[6]); - aug[3] = (uint32)atoul(row[7]); - aug[4] = (uint32)atoul(row[8]); - aug[5] = (uint32)atoul(row[9]); - - bool instnodrop = (row[10] && (uint16)atoi(row[10])) ? true : false; - - uint32 ornament_icon = (uint32)atoul(row[12]); - uint32 ornament_idfile = (uint32)atoul(row[13]); - uint32 ornament_hero_model = (uint32)atoul(row[14]); - - const Item_Struct *item = GetItem(item_id); - - if (!item) { - Log.Out(Logs::General, Logs::Error, - "Warning: charid %i has an invalid item_id %i in inventory slot %i", char_id, item_id, - slot_id); - continue; - } - - int16 put_slot_id = INVALID_INDEX; - - ItemInst *inst = CreateBaseItem(item, charges); - - if (inst == nullptr) - continue; - - if (row[11]) { - std::string data_str(row[11]); - std::string idAsString; - std::string value; - bool use_id = true; - - for (int i = 0; i < data_str.length(); ++i) { - if (data_str[i] == '^') { - if (!use_id) { - inst->SetCustomData(idAsString, value); - idAsString.clear(); - value.clear(); - } - - use_id = !use_id; - continue; - } - - char v = data_str[i]; - if (use_id) - idAsString.push_back(v); - else - value.push_back(v); - } - } - - inst->SetOrnamentIcon(ornament_icon); - inst->SetOrnamentationIDFile(ornament_idfile); - inst->SetOrnamentHeroModel(ornament_hero_model); - - if (instnodrop || - (((slot_id >= EmuConstants::EQUIPMENT_BEGIN && slot_id <= EmuConstants::EQUIPMENT_END) || - slot_id == MainPowerSource) && - inst->GetItem()->Attuneable)) - inst->SetAttuned(true); - - if (color > 0) inst->SetColor(color); + inst->SetAttuned(attuned ? true : false); + inst->SetCustomData(row[8]); + inst->SetOrnamentIcon(ornament_icon); + inst->SetOrnamentIDFile(ornament_idfile); + inst->SetOrnamentHeroModel(ornament_hero_model); + inst->SetTrackingID(row[12]); - if (charges == 0x7FFF) - inst->SetCharges(-1); - else if (charges == 0 && - inst->IsStackable()) // Stackable items need a minimum charge of 1 remain moveable. - inst->SetCharges(1); - else - inst->SetCharges(charges); - - if (item->RecastDelay) { - if (timestamps.count(item->RecastType)) - inst->SetRecastTimestamp(timestamps.at(item->RecastType)); - else - inst->SetRecastTimestamp(0); - } - - if (item->ItemClass == ItemClassCommon) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { - if (aug[i]) - inst->PutAugment(this, i, aug[i]); + auto *item = inst->GetItem(); + if(item->RecastDelay) { + if(timestamps.count(item->RecastType)) { + inst->SetRecastTimestamp(timestamps.at(item->RecastType)); + } } - } - if (slot_id >= 8000 && slot_id <= 8999) { - put_slot_id = inv->PushCursor(*inst); - } else if (slot_id >= 3111 && slot_id <= 3179) { - // Admins: please report any occurrences of this error - Log.Out(Logs::General, Logs::Error, "Warning: Defunct location for item in inventory: " - "charid=%i, item_id=%i, slot_id=%i .. pushing to cursor...", - char_id, item_id, slot_id); - put_slot_id = inv->PushCursor(*inst); + if(!inv->Put(EQEmu::InventorySlot(type, slot, bag_index, aug_index), inst)) { + Log.Out(Logs::General, Logs::Error, "Error putting item %u into (%d, %d, %d, %d) for char %u.", + item_id, type, slot, bag_index, aug_index, char_id); + } } else { - put_slot_id = inv->PutItem(slot_id, *inst); - } - - safe_delete(inst); - - // Save ptr to item in inventory - if (put_slot_id == INVALID_INDEX) { - Log.Out(Logs::General, Logs::Error, - "Warning: Invalid slot_id for item in inventory: charid=%i, item_id=%i, slot_id=%i", - char_id, item_id, slot_id); + Log.Out(Logs::General, Logs::Error, "Error putting item %u into (%d, %d, %d, %d) for char %u. Item does not exist.", + item_id, type, slot, bag_index, aug_index, char_id); } } - // Retrieve shared inventory - return GetSharedBank(char_id, inv, true); + return true; } // Overloaded: Retrieve character inventory based on account_id and character name -bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) +bool SharedDatabase::GetInventory(uint32 account_id, char *name, InventoryOld *inv) { // Retrieve character inventory std::string query = @@ -669,12 +585,12 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) uint32 ornament_idfile = (uint32)atoul(row[13]); uint32 ornament_hero_model = (uint32)atoul(row[14]); - const Item_Struct *item = GetItem(item_id); + const ItemData *item = GetItem(item_id); int16 put_slot_id = INVALID_INDEX; if (!item) continue; - ItemInst *inst = CreateBaseItem(item, charges); + ItemInst *inst = CreateBaseItemOld(item, charges); if (inst == nullptr) continue; @@ -813,12 +729,12 @@ bool SharedDatabase::LoadItems() { if(items == -1) { EQ_EXCEPT("SharedDatabase", "Database returned no result"); } - uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); + uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); if(items_mmf->Size() != size) { EQ_EXCEPT("SharedDatabase", "Couldn't load items because items_mmf->Size() != size"); } - items_hash = new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), size); + items_hash = new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), size); mutex.Unlock(); } catch(std::exception& ex) { Log.Out(Logs::General, Logs::Error, "Error Loading Items: %s", ex.what()); @@ -829,7 +745,7 @@ bool SharedDatabase::LoadItems() { } void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id) { - EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); + EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); char ndbuffer[4]; bool disableNoRent = false; @@ -857,7 +773,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } } - Item_Struct item; + ItemData item; const std::string query = "SELECT source," #define F(x) "`"#x"`," @@ -870,7 +786,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } for(auto row = results.begin(); row != results.end(); ++row) { - memset(&item, 0, sizeof(Item_Struct)); + memset(&item, 0, sizeof(ItemData)); item.ItemClass = (uint8)atoi(row[ItemField::itemclass]); strcpy(item.Name,row[ItemField::name]); @@ -1085,7 +1001,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } -const Item_Struct* SharedDatabase::GetItem(uint32 id) { +const ItemData* SharedDatabase::GetItem(uint32 id) { if (id == 0) { return nullptr; @@ -1104,7 +1020,7 @@ const Item_Struct* SharedDatabase::GetItem(uint32 id) { return nullptr; } -const Item_Struct* SharedDatabase::IterateItems(uint32* id) { +const ItemData* SharedDatabase::IterateItems(uint32* id) { if(!items_hash || !id) { return nullptr; } @@ -1260,14 +1176,14 @@ bool SharedDatabase::LoadNPCFactionLists() { } // Create appropriate ItemInst class -ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) +ItemInst* SharedDatabase::CreateItemOld(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) { - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; ItemInst* inst = nullptr; item = GetItem(item_id); if (item) { - inst = CreateBaseItem(item, charges); + inst = CreateBaseItemOld(item, charges); if (inst == nullptr) { Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateItem()"); @@ -1289,14 +1205,14 @@ ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, // Create appropriate ItemInst class -ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) +ItemInst* SharedDatabase::CreateItemOld(const ItemData* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) { ItemInst* inst = nullptr; if (item) { - inst = CreateBaseItem(item, charges); + inst = CreateBaseItemOld(item, charges); if (inst == nullptr) { - Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateItem()"); + Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateItemOld()"); Log.Out(Logs::General, Logs::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges); return nullptr; } @@ -1313,7 +1229,7 @@ ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uin return inst; } -ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges) { +ItemInst* SharedDatabase::CreateBaseItemOld(const ItemData* item, int16 charges) { ItemInst* inst = nullptr; if (item) { // if maxcharges is -1 that means it is an unlimited use item. @@ -1327,7 +1243,7 @@ ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges) inst = new ItemInst(item, charges); if (inst == nullptr) { - Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateBaseItem()"); + Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateBaseItemOld()"); Log.Out(Logs::General, Logs::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges); return nullptr; } @@ -1339,6 +1255,28 @@ ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges) return inst; } +EQEmu::ItemInstance::pointer SharedDatabase::CreateItem(uint32 item_id, int16 charges, bool unique) { + const ItemData* item = GetItem(item_id); + if(item) { + if(charges == 0 && item->MaxCharges == -1) { + charges = 1; + } + + if(charges <= 0 && item->Stackable) { + charges = 1; + } + + EQEmu::ItemInstance::pointer inst = EQEmu::ItemInstance::pointer(new EQEmu::ItemInstance(item, charges)); + if(unique) { + inst->SetSerialNumber(EQEmu::GetNextItemInstanceSerial()); + //Set Tracking here + } + return inst; + } + + return EQEmu::ItemInstance::pointer(nullptr); +} + int32 SharedDatabase::DeleteStalePlayerCorpses() { if(RuleB(Zone, EnableShadowrest)) { std::string query = StringFormat( diff --git a/common/shareddb.h b/common/shareddb.h index aef325380..33ad207b1 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -9,18 +9,19 @@ #include "base_data.h" #include "fixed_memory_hash_set.h" #include "fixed_memory_variable_hash_set.h" +#include "inventory.h" #include #include class EvolveInfo; -class Inventory; +class InventoryOld; class ItemInst; struct BaseDataStruct; struct InspectMessage_Struct; struct PlayerProfile_Struct; struct SPDat_Spell_Struct; -struct Item_Struct; +struct ItemData; struct NPCFactionList; struct LootTable_Struct; struct LootDrop_Struct; @@ -65,15 +66,15 @@ class SharedDatabase : public Database bool UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id); bool UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id); bool VerifyInventory(uint32 account_id, int16 slot_id, const ItemInst* inst); - bool GetSharedBank(uint32 id, Inventory* inv, bool is_charid); + bool GetSharedBank(uint32 id, InventoryOld* inv, bool is_charid); int32 GetSharedPlatinum(uint32 account_id); bool SetSharedPlatinum(uint32 account_id, int32 amount_to_add); - bool GetInventory(uint32 char_id, Inventory* inv); - bool GetInventory(uint32 account_id, char* name, Inventory* inv); + bool GetInventory(uint32 char_id, EQEmu::Inventory* inv); + bool GetInventory(uint32 account_id, char* name, InventoryOld* inv); std::map GetItemRecastTimestamps(uint32 char_id); uint32 GetItemRecastTimestamp(uint32 char_id, uint32 recast_type); void ClearOldRecastTimestamps(uint32 char_id); - bool SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin); + bool SetStartingItems(PlayerProfile_Struct* pp, InventoryOld* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin); std::string GetBook(const char *txtfile); @@ -81,9 +82,10 @@ class SharedDatabase : public Database /* Item Methods */ - ItemInst* CreateItem(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); - ItemInst* CreateItem(const Item_Struct* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); - ItemInst* CreateBaseItem(const Item_Struct* item, int16 charges = 0); + ItemInst* CreateItemOld(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); + ItemInst* CreateItemOld(const ItemData* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); + ItemInst* CreateBaseItemOld(const ItemData* item, int16 charges = 0); + EQEmu::ItemInstance::pointer CreateItem(uint32 item_id, int16 charges = 0, bool unique = true); /* Shared Memory crap @@ -93,8 +95,8 @@ class SharedDatabase : public Database void GetItemsCount(int32 &item_count, uint32 &max_id); void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id); bool LoadItems(); - const Item_Struct* IterateItems(uint32* id); - const Item_Struct* GetItem(uint32 id); + const ItemData* IterateItems(uint32* id); + const ItemData* GetItem(uint32 id); const EvolveInfo* GetEvolveInfo(uint32 loregroup); //faction lists @@ -130,7 +132,7 @@ class SharedDatabase : public Database EQEmu::MemoryMappedFile *skill_caps_mmf; EQEmu::MemoryMappedFile *items_mmf; - EQEmu::FixedMemoryHashSet *items_hash; + EQEmu::FixedMemoryHashSet *items_hash; EQEmu::MemoryMappedFile *faction_mmf; EQEmu::FixedMemoryHashSet *faction_hash; EQEmu::MemoryMappedFile *loot_table_mmf; diff --git a/queryserv/database.cpp b/queryserv/database.cpp index ea5bdff65..a65255cfc 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -123,229 +123,6 @@ void Database::AddSpeech(const char* from, const char* to, const char* message, } -void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 detailCount) { - - std::string query = StringFormat("INSERT INTO `qs_player_trade_record` SET `time` = NOW(), " - "`char1_id` = '%i', `char1_pp` = '%i', `char1_gp` = '%i', " - "`char1_sp` = '%i', `char1_cp` = '%i', `char1_items` = '%i', " - "`char2_id` = '%i', `char2_pp` = '%i', `char2_gp` = '%i', " - "`char2_sp` = '%i', `char2_cp` = '%i', `char2_items` = '%i'", - QS->char1_id, QS->char1_money.platinum, QS->char1_money.gold, - QS->char1_money.silver, QS->char1_money.copper, QS->char1_count, - QS->char2_id, QS->char2_money.platinum, QS->char2_money.gold, - QS->char2_money.silver, QS->char2_money.copper, QS->char2_count); - auto results = QueryDatabase(query); - if(!results.Success()) { - Log.Out(Logs::Detail, Logs::QS_Server, "Failed Trade Log Record Insert: %s", results.ErrorMessage().c_str()); - Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); - } - - if(detailCount == 0) - return; - - int lastIndex = results.LastInsertedID(); - - for(int i = 0; i < detailCount; i++) { - query = StringFormat("INSERT INTO `qs_player_trade_record_entries` SET `event_id` = '%i', " - "`from_id` = '%i', `from_slot` = '%i', `to_id` = '%i', `to_slot` = '%i', " - "`item_id` = '%i', `charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', " - "`aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].from_id, QS->items[i].from_slot, - QS->items[i].to_id, QS->items[i].to_slot, QS->items[i].item_id, - QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2, - QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5); - results = QueryDatabase(query); - if(!results.Success()) { - Log.Out(Logs::Detail, Logs::QS_Server, "Failed Trade Log Record Entry Insert: %s", results.ErrorMessage().c_str()); - Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); - } - - } - -} - -void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 detailCount) { - - std::string query = StringFormat("INSERT INTO `qs_player_handin_record` SET `time` = NOW(), " - "`quest_id` = '%i', `char_id` = '%i', `char_pp` = '%i', " - "`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', " - "`char_items` = '%i', `npc_id` = '%i', `npc_pp` = '%i', " - "`npc_gp` = '%i', `npc_sp` = '%i', `npc_cp` = '%i', " - "`npc_items`='%i'", - QS->quest_id, QS->char_id, QS->char_money.platinum, - QS->char_money.gold, QS->char_money.silver, QS->char_money.copper, - QS->char_count, QS->npc_id, QS->npc_money.platinum, - QS->npc_money.gold, QS->npc_money.silver, QS->npc_money.copper, - QS->npc_count); - auto results = QueryDatabase(query); - if(!results.Success()) { - Log.Out(Logs::Detail, Logs::QS_Server, "Failed Handin Log Record Insert: %s", results.ErrorMessage().c_str()); - Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); - } - - if(detailCount == 0) - return; - - int lastIndex = results.LastInsertedID(); - - for(int i = 0; i < detailCount; i++) { - query = StringFormat("INSERT INTO `qs_player_handin_record_entries` SET `event_id` = '%i', " - "`action_type` = '%s', `char_slot` = '%i', `item_id` = '%i', " - "`charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', " - "`aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].action_type, QS->items[i].char_slot, - QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1, - QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, - QS->items[i].aug_5); - if(!results.Success()) { - Log.Out(Logs::Detail, Logs::QS_Server, "Failed Handin Log Record Entry Insert: %s", results.ErrorMessage().c_str()); - Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); - } - } - -} - -void Database::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 members){ - - std::string query = StringFormat("INSERT INTO `qs_player_npc_kill_record` " - "SET `npc_id` = '%i', `type` = '%i', " - "`zone_id` = '%i', `time` = NOW()", - QS->s1.NPCID, QS->s1.Type, QS->s1.ZoneID); - auto results = QueryDatabase(query); - if(!results.Success()) { - Log.Out(Logs::Detail, Logs::QS_Server, "Failed NPC Kill Log Record Insert: %s", results.ErrorMessage().c_str()); - Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); - } - - if(members == 0) - return; - - int lastIndex = results.LastInsertedID(); - - for (int i = 0; i < members; i++) { - query = StringFormat("INSERT INTO `qs_player_npc_kill_record_entries` " - "SET `event_id` = '%i', `char_id` = '%i'", - lastIndex, QS->Chars[i].char_id); - auto results = QueryDatabase(query); - if(!results.Success()) { - Log.Out(Logs::Detail, Logs::QS_Server, "Failed NPC Kill Log Entry Insert: %s", results.ErrorMessage().c_str()); - Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); - } - - } - -} - -void Database::LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 items) { - - std::string query = StringFormat("INSERT INTO `qs_player_delete_record` SET `time` = NOW(), " - "`char_id` = '%i', `stack_size` = '%i', `char_items` = '%i'", - QS->char_id, QS->stack_size, QS->char_count, QS->char_count); - auto results = QueryDatabase(query); - if(!results.Success()) { - Log.Out(Logs::Detail, Logs::QS_Server, "Failed Delete Log Record Insert: %s", results.ErrorMessage().c_str()); - Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); - } - - if(items == 0) - return; - - int lastIndex = results.LastInsertedID(); - - for(int i = 0; i < items; i++) { - query = StringFormat("INSERT INTO `qs_player_delete_record_entries` SET `event_id` = '%i', " - "`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', " - "`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, - QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, - QS->items[i].aug_5); - results = QueryDatabase(query); - if(!results.Success()) { - Log.Out(Logs::Detail, Logs::QS_Server, "Failed Delete Log Record Entry Insert: %s", results.ErrorMessage().c_str()); - Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); - } - - } - -} - -void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 items) { - /* These are item moves */ - - std::string query = StringFormat("INSERT INTO `qs_player_move_record` SET `time` = NOW(), " - "`char_id` = '%i', `from_slot` = '%i', `to_slot` = '%i', " - "`stack_size` = '%i', `char_items` = '%i', `postaction` = '%i'", - QS->char_id, QS->from_slot, QS->to_slot, QS->stack_size, - QS->char_count, QS->postaction); - auto results = QueryDatabase(query); - if(!results.Success()) { - Log.Out(Logs::Detail, Logs::QS_Server, "Failed Move Log Record Insert: %s", results.ErrorMessage().c_str()); - Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); - } - - if(items == 0) - return; - - int lastIndex = results.LastInsertedID(); - - for(int i = 0; i < items; i++) { - query = StringFormat("INSERT INTO `qs_player_move_record_entries` SET `event_id` = '%i', " - "`from_slot` = '%i', `to_slot` = '%i', `item_id` = '%i', `charges` = '%i', " - "`aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].from_slot, QS->items[i].to_slot, QS->items[i].item_id, - QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2, - QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5); - results = QueryDatabase(query); - if(!results.Success()) { - Log.Out(Logs::Detail, Logs::QS_Server, "Failed Move Log Record Entry Insert: %s", results.ErrorMessage().c_str()); - Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); - } - - } - -} - -void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 items) { - /* Merchant transactions are from the perspective of the merchant, not the player */ - std::string query = StringFormat("INSERT INTO `qs_merchant_transaction_record` SET `time` = NOW(), " - "`zone_id` = '%i', `merchant_id` = '%i', `merchant_pp` = '%i', " - "`merchant_gp` = '%i', `merchant_sp` = '%i', `merchant_cp` = '%i', " - "`merchant_items` = '%i', `char_id` = '%i', `char_pp` = '%i', " - "`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', " - "`char_items` = '%i'", - QS->zone_id, QS->merchant_id, QS->merchant_money.platinum, - QS->merchant_money.gold, QS->merchant_money.silver, - QS->merchant_money.copper, QS->merchant_count, QS->char_id, - QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver, - QS->char_money.copper, QS->char_count); - auto results = QueryDatabase(query); - if(!results.Success()) { - Log.Out(Logs::Detail, Logs::QS_Server, "Failed Transaction Log Record Insert: %s", results.ErrorMessage().c_str()); - Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); - } - - if(items == 0) - return; - - int lastIndex = results.LastInsertedID(); - - for(int i = 0; i < items; i++) { - query = StringFormat("INSERT INTO `qs_merchant_transaction_record_entries` SET `event_id` = '%i', " - "`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', " - "`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'", - lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, - QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, - QS->items[i].aug_5); - results = QueryDatabase(query); - if(!results.Success()) { - Log.Out(Logs::Detail, Logs::QS_Server, "Failed Transaction Log Record Entry Insert: %s", results.ErrorMessage().c_str()); - Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); - } - - } - -} - void Database::GeneralQueryReceive(ServerPacket *pack) { /* These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again diff --git a/queryserv/database.h b/queryserv/database.h index b2d32341b..02448b6ef 100644 --- a/queryserv/database.h +++ b/queryserv/database.h @@ -44,12 +44,6 @@ public: ~Database(); void AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type); - void LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 DetailCount); - void LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount); - void LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members); - void LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items); - void LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items); - void LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 Items); void GeneralQueryReceive(ServerPacket *pack); void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings); diff --git a/queryserv/worldserver.cpp b/queryserv/worldserver.cpp index 2d2f288a4..914a63708 100644 --- a/queryserv/worldserver.cpp +++ b/queryserv/worldserver.cpp @@ -81,41 +81,6 @@ void WorldServer::Process() database.AddSpeech(tmp1.c_str(), tmp2.c_str(), SSS->message, SSS->minstatus, SSS->guilddbid, SSS->type); break; } - case ServerOP_QSPlayerLogTrades: { - QSPlayerLogTrade_Struct *QS = (QSPlayerLogTrade_Struct*)pack->pBuffer; - database.LogPlayerTrade(QS, QS->_detail_count); - break; - } - case ServerOP_QSPlayerLogHandins: { - QSPlayerLogHandin_Struct *QS = (QSPlayerLogHandin_Struct*)pack->pBuffer; - database.LogPlayerHandin(QS, QS->_detail_count); - break; - } - case ServerOP_QSPlayerLogNPCKills: { - QSPlayerLogNPCKill_Struct *QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; - uint32 Members = pack->size - sizeof(QSPlayerLogNPCKill_Struct); - if (Members > 0) Members = Members / sizeof(QSPlayerLogNPCKillsPlayers_Struct); - database.LogPlayerNPCKill(QS, Members); - break; - } - case ServerOP_QSPlayerLogDeletes: { - QSPlayerLogDelete_Struct *QS = (QSPlayerLogDelete_Struct*)pack->pBuffer; - uint32 Items = QS->char_count; - database.LogPlayerDelete(QS, Items); - break; - } - case ServerOP_QSPlayerLogMoves: { - QSPlayerLogMove_Struct *QS = (QSPlayerLogMove_Struct*)pack->pBuffer; - uint32 Items = QS->char_count; - database.LogPlayerMove(QS, Items); - break; - } - case ServerOP_QSPlayerLogMerchantTransactions: { - QSMerchantLogTransaction_Struct *QS = (QSMerchantLogTransaction_Struct*)pack->pBuffer; - uint32 Items = QS->char_count + QS->merchant_count; - database.LogMerchantTransaction(QS, Items); - break; - } case ServerOP_QueryServGeneric: { /* The purpose of ServerOP_QueryServerGeneric is so that we don't have to add code to world just to relay packets diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index 48b81b6fc..1a02e8022 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -22,7 +22,7 @@ #include "../common/ipc_mutex.h" #include "../common/memory_mapped_file.h" #include "../common/eqemu_exception.h" -#include "../common/item_struct.h" +#include "../common/item_data.h" void LoadItems(SharedDatabase *database) { EQEmu::IPCMutex mutex("items"); @@ -35,7 +35,7 @@ void LoadItems(SharedDatabase *database) { EQ_EXCEPT("Shared Memory", "Unable to get any items from the database."); } - uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); + uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); EQEmu::MemoryMappedFile mmf("shared/items", size); mmf.ZeroFile(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1c13ae26c..3738a5719 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,7 +12,9 @@ SET(tests_headers fixed_memory_test.h fixed_memory_variable_test.h hextoi_32_64_test.h + inventory_test.h ipc_mutex_test.h + memory_buffer_test.h memory_mapped_file_test.h string_util_test.h skills_util_test.h @@ -20,7 +22,7 @@ SET(tests_headers ADD_EXECUTABLE(tests ${tests_sources} ${tests_headers}) -TARGET_LINK_LIBRARIES(tests common cppunit) +TARGET_LINK_LIBRARIES(tests common cppunit debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE}) INSTALL(TARGETS tests RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}) diff --git a/tests/fixed_memory_test.h b/tests/fixed_memory_test.h index fcff0c9e8..98ba842ee 100644 --- a/tests/fixed_memory_test.h +++ b/tests/fixed_memory_test.h @@ -27,7 +27,7 @@ class FixedMemoryHashTest : public Test::Suite { typedef void(FixedMemoryHashTest::*TestFunction)(void); public: FixedMemoryHashTest() { - size_ = EQEmu::FixedMemoryHashSet::estimated_size(72000, 190000); + size_ = EQEmu::FixedMemoryHashSet::estimated_size(72000, 190000); data_ = new uint8[size_]; memset(data_, 0, size_); TEST_ADD(FixedMemoryHashTest::InitTest); @@ -49,7 +49,7 @@ public: private: void InitTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_, 72000, 190000); + EQEmu::FixedMemoryHashSet hash(data_, size_, 72000, 190000); TEST_ASSERT(!hash.exists(1001)); TEST_ASSERT(hash.size() == 0); TEST_ASSERT(hash.max_size() == 72000); @@ -57,7 +57,7 @@ public: } void LoadTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(!hash.exists(1001)); TEST_ASSERT(hash.size() == 0); TEST_ASSERT(hash.max_size() == 72000); @@ -65,8 +65,8 @@ public: } void InsertTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + ItemData item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Iron Sword"); item.ID = 1001; @@ -79,20 +79,20 @@ public: } void RetrieveTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.size() == 1); TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - Item_Struct item = hash[1001]; + ItemData item = hash[1001]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1001); } void OverwriteTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + ItemData item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Steel Sword"); item.ID = 1001; @@ -105,20 +105,20 @@ public: } void OverwriteRetrieveTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.size() == 1); TEST_ASSERT((hash.max_size() == 72000)); TEST_ASSERT(!hash.empty()); - Item_Struct item = hash[1001]; + ItemData item = hash[1001]; TEST_ASSERT(strcmp(item.Name, "Steel Sword") == 0); TEST_ASSERT(item.ID == 1001); } void InsertAgainTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + ItemData item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Iron Sword"); item.ID = 1000; @@ -132,14 +132,14 @@ public: } void RetrieveAgainTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1000)); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.size() == 2); TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - Item_Struct item = hash[1000]; + ItemData item = hash[1000]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1000); @@ -149,8 +149,8 @@ public: } void InsertBeginTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + ItemData item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Bronze Sword"); item.ID = 0; @@ -165,7 +165,7 @@ public: } void RetrieveBeginTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1000)); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.exists(0)); @@ -173,7 +173,7 @@ public: TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - Item_Struct item = hash[1000]; + ItemData item = hash[1000]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1000); @@ -187,8 +187,8 @@ public: } void InsertEndTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + ItemData item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Jade Sword"); item.ID = 190000; @@ -204,7 +204,7 @@ public: } void RetrieveEndTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1000)); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.exists(0)); @@ -213,7 +213,7 @@ public: TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - Item_Struct item = hash[1000]; + ItemData item = hash[1000]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1000); diff --git a/tests/inventory_test.h b/tests/inventory_test.h new file mode 100644 index 000000000..da3f4892d --- /dev/null +++ b/tests/inventory_test.h @@ -0,0 +1,337 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __EQEMU_TESTS_INVENTORY_H +#define __EQEMU_TESTS_INVENTORY_H + +#include "cppunit/cpptest.h" +#include "../common/inventory.h" +#include + +class InventoryTest : public Test::Suite { + typedef void(InventoryTest::*TestFunction)(void); +public: + InventoryTest() : inv(1, 1, 1) { + InitContainer(); + InitArmor(); + InitAugment(); + InitStackable(); + InitInventory(); + TEST_ADD(InventoryTest::InventoryVerifyInitialItemsTest); + TEST_ADD(InventoryTest::InventoryCanEquipTest); + TEST_ADD(InventoryTest::InventorySwapGeneral1ToCursor); + TEST_ADD(InventoryTest::InventorySwapCursorToGeneral2); + TEST_ADD(InventoryTest::InventorySplitStackToCursor); + TEST_ADD(InventoryTest::InventoryStackCombine); + TEST_ADD(InventoryTest::InventorySplitStackToCursor2); + TEST_ADD(InventoryTest::InventoryStackCombine2); + } + + ~InventoryTest() { + } + +private: + void InitContainer() { + memset(&container, 0, sizeof(container)); + strcpy(container.Name, "Backpack"); + strcpy(container.IDFile, "IT64"); + container.ID = 1000; + container.BagSize = 3; + container.BagSlots = 8; + container.BagType = 5; + container.BagWR = 50; + container.ItemClass = 1; + container.Classes = 65535U; + container.Focus.Effect = -1; + container.ItemType = 11; + container.NoDrop = 1; + container.NoRent = 1; + container.Races = 131071U; + container.Size = 3; + container.SkillModType = -1; + container.Click.Effect = -1; + container.Weight = 30; + container.StackSize = 1; + container.Proc.Effect = -1; + container.Worn.Effect = -1; + container.Scroll.Effect = -1; + } + + void InitArmor() { + memset(&armor, 0, sizeof(armor)); + strcpy(armor.Name, "Cloth Shirt"); + strcpy(armor.IDFile, "IT64"); + armor.ID = 1001; + armor.AC = 4; + armor.AugSlotType[0] = 7; + for(int i = 0; i < 6; ++i) + armor.AugSlotVisible[i] = 1; + armor.Size = 2; + armor.Slots = 131072; + armor.Classes = 65535U; + armor.Focus.Effect = -1; + armor.ItemType = 10; + armor.NoDrop = 1; + armor.NoRent = 1; + armor.Races = 131071U; + armor.SkillModType = -1; + armor.Click.Effect = -1; + armor.Weight = 8; + armor.StackSize = 1; + armor.Proc.Effect = -1; + armor.Worn.Effect = -1; + armor.Scroll.Effect = -1; + } + + void InitAugment() { + memset(&augment, 0, sizeof(augment)); + strcpy(augment.Name, "Cloth Augment"); + strcpy(augment.IDFile, "IT64"); + augment.ID = 1002; + augment.AWis = 10; + augment.AInt = 10; + augment.AugType = 64; + augment.Slots = 2072574; + augment.Classes = 65535U; + augment.Focus.Effect = -1; + augment.ItemType = 54; + augment.NoDrop = 1; + augment.NoRent = 1; + augment.Races = 131071U; + augment.SkillModType = -1; + augment.Click.Effect = -1; + augment.Weight = 5; + augment.StackSize = 1; + augment.Size = 1; + augment.Proc.Effect = -1; + augment.Worn.Effect = -1; + augment.Scroll.Effect = -1; + } + + void InitStackable() { + memset(&stackable, 0, sizeof(stackable)); + strcpy(stackable.Name, "Stackable Item"); + strcpy(stackable.IDFile, "IT64"); + stackable.ID = 1003; + stackable.Classes = 65535U; + stackable.Focus.Effect = -1; + stackable.ItemType = 54; + stackable.NoDrop = 1; + stackable.NoRent = 1; + stackable.Races = 131071U; + stackable.SkillModType = -1; + stackable.Click.Effect = -1; + stackable.Weight = 5; + stackable.StackSize = 105; + stackable.Stackable = 1; + stackable.Size = 1; + stackable.Proc.Effect = -1; + stackable.Worn.Effect = -1; + stackable.Scroll.Effect = -1; + } + + void InitInventory() + { + EQEmu::ItemInstance::pointer m_bag(new EQEmu::ItemInstance(&container)); + EQEmu::ItemInstance::pointer m_armor(new EQEmu::ItemInstance(&armor)); + EQEmu::ItemInstance::pointer m_augment(new EQEmu::ItemInstance(&augment)); + EQEmu::ItemInstance::pointer m_stackable(new EQEmu::ItemInstance(&stackable, 100)); + inv.Put(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1), m_bag); + inv.Put(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1, 0), m_armor); + inv.Put(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1, 1), m_augment); + inv.Put(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1, 7), m_stackable); + } + + void InventoryVerifyInitialItemsTest() + { + auto m_bag = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1)); + TEST_ASSERT(m_bag); + TEST_ASSERT(m_bag->GetItem()); + TEST_ASSERT(m_bag->GetItem()->ID == 1000); + + auto m_armor = m_bag->Get(0); + TEST_ASSERT(m_armor); + TEST_ASSERT(m_armor->GetItem()); + TEST_ASSERT(m_armor->GetItem()->ID == 1001); + + auto m_augment = m_bag->Get(1); + TEST_ASSERT(m_augment); + TEST_ASSERT(m_augment->GetItem()); + TEST_ASSERT(m_augment->GetItem()->ID == 1002); + + auto m_stackable = m_bag->Get(7); + TEST_ASSERT(m_stackable); + TEST_ASSERT(m_stackable->GetItem()); + TEST_ASSERT(m_stackable->GetItem()->ID == 1003); + } + + void InventoryCanEquipTest() { + auto m_bag = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1)); + TEST_ASSERT(m_bag); + TEST_ASSERT(m_bag->GetItem()); + TEST_ASSERT(m_bag->GetItem()->ID == 1000); + + auto m_armor = m_bag->Get(0); + TEST_ASSERT(m_armor); + TEST_ASSERT(m_armor->GetItem()); + TEST_ASSERT(m_armor->GetItem()->ID == 1001); + + auto can_equip = inv.CanEquip(m_armor, EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotChest)); + TEST_ASSERT(can_equip); + + can_equip = inv.CanEquip(m_armor, EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotWaist)); + TEST_ASSERT(!can_equip); + + armor.Classes -= 1; + can_equip = inv.CanEquip(m_armor, EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotChest)); + TEST_ASSERT(!can_equip); + armor.Classes += 1; + + armor.Races -= 1; + can_equip = inv.CanEquip(m_armor, EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotChest)); + TEST_ASSERT(!can_equip); + armor.Races += 1; + } + + void InventorySwapGeneral1ToCursor() { + auto swap_result = inv.Swap(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1), + EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor), 0); + + TEST_ASSERT(swap_result == true); + + auto m_bag = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor)); + TEST_ASSERT(m_bag); + TEST_ASSERT(m_bag->GetItem()); + TEST_ASSERT(m_bag->GetItem()->ID == 1000); + + auto m_armor = m_bag->Get(0); + TEST_ASSERT(m_armor); + TEST_ASSERT(m_armor->GetItem()); + TEST_ASSERT(m_armor->GetItem()->ID == 1001); + + auto m_augment = m_bag->Get(1); + TEST_ASSERT(m_augment); + TEST_ASSERT(m_augment->GetItem()); + TEST_ASSERT(m_augment->GetItem()->ID == 1002); + + auto m_stackable = m_bag->Get(7); + TEST_ASSERT(m_stackable); + TEST_ASSERT(m_stackable->GetItem()); + TEST_ASSERT(m_stackable->GetItem()->ID == 1003); + } + + void InventorySwapCursorToGeneral2() { + auto swap_result = inv.Swap(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor), + EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2), 0); + + TEST_ASSERT(swap_result == true); + + auto m_bag = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2)); + TEST_ASSERT(m_bag); + TEST_ASSERT(m_bag->GetItem()); + TEST_ASSERT(m_bag->GetItem()->ID == 1000); + + auto m_armor = m_bag->Get(0); + TEST_ASSERT(m_armor); + TEST_ASSERT(m_armor->GetItem()); + TEST_ASSERT(m_armor->GetItem()->ID == 1001); + + auto m_augment = m_bag->Get(1); + TEST_ASSERT(m_augment); + TEST_ASSERT(m_augment->GetItem()); + TEST_ASSERT(m_augment->GetItem()->ID == 1002); + + auto m_stackable = m_bag->Get(7); + TEST_ASSERT(m_stackable); + TEST_ASSERT(m_stackable->GetItem()); + TEST_ASSERT(m_stackable->GetItem()->ID == 1003); + } + + void InventorySplitStackToCursor() { + auto swap_result = inv.Swap(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 7), + EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor), 10); + + TEST_ASSERT(swap_result == true); + + auto m_stackable_cursor = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor)); + auto m_stackable = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 7)); + + TEST_ASSERT(m_stackable_cursor); + TEST_ASSERT(m_stackable); + + TEST_ASSERT(m_stackable_cursor->GetCharges() == 10); + TEST_ASSERT(m_stackable->GetCharges() == 90); + } + + void InventoryStackCombine() { + auto swap_result = inv.Swap(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor), + EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 7), 0); + + TEST_ASSERT(swap_result == true); + + auto m_cursor = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor)); + auto m_stackable = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 7)); + + TEST_ASSERT(!m_cursor); + TEST_ASSERT(m_stackable); + + TEST_ASSERT(m_stackable->GetCharges() == 100); + } + + void InventorySplitStackToCursor2() { + EQEmu::ItemInstance::pointer m_stackable_i(new EQEmu::ItemInstance(&stackable, 10)); + inv.Put(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 8), m_stackable_i); + + auto swap_result = inv.Swap(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 8), + EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor), 0); + + TEST_ASSERT(swap_result == true); + + auto m_stackable_cursor = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor)); + auto m_stackable = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 8)); + + TEST_ASSERT(m_stackable_cursor); + TEST_ASSERT(!m_stackable); + + TEST_ASSERT(m_stackable_cursor->GetCharges() == 10); + } + + void InventoryStackCombine2() { + auto swap_result = inv.Swap(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor), + EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 7), 5); + + TEST_ASSERT(swap_result == true); + + auto m_cursor = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor)); + auto m_stackable = inv.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral2, 7)); + + TEST_ASSERT(m_cursor); + TEST_ASSERT(m_stackable); + + TEST_ASSERT(m_stackable->GetCharges() == 105); + TEST_ASSERT(m_cursor->GetCharges() == 5); + } + + EQEmu::Inventory inv; + ItemData container; + ItemData armor; + ItemData augment; + ItemData stackable; +}; + +#endif diff --git a/tests/main.cpp b/tests/main.cpp index d64dfead4..d9dad9da6 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -20,6 +20,7 @@ #include #include #include +#include "../common/eqemu_logsys.h" #include "memory_mapped_file_test.h" #include "ipc_mutex_test.h" #include "fixed_memory_test.h" @@ -29,6 +30,10 @@ #include "string_util_test.h" #include "data_verification_test.h" #include "skills_util_test.h" +#include "inventory_test.h" +#include "memory_buffer_test.h" + +EQEmuLogSys Log; int main() { try { @@ -44,7 +49,9 @@ int main() { tests.add(new StringUtilTest()); tests.add(new DataVerificationTest()); tests.add(new SkillsUtilsTest()); - tests.run(*output, true); + tests.add(new InventoryTest()); + tests.add(new MemoryBufferTest()); + tests.run(*output, false); } catch(...) { return -1; } diff --git a/tests/memory_buffer_test.h b/tests/memory_buffer_test.h new file mode 100644 index 000000000..0da7d01be --- /dev/null +++ b/tests/memory_buffer_test.h @@ -0,0 +1,605 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __EQEMU_TESTS_MEMORY_BUFFER_H +#define __EQEMU_TESTS_MEMORY_BUFFER_H + +#include "cppunit/cpptest.h" +#include "../common/memory_buffer.h" + +class MemoryBufferTest : public Test::Suite { + typedef void(MemoryBufferTest::*TestFunction)(void); +public: + MemoryBufferTest() { + TEST_ADD(MemoryBufferTest::WriteTest); + TEST_ADD(MemoryBufferTest::ReadTest); + TEST_ADD(MemoryBufferTest::ConvertTest); + TEST_ADD(MemoryBufferTest::ResizeTest); + 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) + } + + ~MemoryBufferTest() { + } + +private: + void WriteTest() { + uint8 a = 0; + uint16 b = 5 ; + uint32 c = 10; + uint64 d = 15; + std::string s2 = "test2"; + + mb.Write(a); + mb.Write(b); + mb.Write(c); + mb.Write(d); + mb.Write("test1"); + mb.Write(s2); + + TEST_ASSERT(mb.Size() == 27); + + uchar *data = (uchar*)mb; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(data[0] == 0); + TEST_ASSERT(data[1] == 5); + TEST_ASSERT(data[2] == 0); + TEST_ASSERT(data[3] == 10); + TEST_ASSERT(data[4] == 0); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 0); + TEST_ASSERT(data[7] == 15); + TEST_ASSERT(data[8] == 0); + TEST_ASSERT(data[9] == 0); + TEST_ASSERT(data[10] == 0); + TEST_ASSERT(data[11] == 0); + TEST_ASSERT(data[12] == 0); + TEST_ASSERT(data[13] == 0); + TEST_ASSERT(data[14] == 0); + TEST_ASSERT(data[15] == 't'); + TEST_ASSERT(data[16] == 'e'); + TEST_ASSERT(data[17] == 's'); + TEST_ASSERT(data[18] == 't'); + TEST_ASSERT(data[19] == '1'); + TEST_ASSERT(data[20] == 0); + TEST_ASSERT(data[21] == 't'); + TEST_ASSERT(data[22] == 'e'); + TEST_ASSERT(data[23] == 's'); + TEST_ASSERT(data[24] == 't'); + TEST_ASSERT(data[25] == '2'); + TEST_ASSERT(data[26] == 0); + } + + void ReadTest() { + uint8 a = mb.Read(); + uint16 b = mb.Read(); + uint32 c = mb.Read(); + uint64 d = mb.Read(); + std::string s1 = mb.ReadString(); + std::string s2 = mb.ReadString(); + + TEST_ASSERT(a == 0); + TEST_ASSERT(b == 5); + TEST_ASSERT(c == 10); + TEST_ASSERT(d == 15); + TEST_ASSERT(s1.compare("test1") == 0); + TEST_ASSERT(s2.compare("test2") == 0); + } + +#pragma pack(1) + struct ConvertStruct + { + uint8 a; + uint16 b; + uint32 c; + uint64 d; + char test1[6]; + char test2[6]; + }; +#pragma pack() + + void ConvertTest() + { + uchar *v1 = mb; + char *v2 = mb; + ConvertStruct *cs = (ConvertStruct*)mb; + + TEST_ASSERT(v1 != nullptr); + TEST_ASSERT(v1[0] == 0); + TEST_ASSERT(v1[1] == 5); + TEST_ASSERT(v1[2] == 0); + TEST_ASSERT(v1[3] == 10); + TEST_ASSERT(v1[4] == 0); + TEST_ASSERT(v1[5] == 0); + TEST_ASSERT(v1[6] == 0); + TEST_ASSERT(v1[7] == 15); + TEST_ASSERT(v1[8] == 0); + TEST_ASSERT(v1[9] == 0); + TEST_ASSERT(v1[10] == 0); + TEST_ASSERT(v1[11] == 0); + TEST_ASSERT(v1[12] == 0); + TEST_ASSERT(v1[13] == 0); + TEST_ASSERT(v1[14] == 0); + TEST_ASSERT(v1[15] == 't'); + TEST_ASSERT(v1[16] == 'e'); + TEST_ASSERT(v1[17] == 's'); + TEST_ASSERT(v1[18] == 't'); + TEST_ASSERT(v1[19] == '1'); + TEST_ASSERT(v1[20] == 0); + TEST_ASSERT(v1[21] == 't'); + TEST_ASSERT(v1[22] == 'e'); + TEST_ASSERT(v1[23] == 's'); + TEST_ASSERT(v1[24] == 't'); + TEST_ASSERT(v1[25] == '2'); + TEST_ASSERT(v1[26] == 0); + + TEST_ASSERT(v2 != nullptr); + TEST_ASSERT(v2[0] == 0); + TEST_ASSERT(v2[1] == 5); + TEST_ASSERT(v2[2] == 0); + TEST_ASSERT(v2[3] == 10); + TEST_ASSERT(v2[4] == 0); + TEST_ASSERT(v2[5] == 0); + TEST_ASSERT(v2[6] == 0); + TEST_ASSERT(v2[7] == 15); + TEST_ASSERT(v2[8] == 0); + TEST_ASSERT(v2[9] == 0); + TEST_ASSERT(v2[10] == 0); + TEST_ASSERT(v2[11] == 0); + TEST_ASSERT(v2[12] == 0); + TEST_ASSERT(v2[13] == 0); + TEST_ASSERT(v2[14] == 0); + TEST_ASSERT(v2[15] == 't'); + TEST_ASSERT(v2[16] == 'e'); + TEST_ASSERT(v2[17] == 's'); + TEST_ASSERT(v2[18] == 't'); + TEST_ASSERT(v2[19] == '1'); + TEST_ASSERT(v2[20] == 0); + TEST_ASSERT(v2[21] == 't'); + TEST_ASSERT(v2[22] == 'e'); + TEST_ASSERT(v2[23] == 's'); + TEST_ASSERT(v2[24] == 't'); + TEST_ASSERT(v2[25] == '2'); + TEST_ASSERT(v2[26] == 0); + + TEST_ASSERT(cs != nullptr); + TEST_ASSERT(cs->a == 0); + TEST_ASSERT(cs->b == 5); + TEST_ASSERT(cs->c == 10); + TEST_ASSERT(cs->d == 15); + TEST_ASSERT(strcmp(cs->test1, "test1") == 0); + TEST_ASSERT(strcmp(cs->test2, "test2") == 0); + } + + void ResizeTest() + { + mb.Resize(21); + TEST_ASSERT(mb.Size() == 21); + + mb.Resize(27); + uchar *data = (uchar*)mb; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(data[21] == 't'); + TEST_ASSERT(data[22] == 'e'); + TEST_ASSERT(data[23] == 's'); + TEST_ASSERT(data[24] == 't'); + TEST_ASSERT(data[25] == '2'); + TEST_ASSERT(data[26] == 0); + + mb.Resize(40); + data = (uchar*)mb; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(mb.Capacity() >= 40); + TEST_ASSERT(mb.Size() == 40); + TEST_ASSERT(data[0] == 0); + TEST_ASSERT(data[1] == 5); + TEST_ASSERT(data[2] == 0); + TEST_ASSERT(data[3] == 10); + TEST_ASSERT(data[4] == 0); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 0); + TEST_ASSERT(data[7] == 15); + TEST_ASSERT(data[8] == 0); + TEST_ASSERT(data[9] == 0); + TEST_ASSERT(data[10] == 0); + TEST_ASSERT(data[11] == 0); + TEST_ASSERT(data[12] == 0); + TEST_ASSERT(data[13] == 0); + TEST_ASSERT(data[14] == 0); + TEST_ASSERT(data[15] == 't'); + TEST_ASSERT(data[16] == 'e'); + TEST_ASSERT(data[17] == 's'); + TEST_ASSERT(data[18] == 't'); + TEST_ASSERT(data[19] == '1'); + TEST_ASSERT(data[20] == 0); + TEST_ASSERT(data[21] == 't'); + TEST_ASSERT(data[22] == 'e'); + TEST_ASSERT(data[23] == 's'); + TEST_ASSERT(data[24] == 't'); + TEST_ASSERT(data[25] == '2'); + TEST_ASSERT(data[26] == 0); + } + + void CopyTest() + { + EQEmu::MemoryBuffer mb2(mb); + + uchar *data = (uchar*)mb2; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(mb.Size() == 40); + TEST_ASSERT(data[0] == 0); + TEST_ASSERT(data[1] == 5); + TEST_ASSERT(data[2] == 0); + TEST_ASSERT(data[3] == 10); + TEST_ASSERT(data[4] == 0); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 0); + TEST_ASSERT(data[7] == 15); + TEST_ASSERT(data[8] == 0); + TEST_ASSERT(data[9] == 0); + TEST_ASSERT(data[10] == 0); + TEST_ASSERT(data[11] == 0); + TEST_ASSERT(data[12] == 0); + TEST_ASSERT(data[13] == 0); + TEST_ASSERT(data[14] == 0); + TEST_ASSERT(data[15] == 't'); + TEST_ASSERT(data[16] == 'e'); + TEST_ASSERT(data[17] == 's'); + TEST_ASSERT(data[18] == 't'); + TEST_ASSERT(data[19] == '1'); + TEST_ASSERT(data[20] == 0); + TEST_ASSERT(data[21] == 't'); + TEST_ASSERT(data[22] == 'e'); + TEST_ASSERT(data[23] == 's'); + TEST_ASSERT(data[24] == 't'); + TEST_ASSERT(data[25] == '2'); + TEST_ASSERT(data[26] == 0); + + data = (uchar*)mb; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(mb.Size() == 40); + TEST_ASSERT(data[0] == 0); + TEST_ASSERT(data[1] == 5); + TEST_ASSERT(data[2] == 0); + TEST_ASSERT(data[3] == 10); + TEST_ASSERT(data[4] == 0); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 0); + TEST_ASSERT(data[7] == 15); + TEST_ASSERT(data[8] == 0); + TEST_ASSERT(data[9] == 0); + TEST_ASSERT(data[10] == 0); + TEST_ASSERT(data[11] == 0); + TEST_ASSERT(data[12] == 0); + TEST_ASSERT(data[13] == 0); + TEST_ASSERT(data[14] == 0); + TEST_ASSERT(data[15] == 't'); + TEST_ASSERT(data[16] == 'e'); + TEST_ASSERT(data[17] == 's'); + TEST_ASSERT(data[18] == 't'); + TEST_ASSERT(data[19] == '1'); + TEST_ASSERT(data[20] == 0); + TEST_ASSERT(data[21] == 't'); + TEST_ASSERT(data[22] == 'e'); + TEST_ASSERT(data[23] == 's'); + TEST_ASSERT(data[24] == 't'); + TEST_ASSERT(data[25] == '2'); + TEST_ASSERT(data[26] == 0); + TEST_ASSERT((void*)mb != (void*)mb2); + } + + void AssignTest() + { + EQEmu::MemoryBuffer mb2 = mb; + + uchar *data = (uchar*)mb2; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(mb.Size() == 40); + TEST_ASSERT(data[0] == 0); + TEST_ASSERT(data[1] == 5); + TEST_ASSERT(data[2] == 0); + TEST_ASSERT(data[3] == 10); + TEST_ASSERT(data[4] == 0); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 0); + TEST_ASSERT(data[7] == 15); + TEST_ASSERT(data[8] == 0); + TEST_ASSERT(data[9] == 0); + TEST_ASSERT(data[10] == 0); + TEST_ASSERT(data[11] == 0); + TEST_ASSERT(data[12] == 0); + TEST_ASSERT(data[13] == 0); + TEST_ASSERT(data[14] == 0); + TEST_ASSERT(data[15] == 't'); + TEST_ASSERT(data[16] == 'e'); + TEST_ASSERT(data[17] == 's'); + TEST_ASSERT(data[18] == 't'); + TEST_ASSERT(data[19] == '1'); + TEST_ASSERT(data[20] == 0); + TEST_ASSERT(data[21] == 't'); + TEST_ASSERT(data[22] == 'e'); + TEST_ASSERT(data[23] == 's'); + TEST_ASSERT(data[24] == 't'); + TEST_ASSERT(data[25] == '2'); + TEST_ASSERT(data[26] == 0); + + data = (uchar*)mb; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(mb.Size() == 40); + TEST_ASSERT(data[0] == 0); + TEST_ASSERT(data[1] == 5); + TEST_ASSERT(data[2] == 0); + TEST_ASSERT(data[3] == 10); + TEST_ASSERT(data[4] == 0); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 0); + TEST_ASSERT(data[7] == 15); + TEST_ASSERT(data[8] == 0); + TEST_ASSERT(data[9] == 0); + TEST_ASSERT(data[10] == 0); + TEST_ASSERT(data[11] == 0); + TEST_ASSERT(data[12] == 0); + TEST_ASSERT(data[13] == 0); + TEST_ASSERT(data[14] == 0); + TEST_ASSERT(data[15] == 't'); + TEST_ASSERT(data[16] == 'e'); + TEST_ASSERT(data[17] == 's'); + TEST_ASSERT(data[18] == 't'); + TEST_ASSERT(data[19] == '1'); + TEST_ASSERT(data[20] == 0); + TEST_ASSERT(data[21] == 't'); + TEST_ASSERT(data[22] == 'e'); + TEST_ASSERT(data[23] == 's'); + TEST_ASSERT(data[24] == 't'); + TEST_ASSERT(data[25] == '2'); + TEST_ASSERT(data[26] == 0); + TEST_ASSERT((void*)mb != (void*)mb2); + } + + void MoveTest() + { + EQEmu::MemoryBuffer mb2 = std::move(mb); + uchar *data = (uchar*)mb; + uchar *data2 = (uchar*)mb2; + TEST_ASSERT(data == nullptr); + TEST_ASSERT(data2 != nullptr); + TEST_ASSERT(mb.Size() == 0); + TEST_ASSERT(mb2.Size() == 40); + TEST_ASSERT(data2[0] == 0); + TEST_ASSERT(data2[1] == 5); + TEST_ASSERT(data2[2] == 0); + TEST_ASSERT(data2[3] == 10); + TEST_ASSERT(data2[4] == 0); + TEST_ASSERT(data2[5] == 0); + TEST_ASSERT(data2[6] == 0); + TEST_ASSERT(data2[7] == 15); + TEST_ASSERT(data2[8] == 0); + TEST_ASSERT(data2[9] == 0); + TEST_ASSERT(data2[10] == 0); + TEST_ASSERT(data2[11] == 0); + TEST_ASSERT(data2[12] == 0); + TEST_ASSERT(data2[13] == 0); + TEST_ASSERT(data2[14] == 0); + TEST_ASSERT(data2[15] == 't'); + TEST_ASSERT(data2[16] == 'e'); + TEST_ASSERT(data2[17] == 's'); + TEST_ASSERT(data2[18] == 't'); + TEST_ASSERT(data2[19] == '1'); + TEST_ASSERT(data2[20] == 0); + TEST_ASSERT(data2[21] == 't'); + TEST_ASSERT(data2[22] == 'e'); + TEST_ASSERT(data2[23] == 's'); + TEST_ASSERT(data2[24] == 't'); + TEST_ASSERT(data2[25] == '2'); + TEST_ASSERT(data2[26] == 0); + + mb = std::move(mb2); + + data = (uchar*)mb; + data2 = (uchar*)mb2; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(data2 == nullptr); + TEST_ASSERT(mb.Size() == 40); + TEST_ASSERT(mb2.Size() == 0); + TEST_ASSERT(data[0] == 0); + TEST_ASSERT(data[1] == 5); + TEST_ASSERT(data[2] == 0); + TEST_ASSERT(data[3] == 10); + TEST_ASSERT(data[4] == 0); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 0); + TEST_ASSERT(data[7] == 15); + TEST_ASSERT(data[8] == 0); + TEST_ASSERT(data[9] == 0); + TEST_ASSERT(data[10] == 0); + TEST_ASSERT(data[11] == 0); + TEST_ASSERT(data[12] == 0); + TEST_ASSERT(data[13] == 0); + TEST_ASSERT(data[14] == 0); + TEST_ASSERT(data[15] == 't'); + TEST_ASSERT(data[16] == 'e'); + TEST_ASSERT(data[17] == 's'); + TEST_ASSERT(data[18] == 't'); + TEST_ASSERT(data[19] == '1'); + TEST_ASSERT(data[20] == 0); + TEST_ASSERT(data[21] == 't'); + TEST_ASSERT(data[22] == 'e'); + TEST_ASSERT(data[23] == 's'); + TEST_ASSERT(data[24] == 't'); + TEST_ASSERT(data[25] == '2'); + 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(); + uchar *data = (uchar*)mb; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(mb.Size() == 40); + TEST_ASSERT(data[0] == 0); + TEST_ASSERT(data[1] == 0); + TEST_ASSERT(data[2] == 0); + TEST_ASSERT(data[3] == 0); + TEST_ASSERT(data[4] == 0); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 0); + TEST_ASSERT(data[7] == 0); + TEST_ASSERT(data[8] == 0); + TEST_ASSERT(data[9] == 0); + TEST_ASSERT(data[10] == 0); + TEST_ASSERT(data[11] == 0); + TEST_ASSERT(data[12] == 0); + TEST_ASSERT(data[13] == 0); + TEST_ASSERT(data[14] == 0); + TEST_ASSERT(data[15] == 0); + TEST_ASSERT(data[16] == 0); + TEST_ASSERT(data[17] == 0); + TEST_ASSERT(data[18] == 0); + TEST_ASSERT(data[19] == 0); + TEST_ASSERT(data[20] == 0); + TEST_ASSERT(data[21] == 0); + TEST_ASSERT(data[22] == 0); + TEST_ASSERT(data[23] == 0); + TEST_ASSERT(data[24] == 0); + TEST_ASSERT(data[25] == 0); + TEST_ASSERT(data[26] == 0); + TEST_ASSERT(data[27] == 0); + TEST_ASSERT(data[28] == 0); + TEST_ASSERT(data[29] == 0); + TEST_ASSERT(data[30] == 0); + TEST_ASSERT(data[31] == 0); + TEST_ASSERT(data[32] == 0); + TEST_ASSERT(data[33] == 0); + TEST_ASSERT(data[34] == 0); + TEST_ASSERT(data[35] == 0); + TEST_ASSERT(data[36] == 0); + TEST_ASSERT(data[37] == 0); + TEST_ASSERT(data[38] == 0); + TEST_ASSERT(data[39] == 0); + } + + void ClearTest() + { + mb.Clear(); + TEST_ASSERT(!mb); + uchar *data = (uchar*)mb; + TEST_ASSERT(data == nullptr); + } + + void AddTest() + { + EQEmu::MemoryBuffer mb2; + EQEmu::MemoryBuffer mb3; + + mb2 += mb3; + + TEST_ASSERT(!mb2); + TEST_ASSERT(mb2.Size() == 0); + + mb2.Write("test1"); + mb2.Write("test2"); + + mb2 += mb3; + TEST_ASSERT(mb2); + TEST_ASSERT(mb2.Size() == 12); + + uchar *data = (uchar*)mb2; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(data[0] == 't'); + TEST_ASSERT(data[1] == 'e'); + TEST_ASSERT(data[2] == 's'); + TEST_ASSERT(data[3] == 't'); + TEST_ASSERT(data[4] == '1'); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 't'); + TEST_ASSERT(data[7] == 'e'); + TEST_ASSERT(data[8] == 's'); + TEST_ASSERT(data[9] == 't'); + TEST_ASSERT(data[10] == '2'); + TEST_ASSERT(data[11] == 0); + + mb3 += mb2; + TEST_ASSERT(mb3); + TEST_ASSERT(mb3.Size() == 12); + + data = (uchar*)mb3; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(data[0] == 't'); + TEST_ASSERT(data[1] == 'e'); + TEST_ASSERT(data[2] == 's'); + TEST_ASSERT(data[3] == 't'); + TEST_ASSERT(data[4] == '1'); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 't'); + TEST_ASSERT(data[7] == 'e'); + TEST_ASSERT(data[8] == 's'); + TEST_ASSERT(data[9] == 't'); + TEST_ASSERT(data[10] == '2'); + TEST_ASSERT(data[11] == 0); + + mb2.Clear(); + mb3.Clear(); + + mb2.Write("test1"); + mb3.Write("test2"); + + mb2 += mb3; + TEST_ASSERT(mb2); + TEST_ASSERT(mb2.Size() == 12); + + data = (uchar*)mb2; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(data[0] == 't'); + TEST_ASSERT(data[1] == 'e'); + TEST_ASSERT(data[2] == 's'); + TEST_ASSERT(data[3] == 't'); + TEST_ASSERT(data[4] == '1'); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 't'); + TEST_ASSERT(data[7] == 'e'); + TEST_ASSERT(data[8] == 's'); + TEST_ASSERT(data[9] == 't'); + TEST_ASSERT(data[10] == '2'); + TEST_ASSERT(data[11] == 0); + } + + EQEmu::MemoryBuffer mb; +}; + +#endif diff --git a/utils/sql/git/required/inv2_wip.sql b/utils/sql/git/required/inv2_wip.sql new file mode 100644 index 000000000..43879272d --- /dev/null +++ b/utils/sql/git/required/inv2_wip.sql @@ -0,0 +1,21 @@ +DROP TABLE IF EXISTS `character_inventory`; +CREATE TABLE `character_inventory` ( + `id` INT(10) UNSIGNED NOT NULL, + `type` SMALLINT(6) NOT NULL, + `slot` SMALLINT(6) NOT NULL, + `bag_index` SMALLINT(6) NOT NULL, + `aug_index` SMALLINT(6) NOT NULL, + `item_id` INT(10) UNSIGNED NOT NULL, + `charges` SMALLINT(6) NOT NULL, + `color` INT(10) UNSIGNED NOT NULL, + `attuned` TINYINT(3) UNSIGNED NOT NULL, + `custom_data` TEXT NOT NULL, + `ornament_icon` INT(10) UNSIGNED NOT NULL, + `ornament_idfile` INT(10) UNSIGNED NOT NULL, + `ornament_hero_model` INT(10) UNSIGNED NOT NULL, + `tracking_id` BIGINT(20) UNSIGNED NOT NULL, + PRIMARY KEY (`id`, `type`, `slot`, `bag_index`, `aug_index`), + INDEX `tracking_id` (`tracking_id`) +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB; diff --git a/world/client.cpp b/world/client.cpp index 26a69222b..7878c94fb 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1356,7 +1356,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) { PlayerProfile_Struct pp; ExtendedProfile_Struct ext; - Inventory inv; + InventoryOld inv; time_t bday = time(nullptr); char startzone[50]={0}; uint32 i; diff --git a/world/worlddb.cpp b/world/worlddb.cpp index b09758888..86d115233 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -97,7 +97,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou for (auto row = results.begin(); row != results.end(); ++row) { CharacterSelectEntry_Struct *cse = (CharacterSelectEntry_Struct *)buff_ptr; PlayerProfile_Struct pp; - Inventory inv; + InventoryOld inv; uint32 character_id = (uint32)atoi(row[0]); uint8 has_home = 0; uint8 has_bind = 0; @@ -219,12 +219,13 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou /* Load Inventory */ // If we ensure that the material data is updated appropriately, we can do away with inventory loads if (GetInventory(accountID, cse->Name, &inv)) { - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; const ItemInst* inst = nullptr; int16 invslot = 0; for (uint32 matslot = 0; matslot < _MaterialCount; matslot++) { - invslot = Inventory::CalcSlotFromMaterial(matslot); + invslot = InventoryOld::CalcSlotFromMaterial(matslot); + if (invslot == INVALID_INDEX) { continue; } inst = inv.GetItem(invslot); if (inst == nullptr) { continue; } diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 17cac7f62..42574bb09 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1268,15 +1268,8 @@ bool ZoneServer::Process() { UCSLink.SendPacket(pack); break; } - case ServerOP_QSSendQuery: case ServerOP_QueryServGeneric: case ServerOP_Speech: - case ServerOP_QSPlayerLogTrades: - case ServerOP_QSPlayerLogHandins: - case ServerOP_QSPlayerLogNPCKills: - case ServerOP_QSPlayerLogDeletes: - case ServerOP_QSPlayerLogMoves: - case ServerOP_QSPlayerLogMerchantTransactions: { QSLink.SendPacket(pack); break; diff --git a/zone/aa.cpp b/zone/aa.cpp index e81345086..ce0ad5477 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -879,7 +879,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) uint32 sitem = 0; sitem = CorpseToUse->GetWornItem(x); if(sitem){ - const Item_Struct * itm = database.GetItem(sitem); + const ItemData * itm = database.GetItem(sitem); npca->AddLootDrop(itm, &npca->itemlist, 1, 1, 127, true, true); } } @@ -1035,24 +1035,12 @@ void Client::BuyAA(AA_Action* action) */ /* Initial purchase of an AA ability */ - if (cur_level < 1){ + if (cur_level < 1) { Message(15, "You have gained the ability \"%s\" at a cost of %d ability %s.", aa2->name, real_cost, (real_cost>1) ? "points" : "point"); - - /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - } } /* Ranked purchase of an AA ability */ else{ Message(15, "You have improved %s %d at a cost of %d ability %s.", aa2->name, cur_level + 1, real_cost, (real_cost > 1) ? "points" : "point"); - - /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Ranked AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - } } SendAAStats(); diff --git a/zone/attack.cpp b/zone/attack.cpp index ffdb0ec41..32c3d74e0 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -55,7 +55,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w // Determine animation int type = 0; if (weapon && weapon->IsType(ItemClassCommon)) { - const Item_Struct* item = weapon->GetItem(); + const ItemData* item = weapon->GetItem(); Log.Out(Logs::Detail, Logs::Attack, "Weapon skill : %i", item->ItemType); @@ -806,9 +806,9 @@ int32 Client::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, //Returns the weapon damage against the input mob //if we cannot hit the mob with the current weapon we will get a value less than or equal to zero //Else we know we can hit. -//GetWeaponDamage(mob*, const Item_Struct*) is intended to be used for mobs or any other situation where we do not have a client inventory item +//GetWeaponDamage(mob*, const ItemData*) is intended to be used for mobs or any other situation where we do not have a client inventory item //GetWeaponDamage(mob*, const ItemInst*) is intended to be used for situations where we have a client inventory item -int Mob::GetWeaponDamage(Mob *against, const Item_Struct *weapon_item) { +int Mob::GetWeaponDamage(Mob *against, const ItemData *weapon_item) { int dmg = 0; int banedmg = 0; @@ -925,7 +925,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate //check for items being illegally attained if(weapon_item){ - const Item_Struct *mWeaponItem = weapon_item->GetItem(); + const ItemData *mWeaponItem = weapon_item->GetItem(); if(mWeaponItem){ if(mWeaponItem->ReqLevel > GetLevel()){ return 0; @@ -1267,7 +1267,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); + ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const ItemData*) nullptr ); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; @@ -1278,7 +1278,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b if (Hand == MainSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); + ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const ItemData*) nullptr ); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; @@ -1706,14 +1706,6 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att GoToDeath(); } - /* QS: PlayerLogDeaths */ - if (RuleB(QueryServ, PlayerLogDeaths)){ - const char * killer_name = ""; - if (killerMob && killerMob->GetCleanName()){ killer_name = killerMob->GetCleanName(); } - std::string event_desc = StringFormat("Died in zoneid:%i instid:%i by '%s', spellid:%i, damage:%i", this->GetZoneID(), this->GetInstanceID(), killer_name, spell, damage); - QServ->PlayerLogEvent(Player_Log_Deaths, this->CharacterID(), event_desc); - } - parse->EventPlayer(EVENT_DEATH_COMPLETE, this, buffer, 0); return true; } @@ -1760,7 +1752,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool } //figure out what weapon they are using, if any - const Item_Struct* weapon = nullptr; + const ItemData* weapon = nullptr; if (Hand == MainPrimary && equipment[MainPrimary] > 0) weapon = database.GetItem(equipment[MainPrimary]); else if (equipment[MainSecondary]) @@ -2180,27 +2172,6 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack PlayerCount++; } } - - // QueryServ Logging - Raid Kills - if(RuleB(QueryServ, PlayerLogNPCKills)){ - ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); - PlayerCount = 0; - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; - QS->s1.NPCID = this->GetNPCTypeID(); - QS->s1.ZoneID = this->GetZoneID(); - QS->s1.Type = 2; // Raid Fight - for (int i = 0; i < MAX_RAID_MEMBERS; i++) { - if (kr->members[i].member != nullptr && kr->members[i].member->IsClient()) { // If Group Member is Client - Client *c = kr->members[i].member; - QS->Chars[PlayerCount].char_id = c->CharacterID(); - PlayerCount++; - } - } - worldserver.SendPacket(pack); // Send Packet to World - safe_delete(pack); - } - // End QueryServ Logging - } else if (give_exp_client->IsGrouped() && kg != nullptr) { @@ -2227,26 +2198,6 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack PlayerCount++; } } - - // QueryServ Logging - Group Kills - if(RuleB(QueryServ, PlayerLogNPCKills)){ - ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); - PlayerCount = 0; - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; - QS->s1.NPCID = this->GetNPCTypeID(); - QS->s1.ZoneID = this->GetZoneID(); - QS->s1.Type = 1; // Group Fight - for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (kg->members[i] != nullptr && kg->members[i]->IsClient()) { // If Group Member is Client - Client *c = kg->members[i]->CastToClient(); - QS->Chars[PlayerCount].char_id = c->CharacterID(); - PlayerCount++; - } - } - worldserver.SendPacket(pack); // Send Packet to World - safe_delete(pack); - } - // End QueryServ Logging } else { @@ -2273,21 +2224,6 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack if(RuleB(TaskSystem, EnableTaskSystem)) give_exp_client->UpdateTasksOnKill(GetNPCTypeID()); - - // QueryServ Logging - Solo - if(RuleB(QueryServ, PlayerLogNPCKills)){ - ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1)); - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; - QS->s1.NPCID = this->GetNPCTypeID(); - QS->s1.ZoneID = this->GetZoneID(); - QS->s1.Type = 0; // Solo Fight - Client *c = give_exp_client; - QS->Chars[0].char_id = c->CharacterID(); - PlayerCount++; - worldserver.SendPacket(pack); // Send Packet to World - safe_delete(pack); - } - // End QueryServ Logging } } @@ -2663,7 +2599,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) { } } -uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) +uint8 Mob::GetWeaponDamageBonus( const ItemData *Weapon ) { // This function calculates and returns the damage bonus for the weapon identified by the parameter "Weapon". // Modified 9/21/2008 by Cantus @@ -3985,12 +3921,12 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { } if(!weapon_g) { - TrySpellProc(nullptr, (const Item_Struct*)nullptr, on); + TrySpellProc(nullptr, (const ItemData*)nullptr, on); return; } if(!weapon_g->IsType(ItemClassCommon)) { - TrySpellProc(nullptr, (const Item_Struct*)nullptr, on); + TrySpellProc(nullptr, (const ItemData*)nullptr, on); return; } @@ -4003,7 +3939,7 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { return; } -void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand) +void Mob::TryWeaponProc(const ItemInst *inst, const ItemData *weapon, Mob *on, uint16 hand) { if (!weapon) @@ -4056,7 +3992,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on const ItemInst *aug_i = inst->GetAugment(r); if (!aug_i) // no aug, try next slot! continue; - const Item_Struct *aug = aug_i->GetItem(); + const ItemData *aug = aug_i->GetItem(); if (!aug) continue; @@ -4086,7 +4022,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on return; } -void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand) +void Mob::TrySpellProc(const ItemInst *inst, const ItemData *weapon, Mob *on, uint16 hand) { float ProcBonus = static_cast(spellbonuses.SpellProcChance + itembonuses.SpellProcChance + aabonuses.SpellProcChance); @@ -4906,7 +4842,7 @@ void Client::SetAttackTimer() attack_timer.SetAtTrigger(4000, true); Timer *TimerToUse = nullptr; - const Item_Struct *PrimaryWeapon = nullptr; + const ItemData *PrimaryWeapon = nullptr; for (int i = MainRange; i <= MainSecondary; i++) { //pick a timer @@ -4919,7 +4855,7 @@ void Client::SetAttackTimer() else //invalid slot (hands will always hit this) continue; - const Item_Struct *ItemToUse = nullptr; + const ItemData *ItemToUse = nullptr; //find our item ItemInst *ci = GetInv().GetItem(i); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 5dd7440f6..819c83edb 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -153,7 +153,7 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { AddItemBonuses(inst, newbon); //These are given special flags due to how often they are checked for various spell effects. - const Item_Struct *item = inst->GetItem(); + const ItemData *item = inst->GetItem(); if (i == MainSecondary && (item && item->ItemType == ItemTypeShield)) SetShieldEquiped(true); else if (i == MainPrimary && (item && item->ItemType == ItemType2HBlunt)) @@ -216,7 +216,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu return; } - const Item_Struct *item = inst->GetItem(); + const ItemData *item = inst->GetItem(); if(!isTribute && !inst->IsEquipable(GetBaseRace(),GetClass())) { @@ -572,7 +572,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool if(inst->GetAugmentType()==0 && isAug == true) return; - const Item_Struct *item = inst->GetItem(); + const ItemData *item = inst->GetItem(); if(!inst->IsEquipable(GetBaseRace(),GetClass())) return; @@ -604,7 +604,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { break; const ItemInst* inst = GetInv().GetItem(i); if (inst && inst->GetItem() && inst->IsType(ItemClassCommon)) { - const Item_Struct *item=inst->GetItem(); + const ItemData *item=inst->GetItem(); if (item->ItemType == ItemTypeFood && !food) food = true; else if (item->ItemType == ItemTypeDrink && !drink) @@ -620,7 +620,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { break; const ItemInst* inst = GetInv().GetItem(i); if (inst && inst->GetItem() && inst->IsType(ItemClassCommon)) { - const Item_Struct *item=inst->GetItem(); + const ItemData *item=inst->GetItem(); if (item->ItemType == ItemTypeFood && !food) food = true; else if (item->ItemType == ItemTypeDrink && !drink) @@ -3056,7 +3056,7 @@ void NPC::CalcItemBonuses(StatBonuses *newbon) if(newbon){ for(int i = 0; i < EmuConstants::EQUIPMENT_SIZE; i++){ - const Item_Struct *cur = database.GetItem(equipment[i]); + const ItemData *cur = database.GetItem(equipment[i]); if(cur){ //basic stats newbon->AC += cur->AC; @@ -3176,7 +3176,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { // TEST CODE: test for bazaar trader crashing with charm items if (Trader) if (i >= EmuConstants::GENERAL_BAGS_BEGIN && i <= EmuConstants::GENERAL_BAGS_END) { - ItemInst* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); + ItemInst* parent_item = m_inv.GetItem(InventoryOld::CalcSlotId(i)); if (parent_item && parent_item->GetItem()->ID == 17899) // trader satchel continue; } @@ -3269,7 +3269,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { // TEST CODE: test for bazaar trader crashing with charm items if (Trader) if (i >= EmuConstants::GENERAL_BAGS_BEGIN && i <= EmuConstants::GENERAL_BAGS_END) { - ItemInst* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); + ItemInst* parent_item = m_inv.GetItem(InventoryOld::CalcSlotId(i)); if (parent_item && parent_item->GetItem()->ID == 17899) // trader satchel continue; } diff --git a/zone/bot.cpp b/zone/bot.cpp index 3a9d46e97..536b661f8 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -5,6 +5,7 @@ #include "doors.h" #include "quest_parser_collection.h" #include "../common/string_util.h" +#include "../common/item.h" extern volatile bool ZoneLoaded; @@ -212,8 +213,8 @@ uint32 Bot::GetBotArcheryRange() { if (!range_inst || !ammo_inst) return 0; - const Item_Struct *range_item = range_inst->GetItem(); - const Item_Struct *ammo_item = ammo_inst->GetItem(); + const ItemData *range_item = range_inst->GetItem(); + const ItemData *ammo_item = ammo_inst->GetItem(); if (!range_item || !ammo_item || range_item->ItemType != ItemTypeBow || ammo_item->ItemType != ItemTypeArrow) return 0; @@ -2623,12 +2624,12 @@ void Bot::BotRangedAttack(Mob* other) { } ItemInst* rangedItem = GetBotItem(MainRange); - const Item_Struct* RangeWeapon = 0; + const ItemData* RangeWeapon = 0; if(rangedItem) RangeWeapon = rangedItem->GetItem(); ItemInst* ammoItem = GetBotItem(MainAmmo); - const Item_Struct* Ammo = 0; + const ItemData* Ammo = 0; if(ammoItem) Ammo = ammoItem->GetItem(); @@ -2735,7 +2736,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes int32 min_hit = 1; int32 max_hit = ((2 * weapon_damage * GetDamageTable(skillinuse)) / 100); if(GetLevel() >= 28 && IsWarriorClass()) { - int ucDamageBonus = GetWeaponDamageBonus((const Item_Struct*) nullptr); + int ucDamageBonus = GetWeaponDamageBonus((const ItemData*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -2776,7 +2777,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if(skillinuse == SkillBash){ const ItemInst* inst = GetBotItem(MainSecondary); - const Item_Struct* botweapon = 0; + const ItemData* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -2836,7 +2837,7 @@ void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) if (item_slot >= EmuConstants::EQUIPMENT_BEGIN){ const ItemInst* inst = GetBotItem(item_slot); - const Item_Struct* botweapon = 0; + const ItemData* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -3190,7 +3191,7 @@ void Bot::AI_Process() { //now off hand if(GetTarget() && attack_dw_timer.Check() && CanThisClassDualWield()) { const ItemInst* instweapon = GetBotItem(MainSecondary); - const Item_Struct* weapon = 0; + const ItemData* weapon = 0; //can only dual wield without a weapon if you're a monk if(instweapon || (botClass == MONK)) { if(instweapon) @@ -3596,8 +3597,9 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) { uint8 materialFromSlot = 0xFF; for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { itemID = GetBotItemBySlot(i); - if(itemID != 0) { - materialFromSlot = Inventory::CalcMaterialFromSlot(i); + if(itemID != 0) { + materialFromSlot = InventoryOld::CalcMaterialFromSlot(i); + if(materialFromSlot != 0xFF) this->SendWearChange(materialFromSlot); } @@ -3645,7 +3647,7 @@ void Bot::RemoveBotItemBySlot(uint32 slotID, std::string *errorMessage) { } // Retrieves all the inventory records from the database for this bot. -void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { +void Bot::GetBotItems(std::string* errorMessage, InventoryOld &inv) { if(this->GetBotID() == 0) return; @@ -3671,7 +3673,8 @@ void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) { aug[3] = (uint32)atoul(row[7]); aug[4] = (uint32)atoul(row[8]); bool instnodrop = (row[9] && (uint16)atoi(row[9])) ? true : false; - ItemInst* inst = database.CreateItem(item_id, charges, aug[0], aug[1], aug[2], aug[3], aug[4]); + + ItemInst* inst = database.CreateItemOld(item_id, charges, aug[0], aug[1], aug[2], aug[3], aug[4]); if (!inst) { Log.Out(Logs::General, Logs::Error, "Warning: botid %i has an invalid item_id %i in inventory slot %i", this->GetBotID(), item_id, slot_id); continue; @@ -3805,7 +3808,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.light = m_Light.Type.Active; ns->spawn.helm = (GetShowHelm() ? helmtexture : 0); //0xFF; ns->spawn.equip_chest2 = texture; //0xFF; - const Item_Struct* item = 0; + const ItemData* item = 0; const ItemInst* inst = 0; uint32 spawnedbotid = 0; spawnedbotid = this->GetBotID(); @@ -4421,7 +4424,7 @@ ItemInst* Bot::GetBotItem(uint32 slotID) { // Adds the specified item it bot to the NPC equipment array and to the bot inventory collection. void Bot::BotAddEquipItem(int slot, uint32 id) { if(slot > 0 && id > 0) { - uint8 materialFromSlot = Inventory::CalcMaterialFromSlot(slot); + uint8 materialFromSlot = InventoryOld::CalcMaterialFromSlot(slot); if(materialFromSlot != _MaterialInvalid) { equipment[slot] = id; // npc has more than just material slots. Valid material should mean valid inventory index @@ -4437,7 +4440,7 @@ void Bot::BotAddEquipItem(int slot, uint32 id) { // Erases the specified item from bot the NPC equipment array and from the bot inventory collection. void Bot::BotRemoveEquipItem(int slot) { if(slot > 0) { - uint8 materialFromSlot = Inventory::CalcMaterialFromSlot(slot); + uint8 materialFromSlot = InventoryOld::CalcMaterialFromSlot(slot); if(materialFromSlot != _MaterialInvalid) { equipment[slot] = 0; // npc has more than just material slots. Valid material should mean valid inventory index @@ -4903,7 +4906,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli bool UpdateClient = false; bool already_returned = false; - Inventory& clientInventory = client->GetInv(); + InventoryOld& clientInventory = client->GetInv(); const ItemInst* inst = clientInventory[i]; if(inst) { items[i] = inst->GetItem()->ID; @@ -4916,7 +4919,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli //EQoffline: will give the items to the bots and change the bot stats if(inst && (GetBotOwner() == client->CastToMob()) && !IsEngaged()) { std::string TempErrorMessage; - const Item_Struct* mWeaponItem = inst->GetItem(); + const ItemData* mWeaponItem = inst->GetItem(); bool failedLoreCheck = false; for (int m = AUG_BEGIN; m GetAugment(m); @@ -5095,7 +5098,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } - const Item_Struct* item2 = 0; + const ItemData* item2 = 0; for(int y = beginSlotID; y <= endSlotID; ++y) { item2 = database.GetItem(items[y]); if(item2) { @@ -5335,7 +5338,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if(Hand == MainPrimary && GetLevel() >= 28 && IsWarriorClass()) { // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr); + ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const ItemData*) nullptr ); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -5344,7 +5347,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. if (Hand==MainSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr); + ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const ItemData*) nullptr ); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -5809,8 +5812,8 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[bottype]) { - const Item_Struct* TempItem = 0; - const Item_Struct* UsedItem = 0; + const ItemData* TempItem = 0; + const ItemData* UsedItem = 0; const ItemInst* TempInst = 0; uint16 UsedFocusID = 0; int32 Total = 0; @@ -5845,8 +5848,9 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { for (int y = AUG_BEGIN; y < EmuConstants::ITEM_COMMON_SIZE; ++y) { ItemInst *aug = nullptr; aug = ins->GetAugment(y); - if(aug) { - const Item_Struct* TempItemAug = aug->GetItem(); + if(aug) + { + const ItemData* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { focus_max = CalcBotFocusEffect(bottype, TempItemAug->Focus.Effect, spell_id, true); @@ -6498,7 +6502,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if(skill == SkillBash) { const ItemInst* inst = GetBotItem(MainSecondary); - const Item_Struct* botweapon = 0; + const ItemData* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -6565,7 +6569,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { bool bIsBehind = false; bool bCanFrontalBS = false; const ItemInst* inst = GetBotItem(MainPrimary); - const Item_Struct* botpiercer = nullptr; + const ItemData* botpiercer = nullptr; if(inst) botpiercer = inst->GetItem(); @@ -7002,7 +7006,7 @@ bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined) { void Bot::EquipBot(std::string* errorMessage) { GetBotItems(errorMessage, m_inv); const ItemInst* inst = 0; - const Item_Struct* item = 0; + const ItemData* item = 0; for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { @@ -7149,7 +7153,8 @@ void Bot::SetAttackTimer() { float haste_mod = (GetHaste() * 0.01f); attack_timer.SetAtTrigger(4000, true); Timer* TimerToUse = nullptr; - const Item_Struct* PrimaryWeapon = nullptr; + const ItemData* PrimaryWeapon = nullptr; + for (int i = MainRange; i <= MainSecondary; i++) { if (i == MainPrimary) TimerToUse = &attack_timer; @@ -7160,7 +7165,7 @@ void Bot::SetAttackTimer() { else continue; - const Item_Struct* ItemToUse = nullptr; + const ItemData* ItemToUse = nullptr; ItemInst* ci = GetBotItem(i); if (ci) ItemToUse = ci->GetItem(); @@ -8918,7 +8923,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { insr->TargetID = inspectedBot->GetNPCTypeID(); insr->playerid = inspectedBot->GetID(); - const Item_Struct* item = 0; + const ItemData* item = 0; const ItemInst* inst = 0; // Modded to display power source items (will only show up on SoF+ client inspect windows though.) @@ -8970,7 +8975,8 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { void Bot::CalcItemBonuses(StatBonuses* newbon) { - const Item_Struct* itemtmp = 0; + memset(&itembonuses, 0, sizeof(StatBonuses)); + const ItemData* itemtmp = 0; for (int i = EmuConstants::EQUIPMENT_BEGIN; i <= (EmuConstants::EQUIPMENT_END + 1); ++i) { const ItemInst* item = GetBotItem((i == 22 ? 9999 : i)); @@ -9001,7 +9007,7 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, return; } - const Item_Struct *item = inst->GetItem(); + const ItemData *item = inst->GetItem(); if(!isTribute && !inst->IsEquipable(GetBaseRace(),GetClass())) { @@ -9370,7 +9376,7 @@ void Bot::CalcBotStats(bool showtext) { } } -bool Bot::CheckLoreConflict(const Item_Struct* item) { +bool Bot::CheckLoreConflict(const ItemData* item) { if (!item || !(item->LoreFlag)) return false; @@ -9530,7 +9536,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { return; for (int i = 0; i < 7; i++) { - uint8 slotmaterial = Inventory::CalcMaterialFromSlot((uint8)slots[i]); + uint8 slotmaterial = InventoryOld::CalcMaterialFromSlot((uint8)slots[i]); c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); } } else { @@ -9539,10 +9545,9 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { if (!results.Success()) return; - uint8 slotmaterial = Inventory::CalcMaterialFromSlot(setslot); + uint8 slotmaterial = InventoryOld::CalcMaterialFromSlot(setslot); c->GetTarget()->CastToBot()->SendWearChange(slotmaterial); } - } else { c->Message(15, "You must target a bot you own to do this."); @@ -9938,7 +9943,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; const ItemInst* inst = nullptr; - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; bool is2Hweapon = false; std::string item_link; @@ -10003,7 +10008,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; - const Item_Struct* itm = nullptr; + const ItemData* itm = nullptr; const ItemInst* itminst = c->GetTarget()->CastToBot()->GetBotItem(slotId); if(itminst) itm = itminst->GetItem(); @@ -13512,7 +13517,9 @@ uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { uint32 Bot::GetEquipmentColor(uint8 material_slot) const { int16 slotid = 0; uint32 botid = this->GetBotID(); - slotid = Inventory::CalcSlotFromMaterial(material_slot); + + //Translate code slot # to DB slot # + slotid = InventoryOld::CalcSlotFromMaterial(material_slot); if (slotid == INVALID_INDEX) return 0; @@ -13545,7 +13552,7 @@ int Bot::GetRawACNoShield(int &shield_ac) { } uint32 Bot::CalcCurrentWeight() { - const Item_Struct* TempItem = 0; + const ItemData* TempItem = 0; ItemInst* inst; uint32 Total = 0; for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { @@ -14031,4 +14038,4 @@ void Bot::BotHealRotationsClear(Client* c) { } } -#endif \ No newline at end of file +#endif diff --git a/zone/bot.h b/zone/bot.h index 19968c394..c81a22a09 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -333,7 +333,7 @@ public: void BotTradeSwapItem(Client* client, int16 lootSlot, const ItemInst* inst, const ItemInst* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap = true); void BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true); void EquipBot(std::string* errorMessage); - bool CheckLoreConflict(const Item_Struct* item); + bool CheckLoreConflict(const ItemData* item); uint32 GetEquipmentColor(uint8 material_slot) const; virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); } @@ -584,7 +584,7 @@ private: bool _petChooser; uint8 _petChooserID; bool berserk; - Inventory m_inv; + InventoryOld m_inv; double _lastTotalPlayTime; time_t _startTotalPlayTime; Mob* _previousTarget; @@ -657,7 +657,7 @@ private: void SetBotID(uint32 botID); // Private "Inventory" Methods - void GetBotItems(std::string* errorMessage, Inventory &inv); + void GetBotItems(std::string* errorMessage, InventoryOld &inv); void BotRemoveEquipItem(int slot); void BotAddEquipItem(int slot, uint32 id); uint32 GetBotItemBySlot(uint32 slotID); diff --git a/zone/client.cpp b/zone/client.cpp index e4d49e979..96b53647f 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2113,80 +2113,19 @@ bool Client::TakeMoneyFromPP(uint64 copper, bool updateclient) { } } -void Client::AddMoneyToPP(uint64 copper, bool updateclient){ - uint64 tmp; - uint64 tmp2; - tmp = copper; +void Client::AddMoneyToPP(uint64 copper, bool updateclient) { - /* Add Amount of Platinum */ - tmp2 = tmp/1000; - int32 new_val = m_pp.platinum + tmp2; - if(new_val < 0) { m_pp.platinum = 0; } - else { m_pp.platinum = m_pp.platinum + tmp2; } - tmp-=tmp2*1000; - - //if (updateclient) - // SendClientMoneyUpdate(3,tmp2); - - /* Add Amount of Gold */ - tmp2 = tmp/100; - new_val = m_pp.gold + tmp2; - if(new_val < 0) { m_pp.gold = 0; } - else { m_pp.gold = m_pp.gold + tmp2; } - - tmp-=tmp2*100; - //if (updateclient) - // SendClientMoneyUpdate(2,tmp2); - - /* Add Amount of Silver */ - tmp2 = tmp/10; - new_val = m_pp.silver + tmp2; - if(new_val < 0) { - m_pp.silver = 0; - } else { - m_pp.silver = m_pp.silver + tmp2; - } - tmp-=tmp2*10; - //if (updateclient) - // SendClientMoneyUpdate(1,tmp2); - - // Add Copper - //tmp = tmp - (tmp2* 10); - //if (updateclient) - // SendClientMoneyUpdate(0,tmp); - tmp2 = tmp; - new_val = m_pp.copper + tmp2; - if(new_val < 0) { - m_pp.copper = 0; - } else { - m_pp.copper = m_pp.copper + tmp2; - } - - - //send them all at once, since the above code stopped working. - if(updateclient) - SendMoneyUpdate(); - - RecalcWeight(); - - SaveCurrency(); - - Log.Out(Logs::General, Logs::None, "Client::AddMoneyToPP() %s should have: plat:%i gold:%i silver:%i copper:%i", GetName(), m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper); + uint64 plat = copper / 1000; + copper -= plat * 1000; + uint64 gold = copper / 100; + copper -= gold * 100; + uint64 silver = copper / 10; + copper -= silver * 10; + AddMoneyToPP(copper, silver, gold, plat, updateclient); } -void Client::EVENT_ITEM_ScriptStopReturn(){ - /* Set a timestamp in an entity variable for plugin check_handin.pl in return_items - This will stopgap players from items being returned if global_npc.pl has a catch all return_items - */ - struct timeval read_time; - char buffer[50]; - gettimeofday(&read_time, 0); - sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec); - this->SetEntityVariable("Stop_Return", buffer); -} - -void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool updateclient){ - this->EVENT_ITEM_ScriptStopReturn(); +void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, bool updateclient) { + ItemScriptStopReturn(); int32 new_value = m_pp.platinum + platinum; if(new_value >= 0 && new_value > m_pp.platinum) @@ -2209,11 +2148,17 @@ void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 plat RecalcWeight(); SaveCurrency(); +} -#if (EQDEBUG>=5) - Log.Out(Logs::General, Logs::None, "Client::AddMoneyToPP() %s should have: plat:%i gold:%i silver:%i copper:%i", - GetName(), m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper); -#endif +void Client::ItemScriptStopReturn() { + /* Set a timestamp in an entity variable for plugin check_handin.pl in return_items + This will stopgap players from items being returned if global_npc.pl has a catch all return_items + */ + struct timeval read_time; + char buffer[50]; + gettimeofday(&read_time, 0); + sprintf(buffer, "%li.%li \n", read_time.tv_sec, read_time.tv_usec); + SetEntityVariable("Stop_Return", buffer); } void Client::SendMoneyUpdate() { @@ -2515,33 +2460,34 @@ void Client::SetFeigned(bool in_feigned) { feigned=in_feigned; } -void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const Item_Struct* item, bool buying) +void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const ItemData* item, bool buying) { - if(!player || !merchant || !item) - return; - - std::string LogText = "Qty: "; - - char Buffer[255]; - memset(Buffer, 0, sizeof(Buffer)); - - snprintf(Buffer, sizeof(Buffer)-1, "%3i", quantity); - LogText += Buffer; - snprintf(Buffer, sizeof(Buffer)-1, "%10i", price); - LogText += " TotalValue: "; - LogText += Buffer; - snprintf(Buffer, sizeof(Buffer)-1, " ItemID: %7i", item->ID); - LogText += Buffer; - LogText += " "; - snprintf(Buffer, sizeof(Buffer)-1, " %s", item->Name); - LogText += Buffer; - - if (buying==true) { - database.logevents(player->AccountName(),player->AccountID(),player->admin,player->GetName(),merchant->GetName(),"Buying from Merchant",LogText.c_str(),2); - } - else { - database.logevents(player->AccountName(),player->AccountID(),player->admin,player->GetName(),merchant->GetName(),"Selling to Merchant",LogText.c_str(),3); - } + //Inv2 redo or remove + //if(!player || !merchant || !item) + // return; + // + //std::string LogText = "Qty: "; + // + //char Buffer[255]; + //memset(Buffer, 0, sizeof(Buffer)); + // + //snprintf(Buffer, sizeof(Buffer)-1, "%3i", quantity); + //LogText += Buffer; + //snprintf(Buffer, sizeof(Buffer)-1, "%10i", price); + //LogText += " TotalValue: "; + //LogText += Buffer; + //snprintf(Buffer, sizeof(Buffer)-1, " ItemID: %7i", item->ID); + //LogText += Buffer; + //LogText += " "; + //snprintf(Buffer, sizeof(Buffer)-1, " %s", item->Name); + //LogText += Buffer; + // + //if (buying==true) { + // database.logevents(player->AccountName(),player->AccountID(),player->admin,player->GetName(),merchant->GetName(),"Buying from Merchant",LogText.c_str(),2); + //} + //else { + // database.logevents(player->AccountName(),player->AccountID(),player->admin,player->GetName(),merchant->GetName(),"Selling to Merchant",LogText.c_str(),3); + //} } bool Client::BindWound(Mob* bindmob, bool start, bool fail){ @@ -2709,10 +2655,10 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){ } void Client::SetMaterial(int16 in_slot, uint32 item_id) { - const Item_Struct* item = database.GetItem(item_id); + const ItemData* item = database.GetItem(item_id); if (item && (item->ItemClass==ItemClassCommon)) { - uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); + uint8 matslot = InventoryOld::CalcMaterialFromSlot(in_slot); if (matslot != _MaterialInvalid) { m_pp.item_material[matslot] = GetEquipmentMaterial(matslot); @@ -3054,7 +3000,7 @@ void Client::SetTint(int16 in_slot, uint32 color) { // Still need to reconcile bracer01 versus bracer02 void Client::SetTint(int16 in_slot, Color_Struct& color) { - uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); + uint8 matslot = InventoryOld::CalcMaterialFromSlot(in_slot); if (matslot != _MaterialInvalid) { m_pp.item_tint[matslot].Color = color.Color; @@ -3755,7 +3701,7 @@ void Client::SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID) { return; } -void Client::SendPickPocketResponse(Mob *from, uint32 amt, int type, const Item_Struct* item){ +void Client::SendPickPocketResponse(Mob *from, uint32 amt, int type, const ItemData* item){ EQApplicationPacket* outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); sPickPocket_Struct* pick_out = (sPickPocket_Struct*) outapp->pBuffer; pick_out->coin = amt; @@ -3927,7 +3873,7 @@ bool Client::KeyRingCheck(uint32 item_id) void Client::KeyRingList() { Message(4,"Keys on Keyring:"); - const Item_Struct *item = 0; + const ItemData *item = 0; for(std::list::iterator iter = keyring.begin(); iter != keyring.end(); ++iter) @@ -5427,7 +5373,7 @@ bool Client::TryReward(uint32 claim_id) } auto &ivr = (*iter); - ItemInst *claim = database.CreateItem(ivr.items[0].item_id, ivr.items[0].charges); + ItemInst *claim = database.CreateItemOld(ivr.items[0].item_id, ivr.items[0].charges); if (!claim) { Save(); return true; @@ -5437,7 +5383,7 @@ bool Client::TryReward(uint32 claim_id) for (int y = 1; y < 8; y++) if (ivr.items[y].item_id && claim->GetItem()->ItemClass == 1) { - ItemInst *item_temp = database.CreateItem(ivr.items[y].item_id, ivr.items[y].charges); + ItemInst *item_temp = database.CreateItemOld(ivr.items[y].item_id, ivr.items[y].charges); if (item_temp) { if (CheckLoreConflict(item_temp->GetItem())) { lore_conflict = true; @@ -5697,7 +5643,7 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { insr->TargetID = requester->GetID(); insr->playerid = requestee->GetID(); - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; const ItemInst* inst = nullptr; int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); for(int16 L = 0; L <= 20; L++) { @@ -5709,7 +5655,7 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { strcpy(insr->itemnames[L], item->Name); if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - const Item_Struct *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + const ItemData *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); insr->itemicons[L] = aug_item->Icon; } else if (inst && inst->GetOrnamentationIcon()) @@ -6890,7 +6836,7 @@ void Client::SendAltCurrencies() { uint32 i = 0; std::list::iterator iter = zone->AlternateCurrencies.begin(); while(iter != zone->AlternateCurrencies.end()) { - const Item_Struct* item = database.GetItem((*iter).item_id); + const ItemData* item = database.GetItem((*iter).item_id); altc->entries[i].currency_number = (*iter).id; altc->entries[i].unknown00 = 1; altc->entries[i].currency_number2 = (*iter).id; @@ -6922,11 +6868,7 @@ void Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 me /* Added via Quest, rest of the logging methods may be done inline due to information available in that area of the code */ if (method == 1){ - /* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){ - std::string event_desc = StringFormat("Added via Quest :: Cursor to Item :: alt_currency_id:%i amount:%i in zoneid:%i instid:%i", currency_id, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, this->CharacterID(), event_desc); - } + } if(amount == 0) { @@ -7482,7 +7424,7 @@ void Client::DuplicateLoreMessage(uint32 ItemID) return; } - const Item_Struct *item = database.GetItem(ItemID); + const ItemData *item = database.GetItem(ItemID); if(!item) return; @@ -8244,7 +8186,7 @@ void Client::SetConsumption(int32 in_hunger, int32 in_thirst) safe_delete(outapp); } -void Client::Consume(const Item_Struct *item, uint8 type, int16 slot, bool auto_consume) +void Client::Consume(const ItemData *item, uint8 type, int16 slot, bool auto_consume) { if(!item) { return; } @@ -8447,8 +8389,7 @@ void Client::TextLink::generate_body() */ memset(&m_LinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); - - const Item_Struct* item_data = nullptr; + const ItemData* item_data = nullptr; switch (m_LinkType) { case linkBlank: @@ -8528,7 +8469,7 @@ void Client::TextLink::generate_text() return; } - const Item_Struct* item_data = nullptr; + const ItemData* item_data = nullptr; switch (m_LinkType) { case linkBlank: diff --git a/zone/client.h b/zone/client.h index 4a166feed..55c8ee07c 100644 --- a/zone/client.h +++ b/zone/client.h @@ -27,7 +27,7 @@ class Object; class Raid; class Seperator; class ServerPacket; -struct Item_Struct; +struct ItemData; #include "../common/timer.h" #include "../common/ptimer.h" @@ -42,7 +42,7 @@ struct Item_Struct; #include "../common/seperator.h" #include "../common/item.h" #include "../common/guilds.h" -#include "../common/item_struct.h" +#include "../common/item_data.h" #include "../common/clientversions.h" #include "aa.h" @@ -288,7 +288,7 @@ public: void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); virtual bool Process(); - void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const Item_Struct* item, bool buying); + void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const ItemData* item, bool buying); void SendPacketQueue(bool Block = true); void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone); void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL); @@ -333,8 +333,8 @@ public: inline uint8 GetAnon() const { return m_pp.anon; } inline PlayerProfile_Struct& GetPP() { return m_pp; } inline ExtendedProfile_Struct& GetEPP() { return m_epp; } - inline Inventory& GetInv() { return m_inv; } - inline const Inventory& GetInv() const { return m_inv; } + inline InventoryOld& GetInv() { return m_inv; } + inline const InventoryOld& GetInv() const { return m_inv; } inline PetInfo* GetPetInfo(uint16 pet) { return (pet==1)?&m_suspendedminion:&m_petinfo; } inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; } inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; } @@ -396,7 +396,7 @@ public: inline uint8 GetLanguageSkill(uint16 n) const { return m_pp.languages[n]; } - void SendPickPocketResponse(Mob *from, uint32 amt, int type, const Item_Struct* item = nullptr); + void SendPickPocketResponse(Mob *from, uint32 amt, int type, const ItemData* item = nullptr); inline const char* GetLastName() const { return lastname; } @@ -593,7 +593,7 @@ public: void AssignToInstance(uint16 instance_id); void RemoveFromInstance(uint16 instance_id); void WhoAll(); - bool CheckLoreConflict(const Item_Struct* item); + bool CheckLoreConflict(const ItemData* item); void ChangeLastName(const char* in_lastname); void GetGroupAAs(GroupLeadershipAA_Struct *into) const; void GetRaidAAs(RaidLeadershipAA_Struct *into) const; @@ -801,7 +801,7 @@ public: int32 acmod(); // Item methods - void EVENT_ITEM_ScriptStopReturn(); + void ItemScriptStopReturn(); uint32 NukeItem(uint32 itemnum, uint8 where_to_check = (invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor)); void SetTint(int16 slot_id, uint32 color); @@ -814,16 +814,38 @@ 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 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); + 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); void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); + //inv2: New Inventory methods, will probably move these to Mob in a future update as there's + //little reason for them to be in client except for simplicity of implementation atm + bool SwapItem(const EQEmu::InventorySlot &src, const EQEmu::InventorySlot &dest, int number_in_stack); + bool SummonItem(uint32 item_id, + int16 charges, + const EQEmu::InventorySlot &slot = EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor), + uint32 aug1 = 0, + uint32 aug2 = 0, + uint32 aug3 = 0, + uint32 aug4 = 0, + uint32 aug5 = 0, + uint32 aug6 = 0, + bool attuned = false, + uint32 ornament_icon = 0, + uint32 ornament_idfile = 0, + uint32 ornament_hero_model = 0); + bool PutItemInInventory(const EQEmu::InventorySlot &slot, EQEmu::ItemInstance::pointer &inst, bool client_update = false); + bool CanPutItemInInventory(EQEmu::ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end); + void StackItem(EQEmu::ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end, bool client_update); + void PutItemInInventory(EQEmu::ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end, bool client_update); + // // class Client::TextLink // @@ -834,7 +856,7 @@ public: TextLink() { Reset(); } void SetLinkType(LinkType linkType) { m_LinkType = linkType; } - void SetItemData(const Item_Struct* itemData) { m_ItemData = itemData; } + void SetItemData(const ItemData* itemData) { m_ItemData = itemData; } void SetLootData(const ServerLootItem_Struct* lootData) { m_LootData = lootData; } void SetItemInst(const ItemInst* itemInst) { m_ItemInst = itemInst; } void SetProxyItemID(uint32 proxyItemID) { m_ProxyItemID = proxyItemID; } // mainly for saylinks..but, not limited to @@ -858,7 +880,7 @@ public: void generate_text(); int m_LinkType; - const Item_Struct* m_ItemData; + const ItemData* m_ItemData; const ServerLootItem_Struct* m_LootData; const ItemInst* m_ItemInst; uint32 m_ProxyItemID; @@ -871,7 +893,7 @@ public: bool m_Error; }; - int GetItemLinkHash(const ItemInst* inst); // move to Item_Struct..or make use of the pre-calculated database field + int GetItemLinkHash(const ItemInst* inst); // move to ItemData..or make use of the pre-calculated database field void SendItemLink(const ItemInst* inst, bool sendtoall=false); void SendLootItemInPacket(const ItemInst* inst, int16 slot_id); @@ -879,6 +901,9 @@ public: bool IsValidSlot(uint32 slot); bool IsBankSlot(uint32 slot); + //inv2 + void SendItemPacket(const EQEmu::InventorySlot &slot, EQEmu::ItemInstance::pointer &inst, ItemPacketType packet_type); + inline bool IsTrader() const { return(Trader); } inline bool IsBuyer() const { return(Buyer); } eqFilterMode GetFilter(eqFilterType filter_id) const { return ClientFilters[filter_id]; } @@ -1217,7 +1242,7 @@ public: void LoadAccountFlags(); void SetAccountFlag(std::string flag, std::string val); std::string GetAccountFlag(std::string flag); float GetDamageMultiplier(SkillUseTypes); - void Consume(const Item_Struct *item, uint8 type, int16 slot, bool auto_consume); + void Consume(const ItemData *item, uint8 type, int16 slot, bool auto_consume); void PlayMP3(const char* fname); void ExpeditionSay(const char *str, int ExpID); int mod_client_damage(int damage, SkillUseTypes skillinuse, int hand, const ItemInst* weapon, Mob* other); @@ -1239,9 +1264,9 @@ public: int32 mod_client_xp(int32 in_exp, NPC *npc); uint32 mod_client_xp_for_level(uint32 xp, uint16 check_level); int mod_client_haste_cap(int cap); - int mod_consume(Item_Struct *item, ItemUseTypes type, int change); - int mod_food_value(const Item_Struct *item, int change); - int mod_drink_value(const Item_Struct *item, int change); + int mod_consume(ItemData *item, ItemUseTypes type, int change); + int mod_food_value(const ItemData *item, int change); + int mod_drink_value(const ItemData *item, int change); void SetEngagedRaidTarget(bool value) { EngagedRaidTarget = value; } bool GetEngagedRaidTarget() const { return EngagedRaidTarget; } @@ -1413,7 +1438,7 @@ private: PlayerProfile_Struct m_pp; ExtendedProfile_Struct m_epp; - Inventory m_inv; + InventoryOld m_inv; Object* m_tradeskill_object; PetInfo m_petinfo; // current pet data, used while loading from and saving to DB PetInfo m_suspendedminion; // pet data for our suspended minion. diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index f12c20064..2f7041c34 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1302,7 +1302,7 @@ int32 Client::CalcManaRegenCap() uint32 Client::CalcCurrentWeight() { - const Item_Struct* TempItem = 0; + const ItemData* TempItem = 0; ItemInst* ins; uint32 Total = 0; int x; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2ae2babac..8666218d9 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -47,6 +47,7 @@ #include "../common/spdat.h" #include "../common/string_util.h" #include "../common/zone_numbers.h" +#include "../common/inventory_db_data_model.h" #include "event_codes.h" #include "guild_mgr.h" #include "merc.h" @@ -782,11 +783,6 @@ void Client::CompleteConnect() /* This sub event is for if a player logs in for the first time since entering world. */ if (firstlogon == 1){ parse->EventPlayer(EVENT_CONNECT, this, "", 0); - /* QS: PlayerLogConnectDisconnect */ - if (RuleB(QueryServ, PlayerLogConnectDisconnect)){ - std::string event_desc = StringFormat("Connect :: Logged into zoneid:%i instid:%i", this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Connect_State, this->CharacterID(), event_desc); - } } if (zone) { @@ -1279,7 +1275,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) m_pp.platinum_shared = database.GetSharedPlatinum(this->AccountID()); database.ClearOldRecastTimestamps(cid); /* Clear out our old recast timestamps to keep the DB clean */ - loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */ database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */ database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */ database.LoadCharacterMaterialColor(cid, &m_pp); /* Load Character Material */ @@ -1295,6 +1290,12 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */ database.LoadCharacterTribute(cid, &m_pp); /* Load CharacterTribute */ + m_inventory.SetRace(GetBaseRace()); + m_inventory.SetClass(GetBaseClass()); + m_inventory.SetDeity(GetDeity()); + m_inventory.SetDataModel(new EQEmu::InventoryDatabaseDataModel(&database, CharacterID())); + loaditems = database.GetInventory(cid, &m_inventory); /* Load Character Inventory */ + /* Load AdventureStats */ AdventureStats_Struct as; if(database.GetAdventureStats(cid, &as)) @@ -1730,13 +1731,10 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) */ if (loaditems) { /* Dont load if a length error occurs */ BulkSendInventoryItems(); - /* Send stuff on the cursor which isnt sent in bulk */ - for (auto iter = m_inv.cursor_cbegin(); iter != m_inv.cursor_cend(); ++iter) { - /* First item cursor is sent in bulk inventory packet */ - if (iter == m_inv.cursor_cbegin()) - continue; - const ItemInst *inst = *iter; - SendItemPacket(MainCursor, inst, ItemPacketSummonItem); + EQEmu::InventorySlot slot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor); + auto cursor = m_inventory.Get(slot); + if(cursor) { + SendItemPacket(slot, cursor, ItemPacketSummonItem); } } @@ -1927,7 +1925,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) merchantid = tmp->CastToNPC()->MerchantType; - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; bool found = false; std::list merlist = zone->merchanttable[merchantid]; std::list::const_iterator itr; @@ -2070,7 +2068,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) if (item->MaxCharges != 0) charges = item->MaxCharges; - ItemInst *inst = database.CreateItem(item, charges); + ItemInst *inst = database.CreateItemOld(item, charges); if (!AutoPutLootInInventory(*inst, true, true)) { PutLootInInventory(MainCursor, *inst); @@ -2103,7 +2101,7 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app) merchantid = tmp->CastToNPC()->MerchantType; tmp->CastToNPC()->FaceTarget(this->CastToMob()); - const Item_Struct *item = 0; + const ItemData *item = 0; std::list merlist = zone->merchanttable[merchantid]; std::list::const_iterator itr; for (itr = merlist.begin(); itr != merlist.end() && count<255; ++itr){ @@ -2202,7 +2200,7 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app) return; } - const Item_Struct* item = database.GetItem(itemid); + const ItemData* item = database.GetItem(itemid); ItemInst* inst = GetInv().GetItem(ams_in->slot); if (!item || !inst){ Message(13, "You seemed to have misplaced that item..."); @@ -2477,7 +2475,7 @@ void Client::Handle_OP_AltCurrencyMerchantRequest(const EQApplicationPacket *app ss << alt_cur_id << "|1|" << alt_cur_id; uint32 count = 0; uint32 merchant_id = tar->MerchantType; - const Item_Struct *item = nullptr; + const ItemData *item = nullptr; std::list merlist = zone->merchanttable[merchant_id]; std::list::const_iterator itr; @@ -2537,7 +2535,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) return; } - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; uint32 cost = 0; uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id); uint32 merchant_id = tar->MerchantType; @@ -2582,18 +2580,12 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) return; } - /* QS: PlayerLogAlternateCurrencyTransactions :: Merchant Purchase */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){ - std::string event_desc = StringFormat("Merchant Purchase :: Spent alt_currency_id:%i cost:%i for itemid:%i in zoneid:%i instid:%i", alt_cur_id, cost, item->ID, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, this->CharacterID(), event_desc); - } - AddAlternateCurrencyValue(alt_cur_id, -((int32)cost)); int16 charges = 1; if (item->MaxCharges != 0) charges = item->MaxCharges; - ItemInst *inst = database.CreateItem(item, charges); + ItemInst *inst = database.CreateItemOld(item, charges); if (!AutoPutLootInInventory(*inst, true, true)) { PutLootInInventory(MainCursor, *inst); @@ -2625,12 +2617,6 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) uint32 removed = NukeItem(item_id, invWhereWorn | invWherePersonal | invWhereCursor); if (removed > 0) { AddAlternateCurrencyValue(reclaim->currency_id, removed); - - /* QS: PlayerLogAlternateCurrencyTransactions :: Item to Currency */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){ - std::string event_desc = StringFormat("Reclaim :: Item to Currency :: alt_currency_id:%i amount:%i to currency tab in zoneid:%i instid:%i", reclaim->currency_id, removed, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, this->CharacterID(), event_desc); - } } } /* Cursor to Item storage */ @@ -2642,18 +2628,13 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) /* If you input more than you have currency wise, just give the max of the currency you currently have */ if (reclaim->count > max_currency) { - SummonItem(item_id, max_currency); + SummonItem(item_id, max_currency, 0); SetAlternateCurrencyValue(reclaim->currency_id, 0); } else { SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, 0, false, MainCursor); AddAlternateCurrencyValue(reclaim->currency_id, -((int32)reclaim->count)); } - /* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){ - std::string event_desc = StringFormat("Reclaim :: Cursor to Item :: alt_currency_id:%i amount:-%i in zoneid:%i instid:%i", reclaim->currency_id, reclaim->count, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, this->CharacterID(), event_desc); - } } } @@ -2686,7 +2667,7 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) return; } - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; uint32 cost = 0; uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id); uint32 merchant_id = tar->MerchantType; @@ -2743,12 +2724,6 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) sell->cost = cost; - /* QS: PlayerLogAlternateCurrencyTransactions :: Sold to Merchant*/ - if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){ - std::string event_desc = StringFormat("Sold to Merchant :: itemid:%u npcid:%u alt_currency_id:%u cost:%u in zoneid:%u instid:%i", item->ID, npc_id, alt_cur_id, cost, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, this->CharacterID(), event_desc); - } - FastQueuePacket(&outapp); AddAlternateCurrencyValue(alt_cur_id, cost); Save(1); @@ -2779,7 +2754,7 @@ void Client::Handle_OP_AltCurrencySellSelection(const EQApplicationPacket *app) return; } - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; uint32 cost = 0; uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id); uint32 merchant_id = tar->MerchantType; @@ -2953,7 +2928,7 @@ void Client::Handle_OP_AugmentInfo(const EQApplicationPacket *app) } AugmentInfo_Struct* AugInfo = (AugmentInfo_Struct*)app->pBuffer; - const Item_Struct * item = database.GetItem(AugInfo->itemid); + const ItemData * item = database.GetItem(AugInfo->itemid); if (item) { strn0cpy(AugInfo->augment_info, item->Name, 64); @@ -2984,7 +2959,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) { ItemInst *tobe_auged = nullptr, *auged_with = nullptr; int8 slot = -1; - Inventory& user_inv = GetInv(); + InventoryOld& user_inv = GetInv(); uint16 slot_id = in_augment->container_slot; uint16 aug_slot_id = in_augment->augment_slot; @@ -3054,7 +3029,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) { ItemInst *tobe_auged = nullptr, *auged_with = nullptr; int8 slot = -1; - Inventory& user_inv = GetInv(); + InventoryOld& user_inv = GetInv(); uint16 slot_id = in_augment->container_slot; uint16 aug_slot_id = in_augment->augment_slot; //it's actually solvent slot @@ -3393,13 +3368,13 @@ void Client::Handle_OP_Barter(const EQApplicationPacket *app) { BarterItemSearchLinkRequest_Struct* bislr = (BarterItemSearchLinkRequest_Struct*)app->pBuffer; - const Item_Struct* item = database.GetItem(bislr->ItemID); + const ItemData* item = database.GetItem(bislr->ItemID); if (!item) Message(13, "Error: This item does not exist!"); else { - ItemInst* inst = database.CreateItem(item); + ItemInst* inst = database.CreateItemOld(item); if (inst) { SendItemPacket(0, inst, ItemPacketViewLink); @@ -3426,13 +3401,13 @@ void Client::Handle_OP_Barter(const EQApplicationPacket *app) { BuyerItemSearchLinkRequest_Struct* bislr = (BuyerItemSearchLinkRequest_Struct*)app->pBuffer; - const Item_Struct* item = database.GetItem(bislr->ItemID); + const ItemData* item = database.GetItem(bislr->ItemID); if (!item) Message(13, "Error: This item does not exist!"); else { - ItemInst* inst = database.CreateItem(item); + ItemInst* inst = database.CreateItemOld(item); if (inst) { SendItemPacket(0, inst, ItemPacketViewLink); @@ -3465,14 +3440,14 @@ void Client::Handle_OP_BazaarInspect(const EQApplicationPacket *app) BazaarInspect_Struct* bis = (BazaarInspect_Struct*)app->pBuffer; - const Item_Struct* item = database.GetItem(bis->ItemID); + const ItemData* item = database.GetItem(bis->ItemID); if (!item) { Message(13, "Error: This item does not exist!"); return; } - ItemInst* inst = database.CreateItem(item); + ItemInst* inst = database.CreateItemOld(item); if (inst) { SendItemPacket(0, inst, ItemPacketViewLink); @@ -3920,7 +3895,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) //bool cancast = true; if (inst && inst->IsType(ItemClassCommon)) { - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); if (item->Click.Effect != (uint32)castspell->spell_id) { database.SetMQDetectionFlag(account_name, name, "OP_CastSpell with item, tried to cast a different spell.", zone->GetShortName()); @@ -4772,7 +4747,7 @@ void Client::Handle_OP_Consume(const EQApplicationPacket *app) return; } - const Item_Struct* eat_item = myitem->GetItem(); + const ItemData* eat_item = myitem->GetItem(); if (pcs->type == 0x01) { Consume(eat_item, ItemTypeFood, pcs->slot, (pcs->auto_consumed == 0xffffffff)); } @@ -4913,14 +4888,14 @@ void Client::Handle_OP_CrystalCreate(const EQApplicationPacket *app) if (cr->type == 5) { if (cr->amount > GetEbonCrystals()) { - SummonItem(RuleI(Zone, EbonCrystalItemID), GetEbonCrystals()); + SummonItem(RuleI(Zone, EbonCrystalItemID), GetEbonCrystals(), 0); m_pp.currentEbonCrystals = 0; m_pp.careerEbonCrystals = 0; SaveCurrency(); SendCrystalCounts(); } else { - SummonItem(RuleI(Zone, EbonCrystalItemID), cr->amount); + SummonItem(RuleI(Zone, EbonCrystalItemID), cr->amount, 0); m_pp.currentEbonCrystals -= cr->amount; m_pp.careerEbonCrystals -= cr->amount; SaveCurrency(); @@ -4929,14 +4904,14 @@ void Client::Handle_OP_CrystalCreate(const EQApplicationPacket *app) } else if (cr->type == 4) { if (cr->amount > GetRadiantCrystals()) { - SummonItem(RuleI(Zone, RadiantCrystalItemID), GetRadiantCrystals()); + SummonItem(RuleI(Zone, RadiantCrystalItemID), GetRadiantCrystals(), 0); m_pp.currentRadCrystals = 0; m_pp.careerRadCrystals = 0; SaveCurrency(); SendCrystalCounts(); } else { - SummonItem(RuleI(Zone, RadiantCrystalItemID), cr->amount); + SummonItem(RuleI(Zone, RadiantCrystalItemID), cr->amount, 0); m_pp.currentRadCrystals -= cr->amount; m_pp.careerRadCrystals -= cr->amount; SaveCurrency(); @@ -6863,7 +6838,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) return; } - const Item_Struct* CursorItem = CursorItemInst->GetItem(); + const ItemData* CursorItem = CursorItemInst->GetItem(); if (!CursorItem->NoDrop || CursorItemInst->IsAttuned()) { @@ -7932,7 +7907,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) EQApplicationPacket* outapp = app->Copy(); InspectResponse_Struct* insr = (InspectResponse_Struct*)outapp->pBuffer; Mob* tmp = entity_list.GetMob(insr->TargetID); - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); for (int16 L = EmuConstants::EQUIPMENT_BEGIN; L <= MainWaist; L++) { @@ -7942,7 +7917,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) if (item) { strcpy(insr->itemnames[L], item->Name); if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - const Item_Struct *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + const ItemData *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); insr->itemicons[L] = aug_item->Icon; } else if (inst->GetOrnamentationIcon()) { @@ -8040,7 +8015,7 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) //todo: verify ivrs->link_hash based on a rule, in case we don't care about people being able to sniff data from the item DB - const Item_Struct* item = database.GetItem(ivrs->item_id); + const ItemData* item = database.GetItem(ivrs->item_id); if (!item) { if (ivrs->item_id > 500000) { @@ -8119,7 +8094,7 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) } - ItemInst* inst = database.CreateItem(item, item->MaxCharges, ivrs->augments[0], ivrs->augments[1], ivrs->augments[2], ivrs->augments[3], ivrs->augments[4], ivrs->augments[5]); + ItemInst* inst = database.CreateItemOld(item, item->MaxCharges, ivrs->augments[0], ivrs->augments[1], ivrs->augments[2], ivrs->augments[3], ivrs->augments[4], ivrs->augments[5]); if (inst) { SendItemPacket(0, inst, ItemPacketViewLink); safe_delete(inst); @@ -8134,7 +8109,7 @@ void Client::Handle_OP_ItemLinkResponse(const EQApplicationPacket *app) return; } LDONItemViewRequest_Struct* item = (LDONItemViewRequest_Struct*)app->pBuffer; - ItemInst* inst = database.CreateItem(item->item_id); + ItemInst* inst = database.CreateItemOld(item->item_id); if (inst) { SendItemPacket(0, inst, ItemPacketViewLink); safe_delete(inst); @@ -8150,7 +8125,7 @@ void Client::Handle_OP_ItemName(const EQApplicationPacket *app) return; } ItemNamePacket_Struct *p = (ItemNamePacket_Struct*)app->pBuffer; - const Item_Struct *item = 0; + const ItemData *item = 0; if ((item = database.GetItem(p->item_id)) != nullptr) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_ItemName, sizeof(ItemNamePacket_Struct)); p = (ItemNamePacket_Struct*)outapp->pBuffer; @@ -8166,7 +8141,7 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app) VERIFY_PACKET_LENGTH(OP_ItemPreview, app, ItemPreview_Struct); ItemPreview_Struct *ips = (ItemPreview_Struct *)app->pBuffer; - const Item_Struct* item = database.GetItem(ips->itemid); + const ItemData* item = database.GetItem(ips->itemid); if (item) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_ItemPreview, strlen(item->Name) + strlen(item->Lore) + strlen(item->IDFile) + 898); @@ -8382,7 +8357,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) return; } - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); if (!item) { Message(0, "Error: item not found in inventory slot #%i", slot_id); DeleteItemInInventory(slot_id, 0, true); @@ -8430,13 +8405,13 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) int r; bool tryaug = false; ItemInst* clickaug = 0; - Item_Struct* augitem = 0; + ItemData* augitem = 0; for (r = 0; r < EmuConstants::ITEM_COMMON_SIZE; r++) { const ItemInst* aug_i = inst->GetAugment(r); if (!aug_i) continue; - const Item_Struct* aug = aug_i->GetItem(); + const ItemData* aug = aug_i->GetItem(); if (!aug) continue; @@ -8444,7 +8419,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) { tryaug = true; clickaug = (ItemInst*)aug_i; - augitem = (Item_Struct*)aug; + augitem = (ItemData*)aug; spell_id = aug->Click.Effect; break; } @@ -9624,68 +9599,18 @@ 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; - } + EQEmu::InventorySlot src(mi->from_type, mi->from_slot, mi->from_bag_slot, mi->from_aug_slot); + EQEmu::InventorySlot dest(mi->to_type, mi->to_slot, mi->to_bag_slot, mi->to_aug_slot); + if(!SwapItem(src, dest, mi->number_in_stack)) { + //Send Resync Here } - - // 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) @@ -10503,7 +10428,7 @@ void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) } if (mptbs->Action == 0) { - const Item_Struct *BaseItem = database.GetItem(mptbs->ItemID); + const ItemData *BaseItem = database.GetItem(mptbs->ItemID); if (BaseItem) { m_pp.potionbelt.Items[mptbs->SlotNumber].ID = BaseItem->ID; m_pp.potionbelt.Items[mptbs->SlotNumber].Icon = BaseItem->Icon; @@ -11980,7 +11905,7 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app) return; if (inst) { - const Item_Struct* shield = inst->GetItem(); + const ItemData* shield = inst->GetItem(); if (shield && shield->ItemType == ItemTypeShield) { for (int x = 0; x < 2; x++) @@ -12046,29 +11971,24 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) sizeof(Merchant_Sell_Struct), app->size); return; } - RDTSC_Timer t1; - t1.start(); Merchant_Sell_Struct* mp = (Merchant_Sell_Struct*)app->pBuffer; -#if EQDEBUG >= 5 - Log.Out(Logs::General, Logs::None, "%s, purchase item..", GetName()); - DumpPacket(app); -#endif - + int merchantid; bool tmpmer_used = false; Mob* tmp = entity_list.GetMob(mp->npcid); - - if (tmp == 0 || !tmp->IsNPC() || tmp->GetClass() != MERCHANT) + + if (!tmp || !tmp->IsNPC() || tmp->GetClass() != MERCHANT) return; - - if (mp->quantity < 1) return; - + + if (mp->quantity < 1) + return; + //you have to be somewhat close to them to be properly using them if (DistanceSquared(m_Position, tmp->GetPosition()) > USE_NPC_RANGE2) return; - + merchantid = tmp->CastToNPC()->MerchantType; - + uint32 item_id = 0; std::list merlist = zone->merchanttable[merchantid]; std::list::const_iterator itr; @@ -12077,18 +11997,18 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) if (GetLevel() < ml.level_required) { continue; } - + int32 fac = tmp->GetPrimaryFaction(); if (fac != 0 && GetModCharacterFactionLevel(fac) < ml.faction_required) { continue; } - + if (mp->itemslot == ml.slot){ item_id = ml.item; break; } } - const Item_Struct* item = nullptr; + uint32 prevcharges = 0; if (item_id == 0) { //check to see if its on the temporary table std::list tmp_merlist = zone->tmpmerchanttable[tmp->GetNPCTypeID()]; @@ -12104,7 +12024,8 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) } } } - item = database.GetItem(item_id); + + const ItemData* item = database.GetItem(item_id); if (!item){ //error finding item, client didnt get the update packet for whatever reason, roleplay a tad Message(15, "%s tells you 'Sorry, that item is for display purposes only.' as they take the item off the shelf.", tmp->GetCleanName()); @@ -12118,11 +12039,13 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) safe_delete(delitempacket); return; } - if (CheckLoreConflict(item)) + + if (m_inventory.CheckLoreConflict(item)) { Message(15, "You can only have one of a lore item."); return; } + if (tmpmer_used && (mp->quantity > prevcharges || item->MaxCharges > 1)) { if (prevcharges > item->MaxCharges && item->MaxCharges > 1) @@ -12130,95 +12053,75 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) else mp->quantity = prevcharges; } - + // Item's stackable, but the quantity they want to buy exceeds the max stackable quantity. if (item->Stackable && mp->quantity > item->StackSize) mp->quantity = item->StackSize; - + EQApplicationPacket* outapp = new EQApplicationPacket(OP_ShopPlayerBuy, sizeof(Merchant_Sell_Struct)); Merchant_Sell_Struct* mpo = (Merchant_Sell_Struct*)outapp->pBuffer; mpo->quantity = mp->quantity; mpo->playerid = mp->playerid; mpo->npcid = mp->npcid; mpo->itemslot = mp->itemslot; - - int16 freeslotid = INVALID_INDEX; - int16 charges = 0; + + EQEmu::InventorySlot free_slot; + int charges = 0; if (item->Stackable || item->MaxCharges > 1) charges = mp->quantity; else charges = item->MaxCharges; - - ItemInst* inst = database.CreateItem(item, charges); - + int SinglePrice = 0; if (RuleB(Merchant, UsePriceMod)) SinglePrice = (item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate * Client::CalcPriceMod(tmp, false)); else SinglePrice = (item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate); - + if (item->MaxCharges > 1) mpo->price = SinglePrice; else mpo->price = SinglePrice * mp->quantity; - + if (mpo->price < 0) { safe_delete(outapp); - safe_delete(inst); + return; + } + + if(m_inventory.Get(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor))) { + safe_delete(outapp); + return; + } + + auto inst = database.CreateItem(item->ID, charges); + + if(!CanPutItemInInventory(inst, EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1, EQEmu::PersonalSlotGeneral10)) { + Message(13, "You do not have room for any more items."); + + QueuePacket(outapp); + safe_delete(outapp); return; } // this area needs some work..two inventory insertion check failure points // below do not return player's money..is this the intended behavior? - if (!TakeMoneyFromPP(mpo->price)) { - char *hacker_str = nullptr; - MakeAnyLenString(&hacker_str, "Vendor Cheat: attempted to buy %i of %i: %s that cost %d cp but only has %d pp %d gp %d sp %d cp\n", + std::string hacker_str = StringFormat("Vendor Cheat: attempted to buy %i of %i: %s that cost %d cp but only has %d pp %d gp %d sp %d cp\n", mpo->quantity, item->ID, item->Name, mpo->price, m_pp.platinum, m_pp.gold, m_pp.silver, m_pp.copper); - database.SetMQDetectionFlag(AccountName(), GetName(), hacker_str, zone->GetShortName()); - safe_delete_array(hacker_str); + database.SetMQDetectionFlag(AccountName(), GetName(), hacker_str.c_str(), zone->GetShortName()); safe_delete(outapp); - safe_delete(inst); return; } - bool stacked = TryStacking(inst); - if (!stacked) - freeslotid = m_inv.FindFreeSlot(false, true, item->Size); - - // shouldn't we be reimbursing if these two fail? - - //make sure we are not completely full... - if (freeslotid == MainCursor) { - if (m_inv.GetItem(MainCursor) != nullptr) { - Message(13, "You do not have room for any more items."); - safe_delete(outapp); - safe_delete(inst); - return; - } - } - - if (!stacked && freeslotid == INVALID_INDEX) - { - Message(13, "You do not have room for any more items."); - safe_delete(outapp); - safe_delete(inst); - return; - } - - std::string packet; - if (!stacked && inst) { - PutItemInInventory(freeslotid, *inst); - SendItemPacket(freeslotid, inst, ItemPacketTrade); - } - else if (!stacked){ - Log.Out(Logs::General, Logs::Error, "OP_ShopPlayerBuy: item->ItemClass Unknown! Type: %i", item->ItemClass); - } QueuePacket(outapp); - if (inst && tmpmer_used){ + safe_delete(outapp); + + PutItemInInventory(inst, EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1, EQEmu::PersonalSlotGeneral10, true); + + if (inst && tmpmer_used) { int32 new_charges = prevcharges - mp->quantity; zone->SaveTempItem(merchantid, tmp->GetNPCTypeID(), item_id, new_charges); if (new_charges <= 0){ @@ -12237,70 +12140,17 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) inst->SetPrice(SinglePrice); inst->SetMerchantSlot(mp->itemslot); inst->SetMerchantCount(new_charges); - - SendItemPacket(mp->itemslot, inst, ItemPacketMerchant); + + SendItemPacket(EQEmu::InventorySlot(EQEmu::InvTypeMerchant, mp->itemslot), inst, ItemPacketMerchant); } } - safe_delete(inst); - safe_delete(outapp); - - // start QS code - // stacking purchases not supported at this time - entire process will need some work to catch them properly - if (RuleB(QueryServ, PlayerLogMerchantTransactions)) { - ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, sizeof(QSMerchantLogTransaction_Struct)+sizeof(QSTransactionItems_Struct)); - QSMerchantLogTransaction_Struct* qsaudit = (QSMerchantLogTransaction_Struct*)qspack->pBuffer; - - qsaudit->zone_id = zone->GetZoneID(); - qsaudit->merchant_id = tmp->CastToNPC()->MerchantType; - qsaudit->merchant_money.platinum = 0; - qsaudit->merchant_money.gold = 0; - qsaudit->merchant_money.silver = 0; - qsaudit->merchant_money.copper = 0; - qsaudit->merchant_count = 1; - qsaudit->char_id = character_id; - qsaudit->char_money.platinum = (mpo->price / 1000); - qsaudit->char_money.gold = (mpo->price / 100) % 10; - qsaudit->char_money.silver = (mpo->price / 10) % 10; - qsaudit->char_money.copper = mpo->price % 10; - qsaudit->char_count = 0; - - qsaudit->items[0].char_slot = freeslotid == INVALID_INDEX ? 0 : freeslotid; - qsaudit->items[0].item_id = item->ID; - qsaudit->items[0].charges = mpo->quantity; - - if (freeslotid == INVALID_INDEX) { - qsaudit->items[0].aug_1 = 0; - qsaudit->items[0].aug_2 = 0; - qsaudit->items[0].aug_3 = 0; - qsaudit->items[0].aug_4 = 0; - qsaudit->items[0].aug_5 = 0; - } - else { - qsaudit->items[0].aug_1 = m_inv[freeslotid]->GetAugmentItemID(0); - qsaudit->items[0].aug_2 = m_inv[freeslotid]->GetAugmentItemID(1); - qsaudit->items[0].aug_3 = m_inv[freeslotid]->GetAugmentItemID(2); - qsaudit->items[0].aug_4 = m_inv[freeslotid]->GetAugmentItemID(3); - qsaudit->items[0].aug_5 = m_inv[freeslotid]->GetAugmentItemID(4); - } - - qspack->Deflate(); - if (worldserver.Connected()) { worldserver.SendPacket(qspack); } - safe_delete(qspack); - } - // end QS code - - if (RuleB(EventLog, RecordBuyFromMerchant)) - LogMerchant(this, tmp, mpo->quantity, mpo->price, item, true); - + + zone->LogEvent(EventLogItemBuy, this, StringFormat("Merc(%i) -> player %s(%i) %i charges for %ic", merchantid, item->Name, item->ID, mpo->quantity, mpo->price)); if ((RuleB(Character, EnableDiscoveredItems))) { if (!GetGM() && !IsDiscovered(item_id)) DiscoverItem(item_id); } - - t1.stop(); - std::cout << "At 1: " << t1.getDuration() << std::endl; - return; } void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) { @@ -12309,7 +12159,6 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) sizeof(Merchant_Purchase_Struct), app->size); return; } - RDTSC_Timer t1(true); Merchant_Purchase_Struct* mp = (Merchant_Purchase_Struct*)app->pBuffer; Mob* vendor = entity_list.GetMob(mp->npcid); @@ -12325,7 +12174,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) uint32 itemid = GetItemIDAt(mp->itemslot); if (itemid == 0) return; - const Item_Struct* item = database.GetItem(itemid); + const ItemData* item = database.GetItem(itemid); ItemInst* inst = GetInv().GetItem(mp->itemslot); if (!item || !inst){ Message(13, "You seemed to have misplaced that item.."); @@ -12338,7 +12187,6 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) } if (!item->NoDrop) { - //Message(13,"%s tells you, 'LOL NOPE'", vendor->GetName()); return; } @@ -12399,38 +12247,38 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) } // start QS code - if (RuleB(QueryServ, PlayerLogMerchantTransactions)) { - ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, sizeof(QSMerchantLogTransaction_Struct)+sizeof(QSTransactionItems_Struct)); - QSMerchantLogTransaction_Struct* qsaudit = (QSMerchantLogTransaction_Struct*)qspack->pBuffer; - - qsaudit->zone_id = zone->GetZoneID(); - qsaudit->merchant_id = vendor->CastToNPC()->MerchantType; - qsaudit->merchant_money.platinum = (price / 1000); - qsaudit->merchant_money.gold = (price / 100) % 10; - qsaudit->merchant_money.silver = (price / 10) % 10; - qsaudit->merchant_money.copper = price % 10; - qsaudit->merchant_count = 0; - qsaudit->char_id = character_id; - qsaudit->char_money.platinum = 0; - qsaudit->char_money.gold = 0; - qsaudit->char_money.silver = 0; - qsaudit->char_money.copper = 0; - qsaudit->char_count = 1; - - qsaudit->items[0].char_slot = mp->itemslot; - qsaudit->items[0].item_id = itemid; - qsaudit->items[0].charges = charges; - qsaudit->items[0].aug_1 = m_inv[mp->itemslot]->GetAugmentItemID(1); - qsaudit->items[0].aug_2 = m_inv[mp->itemslot]->GetAugmentItemID(2); - qsaudit->items[0].aug_3 = m_inv[mp->itemslot]->GetAugmentItemID(3); - qsaudit->items[0].aug_4 = m_inv[mp->itemslot]->GetAugmentItemID(4); - qsaudit->items[0].aug_5 = m_inv[mp->itemslot]->GetAugmentItemID(5); - - qspack->Deflate(); - if (worldserver.Connected()) { worldserver.SendPacket(qspack); } - safe_delete(qspack); - } - // end QS code + //if (RuleB(QueryServ, PlayerLogMerchantTransactions)) { + // ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, sizeof(QSMerchantLogTransaction_Struct)+sizeof(QSTransactionItems_Struct)); + // QSMerchantLogTransaction_Struct* qsaudit = (QSMerchantLogTransaction_Struct*)qspack->pBuffer; + // + // qsaudit->zone_id = zone->GetZoneID(); + // qsaudit->merchant_id = vendor->CastToNPC()->MerchantType; + // qsaudit->merchant_money.platinum = (price / 1000); + // qsaudit->merchant_money.gold = (price / 100) % 10; + // qsaudit->merchant_money.silver = (price / 10) % 10; + // qsaudit->merchant_money.copper = price % 10; + // qsaudit->merchant_count = 0; + // qsaudit->char_id = character_id; + // qsaudit->char_money.platinum = 0; + // qsaudit->char_money.gold = 0; + // qsaudit->char_money.silver = 0; + // qsaudit->char_money.copper = 0; + // qsaudit->char_count = 1; + // + // qsaudit->items[0].char_slot = mp->itemslot; + // qsaudit->items[0].item_id = itemid; + // qsaudit->items[0].charges = charges; + // qsaudit->items[0].aug_1 = m_inv[mp->itemslot]->GetAugmentItemID(1); + // qsaudit->items[0].aug_2 = m_inv[mp->itemslot]->GetAugmentItemID(2); + // qsaudit->items[0].aug_3 = m_inv[mp->itemslot]->GetAugmentItemID(3); + // qsaudit->items[0].aug_4 = m_inv[mp->itemslot]->GetAugmentItemID(4); + // qsaudit->items[0].aug_5 = m_inv[mp->itemslot]->GetAugmentItemID(5); + // + // qspack->Deflate(); + // if (worldserver.Connected()) { worldserver.SendPacket(qspack); } + // safe_delete(qspack); + //} + //// end QS code // Now remove the item from the player, this happens regardless of outcome if (!inst->IsStackable()) @@ -12451,10 +12299,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) QueuePacket(outapp); safe_delete(outapp); SendMoneyUpdate(); - t1.start(); Save(1); - t1.stop(); - std::cout << "Save took: " << t1.getDuration() << std::endl; return; } @@ -13221,46 +13066,8 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) other->trade->LogTrade(); trade->LogTrade(); - // start QS code - if (RuleB(QueryServ, PlayerLogTrades)) { - QSPlayerLogTrade_Struct event_entry; - std::list event_details; - - memset(&event_entry, 0, sizeof(QSPlayerLogTrade_Struct)); - - // Perform actual trade - this->FinishTrade(other, true, &event_entry, &event_details); - other->FinishTrade(this, false, &event_entry, &event_details); - - event_entry._detail_count = event_details.size(); - - ServerPacket* qs_pack = new ServerPacket(ServerOP_QSPlayerLogTrades, sizeof(QSPlayerLogTrade_Struct)+(sizeof(QSTradeItems_Struct)* event_entry._detail_count)); - QSPlayerLogTrade_Struct* qs_buf = (QSPlayerLogTrade_Struct*)qs_pack->pBuffer; - - memcpy(qs_buf, &event_entry, sizeof(QSPlayerLogTrade_Struct)); - - int offset = 0; - - for (std::list::iterator iter = event_details.begin(); iter != event_details.end(); ++iter, ++offset) { - QSTradeItems_Struct* detail = reinterpret_cast(*iter); - qs_buf->items[offset] = *detail; - safe_delete(detail); - } - - event_details.clear(); - - qs_pack->Deflate(); - - if (worldserver.Connected()) - worldserver.SendPacket(qs_pack); - - safe_delete(qs_pack); - // end QS code - } - else { - this->FinishTrade(other); - other->FinishTrade(this); - } + this->FinishTrade(other); + other->FinishTrade(this); other->trade->Reset(); trade->Reset(); @@ -13277,42 +13084,7 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) QueuePacket(outapp); safe_delete(outapp); if (with->IsNPC()) { - // Audit trade to database for player trade stream - if (RuleB(QueryServ, PlayerLogHandins)) { - QSPlayerLogHandin_Struct event_entry; - std::list event_details; - - memset(&event_entry, 0, sizeof(QSPlayerLogHandin_Struct)); - - FinishTrade(with->CastToNPC(), false, &event_entry, &event_details); - - event_entry._detail_count = event_details.size(); - - ServerPacket* qs_pack = new ServerPacket(ServerOP_QSPlayerLogHandins, sizeof(QSPlayerLogHandin_Struct)+(sizeof(QSHandinItems_Struct)* event_entry._detail_count)); - QSPlayerLogHandin_Struct* qs_buf = (QSPlayerLogHandin_Struct*)qs_pack->pBuffer; - - memcpy(qs_buf, &event_entry, sizeof(QSPlayerLogHandin_Struct)); - - int offset = 0; - - for (std::list::iterator iter = event_details.begin(); iter != event_details.end(); ++iter, ++offset) { - QSHandinItems_Struct* detail = reinterpret_cast(*iter); - qs_buf->items[offset] = *detail; - safe_delete(detail); - } - - event_details.clear(); - - qs_pack->Deflate(); - - if (worldserver.Connected()) - worldserver.SendPacket(qs_pack); - - safe_delete(qs_pack); - } - else { - FinishTrade(with->CastToNPC()); - } + FinishTrade(with->CastToNPC()); } #ifdef BOTS // TODO: Log Bot trades @@ -13422,7 +13194,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) TradeItemsValid = false; break; } - const Item_Struct *Item = database.GetItem(gis->Items[i]); + const ItemData *Item = database.GetItem(gis->Items[i]); if (!Item) { Message(13, "Unexpected error. Unable to start trader mode"); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 4a16e7698..a0056852b 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -782,12 +782,6 @@ void Client::OnDisconnect(bool hard_disconnect) { MyRaid->MemberZoned(this); parse->EventPlayer(EVENT_DISCONNECT, this, "", 0); - - /* QS: PlayerLogConnectDisconnect */ - if (RuleB(QueryServ, PlayerLogConnectDisconnect)){ - std::string event_desc = StringFormat("Disconnect :: in zoneid:%i instid:%i", this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Connect_State, this->CharacterID(), event_desc); - } } Mob *Other = trade->With(); @@ -815,168 +809,24 @@ void Client::OnDisconnect(bool hard_disconnect) { Disconnect(); } -// Sends the client complete inventory used in character login - -// DO WE STILL NEED THE 'ITEMCOMBINED' CONDITIONAL CODE? - -//#ifdef ITEMCOMBINED void Client::BulkSendInventoryItems() { - int16 slot_id = 0; - - // LINKDEAD TRADE ITEMS - // Move trade slot items back into normal inventory..need them there now for the proceeding validity checks - for(slot_id = EmuConstants::TRADE_BEGIN; slot_id <= EmuConstants::TRADE_END; slot_id++) { - ItemInst* inst = m_inv.PopItem(slot_id); - if(inst) { - bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; - int16 free_slot_id = m_inv.FindFreeSlot(inst->IsType(ItemClassContainer), true, inst->GetItem()->Size, is_arrow); - Log.Out(Logs::Detail, Logs::Inventory, "Incomplete Trade Transaction: Moving %s from slot %i to %i", inst->GetItem()->Name, slot_id, free_slot_id); - PutItemInInventory(free_slot_id, *inst, false); - database.SaveInventory(character_id, nullptr, slot_id); - safe_delete(inst); - } + EQEmu::MemoryBuffer items; + if(!m_inventory.Serialize(items)) { + return; } - - bool deletenorent = database.NoRentExpired(GetName()); - if (deletenorent) { //client was offline for more than 30 minutes, delete no rent items - if (RuleB(Inventory, TransformSummonedBags)) - DisenchantSummonedBags(false); - RemoveNoRent(false); - } - - RemoveDuplicateLore(false); - MoveSlotNotAllowed(false); - - // The previous three method calls took care of moving/removing expired/illegal item placements - - //TODO: this function is just retarded... it re-allocates the buffer for every - //new item. It should be changed to loop through once, gather the - //lengths, and item packet pointers into an array (fixed length), and - //then loop again to build the packet. - //EQApplicationPacket *packets[50]; - //unsigned long buflen = 0; - //unsigned long pos = 0; - //memset(packets, 0, sizeof(packets)); - //foreach item in the invendor sections - // packets[pos++] = ReturnItemPacket(...) - // buflen += temp->size - //... - //allocat the buffer - //for r from 0 to pos - // put pos[r]->pBuffer into the buffer - //for r from 0 to pos - // safe_delete(pos[r]); - - uint32 size = 0; - uint16 i = 0; - std::map ser_items; - std::map::iterator itr; - - //Inventory items - for(slot_id = MAIN_BEGIN; slot_id < EmuConstants::MAP_POSSESSIONS_SIZE; slot_id++) { - const ItemInst* inst = m_inv[slot_id]; - if(inst) { - std::string packet = inst->Serialize(slot_id); - ser_items[i++] = packet; - size += packet.length(); - } - } - - // Power Source - if(GetClientVersion() >= ClientVersion::SoF) { - const ItemInst* inst = m_inv[MainPowerSource]; - if(inst) { - std::string packet = inst->Serialize(MainPowerSource); - ser_items[i++] = packet; - size += packet.length(); - } - } - - // Bank items - for(slot_id = EmuConstants::BANK_BEGIN; slot_id <= EmuConstants::BANK_END; slot_id++) { - const ItemInst* inst = m_inv[slot_id]; - if(inst) { - std::string packet = inst->Serialize(slot_id); - ser_items[i++] = packet; - size += packet.length(); - } - } - - // Shared Bank items - for(slot_id = EmuConstants::SHARED_BANK_BEGIN; slot_id <= EmuConstants::SHARED_BANK_END; slot_id++) { - const ItemInst* inst = m_inv[slot_id]; - if(inst) { - std::string packet = inst->Serialize(slot_id); - ser_items[i++] = packet; - size += packet.length(); - } - } - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_CharInventory, size); - uchar* ptr = outapp->pBuffer; - for(itr = ser_items.begin(); itr != ser_items.end(); ++itr){ - int length = itr->second.length(); - if(length > 5) { - memcpy(ptr, itr->second.c_str(), length); - ptr += length; - } - } - QueuePacket(outapp); - safe_delete(outapp); + + EQApplicationPacket outapp(OP_CharInventory, items.Size()); + memcpy(outapp.pBuffer, items, items.Size()); + QueuePacket(&outapp); } -/*#else -void Client::BulkSendInventoryItems() -{ - // Search all inventory buckets for items - bool deletenorent=database.NoRentExpired(GetName()); - // Worn items and Inventory items - int16 slot_id = 0; - if(deletenorent){//client was offline for more than 30 minutes, delete no rent items - RemoveNoRent(); - } - for (slot_id=EmuConstants::POSSESSIONS_BEGIN; slot_id<=EmuConstants::POSSESSIONS_END; slot_id++) { - const ItemInst* inst = m_inv[slot_id]; - if (inst){ - SendItemPacket(slot_id, inst, ItemPacketCharInventory); - } - } - // Bank items - for (slot_id=EmuConstants::BANK_BEGIN; slot_id<=EmuConstants::BANK_END; slot_id++) { // 2015... - const ItemInst* inst = m_inv[slot_id]; - if (inst){ - SendItemPacket(slot_id, inst, ItemPacketCharInventory); - } - } - - // Shared Bank items - for (slot_id=EmuConstants::SHARED_BANK_BEGIN; slot_id<=EmuConstants::SHARED_BANK_END; slot_id++) { - const ItemInst* inst = m_inv[slot_id]; - if (inst){ - SendItemPacket(slot_id, inst, ItemPacketCharInventory); - } - } - - // LINKDEAD TRADE ITEMS - // If player went LD during a trade, they have items in the trade inventory - // slots. These items are now being put into their inventory (then queue up on cursor) - for (int16 trade_slot_id=EmuConstants::TRADE_BEGIN; trade_slot_id<=EmuConstants::TRADE_END; trade_slot_id++) { - const ItemInst* inst = m_inv[slot_id]; - if (inst) { - int16 free_slot_id = m_inv.FindFreeSlot(inst->IsType(ItemClassContainer), true, inst->GetItem()->Size); - DeleteItemInInventory(trade_slot_id, 0, false); - PutItemInInventory(free_slot_id, *inst, true); - } - } -} -#endif*/ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { - const Item_Struct* handyitem = nullptr; + const ItemData* handyitem = nullptr; uint32 numItemSlots = 80; //The max number of items passed in the transaction. if (m_ClientVersionBit & BIT_RoFAndLater) { // RoF+ can send 200 items numItemSlots = 200; } - const Item_Struct *item; + const ItemData *item; std::list merlist = zone->merchanttable[merchant_id]; std::list::const_iterator itr; Mob* merch = entity_list.GetMobByNpcTypeID(npcid); @@ -1017,7 +867,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { int charges = 1; if (item->ItemClass == ItemClassCommon) charges = item->MaxCharges; - ItemInst* inst = database.CreateItem(item, charges); + auto inst = database.CreateItem(item->ID, charges, false); if (inst) { if (RuleB(Merchant, UsePriceMod)) { inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate * Client::CalcPriceMod(merch, false))); @@ -1031,8 +881,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { else inst->SetCharges(1); - SendItemPacket(ml.slot - 1, inst, ItemPacketMerchant); - safe_delete(inst); + SendItemPacket(EQEmu::InventorySlot(EQEmu::InvTypePersonal, ml.slot - 1), inst, ItemPacketMerchant); } } // Account for merchant lists with gaps. @@ -1058,7 +907,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { // charges=ml.charges; //else charges = item->MaxCharges; - ItemInst* inst = database.CreateItem(item, charges); + ItemInst* inst = database.CreateItemOld(item, charges); if (inst) { if (RuleB(Merchant, UsePriceMod)) { inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate * Client::CalcPriceMod(merch, false))); @@ -1234,7 +1083,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) if(inst && inst->IsType(ItemClassCommon)) { - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); if(item && item->Scroll.Effect == (int32)(memspell->spell_id)) { diff --git a/zone/command.cpp b/zone/command.cpp index a286f92bd..5ed6e23a7 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -547,8 +547,6 @@ int command_realdispatch(Client *c, const char *message) { Seperator sep(message, ' ', 10, 100, true); // "three word argument" should be considered 1 arg - command_logcommand(c, message); - std::string cstr(sep.arg[0]+1); if(commandlist.count(cstr) != 1) { @@ -561,12 +559,6 @@ int command_realdispatch(Client *c, const char *message) return(-1); } - /* QS: Player_Log_Issued_Commands */ - if (RuleB(QueryServ, PlayerLogIssuedCommandes)){ - std::string event_desc = StringFormat("Issued command :: '%s' in zoneid:%i instid:%i", message, c->GetZoneID(), c->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Issued_Commands, c->CharacterID(), event_desc); - } - if(cur->access >= COMMANDS_LOGGING_MIN_STATUS) { Log.Out(Logs::General, Logs::Commands, "%s (%s) used command: %s (target=%s)", c->GetName(), c->AccountName(), message, c->GetTarget()?c->GetTarget()->GetName():"NONE"); } @@ -582,71 +574,6 @@ int command_realdispatch(Client *c, const char *message) } -void command_logcommand(Client *c, const char *message) -{ - int admin=c->Admin(); - - bool continueevents=false; - switch (zone->loglevelvar){ //catch failsafe - case 9: { // log only LeadGM - if ((admin>= 150) && (admin <200)) - continueevents=true; - break; - } - case 8: { // log only GM - if ((admin>= 100) && (admin <150)) - continueevents=true; - break; - } - case 1: { - if ((admin>= 200)) - continueevents=true; - break; - } - case 2: { - if ((admin>= 150)) - continueevents=true; - break; - } - case 3: { - if ((admin>= 100)) - continueevents=true; - break; - } - case 4: { - if ((admin>= 80)) - continueevents=true; - break; - } - case 5: { - if ((admin>= 20)) - continueevents=true; - break; - } - case 6: { - if ((admin>= 10)) - continueevents=true; - break; - } - case 7: { - continueevents=true; - break; - } - } - - if (continueevents) - database.logevents( - c->AccountName(), - c->AccountID(), - admin,c->GetName(), - c->GetTarget()?c->GetTarget()->GetName():"None", - "Command", - message, - 1 - ); -} - - /* * commands go below here */ @@ -2553,7 +2480,7 @@ void command_peekinv(Client *c, const Seperator *sep) Client* targetClient = c->GetTarget()->CastToClient(); const ItemInst* inst_main = nullptr; const ItemInst* inst_sub = nullptr; - const Item_Struct* item_data = nullptr; + const ItemData* item_data = nullptr; std::string item_link; Client::TextLink linker; linker.SetLinkType(linker.linkItemInst); @@ -2602,7 +2529,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + InventoryOld::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } @@ -2636,7 +2563,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(MainCursor, indexSub), MainCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + InventoryOld::CalcSlotId(MainCursor, indexSub), MainCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } } @@ -2673,7 +2600,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + InventoryOld::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } @@ -2695,7 +2622,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " SharedBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + InventoryOld::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } @@ -2718,7 +2645,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + InventoryOld::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } @@ -3119,77 +3046,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) @@ -5413,29 +5340,37 @@ void command_summonitem(Client *c, const Seperator *sep) else { uint32 itemid = atoi(sep->arg[1]); int16 item_status = 0; - const Item_Struct* item = database.GetItem(itemid); + const ItemData* item = database.GetItem(itemid); if(item) { item_status = static_cast(item->MinStatus); } - if (item_status > c->Admin()) + EQEmu::InventorySlot cursor(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor); + bool v = false; + if (item_status > c->Admin()) { c->Message(13, "Error: Insufficient status to summon this item."); + return; + } else if (sep->argnum==2 && sep->IsNumber(2)) - c->SummonItem(itemid, atoi(sep->arg[2])); + v = c->SummonItem(itemid, atoi(sep->arg[2]), cursor); else if (sep->argnum==3) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3])); + v = c->SummonItem(itemid, atoi(sep->arg[2]), cursor, atoi(sep->arg[3])); else if (sep->argnum==4) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4])); + v = c->SummonItem(itemid, atoi(sep->arg[2]), cursor, atoi(sep->arg[3]), atoi(sep->arg[4])); else if (sep->argnum==5) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5])); + v = c->SummonItem(itemid, atoi(sep->arg[2]), cursor, atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5])); else if (sep->argnum==6) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6])); + v = c->SummonItem(itemid, atoi(sep->arg[2]), cursor, atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6])); else if (sep->argnum==7) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7])); + v = c->SummonItem(itemid, atoi(sep->arg[2]), cursor, atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7])); else if (sep->argnum==8) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7]), atoi(sep->arg[8])); + v = c->SummonItem(itemid, atoi(sep->arg[2]), cursor, atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7]), atoi(sep->arg[8])); else { - c->SummonItem(itemid); + v = c->SummonItem(itemid, -1, cursor); + } + + if(!v) { + c->Message(13, "Error: unable to summon item."); } } } @@ -5452,29 +5387,37 @@ void command_giveitem(Client *c, const Seperator *sep) Client *t = c->GetTarget()->CastToClient(); uint32 itemid = atoi(sep->arg[1]); int16 item_status = 0; - const Item_Struct* item = database.GetItem(itemid); + const ItemData* item = database.GetItem(itemid); if(item) { item_status = static_cast(item->MinStatus); } - if (item_status > c->Admin()) + EQEmu::InventorySlot cursor(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor); + bool v = false; + if (item_status > c->Admin()) { c->Message(13, "Error: Insufficient status to summon this item."); + return; + } else if (sep->argnum==2 && sep->IsNumber(2)) - t->SummonItem(itemid, atoi(sep->arg[2])); + v = t->SummonItem(itemid, atoi(sep->arg[2]), cursor); else if (sep->argnum==3) - t->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3])); + v = t->SummonItem(itemid, atoi(sep->arg[2]), cursor, atoi(sep->arg[3])); else if (sep->argnum==4) - t->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4])); + v = t->SummonItem(itemid, atoi(sep->arg[2]), cursor, atoi(sep->arg[3]), atoi(sep->arg[4])); else if (sep->argnum==5) - t->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5])); + v = t->SummonItem(itemid, atoi(sep->arg[2]), cursor, atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5])); else if (sep->argnum==6) - t->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6])); + v = t->SummonItem(itemid, atoi(sep->arg[2]), cursor, atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6])); else if (sep->argnum==7) - t->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7])); + v = t->SummonItem(itemid, atoi(sep->arg[2]), cursor, atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7])); else if (sep->argnum == 7) - t->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7]), atoi(sep->arg[8])); + v = t->SummonItem(itemid, atoi(sep->arg[2]), cursor, atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7]), atoi(sep->arg[8])); else { - t->SummonItem(itemid); + v = t->SummonItem(itemid, -1, cursor); + } + + if(!v) { + c->Message(13, "Error: Unable to summon item on target."); } } } @@ -5505,7 +5448,7 @@ void command_itemsearch(Client *c, const Seperator *sep) { const char *search_criteria=sep->argplus[1]; - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; std::string item_link; Client::TextLink linker; linker.SetLinkType(linker.linkItemData); @@ -10179,7 +10122,7 @@ void command_zopp(Client *c, const Seperator *sep) uint32 itemid = atoi(sep->arg[3]); int16 charges = sep->argnum == 4 ? atoi(sep->arg[4]) : 1; // defaults to 1 charge if not specified - const Item_Struct* FakeItem = database.GetItem(itemid); + const ItemData* FakeItem = database.GetItem(itemid); if (!FakeItem) { c->Message(13, "Error: Item [%u] is not a valid item id.", itemid); @@ -10187,7 +10130,7 @@ void command_zopp(Client *c, const Seperator *sep) } int16 item_status = 0; - const Item_Struct* item = database.GetItem(itemid); + const ItemData* item = database.GetItem(itemid); if(item) { item_status = static_cast(item->MinStatus); } @@ -10201,7 +10144,7 @@ void command_zopp(Client *c, const Seperator *sep) c->Message(0, "Processing request..results may cause unpredictable behavior."); } - ItemInst* FakeItemInst = database.CreateItem(FakeItem, charges); + ItemInst* FakeItemInst = database.CreateItemOld(FakeItem, charges); c->SendItemPacket(slotid, FakeItemInst, packettype); c->Message(0, "Sending zephyr op packet to client - [%s] %s (%u) with %i %s to slot %i.", packettype == ItemPacketTrade ? "Trade" : "Summon", FakeItem->Name, itemid, charges, diff --git a/zone/command.h b/zone/command.h index 0560b8eff..04e51866a 100644 --- a/zone/command.h +++ b/zone/command.h @@ -60,7 +60,6 @@ void command_deinit(void); int command_add(const char *command_string, const char *desc, int access, CmdFuncPtr function); int command_notavail(Client *c, const char *message); int command_realdispatch(Client *c, char const *message); -void command_logcommand(Client *c, const char *message); //commands void command_resetaa(Client* c,const Seperator *sep); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index fad65aa3a..f82695bac 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -411,7 +411,7 @@ void Corpse::MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, s if (equipSlot < EmuConstants::GENERAL_BEGIN || equipSlot > MainCursor) { break; } for (auto sub_index = SUB_BEGIN; sub_index < EmuConstants::ITEM_CONTAINER_SIZE; ++sub_index) { - int16 real_bag_slot = Inventory::CalcSlotId(equipSlot, sub_index); + int16 real_bag_slot = InventoryOld::CalcSlotId(equipSlot, sub_index); auto bag_inst = client->GetInv().GetItem(real_bag_slot); if (bag_inst == nullptr) { continue; } @@ -690,8 +690,8 @@ ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct** } } - if (sitem && bag_item_data && Inventory::SupportsContainers(sitem->equip_slot)) { - int16 bagstart = Inventory::CalcSlotId(sitem->equip_slot, SUB_BEGIN); + if (sitem && bag_item_data && InventoryOld::SupportsContainers(sitem->equip_slot)) { + int16 bagstart = InventoryOld::CalcSlotId(sitem->equip_slot, SUB_BEGIN); cur = itemlist.begin(); end = itemlist.end(); @@ -745,7 +745,7 @@ void Corpse::RemoveItem(ServerLootItem_Struct* item_data) is_corpse_changed = true; itemlist.erase(iter); - uint8 material = Inventory::CalcMaterialFromSlot(sitem->equip_slot); // autos to unsigned char + uint8 material = InventoryOld::CalcMaterialFromSlot(sitem->equip_slot); // autos to unsigned char if (material != _MaterialInvalid) SendWearChange(material); @@ -978,8 +978,8 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a safe_delete(outapp); if(Loot_Request_Type == 5) { int pkitem = GetPlayerKillItem(); - const Item_Struct* item = database.GetItem(pkitem); - ItemInst* inst = database.CreateItem(item, item->MaxCharges); + const ItemData* item = database.GetItem(pkitem); + ItemInst* inst = database.CreateItemOld(item, item->MaxCharges); if(inst) { if (item->RecastDelay) inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); @@ -993,7 +993,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a } int i = 0; - const Item_Struct* item = 0; + const ItemData* item = 0; ItemList::iterator cur,end; cur = itemlist.begin(); end = itemlist.end(); @@ -1012,7 +1012,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if(i < corpselootlimit) { item = database.GetItem(item_data->item_id); if(client && item) { - ItemInst* inst = database.CreateItem(item, item_data->charges, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned); + ItemInst* inst = database.CreateItemOld(item, item_data->charges, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned); if(inst) { if (item->RecastDelay) inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); @@ -1108,7 +1108,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { being_looted_by = 0xFFFFFFFF; return; } - const Item_Struct* item = 0; + const ItemData* item = 0; ItemInst *inst = 0; ServerLootItem_Struct* item_data = nullptr, *bag_item_data[10]; @@ -1129,10 +1129,10 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { if (item != 0) { if (item_data){ - inst = database.CreateItem(item, item_data ? item_data->charges : 0, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned); + inst = database.CreateItemOld(item, item_data ? item_data->charges : 0, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned); } else { - inst = database.CreateItem(item); + inst = database.CreateItemOld(item); } } @@ -1303,7 +1303,7 @@ void Corpse::QueryLoot(Client* to) { else x < corpselootlimit ? sitem->lootslot = x : sitem->lootslot = 0xFFFF; - const Item_Struct* item = database.GetItem(sitem->item_id); + const ItemData* item = database.GetItem(sitem->item_id); if (item) to->Message((sitem->lootslot == 0xFFFF), "LootSlot: %i (EquipSlot: %i) Item: %s (%d), Count: %i", static_cast(sitem->lootslot), sitem->equip_slot, item->Name, item->ID, sitem->charges); @@ -1317,7 +1317,7 @@ void Corpse::QueryLoot(Client* to) { } else { sitem->lootslot=y; - const Item_Struct* item = database.GetItem(sitem->item_id); + const ItemData* item = database.GetItem(sitem->item_id); if (item) to->Message(0, "LootSlot: %i Item: %s (%d), Count: %i", sitem->lootslot, item->Name, item->ID, sitem->charges); @@ -1404,7 +1404,7 @@ uint32 Corpse::GetEquipment(uint8 material_slot) const { return NO_ITEM; } - invslot = Inventory::CalcSlotFromMaterial(material_slot); + invslot = InventoryOld::CalcSlotFromMaterial(material_slot); if(invslot == INVALID_INDEX) // GetWornItem() should be returning a NO_ITEM for any invalid index... return NO_ITEM; @@ -1412,7 +1412,7 @@ uint32 Corpse::GetEquipment(uint8 material_slot) const { } uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { - const Item_Struct *item; + const ItemData *item; if(material_slot > EmuConstants::MATERIAL_END) { return 0; diff --git a/zone/effects.cpp b/zone/effects.cpp index 55e56cdac..8ed2af6bf 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -464,7 +464,7 @@ int32 Client::GetActSpellCasttime(uint16 spell_id, int32 casttime) bool Client::TrainDiscipline(uint32 itemid) { //get the item info - const Item_Struct *item = database.GetItem(itemid); + const ItemData *item = database.GetItem(itemid); if(item == nullptr) { Message(13, "Unable to find the tome you turned in!"); Log.Out(Logs::General, Logs::Error, "Unable to find turned in tome id %lu\n", (unsigned long)itemid); diff --git a/zone/embparser.cpp b/zone/embparser.cpp index d571dce24..a47594c92 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -863,8 +863,8 @@ void PerlembParser::GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlaye } } else if(isItemQuest) { - // need a valid ItemInst pointer check here..unsure how to cancel this process - const Item_Struct* item = iteminst->GetItem(); + // need a valid ItemInst pointer check here..unsure how to cancel this process -U + const ItemData* item = iteminst->GetItem(); package_name = "qst_item_"; package_name += itoa(item->ID); } diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 6db7777ac..de49b6040 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3520,10 +3520,11 @@ XS(XS__qs_player_event) if (items != 2){ Perl_croak(aTHX_ "Usage: qs_player_event(char_id, event_desc)"); } - else{ + else { int char_id = (int)SvIV(ST(0)); std::string event_desc = (std::string)SvPV_nolen(ST(1)); - QServ->PlayerLogEvent(Player_Log_Quest, char_id, event_desc); + Client *c = entity_list.GetClientByCharID(char_id); + zone->LogEvent(EventLogQuest, c, event_desc); } XSRETURN_EMPTY; } diff --git a/zone/embxs.cpp b/zone/embxs.cpp index 664416587..c94834d7c 100644 --- a/zone/embxs.cpp +++ b/zone/embxs.cpp @@ -29,7 +29,7 @@ const char *getItemName(unsigned itemid) { - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; item = database.GetItem(itemid); if (item) diff --git a/zone/entity.cpp b/zone/entity.cpp index c7493b907..1f3ec384a 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1935,7 +1935,7 @@ void EntityList::QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struc memcpy(outgbius, gbius, sizeof(GuildBankItemUpdate_Struct)); - const Item_Struct *Item = database.GetItem(gbius->ItemID); + const ItemData *Item = database.GetItem(gbius->ItemID); auto it = client_list.begin(); while (it != client_list.end()) { @@ -3831,7 +3831,7 @@ void EntityList::GroupMessage(uint32 gid, const char *from, const char *message) uint16 EntityList::CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time) { - const Item_Struct *is = database.GetItem(itemid); + const ItemData *is = database.GetItem(itemid); if (!is) return 0; diff --git a/zone/exp.cpp b/zone/exp.cpp index 826b12e67..0982aeac3 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -152,7 +152,7 @@ uint32 Client::CalcEXP(uint8 conlevel) { void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { - this->EVENT_ITEM_ScriptStopReturn(); + ItemScriptStopReturn(); uint32 add_exp = in_add_exp; @@ -430,13 +430,6 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { //Message(15, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA); char val1[20]={0}; Message_StringID(MT_Experience, GAIN_ABILITY_POINT,ConvertArray(m_pp.aapoints, val1),m_pp.aapoints == 1 ? "" : "(s)"); //You have gained an ability point! You now have %1 ability point%2. - - /* QS: PlayerLogAARate */ - if (RuleB(QueryServ, PlayerLogAARate)){ - int add_points = (m_pp.aapoints - last_unspentAA); - std::string query = StringFormat("INSERT INTO `qs_player_aa_rate_hourly` (char_id, aa_count, hour_time) VALUES (%i, %i, UNIX_TIMESTAMP() - MOD(UNIX_TIMESTAMP(), 3600)) ON DUPLICATE KEY UPDATE `aa_count` = `aa_count` + %i", this->CharacterID(), add_points, add_points); - QServ->SendQuery(query.c_str()); - } //Message(15, "You now have %d skill points available to spend.", m_pp.aapoints); } @@ -571,18 +564,6 @@ void Client::SetLevel(uint8 set_level, bool command) } if(set_level > m_pp.level) { parse->EventPlayer(EVENT_LEVEL_UP, this, "", 0); - /* QS: PlayerLogLevels */ - if (RuleB(QueryServ, PlayerLogLevels)){ - std::string event_desc = StringFormat("Leveled UP :: to Level:%i from Level:%i in zoneid:%i instid:%i", set_level, m_pp.level, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Levels, this->CharacterID(), event_desc); - } - } - else if (set_level < m_pp.level){ - /* QS: PlayerLogLevels */ - if (RuleB(QueryServ, PlayerLogLevels)){ - std::string event_desc = StringFormat("Leveled DOWN :: to Level:%i from Level:%i in zoneid:%i instid:%i", set_level, m_pp.level, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Levels, this->CharacterID(), event_desc); - } } m_pp.level = set_level; diff --git a/zone/forage.cpp b/zone/forage.cpp index 89d4e254f..7bbca0b49 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -304,10 +304,10 @@ void Client::GoFish() food_id = common_fish_ids[index]; } - const Item_Struct* food_item = database.GetItem(food_id); + const ItemData* food_item = database.GetItem(food_id); Message_StringID(MT_Skills, FISHING_SUCCESS); - ItemInst* inst = database.CreateItem(food_item, 1); + ItemInst* inst = database.CreateItemOld(food_item, 1); if(inst != nullptr) { if(CheckLoreConflict(inst->GetItem())) { @@ -396,7 +396,7 @@ void Client::ForageItem(bool guarantee) { foragedfood = common_food_ids[index]; } - const Item_Struct* food_item = database.GetItem(foragedfood); + const ItemData* food_item = database.GetItem(foragedfood); if(!food_item) { Log.Out(Logs::General, Logs::Error, "nullptr returned from database.GetItem in ClientForageItem"); @@ -423,7 +423,7 @@ void Client::ForageItem(bool guarantee) { } Message_StringID(MT_Skills, stringid); - ItemInst* inst = database.CreateItem(food_item, 1); + ItemInst* inst = database.CreateItemOld(food_item, 1); if(inst != nullptr) { // check to make sure it isn't a foraged lore item if(CheckLoreConflict(inst->GetItem())) diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index a5188def9..e5d79c621 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -692,7 +692,7 @@ void GuildBankManager::SendGuildBank(Client *c) { if((*Iterator)->Items.DepositArea[i].ItemID > 0) { - const Item_Struct *Item = database.GetItem((*Iterator)->Items.DepositArea[i].ItemID); + const ItemData *Item = database.GetItem((*Iterator)->Items.DepositArea[i].ItemID); if(!Item) continue; @@ -728,7 +728,7 @@ void GuildBankManager::SendGuildBank(Client *c) { if((*Iterator)->Items.MainArea[i].ItemID > 0) { - const Item_Struct *Item = database.GetItem((*Iterator)->Items.MainArea[i].ItemID); + const ItemData *Item = database.GetItem((*Iterator)->Items.MainArea[i].ItemID); if(!Item) continue; @@ -859,7 +859,7 @@ bool GuildBankManager::AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32 return false; } - const Item_Struct *Item = database.GetItem(ItemID); + const ItemData *Item = database.GetItem(ItemID); GuildBankItemUpdate_Struct gbius; @@ -925,7 +925,7 @@ int GuildBankManager::Promote(uint32 guildID, int slotID) (*iter)->Items.DepositArea[slotID].ItemID = 0; - const Item_Struct *Item = database.GetItem((*iter)->Items.MainArea[mainSlot].ItemID); + const ItemData *Item = database.GetItem((*iter)->Items.MainArea[mainSlot].ItemID); GuildBankItemUpdate_Struct gbius; @@ -981,7 +981,7 @@ void GuildBankManager::SetPermissions(uint32 guildID, uint16 slotID, uint32 perm else (*iter)->Items.MainArea[slotID].WhoFor[0] = '\0'; - const Item_Struct *Item = database.GetItem((*iter)->Items.MainArea[slotID].ItemID); + const ItemData *Item = database.GetItem((*iter)->Items.MainArea[slotID].ItemID); GuildBankItemUpdate_Struct gbius; @@ -1021,7 +1021,7 @@ ItemInst* GuildBankManager::GetItem(uint32 GuildID, uint16 Area, uint16 SlotID, if((SlotID > (GUILD_BANK_DEPOSIT_AREA_SIZE - 1))) return nullptr; - inst = database.CreateItem((*Iterator)->Items.DepositArea[SlotID].ItemID); + inst = database.CreateItemOld((*Iterator)->Items.DepositArea[SlotID].ItemID); if(!inst) return nullptr; @@ -1034,7 +1034,7 @@ ItemInst* GuildBankManager::GetItem(uint32 GuildID, uint16 Area, uint16 SlotID, if((SlotID > (GUILD_BANK_MAIN_AREA_SIZE - 1))) return nullptr; - inst = database.CreateItem((*Iterator)->Items.MainArea[SlotID].ItemID); + inst = database.CreateItemOld((*Iterator)->Items.MainArea[SlotID].ItemID); if(!inst) return nullptr; @@ -1112,7 +1112,7 @@ bool GuildBankManager::DeleteItem(uint32 guildID, uint16 area, uint16 slotID, ui bool deleted = true; - const Item_Struct *Item = database.GetItem(BankArea[slotID].ItemID); + const ItemData *Item = database.GetItem(BankArea[slotID].ItemID); if(!Item->Stackable || (quantity >= BankArea[slotID].Quantity)) { std::string query = StringFormat("DELETE FROM `guild_bank` WHERE `guildid` = %i " @@ -1173,7 +1173,7 @@ bool GuildBankManager::MergeStacks(uint32 GuildID, uint16 SlotID) if(BankArea[SlotID].ItemID == 0) return false; - const Item_Struct *Item = database.GetItem(BankArea[SlotID].ItemID); + const ItemData *Item = database.GetItem(BankArea[SlotID].ItemID); if(!Item->Stackable) return false; @@ -1271,7 +1271,7 @@ bool GuildBankManager::SplitStack(uint32 GuildID, uint16 SlotID, uint32 Quantity if(BankArea[SlotID].Quantity <= Quantity || Quantity == 0) return false; - const Item_Struct *Item = database.GetItem(BankArea[SlotID].ItemID); + const ItemData *Item = database.GetItem(BankArea[SlotID].ItemID); if(!Item->Stackable) return false; diff --git a/zone/inventory.cpp b/zone/inventory.cpp index e1904d59f..769c9285c 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -18,8 +18,9 @@ #include "../common/global_define.h" #include "../common/eqemu_logsys.h" - #include "../common/string_util.h" +#include "../common/data_verification.h" +#include "../common/item_data.h" #include "quest_parser_collection.h" #include "worldserver.h" #include "zonedb.h" @@ -177,7 +178,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } -bool Client::CheckLoreConflict(const Item_Struct* item) +bool Client::CheckLoreConflict(const ItemData* item) { if (!item) { return false; } if (!item->LoreFlag) { return false; } @@ -191,11 +192,11 @@ bool Client::CheckLoreConflict(const Item_Struct* item) } bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, bool attuned, uint16 to_slot, uint32 ornament_icon, uint32 ornament_idfile, uint32 ornament_hero_model) { - this->EVENT_ITEM_ScriptStopReturn(); + ItemScriptStopReturn(); // TODO: update calling methods and script apis to handle a failure return - const Item_Struct* item = database.GetItem(item_id); + const ItemData* item = database.GetItem(item_id); // make sure the item exists if(item == nullptr) { @@ -247,7 +248,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, bool enforceusable = RuleB(Inventory, EnforceAugmentUsability); for (int iter = AUG_BEGIN; iter < EmuConstants::ITEM_COMMON_SIZE; ++iter) { - const Item_Struct* augtest = database.GetItem(augments[iter]); + const ItemData* augtest = database.GetItem(augments[iter]); if(augtest == nullptr) { if(augments[iter]) { @@ -528,7 +529,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // in any other situation just use charges as passed - ItemInst* inst = database.CreateItem(item, charges); + ItemInst* inst = database.CreateItemOld(item, charges); if(inst == nullptr) { Message(13, "An unknown server error has occurred and your item was not created."); @@ -716,122 +717,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 = Inventory::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;looppBuffer; - 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;looppBuffer; +// 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) @@ -864,7 +865,7 @@ bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client if (client_update) { SendItemPacket(slot_id, &inst, ((slot_id == MainCursor) ? ItemPacketSummonItem : ItemPacketTrade)); - //SendWearChange(Inventory::CalcMaterialFromSlot(slot_id)); + //SendWearChange(InventoryOld::CalcMaterialFromSlot(slot_id)); } if (slot_id == MainCursor) { @@ -910,7 +911,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI if (bag_item_data[index] == nullptr) continue; - const ItemInst *bagitem = database.CreateItem( + const ItemInst *bagitem = database.CreateItemOld( bag_item_data[index]->item_id, bag_item_data[index]->charges, bag_item_data[index]->aug_1, @@ -932,7 +933,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI PutLootInInventory(MainCursor, *bagitem); } else { - auto bag_slot = Inventory::CalcSlotId(slot_id, index); + auto bag_slot = InventoryOld::CalcSlotId(slot_id, index); Log.Out(Logs::Detail, Logs::Inventory, "Putting bag loot item %s (%d) into slot %d (bag slot %d)", @@ -946,6 +947,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI CalcBonuses(); } + bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cursor){ if(!item || !item->IsStackable() || item->GetCharges()>=item->GetItem()->StackSize) return false; @@ -964,7 +966,7 @@ bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cur } for (i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) { for (uint8 j = SUB_BEGIN; j < EmuConstants::ITEM_CONTAINER_SIZE; j++) { - uint16 slotid = Inventory::CalcSlotId(i, j); + uint16 slotid = InventoryOld::CalcSlotId(i, j); ItemInst* tmp_inst = m_inv.GetItem(slotid); if(tmp_inst && tmp_inst->GetItem()->ID == item_id && tmp_inst->GetCharges() < tmp_inst->GetItem()->StackSize) { @@ -1017,7 +1019,7 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs if (inst.IsEquipable(i)) { // Equippable at this slot? //send worn to everyone... PutLootInInventory(i, inst); - uint8 worn_slot_material = Inventory::CalcMaterialFromSlot(i); + uint8 worn_slot_material = InventoryOld::CalcMaterialFromSlot(i); if (worn_slot_material != _MaterialInvalid) { SendWearChange(worn_slot_material); } @@ -1073,7 +1075,7 @@ void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type) #if 0 // TODO: needs clean-up to save references -bool MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint8 evolving, uint8 evolvedlevel) { +bool MakeItemLink(char* &ret_link, const ItemData *item, uint32 aug0, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint8 evolving, uint8 evolvedlevel) { //we're sending back the entire "link", minus the null characters & item name //that way, we can use it for regular links & Task links //note: initiator needs to pass us ret_link @@ -1188,7 +1190,7 @@ int Client::GetItemLinkHash(const ItemInst* inst) { if (!inst) //have to have an item to make the hash return 0; - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); char* hash_str = 0; /*register */int hash = 0; @@ -1282,7 +1284,7 @@ packet with the item number in it, but I cant seem to find it right now if (!inst) return; - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); const char* name2 = &item->Name[0]; EQApplicationPacket* outapp = new EQApplicationPacket(OP_ItemLinkText,strlen(name2)+68); char buffer2[135] = {0}; @@ -1351,7 +1353,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; @@ -1374,7 +1376,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } if (move_in->from_slot == move_in->to_slot) { // Item summon, no further processing needed - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit + if (GetClientVersion() >= ClientVersion::RoF) { return true; } // Can't do RoF+ if (move_in->to_slot == MainCursor) { @@ -1406,7 +1408,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if (move_in->to_slot == (uint32)INVALID_INDEX) { if (move_in->from_slot == (uint32)MainCursor) { Log.Out(Logs::Detail, Logs::Inventory, "Client destroyed item from cursor slot %d", move_in->from_slot); - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit + ItemInst *inst = m_inv.GetItem(MainCursor); if(inst) { @@ -1420,7 +1422,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } else { Log.Out(Logs::Detail, Logs::Inventory, "Deleted item from slot %d as a result of an inventory container tradeskill combine.", move_in->from_slot); - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit + DeleteItemInInventory(move_in->from_slot); return true; // Item deletion } @@ -1517,8 +1519,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(src_slot_id >= EmuConstants::SHARED_BANK_BEGIN && src_slot_id <= EmuConstants::SHARED_BANK_END && src_inst->IsType(ItemClassContainer)){ for (uint8 idx = SUB_BEGIN; idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = src_inst->GetItem(idx); - if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(src_slot_id, idx), baginst)){ - DeleteItemInInventory(Inventory::CalcSlotId(src_slot_id, idx),0,false); + if(baginst && !database.VerifyInventory(account_id, InventoryOld::CalcSlotId(src_slot_id, idx), baginst)){ + DeleteItemInInventory(InventoryOld::CalcSlotId(src_slot_id, idx),0,false); } } } @@ -1532,8 +1534,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(dst_slot_id >= EmuConstants::SHARED_BANK_BEGIN && dst_slot_id <= EmuConstants::SHARED_BANK_END && dst_inst->IsType(ItemClassContainer)){ for (uint8 idx = SUB_BEGIN; idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = dst_inst->GetItem(idx); - if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(dst_slot_id, idx), baginst)){ - DeleteItemInInventory(Inventory::CalcSlotId(dst_slot_id, idx),0,false); + if(baginst && !database.VerifyInventory(account_id, InventoryOld::CalcSlotId(dst_slot_id, idx), baginst)){ + DeleteItemInInventory(InventoryOld::CalcSlotId(dst_slot_id, idx),0,false); } } } @@ -1554,7 +1556,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { else { auto ndh_item = ndh_inst->GetItem(); if (ndh_item == nullptr) { - ndh_item_data.append("[nullptr on Item_Struct*]"); + ndh_item_data.append("[nullptr on ItemData*]"); } else { ndh_item_data.append(StringFormat("name=%s", ndh_item->Name)); @@ -1575,19 +1577,19 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(m_tradeskill_object != nullptr) { if (src_slot_id >= EmuConstants::WORLD_BEGIN && src_slot_id <= EmuConstants::WORLD_END) { // Picking up item from world container - ItemInst* inst = m_tradeskill_object->PopItem(Inventory::CalcBagIdx(src_slot_id)); + ItemInst* inst = m_tradeskill_object->PopItem(InventoryOld::CalcBagIdx(src_slot_id)); if (inst) { PutItemInInventory(dst_slot_id, *inst, false); safe_delete(inst); } - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in, true); } // QS Audit + return true; } else if (dst_slot_id >= EmuConstants::WORLD_BEGIN && dst_slot_id <= EmuConstants::WORLD_END) { // Putting item into world container, which may swap (or pile onto) with existing item - uint8 world_idx = Inventory::CalcBagIdx(dst_slot_id); + uint8 world_idx = InventoryOld::CalcBagIdx(dst_slot_id); ItemInst* world_inst = m_tradeskill_object->PopItem(world_idx); // Case 1: No item in container, unidirectional "Put" @@ -1596,8 +1598,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { m_inv.DeleteItem(src_slot_id); } else { - const Item_Struct* world_item = world_inst->GetItem(); - const Item_Struct* src_item = src_inst->GetItem(); + const ItemData* world_item = world_inst->GetItem(); + const ItemData* src_item = src_inst->GetItem(); if (world_item && src_item) { // Case 2: Same item on cursor, stacks, transfer of charges needed if ((world_item->ID == src_item->ID) && src_inst->IsStackable()) { @@ -1651,7 +1653,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { database.SaveInventory(character_id, m_inv[src_slot_id], src_slot_id); } - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in, true); } // QS Audit + return true; } @@ -1673,7 +1675,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Add cursor item to trade bucket // Also sends trade information to other client of trade session - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit + trade->AddEntity(dst_slot_id, move_in->number_in_stack); if (dstitemid == 0) @@ -1683,9 +1685,9 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return true; } else { - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit + - SummonItem(src_inst->GetID(), src_inst->GetCharges()); + SummonItem(src_inst->GetID(), src_inst->GetCharges(), 0); DeleteItemInInventory(MainCursor); return true; @@ -1743,7 +1745,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Split into two src_inst->SetCharges(src_inst->GetCharges() - move_in->number_in_stack); Log.Out(Logs::Detail, Logs::Inventory, "Split stack of %s (%d) from slot %d to %d with stack size %d. Src keeps %d.", src_inst->GetItem()->Name, src_inst->GetItem()->ID, src_slot_id, dst_slot_id, move_in->number_in_stack, src_inst->GetCharges()); - ItemInst* inst = database.CreateItem(src_inst->GetItem(), move_in->number_in_stack); + ItemInst* inst = database.CreateItemOld(src_inst->GetItem(), move_in->number_in_stack); m_inv.PutItem(dst_slot_id, *inst); safe_delete(inst); } @@ -1817,14 +1819,14 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { database.SaveInventory(character_id, m_inv.GetItem(dst_slot_id), dst_slot_id); } - if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in, true); } // QS Audit + // Step 8: Re-calc stats CalcBonuses(); 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 @@ -1834,12 +1836,11 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { Message(15, "Inventory Desyncronization detected: Resending slot data..."); if((move_slots->from_slot >= EmuConstants::EQUIPMENT_BEGIN && move_slots->from_slot <= EmuConstants::CURSOR_BAG_END) || move_slots->from_slot == MainPowerSource) { - int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); + int16 resync_slot = (InventoryOld::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : InventoryOld::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { - // This prevents the client from crashing when closing any 'phantom' bags - const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' - ItemInst* token_inst = database.CreateItem(token_struct, 1); - + // This prevents the client from crashing when closing any 'phantom' bags -U + const ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' + ItemInst* token_inst = database.CreateItemOld(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); if(m_inv[resync_slot]) { SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade); } @@ -1859,11 +1860,11 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { else { Message(13, "Could not resyncronize source slot %i.", move_slots->from_slot); } } else { - int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); + int16 resync_slot = (InventoryOld::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : InventoryOld::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { if(m_inv[resync_slot]) { - const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' - ItemInst* token_inst = database.CreateItem(token_struct, 1); + const ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' + ItemInst* token_inst = database.CreateItemOld(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade); @@ -1877,10 +1878,10 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { } if((move_slots->to_slot >= EmuConstants::EQUIPMENT_BEGIN && move_slots->to_slot <= EmuConstants::CURSOR_BAG_END) || move_slots->to_slot == MainPowerSource) { - int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); + int16 resync_slot = (InventoryOld::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : InventoryOld::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { - const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' - ItemInst* token_inst = database.CreateItem(token_struct, 1); + const ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' + ItemInst* token_inst = database.CreateItemOld(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); @@ -1901,11 +1902,11 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { else { Message(13, "Could not resyncronize destination slot %i.", move_slots->to_slot); } } else { - int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); + int16 resync_slot = (InventoryOld::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : InventoryOld::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { if(m_inv[resync_slot]) { - const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' - ItemInst* token_inst = database.CreateItem(token_struct, 1); + const ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' + ItemInst* token_inst = database.CreateItemOld(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade); @@ -1919,104 +1920,6 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { } } -void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { - int16 from_slot_id = static_cast(move_in->from_slot); - int16 to_slot_id = static_cast(move_in->to_slot); - int16 move_amount = static_cast(move_in->number_in_stack); - - if(!m_inv[from_slot_id] && !m_inv[to_slot_id]) { return; } - - uint16 move_count = 0; - - if(m_inv[from_slot_id]) { move_count += m_inv[from_slot_id]->GetTotalItemCount(); } - if(to_slot_id != from_slot_id) { if(m_inv[to_slot_id]) { move_count += m_inv[to_slot_id]->GetTotalItemCount(); } } - - ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogMoves, sizeof(QSPlayerLogMove_Struct) + (sizeof(QSMoveItems_Struct) * move_count)); - QSPlayerLogMove_Struct* qsaudit = (QSPlayerLogMove_Struct*)qspack->pBuffer; - - qsaudit->char_id = character_id; - qsaudit->stack_size = move_amount; - qsaudit->char_count = move_count; - qsaudit->postaction = postaction_call; - qsaudit->from_slot = from_slot_id; - qsaudit->to_slot = to_slot_id; - - move_count = 0; - - const ItemInst* from_inst = m_inv[postaction_call?to_slot_id:from_slot_id]; - - if(from_inst) { - qsaudit->items[move_count].from_slot = from_slot_id; - qsaudit->items[move_count].to_slot = to_slot_id; - qsaudit->items[move_count].item_id = from_inst->GetID(); - qsaudit->items[move_count].charges = from_inst->GetCharges(); - qsaudit->items[move_count].aug_1 = from_inst->GetAugmentItemID(1); - qsaudit->items[move_count].aug_2 = from_inst->GetAugmentItemID(2); - qsaudit->items[move_count].aug_3 = from_inst->GetAugmentItemID(3); - qsaudit->items[move_count].aug_4 = from_inst->GetAugmentItemID(4); - qsaudit->items[move_count++].aug_5 = from_inst->GetAugmentItemID(5); - - if(from_inst->IsType(ItemClassContainer)) { - for(uint8 bag_idx = SUB_BEGIN; bag_idx < from_inst->GetItem()->BagSlots; bag_idx++) { - const ItemInst* from_baginst = from_inst->GetItem(bag_idx); - - if(from_baginst) { - qsaudit->items[move_count].from_slot = Inventory::CalcSlotId(from_slot_id, bag_idx); - qsaudit->items[move_count].to_slot = Inventory::CalcSlotId(to_slot_id, bag_idx); - qsaudit->items[move_count].item_id = from_baginst->GetID(); - qsaudit->items[move_count].charges = from_baginst->GetCharges(); - qsaudit->items[move_count].aug_1 = from_baginst->GetAugmentItemID(1); - qsaudit->items[move_count].aug_2 = from_baginst->GetAugmentItemID(2); - qsaudit->items[move_count].aug_3 = from_baginst->GetAugmentItemID(3); - qsaudit->items[move_count].aug_4 = from_baginst->GetAugmentItemID(4); - qsaudit->items[move_count++].aug_5 = from_baginst->GetAugmentItemID(5); - } - } - } - } - - if(to_slot_id != from_slot_id) { - const ItemInst* to_inst = m_inv[postaction_call?from_slot_id:to_slot_id]; - - if(to_inst) { - qsaudit->items[move_count].from_slot = to_slot_id; - qsaudit->items[move_count].to_slot = from_slot_id; - qsaudit->items[move_count].item_id = to_inst->GetID(); - qsaudit->items[move_count].charges = to_inst->GetCharges(); - qsaudit->items[move_count].aug_1 = to_inst->GetAugmentItemID(1); - qsaudit->items[move_count].aug_2 = to_inst->GetAugmentItemID(2); - qsaudit->items[move_count].aug_3 = to_inst->GetAugmentItemID(3); - qsaudit->items[move_count].aug_4 = to_inst->GetAugmentItemID(4); - qsaudit->items[move_count++].aug_5 = to_inst->GetAugmentItemID(5); - - if(to_inst->IsType(ItemClassContainer)) { - for(uint8 bag_idx = SUB_BEGIN; bag_idx < to_inst->GetItem()->BagSlots; bag_idx++) { - const ItemInst* to_baginst = to_inst->GetItem(bag_idx); - - if(to_baginst) { - qsaudit->items[move_count].from_slot = Inventory::CalcSlotId(to_slot_id, bag_idx); - qsaudit->items[move_count].to_slot = Inventory::CalcSlotId(from_slot_id, bag_idx); - qsaudit->items[move_count].item_id = to_baginst->GetID(); - qsaudit->items[move_count].charges = to_baginst->GetCharges(); - qsaudit->items[move_count].aug_1 = to_baginst->GetAugmentItemID(1); - qsaudit->items[move_count].aug_2 = to_baginst->GetAugmentItemID(2); - qsaudit->items[move_count].aug_3 = to_baginst->GetAugmentItemID(3); - qsaudit->items[move_count].aug_4 = to_baginst->GetAugmentItemID(4); - qsaudit->items[move_count++].aug_5 = to_baginst->GetAugmentItemID(5); - } - } - } - } - } - - if(move_count && worldserver.Connected()) { - qspack->Deflate(); - worldserver.SendPacket(qspack); - } - - safe_delete(qspack); -} - void Client::DyeArmor(DyeStruct* dye){ int16 slot=0; for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_TINT_END; i++) { @@ -2058,7 +1961,7 @@ void Client::DyeArmor(DyeStruct* dye){ #if 0 bool Client::DecreaseByItemType(uint32 type, uint8 amt) { - const Item_Struct* TempItem = 0; + const ItemData* TempItem = 0; ItemInst* ins; int x; for(x=EmuConstants::POSSESSIONS_BEGIN; x <= EmuConstants::POSSESSIONS_END; x++) @@ -2110,7 +2013,7 @@ bool Client::DecreaseByItemType(uint32 type, uint8 amt) { #endif bool Client::DecreaseByID(uint32 type, uint8 amt) { - const Item_Struct* TempItem = nullptr; + const ItemData* TempItem = nullptr; ItemInst* ins = nullptr; int x; int num = 0; @@ -2230,113 +2133,114 @@ static bool CopyBagContents(ItemInst* new_bag, const ItemInst* old_bag) void Client::DisenchantSummonedBags(bool client_update) { - for (auto slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; ++slot_id) { - auto inst = m_inv[slot_id]; - if (!inst) { continue; } - if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } - if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; } - if (inst->GetTotalItemCount() == 1) { continue; } - - auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); - if (!new_id) { continue; } - auto new_item = database.GetItem(new_id); - if (!new_item) { continue; } - auto new_inst = database.CreateBaseItem(new_item); - if (!new_inst) { continue; } - - if (CopyBagContents(new_inst, inst)) { - Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, slot_id); - PutItemInInventory(slot_id, *new_inst, client_update); - } - safe_delete(new_inst); - } - - for (auto slot_id = EmuConstants::BANK_BEGIN; slot_id <= EmuConstants::BANK_END; ++slot_id) { - auto inst = m_inv[slot_id]; - if (!inst) { continue; } - if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } - if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; } - if (inst->GetTotalItemCount() == 1) { continue; } - - auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); - if (!new_id) { continue; } - auto new_item = database.GetItem(new_id); - if (!new_item) { continue; } - auto new_inst = database.CreateBaseItem(new_item); - if (!new_inst) { continue; } - - if (CopyBagContents(new_inst, inst)) { - Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, slot_id); - PutItemInInventory(slot_id, *new_inst, client_update); - } - safe_delete(new_inst); - } - - for (auto slot_id = EmuConstants::SHARED_BANK_BEGIN; slot_id <= EmuConstants::SHARED_BANK_END; ++slot_id) { - auto inst = m_inv[slot_id]; - if (!inst) { continue; } - if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } - if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; } - if (inst->GetTotalItemCount() == 1) { continue; } - - auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); - if (!new_id) { continue; } - auto new_item = database.GetItem(new_id); - if (!new_item) { continue; } - auto new_inst = database.CreateBaseItem(new_item); - if (!new_inst) { continue; } - - if (CopyBagContents(new_inst, inst)) { - Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, slot_id); - PutItemInInventory(slot_id, *new_inst, client_update); - } - safe_delete(new_inst); - } - - while (!m_inv.CursorEmpty()) { - auto inst = m_inv[MainCursor]; - if (!inst) { break; } - if (!IsSummonedBagID(inst->GetItem()->ID)) { break; } - if (inst->GetItem()->ItemClass != ItemClassContainer) { break; } - if (inst->GetTotalItemCount() == 1) { break; } - - auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); - if (!new_id) { break; } - auto new_item = database.GetItem(new_id); - if (!new_item) { break; } - auto new_inst = database.CreateBaseItem(new_item); - if (!new_inst) { break; } - - if (CopyBagContents(new_inst, inst)) { - Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, MainCursor); - std::list local; - local.push_front(new_inst); - m_inv.PopItem(MainCursor); - safe_delete(inst); - - while (!m_inv.CursorEmpty()) { - auto limbo_inst = m_inv.PopItem(MainCursor); - if (limbo_inst == nullptr) { continue; } - local.push_back(limbo_inst); - } - - for (auto iter = local.begin(); iter != local.end(); ++iter) { - auto cur_inst = *iter; - if (cur_inst == nullptr) { continue; } - m_inv.PushCursor(*cur_inst); - safe_delete(cur_inst); - } - local.clear(); - - auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); - database.SaveCursor(this->CharacterID(), s, e); - } - else { - safe_delete(new_inst); // deletes disenchanted bag if not used - } - - break; - } + //Inv2 todo: uh fix this + //for (auto slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; ++slot_id) { + // auto inst = m_inv[slot_id]; + // if (!inst) { continue; } + // if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } + // if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; } + // if (inst->GetTotalItemCount() == 1) { continue; } + // + // auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); + // if (!new_id) { continue; } + // auto new_item = database.GetItem(new_id); + // if (!new_item) { continue; } + // auto new_inst = database.CreateBaseItem(new_item); + // if (!new_inst) { continue; } + // + // if (CopyBagContents(new_inst, inst)) { + // Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, slot_id); + // PutItemInInventory(slot_id, *new_inst, client_update); + // } + // safe_delete(new_inst); + //} + // + //for (auto slot_id = EmuConstants::BANK_BEGIN; slot_id <= EmuConstants::BANK_END; ++slot_id) { + // auto inst = m_inv[slot_id]; + // if (!inst) { continue; } + // if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } + // if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; } + // if (inst->GetTotalItemCount() == 1) { continue; } + // + // auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); + // if (!new_id) { continue; } + // auto new_item = database.GetItem(new_id); + // if (!new_item) { continue; } + // auto new_inst = database.CreateBaseItem(new_item); + // if (!new_inst) { continue; } + // + // if (CopyBagContents(new_inst, inst)) { + // Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, slot_id); + // PutItemInInventory(slot_id, *new_inst, client_update); + // } + // safe_delete(new_inst); + //} + // + //for (auto slot_id = EmuConstants::SHARED_BANK_BEGIN; slot_id <= EmuConstants::SHARED_BANK_END; ++slot_id) { + // auto inst = m_inv[slot_id]; + // if (!inst) { continue; } + // if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } + // if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; } + // if (inst->GetTotalItemCount() == 1) { continue; } + // + // auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); + // if (!new_id) { continue; } + // auto new_item = database.GetItem(new_id); + // if (!new_item) { continue; } + // auto new_inst = database.CreateBaseItem(new_item); + // if (!new_inst) { continue; } + // + // if (CopyBagContents(new_inst, inst)) { + // Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, slot_id); + // PutItemInInventory(slot_id, *new_inst, client_update); + // } + // safe_delete(new_inst); + //} + // + //while (!m_inv.CursorEmpty()) { + // auto inst = m_inv[MainCursor]; + // if (!inst) { break; } + // if (!IsSummonedBagID(inst->GetItem()->ID)) { break; } + // if (inst->GetItem()->ItemClass != ItemClassContainer) { break; } + // if (inst->GetTotalItemCount() == 1) { break; } + // + // auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); + // if (!new_id) { break; } + // auto new_item = database.GetItem(new_id); + // if (!new_item) { break; } + // auto new_inst = database.CreateBaseItem(new_item); + // if (!new_inst) { break; } + // + // if (CopyBagContents(new_inst, inst)) { + // Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, MainCursor); + // std::list local; + // local.push_front(new_inst); + // m_inv.PopItem(MainCursor); + // safe_delete(inst); + // + // while (!m_inv.CursorEmpty()) { + // auto limbo_inst = m_inv.PopItem(MainCursor); + // if (limbo_inst == nullptr) { continue; } + // local.push_back(limbo_inst); + // } + // + // for (auto iter = local.begin(); iter != local.end(); ++iter) { + // auto cur_inst = *iter; + // if (cur_inst == nullptr) { continue; } + // m_inv.PushCursor(*cur_inst); + // safe_delete(cur_inst); + // } + // local.clear(); + // + // auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); + // database.SaveCursor(this->CharacterID(), s, e); + // } + // else { + // safe_delete(new_inst); // deletes disenchanted bag if not used + // } + // + // break; + //} } void Client::RemoveNoRent(bool client_update) @@ -2599,7 +2503,7 @@ uint32 Client::GetEquipment(uint8 material_slot) const return 0; } - invslot = Inventory::CalcSlotFromMaterial(material_slot); + invslot = InventoryOld::CalcSlotFromMaterial(material_slot); if (invslot == INVALID_INDEX) { return 0; @@ -2618,7 +2522,7 @@ uint32 Client::GetEquipment(uint8 material_slot) const #if 0 int32 Client::GetEquipmentMaterial(uint8 material_slot) { - const Item_Struct *item; + const ItemData *item; item = database.GetItem(GetEquipment(material_slot)); if(item != 0) @@ -2635,7 +2539,7 @@ uint32 Client::GetEquipmentColor(uint8 material_slot) const if (material_slot > EmuConstants::MATERIAL_END) return 0; - const Item_Struct *item = database.GetItem(GetEquipment(material_slot)); + const ItemData *item = database.GetItem(GetEquipment(material_slot)); if(item != nullptr) return ((m_pp.item_tint[material_slot].RGB.UseTint) ? m_pp.item_tint[material_slot].Color : item->Color); @@ -2645,52 +2549,74 @@ uint32 Client::GetEquipmentColor(uint8 material_slot) const // Send an item packet (including all subitems of the item) void Client::SendItemPacket(int16 slot_id, const ItemInst* inst, ItemPacketType packet_type) { - if (!inst) +// if (!inst) +// return; +// +// // Serialize item into |-delimited string +// std::string packet = inst->Serialize(slot_id); +// +// EmuOpcode opcode = OP_Unknown; +// EQApplicationPacket* outapp = nullptr; +// ItemPacket_Struct* itempacket = nullptr; +// +// // Construct packet +// opcode = (packet_type==ItemPacketViewLink) ? OP_ItemLinkResponse : OP_ItemPacket; +// outapp = new EQApplicationPacket(opcode, packet.length()+sizeof(ItemPacket_Struct)); +// itempacket = (ItemPacket_Struct*)outapp->pBuffer; +// memcpy(itempacket->SerializedItem, packet.c_str(), packet.length()); +// itempacket->PacketType = packet_type; +// +//#if EQDEBUG >= 9 +// DumpPacket(outapp); +//#endif +// FastQueuePacket(&outapp); +} + +void Client::SendItemPacket(const EQEmu::InventorySlot &slot, EQEmu::ItemInstance::pointer &inst, ItemPacketType packet_type) { + if(!inst) { return; + } - // Serialize item into |-delimited string - std::string packet = inst->Serialize(slot_id); - + EQEmu::MemoryBuffer item; EmuOpcode opcode = OP_Unknown; - EQApplicationPacket* outapp = nullptr; - ItemPacket_Struct* itempacket = nullptr; + opcode = (packet_type == ItemPacketViewLink) ? OP_ItemLinkResponse : OP_ItemPacket; - // Construct packet - opcode = (packet_type==ItemPacketViewLink) ? OP_ItemLinkResponse : OP_ItemPacket; - outapp = new EQApplicationPacket(opcode, packet.length()+sizeof(ItemPacket_Struct)); - itempacket = (ItemPacket_Struct*)outapp->pBuffer; - memcpy(itempacket->SerializedItem, packet.c_str(), packet.length()); - itempacket->PacketType = packet_type; - -#if EQDEBUG >= 9 - DumpPacket(outapp); -#endif - FastQueuePacket(&outapp); + item.Write((int32)packet_type); + item.Write(slot.Type()); + item.Write(slot.Slot()); + item.Write(slot.BagIndex()); + item.Write(slot.AugIndex()); + item.Write(inst.get()); + + EQApplicationPacket outapp(opcode, item.Size()); + memcpy(outapp.pBuffer, item, item.Size()); + QueuePacket(&outapp); } EQApplicationPacket* Client::ReturnItemPacket(int16 slot_id, const ItemInst* inst, ItemPacketType packet_type) { - if (!inst) - return nullptr; - - // Serialize item into |-delimited string - std::string packet = inst->Serialize(slot_id); - - EmuOpcode opcode = OP_Unknown; - EQApplicationPacket* outapp = nullptr; - BulkItemPacket_Struct* itempacket = nullptr; - - // Construct packet - opcode = OP_ItemPacket; - outapp = new EQApplicationPacket(opcode, packet.length()+1); - itempacket = (BulkItemPacket_Struct*)outapp->pBuffer; - memcpy(itempacket->SerializedItem, packet.c_str(), packet.length()); - -#if EQDEBUG >= 9 - DumpPacket(outapp); -#endif - - return outapp; + return nullptr; +// if (!inst) +// return nullptr; +// +// // Serialize item into |-delimited string +// std::string packet = inst->Serialize(slot_id); +// +// EmuOpcode opcode = OP_Unknown; +// EQApplicationPacket* outapp = nullptr; +// BulkItemPacket_Struct* itempacket = nullptr; +// +// // Construct packet +// opcode = OP_ItemPacket; +// outapp = new EQApplicationPacket(opcode, packet.length()+1); +// itempacket = (BulkItemPacket_Struct*)outapp->pBuffer; +// memcpy(itempacket->SerializedItem, packet.c_str(), packet.length()); +// +//#if EQDEBUG >= 9 +// DumpPacket(outapp); +//#endif +// +// return outapp; } static int16 BandolierSlotToWeaponSlot(int BandolierSlot) @@ -2719,8 +2645,8 @@ void Client::CreateBandolier(const EQApplicationPacket *app) strcpy(m_pp.bandoliers[bs->Number].Name, bs->Name); const ItemInst* InvItem = nullptr; - const Item_Struct *BaseItem = nullptr; - int16 WeaponSlot = 0; + const ItemData *BaseItem = nullptr; + int16 WeaponSlot; for(int BandolierSlot = bandolierPrimary; BandolierSlot <= bandolierAmmo; BandolierSlot++) { WeaponSlot = BandolierSlotToWeaponSlot(BandolierSlot); @@ -2955,7 +2881,7 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { // if (InvItem && InvItem->IsType(ItemClassContainer)) { - int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_BEGIN); + int16 BaseSlotID = InventoryOld::CalcSlotId(i, SUB_BEGIN); uint8 BagSize=InvItem->GetItem()->BagSlots; @@ -3005,9 +2931,9 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { return true; } - if(InvItem->IsType(ItemClassContainer) && Inventory::CanItemFitInContainer(ItemToReturn->GetItem(), InvItem->GetItem())) { + if(InvItem->IsType(ItemClassContainer) && InventoryOld::CanItemFitInContainer(ItemToReturn->GetItem(), InvItem->GetItem())) { - int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_BEGIN); + int16 BaseSlotID = InventoryOld::CalcSlotId(i, SUB_BEGIN); uint8 BagSize=InvItem->GetItem()->BagSlots; @@ -3271,7 +3197,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* return false; } -void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value) { +void InventoryOld::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value) { ItemInst *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); @@ -3279,7 +3205,7 @@ void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::strin } } -void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value) { +void InventoryOld::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value) { ItemInst *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); @@ -3287,7 +3213,7 @@ void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::strin } } -void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value) { +void InventoryOld::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value) { ItemInst *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); @@ -3295,7 +3221,7 @@ void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::strin } } -void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value) { +void InventoryOld::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value) { ItemInst *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); @@ -3303,10 +3229,322 @@ void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::strin } } -std::string Inventory::GetCustomItemData(int16 slot_id, std::string identifier) { +std::string InventoryOld::GetCustomItemData(int16 slot_id, std::string identifier) { ItemInst *inst = GetItem(slot_id); if(inst) { return inst->GetCustomData(identifier); } return ""; } + +//New Inventory +bool Client::SwapItem(const EQEmu::InventorySlot &src, const EQEmu::InventorySlot &dest, int number_in_stack) { + + if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id)) + { + if(src != dest && !src.IsCursor() && src.IsValid() && dest.IsValid()) { + auto i_src = m_inventory.Get(src); + auto i_dest = m_inventory.Get(dest); + std::string detect = StringFormat("Player issued a move item from %s (item id %u) to %s (item id %u) while casting %u.", + src.ToString().c_str(), + i_src ? i_src->GetItem()->ID : 0, + dest.ToString().c_str(), + i_dest ? i_dest->GetItem()->ID : 0, + casting_spell_id); + database.SetMQDetectionFlag(AccountName(), GetName(), detect.c_str(), zone->GetShortName()); + Kick(); + return false; + } + } + + bool recalc_weapon_speed = false; + if(src.IsWeapon() || dest.IsWeapon()) { + recalc_weapon_speed = true; + } + + if(src.IsBank() || dest.IsBank()) { + uint32 distance = 0; + NPC *banker = entity_list.GetClosestBanker(this, distance); + if(!banker || distance > USE_NPC_RANGE2) + { + std::string hacked = StringFormat("Player tried to make use of a banker(items) but %s is " + "non-existant or too far away (%u units).", + banker ? banker->GetName() : "UNKNOWN NPC", + distance); + database.SetMQDetectionFlag(AccountName(), GetName(), hacked.c_str(), zone->GetShortName()); + Kick(); + return false; + } + } + + Message(0, "%s -> %s (%i)\n", src.IsCursor() ? "Cursor" : src.ToString().c_str(), dest.IsCursor() ? "Cursor" : dest.ToString().c_str(), number_in_stack); + + bool res = m_inventory.Swap(src, dest, number_in_stack); + + if(res) { + Message(0, "Swap success\n"); + m_inventory.Interrogate(); + } else { + Message(0, "Swap failure!\n"); + //should kick the player here... + } + + EQEmu::InventorySlot cursor(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor); + if(!m_inventory.Get(cursor)) { + if(m_inventory.PopFromCursorBuffer()) { + auto c_inst = m_inventory.Get(cursor); + if(c_inst) { + SendItemPacket(EQEmu::InventorySlot(EQEmu::InvTypePersonal, EQEmu::PersonalSlotCursor), c_inst, ItemPacketSummonItem); + } + } + } + + if(auto_attack && res && recalc_weapon_speed) { + SetAttackTimer(); + } + + if(res) { + CalcBonuses(); + } + + return res; +} + +bool Client::SummonItem(uint32 item_id, + int16 charges, + const EQEmu::InventorySlot &slot, + uint32 aug1, + uint32 aug2, + uint32 aug3, + uint32 aug4, + uint32 aug5, + uint32 aug6, + bool attuned, + uint32 ornament_icon, + uint32 ornament_idfile, + uint32 ornament_hero_model) +{ + EQEmu::ItemInstance::pointer &inst = database.CreateItem(item_id, charges); + if(!inst) + return false; + + if(inst->GetBaseItem()->ItemClass == ItemClassCommon) { + if(aug1) { + EQEmu::ItemInstance::pointer aug = database.CreateItem(aug1); + if(!aug) + return false; + + if(!inst->Put(0, aug)) { + return false; + } + } + + if(aug2) { + EQEmu::ItemInstance::pointer aug = database.CreateItem(aug2); + if(!aug) + return false; + + if(!inst->Put(1, aug)) { + return false; + } + } + + if(aug3) { + EQEmu::ItemInstance::pointer aug = database.CreateItem(aug3); + if(!aug) + return false; + + if(!inst->Put(2, aug)) { + return false; + } + } + + if(aug4) { + EQEmu::ItemInstance::pointer aug = database.CreateItem(aug4); + if(!aug) + return false; + + if(!inst->Put(3, aug)) { + return false; + } + } + + if(aug5) { + EQEmu::ItemInstance::pointer aug = database.CreateItem(aug5); + if(!aug) + return false; + + if(!inst->Put(4, aug)) { + return false; + } + } + + if(aug6) { + EQEmu::ItemInstance::pointer aug = database.CreateItem(aug6); + if(!aug) + return false; + + if(!inst->Put(5, aug)) { + return false; + } + } + } + + auto res = m_inventory.Summon(slot, inst); + if(res) { + SendItemPacket(slot, inst, ItemPacketSummonItem); + } + + return res; +} + +bool Client::PutItemInInventory(const EQEmu::InventorySlot &slot, EQEmu::ItemInstance::pointer &inst, bool client_update) { + if(!inst) + return false; + + if(!slot.IsValid()) { + return false; + } + + Log.Out(Logs::Detail, Logs::Inventory, "Putting item %s (%d) into slot %s", inst->GetBaseItem()->Name, inst->GetBaseItem()->ID, slot.ToString().c_str()); + + if(!m_inventory.Summon(slot, inst)) { + return false; + } + + if(client_update) { + SendItemPacket(slot, inst, slot.IsCursor() ? ItemPacketSummonItem : ItemPacketTrade); + } + + CalcBonuses(); + return true; +} + +bool Client::CanPutItemInInventory(EQEmu::ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end) { + if(inst->IsStackable()) { + int charges = m_inventory.FindFreeStackSlots(inst, EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1, EQEmu::PersonalSlotGeneral10); + + if(charges < inst->GetCharges()) { + EQEmu::InventorySlot slot = m_inventory.FindFreeSlot(inst, container_id, slot_id_start, slot_id_end); + + if(!slot.IsValid()) { + return false; + } + } + } + else { + EQEmu::InventorySlot slot = m_inventory.FindFreeSlot(inst, container_id, slot_id_start, slot_id_end); + if(!slot.IsValid()) { + return false; + } + } + + return true; +} + +void Client::StackItem(EQEmu::ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end, bool client_update) { + auto item_id = inst->GetBaseItem()->ID; + + //not the most efficient of functions but in reality it's fast enough + + //go through the top level slots first + for(int i = slot_id_start; i < slot_id_end; ++i) { + EQEmu::InventorySlot slot(container_id, i); + auto item = m_inventory.Get(slot); + + if(!item) { + continue; + } + + if(item->GetBaseItem()->ID == item_id) { + auto free_charges = item->GetItem()->StackSize - item->GetCharges(); + + if(inst->GetCharges() > free_charges) { + item->SetCharges(item->GetCharges() + free_charges); + inst->SetCharges(inst->GetCharges() - free_charges); + + m_inventory.UpdateSlot(slot, item); + + if(client_update) { + SendItemPacket(slot, item, slot.IsCursor() ? ItemPacketSummonItem : ItemPacketTrade); + } + } else { + item->SetCharges(item->GetCharges() + inst->GetCharges()); + inst->SetCharges(0); + + m_inventory.UpdateSlot(slot, item); + if(client_update) { + SendItemPacket(slot, item, slot.IsCursor() ? ItemPacketSummonItem : ItemPacketTrade); + } + + return; + } + } + } + + //go through the top level slots bag slots + for(int i = slot_id_start; i < slot_id_end; ++i) { + EQEmu::InventorySlot slot(container_id, i); + auto item = m_inventory.Get(slot); + + if(!item) { + continue; + } + + if(item->GetBaseItem()->ItemClass != ItemClassContainer) { + continue; + } + + int sz = item->GetBaseItem()->BagSlots; + bool update_bag = false; + for(int j = 0; j < sz; ++j) { + auto sub_item = item->Get(j); + + if(!sub_item) { + continue; + } + + if(sub_item->GetBaseItem()->ID == item_id) { + EQEmu::InventorySlot bag_slot(container_id, i, j); + auto free_charges = sub_item->GetItem()->StackSize - sub_item->GetCharges(); + + if(inst->GetCharges() > free_charges) { + sub_item->SetCharges(sub_item->GetCharges() + free_charges); + inst->SetCharges(inst->GetCharges() - free_charges); + + m_inventory.UpdateSlot(bag_slot, sub_item); + update_bag = true; + } + else { + sub_item->SetCharges(sub_item->GetCharges() + inst->GetCharges()); + inst->SetCharges(0); + + m_inventory.UpdateSlot(bag_slot, sub_item); + if(client_update) { + SendItemPacket(slot, item, slot.IsCursor() ? ItemPacketSummonItem : ItemPacketTrade); + } + + return; + } + } + } + + if(update_bag && client_update) { + SendItemPacket(slot, item, slot.IsCursor() ? ItemPacketSummonItem : ItemPacketTrade); + } + } +} + +void Client::PutItemInInventory(EQEmu::ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end, bool client_update) { + if(inst->IsStackable()) { + StackItem(inst, EQEmu::InvTypePersonal, EQEmu::PersonalSlotGeneral1, EQEmu::PersonalSlotGeneral10, client_update); + + if(inst->GetCharges() > 0) { + EQEmu::InventorySlot slot = m_inventory.FindFreeSlot(inst, container_id, slot_id_start, slot_id_end); + PutItemInInventory(slot, inst, client_update); + } + } else { + EQEmu::InventorySlot slot = m_inventory.FindFreeSlot(inst, container_id, slot_id_start, slot_id_end); + PutItemInInventory(slot, inst, client_update); + } +} diff --git a/zone/loottables.cpp b/zone/loottables.cpp index e3014b12e..372d7acd3 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -119,8 +119,8 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml int charges = lds->Entries[i].multiplier; for(int j = 0; j < charges; ++j) { if(zone->random.Real(0.0, 100.0) <= lds->Entries[i].chance) { - const Item_Struct* dbitem = GetItem(lds->Entries[i].item_id); - npc->AddLootDrop(dbitem, itemlist, lds->Entries[i].item_charges, lds->Entries[i].minlevel, + const ItemData* dbitem = GetItem(lds->Entries[i].item_id); + npc->AddLootDrop(dbitem, itemlist, lds->Entries[i].item_charges, lds->Entries[i].minlevel, lds->Entries[i].maxlevel, lds->Entries[i].equip_item > 0 ? true : false, false); } } @@ -140,7 +140,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml float roll_t_min = 0.0f; bool active_item_list = false; for(uint32 i = 0; i < lds->NumEntries; ++i) { - const Item_Struct* db_item = GetItem(lds->Entries[i].item_id); + const ItemData* db_item = GetItem(lds->Entries[i].item_id); if(db_item) { roll_t += lds->Entries[i].chance; active_item_list = true; @@ -157,7 +157,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml for(int i = 0; i < mindrop; ++i) { float roll = (float)zone->random.Real(0.0, roll_t_min); for(uint32 j = 0; j < lds->NumEntries; ++j) { - const Item_Struct* db_item = GetItem(lds->Entries[j].item_id); + const ItemData* db_item = GetItem(lds->Entries[j].item_id); if(db_item) { if(roll < lds->Entries[j].chance) { npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel, @@ -187,7 +187,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml for(int i = mindrop; i < droplimit; ++i) { float roll = (float)zone->random.Real(0.0, roll_t); for(uint32 j = 0; j < lds->NumEntries; ++j) { - const Item_Struct* db_item = GetItem(lds->Entries[j].item_id); + const ItemData* db_item = GetItem(lds->Entries[j].item_id); if(db_item) { if(roll < lds->Entries[j].chance) { npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel, @@ -221,7 +221,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml } //if itemlist is null, just send wear changes -void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange) { +void NPC::AddLootDrop(const ItemData *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange) { if(item2 == nullptr) return; @@ -258,7 +258,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge if (equipit) { uint8 eslot = 0xFF; char newid[20]; - const Item_Struct* compitem = nullptr; + const ItemData* compitem = nullptr; bool found = false; // track if we found an empty slot we fit into int32 foundslot = -1; // for multi-slot items @@ -414,14 +414,14 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge SendAppearancePacket(AT_Light, GetActiveLightType()); } -void NPC::AddItem(const Item_Struct* item, uint16 charges, bool equipitem) { +void NPC::AddItem(const ItemData* item, uint16 charges, bool equipitem) { //slot isnt needed, its determined from the item. AddLootDrop(item, &itemlist, charges, 1, 127, equipitem, equipitem); } void NPC::AddItem(uint32 itemid, uint16 charges, bool equipitem) { //slot isnt needed, its determined from the item. - const Item_Struct * i = database.GetItem(itemid); + const ItemData * i = database.GetItem(itemid); if(i == nullptr) return; AddLootDrop(i, &itemlist, charges, 1, 127, equipitem, equipitem); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 47607b705..d0e325fdf 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -672,7 +672,7 @@ void Lua_Client::SummonItem(uint32 item_id) { void Lua_Client::SummonItem(uint32 item_id, int charges) { Lua_Safe_Call_Void(); - self->SummonItem(item_id, charges); + self->SummonItem(item_id, charges, 0); } void Lua_Client::SummonItem(uint32 item_id, int charges, uint32 aug1) { diff --git a/zone/lua_inventory.cpp b/zone/lua_inventory.cpp index 498835926..e2578603c 100644 --- a/zone/lua_inventory.cpp +++ b/zone/lua_inventory.cpp @@ -164,7 +164,7 @@ int Lua_Inventory::GetSlotByItemInst(Lua_ItemInst inst) { } luabind::scope lua_register_inventory() { - return luabind::class_("Inventory") + return luabind::class_("InventoryOld") .def(luabind::constructor<>()) .def("GetItem", (Lua_ItemInst(Lua_Inventory::*)(int))&Lua_Inventory::GetItem) .def("GetItem", (Lua_ItemInst(Lua_Inventory::*)(int,int))&Lua_Inventory::GetItem) diff --git a/zone/lua_inventory.h b/zone/lua_inventory.h index ca49a55e6..12e531050 100644 --- a/zone/lua_inventory.h +++ b/zone/lua_inventory.h @@ -4,7 +4,7 @@ #include "lua_ptr.h" -class Inventory; +class InventoryOld; class Lua_ItemInst; class Lua_Item; @@ -14,16 +14,16 @@ namespace luabind { luabind::scope lua_register_inventory(); -class Lua_Inventory : public Lua_Ptr +class Lua_Inventory : public Lua_Ptr { - typedef Inventory NativeType; + typedef InventoryOld NativeType; public: Lua_Inventory() : Lua_Ptr(nullptr) { } - Lua_Inventory(Inventory *d) : Lua_Ptr(d) { } + Lua_Inventory(InventoryOld *d) : Lua_Ptr(d) { } virtual ~Lua_Inventory() { } - operator Inventory*() { - return reinterpret_cast(GetLuaPtrData()); + operator InventoryOld*() { + return reinterpret_cast(GetLuaPtrData()); } Lua_ItemInst GetItem(int slot_id); diff --git a/zone/lua_item.cpp b/zone/lua_item.cpp index 16254c52e..003a4973e 100644 --- a/zone/lua_item.cpp +++ b/zone/lua_item.cpp @@ -7,7 +7,7 @@ #include "lua_item.h" Lua_Item::Lua_Item(uint32 item_id) { - const Item_Struct *t = database.GetItem(item_id); + const ItemData *t = database.GetItem(item_id); SetLuaPtrData(t); } diff --git a/zone/lua_item.h b/zone/lua_item.h index 961da1333..f7865c84d 100644 --- a/zone/lua_item.h +++ b/zone/lua_item.h @@ -4,7 +4,7 @@ #include "lua_ptr.h" -struct Item_Struct; +struct ItemData; namespace luabind { struct scope; @@ -12,17 +12,17 @@ namespace luabind { luabind::scope lua_register_item(); -class Lua_Item : public Lua_Ptr +class Lua_Item : public Lua_Ptr { - typedef const Item_Struct NativeType; + typedef const ItemData NativeType; public: Lua_Item(uint32 item_id); Lua_Item() : Lua_Ptr(nullptr) { } - Lua_Item(const Item_Struct *d) : Lua_Ptr(d) { } + Lua_Item(const ItemData *d) : Lua_Ptr(d) { } virtual ~Lua_Item() { } - operator const Item_Struct*() { - return reinterpret_cast(GetLuaPtrData()); + operator const ItemData*() { + return reinterpret_cast(GetLuaPtrData()); } int GetMinStatus(); diff --git a/zone/lua_iteminst.cpp b/zone/lua_iteminst.cpp index 4ebc6908f..44a1b7ffa 100644 --- a/zone/lua_iteminst.cpp +++ b/zone/lua_iteminst.cpp @@ -9,12 +9,12 @@ #include "lua_item.h" Lua_ItemInst::Lua_ItemInst(int item_id) { - SetLuaPtrData(database.CreateItem(item_id)); + SetLuaPtrData(database.CreateItemOld(item_id)); cloned_ = true; } Lua_ItemInst::Lua_ItemInst(int item_id, int charges) { - SetLuaPtrData(database.CreateItem(item_id, charges)); + SetLuaPtrData(database.CreateItemOld(item_id, charges)); cloned_ = true; } diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index 840bcb40d..dbf1e0ba5 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -298,7 +298,7 @@ void handle_player_timer(QuestInterface *parse, lua_State* L, Client* client, st void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { - const Item_Struct *item = database.GetItem(extra_data); + const ItemData *item = database.GetItem(extra_data); if(item) { Lua_Item l_item(item); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); diff --git a/zone/merc.cpp b/zone/merc.cpp index 936dfcc68..888a9c425 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -209,7 +209,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) { for (i=0; iReqLevel) { @@ -1213,7 +1213,7 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { { continue; } - const Item_Struct* item = database.GetItem(equipment[i]); + const ItemData* item = database.GetItem(equipment[i]); if(item) { ns->spawn.equipment[i].material = item->Material; @@ -2536,8 +2536,8 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) { //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[type]){ - const Item_Struct* TempItem = 0; - const Item_Struct* UsedItem = 0; + const ItemData* TempItem = 0; + const ItemData* UsedItem = 0; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -4399,7 +4399,7 @@ void Merc::DoClassAttacks(Mob *target) { DoAnim(animKick); int32 dmg = 0; - if(GetWeaponDamage(target, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(target, (const ItemData*)nullptr) <= 0){ dmg = -5; } else{ @@ -4421,7 +4421,7 @@ void Merc::DoClassAttacks(Mob *target) { DoAnim(animTailRake); int32 dmg = 0; - if(GetWeaponDamage(target, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(target, (const ItemData*)nullptr) <= 0){ dmg = -5; } else{ @@ -5021,7 +5021,7 @@ void Merc::UpdateMercAppearance() { for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { itemID = equipment[i]; if(itemID != NO_ITEM) { - materialFromSlot = Inventory::CalcMaterialFromSlot(i); + materialFromSlot = InventoryOld::CalcMaterialFromSlot(i); if(materialFromSlot != _MaterialInvalid) this->SendWearChange(materialFromSlot); } diff --git a/zone/merc.h b/zone/merc.h index 9c683ed52..f800642f8 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -8,7 +8,7 @@ class Corpse; class Group; class Mob; class Raid; -struct Item_Struct; +struct ItemData; struct MercTemplate; struct NPCType; struct NewSpawn_Struct; @@ -278,7 +278,7 @@ public: protected: void CalcItemBonuses(StatBonuses* newbon); - void AddItemBonuses(const Item_Struct *item, StatBonuses* newbon); + void AddItemBonuses(const ItemData *item, StatBonuses* newbon); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); int16 GetFocusEffect(focusType type, uint16 spell_id); @@ -381,7 +381,7 @@ private: uint8 _OwnerClientVersion; uint32 _currentStance; - Inventory m_inv; + InventoryOld m_inv; int32 max_end; int32 cur_end; bool _medding; diff --git a/zone/mob.cpp b/zone/mob.cpp index b107565bc..990698e4b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -108,7 +108,8 @@ Mob::Mob(const char* in_name, m_TargetLocation(glm::vec3()), m_TargetV(glm::vec3()), flee_timer(FLEE_CHECK_TIMER), - m_Position(position) + m_Position(position), + m_inventory(in_race, in_class, in_deity) { targeted = 0; tar_ndx=0; @@ -2366,7 +2367,7 @@ bool Mob::CanThisClassDualWield(void) const { // 2HS, 2HB, or 2HP if(pinst && pinst->IsWeapon()) { - const Item_Struct* item = pinst->GetItem(); + const ItemData* item = pinst->GetItem(); if((item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HPiercing)) return false; @@ -2707,7 +2708,7 @@ uint32 NPC::GetEquipment(uint8 material_slot) const { if(material_slot > 8) return 0; - int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); + int16 invslot = InventoryOld::CalcSlotFromMaterial(material_slot); if (invslot == INVALID_INDEX) return 0; return equipment[invslot]; @@ -2728,7 +2729,7 @@ void Mob::SendArmorAppearance(Client *one_client) { if (!IsClient()) { - const Item_Struct *item; + const ItemData *item; for (int i=0; i< 7 ; ++i) { item=database.GetItem(GetEquipment(i)); @@ -2831,7 +2832,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const { uint32 equipmaterial = 0; int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - const Item_Struct *item; + const ItemData *item; item = database.GetItem(GetEquipment(material_slot)); if (item != 0) @@ -2841,7 +2842,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const { if (this->IsClient()) { - int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); + int16 invslot = InventoryOld::CalcSlotFromMaterial(material_slot); if (invslot == INVALID_INDEX) { return 0; @@ -2884,9 +2885,9 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const if (material_slot >= 0 && material_slot < MaterialPrimary) { uint32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - const Item_Struct *item; + const ItemData *item; item = database.GetItem(GetEquipment(material_slot)); - int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); + int16 invslot = InventoryOld::CalcSlotFromMaterial(material_slot); if (item != 0 && invslot != INVALID_INDEX) { @@ -2938,7 +2939,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const uint32 Mob::GetEquipmentColor(uint8 material_slot) const { - const Item_Struct *item; + const ItemData *item; if (armor_tint[material_slot]) { @@ -2954,7 +2955,7 @@ uint32 Mob::GetEquipmentColor(uint8 material_slot) const uint32 Mob::IsEliteMaterialItem(uint8 material_slot) const { - const Item_Struct *item; + const ItemData *item; item = database.GetItem(GetEquipment(material_slot)); if(item != 0) @@ -3863,11 +3864,11 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) int32 Mob::GetItemStat(uint32 itemid, const char *identifier) { - const ItemInst* inst = database.CreateItem(itemid); + const ItemInst* inst = database.CreateItemOld(itemid); if (!inst) return 0; - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); if (!item) return 0; @@ -5597,7 +5598,7 @@ int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot) bool Mob::CanClassEquipItem(uint32 item_id) { - const Item_Struct* itm = nullptr; + const ItemData* itm = nullptr; itm = database.GetItem(item_id); if (!itm) diff --git a/zone/mob.h b/zone/mob.h index ded9c04dc..fa78c1cc2 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -18,6 +18,7 @@ #ifndef MOB_H #define MOB_H +#include "../common/inventory.h" #include "common.h" #include "entity.h" #include "hate_list.h" @@ -38,7 +39,7 @@ class Group; class ItemInst; class NPC; class Raid; -struct Item_Struct; +struct ItemData; struct NewSpawn_Struct; struct PlayerPositionUpdateServer_Struct; @@ -725,7 +726,7 @@ public: inline void SetExtraHaste(int Haste) { ExtraHaste = Haste; } virtual int GetHaste(); - uint8 GetWeaponDamageBonus(const Item_Struct* Weapon); + uint8 GetWeaponDamageBonus(const ItemData* Weapon); uint16 GetDamageTable(SkillUseTypes skillinuse); virtual int GetMonkHandToHandDamage(void); @@ -749,10 +750,10 @@ public: int32 ReduceAllDamage(int32 damage); virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false, bool CanAvoid=true); - virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* AmmoItem=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0, uint32 range_id=0, int AmmoSlot=0, float speed = 4.0f); + virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemData* AmmoItem=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0, uint32 range_id=0, int AmmoSlot=0, float speed = 4.0f); virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false, int ReuseTime=0); - virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0, uint32 range_id=0, uint32 ammo_id=0, const Item_Struct *AmmoItem=nullptr, int AmmoSlot=0, float speed= 4.0f); - bool TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed); + virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0, uint32 range_id=0, uint32 ammo_id=0, const ItemData *AmmoItem=nullptr, int AmmoSlot=0, float speed= 4.0f); + bool TryProjectileAttack(Mob* other, const ItemData *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed); void ProjectileAttack(); inline bool HasProjectileAttack() const { return ActiveProjectileATK; } inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; } @@ -871,7 +872,7 @@ public: // HP Event inline int GetNextHPEvent() const { return nexthpevent; } void SetNextHPEvent( int hpevent ); - void SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse, float velocity= 4.0); + void SendItemAnimation(Mob *to, const ItemData *item, SkillUseTypes skillInUse, float velocity= 4.0); inline int& GetNextIncHPEvent() { return nextinchpevent; } void SetNextIncHPEvent( int inchpevent ); @@ -956,6 +957,9 @@ public: void Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int avoid_override, int Msg = 0); void Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int acc_override, int Msg = 0); + inline EQEmu::Inventory& GetInventory() { return m_inventory; } + inline const EQEmu::Inventory& GetInventory() const { return m_inventory; } + protected: void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); static uint16 GetProcID(uint16 spell_id, uint8 effect_index); @@ -1077,8 +1081,8 @@ protected: bool PassLimitToSkill(uint16 spell_id, uint16 skill); bool PassLimitClass(uint32 Classes_, uint16 Class_); void TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary); - void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = MainPrimary); - void TrySpellProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = MainPrimary); + void TryWeaponProc(const ItemInst* inst, const ItemData* weapon, Mob *on, uint16 hand = MainPrimary); + void TrySpellProc(const ItemInst* inst, const ItemData* weapon, Mob *on, uint16 hand = MainPrimary); void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary); void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on, int level_override = -1); virtual float GetProcChances(float ProcBonus, uint16 hand = MainPrimary); @@ -1087,7 +1091,7 @@ protected: virtual float GetAssassinateProcChances(uint16 ReuseTime); virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm? uint16 GetWeaponSpeedbyHand(uint16 hand); - int GetWeaponDamage(Mob *against, const Item_Struct *weapon_item); + int GetWeaponDamage(Mob *against, const ItemData *weapon_item); int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr); int GetKickDamage(); int GetBashDamage(); @@ -1311,6 +1315,8 @@ protected: bool bEnraged; bool destructibleobject; + EQEmu::Inventory m_inventory; + private: void _StopSong(); //this is not what you think it is Mob* target; diff --git a/zone/mod_functions.cpp b/zone/mod_functions.cpp index 6ae0eddad..c5cbce9ec 100644 --- a/zone/mod_functions.cpp +++ b/zone/mod_functions.cpp @@ -9,7 +9,7 @@ class ItemInst; class Spawn2; struct Consider_Struct; struct DBTradeskillRecipe_Struct; -struct Item_Struct; +struct ItemData; extern EntityList entity_list; extern Zone* zone; @@ -26,7 +26,7 @@ void Zone::mod_repop() { return; } void NPC::mod_prespawn(Spawn2 *sp) { return; } //Base damage from NPC::Attack -int NPC::mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const Item_Struct* weapon, Mob* other) { return(damage); } +int NPC::mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const ItemData* weapon, Mob* other) { return(damage); } //Mob c has been given credit for a kill. This is called after the regular EVENT_KILLED_MERIT event. void NPC::mod_npc_killed_merit(Mob* c) { return; } @@ -104,8 +104,8 @@ int32 Client::mod_client_xp(int32 in_xp, NPC *npc) { return(in_xp); } uint32 Client::mod_client_xp_for_level(uint32 xp, uint16 check_level) { return(xp); } //Food and drink values as computed by consume requests. Return < 0 to abort the request. -int Client::mod_food_value(const Item_Struct *item, int change) { return(change); } -int Client::mod_drink_value(const Item_Struct *item, int change) { return(change); } +int Client::mod_food_value(const ItemData *item, int change) { return(change); } +int Client::mod_drink_value(const ItemData *item, int change) { return(change); } //effect_vallue - Spell effect value as calculated by default formulas. You will want to ignore effects that don't lend themselves to scaling - pet ID's, gate coords, etc. int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster) { return(effect_value); } diff --git a/zone/npc.cpp b/zone/npc.cpp index d4a33b6d0..eae905df1 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -27,7 +27,7 @@ #include "../common/clientversions.h" #include "../common/features.h" #include "../common/item.h" -#include "../common/item_struct.h" +#include "../common/item_data.h" #include "../common/linked_list.h" #include "../common/servertalk.h" @@ -475,7 +475,7 @@ void NPC::CheckMinMaxLevel(Mob *them) if(themlevel < (*cur)->min_level || themlevel > (*cur)->max_level) { - material = Inventory::CalcMaterialFromSlot((*cur)->equip_slot); + material = InventoryOld::CalcMaterialFromSlot((*cur)->equip_slot); if (material != _MaterialInvalid) SendWearChange(material); @@ -511,7 +511,7 @@ void NPC::QueryLoot(Client* to) int x = 0; for(ItemList::iterator cur = itemlist.begin(); cur != itemlist.end(); ++cur, ++x) { - const Item_Struct* item = database.GetItem((*cur)->item_id); + const ItemData* item = database.GetItem((*cur)->item_id); if (item == nullptr) { Log.Out(Logs::General, Logs::Error, "Database error, invalid item"); continue; @@ -1301,7 +1301,7 @@ int32 NPC::GetEquipmentMaterial(uint8 material_slot) const if (material_slot >= _MaterialCount) return 0; - int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); + int16 invslot = InventoryOld::CalcSlotFromMaterial(material_slot); if (invslot == INVALID_INDEX) return 0; @@ -1401,10 +1401,10 @@ void NPC::PickPocket(Client* thief) { end = itemlist.end(); for(; cur != end && x < 49; ++cur) { ServerLootItem_Struct* citem = *cur; - const Item_Struct* item = database.GetItem(citem->item_id); + const ItemData* item = database.GetItem(citem->item_id); if (item) { - inst = database.CreateItem(item, citem->charges); + inst = database.CreateItemOld(item, citem->charges); bool is_arrow = (item->ItemType == ItemTypeArrow) ? true : false; int slot_id = thief->GetInv().FindFreeSlot(false, true, inst->GetItem()->Size, is_arrow); if (/*!Equipped(item->ID) &&*/ @@ -1424,10 +1424,10 @@ void NPC::PickPocket(Client* thief) { if (x > 0) { int random = zone->random.Int(0, x-1); - inst = database.CreateItem(steal_items[random], charges[random]); + inst = database.CreateItemOld(steal_items[random], charges[random]); if (inst) { - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); if (item) { if (/*item->StealSkill || */steal_skill >= stealchance) diff --git a/zone/npc.h b/zone/npc.h index 7274cccd1..25ecdc4ec 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -90,7 +90,7 @@ class Client; class Group; class Raid; class Spawn2; -struct Item_Struct; +struct ItemData; class NPC : public Mob { @@ -173,7 +173,7 @@ public: virtual void SpellProcess(); virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); - void AddItem(const Item_Struct* item, uint16 charges, bool equipitem = true); + void AddItem(const ItemData* item, uint16 charges, bool equipitem = true); void AddItem(uint32 itemid, uint16 charges, bool equipitem = true); void AddLootTable(); void AddLootTable(uint32 ldid); @@ -265,7 +265,7 @@ public: bool IsTaunting() const { return taunting; } void PickPocket(Client* thief); void StartSwarmTimer(uint32 duration) { swarm_timer.Start(duration); } - void AddLootDrop(const Item_Struct*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false); + void AddLootDrop(const ItemData*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false); virtual void DoClassAttacks(Mob *target); void CheckSignal(); inline bool IsNotTargetableWithHotkey() const { return no_target_hotkey; } @@ -398,7 +398,7 @@ public: void SetMerchantProbability(uint8 amt) { probability = amt; } uint8 GetMerchantProbability() { return probability; } void mod_prespawn(Spawn2 *sp); - int mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const Item_Struct* weapon, Mob* other); + int mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const ItemData* weapon, Mob* other); void mod_npc_killed_merit(Mob* c); void mod_npc_killed(Mob* oos); void AISpellsList(Client *c); diff --git a/zone/object.cpp b/zone/object.cpp index 7255cd9e9..0499cc753 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -138,7 +138,7 @@ Object::Object(Client* client, const ItemInst* inst) // Set object name if (inst) { - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); if (item && item->IDFile) { if (strlen(item->IDFile) == 0) { strcpy(m_data.object_name, DEFAULT_OBJECT_NAME); @@ -194,7 +194,7 @@ Object::Object(const ItemInst *inst, float x, float y, float z, float heading, u // Set object name if (inst) { - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); if (item && item->IDFile) { if (strlen(item->IDFile) == 0) { strcpy(m_data.object_name, DEFAULT_OBJECT_NAME); @@ -875,7 +875,7 @@ uint32 Object::GetItemID() return 0; } - const Item_Struct* item = this->m_inst->GetItem(); + const ItemData* item = this->m_inst->GetItem(); if (item == 0) { @@ -891,7 +891,7 @@ void Object::SetItemID(uint32 itemid) if (itemid) { - this->m_inst = database.CreateItem(itemid); + this->m_inst = database.CreateItemOld(itemid); } } diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index f5ef80a4c..df04831ae 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -8044,7 +8044,7 @@ XS(XS_Mob_DoThrowingAttackDmg) Mob * THIS; Mob* target; ItemInst* RangeWeapon = nullptr; - Item_Struct* item = nullptr; + ItemData* item = nullptr; uint16 weapon_damage = (uint16)SvIV(ST(4)); int16 chance_mod = (int16)SvIV(ST(5)); int16 focus = (int16)SvIV(ST(6)); diff --git a/zone/pets.cpp b/zone/pets.cpp index f5f741f44..f09c78a04 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -419,7 +419,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, // like the special back items some focused pets may receive. uint32 petinv[EmuConstants::EQUIPMENT_SIZE]; memset(petinv, 0, sizeof(petinv)); - const Item_Struct *item = 0; + const ItemData *item = 0; if (database.GetBasePetItems(record.equipmentset, petinv)) { for (int i = 0; iNoDrop != 0) { //dont bother saving item charges for now, NPCs never use them //and nobody should be able to get them off the corpse..? diff --git a/zone/queryserv.cpp b/zone/queryserv.cpp index d67ca46c7..b8960f89d 100644 --- a/zone/queryserv.cpp +++ b/zone/queryserv.cpp @@ -42,10 +42,3 @@ void QueryServ::SendQuery(std::string Query) safe_delete(pack); } -void QueryServ::PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc) -{ - std::string query = StringFormat( - "INSERT INTO `qs_player_events` (event, char_id, event_desc, time) VALUES (%i, %i, '%s', UNIX_TIMESTAMP(now()))", - Event_Type, Character_ID, EscapeString(Event_Desc).c_str()); - SendQuery(query); -} diff --git a/zone/queryserv.h b/zone/queryserv.h index 8aafcafda..b3732d2ba 100644 --- a/zone/queryserv.h +++ b/zone/queryserv.h @@ -29,7 +29,6 @@ class QueryServ{ QueryServ(); ~QueryServ(); void SendQuery(std::string Query); - void PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc); }; #endif /* QUERYSERV_ZONE_H */ \ No newline at end of file diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 67a1f06da..6750195b7 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -191,7 +191,7 @@ void QuestManager::summonitem(uint32 itemid, int16 charges) { QuestManagerCurrentQuestVars(); if(!initiator) return; - initiator->SummonItem(itemid, charges); + initiator->SummonItem(itemid, charges, 0); } void QuestManager::write(const char *file, const char *str) { @@ -812,7 +812,7 @@ void QuestManager::traindisc(int discipline_tome_item_id) { } bool QuestManager::isdisctome(int item_id) { - const Item_Struct *item = database.GetItem(item_id); + const ItemData *item = database.GetItem(item_id); if(item == nullptr) { return(false); } @@ -1303,7 +1303,7 @@ void QuestManager::settime(uint8 new_hour, uint8 new_min, bool update_world /*= void QuestManager::itemlink(int item_id) { QuestManagerCurrentQuestVars(); if (initiator) { - const Item_Struct* item = database.GetItem(item_id); + const ItemData* item = database.GetItem(item_id); if (item == nullptr) return; @@ -1370,12 +1370,6 @@ void QuestManager::setglobal(const char *varname, const char *newvalue, int opti } InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, newvalue, QGVarDuration(duration)); - - /* QS: PlayerLogQGlobalUpdate */ - if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator && initiator->IsClient()){ - std::string event_desc = StringFormat("Update :: qglobal:%s to qvalue:%s zoneid:%i instid:%i", varname, newvalue, initiator->GetZoneID(), initiator->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc); - } } /* Inserts global variable into quest_globals table */ @@ -1462,12 +1456,6 @@ void QuestManager::delglobal(const char *varname) { else qgCharid=-qgNpcid; // make char id negative npc id as a fudge - /* QS: PlayerLogQGlobalUpdate */ - if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator && initiator->IsClient()){ - std::string event_desc = StringFormat("Deleted :: qglobal:%s zoneid:%i instid:%i", varname, initiator->GetZoneID(), initiator->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc); - } - std::string query = StringFormat("DELETE FROM quest_globals " "WHERE name = '%s' " "&& (npcid=0 || npcid=%i) " @@ -2501,7 +2489,7 @@ void QuestManager::MerchantSetItem(uint32 NPCid, uint32 itemid, uint32 quantity) if (merchant == 0 || !merchant->IsNPC() || (merchant->GetClass() != MERCHANT)) return; // don't do anything if NPCid isn't a merchant - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; item = database.GetItem(itemid); if (!item) return; // if the item id doesn't correspond to a real item, do nothing @@ -2514,7 +2502,7 @@ uint32 QuestManager::MerchantCountItem(uint32 NPCid, uint32 itemid) { if (merchant == 0 || !merchant->IsNPC() || (merchant->GetClass() != MERCHANT)) return 0; // if it isn't a merchant, it doesn't have any items - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; item = database.GetItem(itemid); if (!item) return 0; // if it isn't a valid item, the merchant doesn't have any @@ -2537,7 +2525,7 @@ uint32 QuestManager::MerchantCountItem(uint32 NPCid, uint32 itemid) { // Item Link for use in Variables - "my $example_link = quest::varlink(item_id);" const char* QuestManager::varlink(char* perltext, int item_id) { QuestManagerCurrentQuestVars(); - const Item_Struct* item = database.GetItem(item_id); + const ItemData* item = database.GetItem(item_id); if (!item) return "INVALID ITEM ID IN VARLINK"; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index b844e9ca1..eded4bf74 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -119,7 +119,8 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, { hate += item->GetItem()->AC; } - const Item_Struct *itm = item->GetItem(); + + const ItemData *itm = item->GetItem(); auto fbash = GetFuriousBash(itm->Focus.Effect); hate = hate * (100 + fbash) / 100; if (fbash) @@ -482,7 +483,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) } } else{ - if(GetWeaponDamage(other, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(other, (const ItemData*)nullptr) <= 0){ ndamage = -5; } } @@ -713,8 +714,8 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { return; } - const Item_Struct* RangeItem = RangeWeapon->GetItem(); - const Item_Struct* AmmoItem = Ammo->GetItem(); + const ItemData* RangeItem = RangeWeapon->GetItem(); + const ItemData* AmmoItem = Ammo->GetItem(); if(RangeItem->ItemType != ItemTypeBow) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item is not a bow. type %d.", RangeItem->ItemType); @@ -738,7 +739,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { const ItemInst *pi = m_inv[r]; if(pi == nullptr || !pi->IsType(ItemClassContainer)) continue; - const Item_Struct* bagitem = pi->GetItem(); + const ItemData* bagitem = pi->GetItem(); if(!bagitem || bagitem->BagType != BagTypeQuiver) continue; @@ -816,13 +817,13 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { CommonBreakInvisible(); } -void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, - uint32 range_id, uint32 ammo_id, const Item_Struct *AmmoItem, int AmmoSlot, float speed) { - - if ((other == nullptr || - ((IsClient() && CastToClient()->dead) || - (other->IsClient() && other->CastToClient()->dead)) || - HasDied() || +void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, + uint32 range_id, uint32 ammo_id, const ItemData *AmmoItem, int AmmoSlot, float speed) { + + if ((other == nullptr || + ((IsClient() && CastToClient()->dead) || + (other->IsClient() && other->CastToClient()->dead)) || + HasDied() || (!IsAttackAllowed(other)) || (other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)))) @@ -832,7 +833,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite const ItemInst* _RangeWeapon = nullptr; const ItemInst* _Ammo = nullptr; - const Item_Struct* ammo_lost = nullptr; + const ItemData* ammo_lost = nullptr; /* If LaunchProjectile is false this function will do archery damage on target, @@ -1025,7 +1026,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } } -bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed){ +bool Mob::TryProjectileAttack(Mob* other, const ItemData *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed){ if (!other) return false; @@ -1329,7 +1330,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha //try proc on hits and misses if(other && !other->HasDied()) - TrySpellProc(nullptr, (const Item_Struct*)nullptr, other, MainRange); + TrySpellProc(nullptr, (const ItemData*)nullptr, other, MainRange); if (HasSkillProcs() && other && !other->HasDied()) TrySkillProc(other, skillInUse, 0, false, MainRange); @@ -1383,7 +1384,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 return; } - const Item_Struct* item = RangeWeapon->GetItem(); + const ItemData* item = RangeWeapon->GetItem(); if(item->ItemType != ItemTypeLargeThrowing && item->ItemType != ItemTypeSmallThrowing) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item %d is not a throwing weapon. type %d.", item->ItemType); Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(MainRange)); @@ -1444,7 +1445,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 CommonBreakInvisible(); } -void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item_Struct* AmmoItem, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed) +void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemData* AmmoItem, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed) { if ((other == nullptr || ((IsClient() && CastToClient()->dead) || @@ -1458,7 +1459,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } const ItemInst* _RangeWeapon = nullptr; - const Item_Struct* ammo_lost = nullptr; + const ItemData* ammo_lost = nullptr; /* If LaunchProjectile is false this function will do archery damage on target, @@ -1582,7 +1583,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } } -void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse, float velocity) { +void Mob::SendItemAnimation(Mob *to, const ItemData *item, SkillUseTypes skillInUse, float velocity) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_SomeItemPacketMaybe, sizeof(Arrow_Struct)); Arrow_Struct *as = (Arrow_Struct *) outapp->pBuffer; as->type = 1; @@ -1632,7 +1633,7 @@ void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, f if (!to) return; - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; uint8 item_type = 0; if(!item_id) { @@ -1773,7 +1774,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animKick); int32 dmg = 0; - if(GetWeaponDamage(target, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(target, (const ItemData*)nullptr) <= 0){ dmg = -5; } else{ @@ -1794,7 +1795,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animTailRake); int32 dmg = 0; - if(GetWeaponDamage(target, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(target, (const ItemData*)nullptr) <= 0){ dmg = -5; } else{ @@ -1847,7 +1848,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animKick); int32 dmg = 0; - if(GetWeaponDamage(target, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(target, (const ItemData*)nullptr) <= 0){ dmg = -5; } else{ @@ -1872,7 +1873,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animTailRake); int32 dmg = 0; - if(GetWeaponDamage(target, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(target, (const ItemData*)nullptr) <= 0){ dmg = -5; } else{ @@ -2384,7 +2385,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes int32 max_hit = (2 * weapon_damage*GetDamageTable(skillinuse)) / 100; if(GetLevel() >= 28 && IsWarriorClass() ) { - int ucDamageBonus = GetWeaponDamageBonus((const Item_Struct*) nullptr ); + int ucDamageBonus = GetWeaponDamageBonus((const ItemData*) nullptr ); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -2397,7 +2398,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if(item->GetItem()->ItemType == ItemTypeShield) { hate += item->GetItem()->AC; } - const Item_Struct *itm = item->GetItem(); + const ItemData *itm = item->GetItem(); hate = hate * (100 + GetFuriousBash(itm->Focus.Effect)) / 100; } } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index b331113bd..a28c924c3 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -620,7 +620,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove strstr(transI->GetItem()->Name, "parts") || strstr(transI->GetItem()->Name, "Parts")){ CastToClient()->DeleteItemInInventory(MainCursor, fcharges, true); - CastToClient()->SummonItem(13073, fcharges); + CastToClient()->SummonItem(13073, fcharges, 0); } else{ Message(13, "You can only transmute flesh to bone."); @@ -1143,7 +1143,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_SummonItem: { - const Item_Struct *item = database.GetItem(spell.base[i]); + const ItemData *item = database.GetItem(spell.base[i]); #ifdef SPELL_EFFECT_SPAM const char *itemname = item ? item->Name : "*Unknown Item*"; snprintf(effect_desc, _EDLEN, "Summon Item: %s (id %d)", itemname, spell.base[i]); @@ -1171,7 +1171,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove c->SendItemPacket(MainCursor, SummonedItem, ItemPacketSummonItem); safe_delete(SummonedItem); } - SummonedItem = database.CreateItem(spell.base[i], charges); + SummonedItem = database.CreateItemOld(spell.base[i], charges); } } @@ -1179,7 +1179,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } case SE_SummonItemIntoBag: { - const Item_Struct *item = database.GetItem(spell.base[i]); + const ItemData *item = database.GetItem(spell.base[i]); #ifdef SPELL_EFFECT_SPAM const char *itemname = item ? item->Name : "*Unknown Item*"; snprintf(effect_desc, _EDLEN, "Summon Item In Bag: %s (id %d)", itemname, spell.base[i]); @@ -1208,7 +1208,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (charges < 1) charges = 1; - ItemInst *SubItem = database.CreateItem(spell.base[i], charges); + ItemInst *SubItem = database.CreateItemOld(spell.base[i], charges); if (SubItem != nullptr) { SummonedItem->PutItem(slot, *SubItem); safe_delete(SubItem); @@ -5154,7 +5154,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { //item focus if (itembonuses.FocusEffects[type]){ - const Item_Struct* TempItem = 0; + const ItemData* TempItem = 0; for(int x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::EQUIPMENT_END; x++) { @@ -5185,7 +5185,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { aug = ins->GetAugment(y); if(aug) { - const Item_Struct* TempItemAug = aug->GetItem(); + const ItemData* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && IsValidSpell(TempItemAug->Focus.Effect)) { proc_spellid = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id); if (IsValidSpell(proc_spellid)){ @@ -5280,8 +5280,8 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[type]){ - const Item_Struct* TempItem = 0; - const Item_Struct* UsedItem = 0; + const ItemData* TempItem = 0; + const ItemData* UsedItem = 0; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -5328,7 +5328,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { aug = ins->GetAugment(y); if(aug) { - const Item_Struct* TempItemAug = aug->GetItem(); + const ItemData* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { focus_max = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id, true); @@ -5549,8 +5549,8 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { if (RuleB(Spells, NPC_UseFocusFromItems) && itembonuses.FocusEffects[type]){ - const Item_Struct* TempItem = 0; - const Item_Struct* UsedItem = 0; + const ItemData* TempItem = 0; + const ItemData* UsedItem = 0; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -5558,8 +5558,8 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { //item focus for(int i = 0; i < EmuConstants::EQUIPMENT_SIZE; i++){ - const Item_Struct *cur = database.GetItem(equipment[i]); - + const ItemData *cur = database.GetItem(equipment[i]); + if(!cur) continue; diff --git a/zone/spells.cpp b/zone/spells.cpp index faaace669..5424fde25 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1148,7 +1148,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, missingreags=true; } - const Item_Struct *item = database.GetItem(component); + const ItemData *item = database.GetItem(component); if(item) { c->Message_StringID(13, MISSING_SPELL_COMP_ITEM, item->Name); Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Canceled. Missing required reagent %s (%d)", spell_id, item->Name, component); @@ -1210,7 +1210,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, { bool fromaug = false; const ItemInst* inst = CastToClient()->GetInv()[inventory_slot]; - Item_Struct* augitem = 0; + ItemData* augitem = 0; uint32 recastdelay = 0; uint32 recasttype = 0; @@ -1223,7 +1223,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, if (!aug_i) continue; - const Item_Struct* aug = aug_i->GetItem(); + const ItemData* aug = aug_i->GetItem(); if (!aug) continue; @@ -1259,7 +1259,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, if (inst && inst->IsType(ItemClassCommon) && (inst->GetItem()->Click.Effect == spell_id) && inst->GetCharges() || fromaug) { - //const Item_Struct* item = inst->GetItem(); + //const ItemData* item = inst->GetItem(); int16 charges = inst->GetItem()->MaxCharges; if(fromaug) { charges = -1; } //Don't destroy the parent item diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 4f3fe8124..f1c8c627a 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -1821,11 +1821,6 @@ void ClientTaskState::IncrementDoneCount(Client *c, TaskInformation* Task, int T buf[23] = '\0'; parse->EventPlayer(EVENT_TASK_STAGE_COMPLETE, c, buf, 0); } - /* QS: PlayerLogTaskUpdates :: Update */ - if (RuleB(QueryServ, PlayerLogTaskUpdates)){ - std::string event_desc = StringFormat("Task Stage Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", ActiveTasks[TaskIndex].TaskID, ActiveTasks[TaskIndex].Activity[ActivityID].ActivityID, ActiveTasks[TaskIndex].Activity[ActivityID].DoneCount, c->GetZoneID(), c->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Task_Updates, c->CharacterID(), event_desc); - } } // If this task is now complete, the Completed tasks will have been @@ -1837,12 +1832,6 @@ void ClientTaskState::IncrementDoneCount(Client *c, TaskInformation* Task, int T buf[23] = '\0'; parse->EventPlayer(EVENT_TASK_COMPLETE, c, buf, 0); - /* QS: PlayerLogTaskUpdates :: Complete */ - if (RuleB(QueryServ, PlayerLogTaskUpdates)){ - std::string event_desc = StringFormat("Task Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", ActiveTasks[TaskIndex].TaskID, ActiveTasks[TaskIndex].Activity[ActivityID].ActivityID, ActiveTasks[TaskIndex].Activity[ActivityID].DoneCount, c->GetZoneID(), c->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Task_Updates, c->CharacterID(), event_desc); - } - taskmanager->SendCompletedTasksToClient(c, this); c->SendTaskActivityComplete(ActiveTasks[TaskIndex].TaskID, 0, TaskIndex, false); taskmanager->SaveClientState(c, this); @@ -1866,7 +1855,7 @@ void ClientTaskState::RewardTask(Client *c, TaskInformation *Task) { if(!Task || !c) return; - const Item_Struct* Item; + const ItemData* Item; std::vector RewardList; switch(Task->RewardMethod) { @@ -2759,7 +2748,7 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN } if(ItemID) { - const Item_Struct* reward_item = database.GetItem(ItemID); + const ItemData* reward_item = database.GetItem(ItemID); Client::TextLink linker; linker.SetLinkType(linker.linkItemData); diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 6ed516da0..b9e946758 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -55,13 +55,13 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme else { // Check to see if they have an inventory container type 53 that is used for this. - Inventory& user_inv = user->GetInv(); + InventoryOld& user_inv = user->GetInv(); ItemInst* inst = nullptr; inst = user_inv.GetItem(in_augment->container_slot); if (inst) { - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); if (item && inst->IsType(ItemClassContainer) && item->BagType == 53) { // We have found an appropriate inventory augmentation sealer @@ -218,7 +218,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme const ItemInst* inst = container->GetItem(i); if (inst) { - user->DeleteItemInInventory(Inventory::CalcSlotId(in_augment->container_slot,i),0,true); + user->DeleteItemInInventory(InventoryOld::CalcSlotId(in_augment->container_slot,i),0,true); } } // Explicitly mark container as cleared. @@ -247,7 +247,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob return; } - Inventory& user_inv = user->GetInv(); + InventoryOld& user_inv = user->GetInv(); PlayerProfile_Struct& user_pp = user->GetPP(); ItemInst* container = nullptr; ItemInst* inst = nullptr; @@ -267,7 +267,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob else { inst = user_inv.GetItem(in_combine->container_slot); if (inst) { - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); if (item && inst->IsType(ItemClassContainer)) { c_type = item->BagType; some_id = item->ID; @@ -285,8 +285,8 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob const ItemInst* inst = container->GetItem(0); bool AllowAll = RuleB(Inventory, AllowAnyWeaponTransformation); if (inst && ItemInst::CanTransform(inst->GetItem(), container->GetItem(), AllowAll)) { - const Item_Struct* new_weapon = inst->GetItem(); - user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); + const ItemData* new_weapon = inst->GetItem(); + user->DeleteItemInInventory(InventoryOld::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), MainCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2)); user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name); @@ -305,8 +305,8 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob if (container->GetItem() && container->GetItem()->BagType == BagTypeDetransformationmold) { const ItemInst* inst = container->GetItem(0); if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIcon()) { - const Item_Struct* new_weapon = inst->GetItem(); - user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); + const ItemData* new_weapon = inst->GetItem(); + user->DeleteItemInInventory(InventoryOld::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), MainCursor, 0, 0); user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name); @@ -395,7 +395,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob for (uint8 i = MAIN_BEGIN; i < EmuConstants::MAP_WORLD_SIZE; i++) { const ItemInst* inst = container->GetItem(i); if (inst) { - user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot,i),0,true); + user->DeleteItemInInventory(InventoryOld::CalcSlotId(in_combine->container_slot,i),0,true); } } container->Clear(); @@ -492,7 +492,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac memset(counts, 0, sizeof(counts)); //search for all the items in their inventory - Inventory& user_inv = user->GetInv(); + InventoryOld& user_inv = user->GetInv(); uint8 count = 0; uint8 needcount = 0; @@ -529,7 +529,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac for(std::list::iterator it = MissingItems.begin(); it != MissingItems.end(); ++it) { - const Item_Struct* item = database.GetItem(*it); + const ItemData* item = database.GetItem(*it); if(item) user->Message_StringID(MT_Skills, TRADESKILL_MISSING_ITEM, item->Name); @@ -970,7 +970,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { break; } } - const Item_Struct* item = nullptr; + const ItemData* item = nullptr; if (spec->tradeskill == SkillBlacksmithing) { switch(GetAA(aaBlacksmithingMastery)) { @@ -1085,18 +1085,12 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { itr = spec->onsuccess.begin(); while(itr != spec->onsuccess.end() && !spec->quest) { //should we check this crap? - SummonItem(itr->first, itr->second); + SummonItem(itr->first, itr->second, 0); item = database.GetItem(itr->first); if (this->GetGroup()) { entity_list.MessageGroup(this, true, MT_Skills, "%s has successfully fashioned %s!", GetName(), item->Name); } - /* QS: Player_Log_Trade_Skill_Events */ - if (RuleB(QueryServ, PlayerLogTradeSkillEvents)){ - std::string event_desc = StringFormat("Success :: fashioned recipe_id:%i tskillid:%i trivial:%i chance:%4.2f in zoneid:%i instid:%i", spec->recipe_id, spec->tradeskill, spec->trivial, chance, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Trade_Skill_Events, this->CharacterID(), event_desc); - } - if(RuleB(TaskSystem, EnableTaskSystem)) UpdateTasksForItem(ActivityTradeSkill, itr->first, itr->second); ++itr; @@ -1119,16 +1113,10 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { } - /* QS: Player_Log_Trade_Skill_Events */ - if (RuleB(QueryServ, PlayerLogTradeSkillEvents)){ - std::string event_desc = StringFormat("Failed :: recipe_id:%i tskillid:%i trivial:%i chance:%4.2f in zoneid:%i instid:%i", spec->recipe_id, spec->tradeskill, spec->trivial, chance, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Trade_Skill_Events, this->CharacterID(), event_desc); - } - itr = spec->onfail.begin(); while(itr != spec->onfail.end()) { //should we check these arguments? - SummonItem(itr->first, itr->second); + SummonItem(itr->first, itr->second, 0); ++itr; } @@ -1143,7 +1131,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { while(itr != spec->salvage.end()) { for(sc = 0; sc < itr->second; sc++) if(zone->random.Roll(SalvageChance)) - SummonItem(itr->first, 1); + SummonItem(itr->first, 1, 0); ++itr; } } @@ -1219,7 +1207,7 @@ bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint3 if (!inst) continue; - const Item_Struct* item = GetItem(inst->GetItem()->ID); + const ItemData* item = GetItem(inst->GetItem()->ID); if (!item) continue; @@ -1348,7 +1336,7 @@ bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint3 if(!inst) continue; - const Item_Struct* item = GetItem(inst->GetItem()->ID); + const ItemData* item = GetItem(inst->GetItem()->ID); if (!item) continue; diff --git a/zone/trading.cpp b/zone/trading.cpp index df8d159b1..b1d5f8633 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -174,7 +174,7 @@ void Trade::SendItemData(const ItemInst* inst, int16 dest_slot_id) with->SendItemPacket(dest_slot_id - EmuConstants::TRADE_BEGIN, inst, ItemPacketTradeView); if (inst->GetItem()->ItemClass == 1) { for (uint16 i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) { - uint16 bagslot_id = Inventory::CalcSlotId(dest_slot_id, i); + uint16 bagslot_id = InventoryOld::CalcSlotId(dest_slot_id, i); const ItemInst* bagitem = trader->GetInv().GetItem(bagslot_id); if (bagitem) { with->SendItemPacket(bagslot_id - EmuConstants::TRADE_BEGIN, bagitem, ItemPacketTradeView); @@ -189,107 +189,107 @@ void Trade::SendItemData(const ItemInst* inst, int16 dest_slot_id) // Audit trade: The part logged is what travels owner -> with void Trade::LogTrade() { - Mob* with = With(); - if (!owner->IsClient() || !with) - return; // Should never happen - - Client* trader = owner->CastToClient(); - bool logtrade = false; - int admin_level = 0; - uint8 item_count = 0; - - if (zone->tradevar != 0) { - for (uint16 i = EmuConstants::TRADE_BEGIN; i <= EmuConstants::TRADE_END; i++) { - if (trader->GetInv().GetItem(i)) - item_count++; - } - - if (((this->cp + this->sp + this->gp + this->pp)>0) || (item_count>0)) - admin_level = trader->Admin(); - else - admin_level = 999; - - if (zone->tradevar == 7) { - logtrade = true; - } - else if ((admin_level>=10) && (admin_level<20)) { - if ((zone->tradevar<8) && (zone->tradevar>5)) - logtrade = true; - } - else if (admin_level<=20) { - if ((zone->tradevar<8) && (zone->tradevar>4)) - logtrade = true; - } - else if (admin_level<=80) { - if ((zone->tradevar<8) && (zone->tradevar>3)) - logtrade = true; - } - else if (admin_level<=100){ - if ((zone->tradevar<9) && (zone->tradevar>2)) - logtrade = true; - } - else if (admin_level<=150){ - if (((zone->tradevar<8) && (zone->tradevar>1)) || (zone->tradevar==9)) - logtrade = true; - } - else if (admin_level<=255){ - if ((zone->tradevar<8) && (zone->tradevar>0)) - logtrade = true; - } - } - - if (logtrade == true) { - char logtext[1000] = {0}; - uint32 cash = 0; - bool comma = false; - - // Log items offered by owner - cash = this->cp + this->sp + this->gp + this->pp; - if ((cash>0) || (item_count>0)) { - sprintf(logtext, "%s gave %s ", trader->GetName(), with->GetName()); - - if (item_count > 0) { - strcat(logtext, "items {"); - - for (uint16 i = EmuConstants::TRADE_BEGIN; i <= EmuConstants::TRADE_END; i++) { - const ItemInst* inst = trader->GetInv().GetItem(i); - - if (!comma) - comma = true; - else { - if (inst) - strcat(logtext, ","); - } - - if (inst) { - char item_num[15] = {0}; - sprintf(item_num, "%i", inst->GetItem()->ID); - strcat(logtext, item_num); - - if (inst->IsType(ItemClassContainer)) { - for (uint8 j = SUB_BEGIN; j < EmuConstants::ITEM_CONTAINER_SIZE; j++) { - inst = trader->GetInv().GetItem(i, j); - if (inst) { - strcat(logtext, ","); - sprintf(item_num, "%i", inst->GetItem()->ID); - strcat(logtext, item_num); - } - } - } - } - } - } - - if (cash > 0) { - char money[100] = {0}; - sprintf(money, " %ipp, %igp, %isp, %icp", trader->trade->pp, trader->trade->gp, trader->trade->sp, trader->trade->cp); - strcat(logtext, money); - } - - database.logevents(trader->AccountName(), trader->AccountID(), - trader->Admin(), trader->GetName(), with->GetName(), "Trade", logtext, 6); - } - } + //Mob* with = With(); + //if (!owner->IsClient() || !with) + // return; // Should never happen + // + //Client* trader = owner->CastToClient(); + //bool logtrade = false; + //int admin_level = 0; + //uint8 item_count = 0; + // + //if (zone->tradevar != 0) { + // for (uint16 i = EmuConstants::TRADE_BEGIN; i <= EmuConstants::TRADE_END; i++) { + // if (trader->GetInv().GetItem(i)) + // item_count++; + // } + // + // if (((this->cp + this->sp + this->gp + this->pp)>0) || (item_count>0)) + // admin_level = trader->Admin(); + // else + // admin_level = 999; + // + // if (zone->tradevar == 7) { + // logtrade = true; + // } + // else if ((admin_level>=10) && (admin_level<20)) { + // if ((zone->tradevar<8) && (zone->tradevar>5)) + // logtrade = true; + // } + // else if (admin_level<=20) { + // if ((zone->tradevar<8) && (zone->tradevar>4)) + // logtrade = true; + // } + // else if (admin_level<=80) { + // if ((zone->tradevar<8) && (zone->tradevar>3)) + // logtrade = true; + // } + // else if (admin_level<=100){ + // if ((zone->tradevar<9) && (zone->tradevar>2)) + // logtrade = true; + // } + // else if (admin_level<=150){ + // if (((zone->tradevar<8) && (zone->tradevar>1)) || (zone->tradevar==9)) + // logtrade = true; + // } + // else if (admin_level<=255){ + // if ((zone->tradevar<8) && (zone->tradevar>0)) + // logtrade = true; + // } + //} + // + //if (logtrade == true) { + // char logtext[1000] = {0}; + // uint32 cash = 0; + // bool comma = false; + // + // // Log items offered by owner + // cash = this->cp + this->sp + this->gp + this->pp; + // if ((cash>0) || (item_count>0)) { + // sprintf(logtext, "%s gave %s ", trader->GetName(), with->GetName()); + // + // if (item_count > 0) { + // strcat(logtext, "items {"); + // + // for (uint16 i = EmuConstants::TRADE_BEGIN; i <= EmuConstants::TRADE_END; i++) { + // const ItemInst* inst = trader->GetInv().GetItem(i); + // + // if (!comma) + // comma = true; + // else { + // if (inst) + // strcat(logtext, ","); + // } + // + // if (inst) { + // char item_num[15] = {0}; + // sprintf(item_num, "%i", inst->GetItem()->ID); + // strcat(logtext, item_num); + // + // if (inst->IsType(ItemClassContainer)) { + // for (uint8 j = SUB_BEGIN; j < EmuConstants::ITEM_CONTAINER_SIZE; j++) { + // inst = trader->GetInv().GetItem(i, j); + // if (inst) { + // strcat(logtext, ","); + // sprintf(item_num, "%i", inst->GetItem()->ID); + // strcat(logtext, item_num); + // } + // } + // } + // } + // } + // } + // + // if (cash > 0) { + // char money[100] = {0}; + // sprintf(money, " %ipp, %igp, %isp, %icp", trader->trade->pp, trader->trade->gp, trader->trade->sp, trader->trade->cp); + // strcat(logtext, money); + // } + // + // database.logevents(trader->AccountName(), trader->AccountID(), + // trader->Admin(), trader->GetName(), with->GetName(), "Trade", logtext, 6); + // } + //} } @@ -317,7 +317,7 @@ void Trade::DumpTrade() if (inst) { Log.Out(Logs::Detail, Logs::Trading, "\tBagItem %i (Charges=%i, Slot=%i)", inst->GetItem()->ID, inst->GetCharges(), - Inventory::CalcSlotId(i, j)); + InventoryOld::CalcSlotId(i, j)); } } } @@ -368,7 +368,7 @@ void Client::ResetTrade() { break; if (partial_inst->GetID() != inst->GetID()) { - Log.Out(Logs::Detail, Logs::None, "[CLIENT] Client::ResetTrade() - an incompatible location reference was returned by Inventory::FindFreeSlotForTradeItem()"); + Log.Out(Logs::Detail, Logs::None, "[CLIENT] Client::ResetTrade() - an incompatible location reference was returned by InventoryOld::FindFreeSlotForTradeItem()"); break; } @@ -454,38 +454,12 @@ void Client::ResetTrade() { void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, std::list* event_details) { if(tradingWith && tradingWith->IsClient()) { Client* other = tradingWith->CastToClient(); - QSPlayerLogTrade_Struct* qs_audit = nullptr; - bool qs_log = false; if(other) { Log.Out(Logs::Detail, Logs::Trading, "Finishing trade with client %s", other->GetName()); this->AddMoneyToPP(other->trade->cp, other->trade->sp, other->trade->gp, other->trade->pp, true); - // step 0: pre-processing - // QS code - if (RuleB(QueryServ, PlayerLogTrades) && event_entry && event_details) { - qs_audit = (QSPlayerLogTrade_Struct*)event_entry; - qs_log = true; - - if (finalizer) { - qs_audit->char2_id = this->character_id; - - qs_audit->char2_money.platinum = this->trade->pp; - qs_audit->char2_money.gold = this->trade->gp; - qs_audit->char2_money.silver = this->trade->sp; - qs_audit->char2_money.copper = this->trade->cp; - } - else { - qs_audit->char1_id = this->character_id; - - qs_audit->char1_money.platinum = this->trade->pp; - qs_audit->char1_money.gold = this->trade->gp; - qs_audit->char1_money.silver = this->trade->sp; - qs_audit->char1_money.copper = this->trade->cp; - } - } - // step 1: process bags for (int16 trade_slot = EmuConstants::TRADE_BEGIN; trade_slot <= EmuConstants::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; @@ -500,56 +474,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (free_slot != INVALID_INDEX) { if (other->PutItemInInventory(free_slot, *inst, true)) { Log.Out(Logs::Detail, Logs::Trading, "Container %s (%d) successfully transferred, deleting from trade slot.", inst->GetItem()->Name, inst->GetItem()->ID); - if (qs_log) { - QSTradeItems_Struct* detail = new QSTradeItems_Struct; - - detail->from_id = this->character_id; - detail->from_slot = trade_slot; - detail->to_id = other->CharacterID(); - detail->to_slot = free_slot; - detail->item_id = inst->GetID(); - detail->charges = 1; - detail->aug_1 = inst->GetAugmentItemID(1); - detail->aug_2 = inst->GetAugmentItemID(2); - detail->aug_3 = inst->GetAugmentItemID(3); - detail->aug_4 = inst->GetAugmentItemID(4); - detail->aug_5 = inst->GetAugmentItemID(5); - - event_details->push_back(detail); - - if (finalizer) - qs_audit->char2_count += detail->charges; - else - qs_audit->char1_count += detail->charges; - - //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { - for (uint8 sub_slot = SUB_BEGIN; (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items - const ItemInst* bag_inst = inst->GetItem(sub_slot); - - if (bag_inst) { - detail = new QSTradeItems_Struct; - - detail->from_id = this->character_id; - detail->from_slot = Inventory::CalcSlotId(trade_slot, sub_slot); - detail->to_id = other->CharacterID(); - detail->to_slot = Inventory::CalcSlotId(free_slot, sub_slot); - detail->item_id = bag_inst->GetID(); - detail->charges = (!bag_inst->IsStackable() ? 1 : bag_inst->GetCharges()); - detail->aug_1 = bag_inst->GetAugmentItemID(1); - detail->aug_2 = bag_inst->GetAugmentItemID(2); - detail->aug_3 = bag_inst->GetAugmentItemID(3); - detail->aug_4 = bag_inst->GetAugmentItemID(4); - detail->aug_5 = bag_inst->GetAugmentItemID(5); - - event_details->push_back(detail); - - if (finalizer) - qs_audit->char2_count += detail->charges; - else - qs_audit->char1_count += detail->charges; - } - } - } } else { Log.Out(Logs::Detail, Logs::Trading, "Transfer of container %s (%d) to %s failed, returning to giver.", inst->GetItem()->Name, inst->GetItem()->ID, other->GetName()); @@ -588,7 +512,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st break; if (partial_inst->GetID() != inst->GetID()) { - Log.Out(Logs::Detail, Logs::Trading, "[CLIENT] Client::ResetTrade() - an incompatible location reference was returned by Inventory::FindFreeSlotForTradeItem()"); + Log.Out(Logs::Detail, Logs::Trading, "[CLIENT] Client::ResetTrade() - an incompatible location reference was returned by InventoryOld::FindFreeSlotForTradeItem()"); break; } @@ -611,28 +535,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (other->PutItemInInventory(partial_slot, *partial_inst, true)) { Log.Out(Logs::Detail, Logs::Trading, "Partial stack %s (%d) successfully transferred, deleting %i charges from trade slot.", inst->GetItem()->Name, inst->GetItem()->ID, (old_charges - inst->GetCharges())); - if (qs_log) { - QSTradeItems_Struct* detail = new QSTradeItems_Struct; - - detail->from_id = this->character_id; - detail->from_slot = trade_slot; - detail->to_id = other->CharacterID(); - detail->to_slot = partial_slot; - detail->item_id = inst->GetID(); - detail->charges = (old_charges - inst->GetCharges()); - detail->aug_1 = 0; - detail->aug_2 = 0; - detail->aug_3 = 0; - detail->aug_4 = 0; - detail->aug_5 = 0; - - event_details->push_back(detail); - - if (finalizer) - qs_audit->char2_count += detail->charges; - else - qs_audit->char1_count += detail->charges; - } } else { Log.Out(Logs::Detail, Logs::Trading, "Transfer of partial stack %s (%d) to %s failed, returning %i charges to trade slot.", @@ -679,24 +581,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st inst->SetCharges(0); } - if (qs_log) { - QSTradeItems_Struct* detail = new QSTradeItems_Struct; - - detail->from_id = this->character_id; - detail->from_slot = trade_slot; - detail->to_id = this->character_id; - detail->to_slot = bias_slot; - detail->item_id = inst->GetID(); - detail->charges = (old_charges - inst->GetCharges()); - detail->aug_1 = 0; - detail->aug_2 = 0; - detail->aug_3 = 0; - detail->aug_4 = 0; - detail->aug_5 = 0; - - event_details->push_back(detail); - } - if (inst->GetCharges() == 0) { DeleteItemInInventory(trade_slot); break; @@ -719,57 +603,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (free_slot != INVALID_INDEX) { if (other->PutItemInInventory(free_slot, *inst, true)) { Log.Out(Logs::Detail, Logs::Trading, "Item %s (%d) successfully transferred, deleting from trade slot.", inst->GetItem()->Name, inst->GetItem()->ID); - if (qs_log) { - QSTradeItems_Struct* detail = new QSTradeItems_Struct; - - detail->from_id = this->character_id; - detail->from_slot = trade_slot; - detail->to_id = other->CharacterID(); - detail->to_slot = free_slot; - detail->item_id = inst->GetID(); - detail->charges = (!inst->IsStackable() ? 1 : inst->GetCharges()); - detail->aug_1 = inst->GetAugmentItemID(1); - detail->aug_2 = inst->GetAugmentItemID(2); - detail->aug_3 = inst->GetAugmentItemID(3); - detail->aug_4 = inst->GetAugmentItemID(4); - detail->aug_5 = inst->GetAugmentItemID(5); - - event_details->push_back(detail); - - if (finalizer) - qs_audit->char2_count += detail->charges; - else - qs_audit->char1_count += detail->charges; - - // 'step 3' should never really see containers..but, just in case... - //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { - for (uint8 sub_slot = SUB_BEGIN; (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items - const ItemInst* bag_inst = inst->GetItem(sub_slot); - - if (bag_inst) { - detail = new QSTradeItems_Struct; - - detail->from_id = this->character_id; - detail->from_slot = trade_slot; - detail->to_id = other->CharacterID(); - detail->to_slot = free_slot; - detail->item_id = bag_inst->GetID(); - detail->charges = (!bag_inst->IsStackable() ? 1 : bag_inst->GetCharges()); - detail->aug_1 = bag_inst->GetAugmentItemID(1); - detail->aug_2 = bag_inst->GetAugmentItemID(2); - detail->aug_3 = bag_inst->GetAugmentItemID(3); - detail->aug_4 = bag_inst->GetAugmentItemID(4); - detail->aug_5 = bag_inst->GetAugmentItemID(5); - - event_details->push_back(detail); - - if (finalizer) - qs_audit->char2_count += detail->charges; - else - qs_audit->char1_count += detail->charges; - } - } - } } else { Log.Out(Logs::Detail, Logs::Trading, "Transfer of Item %s (%d) to %s failed, returning to giver.", inst->GetItem()->Name, inst->GetItem()->ID, other->GetName()); @@ -794,79 +627,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } } else if(tradingWith && tradingWith->IsNPC()) { - QSPlayerLogHandin_Struct* qs_audit = nullptr; - bool qs_log = false; - - // QS code - if(RuleB(QueryServ, PlayerLogTrades) && event_entry && event_details) { - // Currently provides only basic functionality. Calling method will also - // need to be modified before item returns and rewards can be logged. - qs_audit = (QSPlayerLogHandin_Struct*)event_entry; - qs_log = true; - - qs_audit->quest_id = 0; - qs_audit->char_id = character_id; - qs_audit->char_money.platinum = trade->pp; - qs_audit->char_money.gold = trade->gp; - qs_audit->char_money.silver = trade->sp; - qs_audit->char_money.copper = trade->cp; - qs_audit->char_count = 0; - qs_audit->npc_id = tradingWith->GetNPCTypeID(); - qs_audit->npc_money.platinum = 0; - qs_audit->npc_money.gold = 0; - qs_audit->npc_money.silver = 0; - qs_audit->npc_money.copper = 0; - qs_audit->npc_count = 0; - } - - if(qs_log) { // This can be incorporated below when revisions are made - for (int16 trade_slot = EmuConstants::TRADE_BEGIN; trade_slot <= EmuConstants::TRADE_NPC_END; ++trade_slot) { - const ItemInst* trade_inst = m_inv[trade_slot]; - - if(trade_inst) { - QSHandinItems_Struct* detail = new QSHandinItems_Struct; - - strcpy(detail->action_type, "HANDIN"); - - detail->char_slot = trade_slot; - detail->item_id = trade_inst->GetID(); - detail->charges = (!trade_inst->IsStackable() ? 1 : trade_inst->GetCharges()); - detail->aug_1 = trade_inst->GetAugmentItemID(1); - detail->aug_2 = trade_inst->GetAugmentItemID(2); - detail->aug_3 = trade_inst->GetAugmentItemID(3); - detail->aug_4 = trade_inst->GetAugmentItemID(4); - detail->aug_5 = trade_inst->GetAugmentItemID(5); - - event_details->push_back(detail); - qs_audit->char_count += detail->charges; - - if(trade_inst->IsType(ItemClassContainer)) { - for (uint8 sub_slot = SUB_BEGIN; sub_slot < trade_inst->GetItem()->BagSlots; ++sub_slot) { - const ItemInst* trade_baginst = trade_inst->GetItem(sub_slot); - - if(trade_baginst) { - detail = new QSHandinItems_Struct; - - strcpy(detail->action_type, "HANDIN"); - - detail->char_slot = Inventory::CalcSlotId(trade_slot, sub_slot); - detail->item_id = trade_baginst->GetID(); - detail->charges = (!trade_inst->IsStackable() ? 1 : trade_inst->GetCharges()); - detail->aug_1 = trade_baginst->GetAugmentItemID(1); - detail->aug_2 = trade_baginst->GetAugmentItemID(2); - detail->aug_3 = trade_baginst->GetAugmentItemID(3); - detail->aug_4 = trade_baginst->GetAugmentItemID(4); - detail->aug_5 = trade_baginst->GetAugmentItemID(5); - - event_details->push_back(detail); - qs_audit->char_count += detail->charges; - } - } - } - } - } - } - bool quest_npc = false; if(parse->HasQuestSub(tradingWith->GetNPCTypeID(), EVENT_TRADE)) { // This is a quest NPC @@ -885,7 +645,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st continue; } - const Item_Struct* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); if(item && quest_npc == false) { // if it was not a NO DROP or Attuned item (or if a GM is trading), let the NPC have it if(GetGM() || (item->NoDrop != 0 && inst->IsAttuned() == false)) { @@ -894,7 +654,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st for(int16 bslot = SUB_BEGIN; bslot < item->BagSlots; bslot++) { const ItemInst* baginst = inst->GetItem(bslot); if (baginst) { - const Item_Struct* bagitem = baginst->GetItem(); + const ItemData* bagitem = baginst->GetItem(); if (bagitem && (GetGM() || (bagitem->NoDrop != 0 && baginst->IsAttuned() == false))) { tradingWith->CastToNPC()->AddLootDrop(bagitem, &tradingWith->CastToNPC()->itemlist, baginst->GetCharges(), 1, 127, true, true); @@ -923,7 +683,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if(!tradingWith->IsMoving()) tradingWith->FaceTarget(this); - this->EVENT_ITEM_ScriptStopReturn(); + ItemScriptStopReturn(); } } @@ -1158,14 +918,14 @@ void Client::SendTraderItem(uint32 ItemID, uint16 Quantity) { std::string Packet; int16 FreeSlotID=0; - const Item_Struct* item = database.GetItem(ItemID); + const ItemData* item = database.GetItem(ItemID); if(!item){ Log.Out(Logs::Detail, Logs::Trading, "Bogus item deleted in Client::SendTraderItem!\n"); return; } - ItemInst* inst = database.CreateItem(item, Quantity); + ItemInst* inst = database.CreateItemOld(item, Quantity); if (inst) { @@ -1192,7 +952,7 @@ void Client::SendSingleTraderItem(uint32 CharID, int SerialNumber) { } void Client::BulkSendTraderInventory(uint32 char_id) { - const Item_Struct *item; + const ItemData *item; TraderCharges_Struct* TraderItems = database.LoadTraderItemWithCharges(char_id); @@ -1204,7 +964,7 @@ void Client::BulkSendTraderInventory(uint32 char_id) { item=database.GetItem(TraderItems->ItemID[i]); if (item && (item->NoDrop!=0)) { - ItemInst* inst = database.CreateItem(item); + ItemInst* inst = database.CreateItemOld(item); if (inst) { inst->SetSerialNumber(TraderItems->SerialNumber[i]); if(TraderItems->Charges[i] > 0) @@ -1237,7 +997,7 @@ uint32 Client::FindTraderItemSerialNumber(int32 ItemID) { if (item && item->GetItem()->ID == 17899){ //Traders Satchel for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; x++) { // we already have the parent bag and a contents iterator..why not just iterate the bag!?? - SlotID = Inventory::CalcSlotId(i, x); + SlotID = InventoryOld::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); if (item) { if (item->GetID() == ItemID) @@ -1260,7 +1020,7 @@ ItemInst* Client::FindTraderItemBySerialNumber(int32 SerialNumber){ if(item && item->GetItem()->ID == 17899){ //Traders Satchel for(int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; x++) { // we already have the parent bag and a contents iterator..why not just iterate the bag!?? - SlotID = Inventory::CalcSlotId(i, x); + SlotID = InventoryOld::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); if(item) { if(item->GetSerialNumber() == SerialNumber) @@ -1290,7 +1050,7 @@ GetItems_Struct* Client::GetTraderItems(){ item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel for(int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; x++) { - SlotID = Inventory::CalcSlotId(i, x); + SlotID = InventoryOld::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1314,7 +1074,7 @@ uint16 Client::FindTraderItem(int32 SerialNumber, uint16 Quantity){ item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel for(int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; x++){ - SlotID = Inventory::CalcSlotId(i, x); + SlotID = InventoryOld::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1333,68 +1093,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. @@ -2030,11 +1790,11 @@ static void UpdateTraderCustomerItemsAdded(uint32 CustomerID, TraderCharges_Stru if(!Customer) return; - const Item_Struct *item = database.GetItem(ItemID); + const ItemData *item = database.GetItem(ItemID); if(!item) return; - ItemInst* inst = database.CreateItem(item); + ItemInst* inst = database.CreateItemOld(item); if(!inst) return; @@ -2074,7 +1834,7 @@ static void UpdateTraderCustomerPriceChanged(uint32 CustomerID, TraderCharges_St if(!Customer) return; - const Item_Struct *item = database.GetItem(ItemID); + const ItemData *item = database.GetItem(ItemID); if(!item) return; @@ -2115,7 +1875,7 @@ static void UpdateTraderCustomerPriceChanged(uint32 CustomerID, TraderCharges_St Log.Out(Logs::Detail, Logs::Trading, "Sending price updates to customer %s", Customer->GetName()); - ItemInst* inst = database.CreateItem(item); + ItemInst* inst = database.CreateItemOld(item); if(!inst) return; @@ -2233,7 +1993,7 @@ void Client::HandleTraderPriceUpdate(const EQApplicationPacket *app) { } - const Item_Struct *item = 0; + const ItemData *item = 0; if(IDOfItemToAdd) item = database.GetItem(IDOfItemToAdd); @@ -2399,7 +2159,7 @@ void Client::SendBuyerResults(char* searchString, uint32 searchID) { char *buf = (char *)outapp->pBuffer; - const Item_Struct* item = database.GetItem(itemID); + const ItemData* item = database.GetItem(itemID); if(!item) continue; @@ -2491,7 +2251,7 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) { char *Buf = (char *)outapp->pBuffer; - const Item_Struct* item = database.GetItem(ItemID); + const ItemData* item = database.GetItem(ItemID); if(!item) continue; @@ -2514,347 +2274,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 Item_Struct *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(Quantity) * static_cast(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 to for ' - // - // 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 from for ' - // - - 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(Quantity) * static_cast(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 to for ' +// // +// // 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 from for ' +// // +// +// 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) { @@ -2924,7 +2684,7 @@ void Client::UpdateBuyLine(const EQApplicationPacket *app) { /*uint32 UnknownZ =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused uint32 ItemCount = VARSTRUCT_DECODE_TYPE(uint32, Buf); - const Item_Struct *item = database.GetItem(ItemID); + const ItemData *item = database.GetItem(ItemID); if(!item) return; @@ -2988,7 +2748,7 @@ void Client::BuyerItemSearch(const EQApplicationPacket *app) { BuyerItemSearchResults_Struct* bisr = (BuyerItemSearchResults_Struct*)outapp->pBuffer; - const Item_Struct* item = 0; + const ItemData* item = 0; int Count=0; diff --git a/zone/tribute.cpp b/zone/tribute.cpp index df01f843e..f6a7df4c9 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -161,7 +161,7 @@ void Client::DoTributeUpdate() { uint32 item_id = tier.tribute_item_id; //summon the item for them - const ItemInst* inst = database.CreateItem(item_id, 1); + const ItemInst* inst = database.CreateItemOld(item_id, 1); if(inst == nullptr) continue; diff --git a/zone/tune.cpp b/zone/tune.cpp index 4153d5b84..cf0c394c3 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -630,7 +630,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) if( Hand == MainPrimary && GetLevel() >= 28 && IsWarriorClass() ) { - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); + ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const ItemData*) nullptr ); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; diff --git a/zone/zone.cpp b/zone/zone.cpp index e58bea24a..4fc745c6b 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -51,6 +51,7 @@ #include "worldserver.h" #include "zone.h" #include "zone_config.h" +#include "queryserv.h" #include #include @@ -62,8 +63,6 @@ #define strcasecmp _stricmp #endif - - extern bool staticzone; extern NetConnection net; extern PetitionList petition_list; @@ -72,6 +71,7 @@ extern uint16 adverrornum; extern uint32 numclients; extern WorldServer worldserver; extern Zone* zone; +extern QueryServ* QServ; Mutex MZoneShutdown; @@ -104,34 +104,6 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { zone->zonemap = Map::LoadMapFile(zone->map_name); zone->watermap = WaterMap::LoadWaterMapfile(zone->map_name); zone->pathing = PathManager::LoadPathFile(zone->map_name); - - char tmp[10]; - if (database.GetVariable("loglevel",tmp, 9)) { - int log_levels[4]; - if (atoi(tmp)>9){ //Server is using the new code - for(int i=0;i<4;i++){ - if (((int)tmp[i]>=48) && ((int)tmp[i]<=57)) - log_levels[i]=(int)tmp[i]-48; //get the value to convert it to an int from the ascii value - else - log_levels[i]=0; //set to zero on a bogue char - } - zone->loglevelvar = log_levels[0]; - Log.Out(Logs::General, Logs::Status, "General logging level: %i", zone->loglevelvar); - zone->merchantvar = log_levels[1]; - Log.Out(Logs::General, Logs::Status, "Merchant logging level: %i", zone->merchantvar); - zone->tradevar = log_levels[2]; - Log.Out(Logs::General, Logs::Status, "Trade logging level: %i", zone->tradevar); - zone->lootvar = log_levels[3]; - Log.Out(Logs::General, Logs::Status, "Loot logging level: %i", zone->lootvar); - } - else { - zone->loglevelvar = uint8(atoi(tmp)); //continue supporting only command logging (for now) - zone->merchantvar = 0; - zone->tradevar = 0; - zone->lootvar = 0; - } - } - ZoneLoaded = true; worldserver.SetZone(iZoneID, iInstanceID); @@ -257,7 +229,7 @@ bool Zone::LoadZoneObjects() { } else { // Groundspawn object - inst = database.CreateItem(itemid); + inst = database.CreateItemOld(itemid); } //Father Nitwit's fix... not perfect... @@ -295,7 +267,7 @@ bool Zone::LoadGroundSpawns() { for(gsindex=0;gsindex<50;gsindex++){ if(groundspawn.spawn[gsindex].item>0 && groundspawn.spawn[gsindex].item<500000){ ItemInst* inst = nullptr; - inst = database.CreateItem(groundspawn.spawn[gsindex].item); + inst = database.CreateItemOld(groundspawn.spawn[gsindex].item); gsnumber=groundspawn.spawn[gsindex].max_allowed; ix=0; if(inst){ @@ -762,11 +734,6 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) is_zone_time_localized = false; - loglevelvar = 0; - merchantvar = 0; - tradevar = 0; - lootvar = 0; - if(RuleB(TaskSystem, EnableTaskSystem)) { taskmanager->LoadProximities(zoneid); } @@ -1175,7 +1142,7 @@ bool Zone::Process() { if(spawn2_timer.Check()) { LinkedListIterator iterator(spawn2_list); - Inventory::CleanDirty(); + InventoryOld::CleanDirty(); iterator.Reset(); while (iterator.MoreElements()) { @@ -2299,3 +2266,70 @@ void Zone::UpdateHotzone() is_hotzone = atoi(row[0]) == 0 ? false: true; } +void Zone::LogEvent(EventLogTypes type, Client *c, const std::string &desc) { + if(!c) + return; + + int zone_id = GetZoneID(); + int zone_instance = GetInstanceID(); + int zone_version = GetInstanceVersion(); + + int account_id = c->AccountID(); + std::string name = c->GetName(); + int id = c->CharacterID(); + + int target_account_id; + std::string target_name; + int target_id; + + Mob *target = c->GetTarget(); + if(target && target->IsClient()) { + Client *target_c = target->CastToClient(); + + target_account_id = target_c->AccountID(); + target_name = target_c->GetName(); + target_id = target_c->CharacterID(); + } + else if(target && target->IsNPC()) { + NPC *target_n = target->CastToNPC(); + + target_account_id = 0; + target_name = target_n->GetName(); + target_id = target_n->GetNPCTypeID(); + } + else if(target) { + target_account_id = 0; + target_name = target->GetName(); + target_id = 0; + } + else { + target_account_id = 0; + target_name = ""; + target_id = 0; + } + + + std::string query = StringFormat("INSERT INTO event_log " + "(type, zone_id, zone_instance, zone_version, player_account_id, " + "player_id, player_name, target_account_id, target_id, target_name, `desc`)" + " VALUES " + "(%i, %i, %i, %i, %i, %i, '%s', %i, %i, '%s', '%s')", + (int)type, + zone_id, + zone_instance, + zone_version, + account_id, + id, + EscapeString(name).c_str(), + target_account_id, + target_id, + EscapeString(target_name).c_str(), + EscapeString(desc).c_str() + ); + + auto results = database.QueryDatabase(query); + if(!results.Success()) { + Log.Out(Logs::General, Logs::Error, "Log Error: %s", results.ErrorMessage().c_str()); + } + //QServ->SendQuery(query); +} \ No newline at end of file diff --git a/zone/zone.h b/zone/zone.h index 7b1b855a7..8c4008df0 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -69,6 +69,14 @@ struct item_tick_struct { std::string qglobal; }; +enum EventLogTypes +{ + EventLogItemSummon = 0, + EventLogItemBuy = 1, + EventLogQuest = 500, + EventLogMax +}; + class Client; class Map; class Mob; @@ -227,11 +235,6 @@ public: uint8 weather_intensity; uint8 zone_weather; - uint8 loglevelvar; - uint8 merchantvar; - uint8 tradevar; - uint8 lootvar; - bool HasGraveyard(); void SetGraveyard(uint32 zoneid, const glm::vec4& graveyardPosition); @@ -282,6 +285,8 @@ public: } } + void LogEvent(EventLogTypes type, Client *c, const std::string &desc); + //MODDING HOOKS void mod_init(); void mod_repop(); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 08a3dd38a..a6285294b 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -311,33 +311,6 @@ void ZoneDatabase::UpdateSpawn2Status(uint32 id, uint8 new_status) QueryDatabase(query); } -bool ZoneDatabase::logevents(const char* accountname,uint32 accountid,uint8 status,const char* charname, const char* target,const char* descriptiontype, const char* description,int event_nid){ - - uint32 len = strlen(description); - uint32 len2 = strlen(target); - char* descriptiontext = new char[2*len+1]; - char* targetarr = new char[2*len2+1]; - memset(descriptiontext, 0, 2*len+1); - memset(targetarr, 0, 2*len2+1); - DoEscapeString(descriptiontext, description, len); - DoEscapeString(targetarr, target, len2); - - std::string query = StringFormat("INSERT INTO eventlog (accountname, accountid, status, " - "charname, target, descriptiontype, description, event_nid) " - "VALUES('%s', %i, %i, '%s', '%s', '%s', '%s', '%i')", - accountname, accountid, status, charname, targetarr, - descriptiontype, descriptiontext, event_nid); - safe_delete_array(descriptiontext); - safe_delete_array(targetarr); - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } - - return true; -} - - void ZoneDatabase::UpdateBug(BugStruct* bug) { uint32 len = strlen(bug->bug); @@ -495,7 +468,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, ItemInst* container) aug[4] = (uint32)atoi(row[7]); aug[5] = (uint32)atoi(row[8]); - ItemInst* inst = database.CreateItem(item_id, charges); + ItemInst* inst = database.CreateItemOld(item_id, charges); if (inst && inst->GetItem()->ItemClass == ItemClassCommon) { for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) if (aug[i]) @@ -629,7 +602,7 @@ ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { int Charges = atoi(row[3]); int Cost = atoi(row[4]); - const Item_Struct *item = database.GetItem(ItemID); + const ItemData *item = database.GetItem(ItemID); if(!item) { Log.Out(Logs::Detail, Logs::Trading, "Unable to create item\n"); @@ -640,7 +613,7 @@ ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { if (item->NoDrop == 0) return nullptr; - ItemInst* inst = database.CreateItem(item); + ItemInst* inst = database.CreateItemOld(item); if(!inst) { Log.Out(Logs::Detail, Logs::Trading, "Unable to create item instance\n"); fflush(stdout); @@ -684,7 +657,7 @@ void ZoneDatabase::UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charg Log.Out(Logs::Detail, Logs::Trading, "ZoneDatabase::UpdateTraderPrice(%i, %i, %i, %i)", CharID, ItemID, Charges, NewPrice); - const Item_Struct *item = database.GetItem(ItemID); + const ItemData *item = database.GetItem(ItemID); if(!item) return; @@ -1194,7 +1167,7 @@ bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Str i = atoi(row[r]); /* Bandolier ID */ r++; si = atoi(row[r]); /* Bandolier Slot */ r++; - const Item_Struct* item_data = database.GetItem(atoi(row[r])); + const ItemData* item_data = database.GetItem(atoi(row[r])); if (item_data) { pp->bandoliers[i].Items[si].ID = item_data->ID; r++; pp->bandoliers[i].Items[si].Icon = atoi(row[r]); r++; // Must use db value in case an Ornamentation is assigned @@ -1246,9 +1219,10 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); - const Item_Struct *item_data = database.GetItem(atoi(row[1])); + const ItemData *item_data = database.GetItem(atoi(row[1])); if (!item_data) continue; + pp->potionbelt.Items[i].ID = item_data->ID; pp->potionbelt.Items[i].Icon = atoi(row[2]); strncpy(pp->potionbelt.Items[i].Name, item_data->Name, 64); diff --git a/zone/zonedb.h b/zone/zonedb.h index 1fb4d3b29..a3b8c9ae9 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -488,7 +488,6 @@ public: * PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD * REALLY HAS NO BETTER SECTION */ - bool logevents(const char* accountname,uint32 accountid,uint8 status,const char* charname,const char* target, const char* descriptiontype, const char* description,int event_nid); void GetEventLogs(const char* name,char* target,uint32 account_id=0,uint8 eventid=0,char* detail=0,char* timestamp=0, CharacterEventLog_Struct* cel=0); uint32 GetKarma(uint32 acct_id); void UpdateKarma(uint32 acct_id, uint32 amount); diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 5b60448ec..f8ec4d2c2 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -335,12 +335,6 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc SendLogoutPackets(); - /* QS: PlayerLogZone */ - if (RuleB(QueryServ, PlayerLogZone)){ - std::string event_desc = StringFormat("Zoning :: zoneid:%u instid:%u x:%4.2f y:%4.2f z:%4.2f h:%4.2f zonemode:%d from zoneid:%u instid:%i", zone_id, instance_id, dest_x, dest_y, dest_z, dest_h, zone_mode, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Zoning, this->CharacterID(), event_desc); - } - /* Dont clear aggro until the zone is successful */ entity_list.RemoveFromHateLists(this);