From 5a6314e1a9612ee10d2e26068c16e4635708e681 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 22 Mar 2023 23:16:52 -0700 Subject: [PATCH] [Fix] Fixes for corpses not properly saving some item instance data correctly. (#3123) * Convert ZoneDb::LoadCharacterCorpseData to use a cleaner api that has a better layout. * Update corpse save methods to use a new cleaner api. * Add item to corpse will use a few new fields that don't yet save. * Fix for some issues moving data to corpses. * Make CreateItem more explicit to avoid overlooking places it's used and add more arguments. * DB changes * Revert of the changes to the database.CreateItem api change. * Missed one. * Fixes for mr Krab * Small formatting --------- Co-authored-by: KimLS Co-authored-by: Akkadius --- common/eq_packet_structs.h | 6 +- common/inventory_profile.h | 12 +- common/item_instance.cpp | 25 +- common/item_instance.h | 13 +- common/shareddb.cpp | 88 ++---- common/shareddb.h | 12 +- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../git/required/2023_03_17_corpse_fields.sql | 5 + world/worlddb.cpp | 23 +- zone/bot_database.cpp | 23 +- zone/client.cpp | 6 +- zone/corpse.cpp | 272 +++++++++++------- zone/corpse.h | 15 +- zone/inventory.cpp | 18 +- zone/lua_iteminst.cpp | 24 +- zone/lua_iteminst.h | 12 +- zone/questmgr.cpp | 12 +- zone/zonedb.cpp | 268 +++++++++-------- zone/zonedb.h | 56 +++- zone/zonedump.h | 50 ---- 21 files changed, 491 insertions(+), 452 deletions(-) create mode 100644 utils/sql/git/required/2023_03_17_corpse_fields.sql diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index cd26fe79a..8d1b3f13e 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -5522,7 +5522,11 @@ struct ServerLootItem_Struct { uint32 aug_4; // uint32 aug_4; uint32 aug_5; // uint32 aug_5; uint32 aug_6; // uint32 aug_5; - uint8 attuned; + bool attuned; + std::string custom_data; + uint32 ornamenticon; + uint32 ornamentidfile; + uint32 ornament_hero_model; uint16 trivial_min_level; uint16 trivial_max_level; uint16 npc_min_level; diff --git a/common/inventory_profile.h b/common/inventory_profile.h index 43f4a88f4..c1a82e407 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -203,12 +203,12 @@ namespace EQ void dumpBankItems(); void dumpSharedBankItems(); - void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value); - void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value); - void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value); - void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value); - std::string GetCustomItemData(int16 slot_id, std::string identifier); - static const int GetItemStatValue(uint32 item_id, std::string identifier); + void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, const std::string& value); + void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, int value); + void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, float value); + void SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, bool value); + std::string GetCustomItemData(int16 slot_id, const std::string& identifier); + static const int GetItemStatValue(uint32 item_id, const std::string& identifier); protected: /////////////////////////////// // Protected Methods diff --git a/common/item_instance.cpp b/common/item_instance.cpp index eb025ee98..696a34b6f 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -840,7 +840,20 @@ std::string EQ::ItemInstance::GetCustomDataString() const { return ret_val; } -std::string EQ::ItemInstance::GetCustomData(std::string identifier) { +void EQ::ItemInstance::SetCustomDataString(const std::string& str) +{ + auto components = Strings::Split(str, "^"); + auto value_count = components.size() / 2; + + for (auto i = 0; i < value_count; i++) { + auto identifier = components[i * 2]; + auto value = components[(i * 2) + 1]; + + SetCustomData(identifier, value); + } +} + +std::string EQ::ItemInstance::GetCustomData(const std::string& identifier) { std::map::const_iterator iter = m_custom_data.find(identifier); if (iter != m_custom_data.end()) { return iter->second; @@ -849,33 +862,33 @@ std::string EQ::ItemInstance::GetCustomData(std::string identifier) { return ""; } -void EQ::ItemInstance::SetCustomData(std::string identifier, std::string value) { +void EQ::ItemInstance::SetCustomData(const std::string& identifier, const std::string& value) { DeleteCustomData(identifier); m_custom_data[identifier] = value; } -void EQ::ItemInstance::SetCustomData(std::string identifier, int value) { +void EQ::ItemInstance::SetCustomData(const std::string& identifier, int value) { DeleteCustomData(identifier); std::stringstream ss; ss << value; m_custom_data[identifier] = ss.str(); } -void EQ::ItemInstance::SetCustomData(std::string identifier, float value) { +void EQ::ItemInstance::SetCustomData(const std::string& identifier, float value) { DeleteCustomData(identifier); std::stringstream ss; ss << value; m_custom_data[identifier] = ss.str(); } -void EQ::ItemInstance::SetCustomData(std::string identifier, bool value) { +void EQ::ItemInstance::SetCustomData(const std::string& identifier, bool value) { DeleteCustomData(identifier); std::stringstream ss; ss << value; m_custom_data[identifier] = ss.str(); } -void EQ::ItemInstance::DeleteCustomData(std::string identifier) { +void EQ::ItemInstance::DeleteCustomData(const std::string& identifier) { auto iter = m_custom_data.find(identifier); if (iter != m_custom_data.end()) { m_custom_data.erase(iter); diff --git a/common/item_instance.h b/common/item_instance.h index 89620d0b5..d1a8e021e 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -175,12 +175,13 @@ namespace EQ void SetAttuned(bool flag) { m_attuned = flag; } std::string GetCustomDataString() const; - std::string GetCustomData(std::string identifier); - void SetCustomData(std::string identifier, std::string value); - void SetCustomData(std::string identifier, int value); - void SetCustomData(std::string identifier, float value); - void SetCustomData(std::string identifier, bool value); - void DeleteCustomData(std::string identifier); + std::string GetCustomData(const std::string &identifier); + void SetCustomDataString(const std::string& str); + void SetCustomData(const std::string &identifier, const std::string& value); + void SetCustomData(const std::string &identifier, int value); + void SetCustomData(const std::string &identifier, float value); + void SetCustomData(const std::string &identifier, bool value); + void DeleteCustomData(const std::string& identifier); // Allows treatment of this object as though it were a pointer to m_item operator bool() const { return (m_item != nullptr); } diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 08c82fb1e..b37cb8127 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -548,27 +548,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, EQ::InventoryProfile *inv, bool is if (inst && row[9]) { std::string data_str(row[9]); - 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; - } - - const char v = data_str[i]; - if (use_id) - idAsString.push_back(v); - else - value.push_back(v); - } + inst->SetCustomDataString(data_str); } // theoretically inst can be nullptr ... this would be very bad ... @@ -679,28 +659,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQ::InventoryProfile *inv) 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; - } - - const char v = data_str[i]; - if (use_id) - idAsString.push_back(v); - else - value.push_back(v); - } + inst->SetCustomDataString(data_str); } inst->SetOrnamentIcon(ornament_icon); @@ -825,28 +784,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQ::InventoryPr 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; - } - - const char v = data_str[i]; - if (use_id) - idAsString.push_back(v); - else - value.push_back(v); - } + inst->SetCustomDataString(data_str); } inst->SetOrnamentIcon(ornament_icon); @@ -1544,7 +1482,11 @@ EQ::ItemInstance* SharedDatabase::CreateItem( uint32 aug4, uint32 aug5, uint32 aug6, - bool attuned + bool attuned, + const std::string& custom_data, + uint32 ornamenticon, + uint32 ornamentidfile, + uint32 ornament_hero_model ) { EQ::ItemInstance* inst = nullptr; @@ -1565,6 +1507,10 @@ EQ::ItemInstance* SharedDatabase::CreateItem( inst->PutAugment(this, 4, aug5); inst->PutAugment(this, 5, aug6); inst->SetAttuned(attuned); + inst->SetCustomDataString(custom_data); + inst->SetOrnamentIcon(ornamenticon); + inst->SetOrnamentationIDFile(ornamentidfile); + inst->SetOrnamentHeroModel(ornament_hero_model); } return inst; @@ -1581,7 +1527,11 @@ EQ::ItemInstance* SharedDatabase::CreateItem( uint32 aug4, uint32 aug5, uint32 aug6, - bool attuned + bool attuned, + const std::string& custom_data, + uint32 ornamenticon, + uint32 ornamentidfile, + uint32 ornament_hero_model ) { EQ::ItemInstance* inst = nullptr; if (item) { @@ -1600,6 +1550,10 @@ EQ::ItemInstance* SharedDatabase::CreateItem( inst->PutAugment(this, 4, aug5); inst->PutAugment(this, 5, aug6); inst->SetAttuned(attuned); + inst->SetCustomDataString(custom_data); + inst->SetOrnamentIcon(ornamenticon); + inst->SetOrnamentationIDFile(ornamentidfile); + inst->SetOrnamentHeroModel(ornament_hero_model); } return inst; diff --git a/common/shareddb.h b/common/shareddb.h index fc5f89932..7139b17fd 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -126,7 +126,11 @@ public: uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, - bool attuned = 0 + bool attuned = false, + const std::string& custom_data = "", + uint32 ornamenticon = 0, + uint32 ornamentidfile = 0, + uint32 ornament_hero_model = 0 ); EQ::ItemInstance *CreateItem( const EQ::ItemData *item, @@ -137,7 +141,11 @@ public: uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, - bool attuned = 0 + bool attuned = false, + const std::string &custom_data = "", + uint32 ornamenticon = 0, + uint32 ornamentidfile = 0, + uint32 ornament_hero_model = 0 ); EQ::ItemInstance *CreateBaseItem(const EQ::ItemData *item, int16 charges = 0); diff --git a/common/version.h b/common/version.h index 3941cce9d..6f6179db5 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9225 +#define CURRENT_BINARY_DATABASE_VERSION 9226 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9038 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 14f6b208e..c7aaab906 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -479,6 +479,7 @@ 9223|2023_03_04_npc_scale_global_base_heroic_strikethrough.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'heroic_strikethrough'|empty| 9224|2023_03_08_npc_scale_global_base_avoidance.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'hp_regen_per_second'|empty| 9225|2023_01_21_bots_raid_members.sql|SHOW COLUMNS FROM `raid_members` LIKE 'bot_id'|empty| +9226|2023_03_17_corpse_fields.sql|SHOW COLUMNS FROM `character_corpse_items` LIKE 'custom_data'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2023_03_17_corpse_fields.sql b/utils/sql/git/required/2023_03_17_corpse_fields.sql new file mode 100644 index 000000000..0552deb9b --- /dev/null +++ b/utils/sql/git/required/2023_03_17_corpse_fields.sql @@ -0,0 +1,5 @@ +ALTER TABLE `character_corpse_items` + ADD COLUMN `custom_data` TEXT NULL AFTER `attuned`, + ADD COLUMN `ornamenticon` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `custom_data`, + ADD COLUMN `ornamentidfile` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `ornamenticon`, + ADD COLUMN `ornament_hero_model` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `ornamentidfile`; diff --git a/world/worlddb.cpp b/world/worlddb.cpp index a6186907e..dcf03bc5b 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -946,28 +946,7 @@ bool WorldDatabase::GetCharSelInventory(uint32 account_id, char *name, EQ::Inven 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->SetCustomDataString(data_str); } inst->SetOrnamentIcon(ornament_icon); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index a12e4e6dd..6057ce8aa 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -1101,28 +1101,7 @@ bool BotDatabase::LoadItems(const uint32 bot_id, EQ::InventoryProfile& inventory if (row[5]) { std::string data_str(row[5]); - 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) { - item_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); - } + item_inst->SetCustomDataString(data_str); } item_inst->SetOrnamentIcon((uint32)Strings::ToUnsignedInt(row[6])); diff --git a/zone/client.cpp b/zone/client.cpp index 36d1334b5..5781fce25 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -11050,7 +11050,11 @@ void Client::SummonBaggedItems(uint32 bag_item_id, const std::vectoritemcount; i++) { - tmp = new ServerLootItem_Struct; - memcpy(tmp, &pcs->items[i], sizeof(player_lootitem::ServerLootItem_Struct)); + for (auto &item: ce.items) { + auto tmp = new ServerLootItem_Struct; + + tmp->equip_slot = item.equip_slot; + tmp->item_id = item.item_id; + tmp->charges = item.charges; + tmp->lootslot = item.lootslot; + tmp->aug_1 = item.aug_1; + tmp->aug_2 = item.aug_2; + tmp->aug_3 = item.aug_3; + tmp->aug_4 = item.aug_4; + tmp->aug_5 = item.aug_5; + tmp->aug_6 = item.aug_6; + tmp->attuned = item.attuned; + itemlist.push_back(tmp); } /* Create Corpse Entity */ - auto pc = new Corpse(in_dbid, // uint32 in_dbid - in_charid, // uint32 in_charid - in_charname.c_str(), // char* in_charname - &itemlist, // ItemList* in_itemlist - pcs->copper, // uint32 in_copper - pcs->silver, // uint32 in_silver - pcs->gold, // uint32 in_gold - pcs->plat, // uint32 in_plat - position, - pcs->size, // float in_size - pcs->gender, // uint8 in_gender - pcs->race, // uint16 in_race - pcs->class_, // uint8 in_class - pcs->deity, // uint8 in_deity - pcs->level, // uint8 in_level - pcs->texture, // uint8 in_texture - pcs->helmtexture, // uint8 in_helmtexture - pcs->exp, // uint32 in_rezexp - was_at_graveyard // bool wasAtGraveyard - ); + auto pc = new Corpse( + in_dbid, // uint32 in_dbid + in_charid, // uint32 in_charid + in_charname.c_str(), // char* in_charname + &itemlist, // ItemList* in_itemlist + ce.copper, // uint32 in_copper + ce.silver, // uint32 in_silver + ce.gold, // uint32 in_gold + ce.plat, // uint32 in_plat + position, + ce.size, // float in_size + ce.gender, // uint8 in_gender + ce.race, // uint16 in_race + ce.class_, // uint8 in_class + ce.deity, // uint8 in_deity + ce.level, // uint8 in_level + ce.texture, // uint8 in_texture + ce.helmtexture, // uint8 in_helmtexture + ce.exp, // uint32 in_rezexp + was_at_graveyard // bool wasAtGraveyard + ); - if (pcs->locked) + if (ce.locked) pc->Lock(); /* Load Item Tints */ - pc->item_tint.Head.Color = pcs->item_tint.Head.Color; - pc->item_tint.Chest.Color = pcs->item_tint.Chest.Color; - pc->item_tint.Arms.Color = pcs->item_tint.Arms.Color; - pc->item_tint.Wrist.Color = pcs->item_tint.Wrist.Color; - pc->item_tint.Hands.Color = pcs->item_tint.Hands.Color; - pc->item_tint.Legs.Color = pcs->item_tint.Legs.Color; - pc->item_tint.Feet.Color = pcs->item_tint.Feet.Color; - pc->item_tint.Primary.Color = pcs->item_tint.Primary.Color; - pc->item_tint.Secondary.Color = pcs->item_tint.Secondary.Color; + pc->item_tint.Head.Color = ce.item_tint.Head.Color; + pc->item_tint.Chest.Color = ce.item_tint.Chest.Color; + pc->item_tint.Arms.Color = ce.item_tint.Arms.Color; + pc->item_tint.Wrist.Color = ce.item_tint.Wrist.Color; + pc->item_tint.Hands.Color = ce.item_tint.Hands.Color; + pc->item_tint.Legs.Color = ce.item_tint.Legs.Color; + pc->item_tint.Feet.Color = ce.item_tint.Feet.Color; + pc->item_tint.Primary.Color = ce.item_tint.Primary.Color; + pc->item_tint.Secondary.Color = ce.item_tint.Secondary.Color; /* Load Physical Appearance */ - pc->haircolor = pcs->haircolor; - pc->beardcolor = pcs->beardcolor; - pc->eyecolor1 = pcs->eyecolor1; - pc->eyecolor2 = pcs->eyecolor2; - pc->hairstyle = pcs->hairstyle; - pc->luclinface = pcs->face; - pc->beard = pcs->beard; - pc->drakkin_heritage = pcs->drakkin_heritage; - pc->drakkin_tattoo = pcs->drakkin_tattoo; - pc->drakkin_details = pcs->drakkin_details; + pc->haircolor = ce.haircolor; + pc->beardcolor = ce.beardcolor; + pc->eyecolor1 = ce.eyecolor1; + pc->eyecolor2 = ce.eyecolor2; + pc->hairstyle = ce.hairstyle; + pc->luclinface = ce.face; + pc->beard = ce.beard; + pc->drakkin_heritage = ce.drakkin_heritage; + pc->drakkin_tattoo = ce.drakkin_tattoo; + pc->drakkin_details = ce.drakkin_details; pc->IsRezzed(rezzed); - pc->become_npc = false; + pc->become_npc = false; pc->consented_guild_id = guild_consent_id; pc->UpdateEquipmentLight(); // itemlist populated above..need to determine actual values - safe_delete_array(pcs); - return pc; } @@ -509,8 +518,13 @@ void Corpse::MoveItemToCorpse(Client *client, EQ::ItemInstance *inst, int16 equi inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), - inst->IsAttuned() - ); + inst->IsAttuned(), + inst->GetCustomDataString(), + inst->GetOrnamentationIcon(), + inst->GetOrnamentationIDFile(), + inst->GetOrnamentHeroModel() + ); + removedList.push_back(equipSlot); while (true) { @@ -532,8 +546,13 @@ void Corpse::MoveItemToCorpse(Client *client, EQ::ItemInstance *inst, int16 equi bag_inst->GetAugmentItemID(3), bag_inst->GetAugmentItemID(4), bag_inst->GetAugmentItemID(5), - bag_inst->IsAttuned() - ); + bag_inst->IsAttuned(), + bag_inst->GetCustomDataString(), + bag_inst->GetOrnamentationIcon(), + bag_inst->GetOrnamentationIDFile(), + bag_inst->GetOrnamentHeroModel() + ); + removedList.push_back(real_bag_slot); client->DeleteItemInInventory(real_bag_slot, 0, true, false); } @@ -677,63 +696,72 @@ void Corpse::CalcCorpseName() { } bool Corpse::Save() { - if (!is_player_corpse) + if (!is_player_corpse) { return true; - if (!is_corpse_changed) + } + + if (!is_corpse_changed) { return true; + } - uint32 tmp = CountItems(); - uint32 tmpsize = sizeof(PlayerCorpse_Struct) + (tmp * sizeof(player_lootitem::ServerLootItem_Struct)); + CharacterCorpseEntry ce; - PlayerCorpse_Struct* dbpc = (PlayerCorpse_Struct*) new uchar[tmpsize]; - memset(dbpc, 0, tmpsize); - dbpc->itemcount = tmp; - dbpc->size = size; - dbpc->locked = is_locked; - dbpc->copper = copper; - dbpc->silver = silver; - dbpc->gold = gold; - dbpc->plat = platinum; - dbpc->race = race; - dbpc->class_ = class_; - dbpc->gender = gender; - dbpc->deity = deity; - dbpc->level = level; - dbpc->texture = texture; - dbpc->helmtexture = helmtexture; - dbpc->exp = rez_experience; + ce.size = size; + ce.locked = is_locked; + ce.copper = copper; + ce.silver = silver; + ce.gold = gold; + ce.plat = platinum; + ce.race = race; + ce.class_ = class_; + ce.gender = gender; + ce.deity = deity; + ce.level = level; + ce.texture = texture; + ce.helmtexture = helmtexture; + ce.exp = rez_experience; + ce.item_tint = item_tint; + ce.haircolor = haircolor; + ce.beardcolor = beardcolor; + ce.eyecolor2 = eyecolor1; + ce.hairstyle = hairstyle; + ce.face = luclinface; + ce.beard = beard; + ce.drakkin_heritage = drakkin_heritage; + ce.drakkin_tattoo = drakkin_tattoo; + ce.drakkin_details = drakkin_details; - memcpy(&dbpc->item_tint.Slot, &item_tint.Slot, sizeof(dbpc->item_tint)); - dbpc->haircolor = haircolor; - dbpc->beardcolor = beardcolor; - dbpc->eyecolor2 = eyecolor1; - dbpc->hairstyle = hairstyle; - dbpc->face = luclinface; - dbpc->beard = beard; - dbpc->drakkin_heritage = drakkin_heritage; - dbpc->drakkin_tattoo = drakkin_tattoo; - dbpc->drakkin_details = drakkin_details; + for (auto &item: itemlist) { + CharacterCorpseItemEntry e; - uint32 x = 0; - ItemList::iterator cur, end; - cur = itemlist.begin(); - end = itemlist.end(); - for (; cur != end; ++cur) { - ServerLootItem_Struct* item = *cur; - memcpy((char*)&dbpc->items[x++], (char*)item, sizeof(player_lootitem::ServerLootItem_Struct)); + e.item_id = item->item_id; + e.equip_slot = item->equip_slot; + e.charges = item->charges; + e.lootslot = item->lootslot; + e.aug_1 = item->aug_1; + e.aug_2 = item->aug_2; + e.aug_3 = item->aug_3; + e.aug_4 = item->aug_4; + e.aug_5 = item->aug_5; + e.aug_6 = item->aug_6; + e.attuned = item->attuned; + e.custom_data = item->custom_data; + e.ornamenticon = item->ornamenticon; + e.ornamentidfile = item->ornamentidfile; + e.ornament_hero_model = item->ornament_hero_model; + + ce.items.push_back(std::move(e)); } /* Create New Corpse*/ if (corpse_db_id == 0) { - corpse_db_id = database.SaveCharacterCorpse(char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position, consented_guild_id); + corpse_db_id = database.SaveCharacterCorpse(char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), ce, m_Position, consented_guild_id); } /* Update Corpse Data */ else{ - corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), dbpc, m_Position, consented_guild_id, IsRezzed()); + corpse_db_id = database.UpdateCharacterCorpse(corpse_db_id, char_id, corpse_name, zone->GetZoneID(), zone->GetInstanceID(), ce, m_Position, consented_guild_id, IsRezzed()); } - safe_delete_array(dbpc); - return true; } @@ -784,7 +812,21 @@ uint32 Corpse::CountItems() { return itemlist.size(); } -void Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) { +void Corpse::AddItem(uint32 itemnum, + uint16 charges, + int16 slot, + uint32 aug1, + uint32 aug2, + uint32 aug3, + uint32 aug4, + uint32 aug5, + uint32 aug6, + bool attuned, + const std::string& custom_data, + uint32 ornamenticon, + uint32 ornamentidfile, + uint32 ornament_hero_model) { + if (!database.GetItem(itemnum)) return; @@ -792,17 +834,21 @@ void Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, ui auto item = new ServerLootItem_Struct; - memset(item, 0, sizeof(ServerLootItem_Struct)); item->item_id = itemnum; item->charges = charges; item->equip_slot = slot; - item->aug_1=aug1; - item->aug_2=aug2; - item->aug_3=aug3; - item->aug_4=aug4; - item->aug_5=aug5; - item->aug_6=aug6; - item->attuned=attuned; + item->aug_1 = aug1; + item->aug_2 = aug2; + item->aug_3 = aug3; + item->aug_4 = aug4; + item->aug_5 = aug5; + item->aug_6 = aug6; + item->attuned = attuned; + item->custom_data = custom_data; + item->ornamenticon = ornamenticon; + item->ornamentidfile = ornamentidfile; + item->ornament_hero_model = ornament_hero_model; + itemlist.push_back(item); UpdateEquipmentLight(); @@ -1291,7 +1337,11 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a item_data->aug_4, item_data->aug_5, item_data->aug_6, - item_data->attuned + item_data->attuned, + item_data->custom_data, + item_data->ornamenticon, + item_data->ornamentidfile, + item_data->ornament_hero_model ); if (!inst) continue; @@ -1418,7 +1468,9 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) 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); + item_data->aug_5, item_data->aug_6, item_data->attuned, + item_data->custom_data, item_data->ornamenticon, + item_data->ornamentidfile, item_data->ornament_hero_model); } else { inst = database.CreateItem(item); diff --git a/zone/corpse.h b/zone/corpse.h index ac76f9b85..c9f7b4652 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -100,7 +100,20 @@ class Corpse : public Mob { void RemoveItem(uint16 lootslot); void RemoveItem(ServerLootItem_Struct* item_data); void RemoveItemByID(uint32 item_id, int quantity = 1); - void AddItem(uint32 itemnum, uint16 charges, int16 slot = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); + void AddItem(uint32 itemnum, + uint16 charges, + int16 slot = 0, + uint32 aug1 = 0, + uint32 aug2 = 0, + uint32 aug3 = 0, + uint32 aug4 = 0, + uint32 aug5 = 0, + uint32 aug6 = 0, + bool attuned = false, + const std::string &custom_data = std::string(), + uint32 ornamenticon = 0, + uint32 ornamentidfile = 0, + uint32 ornament_hero_model = 0); /* Corpse: Coin */ void SetCash(uint32 in_copper, uint32 in_silver, uint32 in_gold, uint32 in_platinum); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 6f8854b3f..f71b34fce 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1387,7 +1387,11 @@ void Client::PutLootInInventory(int16 slot_id, const EQ::ItemInstance &inst, Ser bag_item_data[index]->aug_4, bag_item_data[index]->aug_5, bag_item_data[index]->aug_6, - bag_item_data[index]->attuned + bag_item_data[index]->attuned, + bag_item_data[index]->custom_data, + bag_item_data[index]->ornamenticon, + bag_item_data[index]->ornamentidfile, + bag_item_data[index]->ornament_hero_model ); // Dump bag contents to cursor in the event that owning bag is not the first cursor item @@ -3958,7 +3962,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const EQ::ItemI return false; } -void EQ::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value) { +void EQ::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, const std::string &value) { EQ::ItemInstance *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); @@ -3966,7 +3970,7 @@ void EQ::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, } } -void EQ::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value) { +void EQ::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, int value) { EQ::ItemInstance *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); @@ -3974,7 +3978,7 @@ void EQ::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, } } -void EQ::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value) { +void EQ::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, float value) { EQ::ItemInstance *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); @@ -3982,7 +3986,7 @@ void EQ::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, } } -void EQ::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value) { +void EQ::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, const std::string &identifier, bool value) { EQ::ItemInstance *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); @@ -3990,7 +3994,7 @@ void EQ::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, } } -std::string EQ::InventoryProfile::GetCustomItemData(int16 slot_id, std::string identifier) { +std::string EQ::InventoryProfile::GetCustomItemData(int16 slot_id, const std::string &identifier) { EQ::ItemInstance *inst = GetItem(slot_id); if(inst) { return inst->GetCustomData(identifier); @@ -3998,7 +4002,7 @@ std::string EQ::InventoryProfile::GetCustomItemData(int16 slot_id, std::string i return ""; } -const int EQ::InventoryProfile::GetItemStatValue(uint32 item_id, std::string identifier) { +const int EQ::InventoryProfile::GetItemStatValue(uint32 item_id, const std::string &identifier) { if (identifier.empty()) { return 0; } diff --git a/zone/lua_iteminst.cpp b/zone/lua_iteminst.cpp index 54f7deef4..180856f66 100644 --- a/zone/lua_iteminst.cpp +++ b/zone/lua_iteminst.cpp @@ -179,32 +179,32 @@ std::string Lua_ItemInst::GetCustomDataString() { return self->GetCustomDataString(); } -void Lua_ItemInst::SetCustomData(std::string identifier, std::string value) { +void Lua_ItemInst::SetCustomData(const std::string &identifier, const std::string& value) { Lua_Safe_Call_Void(); self->SetCustomData(identifier, value); } -void Lua_ItemInst::SetCustomData(std::string identifier, int value) { +void Lua_ItemInst::SetCustomData(const std::string& identifier, int value) { Lua_Safe_Call_Void(); self->SetCustomData(identifier, value); } -void Lua_ItemInst::SetCustomData(std::string identifier, float value) { +void Lua_ItemInst::SetCustomData(const std::string& identifier, float value) { Lua_Safe_Call_Void(); self->SetCustomData(identifier, value); } -void Lua_ItemInst::SetCustomData(std::string identifier, bool value) { +void Lua_ItemInst::SetCustomData(const std::string& identifier, bool value) { Lua_Safe_Call_Void(); self->SetCustomData(identifier, value); } -std::string Lua_ItemInst::GetCustomData(std::string identifier) { +std::string Lua_ItemInst::GetCustomData(const std::string& identifier) { Lua_Safe_Call_String(); return self->GetCustomData(identifier); } -void Lua_ItemInst::DeleteCustomData(std::string identifier) { +void Lua_ItemInst::DeleteCustomData(const std::string& identifier) { Lua_Safe_Call_Void(); self->DeleteCustomData(identifier); } @@ -296,13 +296,13 @@ luabind::scope lua_register_iteminst() { .def("Clone", (Lua_ItemInst(Lua_ItemInst::*)(void))&Lua_ItemInst::Clone) .def("ContainsAugmentByID", (bool(Lua_ItemInst::*)(uint32))&Lua_ItemInst::ContainsAugmentByID) .def("CountAugmentByID", (int(Lua_ItemInst::*)(uint32))&Lua_ItemInst::CountAugmentByID) - .def("DeleteCustomData", (void(Lua_ItemInst::*)(std::string))&Lua_ItemInst::DeleteCustomData) + .def("DeleteCustomData", (void(Lua_ItemInst::*)(const std::string &))&Lua_ItemInst::DeleteCustomData) .def("GetAugment", (Lua_ItemInst(Lua_ItemInst::*)(int))&Lua_ItemInst::GetAugment) .def("GetAugmentItemID", (uint32(Lua_ItemInst::*)(int))&Lua_ItemInst::GetAugmentItemID) .def("GetAugmentType", (int(Lua_ItemInst::*)(void))&Lua_ItemInst::GetAugmentType) .def("GetCharges", (int(Lua_ItemInst::*)(void))&Lua_ItemInst::GetCharges) .def("GetColor", (uint32(Lua_ItemInst::*)(void))&Lua_ItemInst::GetColor) - .def("GetCustomData", (std::string(Lua_ItemInst::*)(std::string))&Lua_ItemInst::GetCustomData) + .def("GetCustomData", (std::string(Lua_ItemInst::*)(const std::string &))&Lua_ItemInst::GetCustomData) .def("GetCustomDataString", (std::string(Lua_ItemInst::*)(void))&Lua_ItemInst::GetCustomDataString) .def("GetExp", (uint32(Lua_ItemInst::*)(void))&Lua_ItemInst::GetExp) .def("GetID", (uint32(Lua_ItemInst::*)(void))&Lua_ItemInst::GetID) @@ -329,10 +329,10 @@ luabind::scope lua_register_iteminst() { .def("RemoveTaskDeliveredItems", &Lua_ItemInst::RemoveTaskDeliveredItems) .def("SetCharges", (void(Lua_ItemInst::*)(int))&Lua_ItemInst::SetCharges) .def("SetColor", (void(Lua_ItemInst::*)(uint32))&Lua_ItemInst::SetColor) - .def("SetCustomData", (void(Lua_ItemInst::*)(std::string,bool))&Lua_ItemInst::SetCustomData) - .def("SetCustomData", (void(Lua_ItemInst::*)(std::string,float))&Lua_ItemInst::SetCustomData) - .def("SetCustomData", (void(Lua_ItemInst::*)(std::string,int))&Lua_ItemInst::SetCustomData) - .def("SetCustomData", (void(Lua_ItemInst::*)(std::string,std::string))&Lua_ItemInst::SetCustomData) + .def("SetCustomData", (void(Lua_ItemInst::*)(const std::string&,bool))&Lua_ItemInst::SetCustomData) + .def("SetCustomData", (void(Lua_ItemInst::*)(const std::string&,float))&Lua_ItemInst::SetCustomData) + .def("SetCustomData", (void(Lua_ItemInst::*)(const std::string&,int))&Lua_ItemInst::SetCustomData) + .def("SetCustomData", (void(Lua_ItemInst::*)(const std::string&,const std::string&))&Lua_ItemInst::SetCustomData) .def("SetExp", (void(Lua_ItemInst::*)(uint32))&Lua_ItemInst::SetExp) .def("SetInstNoDrop", (void(Lua_ItemInst::*)(bool))&Lua_ItemInst::SetInstNoDrop) .def("SetPrice", (void(Lua_ItemInst::*)(uint32))&Lua_ItemInst::SetPrice) diff --git a/zone/lua_iteminst.h b/zone/lua_iteminst.h index 04138dafd..ea8e98e37 100644 --- a/zone/lua_iteminst.h +++ b/zone/lua_iteminst.h @@ -63,12 +63,12 @@ public: bool IsInstNoDrop(); void SetInstNoDrop(bool flag); std::string GetCustomDataString(); - void SetCustomData(std::string identifier, std::string value); - void SetCustomData(std::string identifier, int value); - void SetCustomData(std::string identifier, float value); - void SetCustomData(std::string identifier, bool value); - std::string GetCustomData(std::string identifier); - void DeleteCustomData(std::string identifier); + void SetCustomData(const std::string &identifier, const std::string &value); + void SetCustomData(const std::string &identifier, int value); + void SetCustomData(const std::string &identifier, float value); + void SetCustomData(const std::string &identifier, bool value); + std::string GetCustomData(const std::string& identifier); + void DeleteCustomData(const std::string& identifier); void SetScaling(bool v); void SetScale(double scale_factor); uint32 GetExp(); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 7c2898c7c..027df7e0b 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -3606,7 +3606,17 @@ void QuestManager::UpdateZoneHeader(std::string type, std::string value) { EQ::ItemInstance *QuestManager::CreateItem(uint32 item_id, int16 charges, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five, uint32 augment_six, bool attuned) const { if (database.GetItem(item_id)) { - return database.CreateItem(item_id, charges, augment_one, augment_two, augment_three, augment_four, augment_five, augment_six, attuned); + return database.CreateItem( + item_id, + charges, + augment_one, + augment_two, + augment_three, + augment_four, + augment_five, + augment_six, + attuned + ); } return nullptr; } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 734b70677..62e984f4d 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3780,7 +3780,7 @@ uint32 ZoneDatabase::GetCharacterCorpseDecayTimer(uint32 corpse_db_id){ return 0; } -uint32 ZoneDatabase::UpdateCharacterCorpse(uint32 db_id, uint32 char_id, const char* char_name, uint32 zone_id, uint16 instance_id, PlayerCorpse_Struct* dbpc, const glm::vec4& position, uint32 guild_id, bool is_rezzed) { +uint32 ZoneDatabase::UpdateCharacterCorpse(uint32 db_id, uint32 char_id, const char* char_name, uint32 zone_id, uint16 instance_id, const CharacterCorpseEntry& corpse, const glm::vec4& position, uint32 guild_id, bool is_rezzed) { std::string query = StringFormat("UPDATE `character_corpses` " "SET `charname` = '%s', `zone_id` = %u, `instance_id` = %u, `charid` = %d, " "`x` = %1.1f,`y` = %1.1f,`z` = %1.1f, `heading` = %1.1f, `guild_consent_id` = %u, " @@ -3796,15 +3796,15 @@ uint32 ZoneDatabase::UpdateCharacterCorpse(uint32 db_id, uint32 char_id, const c "WHERE `id` = %u", Strings::Escape(char_name).c_str(), zone_id, instance_id, char_id, position.x, position.y, position.z, position.w, guild_id, - dbpc->locked, dbpc->exp, dbpc->size, dbpc->level, dbpc->race, - dbpc->gender, dbpc->class_, dbpc->deity, dbpc->texture, - dbpc->helmtexture, dbpc->copper, dbpc->silver, dbpc->gold, - dbpc->plat, dbpc->haircolor, dbpc->beardcolor, dbpc->eyecolor1, - dbpc->eyecolor2, dbpc->hairstyle, dbpc->face, dbpc->beard, - dbpc->drakkin_heritage, dbpc->drakkin_tattoo, dbpc->drakkin_details, - dbpc->item_tint.Head.Color, dbpc->item_tint.Chest.Color, dbpc->item_tint.Arms.Color, - dbpc->item_tint.Wrist.Color, dbpc->item_tint.Hands.Color, dbpc->item_tint.Legs.Color, - dbpc->item_tint.Feet.Color, dbpc->item_tint.Primary.Color, dbpc->item_tint.Secondary.Color, + corpse.locked, corpse.exp, corpse.size, corpse.level, corpse.race, + corpse.gender, corpse.class_, corpse.deity, corpse.texture, + corpse.helmtexture, corpse.copper, corpse.silver, corpse.gold, + corpse.plat, corpse.haircolor, corpse.beardcolor, corpse.eyecolor1, + corpse.eyecolor2, corpse.hairstyle, corpse.face, corpse.beard, + corpse.drakkin_heritage, corpse.drakkin_tattoo, corpse.drakkin_details, + corpse.item_tint.Head.Color, corpse.item_tint.Chest.Color, corpse.item_tint.Arms.Color, + corpse.item_tint.Wrist.Color, corpse.item_tint.Hands.Color, corpse.item_tint.Legs.Color, + corpse.item_tint.Feet.Color, corpse.item_tint.Primary.Color, corpse.item_tint.Secondary.Color, db_id); auto results = QueryDatabase(query); @@ -3823,7 +3823,7 @@ void ZoneDatabase::MarkCorpseAsRezzed(uint32 db_id) { auto results = QueryDatabase(query); } -uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position, uint32 guildid) { +uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, const CharacterCorpseEntry& corpse, const glm::vec4& position, uint32 guildid) { /* Dump Basic Corpse Data */ std::string query = StringFormat( "INSERT INTO `character_corpses` " @@ -3880,39 +3880,39 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui position.z, position.w, guildid, - dbpc->locked, - dbpc->exp, - dbpc->size, - dbpc->level, - dbpc->race, - dbpc->gender, - dbpc->class_, - dbpc->deity, - dbpc->texture, - dbpc->helmtexture, - dbpc->copper, - dbpc->silver, - dbpc->gold, - dbpc->plat, - dbpc->haircolor, - dbpc->beardcolor, - dbpc->eyecolor1, - dbpc->eyecolor2, - dbpc->hairstyle, - dbpc->face, - dbpc->beard, - dbpc->drakkin_heritage, - dbpc->drakkin_tattoo, - dbpc->drakkin_details, - dbpc->item_tint.Head.Color, - dbpc->item_tint.Chest.Color, - dbpc->item_tint.Arms.Color, - dbpc->item_tint.Wrist.Color, - dbpc->item_tint.Hands.Color, - dbpc->item_tint.Legs.Color, - dbpc->item_tint.Feet.Color, - dbpc->item_tint.Primary.Color, - dbpc->item_tint.Secondary.Color + corpse.locked, + corpse.exp, + corpse.size, + corpse.level, + corpse.race, + corpse.gender, + corpse.class_, + corpse.deity, + corpse.texture, + corpse.helmtexture, + corpse.copper, + corpse.silver, + corpse.gold, + corpse.plat, + corpse.haircolor, + corpse.beardcolor, + corpse.eyecolor1, + corpse.eyecolor2, + corpse.hairstyle, + corpse.face, + corpse.beard, + corpse.drakkin_heritage, + corpse.drakkin_tattoo, + corpse.drakkin_details, + corpse.item_tint.Head.Color, + corpse.item_tint.Chest.Color, + corpse.item_tint.Arms.Color, + corpse.item_tint.Wrist.Color, + corpse.item_tint.Hands.Color, + corpse.item_tint.Legs.Color, + corpse.item_tint.Feet.Color, + corpse.item_tint.Primary.Color, + corpse.item_tint.Secondary.Color ); auto results = QueryDatabase(query); uint32 last_insert_id = results.LastInsertedID(); @@ -3920,41 +3920,51 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui std::string corpse_items_query; /* Dump Items from Inventory */ uint8 first_entry = 0; - for (unsigned int i = 0; i < dbpc->itemcount; i++) { + for(auto &item : corpse.items) + { if (first_entry != 1){ corpse_items_query = StringFormat("REPLACE INTO `character_corpse_items` \n" - " (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n" - " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", + " (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned, custom_data, ornamenticon, ornamentidfile, ornament_hero_model) \n" + " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, '%s', %u, %u, %u) \n", last_insert_id, - dbpc->items[i].equip_slot, - dbpc->items[i].item_id, - dbpc->items[i].charges, - dbpc->items[i].aug_1, - dbpc->items[i].aug_2, - dbpc->items[i].aug_3, - dbpc->items[i].aug_4, - dbpc->items[i].aug_5, - dbpc->items[i].aug_6, - dbpc->items[i].attuned + item.equip_slot, + item.item_id, + item.charges, + item.aug_1, + item.aug_2, + item.aug_3, + item.aug_4, + item.aug_5, + item.aug_6, + item.attuned, + item.custom_data.c_str(), + item.ornamenticon, + item.ornamentidfile, + item.ornament_hero_model ); first_entry = 1; } else{ - corpse_items_query = corpse_items_query + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", + corpse_items_query = corpse_items_query + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, '%s', %u, %u, %u) \n", last_insert_id, - dbpc->items[i].equip_slot, - dbpc->items[i].item_id, - dbpc->items[i].charges, - dbpc->items[i].aug_1, - dbpc->items[i].aug_2, - dbpc->items[i].aug_3, - dbpc->items[i].aug_4, - dbpc->items[i].aug_5, - dbpc->items[i].aug_6, - dbpc->items[i].attuned + item.equip_slot, + item.item_id, + item.charges, + item.aug_1, + item.aug_2, + item.aug_3, + item.aug_4, + item.aug_5, + item.aug_6, + item.attuned, + item.custom_data.c_str(), + item.ornamenticon, + item.ornamentidfile, + item.ornament_hero_model ); } } + if (!corpse_items_query.empty()) QueryDatabase(corpse_items_query); @@ -3993,18 +4003,6 @@ uint32 ZoneDatabase::GetCharacterCorpseID(uint32 char_id, uint8 corpse) { return 0; } -uint32 ZoneDatabase::GetCharacterCorpseItemCount(uint32 corpse_id){ - std::string query = StringFormat("SELECT COUNT(*) FROM character_corpse_items WHERE `corpse_id` = %u", - corpse_id - ); - auto results = QueryDatabase(query); - auto& row = results.begin(); - if (results.Success() && results.RowsAffected() != 0){ - return Strings::ToInt(row[0]); - } - return 0; -} - uint32 ZoneDatabase::GetCharacterCorpseItemAt(uint32 corpse_id, uint16 slotid) { Corpse* tmp = LoadCharacterCorpse(corpse_id); uint32 itemid = 0; @@ -4016,7 +4014,7 @@ uint32 ZoneDatabase::GetCharacterCorpseItemAt(uint32 corpse_id, uint16 slotid) { return itemid; } -bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct* pcs){ +bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, CharacterCorpseEntry& corpse){ std::string query = StringFormat( "SELECT \n" "is_locked, \n" @@ -4060,39 +4058,39 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct auto results = QueryDatabase(query); uint16 i = 0; for (auto& row = results.begin(); row != results.end(); ++row) { - pcs->locked = Strings::ToInt(row[i++]); // is_locked, - pcs->exp = Strings::ToUnsignedInt(row[i++]); // exp, - pcs->size = Strings::ToInt(row[i++]); // size, - pcs->level = Strings::ToInt(row[i++]); // `level`, - pcs->race = Strings::ToInt(row[i++]); // race, - pcs->gender = Strings::ToInt(row[i++]); // gender, - pcs->class_ = Strings::ToInt(row[i++]); // class, - pcs->deity = Strings::ToInt(row[i++]); // deity, - pcs->texture = Strings::ToInt(row[i++]); // texture, - pcs->helmtexture = Strings::ToInt(row[i++]); // helm_texture, - pcs->copper = Strings::ToUnsignedInt(row[i++]); // copper, - pcs->silver = Strings::ToUnsignedInt(row[i++]); // silver, - pcs->gold = Strings::ToUnsignedInt(row[i++]); // gold, - pcs->plat = Strings::ToUnsignedInt(row[i++]); // platinum, - pcs->haircolor = Strings::ToInt(row[i++]); // hair_color, - pcs->beardcolor = Strings::ToInt(row[i++]); // beard_color, - pcs->eyecolor1 = Strings::ToInt(row[i++]); // eye_color_1, - pcs->eyecolor2 = Strings::ToInt(row[i++]); // eye_color_2, - pcs->hairstyle = Strings::ToInt(row[i++]); // hair_style, - pcs->face = Strings::ToInt(row[i++]); // face, - pcs->beard = Strings::ToInt(row[i++]); // beard, - pcs->drakkin_heritage = Strings::ToUnsignedInt(row[i++]); // drakkin_heritage, - pcs->drakkin_tattoo = Strings::ToUnsignedInt(row[i++]); // drakkin_tattoo, - pcs->drakkin_details = Strings::ToUnsignedInt(row[i++]); // drakkin_details, - pcs->item_tint.Head.Color = Strings::ToUnsignedInt(row[i++]); // wc_1, - pcs->item_tint.Chest.Color = Strings::ToUnsignedInt(row[i++]); // wc_2, - pcs->item_tint.Arms.Color = Strings::ToUnsignedInt(row[i++]); // wc_3, - pcs->item_tint.Wrist.Color = Strings::ToUnsignedInt(row[i++]); // wc_4, - pcs->item_tint.Hands.Color = Strings::ToUnsignedInt(row[i++]); // wc_5, - pcs->item_tint.Legs.Color = Strings::ToUnsignedInt(row[i++]); // wc_6, - pcs->item_tint.Feet.Color = Strings::ToUnsignedInt(row[i++]); // wc_7, - pcs->item_tint.Primary.Color = Strings::ToUnsignedInt(row[i++]); // wc_8, - pcs->item_tint.Secondary.Color = Strings::ToUnsignedInt(row[i++]); // wc_9 + corpse.locked = Strings::ToInt(row[i++]); // is_locked, + corpse.exp = Strings::ToUnsignedInt(row[i++]); // exp, + corpse.size = Strings::ToInt(row[i++]); // size, + corpse.level = Strings::ToInt(row[i++]); // `level`, + corpse.race = Strings::ToInt(row[i++]); // race, + corpse.gender = Strings::ToInt(row[i++]); // gender, + corpse.class_ = Strings::ToInt(row[i++]); // class, + corpse.deity = Strings::ToInt(row[i++]); // deity, + corpse.texture = Strings::ToInt(row[i++]); // texture, + corpse.helmtexture = Strings::ToInt(row[i++]); // helm_texture, + corpse.copper = Strings::ToUnsignedInt(row[i++]); // copper, + corpse.silver = Strings::ToUnsignedInt(row[i++]); // silver, + corpse.gold = Strings::ToUnsignedInt(row[i++]); // gold, + corpse.plat = Strings::ToUnsignedInt(row[i++]); // platinum, + corpse.haircolor = Strings::ToInt(row[i++]); // hair_color, + corpse.beardcolor = Strings::ToInt(row[i++]); // beard_color, + corpse.eyecolor1 = Strings::ToInt(row[i++]); // eye_color_1, + corpse.eyecolor2 = Strings::ToInt(row[i++]); // eye_color_2, + corpse.hairstyle = Strings::ToInt(row[i++]); // hair_style, + corpse.face = Strings::ToInt(row[i++]); // face, + corpse.beard = Strings::ToInt(row[i++]); // beard, + corpse.drakkin_heritage = Strings::ToUnsignedInt(row[i++]); // drakkin_heritage, + corpse.drakkin_tattoo = Strings::ToUnsignedInt(row[i++]); // drakkin_tattoo, + corpse.drakkin_details = Strings::ToUnsignedInt(row[i++]); // drakkin_details, + corpse.item_tint.Head.Color = Strings::ToUnsignedInt(row[i++]); // wc_1, + corpse.item_tint.Chest.Color = Strings::ToUnsignedInt(row[i++]); // wc_2, + corpse.item_tint.Arms.Color = Strings::ToUnsignedInt(row[i++]); // wc_3, + corpse.item_tint.Wrist.Color = Strings::ToUnsignedInt(row[i++]); // wc_4, + corpse.item_tint.Hands.Color = Strings::ToUnsignedInt(row[i++]); // wc_5, + corpse.item_tint.Legs.Color = Strings::ToUnsignedInt(row[i++]); // wc_6, + corpse.item_tint.Feet.Color = Strings::ToUnsignedInt(row[i++]); // wc_7, + corpse.item_tint.Primary.Color = Strings::ToUnsignedInt(row[i++]); // wc_8, + corpse.item_tint.Secondary.Color = Strings::ToUnsignedInt(row[i++]); // wc_9 } query = StringFormat( "SELECT \n" @@ -4105,7 +4103,11 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct "aug_4, \n" "aug_5, \n" "aug_6, \n" - "attuned \n" + "attuned, \n" + "custom_data, \n" + "ornamenticon, \n" + "ornamentidfile, \n" + "ornament_hero_model \n" "FROM \n" "character_corpse_items \n" "WHERE `corpse_id` = %u\n" @@ -4115,20 +4117,32 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct results = QueryDatabase(query); i = 0; - pcs->itemcount = results.RowCount(); uint16 r = 0; for (auto& row = results.begin(); row != results.end(); ++row) { - memset(&pcs->items[i], 0, sizeof (player_lootitem::ServerLootItem_Struct)); - pcs->items[i].equip_slot = Strings::ToInt(row[r++]); // equip_slot, - pcs->items[i].item_id = Strings::ToUnsignedInt(row[r++]); // item_id, - pcs->items[i].charges = Strings::ToInt(row[r++]); // charges, - pcs->items[i].aug_1 = Strings::ToInt(row[r++]); // aug_1, - pcs->items[i].aug_2 = Strings::ToInt(row[r++]); // aug_2, - pcs->items[i].aug_3 = Strings::ToInt(row[r++]); // aug_3, - pcs->items[i].aug_4 = Strings::ToInt(row[r++]); // aug_4, - pcs->items[i].aug_5 = Strings::ToInt(row[r++]); // aug_5, - pcs->items[i].aug_6 = Strings::ToInt(row[r++]); // aug_6, - pcs->items[i].attuned = Strings::ToInt(row[r++]); // attuned, + CharacterCorpseItemEntry item; + item.equip_slot = Strings::ToInt(row[r++]); // equip_slot, + item.item_id = Strings::ToUnsignedInt(row[r++]); // item_id, + item.charges = Strings::ToInt(row[r++]); // charges, + item.aug_1 = Strings::ToInt(row[r++]); // aug_1, + item.aug_2 = Strings::ToInt(row[r++]); // aug_2, + item.aug_3 = Strings::ToInt(row[r++]); // aug_3, + item.aug_4 = Strings::ToInt(row[r++]); // aug_4, + item.aug_5 = Strings::ToInt(row[r++]); // aug_5, + item.aug_6 = Strings::ToInt(row[r++]); // aug_6, + item.attuned = Strings::ToInt(row[r++]) > 0 ? true : false; // attuned, + + if (row[r]) { + item.custom_data = row[r++]; + } + else { + r++; + } + + item.ornamenticon = Strings::ToUnsignedInt(row[r++]); + item.ornamentidfile = Strings::ToUnsignedInt(row[r++]); + item.ornament_hero_model = Strings::ToUnsignedInt(row[r++]); + + corpse.items.push_back(std::move(item)); r = 0; i++; } diff --git a/zone/zonedb.h b/zone/zonedb.h index b7c196a78..23309128c 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -285,6 +285,55 @@ struct ClientMercEntry { uint32 npcid; }; +struct CharacterCorpseItemEntry +{ + uint32 item_id; + int16 equip_slot; + uint16 charges; + uint16 lootslot; + uint32 aug_1; + uint32 aug_2; + uint32 aug_3; + uint32 aug_4; + uint32 aug_5; + uint32 aug_6; + bool attuned; + std::string custom_data; + uint32 ornamenticon; + uint32 ornamentidfile; + uint32 ornament_hero_model; +}; + +struct CharacterCorpseEntry +{ + bool locked; + uint32 exp; + float size; + uint8 level; + uint32 race; + uint8 gender; + uint8 class_; + uint8 deity; + uint8 texture; + uint8 helmtexture; + uint32 copper; + uint32 silver; + uint32 gold; + uint32 plat; + EQ::TintProfile item_tint; + uint8 haircolor; + uint8 beardcolor; + uint8 eyecolor1; + uint8 eyecolor2; + uint8 hairstyle; + uint8 face; + uint8 beard; + uint32 drakkin_heritage; + uint32 drakkin_tattoo; + uint32 drakkin_details; + std::vector items; +}; + namespace BeastlordPetData { struct PetStruct { uint16 race_id = WOLF; @@ -429,8 +478,7 @@ public: /* Corpses */ bool DeleteItemOffCharacterCorpse(uint32 db_id, uint32 equip_slot, uint32 item_id); - uint32 GetCharacterCorpseItemCount(uint32 corpse_id); - bool LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct* pcs); + bool LoadCharacterCorpseData(uint32 corpse_id, CharacterCorpseEntry &corpse); Corpse* LoadCharacterCorpse(uint32 player_corpse_id); Corpse* SummonBuriedCharacterCorpses(uint32 char_id, uint32 dest_zoneid, uint16 dest_instanceid, const glm::vec4& position); void MarkCorpseAsRezzed(uint32 dbid); @@ -446,8 +494,8 @@ public: uint32 GetCharacterCorpseDecayTimer(uint32 corpse_db_id); uint32 GetCharacterBuriedCorpseCount(uint32 char_id); uint32 SendCharacterCorpseToGraveyard(uint32 dbid, uint32 zoneid, uint16 instanceid, const glm::vec4& position); - uint32 SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position, uint32 guildid); - uint32 UpdateCharacterCorpse(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, PlayerCorpse_Struct* dbpc, const glm::vec4& position, uint32 guildid, bool rezzed = false); + uint32 SaveCharacterCorpse(uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, const CharacterCorpseEntry& corpse, const glm::vec4& position, uint32 guildid); + uint32 UpdateCharacterCorpse(uint32 dbid, uint32 charid, const char* charname, uint32 zoneid, uint16 instanceid, const CharacterCorpseEntry& corpse, const glm::vec4& position, uint32 guildid, bool rezzed = false); uint32 UpdateCharacterCorpseConsent(uint32 charid, uint32 guildid); uint32 GetFirstCorpseID(uint32 char_id); uint32 GetCharacterCorpseCount(uint32 char_id); diff --git a/zone/zonedump.h b/zone/zonedump.h index 51b21ee31..7de07c0fd 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -155,56 +155,6 @@ struct NPCType bool keeps_sold_items; }; -namespace player_lootitem { - struct ServerLootItem_Struct { - uint32 item_id; - int16 equip_slot; - uint16 charges; - uint16 lootslot; - uint32 aug_1; - uint32 aug_2; - uint32 aug_3; - uint32 aug_4; - uint32 aug_5; - uint32 aug_6; - int8 attuned; - uint8 min_level; // - uint8 max_level; // - }; -} - -struct PlayerCorpse_Struct { - uint32 crc; - bool locked; - uint32 itemcount; - uint32 exp; - float size; - uint8 level; - uint32 race; - uint8 gender; - uint8 class_; - uint8 deity; - uint8 texture; - uint8 helmtexture; - uint32 copper; - uint32 silver; - uint32 gold; - uint32 plat; - EQ::TintProfile item_tint; - uint8 haircolor; - uint8 beardcolor; - uint8 eyecolor1; - uint8 eyecolor2; - uint8 hairstyle; - uint8 face; - uint8 beard; - uint32 drakkin_heritage; - uint32 drakkin_tattoo; - uint32 drakkin_details; - player_lootitem::ServerLootItem_Struct items[0]; - //std::list items; -}; - #pragma pack() #endif