diff --git a/src/Database.cpp b/src/Database.cpp index 8e431b8..8c42133 100644 --- a/src/Database.cpp +++ b/src/Database.cpp @@ -77,12 +77,9 @@ auto db = make_storage("database.db", make_table("RunningQuests", make_column("PlayerId", &Database::DbQuest::PlayerId), make_column("TaskId", &Database::DbQuest::TaskId), - make_column("KillNPCCount1", &Database::DbQuest::KillNPCCount1), - make_column("KillNPCCount2", &Database::DbQuest::KillNPCCount2), - make_column("KillNPCCount3", &Database::DbQuest::KillNPCCount3), - make_column("NeededItemCount1", &Database::DbQuest::NeededItemCount1), - make_column("NeededItemCount2", &Database::DbQuest::NeededItemCount2), - make_column("NeededItemCount3", &Database::DbQuest::NeededItemCount3) + make_column("RemainingNPCCount1", &Database::DbQuest::RemainingNPCCount1), + make_column("RemainingNPCCount2", &Database::DbQuest::RemainingNPCCount2), + make_column("RemainingNPCCount3", &Database::DbQuest::RemainingNPCCount3) ) ); @@ -525,6 +522,7 @@ void Database::updateInventory(Player *player){ } db.commit(); } + void Database::updateNanos(Player *player) { // start transaction db.begin_transaction(); @@ -563,12 +561,9 @@ void Database::updateQuests(Player* player) { DbQuest toAdd = {}; toAdd.PlayerId = player->iID; toAdd.TaskId = player->tasks[i]; - toAdd.KillNPCCount1 = player->killNPCCount[i][0]; - toAdd.KillNPCCount2 = player->killNPCCount[i][1]; - toAdd.KillNPCCount3 = player->killNPCCount[i][2]; - toAdd.NeededItemCount1 = player->NeededItemCount[i][0]; - toAdd.NeededItemCount2 = player->NeededItemCount[i][1]; - toAdd.NeededItemCount3 = player->NeededItemCount[i][2]; + toAdd.RemainingNPCCount1 = player->RemainingNPCCount[i][0]; + toAdd.RemainingNPCCount2 = player->RemainingNPCCount[i][1]; + toAdd.RemainingNPCCount3 = player->RemainingNPCCount[i][2]; db.insert(toAdd); } db.commit(); @@ -598,6 +593,7 @@ void Database::getInventory(Player* player) { } } + void Database::getNanos(Player* player) { // get from DB auto nanos = db.get_all( @@ -621,12 +617,9 @@ void Database::getQuests(Player* player) { int i = 0; for (const DbQuest& current : quests) { player->tasks[i] = current.TaskId; - player->killNPCCount[i][0] = current.KillNPCCount1; - player->killNPCCount[i][1] = current.KillNPCCount2; - player->killNPCCount[i][2] = current.KillNPCCount3; - player->NeededItemCount[i][0] = current.NeededItemCount1; - player->NeededItemCount[i][1] = current.NeededItemCount2; - player->NeededItemCount[i][2] = current.NeededItemCount3; + player->RemainingNPCCount[i][0] = current.RemainingNPCCount1; + player->RemainingNPCCount[i][1] = current.RemainingNPCCount2; + player->RemainingNPCCount[i][2] = current.RemainingNPCCount3; i++; } } diff --git a/src/Database.hpp b/src/Database.hpp index 9cbccbc..b01ff8d 100644 --- a/src/Database.hpp +++ b/src/Database.hpp @@ -74,12 +74,9 @@ namespace Database { struct DbQuest { int PlayerId; int32_t TaskId; - int KillNPCCount1; - int KillNPCCount2; - int KillNPCCount3; - int NeededItemCount1; - int NeededItemCount2; - int NeededItemCount3; + int RemainingNPCCount1; + int RemainingNPCCount2; + int RemainingNPCCount3; }; diff --git a/src/MissionManager.cpp b/src/MissionManager.cpp index f201fff..d349e7d 100644 --- a/src/MissionManager.cpp +++ b/src/MissionManager.cpp @@ -32,13 +32,18 @@ void MissionManager::taskStart(CNSocket* sock, CNPacketData* data) { return; } + TaskData& task = *Tasks[missionData->iTaskNum]; int i; for (i = 0; i < ACTIVE_MISSION_COUNT; i++) { if (plr->tasks[i] == 0) { plr->tasks[i] = missionData->iTaskNum; + for (int j = 0; j < 3; j++) { + plr->RemainingNPCCount[i][j] = (int)task["m_iCSUNumToKill"][j]; + } break; } } + if (i == ACTIVE_MISSION_COUNT - 1 && plr->tasks[i] != missionData->iTaskNum) { std::cout << "[WARN] Player has more than 6 active missions!?" << std::endl; } @@ -80,18 +85,11 @@ void MissionManager::taskEnd(CNSocket* sock, CNPacketData* data) { * iSUInstancename is the number of items to give. It is usually negative at the end of * a mission, so as to clean up it's quest items. */ - int playerTaskNum = 0; - for (int i = 0; i < ACTIVE_MISSION_COUNT; i++) { - if (plr->tasks[i] == missionData->iTaskNum) { - playerTaskNum = i; - break; - } - } + 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); - plr->NeededItemCount[playerTaskNum][i]++; - } + // mission rewards if (Rewards.find(missionData->iTaskNum) != Rewards.end()) { if (giveMissionReward(sock, missionData->iTaskNum) == -1) @@ -105,8 +103,7 @@ void MissionManager::taskEnd(CNSocket* sock, CNPacketData* data) { { plr->tasks[i] = 0; for (int j = 0; j < 3; j++) { - plr->killNPCCount[i][j] = 0; - plr->NeededItemCount[i][j] = 0; + plr->RemainingNPCCount[i][j] = 0; } } } @@ -154,8 +151,7 @@ void MissionManager::quitMission(CNSocket* sock, CNPacketData* data) { { plr->tasks[i] = 0; for (int j = 0; j < 3; j++) { - plr->killNPCCount[i][j] = 0; - plr->NeededItemCount[i][j] = 0; + plr->RemainingNPCCount[i][j] = 0; } } } @@ -165,7 +161,6 @@ void MissionManager::quitMission(CNSocket* sock, CNPacketData* data) { // remove current mission plr->CurrentMissionID = 0; - TaskData& task = *Tasks[missionData->iTaskNum]; // clean up quest items @@ -333,15 +328,14 @@ void MissionManager::mobKilled(CNSocket *sock, int mobid) { if (task["m_iCSUNumToKill"][j] != 0) { missionmob = true; - plr->killNPCCount[i][j]++; + plr->RemainingNPCCount[i][j]--; } // drop quest item - if (task["m_iCSUItemNumNeeded"][j] != 0) { + if (task["m_iCSUItemNumNeeded"][j] != 0 && !isQuestItemFull(sock, task["m_iCSUItemID"][j], task["m_iCSUItemNumNeeded"][j]) ) { bool drop = rand() % 100 < task["m_iSTItemDropRate"][j]; if (drop) { // XXX: are CSUItemID and CSTItemID the same? dropQuestItem(sock, plr->tasks[i], 1, task["m_iCSUItemID"][j], mobid); - plr->NeededItemCount[i][j]++; } else { // fail to drop (itemID == 0) dropQuestItem(sock, plr->tasks[i], 1, 0, mobid); @@ -373,3 +367,15 @@ void MissionManager::saveMission(Player* player, int missionId) { int column = missionId % 64; player->aQuestFlag[row] |= (1ULL << column); } + +bool MissionManager::isQuestItemFull(CNSocket* sock, int itemId, int itemCount) { + Player* plr = PlayerManager::getPlayer(sock); + int slot = findQSlot(plr, itemId); + if (slot == -1) { + // this should never happen + std::cout << "[WARN] Player has no room for quest item!?" << std::endl; + return true; + } + + return (itemCount == plr->QInven[slot].iOpt); +} diff --git a/src/MissionManager.hpp b/src/MissionManager.hpp index 4105514..1d6bed5 100644 --- a/src/MissionManager.hpp +++ b/src/MissionManager.hpp @@ -47,6 +47,8 @@ namespace MissionManager { int findQSlot(Player *plr, int id); void dropQuestItem(CNSocket *sock, int task, int count, int id, int mobid); + //checks if player doesn't have n/n quest items + bool isQuestItemFull(CNSocket* sock, int itemId, int itemCount); int giveMissionReward(CNSocket *sock, int task); void mobKilled(CNSocket *sock, int mobid); diff --git a/src/Player.hpp b/src/Player.hpp index 3558916..ab198ee 100644 --- a/src/Player.hpp +++ b/src/Player.hpp @@ -43,8 +43,7 @@ struct Player { int64_t aQuestFlag[16]; int tasks[ACTIVE_MISSION_COUNT]; - int killNPCCount[ACTIVE_MISSION_COUNT][3]; - int NeededItemCount[ACTIVE_MISSION_COUNT][3]; + int RemainingNPCCount[ACTIVE_MISSION_COUNT][3]; sItemBase QInven[AQINVEN_COUNT]; int32_t CurrentMissionID; }; diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index 4af4a51..ceb351b 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -246,10 +246,14 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) { TaskData &task = *MissionManager::Tasks[plr.tasks[i]]; for (int j = 0; j < 3; j++) { response.PCLoadData2CL.aRunningQuest[i].m_aKillNPCID[j] = (int)task["m_iCSUEnemyID"][j]; - response.PCLoadData2CL.aRunningQuest[i].m_aNeededItemID[j] = (int)task["m_iCSUItemID"][j]; - response.PCLoadData2CL.aRunningQuest[i].m_aKillNPCCount[j] = plr.killNPCCount[i][j]; - //response.PCLoadData2CL.aRunningQuest[i].m_aNeededItemCount[j] = plr.NeededItemCount[i][j]; - //why is client not using that smh + response.PCLoadData2CL.aRunningQuest[i].m_aKillNPCCount[j] = plr.RemainingNPCCount[i][j]; + /* + * client doesn't care about NeededItem ID and Count, + * it gets Count from Quest Inventory + * + * KillNPCCount sets RemainEnemyNum in the client + * Yes, this is extraordinary stupid, even for Grigon + */ } } response.PCLoadData2CL.iCurrentMissionID = plr.CurrentMissionID;