diff --git a/changelog.txt b/changelog.txt index 34fca5197..a7f8ed9f2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/28/2014 == +Uleat: Implemented class Client::TextLink as a replacement for the dozens of individual link formatters. + == 12/27/2014 == Akkadius: Add option to automatic database upgrade script 5) Download latest Opcodes from Github Trevius: (RoF2) Fixed dropping items on the ground so they go to ground level instead of camera height. diff --git a/zone/bot.cpp b/zone/bot.cpp index 4fd830659..d41b6db11 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -11699,58 +11699,47 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { const char* equipped[EmuConstants::EQUIPMENT_SIZE] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo" }; - const ItemInst* item1 = nullptr; - const Item_Struct* item2 = nullptr; + + const ItemInst* inst = nullptr; + const Item_Struct* item = nullptr; bool is2Hweapon = false; - for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) - { + + std::string item_link; + Client::TextLink linker; + linker.SetLinkType(linker.linkItemInst); + linker.SetClientVersion(c->GetClientVersion()); + + for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { if((i == MainSecondary) && is2Hweapon) { continue; } - item1 = b->CastToBot()->GetBotItem(i); - if(item1) - item2 = item1->GetItem(); + inst = b->CastToBot()->GetBotItem(i); + if (inst) + item = inst->GetItem(); else - item2 = nullptr; + item = nullptr; if(!TempErrorMessage.empty()) { c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); return; } - if(item2 == nullptr) { + if(item == nullptr) { c->Message(15, "I need something for my %s (Item %i)", equipped[i], i); continue; } - if((i == MainPrimary) && ((item2->ItemType == ItemType2HSlash) || (item2->ItemType == ItemType2HBlunt) || (item2->ItemType == ItemType2HPiercing))) { + if((i == MainPrimary) && ((item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HPiercing))) { is2Hweapon = true; } - char* link_core = nullptr; - std::string link_base; - // I could not find a difference between the criteria positive code and the criteria negative code.. - // ..so, I deleted the check (criteria: i = { MainCharm, MainRange, MainPrimary, MainSecondary, MainAmmo }) + // ..so, I deleted the check (old criteria: i = { MainCharm, MainRange, MainPrimary, MainSecondary, MainAmmo }) + + linker.SetItemInst(inst); - c->MakeItemLink( - link_core, - item2, - item1->GetAugmentItemID(0), - item1->GetAugmentItemID(1), - item1->GetAugmentItemID(2), - item1->GetAugmentItemID(3), - item1->GetAugmentItemID(4), - item1->GetAugmentItemID(5) - ); + item_link = linker.GenerateLink(); - if (link_core) - link_base = StringFormat("%c%s%s%c", 0x12, link_core, item2->Name, 0x12); - else - link_base = ""; - - c->Message(15, "Using %s in my %s (Item %i)", link_base.c_str(), equipped[i], i); - - safe_delete_array(link_core); + c->Message(15, "Using %s in my %s (Item %i)", item_link.c_str(), equipped[i], i); } } else { diff --git a/zone/client.cpp b/zone/client.cpp index e25aec69a..0ad34d752 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8258,3 +8258,236 @@ void Client::SendColoredText(uint32 color, std::string message) safe_delete(outapp); } + +// +// class Client::TextLink +// +std::string Client::TextLink::GenerateLink() +{ + m_Link.clear(); + m_LinkBody.clear(); + m_LinkText.clear(); + + generate_body(); + generate_text(); + + if (m_LinkBody.length() && m_LinkText.length()) { + m_Link.append(StringFormat("%c", 0x12)); + m_Link.append(m_LinkBody); + m_Link.append(m_LinkText); + m_Link.append(StringFormat("%c", 0x12)); + } + + if ((m_Link.length() == 0) || (m_Link.length() > 250)) { + m_Error = true; + m_Link = ""; + _log(CHANNELS__ERROR, "TextLink::GenerateLink() failed to generate a useable text link (LinkType: %i, Lengths: {l: %u, b: %u, t: %u})", + m_LinkType, m_Link.length(), m_LinkBody.length(), m_LinkText.length()); + } + + return m_Link; +} + +const char* Client::TextLink::GetLink() +{ + if (m_Link.length() == 0) + return nullptr; + + return m_Link.c_str(); +} + +const char* Client::TextLink::GetLinkBody() +{ + if (m_LinkBody.length() == 0) + return nullptr; + + return m_LinkBody.c_str(); +} + +const char* Client::TextLink::GetLinkText() +{ + if (m_LinkText.length() == 0) + return nullptr; + + return m_LinkText.c_str(); +} + +std::string Client::TextLink::GetLinkString() +{ + if (m_Link.length() == 0) + return ""; + + return m_Link; +} + +std::string Client::TextLink::GetLinkBodyString() +{ + if (m_LinkBody.length() == 0) + return ""; + + return m_LinkBody; +} + +std::string Client::TextLink::GetLinkTextString() +{ + if (m_LinkText.length() == 0) + return ""; + + return m_LinkText; +} + +void Client::TextLink::Reset() +{ + m_LinkType = linkBlank; + m_ItemData = nullptr; + m_LootData = nullptr; + m_ItemInst = nullptr; + m_ProxyItemID = NOT_USED; + m_ProxyText = nullptr; + m_TaskUse = false; + m_Link.clear(); + m_LinkBody.clear(); + m_LinkText.clear(); + m_ClientVersion = EQClientUnknown; + m_Error = false; +} + +void Client::TextLink::generate_body() +{ + enum { field_0 = 0, field_1, field_2, field_3, field_4, field_5, field_6, field_7, field_8, field_9, field_10, field_11, field_12, field_13 }; + static const int field_count = 14; + static const bool field_use[_EQClientCount][field_count] = { + // 6.2: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" + // SoF: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" + // RoF: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" + // RoF2: MakeAnyLenString(&ret_link, "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%1X" "%04X" "%1X" "%05X" "%08X" + +//(RoF2) %01x %05x %05x %05x %05x %05x %05x %05x %01x %01x %04x %01x %05x %08x + { true, true, true, true, true, true, true, true, true, true, true, true, true, true }, // EQClientUnknown + { true, true, true, true, true, true, true, false, false, true, true, true, false, true }, // EQClient6.2 + { true, true, true, true, true, true, true, false, false, true, true, true, false, true }, // EQClientTitanium + { true, true, true, true, true, true, true, false, false, true, true, true, true, true }, // EQClientSoF + { true, true, true, true, true, true, true, false, false, true, true, true, true, true }, // EQClientSoD + { true, true, true, true, true, true, true, false, false, true, true, true, true, true }, // EQClientUnderfoot + { true, true, true, true, true, true, true, true, false, true, true, true, true, true }, // EQClientRoF + { true, true, true, true, true, true, true, true, true, true, true, true, true, true } // EQClientRoF2 + }; + +/*%01X*/ uint8 unknown_0 = NOT_USED; +/*%05X*/ uint32 item_id = NOT_USED; +/*%05X*/ uint32 augment_0 = NOT_USED; +/*%05X*/ uint32 augment_1 = NOT_USED; +/*%05X*/ uint32 augment_2 = NOT_USED; +/*%05X*/ uint32 augment_3 = NOT_USED; +/*%05X*/ uint32 augment_4 = NOT_USED; +/*%05X*/ uint32 augment_5 = NOT_USED; +/*%01X*/ uint8 unknown_8 = NOT_USED; +/*%01X*/ uint8 unknown_9 = NOT_USED; +/*%04X*/ uint32 unknown_10 = NOT_USED; +/*%01X*/ uint8 unknown_11 = NOT_USED; +/*%05X*/ uint32 unknown_12 = NOT_USED; +/*%08X*/ int hash = NOT_USED; + + switch (m_LinkType) { + case linkBlank: + break; + case linkItemData: + if (m_ItemData != nullptr) { + item_id = m_ItemData->ID; + // TODO: add hash call + } + break; + case linkLootItem: + if (m_LootData != nullptr) { + const Item_Struct* item_data = database.GetItem(m_LootData->item_id); + if (item_data == nullptr) { break; } + item_id = item_data->ID; + augment_0 = m_LootData->aug_1; + augment_1 = m_LootData->aug_2; + augment_2 = m_LootData->aug_3; + augment_3 = m_LootData->aug_4; + augment_4 = m_LootData->aug_5; + augment_5 = m_LootData->aug_6; + // TODO: add hash call + } + break; + case linkItemInst: + if (m_ItemInst != nullptr) { + if (m_ItemInst->GetItem() == nullptr) { break; } + item_id = m_ItemInst->GetItem()->ID; + augment_0 = m_ItemInst->GetAugmentItemID(0); + augment_1 = m_ItemInst->GetAugmentItemID(1); + augment_2 = m_ItemInst->GetAugmentItemID(2); + augment_3 = m_ItemInst->GetAugmentItemID(3); + augment_4 = m_ItemInst->GetAugmentItemID(4); + augment_5 = m_ItemInst->GetAugmentItemID(5); + // TODO: add hash call + } + break; + default: + break; + } + + if (m_ProxyItemID != NOT_USED) { + item_id = m_ProxyItemID; + } + + if (m_TaskUse) { + hash = 0x0000000014505DC2; + } + + if (field_use[m_ClientVersion][field_0]) { m_LinkBody.append(StringFormat("%01x", unknown_0)); } + if (field_use[m_ClientVersion][field_1]) { m_LinkBody.append(StringFormat("%05x", item_id)); } + if (field_use[m_ClientVersion][field_2]) { m_LinkBody.append(StringFormat("%05x", augment_0)); } + if (field_use[m_ClientVersion][field_3]) { m_LinkBody.append(StringFormat("%05x", augment_1)); } + if (field_use[m_ClientVersion][field_4]) { m_LinkBody.append(StringFormat("%05x", augment_2)); } + if (field_use[m_ClientVersion][field_5]) { m_LinkBody.append(StringFormat("%05x", augment_3)); } + if (field_use[m_ClientVersion][field_6]) { m_LinkBody.append(StringFormat("%05x", augment_4)); } + if (field_use[m_ClientVersion][field_7]) { m_LinkBody.append(StringFormat("%05x", augment_5)); } + if (field_use[m_ClientVersion][field_8]) { m_LinkBody.append(StringFormat("%01x", unknown_8)); } + if (field_use[m_ClientVersion][field_9]) { m_LinkBody.append(StringFormat("%01x", unknown_9)); } + if (field_use[m_ClientVersion][field_10]) { m_LinkBody.append(StringFormat("%04x", unknown_10)); } + if (field_use[m_ClientVersion][field_11]) { m_LinkBody.append(StringFormat("%01x", unknown_11)); } + if (field_use[m_ClientVersion][field_12]) { m_LinkBody.append(StringFormat("%05x", unknown_12)); } + if (field_use[m_ClientVersion][field_13]) { m_LinkBody.append(StringFormat("%08x", hash)); } +} + +void Client::TextLink::generate_text() +{ + if (m_ProxyText != nullptr) { + m_LinkText = m_ProxyText; + return; + } + + switch (m_LinkType) { + case linkBlank: + break; + case linkItemData: + if (m_ItemData != nullptr) { + m_LinkText = m_ItemData->Name; + return; + } + break; + case linkLootItem: + if (m_LootData != nullptr) { + const Item_Struct* item_data = database.GetItem(m_LootData->item_id); + if (item_data != nullptr) { + m_LinkText = item_data->Name; + return; + } + } + break; + case linkItemInst: + if (m_ItemInst != nullptr) { + if (m_ItemInst->GetItem() != nullptr) { + m_LinkText = m_ItemInst->GetItem()->Name; + return; + } + } + break; + default: + break; + } + + m_LinkText = "null"; +} diff --git a/zone/client.h b/zone/client.h index c88971dd4..ee9f990da 100644 --- a/zone/client.h +++ b/zone/client.h @@ -815,12 +815,57 @@ public: void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); - bool MakeItemLink(char* &ret_link, const Item_Struct* item, uint32 aug0=0, uint32 aug1=0, uint32 aug2=0, uint32 aug3=0, uint32 aug4=0, uint32 aug5=0, uint8 evolving=0, uint8 evolvedlevel=0); - bool MakeItemLink(char* &ret_link, const ItemInst* inst); - bool MakeTaskLink(char* &ret_link); - bool MakeBlankLink(char* &ret_link); - static bool MakeBlankLink_(char* &ret_link); - int GetItemLinkHash(const ItemInst* inst); + + // + // class Client::TextLink + // + class TextLink { + public: + enum LinkType { linkBlank = 0, linkItemData, linkLootItem, linkItemInst }; + + TextLink() { Reset(); } + + void SetLinkType(LinkType linkType) { m_LinkType = linkType; } + void SetItemData(const Item_Struct* 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 + void SetProxyText(const char* proxyText) { m_ProxyText = proxyText; } // overrides standard text use + void SetTaskUse() { m_TaskUse = true; } + void SetClientVersion(EQClientVersion clientVersion) { m_ClientVersion = EQLimits::ValidateClientVersion(clientVersion); } + + std::string GenerateLink(); + bool LinkError() { return m_Error; } + + const char* GetLink(); // contains full format: '/12x' '' '' '/12x' + const char* GetLinkBody(); // contains format: '' + const char* GetLinkText(); // contains format: '' + std::string GetLinkString(); + std::string GetLinkBodyString(); + std::string GetLinkTextString(); + + void Reset(); + + private: + void generate_body(); + void generate_text(); + + int m_LinkType; + const Item_Struct* m_ItemData; + const ServerLootItem_Struct* m_LootData; + const ItemInst* m_ItemInst; + uint32 m_ProxyItemID; + const char* m_ProxyText; + bool m_TaskUse; + std::string m_Link; + std::string m_LinkBody; + std::string m_LinkText; + EQClientVersion m_ClientVersion; + bool m_Error; + }; + + int GetItemLinkHash(const ItemInst* inst); // move to Item_Struct..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); void SendItemPacket(int16 slot_id, const ItemInst* inst, ItemPacketType packet_type); diff --git a/zone/command.cpp b/zone/command.cpp index ba3ffd5a7..d31ea97b7 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2615,117 +2615,93 @@ void command_peekinv(Client *c, const Seperator *sep) } Client* targetClient = c->GetTarget()->CastToClient(); - const ItemInst* instMain = nullptr; - const ItemInst* instSub = nullptr; - const Item_Struct* itemData = nullptr; - char* itemLinkCore = nullptr; - std::string itemLink; + const ItemInst* inst_main = nullptr; + const ItemInst* inst_sub = nullptr; + const Item_Struct* item_data = nullptr; + std::string item_link; + Client::TextLink linker; + linker.SetLinkType(linker.linkItemInst); + linker.SetClientVersion(c->GetClientVersion()); c->Message(0, "Displaying inventory for %s...", targetClient->GetName()); // worn for (int16 indexMain = EmuConstants::EQUIPMENT_BEGIN; (scopeWhere & peekWorn) && (indexMain <= EmuConstants::EQUIPMENT_END); ++indexMain) { - instMain = targetClient->GetInv().GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = targetClient->GetInv().GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); + item_link = linker.GenerateLink(); - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "WornSlot: %i, Item: %i (%s), Charges: %i", - indexMain, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); - - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "WornSlot: %i, Item: %i (%s), Charges: %i", + indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); } if ((scopeWhere & peekWorn) && (targetClient->GetClientVersion() >= EQClientSoF)) { - instMain = targetClient->GetInv().GetItem(MainPowerSource); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; - - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); + inst_main = targetClient->GetInv().GetItem(MainPowerSource); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - c->Message((itemData == 0), "WornSlot: %i, Item: %i (%s), Charges: %i", - MainPowerSource, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "WornSlot: %i, Item: %i (%s), Charges: %i", + MainPowerSource, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); } // inv for (int16 indexMain = EmuConstants::GENERAL_BEGIN; (scopeWhere & peekInv) && (indexMain <= EmuConstants::GENERAL_END); ++indexMain) { - instMain = targetClient->GetInv().GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = targetClient->GetInv().GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "InvSlot: %i, Item: %i (%s), Charges: %i", - indexMain, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "InvSlot: %i, Item: %i (%s), Charges: %i", + indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; instMain && instMain->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { - instSub = instMain->GetItem(indexSub); - itemData = (instSub ? instSub->GetItem() : nullptr); - itemLinkCore = nullptr; + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + inst_sub = inst_main->GetItem(indexSub); + item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); + linker.SetItemInst(inst_sub); - if (itemData) - c->MakeItemLink(itemLinkCore, instSub); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instSub->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), " InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instSub->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + 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())); } } // cursor if (scopeWhere & peekCursor) { if (targetClient->GetInv().CursorEmpty()) { + linker.SetItemInst(nullptr); + + item_link = linker.GenerateLink(); + c->Message(1, "CursorSlot: %i, Item: %i (%s), Charges: %i", - MainCursor, 0, "null", 0); + MainCursor, 0, item_link.c_str(), 0); } else { int cursorDepth = 0; for (iter_queue it = targetClient->GetInv().cursor_begin(); (it != targetClient->GetInv().cursor_end()); ++it, ++cursorDepth) { - instMain = *it; - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = *it; + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "CursorSlot: %i, Depth: %i, Item: %i (%s), Charges: %i", - MainCursor, cursorDepth, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "CursorSlot: %i, Depth: %i, Item: %i (%s), Charges: %i", + MainCursor, cursorDepth, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; (cursorDepth == 0) && instMain && instMain->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { - instSub = instMain->GetItem(indexSub); - itemData = (instSub ? instSub->GetItem() : nullptr); - itemLinkCore = nullptr; + for (uint8 indexSub = SUB_BEGIN; (cursorDepth == 0) && inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + inst_sub = inst_main->GetItem(indexSub); + item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); + linker.SetItemInst(inst_sub); - if (itemData) - c->MakeItemLink(itemLinkCore, instSub); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instSub->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(MainCursor, indexSub), MainCursor, indexSub, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instSub->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + 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())); } } } @@ -2733,116 +2709,81 @@ void command_peekinv(Client *c, const Seperator *sep) // trib for (int16 indexMain = EmuConstants::TRIBUTE_BEGIN; (scopeWhere & peekTrib) && (indexMain <= EmuConstants::TRIBUTE_END); ++indexMain) { - instMain = targetClient->GetInv().GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = targetClient->GetInv().GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "TributeSlot: %i, Item: %i (%s), Charges: %i", - indexMain, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "TributeSlot: %i, Item: %i (%s), Charges: %i", + indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); } // bank for (int16 indexMain = EmuConstants::BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EmuConstants::BANK_END); ++indexMain) { - instMain = targetClient->GetInv().GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = targetClient->GetInv().GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null" ); - - c->Message((itemData == 0), "BankSlot: %i, Item: %i (%s), Charges: %i", - indexMain, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "BankSlot: %i, Item: %i (%s), Charges: %i", + indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; instMain && instMain->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { - instSub = instMain->GetItem(indexSub); - itemData = (instSub ? instSub->GetItem() : nullptr); - itemLinkCore = nullptr; + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + inst_sub = inst_main->GetItem(indexSub); + item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); + linker.SetItemInst(inst_sub); - if (itemData) - c->MakeItemLink(itemLinkCore, instSub); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instSub->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), " BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instSub->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + 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())); } } for (int16 indexMain = EmuConstants::SHARED_BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EmuConstants::SHARED_BANK_END); ++indexMain) { - instMain = targetClient->GetInv().GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = targetClient->GetInv().GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); + item_link = linker.GenerateLink(); - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "SharedBankSlot: %i, Item: %i (%s), Charges: %i", - indexMain, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + c->Message((item_data == nullptr), "SharedBankSlot: %i, Item: %i (%s), Charges: %i", + indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - safe_delete_array(itemLinkCore); + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + inst_sub = inst_main->GetItem(indexSub); + item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); + linker.SetItemInst(inst_sub); - for (uint8 indexSub = SUB_BEGIN; instMain && instMain->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { - instSub = instMain->GetItem(indexSub); - itemData = (instSub ? instSub->GetItem() : nullptr); - itemLinkCore = nullptr; + item_link = linker.GenerateLink(); - if (itemData) - c->MakeItemLink(itemLinkCore, instSub); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instSub->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), " SharedBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instSub->GetCharges())); - - safe_delete_array(itemLinkCore); + 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())); } } // trade for (int16 indexMain = EmuConstants::TRADE_BEGIN; (scopeWhere & peekTrade) && (indexMain <= EmuConstants::TRADE_END); ++indexMain) { - instMain = targetClient->GetInv().GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = targetClient->GetInv().GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "TradeSlot: %i, Item: %i (%s), Charges: %i", - indexMain, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "TradeSlot: %i, Item: %i (%s), Charges: %i", + indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; instMain && instMain->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { - instSub = instMain->GetItem(indexSub); - itemData = (instSub ? instSub->GetItem() : nullptr); - itemLinkCore = nullptr; + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + inst_sub = inst_main->GetItem(indexSub); + item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); + linker.SetItemInst(inst_sub); - if (itemData) - c->MakeItemLink(itemLinkCore, instSub); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instSub->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), " TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instSub->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + 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())); } } @@ -2857,34 +2798,24 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message(0, "[WorldObject DBID: %i (entityid: %i)]", objectTradeskill->GetDBID(), objectTradeskill->GetID()); for (int16 indexMain = MAIN_BEGIN; indexMain < EmuConstants::MAP_WORLD_SIZE; ++indexMain) { - instMain = objectTradeskill->GetItem(indexMain); - itemData = (instMain ? instMain->GetItem() : nullptr); - itemLinkCore = nullptr; + inst_main = objectTradeskill->GetItem(indexMain); + item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); + linker.SetItemInst(inst_main); - if (itemData) - c->MakeItemLink(itemLinkCore, instMain); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instMain->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), "WorldSlot: %i, Item: %i (%s), Charges: %i", - (EmuConstants::WORLD_BEGIN + indexMain), ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instMain->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), "WorldSlot: %i, Item: %i (%s), Charges: %i", + (EmuConstants::WORLD_BEGIN + indexMain), ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; instMain && instMain->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { - instSub = instMain->GetItem(indexSub); - itemData = (instSub ? instSub->GetItem() : nullptr); - itemLinkCore = nullptr; + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + inst_sub = inst_main->GetItem(indexSub); + item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); + linker.SetItemInst(inst_sub); - if (itemData) - c->MakeItemLink(itemLinkCore, instSub); - - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, instSub->GetItem()->Name, 0x12) : "null"); - - c->Message((itemData == 0), " WorldBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - INVALID_INDEX, indexMain, indexSub, ((itemData == 0) ? 0 : itemData->ID), itemLink.c_str(), ((itemData == 0) ? 0 : instSub->GetCharges())); + item_link = linker.GenerateLink(); - safe_delete_array(itemLinkCore); + c->Message((item_data == nullptr), " WorldBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", + INVALID_INDEX, indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } } @@ -5640,22 +5571,19 @@ void command_itemsearch(Client *c, const Seperator *sep) const char *search_criteria=sep->argplus[1]; const Item_Struct* item = nullptr; + std::string item_link; + Client::TextLink linker; + linker.SetLinkType(linker.linkItemData); + linker.SetClientVersion(c->GetClientVersion()); + if (Seperator::IsNumber(search_criteria)) { item = database.GetItem(atoi(search_criteria)); if (item) { - char* link_core = nullptr; - std::string link_base; + linker.SetItemData(item); - c->MakeItemLink(link_core, item); + item_link = linker.GenerateLink(); - if (link_core) - link_base = StringFormat("%c%s%s%c", 0x12, link_core, item->Name, 0x12); - else - link_base = ""; - - c->Message(0, "%i: %s", (int)item->ID, link_base.c_str()); - - safe_delete_array(link_core); + c->Message(0, "%u: %s", item->ID, item_link.c_str()); } else { c->Message(0, "Item #%s not found", search_criteria); @@ -5676,19 +5604,12 @@ void command_itemsearch(Client *c, const Seperator *sep) strupr(sName); pdest = strstr(sName, sCriteria); if (pdest != nullptr) { - char* link_core = nullptr; - std::string link_base; + linker.SetItemData(item); - c->MakeItemLink(link_core, item); + item_link = linker.GenerateLink(); - if (link_core) - link_base = StringFormat("%c%s%s%c", 0x12, link_core, item->Name, 0x12); - else - link_base = ""; + c->Message(0, "%u: %s", item->ID, item_link.c_str()); - c->Message(0, "%i: %s", (int)item->ID, link_base.c_str()); - - safe_delete_array(link_core); ++count; } diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 1e3bdcafb..a99b8b500 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1254,33 +1254,38 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } } - if (GetPlayerKillItem() != -1){ + if (GetPlayerKillItem() != -1) { SetPlayerKillItemID(0); } /* Send message with item link to groups and such */ - char *link = 0, *link2 = 0; //just like a db query :-) - client->MakeItemLink(link2, inst); - MakeAnyLenString(&link, "%c" "%s" "%s" "%c", - 0x12, - link2, - item->Name, - 0x12); - safe_delete_array(link2); + Client::TextLink linker; + linker.SetLinkType(linker.linkItemInst); + linker.SetItemInst(inst); + linker.SetClientVersion(client->GetClientVersion()); + + auto item_link = linker.GenerateLink(); + + client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, item_link.c_str()); - client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, link); if(!IsPlayerCorpse()) { + // When sending to multiple/unknown client types, we set for the highest client.. + // ..which is processed when 'EQClientUnknown,' or default value, is selected. + // This should help with any current issues..or it may create more! O.o + linker.SetClientVersion(EQClientUnknown); + item_link = linker.GenerateLink(); + Group *g = client->GetGroup(); if(g != nullptr) { - g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), link); - } else { + g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str()); + } + else { Raid *r = client->GetRaid(); if(r != nullptr) { - r->RaidMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), link); + r->RaidMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str()); } } } - safe_delete_array(link); } else { SendEndLootErrorPacket(client); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 0ccd29611..19520a177 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1027,7 +1027,8 @@ void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type) } } -bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint8 evolving, uint8 evolvedlevel) { +// 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) { //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 @@ -1058,7 +1059,8 @@ bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, // into it further to determine the cause..but, the function is setup to accept the parameters. // Note: some links appear with '00000' in front of the name..so, it's likely we need to send // some additional information when certain parameters are true -U - switch (GetClientVersion()) { + //switch (GetClientVersion()) { + switch (0) { case EQClientRoF2: // This operator contains 14 parameter masks..but, only 13 parameter values. // Even so, the client link appears ok... Need to figure out the discrepancy -U @@ -1134,76 +1136,6 @@ bool Client::MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, } } -bool Client::MakeItemLink(char* &ret_link, const ItemInst *inst) { - if (!inst) - return false; - - return MakeItemLink( - ret_link, - inst->GetItem(), - inst->GetAugmentItemID(0), - inst->GetAugmentItemID(1), - inst->GetAugmentItemID(2), - inst->GetAugmentItemID(3), - inst->GetAugmentItemID(4), - inst->GetAugmentItemID(5), - inst->IsEvolving(), - inst->GetEvolveLvl() - ); -} - -bool Client::MakeTaskLink(char* &ret_link) -{ - switch (GetClientVersion()) { - case EQClientRoF2: - MakeAnyLenString(&ret_link, "00000000000000000000000000000000000000000014505DC2"); - return true; - case EQClientRoF: - MakeAnyLenString(&ret_link, "0000000000000000000000000000000000000000014505DC2"); - return true; - case EQClientUnderfoot: - case EQClientSoD: - case EQClientSoF: - MakeAnyLenString(&ret_link, "00000000000000000000000000000000000014505DC2"); - return true; - case EQClientTitanium: - MakeAnyLenString(&ret_link, "000000000000000000000000000000014505DC2"); - return true; - case EQClient62: - default: - return false; - } -} - -bool Client::MakeBlankLink(char* &ret_link) -{ - switch (GetClientVersion()) { - case EQClientRoF2: - MakeAnyLenString(&ret_link, "00000000000000000000000000000000000000000000000000"); - return true; - case EQClientRoF: - MakeAnyLenString(&ret_link, "0000000000000000000000000000000000000000000000000"); - return true; - case EQClientUnderfoot: - case EQClientSoD: - case EQClientSoF: - MakeAnyLenString(&ret_link, "00000000000000000000000000000000000000000000"); - return true; - case EQClientTitanium: - MakeAnyLenString(&ret_link, "000000000000000000000000000000000000000"); - return true; - case EQClient62: - default: - return false; - } -} - -bool Client::MakeBlankLink_(char* &ret_link) -{ - MakeAnyLenString(&ret_link, "00000000000000000000000000000000000000000000000000"); // should be same as newest/longest client in local operator - return true; -} - int Client::GetItemLinkHash(const ItemInst* inst) { //pre-Titanium: http://eqitems.13th-floor.org/phpBB2/viewtopic.php?t=70&postdays=0&postorder=asc //Titanium: http://eqitems.13th-floor.org/phpBB2/viewtopic.php?t=145 @@ -1292,6 +1224,7 @@ int Client::GetItemLinkHash(const ItemInst* inst) { return hash; } +// This appears to still be in use... The core of this should be incorporated into class Client::TextLink void Client::SendItemLink(const ItemInst* inst, bool send_to_all) { /* diff --git a/zone/npc.cpp b/zone/npc.cpp index ad96af1c4..a478e3b51 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -512,14 +512,14 @@ void NPC::QueryLoot(Client* to) continue; } - char* itemLinkCore = nullptr; - std::string itemLink; + Client::TextLink linker; + linker.SetLinkType(linker.linkItemData); + linker.SetItemData(item); + linker.SetClientVersion(to->GetClientVersion()); - to->MakeItemLink(itemLinkCore, item); - itemLink = (itemLinkCore ? StringFormat("%c%s%s%c", 0x12, itemLinkCore, item->Name, 0x12) : "null"); - to->Message(0, "%s, ID: %u, Level: (min: %u, max: %u)", itemLink.c_str(), item->ID, (*cur)->min_level, (*cur)->max_level); - - safe_delete_array(itemLinkCore); + auto item_link = linker.GenerateLink(); + + to->Message(0, "%s, ID: %u, Level: (min: %u, max: %u)", item_link.c_str(), item->ID, (*cur)->min_level, (*cur)->max_level); } to->Message(0, "%i items on %s.", x, GetName()); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index fbf4586bc..8dbc068c7 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1227,15 +1227,18 @@ void QuestManager::settime(uint8 new_hour, uint8 new_min) { void QuestManager::itemlink(int item_id) { QuestManagerCurrentQuestVars(); if (initiator) { - const ItemInst* inst = database.CreateItem(item_id); - char* link = 0; - if (inst == nullptr) + const Item_Struct* item = database.GetItem(item_id); + if (item == nullptr) return; - if (initiator->MakeItemLink(link, inst)) - initiator->Message(0, "%s tells you, %c%s%s%c", owner->GetCleanName(), - 0x12, link, inst->GetItem()->Name, 0x12); - safe_delete_array(link); - safe_delete(inst); + + Client::TextLink linker; + linker.SetLinkType(linker.linkItemData); + linker.SetItemData(item); + linker.SetClientVersion(initiator->GetClientVersion()); + + auto item_link = linker.GenerateLink(); + + initiator->Message(0, "%s tells you, %s", owner->GetCleanName(), item_link.c_str()); } } @@ -2463,17 +2466,19 @@ 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 ItemInst* inst = database.CreateItem(item_id); - if (!inst) + const Item_Struct* item = database.GetItem(item_id); + if (!item) return "INVALID ITEM ID IN VARLINK"; - char* link = 0; - char* tempstr = 0; - // already uses Client::operator-based item link method - if (initiator->MakeItemLink(link, inst)) { // make a link to the item - snprintf(perltext, 250, "%c%s%s%c", 0x12, link, inst->GetItem()->Name, 0x12); - } - safe_delete_array(link); // MakeItemLink() uses new also - safe_delete(inst); + + Client::TextLink linker; + linker.SetLinkType(linker.linkItemData); + linker.SetItemData(item); + if (initiator) + linker.SetClientVersion(initiator->GetClientVersion()); + + auto item_link = linker.GenerateLink(); + strcpy(perltext, item_link.c_str()); // link length is currently ranged from 1 to 250 in TextLink::GenerateLink() + return perltext; } @@ -2659,33 +2664,15 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam sayid = sayid + 500000; //Create the say link as an item link hash - char* link_core = nullptr; - std::string say_link; + Client::TextLink linker; + linker.SetProxyItemID(sayid); + linker.SetProxyText(LinkName); + if (initiator) + linker.SetClientVersion(initiator->GetClientVersion()); - if (initiator) { - initiator->MakeBlankLink(link_core); + auto say_link = linker.GenerateLink(); + strcpy(Phrase, say_link.c_str()); // link length is currently ranged from 1 to 250 in TextLink::GenerateLink() - if (link_core) - say_link = StringFormat("%c%06x%s%s%c", 0x12, sayid, link_core, LinkName, 0x12); - else - say_link = ""; - } - else { // If no initiator, create an RoF2 saylink, since older clients handle RoF2 ones better than RoF2 handles older ones. - Client::MakeBlankLink_(link_core); // Note: this is a global operator - say_link = StringFormat("%c%06x%s%s%c", 0x12, sayid, link_core, LinkName, 0x12); - } - - safe_delete_array(link_core); - - if (say_link.length() > 250) - strcpy(Phrase, ""); - else if (say_link.length() == 0) - strcpy(Phrase, ""); - else - strcpy(Phrase, say_link.c_str()); - - // Why do we have '(char*)Phrase' as an argument and then return it? - // The current behavior of this function doesn't allow recursive action return Phrase; } diff --git a/zone/tasks.cpp b/zone/tasks.cpp index e0e96d70c..6c7f933b0 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -2770,29 +2770,18 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN } if(ItemID) { - char* link_core = nullptr; - std::string reward_link; + const Item_Struct* reward_item = database.GetItem(ItemID); - c->MakeTaskLink(link_core); + Client::TextLink linker; + linker.SetLinkType(linker.linkItemData); + linker.SetItemData(reward_item); + linker.SetClientVersion(c->GetClientVersion()); + linker.SetTaskUse(); + if (strlen(Tasks[TaskID]->Reward) != 0) + linker.SetProxyText(Tasks[TaskID]->Reward); - if (link_core && (strlen(Tasks[TaskID]->Reward) != 0)) { - reward_link = StringFormat("%c%06x%s%s%c", 0x12, ItemID, link_core, Tasks[TaskID]->Reward, 0x12); - } - else if (link_core) { - const Item_Struct* Item = database.GetItem(ItemID); - if (Item) - reward_link = StringFormat("%c%06x%s%s%c", 0x12, ItemID, link_core, Item->Name, 0x12); - else - reward_link = ""; - } - else { - reward_link = ""; - } - - if(reward_link.length() != 0) - RewardText += reward_link.c_str(); - - safe_delete_array(link_core); + auto reward_link = linker.GenerateLink(); + RewardText += reward_link.c_str(); } else { RewardText += Tasks[TaskID]->Reward;