From d3ca93a9b83ce605d38db76f432ecbc1c1752e94 Mon Sep 17 00:00:00 2001 From: JadeShrineMaiden <69916714+JadeShrineMaiden@users.noreply.github.com> Date: Wed, 26 Aug 2020 18:40:10 +0100 Subject: [PATCH] Trading System (#43) * Sanity checks + Starting level changes - Item movement handler checks to make sure items aren't moved from equipment slot to equipment slot. - Item give command checks to make sure an out of bounds item is not spawned (Below iType 0 or above iType 8) - Players now begin at level 36, consequently the item give command does not level you up now. * Initial Trade Implementation * Taros and Trading * working trading system * Trading system code pointerified - It works with the recent pointer changes needed. --- src/CNLoginServer.cpp | 2 + src/ItemManager.cpp | 488 +++++++++++++++++++++++++++++++++++++++++- src/ItemManager.hpp | 9 + src/Player.hpp | 5 + src/PlayerManager.cpp | 1 + 5 files changed, 494 insertions(+), 11 deletions(-) diff --git a/src/CNLoginServer.cpp b/src/CNLoginServer.cpp index 1570ebc..5217c7d 100644 --- a/src/CNLoginServer.cpp +++ b/src/CNLoginServer.cpp @@ -85,6 +85,7 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) { int64_t UID = charInfo.sPC_Style.iPC_UID; loginSessions[sock].characters[UID] = Player(); loginSessions[sock].characters[UID].level = charInfo.iLevel; + loginSessions[sock].characters[UID].money = 9001; loginSessions[sock].characters[UID].slot = charInfo.iSlot; loginSessions[sock].characters[UID].FEKey = sock->getFEKey(); loginSessions[sock].characters[UID].x = charInfo.iX; @@ -213,6 +214,7 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) { loginSessions[sock].characters[UID] = Player(); loginSessions[sock].characters[UID].level = 36; + loginSessions[sock].characters[UID].money = 9001; loginSessions[sock].characters[UID].FEKey = sock->getFEKey(); loginSessions[sock].characters[UID].PCStyle = character->PCStyle; loginSessions[sock].characters[UID].PCStyle2.iAppearanceFlag = 1; diff --git a/src/ItemManager.cpp b/src/ItemManager.cpp index 67fff60..bb7b61c 100644 --- a/src/ItemManager.cpp +++ b/src/ItemManager.cpp @@ -8,6 +8,15 @@ void ItemManager::init() { REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_MOVE, itemMoveHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ITEM_DELETE, itemDeleteHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GIVE_ITEM, itemGMGiveHandler); + //Trade handlers + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_OFFER, itemTradeOfferHandler); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_OFFER_ACCEPT, itemTradeOfferAcceptHandler); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_OFFER_REFUSAL, itemTradeOfferRefusalHandler); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_CONFIRM, itemTradeConfirmHandler); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_CONFIRM_CANCEL, itemTradeConfirmCancelHandler); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_ITEM_REGISTER, itemTradeRegisterItemHandler); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_ITEM_UNREGISTER, itemTradeUnregisterItemHandler); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TRADE_CASH_REGISTER, itemTradeRegisterCashHandler); } void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) { @@ -137,16 +146,473 @@ void ItemManager::itemGMGiveHandler(CNSocket* sock, CNPacketData* data) { plr.plr->Inven[itemreq->iSlotNum] = itemreq->Item; sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_GIVE_ITEM_SUCC, sizeof(sP_FE2CL_REP_PC_GIVE_ITEM_SUCC)); - - // some items require a level, for now we're just going to bypass this by setting your level to 36 - //plr.plr->level = 36; - - //sP_FE2CL_REP_PC_CHANGE_LEVEL resp2; - - //resp2.iPC_ID = plr.plr->iID; - //resp2.iPC_Level = 36; - - //sock->sendPacket((void*)&resp2, P_FE2CL_REP_PC_CHANGE_LEVEL, sizeof(sP_FE2CL_REP_PC_CHANGE_LEVEL)); - // saving this for later use on a /level command } } + +void ItemManager::itemTradeOfferHandler(CNSocket* sock, CNPacketData* data) { + if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_OFFER)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_PC_TRADE_OFFER* pacdat = (sP_CL2FE_REQ_PC_TRADE_OFFER*)data->buf; + + int iID_Check; + + if (pacdat->iID_Request == pacdat->iID_From) { + iID_Check = pacdat->iID_To; + } else { + iID_Check = pacdat->iID_From; + } + + CNSocket* otherSock = sock; + + for (auto pair : PlayerManager::players) { + if (pair.second.plr->iID == iID_Check) { + otherSock = pair.first; + } + } + + INITSTRUCT(sP_FE2CL_REP_PC_TRADE_OFFER, resp); + + resp.iID_Request = pacdat->iID_Request; + resp.iID_From = pacdat->iID_From; + resp.iID_To = pacdat->iID_To; + + otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_OFFER, sizeof(sP_FE2CL_REP_PC_TRADE_OFFER)); +} + +void ItemManager::itemTradeOfferAcceptHandler(CNSocket* sock, CNPacketData* data) { + if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_OFFER_ACCEPT)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_PC_TRADE_OFFER_ACCEPT* pacdat = (sP_CL2FE_REQ_PC_TRADE_OFFER_ACCEPT*)data->buf; + + int iID_Check; + + if (pacdat->iID_Request == pacdat->iID_From) { + iID_Check = pacdat->iID_To; + } else { + iID_Check = pacdat->iID_From; + } + + CNSocket* otherSock = sock; + + for (auto pair : PlayerManager::players) { + if (pair.second.plr->iID == iID_Check) { + otherSock = pair.first; + } + } + + INITSTRUCT(sP_FE2CL_REP_PC_TRADE_OFFER, resp); + + resp.iID_Request = pacdat->iID_Request; + resp.iID_From = pacdat->iID_From; + resp.iID_To = pacdat->iID_To; + + // Clearing up trade slots + + PlayerView& plr = PlayerManager::players[sock]; + PlayerView& plr2 = PlayerManager::players[otherSock]; + + plr.plr->IsTradeConfirm = false; + plr2.plr->IsTradeConfirm = false; + + for (int i = 0; i < 5; i++) { + plr.plr->Trade[i].iID = 0; + plr.plr->Trade[i].iType = 0; + plr.plr->Trade[i].iOpt = 0; + plr.plr->Trade[i].iInvenNum = 0; + plr.plr->Trade[i].iSlotNum = 0; + } + + for (int i = 0; i < 5; i++) { + plr2.plr->Trade[i].iID = 0; + plr2.plr->Trade[i].iType = 0; + plr2.plr->Trade[i].iOpt = 0; + plr2.plr->Trade[i].iInvenNum = 0; + plr2.plr->Trade[i].iSlotNum = 0; + } + + otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_OFFER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_OFFER_SUCC)); +} + +void ItemManager::itemTradeOfferRefusalHandler(CNSocket* sock, CNPacketData* data) { + if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_OFFER_REFUSAL)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_PC_TRADE_OFFER_REFUSAL* pacdat = (sP_CL2FE_REQ_PC_TRADE_OFFER_REFUSAL*)data->buf; + INITSTRUCT(sP_FE2CL_REP_PC_TRADE_OFFER_REFUSAL, resp); + + resp.iID_Request = pacdat->iID_Request; + resp.iID_From = pacdat->iID_From; + resp.iID_To = pacdat->iID_To; + + int iID_Check; + + if (pacdat->iID_Request == pacdat->iID_From) { + iID_Check = pacdat->iID_To; + } else { + iID_Check = pacdat->iID_From; + } + + CNSocket* otherSock = sock; + + for (auto pair : PlayerManager::players) { + if (pair.second.plr->iID == iID_Check) { + otherSock = pair.first; + } + } + + otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_OFFER_REFUSAL, sizeof(sP_FE2CL_REP_PC_TRADE_OFFER_REFUSAL)); +} + +void ItemManager::itemTradeConfirmHandler(CNSocket* sock, CNPacketData* data) { + if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_CONFIRM)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_PC_TRADE_CONFIRM* pacdat = (sP_CL2FE_REQ_PC_TRADE_CONFIRM*)data->buf; + + int iID_Check; + + if (pacdat->iID_Request == pacdat->iID_From) { + iID_Check = pacdat->iID_To; + } else { + iID_Check = pacdat->iID_From; + } + + CNSocket* otherSock = sock; + + for (auto pair : PlayerManager::players) { + if (pair.second.plr->iID == iID_Check) { + otherSock = pair.first; + } + } + + PlayerView& plr = PlayerManager::players[sock]; + PlayerView& plr2 = PlayerManager::players[otherSock]; + + if (plr2.plr->IsTradeConfirm) { + + plr.plr->IsTrading = false; + plr2.plr->IsTrading = false; + plr.plr->IsTradeConfirm = false; + plr2.plr->IsTradeConfirm = false; + + // Check if we have enough free slots + int freeSlots = 0; + int freeSlotsNeeded = 0; + int freeSlots2 = 0; + int freeSlotsNeeded2 = 0; + + for (int i = 0; i < AINVEN_COUNT; i++) { + if (plr.plr->Inven[i].iID == 0) + freeSlots++; + } + + for (int i = 0; i < 5; i++) { + if (plr.plr->Trade[i].iID != 0) + freeSlotsNeeded++; + } + + for (int i = 0; i < AINVEN_COUNT; i++) { + if (plr2.plr->Inven[i].iID == 0) + freeSlots2++; + } + + for (int i = 0; i < 5; i++) { + if (plr2.plr->Trade[i].iID != 0) + freeSlotsNeeded2++; + } + + DEBUGLOG( + std::cout << "Slots Free and Needed:" << std::endl; + std::cout << "\tfreeSlots: " << (int)freeSlots << std::endl; + std::cout << "\tfreeSlotsNeeded: " << (int)freeSlotsNeeded << std::endl; + std::cout << "\tfreeSlots2: " << (int)freeSlots2 << std::endl; + std::cout << "\tfreeSlotsNeeded2: " << (int)freeSlotsNeeded2 << std::endl; + ) + + if (freeSlotsNeeded2 - freeSlotsNeeded > freeSlots) { + INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, resp); + + resp.iID_Request = pacdat->iID_Request; + resp.iID_From = pacdat->iID_From; + resp.iID_To = pacdat->iID_To; + + sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL)); + otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL)); + return; // Fail trade because of the lack of slots + } + + if (freeSlotsNeeded - freeSlotsNeeded2 > freeSlots2) { + INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, resp); + + resp.iID_Request = pacdat->iID_Request; + resp.iID_From = pacdat->iID_From; + resp.iID_To = pacdat->iID_To; + + sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL)); + otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL)); + return; // Fail trade because of the lack of slots + } + + INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CONFIRM, resp); + + resp.iID_Request = pacdat->iID_Request; + resp.iID_From = pacdat->iID_From; + resp.iID_To = pacdat->iID_To; + + sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM)); + // ^^ this is a must have or else the player won't accept a succ packet for some reason + + for (int i = 0; i < freeSlotsNeeded; i++) { + plr.plr->Inven[plr.plr->Trade[i].iInvenNum].iID = 0; + plr.plr->Inven[plr.plr->Trade[i].iInvenNum].iType = 0; + plr.plr->Inven[plr.plr->Trade[i].iInvenNum].iOpt = 0; + } + + for (int i = 0; i < freeSlotsNeeded2; i++) { + plr2.plr->Inven[plr2.plr->Trade[i].iInvenNum].iID = 0; + plr2.plr->Inven[plr2.plr->Trade[i].iInvenNum].iType = 0; + plr2.plr->Inven[plr2.plr->Trade[i].iInvenNum].iOpt = 0; + } + + for (int i = 0; i < AINVEN_COUNT; i++) { + if (freeSlotsNeeded <= 0) + break; + + if (plr2.plr->Inven[i].iID == 0) { + + plr2.plr->Inven[i].iID = plr.plr->Trade[freeSlotsNeeded - 1].iID; + plr2.plr->Inven[i].iType = plr.plr->Trade[freeSlotsNeeded - 1].iType; + plr2.plr->Inven[i].iOpt = plr.plr->Trade[freeSlotsNeeded - 1].iOpt; + plr.plr->Trade[freeSlotsNeeded - 1].iInvenNum = i; + DEBUGLOG( + std::cout << "Player 1 Trade Item #" << (int)freeSlotsNeeded << std::endl; + std::cout << "\tiID: " << (int)plr.plr->Trade[freeSlotsNeeded - 1].iID << std::endl; + std::cout << "\tiType: " << (int)plr.plr->Trade[freeSlotsNeeded - 1].iType << std::endl; + std::cout << "\tiOpt: " << (int)plr.plr->Trade[freeSlotsNeeded - 1].iOpt << std::endl; + std::cout << "\tiInvenNum: " << (int)plr.plr->Trade[freeSlotsNeeded - 1].iInvenNum << std::endl; + std::cout << "\tiSlotNum: " << (int)plr.plr->Trade[freeSlotsNeeded - 1].iSlotNum << std::endl; + std::cout << "\t added item " << (int)plr2.plr->Inven[i].iID << " to slot " << (int)i << std::endl; + ) + freeSlotsNeeded--; + } + } + + for (int i = 0; i < AINVEN_COUNT; i++) { + if (freeSlotsNeeded2 <= 0) + break; + + if (plr.plr->Inven[i].iID == 0) { + + plr.plr->Inven[i].iID = plr2.plr->Trade[freeSlotsNeeded2 - 1].iID; + plr.plr->Inven[i].iType = plr2.plr->Trade[freeSlotsNeeded2 - 1].iType; + plr.plr->Inven[i].iOpt = plr2.plr->Trade[freeSlotsNeeded2 - 1].iOpt; + plr2.plr->Trade[freeSlotsNeeded2 - 1].iInvenNum = i; + DEBUGLOG( + std::cout << "Player 2 Trade Item #" << (int)freeSlotsNeeded2 << std::endl; + std::cout << "\tiID: " << (int)plr2.plr->Trade[freeSlotsNeeded2 - 1].iID << std::endl; + std::cout << "\tiType: " << (int)plr2.plr->Trade[freeSlotsNeeded2 - 1].iType << std::endl; + std::cout << "\tiOpt: " << (int)plr2.plr->Trade[freeSlotsNeeded2 - 1].iOpt << std::endl; + std::cout << "\tiInvenNum: " << (int)plr2.plr->Trade[freeSlotsNeeded2 - 1].iInvenNum << std::endl; + std::cout << "\tiSlotNum: " << (int)plr2.plr->Trade[freeSlotsNeeded2 - 1].iSlotNum << std::endl; + std::cout << "\t added item " << (int)plr.plr->Inven[i].iID << " to slot " << (int)i << std::endl; + ) + freeSlotsNeeded2--; + } + } + + INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CONFIRM_SUCC, resp2); + + resp2.iID_Request = pacdat->iID_Request; + resp2.iID_From = pacdat->iID_From; + resp2.iID_To = pacdat->iID_To; + + plr.plr->money = plr.plr->money + plr2.plr->moneyInTrade - plr.plr->moneyInTrade; + resp2.iCandy = plr.plr->money; + + memcpy(resp2.Item, plr2.plr->Trade, sizeof(plr2.plr->Trade)); + memcpy(resp2.ItemStay, plr.plr->Trade, sizeof(plr.plr->Trade)); + + sock->sendPacket((void*)&resp2, P_FE2CL_REP_PC_TRADE_CONFIRM_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_SUCC)); + + plr2.plr->money = plr2.plr->money + plr.plr->moneyInTrade - plr2.plr->moneyInTrade; + resp2.iCandy = plr2.plr->money; + + memcpy(resp2.Item, plr.plr->Trade, sizeof(plr.plr->Trade)); + memcpy(resp2.ItemStay, plr2.plr->Trade, sizeof(plr2.plr->Trade)); + + otherSock->sendPacket((void*)&resp2, P_FE2CL_REP_PC_TRADE_CONFIRM_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_SUCC)); + } else { + + INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CONFIRM, resp); + + resp.iID_Request = pacdat->iID_Request; + resp.iID_From = pacdat->iID_From; + resp.iID_To = pacdat->iID_To; + + plr.plr->IsTradeConfirm = true; + + sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM)); + otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM)); + } +} + +void ItemManager::itemTradeConfirmCancelHandler(CNSocket* sock, CNPacketData* data) { + if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_CONFIRM_CANCEL)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_PC_TRADE_CONFIRM_CANCEL* pacdat = (sP_CL2FE_REQ_PC_TRADE_CONFIRM_CANCEL*)data->buf; + INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, resp); + + resp.iID_Request = pacdat->iID_Request; + resp.iID_From = pacdat->iID_From; + resp.iID_To = pacdat->iID_To; + + int iID_Check; + + if (pacdat->iID_Request == pacdat->iID_From) { + iID_Check = pacdat->iID_To; + } else { + iID_Check = pacdat->iID_From; + } + + CNSocket* otherSock = sock; + + for (auto pair : PlayerManager::players) { + if (pair.second.plr->iID == iID_Check) { + otherSock = pair.first; + } + } + + PlayerView& plr = PlayerManager::players[sock]; + + plr.plr->IsTradeConfirm = false; + + otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL, sizeof(sP_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL)); +} + +void ItemManager::itemTradeRegisterItemHandler(CNSocket* sock, CNPacketData* data) { + if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_ITEM_REGISTER)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_PC_TRADE_ITEM_REGISTER* pacdat = (sP_CL2FE_REQ_PC_TRADE_ITEM_REGISTER*)data->buf; + + if (pacdat->Item.iSlotNum < 0 || pacdat->Item.iSlotNum > 4) + return; // sanity check + + INITSTRUCT(sP_FE2CL_REP_PC_TRADE_ITEM_REGISTER_SUCC, resp); + + resp.iID_Request = pacdat->iID_Request; + resp.iID_From = pacdat->iID_From; + resp.iID_To = pacdat->iID_To; + resp.TradeItem = pacdat->Item; + resp.InvenItem = pacdat->Item; + + int iID_Check; + + if (pacdat->iID_Request == pacdat->iID_From) { + iID_Check = pacdat->iID_To; + } else { + iID_Check = pacdat->iID_From; + } + + CNSocket* otherSock = sock; + + for (auto pair : PlayerManager::players) { + if (pair.second.plr->iID == iID_Check) { + otherSock = pair.first; + } + } + + PlayerView& plr = PlayerManager::players[sock]; + plr.plr->Trade[pacdat->Item.iSlotNum] = pacdat->Item; + + sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_ITEM_REGISTER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_ITEM_REGISTER_SUCC)); + otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_ITEM_REGISTER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_ITEM_REGISTER_SUCC)); +} + +void ItemManager::itemTradeUnregisterItemHandler(CNSocket* sock, CNPacketData* data) { + if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_ITEM_UNREGISTER)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_PC_TRADE_ITEM_UNREGISTER* pacdat = (sP_CL2FE_REQ_PC_TRADE_ITEM_UNREGISTER*)data->buf; + INITSTRUCT(sP_FE2CL_REP_PC_TRADE_ITEM_UNREGISTER_SUCC, resp); + + resp.iID_Request = pacdat->iID_Request; + resp.iID_From = pacdat->iID_From; + resp.iID_To = pacdat->iID_To; + resp.TradeItem = pacdat->Item; + + PlayerView& plr = PlayerManager::players[sock]; + resp.InvenItem = plr.plr->Trade[pacdat->Item.iSlotNum]; + + int iID_Check; + + if (pacdat->iID_Request == pacdat->iID_From) { + iID_Check = pacdat->iID_To; + } else { + iID_Check = pacdat->iID_From; + } + + CNSocket* otherSock = sock; + + for (auto pair : PlayerManager::players) { + if (pair.second.plr->iID == iID_Check) { + otherSock = pair.first; + } + } + + int temp_num = pacdat->Item.iSlotNum; + + if (temp_num >= 0 && temp_num <= 4) { + plr.plr->Trade[temp_num].iID = 0; + plr.plr->Trade[temp_num].iType = 0; + plr.plr->Trade[temp_num].iOpt = 0; + plr.plr->Trade[temp_num].iInvenNum = 0; + plr.plr->Trade[temp_num].iSlotNum = 0; + } + + sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_ITEM_UNREGISTER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_ITEM_UNREGISTER_SUCC)); + otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_ITEM_UNREGISTER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_ITEM_UNREGISTER_SUCC)); +} + +void ItemManager::itemTradeRegisterCashHandler(CNSocket* sock, CNPacketData* data) { + if (data->size != sizeof(sP_CL2FE_REQ_PC_TRADE_CASH_REGISTER)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_PC_TRADE_CASH_REGISTER* pacdat = (sP_CL2FE_REQ_PC_TRADE_CASH_REGISTER*)data->buf; + + if (pacdat->iCandy < 0) + return; // famous glitch, begone + + INITSTRUCT(sP_FE2CL_REP_PC_TRADE_CASH_REGISTER_SUCC, resp); + + resp.iID_Request = pacdat->iID_Request; + resp.iID_From = pacdat->iID_From; + resp.iID_To = pacdat->iID_To; + resp.iCandy = pacdat->iCandy; + + int iID_Check; + + if (pacdat->iID_Request == pacdat->iID_From) { + iID_Check = pacdat->iID_To; + } else { + iID_Check = pacdat->iID_From; + } + + CNSocket* otherSock = sock; + + for (auto pair : PlayerManager::players) { + if (pair.second.plr->iID == iID_Check) { + otherSock = pair.first; + } + } + + PlayerView& plr = PlayerManager::players[sock]; + + plr.plr->moneyInTrade = pacdat->iCandy; + + sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CASH_REGISTER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_CASH_REGISTER_SUCC)); + otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_TRADE_CASH_REGISTER_SUCC, sizeof(sP_FE2CL_REP_PC_TRADE_CASH_REGISTER_SUCC)); +} diff --git a/src/ItemManager.hpp b/src/ItemManager.hpp index f87576b..197b863 100644 --- a/src/ItemManager.hpp +++ b/src/ItemManager.hpp @@ -7,4 +7,13 @@ namespace ItemManager { void itemMoveHandler(CNSocket* sock, CNPacketData* data); void itemDeleteHandler(CNSocket* sock, CNPacketData* data); void itemGMGiveHandler(CNSocket* sock, CNPacketData* data); + void itemTradeOfferHandler(CNSocket* sock, CNPacketData* data); + //void itemTradeOfferCancel(CNSocket* sock, CNPacketData* data); + void itemTradeOfferAcceptHandler(CNSocket* sock, CNPacketData* data); + void itemTradeOfferRefusalHandler(CNSocket* sock, CNPacketData* data); + void itemTradeConfirmHandler(CNSocket* sock, CNPacketData* data); + void itemTradeConfirmCancelHandler(CNSocket* sock, CNPacketData* data); + void itemTradeRegisterItemHandler(CNSocket* sock, CNPacketData* data); + void itemTradeUnregisterItemHandler(CNSocket* sock, CNPacketData* data); + void itemTradeRegisterCashHandler(CNSocket* sock, CNPacketData* data); } diff --git a/src/Player.hpp b/src/Player.hpp index 2570c99..c228b91 100644 --- a/src/Player.hpp +++ b/src/Player.hpp @@ -14,6 +14,7 @@ struct Player { int level; int HP; int slot; // player slot, not nano slot + int32_t money; sPCStyle PCStyle; sPCStyle2 PCStyle2; sNano Nanos[37]; // acquired nanos @@ -24,5 +25,9 @@ struct Player { int x, y, z, angle; sItemBase Equip[AEQUIP_COUNT]; sItemBase Inven[AINVEN_COUNT]; + sItemTrade Trade[12]; + int32_t moneyInTrade; + bool IsTrading; + bool IsTradeConfirm; bool IsGM; }; diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index 3085521..4d6c256 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -196,6 +196,7 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) { response.PCLoadData2CL.iUserLevel = 1; response.PCLoadData2CL.iHP = 3625; //TODO: Check player levelupdata and get this right response.PCLoadData2CL.iLevel = plr.level; + response.PCLoadData2CL.iCandy = plr.money; response.PCLoadData2CL.iMentor = 1; response.PCLoadData2CL.iMentorCount = 4; response.PCLoadData2CL.iMapNum = 0;