[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.
This commit is contained in:
dongresource 2020-09-10 00:31:09 +02:00
parent e33b7f20e9
commit ae654f996c
4 changed files with 94 additions and 5 deletions

View File

@ -5,10 +5,12 @@
#include "ItemManager.hpp" #include "ItemManager.hpp"
std::map<int32_t, Reward*> MissionManager::Rewards; std::map<int32_t, Reward*> MissionManager::Rewards;
std::map<int32_t, SUItem*> MissionManager::SUItems;
std::map<int32_t, QuestDropSet*> MissionManager::QuestDropSets;
void MissionManager::init() { void MissionManager::init() {
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TASK_START, acceptMission); 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_SET_CURRENT_MISSION_ID, setMission);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TASK_STOP, quitMission); 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)); 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)) if (data->size != sizeof(sP_CL2FE_REQ_PC_TASK_END))
return; // malformed packet return; // malformed packet
@ -33,7 +35,50 @@ void MissionManager::completeMission(CNSocket* sock, CNPacketData* data) {
Player *plr = PlayerManager::getPlayer(sock); Player *plr = PlayerManager::getPlayer(sock);
response.iTaskNum = missionData->iTaskNum; 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()) { if (Rewards.find(missionData->iTaskNum) == Rewards.end()) {
// not a mission's final task // 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)); 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; response.iTaskNum = missionData->iTaskNum;
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_TASK_STOP_SUCC, sizeof(sP_FE2CL_REP_PC_TASK_STOP_SUCC)); 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) {}

View File

@ -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 { namespace MissionManager {
extern std::map<int32_t, Reward*> Rewards; extern std::map<int32_t, Reward*> Rewards;
extern std::map<int32_t, SUItem*> SUItems;
extern std::map<int32_t, QuestDropSet*> QuestDropSets;
void init(); void init();
void acceptMission(CNSocket* sock, CNPacketData* data); 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 setMission(CNSocket* sock, CNPacketData* data);
void quitMission(CNSocket* sock, CNPacketData* data); void quitMission(CNSocket* sock, CNPacketData* data);
} }

View File

@ -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.iHP = 3625; //TODO: Check player levelupdata and get this right
response.PCLoadData2CL.iLevel = plr.level; response.PCLoadData2CL.iLevel = plr.level;
response.PCLoadData2CL.iCandy = plr.money; response.PCLoadData2CL.iCandy = plr.money;
response.PCLoadData2CL.iMentor = 1; response.PCLoadData2CL.iMentor = 5; // Computress
response.PCLoadData2CL.iMentorCount = 4; response.PCLoadData2CL.iMentorCount = 4;
response.PCLoadData2CL.iMapNum = 0; response.PCLoadData2CL.iMapNum = 0;
response.PCLoadData2CL.iX = plr.x; response.PCLoadData2CL.iX = plr.x;

View File

@ -63,14 +63,15 @@ void TableData::init() {
} }
// load everything else from xdttable // load everything else from xdttable
std::cout << "[INFO] Parsing xdt.json..." << std::endl;
std::ifstream infile(settings::XDTJSON); std::ifstream infile(settings::XDTJSON);
nlohmann::json xdtData; nlohmann::json xdtData;
// read file into json // read file into json
infile >> xdtData; infile >> xdtData;
// load warps from m_pInstanceTable.m_pWarpData
try { try {
// load warps
nlohmann::json warpData = xdtData["m_pInstanceTable"]["m_pWarpData"]; nlohmann::json warpData = xdtData["m_pInstanceTable"]["m_pWarpData"];
for (nlohmann::json::iterator warp = warpData.begin(); warp != warpData.end(); warp++) { for (nlohmann::json::iterator warp = warpData.begin(); warp != warpData.end(); warp++) {
@ -95,6 +96,19 @@ void TableData::init() {
MissionManager::Rewards[task["m_iHTaskID"]] = rew; 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; std::cout << "[INFO] Loaded mission-related data" << std::endl;
@ -111,4 +125,8 @@ void TableData::cleanup() {
*/ */
for (auto& pair : MissionManager::Rewards) for (auto& pair : MissionManager::Rewards)
delete pair.second; delete pair.second;
for (auto& pair : MissionManager::SUItems)
delete pair.second;
for (auto& pair : MissionManager::QuestDropSets)
delete pair.second;
} }