From ae654f996c5e86ff941b9f2bc9c13c623726d438 Mon Sep 17 00:00:00 2001 From: dongresource Date: Thu, 10 Sep 2020 00:31:09 +0200 Subject: [PATCH] [WIP] Incremental mission save 1 This commit (and the next one) exist to document the first approach I took to storing mission data. It's only here for posterity. This comment was added while rebasing. --- src/MissionManager.cpp | 51 ++++++++++++++++++++++++++++++++++++++++-- src/MissionManager.hpp | 26 ++++++++++++++++++++- src/PlayerManager.cpp | 2 +- src/TableData.cpp | 20 ++++++++++++++++- 4 files changed, 94 insertions(+), 5 deletions(-) diff --git a/src/MissionManager.cpp b/src/MissionManager.cpp index b28a974..078c63a 100644 --- a/src/MissionManager.cpp +++ b/src/MissionManager.cpp @@ -5,10 +5,12 @@ #include "ItemManager.hpp" std::map MissionManager::Rewards; +std::map MissionManager::SUItems; +std::map MissionManager::QuestDropSets; void MissionManager::init() { REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TASK_START, acceptMission); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TASK_END, completeMission); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TASK_END, completeTask); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_SET_CURRENT_MISSION_ID, setMission); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TASK_STOP, quitMission); } @@ -24,7 +26,7 @@ void MissionManager::acceptMission(CNSocket* sock, CNPacketData* data) { sock->sendPacket((void*)&response, P_FE2CL_REP_PC_TASK_START_SUCC, sizeof(sP_FE2CL_REP_PC_TASK_START_SUCC)); } -void MissionManager::completeMission(CNSocket* sock, CNPacketData* data) { +void MissionManager::completeTask(CNSocket* sock, CNPacketData* data) { if (data->size != sizeof(sP_CL2FE_REQ_PC_TASK_END)) return; // malformed packet @@ -33,7 +35,50 @@ void MissionManager::completeMission(CNSocket* sock, CNPacketData* data) { Player *plr = PlayerManager::getPlayer(sock); response.iTaskNum = missionData->iTaskNum; + std::cout << missionData->iTaskNum << std::endl; + /* + * SUItems + * + * Some mission tasks give the player a quest item upon completion. + * This is distinct from quest item mob drops. + * They can be identified by a counter in the task indicator (ie. 1/1 Gravity Decelerator). + * The server is responsible for dropping the correct item. + * Yes, this is idiotic. + */ + if (SUItems.find(missionData->iTaskNum) != SUItems.end()) { + SUItem *suitem = SUItems[missionData->iTaskNum]; + + const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); + assert(resplen < CN_PACKET_BUFFER_SIZE); + // we know it's only one trailing struct, so we can skip full validation + + uint8_t respbuf[resplen]; // not a variable length array, don't worry + sP_FE2CL_REP_REWARD_ITEM *reward = (sP_FE2CL_REP_REWARD_ITEM *)respbuf; + sItemReward *item = (sItemReward *)(respbuf + sizeof(sP_FE2CL_REP_REWARD_ITEM)); + + // don't forget to zero the buffer! + memset(respbuf, 0, resplen); + + reward->m_iCandy = plr->money; + reward->m_iFusionMatter = plr->fusionmatter; + reward->iFatigue = 100; // prevents warning message + reward->iFatigue_Level = 1; + reward->iItemCnt = 1; // remember to update resplen if you change this + reward->iTaskID = missionData->iTaskNum; + reward->iNPC_TypeID = 0; // XXX + + item->sItem.iType = 8; + item->sItem.iID = suitem->itemIds[0]; // XXX XXX XXX + item->sItem.iOpt = 1; // XXX count needs to be correct + item->iSlotNum = 0; // XXX + item->eIL = 2; + + std::cout << "sending item packet\n"; + sock->sendPacket((void*)respbuf, P_FE2CL_REP_REWARD_ITEM, resplen); + } + + // mission rewards if (Rewards.find(missionData->iTaskNum) == Rewards.end()) { // not a mission's final task sock->sendPacket((void*)&response, P_FE2CL_REP_PC_TASK_END_SUCC, sizeof(sP_FE2CL_REP_PC_TASK_END_SUCC)); @@ -117,3 +162,5 @@ void MissionManager::quitMission(CNSocket* sock, CNPacketData* data) { response.iTaskNum = missionData->iTaskNum; sock->sendPacket((void*)&response, P_FE2CL_REP_PC_TASK_STOP_SUCC, sizeof(sP_FE2CL_REP_PC_TASK_STOP_SUCC)); } + +//void MissionManager::dropQuestItem(CNSocket *sock, int mobid, int count) {} diff --git a/src/MissionManager.hpp b/src/MissionManager.hpp index def2552..81e8449 100644 --- a/src/MissionManager.hpp +++ b/src/MissionManager.hpp @@ -20,12 +20,36 @@ struct Reward { }; }; +struct SUItem { + int32_t itemIds[3]; + + SUItem(nlohmann::json ids) { + for (int i = 0; i < 3; i++) { + itemIds[i] = ids[i]; + } + } +}; + +struct QuestDropSet { + int32_t mobIds[3]; + int32_t itemIds[3]; + + QuestDropSet(nlohmann::json mobs, nlohmann::json items) { + for (int i = 0; i < 3; i++) { + mobIds[i] = mobs[i]; + itemIds[i] = items[i]; + } + } +}; + namespace MissionManager { extern std::map Rewards; + extern std::map SUItems; + extern std::map QuestDropSets; void init(); void acceptMission(CNSocket* sock, CNPacketData* data); - void completeMission(CNSocket* sock, CNPacketData* data); + void completeTask(CNSocket* sock, CNPacketData* data); void setMission(CNSocket* sock, CNPacketData* data); void quitMission(CNSocket* sock, CNPacketData* data); } diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index 5d64db5..1233e9f 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -198,7 +198,7 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) { 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.iMentor = 5; // Computress response.PCLoadData2CL.iMentorCount = 4; response.PCLoadData2CL.iMapNum = 0; response.PCLoadData2CL.iX = plr.x; diff --git a/src/TableData.cpp b/src/TableData.cpp index 4a49cb9..82ee372 100644 --- a/src/TableData.cpp +++ b/src/TableData.cpp @@ -63,14 +63,15 @@ void TableData::init() { } // load everything else from xdttable + std::cout << "[INFO] Parsing xdt.json..." << std::endl; std::ifstream infile(settings::XDTJSON); nlohmann::json xdtData; // read file into json infile >> xdtData; - // load warps from m_pInstanceTable.m_pWarpData try { + // load warps nlohmann::json warpData = xdtData["m_pInstanceTable"]["m_pWarpData"]; for (nlohmann::json::iterator warp = warpData.begin(); warp != warpData.end(); warp++) { @@ -95,6 +96,19 @@ void TableData::init() { MissionManager::Rewards[task["m_iHTaskID"]] = rew; } + + // quest items obtained after completing a certain task + // (distinct from quest items dropped from mobs) + if (task["m_iSUItem"][0] != 0) { + MissionManager::SUItems[task["m_iHTaskID"]] = new SUItem(task["m_iSUItem"]); + } + + // quest item mob drops + if (task["m_iCSUItemID"][0] != 0) { + MissionManager::QuestDropSets[task["m_iHTaskID"]] = new QuestDropSet(task["m_iCSUEnemyID"], task["m_iCSUItemID"]); + // TODO: timeouts, drop rates, etc. + // not sure if we need to keep track of NumNeeded/NumToKill server-side. + } } std::cout << "[INFO] Loaded mission-related data" << std::endl; @@ -111,4 +125,8 @@ void TableData::cleanup() { */ for (auto& pair : MissionManager::Rewards) delete pair.second; + for (auto& pair : MissionManager::SUItems) + delete pair.second; + for (auto& pair : MissionManager::QuestDropSets) + delete pair.second; }