Kick players out of instances when they leave

This commit is contained in:
Gent 2020-10-14 00:26:30 -04:00
parent 85530ef57f
commit efd729710f
7 changed files with 47 additions and 20 deletions

View File

@ -82,9 +82,7 @@ void CNShardServer::_killConnection(CNSocket* cns) {
int64_t key = plr->SerialKey;
// save player to DB
Database::updatePlayer(PlayerManager::players[cns].plr);
PlayerManager::removePlayer(cns);
PlayerManager::removePlayer(cns); // removes the player from the list and saves it to DB
// remove from CNSharedData
CNSharedData::erasePlayer(key);

View File

@ -390,10 +390,18 @@ Database::DbPlayer Database::playerToDb(Player *player)
result.slot = player->slot;
result.Taros = player->money;
result.TutorialFlag = player->PCStyle2.iTutorialFlag;
if (player->instanceID == 0) { // only save coords if player isn't instanced
result.x_coordinates = player->x;
result.y_coordinates = player->y;
result.z_coordinates = player->z;
result.angle = player->angle;
}
else {
result.x_coordinates = player->lastX;
result.y_coordinates = player->lastY;
result.z_coordinates = player->lastZ;
result.angle = player->lastAngle;
}
result.Nano1 = player->equippedNanos[0];
result.Nano2 = player->equippedNanos[1];
result.Nano3 = player->equippedNanos[2];

View File

@ -506,3 +506,21 @@ bool MissionManager::isQuestItemFull(CNSocket* sock, int itemId, int itemCount)
return (itemCount == plr->QInven[slot].iOpt);
}
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) {
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
int failTaskID = task->task["m_iFOutgoingTask"];
if (failTaskID != 0) {
MissionManager::quitTask(sock, taskNum);
MissionManager::startTask(sock, failTaskID, task->task["m_iSTNanoID"] != 0);
}
}
}
}

View File

@ -58,4 +58,6 @@ namespace MissionManager {
bool endTask(CNSocket *sock, int32_t taskNum);
void saveMission(Player* player, int missionId);
void quitTask(CNSocket* sock, int32_t taskNum);
void failInstancedMissions(CNSocket* sock);
}

View File

@ -590,19 +590,14 @@ void NPCManager::handleWarp(CNSocket* sock, int32_t warpId) {
if (Warps.find(warpId) == Warps.end())
return;
// loop through all tasks; if the required instance is being left, "fail" the task
for (int taskNum : plrv.plr->tasks) {
if (MissionManager::Tasks.find(taskNum) == MissionManager::Tasks.end())
continue; // sanity check
MissionManager::failInstancedMissions(sock); // fail any missions that require the player's current instance
TaskData* task = MissionManager::Tasks[taskNum];
if ((plrv.plr->instanceID & 0xffffffff) == (int)(task->task["m_iRequireInstanceID"])) { // instance ID matches
int failTaskID = task->task["m_iFOutgoingTask"];
if (failTaskID != 0) {
MissionManager::quitTask(sock, taskNum);
// TODO: start fail task
}
}
if (plrv.plr->instanceID == 0) {
// save last uninstanced coords
plrv.plr->lastX = plrv.plr->x;
plrv.plr->lastY = plrv.plr->y;
plrv.plr->lastZ = plrv.plr->z;
plrv.plr->lastAngle = plrv.plr->angle;
}
// std::cerr << "Warped to Map Num:" << Warps[warpId].instanceID << " NPC ID " << Warps[warpId].npcID << std::endl;

View File

@ -38,6 +38,7 @@ struct Player {
int8_t iSpecialState;
int x, y, z, angle;
int lastX, lastY, lastZ, lastAngle;
uint64_t instanceID;
sItemBase Equip[AEQUIP_COUNT];
sItemBase Inven[AINVEN_COUNT];

View File

@ -8,6 +8,7 @@
#include "NanoManager.hpp"
#include "GroupManager.hpp"
#include "ChatManager.hpp"
#include "Database.hpp"
#include "settings.hpp"
@ -64,8 +65,12 @@ void PlayerManager::addPlayer(CNSocket* key, Player plr) {
void PlayerManager::removePlayer(CNSocket* key) {
PlayerView& view = players[key];
MissionManager::failInstancedMissions(key);
GroupManager::groupKickPlayer(view.plr);
// save player to DB
Database::updatePlayer(view.plr);
INITSTRUCT(sP_FE2CL_PC_EXIT, exitPacket);
exitPacket.iID = players[key].plr->iID;