eqemu-server/world/expedition.cpp
hg 8eef2ae089 Add DynamicZone class for expedition instancing
Add DynamicZone sql table schema

Add DynamicZones logging category

Modify CreateExpedition to take DynamicZone and ExpeditionRequest objects

Implement DynamicZone compass, safereturn, and zone-in coordinates.

Implement live-like DynamicZone instance kick timer for removed members

Implement updating multiple client compasses (supports existing quest compass)

fix: Send client compass update after entering zones to clear existing compass

Implement Client::MovePCDynamicZone to invoke DynamicZoneSwitchListWnd
when entering a zone where client has multiple dynamic zones assigned

Implement OP_DzChooseZoneReply handling

Add Lua api methods for expedition's associated dynamic zone

Add #dz list gm command to list current DynamicZone instances from database
2020-12-30 18:47:07 -05:00

141 lines
4.3 KiB
C++

/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "expedition.h"
#include "clientlist.h"
#include "cliententry.h"
#include "zonelist.h"
#include "zoneserver.h"
#include "worlddb.h"
#include "../common/servertalk.h"
#include "../common/string_util.h"
extern ClientList client_list;
extern ZSList zoneserver_list;
void Expedition::PurgeExpiredExpeditions()
{
std::string query = SQL(
DELETE expedition FROM expedition_details expedition
LEFT JOIN instance_list ON expedition.instance_id = instance_list.id
LEFT JOIN (
SELECT expedition_id, COUNT(IF(is_current_member = TRUE, 1, NULL)) member_count
FROM expedition_members
GROUP BY expedition_id
) AS expedition_members
ON expedition_members.expedition_id = expedition.id
WHERE
expedition.instance_id IS NULL
OR expedition_members.member_count = 0
OR (instance_list.start_time + instance_list.duration) <= UNIX_TIMESTAMP();
);
auto results = database.QueryDatabase(query);
if (!results.Success())
{
LogExpeditions("Failed to purge expired and empty expeditions");
}
}
void Expedition::PurgeExpiredCharacterLockouts()
{
std::string query = SQL(
DELETE FROM expedition_character_lockouts
WHERE expire_time <= NOW();
);
auto results = database.QueryDatabase(query);
if (!results.Success())
{
LogExpeditions("Failed to purge expired lockouts");
}
}
void Expedition::AddPlayer(ServerPacket* pack)
{
auto buf = reinterpret_cast<ServerDzCommand_Struct*>(pack->pBuffer);
ClientListEntry* invited_cle = client_list.FindCharacter(buf->target_name);
if (invited_cle && invited_cle->Server())
{
// continue in the add target's zone
buf->is_char_online = true;
invited_cle->Server()->SendPacket(pack);
}
else
{
// add target not online, return to inviter
ClientListEntry* inviter_cle = client_list.FindCharacter(buf->requester_name);
if (inviter_cle && inviter_cle->Server())
{
inviter_cle->Server()->SendPacket(pack);
}
}
}
void Expedition::MakeLeader(ServerPacket* pack)
{
auto buf = reinterpret_cast<ServerDzCommand_Struct*>(pack->pBuffer);
// notify requester (old leader) and new leader of the result
ZoneServer* new_leader_zs = nullptr;
ClientListEntry* new_leader_cle = client_list.FindCharacter(buf->target_name);
if (new_leader_cle && new_leader_cle->Server())
{
buf->is_char_online = true;
new_leader_zs = new_leader_cle->Server();
new_leader_zs->SendPacket(pack);
}
// if old and new leader are in the same zone only send one message
ClientListEntry* requester_cle = client_list.FindCharacter(buf->requester_name);
if (requester_cle && requester_cle->Server() && requester_cle->Server() != new_leader_zs)
{
requester_cle->Server()->SendPacket(pack);
}
}
void Expedition::GetOnlineMembers(ServerPacket* pack)
{
auto buf = reinterpret_cast<ServerExpeditionCharacters_Struct*>(pack->pBuffer);
// not efficient but only requested during caching
char zone_name[64] = {0};
std::vector<ClientListEntry*> all_clients;
all_clients.reserve(client_list.GetClientCount());
client_list.GetClients(zone_name, all_clients);
for (uint32_t i = 0; i < buf->count; ++i)
{
for (const auto& cle : all_clients)
{
if (cle && cle->CharID() == buf->entries[i].character_id)
{
buf->entries[i].character_zone_id = cle->zone();
buf->entries[i].character_instance_id = cle->instance();
buf->entries[i].character_online = true;
break;
}
}
}
zoneserver_list.SendPacket(buf->sender_zone_id, buf->sender_instance_id, pack);
}