From 04c56ce426535b0296632abf8a73844147d1e175 Mon Sep 17 00:00:00 2001 From: dongresource Date: Tue, 16 Mar 2021 21:08:08 +0100 Subject: [PATCH] [refactor] Move Croc Pot logic to Vendor.cpp --- src/ItemManager.cpp | 97 --------------------------------------------- src/Vendor.cpp | 96 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 97 deletions(-) diff --git a/src/ItemManager.cpp b/src/ItemManager.cpp index f0c0ed8..bef57a2 100644 --- a/src/ItemManager.cpp +++ b/src/ItemManager.cpp @@ -348,101 +348,6 @@ void itemBankOpenHandler(CNSocket* sock, CNPacketData* data) { sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_BANK_OPEN_SUCC, sizeof(sP_FE2CL_REP_PC_BANK_OPEN_SUCC)); } -void itemCombineHandler(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_REQ_PC_ITEM_COMBINATION)) - return; // malformed packet - - sP_CL2FE_REQ_PC_ITEM_COMBINATION* req = (sP_CL2FE_REQ_PC_ITEM_COMBINATION*)data->buf; - Player* plr = PlayerManager::getPlayer(sock); - - // prepare fail packet - INITSTRUCT(sP_FE2CL_REP_PC_ITEM_COMBINATION_FAIL, failResp); - failResp.iCostumeItemSlot = req->iCostumeItemSlot; - failResp.iStatItemSlot = req->iStatItemSlot; - failResp.iErrorCode = 0; - - // sanity check slot indices - if (req->iCostumeItemSlot < 0 || req->iCostumeItemSlot >= AINVEN_COUNT || req->iStatItemSlot < 0 || req->iStatItemSlot >= AINVEN_COUNT) { - std::cout << "[WARN] Inventory slot(s) out of range (" << req->iStatItemSlot << " and " << req->iCostumeItemSlot << ")" << std::endl; - sock->sendPacket((void*)&failResp, P_FE2CL_REP_PC_ITEM_COMBINATION_FAIL, sizeof(sP_FE2CL_REP_PC_ITEM_COMBINATION_FAIL)); - return; - } - - sItemBase* itemStats = &plr->Inven[req->iStatItemSlot]; - sItemBase* itemLooks = &plr->Inven[req->iCostumeItemSlot]; - ItemManager::Item* itemStatsDat = ItemManager::getItemData(itemStats->iID, itemStats->iType); - ItemManager::Item* itemLooksDat = ItemManager::getItemData(itemLooks->iID, itemLooks->iType); - - // sanity check item and combination entry existence - if (itemStatsDat == nullptr || itemLooksDat == nullptr - || ItemManager::CrocPotTable.find(abs(itemStatsDat->level - itemLooksDat->level)) == ItemManager::CrocPotTable.end()) { - std::cout << "[WARN] Either item ids or croc pot value set not found" << std::endl; - sock->sendPacket((void*)&failResp, P_FE2CL_REP_PC_ITEM_COMBINATION_FAIL, sizeof(sP_FE2CL_REP_PC_ITEM_COMBINATION_FAIL)); - return; - } - - // sanity check matching item types - if (itemStats->iType != itemLooks->iType - || (itemStats->iType == 0 && itemStatsDat->weaponType != itemLooksDat->weaponType)) { - std::cout << "[WARN] Player attempted to combine mismatched items" << std::endl; - sock->sendPacket((void*)&failResp, P_FE2CL_REP_PC_ITEM_COMBINATION_FAIL, sizeof(sP_FE2CL_REP_PC_ITEM_COMBINATION_FAIL)); - return; - } - - CrocPotEntry* recipe = &ItemManager::CrocPotTable[abs(itemStatsDat->level - itemLooksDat->level)]; - int cost = itemStatsDat->buyPrice * recipe->multStats + itemLooksDat->buyPrice * recipe->multLooks; - float successChance = recipe->base / 100.0f; // base success chance - - // rarity gap multiplier - switch (abs(itemStatsDat->rarity - itemLooksDat->rarity)) { - case 0: - successChance *= recipe->rd0; - break; - case 1: - successChance *= recipe->rd1; - break; - case 2: - successChance *= recipe->rd2; - break; - case 3: - successChance *= recipe->rd3; - break; - default: - break; - } - - float rolled = (rand() * 1.0f / RAND_MAX) * 100.0f; // success chance out of 100 - //std::cout << rolled << " vs " << successChance << std::endl; - plr->money -= cost; - - - INITSTRUCT(sP_FE2CL_REP_PC_ITEM_COMBINATION_SUCC, resp); - if (rolled < successChance) { - // success - resp.iSuccessFlag = 1; - - // modify the looks item with the new stats and set the appearance through iOpt - itemLooks->iOpt = (int32_t)((itemLooks->iOpt) >> 16 > 0 ? (itemLooks->iOpt >> 16) : itemLooks->iID) << 16; - itemLooks->iID = itemStats->iID; - - // delete stats item - itemStats->iID = 0; - itemStats->iOpt = 0; - itemStats->iTimeLimit = 0; - itemStats->iType = 0; - } - else { - // failure; don't do anything? - resp.iSuccessFlag = 0; - } - resp.iCandy = plr->money; - resp.iNewItemSlot = req->iCostumeItemSlot; - resp.iStatItemSlot = req->iStatItemSlot; - resp.sNewItem = *itemLooks; - - sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_ITEM_COMBINATION_SUCC, sizeof(sP_FE2CL_REP_PC_ITEM_COMBINATION_SUCC)); -} - void chestOpenHandler(CNSocket *sock, CNPacketData *data) { if (data->size != sizeof(sP_CL2FE_REQ_ITEM_CHEST_OPEN)) return; // ignore the malformed packet @@ -900,6 +805,4 @@ void ItemManager::init() { // Bank REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_BANK_OPEN, itemBankOpenHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_CHEST_OPEN, chestOpenHandler); - // Croc Pot - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ITEM_COMBINATION, itemCombineHandler); } diff --git a/src/Vendor.cpp b/src/Vendor.cpp index 70426e8..d561368 100644 --- a/src/Vendor.cpp +++ b/src/Vendor.cpp @@ -284,6 +284,101 @@ void Vendor::vendorBuyBattery(CNSocket* sock, CNPacketData* data) { sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_VENDOR_BATTERY_BUY_SUCC, sizeof(sP_FE2CL_REP_PC_VENDOR_BATTERY_BUY_SUCC)); } +void vendorCombineItems(CNSocket* sock, CNPacketData* data) { + if (data->size != sizeof(sP_CL2FE_REQ_PC_ITEM_COMBINATION)) + return; // malformed packet + + sP_CL2FE_REQ_PC_ITEM_COMBINATION* req = (sP_CL2FE_REQ_PC_ITEM_COMBINATION*)data->buf; + Player* plr = PlayerManager::getPlayer(sock); + + // prepare fail packet + INITSTRUCT(sP_FE2CL_REP_PC_ITEM_COMBINATION_FAIL, failResp); + failResp.iCostumeItemSlot = req->iCostumeItemSlot; + failResp.iStatItemSlot = req->iStatItemSlot; + failResp.iErrorCode = 0; + + // sanity check slot indices + if (req->iCostumeItemSlot < 0 || req->iCostumeItemSlot >= AINVEN_COUNT || req->iStatItemSlot < 0 || req->iStatItemSlot >= AINVEN_COUNT) { + std::cout << "[WARN] Inventory slot(s) out of range (" << req->iStatItemSlot << " and " << req->iCostumeItemSlot << ")" << std::endl; + sock->sendPacket((void*)&failResp, P_FE2CL_REP_PC_ITEM_COMBINATION_FAIL, sizeof(sP_FE2CL_REP_PC_ITEM_COMBINATION_FAIL)); + return; + } + + sItemBase* itemStats = &plr->Inven[req->iStatItemSlot]; + sItemBase* itemLooks = &plr->Inven[req->iCostumeItemSlot]; + ItemManager::Item* itemStatsDat = ItemManager::getItemData(itemStats->iID, itemStats->iType); + ItemManager::Item* itemLooksDat = ItemManager::getItemData(itemLooks->iID, itemLooks->iType); + + // sanity check item and combination entry existence + if (itemStatsDat == nullptr || itemLooksDat == nullptr + || ItemManager::CrocPotTable.find(abs(itemStatsDat->level - itemLooksDat->level)) == ItemManager::CrocPotTable.end()) { + std::cout << "[WARN] Either item ids or croc pot value set not found" << std::endl; + sock->sendPacket((void*)&failResp, P_FE2CL_REP_PC_ITEM_COMBINATION_FAIL, sizeof(sP_FE2CL_REP_PC_ITEM_COMBINATION_FAIL)); + return; + } + + // sanity check matching item types + if (itemStats->iType != itemLooks->iType + || (itemStats->iType == 0 && itemStatsDat->weaponType != itemLooksDat->weaponType)) { + std::cout << "[WARN] Player attempted to combine mismatched items" << std::endl; + sock->sendPacket((void*)&failResp, P_FE2CL_REP_PC_ITEM_COMBINATION_FAIL, sizeof(sP_FE2CL_REP_PC_ITEM_COMBINATION_FAIL)); + return; + } + + CrocPotEntry* recipe = &ItemManager::CrocPotTable[abs(itemStatsDat->level - itemLooksDat->level)]; + int cost = itemStatsDat->buyPrice * recipe->multStats + itemLooksDat->buyPrice * recipe->multLooks; + float successChance = recipe->base / 100.0f; // base success chance + + // rarity gap multiplier + switch (abs(itemStatsDat->rarity - itemLooksDat->rarity)) { + case 0: + successChance *= recipe->rd0; + break; + case 1: + successChance *= recipe->rd1; + break; + case 2: + successChance *= recipe->rd2; + break; + case 3: + successChance *= recipe->rd3; + break; + default: + break; + } + + float rolled = (rand() * 1.0f / RAND_MAX) * 100.0f; // success chance out of 100 + //std::cout << rolled << " vs " << successChance << std::endl; + plr->money -= cost; + + + INITSTRUCT(sP_FE2CL_REP_PC_ITEM_COMBINATION_SUCC, resp); + if (rolled < successChance) { + // success + resp.iSuccessFlag = 1; + + // modify the looks item with the new stats and set the appearance through iOpt + itemLooks->iOpt = (int32_t)((itemLooks->iOpt) >> 16 > 0 ? (itemLooks->iOpt >> 16) : itemLooks->iID) << 16; + itemLooks->iID = itemStats->iID; + + // delete stats item + itemStats->iID = 0; + itemStats->iOpt = 0; + itemStats->iTimeLimit = 0; + itemStats->iType = 0; + } + else { + // failure; don't do anything? + resp.iSuccessFlag = 0; + } + resp.iCandy = plr->money; + resp.iNewItemSlot = req->iCostumeItemSlot; + resp.iStatItemSlot = req->iStatItemSlot; + resp.sNewItem = *itemLooks; + + sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_ITEM_COMBINATION_SUCC, sizeof(sP_FE2CL_REP_PC_ITEM_COMBINATION_SUCC)); +} + void Vendor::init() { REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VENDOR_START, vendorStart); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VENDOR_TABLE_UPDATE, vendorTable); @@ -291,4 +386,5 @@ void Vendor::init() { REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VENDOR_ITEM_SELL, vendorSell); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VENDOR_ITEM_RESTORE_BUY, vendorBuyback); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VENDOR_BATTERY_BUY, vendorBuyBattery); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ITEM_COMBINATION, vendorCombineItems); }