Instance tweaks + fixes

Instanced mobs tick, fusions stay dead, missions reset on enter
This commit is contained in:
Gent 2020-10-14 14:36:38 -04:00
parent 3050801399
commit 6473951b9a
5 changed files with 39 additions and 18 deletions

View File

@ -2,6 +2,7 @@
#include "PlayerManager.hpp" #include "PlayerManager.hpp"
#include "NPCManager.hpp" #include "NPCManager.hpp"
#include "settings.hpp" #include "settings.hpp"
#include "MobManager.hpp"
std::map<std::tuple<int, int, uint64_t>, Chunk*> ChunkManager::chunks; std::map<std::tuple<int, int, uint64_t>, Chunk*> ChunkManager::chunks;
@ -207,11 +208,18 @@ void ChunkManager::createInstance(uint64_t instanceID) {
for (int npcID : chunks[coords]->NPCs) { for (int npcID : chunks[coords]->NPCs) {
// make a copy of each NPC in the template chunks and put them in the new instance // make a copy of each NPC in the template chunks and put them in the new instance
int newID = NPCManager::nextId++; int newID = NPCManager::nextId++;
BaseNPC* newNPC = new BaseNPC(); BaseNPC* baseNPC = NPCManager::NPCs[npcID];
memcpy(newNPC, NPCManager::NPCs[npcID], sizeof(BaseNPC)); if (baseNPC->npcClass == NPC_MOB) {
newNPC->appearanceData.iNPC_ID = newID; 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::NPCs[newID] = newNPC;
NPCManager::updateNPCInstance(newID, instanceID); }
NPCManager::updateNPCInstance(newID, instanceID); // make sure the npc state gets updated
} }
} }
} }

View File

@ -199,11 +199,10 @@ void MissionManager::quitMission(CNSocket* sock, CNPacketData* data) {
return; // malformed packet return; // malformed packet
sP_CL2FE_REQ_PC_TASK_STOP* missionData = (sP_CL2FE_REQ_PC_TASK_STOP*)data->buf; 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) { void MissionManager::quitTask(CNSocket* sock, int32_t taskNum, bool manual) {
INITSTRUCT(sP_FE2CL_REP_PC_TASK_STOP_SUCC, response);
Player* plr = PlayerManager::getPlayer(sock); Player* plr = PlayerManager::getPlayer(sock);
if (plr == nullptr) if (plr == nullptr)
@ -242,6 +241,14 @@ void MissionManager::quitTask(CNSocket* sock, int32_t taskNum) {
memset(&plr->QInven[j], 0, sizeof(sItemBase)); 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; response.iTaskNum = 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));
} }
@ -510,16 +517,17 @@ bool MissionManager::isQuestItemFull(CNSocket* sock, int itemId, int itemCount)
void MissionManager::failInstancedMissions(CNSocket* sock) { void MissionManager::failInstancedMissions(CNSocket* sock) {
// loop through all tasks; if the required instance is being left, "fail" the task // loop through all tasks; if the required instance is being left, "fail" the task
Player* plr = PlayerManager::getPlayer(sock); 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()) if (MissionManager::Tasks.find(taskNum) == MissionManager::Tasks.end())
continue; // sanity check continue; // sanity check
TaskData* task = MissionManager::Tasks[taskNum]; 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"]; int failTaskID = task->task["m_iFOutgoingTask"];
if (failTaskID != 0) { if (failTaskID != 0) {
MissionManager::quitTask(sock, taskNum); MissionManager::quitTask(sock, taskNum, false);
MissionManager::startTask(sock, failTaskID, task->task["m_iSTNanoID"] != 0); plr->tasks[i] = failTaskID;
} }
} }
} }

View File

@ -57,7 +57,7 @@ namespace MissionManager {
bool endTask(CNSocket *sock, int32_t taskNum); 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, bool manual);
void failInstancedMissions(CNSocket* sock); void failInstancedMissions(CNSocket* sock);
} }

View File

@ -55,8 +55,8 @@ struct Mob : public BaseNPC {
idleRange = (int)data["m_iIdleRange"] * 2; // TODO: tuning? idleRange = (int)data["m_iIdleRange"] * 2; // TODO: tuning?
// XXX: temporarily force respawns for Fusions until we implement instancing // XXX: temporarily force respawns for Fusions until we implement instancing
if (regenTime >= 300000000) //if (regenTime >= 300000000)
regenTime = 1500; // regenTime = 1500;
roamX = spawnX = appearanceData.iX; roamX = spawnX = appearanceData.iX;
roamY = spawnY = appearanceData.iY; roamY = spawnY = appearanceData.iY;

View File

@ -65,7 +65,7 @@ void PlayerManager::addPlayer(CNSocket* key, Player plr) {
void PlayerManager::removePlayer(CNSocket* key) { void PlayerManager::removePlayer(CNSocket* key) {
PlayerView& view = players[key]; PlayerView& view = players[key];
MissionManager::failInstancedMissions(key); //MissionManager::failInstancedMissions(key); moved to enter
GroupManager::groupKickPlayer(view.plr); GroupManager::groupKickPlayer(view.plr);
// save player to DB // 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; plr->instanceID = I;
if (I != INSTANCE_OVERWORLD) { if (I != INSTANCE_OVERWORLD) {
INITSTRUCT(sP_FE2CL_INSTANCE_MAP_INFO, pkt); 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 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)); sock->sendPacket((void*)&pkt, P_FE2CL_INSTANCE_MAP_INFO, sizeof(sP_FE2CL_INSTANCE_MAP_INFO));
sendPlayerTo(sock, X, Y, Z); sendPlayerTo(sock, X, Y, Z);
} else { } else {
// annoying but necessary to set the flag back // 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); INITSTRUCT(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC, resp);
resp.iX = X; resp.iX = X;
resp.iY = Y; resp.iY = Y;
@ -383,6 +385,8 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
//set player equip stats //set player equip stats
ItemManager::setItemStats(getPlayer(sock)); ItemManager::setItemStats(getPlayer(sock));
MissionManager::failInstancedMissions(sock);
} }
void PlayerManager::sendToViewable(CNSocket* sock, void* buf, uint32_t type, size_t size) { void PlayerManager::sendToViewable(CNSocket* sock, void* buf, uint32_t type, size_t size) {
@ -694,6 +698,7 @@ void PlayerManager::gotoPlayer(CNSocket* sock, CNPacketData* data) {
std::cout << "\tZ: " << gotoData->iToZ << 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); sendPlayerTo(sock, gotoData->iToX, gotoData->iToY, gotoData->iToZ, 0);
} }
@ -910,7 +915,7 @@ void PlayerManager::changePlayerGuide(CNSocket *sock, CNPacketData *data) {
// remove all active missions // remove all active missions
for (int i = 0; i < ACTIVE_MISSION_COUNT; i++) { for (int i = 0; i < ACTIVE_MISSION_COUNT; i++) {
if (plr->tasks[i] != 0) if (plr->tasks[i] != 0)
MissionManager::quitTask(sock, plr->tasks[i]); MissionManager::quitTask(sock, plr->tasks[i], true);
} }
// start Blossom nano mission if applicable // start Blossom nano mission if applicable