The Future is now playable.

* Sync'd tdata so it has all the lair NPCs
* Bypassed Eduardo escort task
* Fixed the level 36 updateFusionMatter() memory error
* Fixed qitems being deleted even if the player fails to complete the
mission due to not having any inventory space, thus softlocking the
mission
This commit is contained in:
dongresource 2020-09-25 23:05:36 +02:00
parent 1b35aab958
commit dccd92aff9
6 changed files with 62 additions and 41 deletions

View File

@ -76,6 +76,18 @@ void MissionManager::taskStart(CNSocket* sock, CNPacketData* data) {
response.iTaskNum = missionData->iTaskNum; response.iTaskNum = missionData->iTaskNum;
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));
// HACK: auto-succeed Eduardo escort task
// TODO: maybe check for iTaskType == 6 and skip all escort missions?
if (missionData->iTaskNum == 576) {
std::cout << "Sending Eduardo success packet" << std::endl;
INITSTRUCT(sP_FE2CL_REP_PC_TASK_END_SUCC, response);
endTask(sock, 576);
response.iTaskNum = 576;
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_TASK_END_SUCC, sizeof(sP_FE2CL_REP_PC_TASK_END_SUCC));
}
} }
void MissionManager::taskEnd(CNSocket* sock, CNPacketData* data) { void MissionManager::taskEnd(CNSocket* sock, CNPacketData* data) {
@ -84,20 +96,31 @@ void MissionManager::taskEnd(CNSocket* sock, CNPacketData* data) {
sP_CL2FE_REQ_PC_TASK_END* missionData = (sP_CL2FE_REQ_PC_TASK_END*)data->buf; sP_CL2FE_REQ_PC_TASK_END* missionData = (sP_CL2FE_REQ_PC_TASK_END*)data->buf;
INITSTRUCT(sP_FE2CL_REP_PC_TASK_END_SUCC, response); INITSTRUCT(sP_FE2CL_REP_PC_TASK_END_SUCC, response);
Player *plr = PlayerManager::getPlayer(sock);
response.iTaskNum = missionData->iTaskNum; response.iTaskNum = missionData->iTaskNum;
//std::cout << missionData->iTaskNum << std::endl;
if (Tasks.find(missionData->iTaskNum) == Tasks.end()) { if (!endTask(sock, missionData->iTaskNum)) {
std::cout << "[WARN] Player submitted unknown task!?" << std::endl;
// TODO: TASK_FAIL?
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_TASK_END_SUCC, sizeof(sP_FE2CL_REP_PC_TASK_END_SUCC));
return; return;
} }
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_TASK_END_SUCC, sizeof(sP_FE2CL_REP_PC_TASK_END_SUCC));
}
bool MissionManager::endTask(CNSocket *sock, int32_t taskNum) {
Player *plr = PlayerManager::getPlayer(sock);
if (Tasks.find(taskNum) == Tasks.end())
return false;
// ugly pointer/reference juggling for the sake of operator overloading... // ugly pointer/reference juggling for the sake of operator overloading...
TaskData& task = *Tasks[missionData->iTaskNum]; TaskData& task = *Tasks[taskNum];
// mission rewards
if (Rewards.find(taskNum) != Rewards.end()) {
if (giveMissionReward(sock, taskNum) == -1)
return false; // we don't want to send anything
}
// don't take away quest items if we haven't finished the quest
/* /*
* Give (or take away) quest items * Give (or take away) quest items
@ -114,18 +137,12 @@ void MissionManager::taskEnd(CNSocket* sock, CNPacketData* data) {
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
if (task["m_iSUItem"][i] != 0) if (task["m_iSUItem"][i] != 0)
dropQuestItem(sock, missionData->iTaskNum, task["m_iSUInstancename"][i], task["m_iSUItem"][i], 0); dropQuestItem(sock, taskNum, task["m_iSUInstancename"][i], task["m_iSUItem"][i], 0);
// mission rewards
if (Rewards.find(missionData->iTaskNum) != Rewards.end()) {
if (giveMissionReward(sock, missionData->iTaskNum) == -1)
return;
}
// update player // update player
int i; int i;
for (i = 0; i < ACTIVE_MISSION_COUNT; i++) { for (i = 0; i < ACTIVE_MISSION_COUNT; i++) {
if (plr->tasks[i] == missionData->iTaskNum) if (plr->tasks[i] == taskNum)
{ {
plr->tasks[i] = 0; plr->tasks[i] = 0;
for (int j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
@ -146,13 +163,15 @@ void MissionManager::taskEnd(CNSocket* sock, CNPacketData* data) {
// if it's a nano mission, reward the nano. // if it's a nano mission, reward the nano.
if (task["m_iSTNanoID"] != 0) { if (task["m_iSTNanoID"] != 0) {
NanoManager::addNano(sock, task["m_iSTNanoID"], 0); NanoManager::addNano(sock, task["m_iSTNanoID"], 0);
// check if the player already has enough fm for the next mission
updateFusionMatter(sock, 0);
} }
// remove current mission // remove current mission
plr->CurrentMissionID = 0; plr->CurrentMissionID = 0;
} }
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_TASK_END_SUCC, sizeof(sP_FE2CL_REP_PC_TASK_END_SUCC)); return true;
} }
void MissionManager::setMission(CNSocket* sock, CNPacketData* data) { void MissionManager::setMission(CNSocket* sock, CNPacketData* data) {
@ -217,7 +236,6 @@ void MissionManager::quitTask(CNSocket* sock, int32_t taskNum) {
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));
} }
// TODO: coalesce into ItemManager::findFreeSlot()?
int MissionManager::findQSlot(Player *plr, int id) { int MissionManager::findQSlot(Player *plr, int id) {
int i; int i;
@ -322,7 +340,7 @@ int MissionManager::giveMissionReward(CNSocket *sock, int task) {
// update player // update player
plr->money += reward->money; plr->money += reward->money;
MissionManager::updateFusionMatter(sock, reward->fusionmatter); updateFusionMatter(sock, reward->fusionmatter);
// simple rewards // simple rewards
resp->m_iCandy = plr->money; resp->m_iCandy = plr->money;
@ -351,24 +369,27 @@ void MissionManager::updateFusionMatter(CNSocket* sock, int fusion) {
plr->fusionmatter += fusion; plr->fusionmatter += fusion;
// check if it is over the limit // sanity check
if (plr->fusionmatter > AvatarGrowth[plr->level]["m_iReqBlob_NanoCreate"]) { if (plr->level >= 36)
// check if the nano task is already started
for (int i = 0; i < ACTIVE_MISSION_COUNT; i++) {
TaskData& task = *Tasks[plr->tasks[i]];
if (task["m_iSTNanoID"] != 0)
return; // nano mission was already started!
}
// start the nano mission
startTask(plr, AvatarGrowth[plr->level]["m_iNanoQuestTaskID"], true);
INITSTRUCT(sP_FE2CL_REP_PC_TASK_START_SUCC, response);
response.iTaskNum = AvatarGrowth[plr->level]["m_iNanoQuestTaskID"];
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_TASK_START_SUCC, sizeof(sP_FE2CL_REP_PC_TASK_START_SUCC));
return; return;
// check if it is over the limit
if (plr->fusionmatter <= AvatarGrowth[plr->level]["m_iReqBlob_NanoCreate"])
return;
// check if the nano task is already started
for (int i = 0; i < ACTIVE_MISSION_COUNT; i++) {
TaskData& task = *Tasks[plr->tasks[i]];
if (task["m_iSTNanoID"] != 0)
return; // nano mission was already started!
} }
// start the nano mission
startTask(plr, AvatarGrowth[plr->level]["m_iNanoQuestTaskID"], true);
INITSTRUCT(sP_FE2CL_REP_PC_TASK_START_SUCC, response);
response.iTaskNum = AvatarGrowth[plr->level]["m_iNanoQuestTaskID"];
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_TASK_START_SUCC, sizeof(sP_FE2CL_REP_PC_TASK_START_SUCC));
} }
void MissionManager::mobKilled(CNSocket *sock, int mobid) { void MissionManager::mobKilled(CNSocket *sock, int mobid) {
@ -430,7 +451,7 @@ void MissionManager::saveMission(Player* player, int missionId) {
return; return;
} }
// Missions are stored in int_64t array // Missions are stored in int64_t array
int row = missionId / 64; int row = missionId / 64;
int column = missionId % 64; int column = missionId % 64;
player->aQuestFlag[row] |= (1ULL << column); player->aQuestFlag[row] |= (1ULL << column);

View File

@ -55,6 +55,7 @@ namespace MissionManager {
void mobKilled(CNSocket *sock, int mobid); void mobKilled(CNSocket *sock, int mobid);
bool endTask(CNSocket *sock, int32_t taskNum);
void saveMission(Player* player, int missionId); void saveMission(Player* player, int missionId);
void quitTask(CNSocket* sock, int32_t taskNum); void quitTask(CNSocket* sock, int32_t taskNum);
} }

View File

@ -36,10 +36,10 @@ std::set<int> TreasureFinderPowers = {26, 40, 74};
* worker functions so we don't have to have unsightly function declarations. * worker functions so we don't have to have unsightly function declarations.
*/ */
std::map<int32_t, NanoData> NanoManager::NanoTable;
}; // namespace }; // namespace
std::map<int32_t, NanoData> NanoManager::NanoTable;
void NanoManager::init() { void NanoManager::init() {
REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_ACTIVE, nanoSummonHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_ACTIVE, nanoSummonHandler);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_EQUIP, nanoEquipHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_EQUIP, nanoEquipHandler);

View File

@ -199,8 +199,8 @@ void TableData::init() {
} }
/* /*
* Some item categories either don't possess iEquipLoc or use a different value for item type. * Some item categories either don't possess iEquipLoc or use a different value for item type.
*/ */
int TableData::getItemType(int itemSet) { int TableData::getItemType(int itemSet) {
int overriden; int overriden;
switch (itemSet) switch (itemSet)

View File

@ -2,5 +2,4 @@ leak:TableData::init
leak:ChunkManager::addPlayer leak:ChunkManager::addPlayer
leak:ChunkManager::addNPC leak:ChunkManager::addNPC
leak:NPCManager::npcSummonHandler leak:NPCManager::npcSummonHandler
leak:BaseNPC::BaseNPC
leak:nlohmann::basic_json leak:nlohmann::basic_json

2
tdata

@ -1 +1 @@
Subproject commit 2d16da519452c934b6fc2fa61adbcb25f855e95f Subproject commit 9c595541b3803664359a19379a2cef9b1c2cdc65