From 6473951b9afde25ed6b43b36d67a78bc1b0a4df1 Mon Sep 17 00:00:00 2001 From: Gent Date: Wed, 14 Oct 2020 14:36:38 -0400 Subject: [PATCH] Instance tweaks + fixes Instanced mobs tick, fusions stay dead, missions reset on enter --- src/ChunkManager.cpp | 18 +++++++++++++----- src/MissionManager.cpp | 22 +++++++++++++++------- src/MissionManager.hpp | 2 +- src/MobManager.hpp | 4 ++-- src/PlayerManager.cpp | 11 ++++++++--- 5 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/ChunkManager.cpp b/src/ChunkManager.cpp index d49cb6f..ce03ecc 100644 --- a/src/ChunkManager.cpp +++ b/src/ChunkManager.cpp @@ -2,6 +2,7 @@ #include "PlayerManager.hpp" #include "NPCManager.hpp" #include "settings.hpp" +#include "MobManager.hpp" std::map, Chunk*> ChunkManager::chunks; @@ -207,11 +208,18 @@ void ChunkManager::createInstance(uint64_t instanceID) { for (int npcID : chunks[coords]->NPCs) { // make a copy of each NPC in the template chunks and put them in the new instance int newID = NPCManager::nextId++; - BaseNPC* newNPC = new BaseNPC(); - memcpy(newNPC, NPCManager::NPCs[npcID], sizeof(BaseNPC)); - newNPC->appearanceData.iNPC_ID = newID; - NPCManager::NPCs[newID] = newNPC; - NPCManager::updateNPCInstance(newID, instanceID); + BaseNPC* baseNPC = NPCManager::NPCs[npcID]; + if (baseNPC->npcClass == NPC_MOB) { + Mob* newMob = new Mob(baseNPC->appearanceData.iX, baseNPC->appearanceData.iY, baseNPC->appearanceData.iZ, baseNPC->appearanceData.iAngle, + instanceID, baseNPC->appearanceData.iNPCType, baseNPC->appearanceData.iHP, NPCManager::NPCData[baseNPC->appearanceData.iNPCType], newID); + NPCManager::NPCs[newID] = newMob; + MobManager::Mobs[newID] = newMob; + } else { + BaseNPC* newNPC = new BaseNPC(baseNPC->appearanceData.iX, baseNPC->appearanceData.iY, baseNPC->appearanceData.iZ, baseNPC->appearanceData.iAngle, + instanceID, baseNPC->appearanceData.iNPCType, newID); + NPCManager::NPCs[newID] = newNPC; + } + NPCManager::updateNPCInstance(newID, instanceID); // make sure the npc state gets updated } } } diff --git a/src/MissionManager.cpp b/src/MissionManager.cpp index 536128f..9951d36 100644 --- a/src/MissionManager.cpp +++ b/src/MissionManager.cpp @@ -199,11 +199,10 @@ void MissionManager::quitMission(CNSocket* sock, CNPacketData* data) { return; // malformed packet sP_CL2FE_REQ_PC_TASK_STOP* missionData = (sP_CL2FE_REQ_PC_TASK_STOP*)data->buf; - quitTask(sock, missionData->iTaskNum); + quitTask(sock, missionData->iTaskNum, true); } -void MissionManager::quitTask(CNSocket* sock, int32_t taskNum) { - INITSTRUCT(sP_FE2CL_REP_PC_TASK_STOP_SUCC, response); +void MissionManager::quitTask(CNSocket* sock, int32_t taskNum, bool manual) { Player* plr = PlayerManager::getPlayer(sock); if (plr == nullptr) @@ -242,6 +241,14 @@ void MissionManager::quitTask(CNSocket* sock, int32_t taskNum) { memset(&plr->QInven[j], 0, sizeof(sItemBase)); } + if (!manual) { + INITSTRUCT(sP_FE2CL_REP_PC_TASK_END_FAIL, failResp); + failResp.iErrorCode = 1; + failResp.iTaskNum = taskNum; + sock->sendPacket((void*)&failResp, P_FE2CL_REP_PC_TASK_END_FAIL, sizeof(sP_FE2CL_REP_PC_TASK_END_FAIL)); + } + + INITSTRUCT(sP_FE2CL_REP_PC_TASK_STOP_SUCC, response); response.iTaskNum = taskNum; sock->sendPacket((void*)&response, P_FE2CL_REP_PC_TASK_STOP_SUCC, sizeof(sP_FE2CL_REP_PC_TASK_STOP_SUCC)); } @@ -510,16 +517,17 @@ bool MissionManager::isQuestItemFull(CNSocket* sock, int itemId, int itemCount) void MissionManager::failInstancedMissions(CNSocket* sock) { // loop through all tasks; if the required instance is being left, "fail" the task Player* plr = PlayerManager::getPlayer(sock); - for (int taskNum : plr->tasks) { + for (int i = 0; i < 6; i++) { + int taskNum = plr->tasks[i]; if (MissionManager::Tasks.find(taskNum) == MissionManager::Tasks.end()) continue; // sanity check TaskData* task = MissionManager::Tasks[taskNum]; - if ((plr->instanceID & 0xffffffff) == (int)(task->task["m_iRequireInstanceID"])) { // map num matches + if (task->task["m_iRequireInstanceID"] != 0) { // mission is instanced int failTaskID = task->task["m_iFOutgoingTask"]; if (failTaskID != 0) { - MissionManager::quitTask(sock, taskNum); - MissionManager::startTask(sock, failTaskID, task->task["m_iSTNanoID"] != 0); + MissionManager::quitTask(sock, taskNum, false); + plr->tasks[i] = failTaskID; } } } diff --git a/src/MissionManager.hpp b/src/MissionManager.hpp index 18a73be..d289894 100644 --- a/src/MissionManager.hpp +++ b/src/MissionManager.hpp @@ -57,7 +57,7 @@ namespace MissionManager { bool endTask(CNSocket *sock, int32_t taskNum); void saveMission(Player* player, int missionId); - void quitTask(CNSocket* sock, int32_t taskNum); + void quitTask(CNSocket* sock, int32_t taskNum, bool manual); void failInstancedMissions(CNSocket* sock); } diff --git a/src/MobManager.hpp b/src/MobManager.hpp index ed3f243..2555175 100644 --- a/src/MobManager.hpp +++ b/src/MobManager.hpp @@ -55,8 +55,8 @@ struct Mob : public BaseNPC { idleRange = (int)data["m_iIdleRange"] * 2; // TODO: tuning? // XXX: temporarily force respawns for Fusions until we implement instancing - if (regenTime >= 300000000) - regenTime = 1500; + //if (regenTime >= 300000000) + // regenTime = 1500; roamX = spawnX = appearanceData.iX; roamY = spawnY = appearanceData.iY; diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index aa83d49..a579378 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -65,7 +65,7 @@ void PlayerManager::addPlayer(CNSocket* key, Player plr) { void PlayerManager::removePlayer(CNSocket* key) { PlayerView& view = players[key]; - MissionManager::failInstancedMissions(key); + //MissionManager::failInstancedMissions(key); moved to enter GroupManager::groupKickPlayer(view.plr); // save player to DB @@ -233,11 +233,13 @@ void PlayerManager::sendPlayerTo(CNSocket* sock, int X, int Y, int Z, uint64_t I plr->instanceID = I; if (I != INSTANCE_OVERWORLD) { INITSTRUCT(sP_FE2CL_INSTANCE_MAP_INFO, pkt); + pkt.iEP_ID = (I >> 32) == 0; // iEP_ID has to be positive for the map to be enabled pkt.iInstanceMapNum = (int32_t)(I & 0xffffffff); // lower 32 bits are mapnum sock->sendPacket((void*)&pkt, P_FE2CL_INSTANCE_MAP_INFO, sizeof(sP_FE2CL_INSTANCE_MAP_INFO)); sendPlayerTo(sock, X, Y, Z); } else { // annoying but necessary to set the flag back + MissionManager::failInstancedMissions(sock); // fail any instanced missions INITSTRUCT(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC, resp); resp.iX = X; resp.iY = Y; @@ -383,6 +385,8 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) { //set player equip stats ItemManager::setItemStats(getPlayer(sock)); + + MissionManager::failInstancedMissions(sock); } void PlayerManager::sendToViewable(CNSocket* sock, void* buf, uint32_t type, size_t size) { @@ -692,8 +696,9 @@ void PlayerManager::gotoPlayer(CNSocket* sock, CNPacketData* data) { std::cout << "\tX: " << gotoData->iToX << std::endl; std::cout << "\tY: " << gotoData->iToY << std::endl; std::cout << "\tZ: " << gotoData->iToZ << std::endl; - ) + ) + MissionManager::failInstancedMissions(sock); // this ensures warping by command still fails instanced missions sendPlayerTo(sock, gotoData->iToX, gotoData->iToY, gotoData->iToZ, 0); } @@ -910,7 +915,7 @@ void PlayerManager::changePlayerGuide(CNSocket *sock, CNPacketData *data) { // remove all active missions for (int i = 0; i < ACTIVE_MISSION_COUNT; i++) { if (plr->tasks[i] != 0) - MissionManager::quitTask(sock, plr->tasks[i]); + MissionManager::quitTask(sock, plr->tasks[i], true); } // start Blossom nano mission if applicable