From c91022030c9fb33fe931f13047f3e3e7698ee61e Mon Sep 17 00:00:00 2001 From: Gent Date: Mon, 14 Sep 2020 00:25:14 -0400 Subject: [PATCH] Load item tables + price implementation --- src/ItemManager.cpp | 9 +++++++++ src/ItemManager.hpp | 9 ++++++++- src/NPCManager.cpp | 17 ++++++++++++----- src/TableData.cpp | 16 +++++++++++++++- 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/ItemManager.cpp b/src/ItemManager.cpp index 05e6696..f45bb58 100644 --- a/src/ItemManager.cpp +++ b/src/ItemManager.cpp @@ -7,6 +7,7 @@ #include // for memset() and memcmp() #include +std::map, Item> ItemManager::ItemData; std::map> ItemManager::VendorTables; void ItemManager::init() { @@ -749,3 +750,11 @@ int ItemManager::findFreeSlot(Player *plr) { // not found return -1; } + +bool ItemManager::isItemRegistered(int32_t id, int32_t type) { + return ItemData.find(std::pair(id, type)) != ItemData.end(); +} + +Item ItemManager::getItemData(int32_t id, int32_t type) { + return ItemData[std::pair(id, type)]; +} diff --git a/src/ItemManager.hpp b/src/ItemManager.hpp index 66c9545..00bd4b5 100644 --- a/src/ItemManager.hpp +++ b/src/ItemManager.hpp @@ -3,8 +3,12 @@ #include "CNShardServer.hpp" #include "Player.hpp" +struct Item { + bool tradeable, sellable; + int buyPrice, sellPrice, stackSize, level; // TODO: implement more as needed +}; struct VendorListing { - int sort, type, iID, price; + int sort, type, iID; }; namespace ItemManager { @@ -14,6 +18,7 @@ namespace ItemManager { BANK = 3 }; // hopefully this is fine since it's never modified after load + extern std::map, Item> ItemData; // -> data extern std::map> VendorTables; void init(); @@ -36,4 +41,6 @@ namespace ItemManager { void chestOpenHandler(CNSocket* sock, CNPacketData* data); int findFreeSlot(Player *plr); + bool isItemRegistered(int32_t id, int32_t type); + Item getItemData(int32_t id, int32_t type); } diff --git a/src/NPCManager.cpp b/src/NPCManager.cpp index d1876ab..7ddfb6d 100644 --- a/src/NPCManager.cpp +++ b/src/NPCManager.cpp @@ -31,10 +31,17 @@ void NPCManager::npcVendorBuy(CNSocket* sock, CNPacketData* data) { sP_CL2FE_REQ_PC_VENDOR_ITEM_BUY* req = (sP_CL2FE_REQ_PC_VENDOR_ITEM_BUY*)data->buf; Player *plr = PlayerManager::getPlayer(sock); - int itemCost = 100; // TODO: placeholder, look up the price of item + if (!ItemManager::isItemRegistered(req->Item.iID, req->Item.iType)) { + std::cout << "[WARN] Item id " << req->Item.iID << " with type " << req->Item.iType << " not found" << std::endl; + // NOTE: VENDOR_ITEM_BUY_FAIL is not actually handled client-side. + INITSTRUCT(sP_FE2CL_REP_PC_VENDOR_ITEM_BUY_FAIL, failResp); + failResp.iErrorCode = 0; + sock->sendPacket((void*)&failResp, P_FE2CL_REP_PC_VENDOR_ITEM_BUY_FAIL, sizeof(sP_FE2CL_REP_PC_VENDOR_ITEM_BUY_FAIL)); + return; + } + int itemCost = ItemManager::getItemData(req->Item.iID, req->Item.iType).buyPrice; int slot = ItemManager::findFreeSlot(plr); - if (itemCost > plr->money || slot == -1) { // NOTE: VENDOR_ITEM_BUY_FAIL is not actually handled client-side. INITSTRUCT(sP_FE2CL_REP_PC_VENDOR_ITEM_BUY_FAIL, failResp); @@ -78,8 +85,8 @@ void NPCManager::npcVendorSell(CNSocket* sock, CNPacketData* data) { sItemBase* item = &plr->Inven[req->iInvenSlotNum]; INITSTRUCT(sP_FE2CL_REP_PC_VENDOR_ITEM_SELL_SUCC, resp); - - int sellValue = 100 * req->iItemCnt; // TODO: lookup item price + + int sellValue = ItemManager::getItemData(item->iID, item->iType).sellPrice * req->iItemCnt; // TODO: lookup item price // increment taros plr->money = plr->money + sellValue; @@ -124,7 +131,7 @@ void NPCManager::npcVendorTable(CNSocket* sock, CNPacketData* data) { vItem.item = base; vItem.iSortNum = listings[i].sort; vItem.iVendorID = req->iVendorID; - vItem.fBuyCost = listings[i].price; + //vItem.fBuyCost = listings[i].price; resp.item[i] = vItem; } diff --git a/src/TableData.cpp b/src/TableData.cpp index 711a4fa..587e2f4 100644 --- a/src/TableData.cpp +++ b/src/TableData.cpp @@ -121,11 +121,25 @@ void TableData::init() { std::cout << "[INFO] Loaded mission-related data" << std::endl; + // load all item data. i'm sorry. it has to be done + const char* setNames[10] = { "m_pBackItemTable", "m_pFaceItemTable", "m_pGlassItemTable", "m_pHatItemTable", + "m_pHeadItemTable", "m_pPantsItemTable", "m_pShirtsItemTable", "m_pShoesItemTable", "m_pWeaponItemTable", + "m_pVehicleItemTable"}; + nlohmann::json itemSet; + for (int i = 0; i < 10; i++) { + itemSet = xdtData[setNames[i]]["m_pItemData"]; + for (nlohmann::json::iterator item = itemSet.begin(); item != itemSet.end(); item++) + ItemManager::ItemData[std::pair(item.value()["m_iItemNumber"], item.value()["m_iEquipLoc"])] + = { item.value()["m_iTradeAble"] == 1, item.value()["m_iSellAble"] == 1, item.value()["m_iItemPrice"], item.value()["m_iItemSellPrice"], item.value()["m_iStackNumber"], item.value()["m_iMinReqLev"] }; + } + + std::cout << "[INFO] Loaded " << ItemManager::ItemData.size() << " items" << std::endl; + // load vendor listings nlohmann::json listings = xdtData["m_pVendorTable"]["m_pItemData"]; for (nlohmann::json::iterator listing = listings.begin(); listing != listings.end(); listing++) { - VendorListing vListing = {listing.value()["m_iSortNumber"], listing.value()["m_iItemType"], listing.value()["m_iitemID"], listing.value()["m_iSellCost"]}; + VendorListing vListing = { listing.value()["m_iSortNumber"], listing.value()["m_iItemType"], listing.value()["m_iitemID"] }; ItemManager::VendorTables[listing.value()["m_iNpcNumber"]].push_back(vListing); }