diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 6b3c58e7d..6da387bbd 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -22,7 +22,7 @@ SET(zone_sources corpse.cpp data_bucket.cpp doors.cpp - dynamiczone.cpp + dynamic_zone.cpp effects.cpp embparser.cpp embparser_api.cpp @@ -176,7 +176,7 @@ SET(zone_headers corpse.h data_bucket.h doors.h - dynamiczone.h + dynamic_zone.h embparser.h embperl.h embxs.h diff --git a/zone/client.cpp b/zone/client.cpp index 104dce3bc..98e1b29e4 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -6161,17 +6161,10 @@ void Client::CheckEmoteHail(Mob *target, const char* message) void Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, uint8 count) { - if (count == 0) - { - m_has_quest_compass = false; - } - else - { - m_has_quest_compass = true; - m_quest_compass.x = in_x; - m_quest_compass.y = in_y; - m_quest_compass.z = in_z; - } + m_has_quest_compass = (count != 0); + m_quest_compass.x = in_x; + m_quest_compass.y = in_y; + m_quest_compass.z = in_z; SendDzCompassUpdate(); } @@ -9862,13 +9855,13 @@ void Client::SendDzCompassUpdate() for (const auto& client_dz : GetDynamicZones()) { - auto compass = client_dz.dynamic_zone.GetCompassLocation(); - if (zone && zone->GetZoneID() == compass.zone_id && zone->GetInstanceID() == 0) + auto compass = client_dz->GetCompassLocation(); + if (zone && zone->IsZone(compass.zone_id, 0)) { DynamicZoneCompassEntry_Struct entry; - entry.dz_zone_id = static_cast(client_dz.dynamic_zone.GetZoneID()); - entry.dz_instance_id = static_cast(client_dz.dynamic_zone.GetInstanceID()); - entry.dz_type = static_cast(client_dz.dynamic_zone.GetType()); + entry.dz_zone_id = client_dz->GetZoneID(); + entry.dz_instance_id = client_dz->GetInstanceID(); + entry.dz_type = static_cast(client_dz->GetType()); entry.x = compass.x; entry.y = compass.y; entry.z = compass.z; @@ -9891,6 +9884,12 @@ void Client::SendDzCompassUpdate() compass_entries.emplace_back(entry); } + QueuePacket(CreateCompassPacket(compass_entries).get()); +} + +std::unique_ptr Client::CreateCompassPacket( + const std::vector& compass_entries) +{ uint32 count = static_cast(compass_entries.size()); uint32 entries_size = sizeof(DynamicZoneCompassEntry_Struct) * count; uint32 outsize = sizeof(DynamicZoneCompass_Struct) + entries_size; @@ -9899,7 +9898,7 @@ void Client::SendDzCompassUpdate() outbuf->count = count; memcpy(outbuf->entries, compass_entries.data(), entries_size); - QueuePacket(outapp.get()); + return outapp; } void Client::GoToDzSafeReturnOrBind(const DynamicZone& dynamic_zone) @@ -9919,9 +9918,9 @@ void Client::GoToDzSafeReturnOrBind(const DynamicZone& dynamic_zone) } } -std::vector Client::GetDynamicZones(uint32_t zone_id, int zone_version) +std::vector Client::GetDynamicZones(uint32_t zone_id, int zone_version) { - std::vector client_dzs; + std::vector client_dzs; // check client systems for any associated dynamic zones optionally filtered by zone Expedition* expedition = GetExpedition(); @@ -9929,7 +9928,7 @@ std::vector Client::GetDynamicZones(uint32_t zone_id, int zone_ (zone_id == 0 || expedition->GetDynamicZone().GetZoneID() == zone_id) && (zone_version < 0 || expedition->GetDynamicZone().GetZoneVersion() == zone_version)) { - client_dzs.emplace_back(expedition->GetName(), expedition->GetLeaderName(), expedition->GetDynamicZone()); + client_dzs.emplace_back(&expedition->GetDynamicZone()); } // todo: tasks, missions (shared tasks), and quests with an associated dz to zone_id @@ -9955,38 +9954,41 @@ void Client::MovePCDynamicZone(uint32 zone_id, int zone_version, bool msg_if_inv } else if (client_dzs.size() == 1) { - const DynamicZone& dz = client_dzs[0].dynamic_zone; - DynamicZoneLocation zonein = dz.GetZoneInLocation(); - ZoneMode zone_mode = dz.HasZoneInLocation() ? ZoneMode::ZoneSolicited : ZoneMode::ZoneToSafeCoords; - MovePC(zone_id, dz.GetInstanceID(), zonein.x, zonein.y, zonein.z, zonein.heading, 0, zone_mode); + auto dz = client_dzs.front(); + DynamicZoneLocation zonein = dz->GetZoneInLocation(); + ZoneMode zone_mode = dz->HasZoneInLocation() ? ZoneMode::ZoneSolicited : ZoneMode::ZoneToSafeCoords; + MovePC(zone_id, dz->GetInstanceID(), zonein.x, zonein.y, zonein.z, zonein.heading, 0, zone_mode); } else { - LogDynamicZonesDetail( - "Sending DzSwitchListWnd to character [{}] associated with [{}] dynamic zone(s)", - CharacterID(), client_dzs.size()); + LogDynamicZonesDetail("Sending DzSwitchListWnd to [{}] for zone [{}] with [{}] dynamic zone(s)", + CharacterID(), zone_id, client_dzs.size()); - // more than one dynamic zone to this zone, send out the switchlist window - // note that this will most likely crash clients if they've reloaded the ui - // this occurs on live as well so it may just be a long lasting client bug - uint32 count = static_cast(client_dzs.size()); - uint32 entries_size = sizeof(DynamicZoneChooseZoneEntry_Struct) * count; - uint32 outsize = sizeof(DynamicZoneChooseZone_Struct) + entries_size; - auto outapp = std::make_unique(OP_DzChooseZone, outsize); - auto outbuf = reinterpret_cast(outapp->pBuffer); - outbuf->count = count; - for (int i = 0; i < client_dzs.size(); ++i) - { - outbuf->choices[i].dz_zone_id = client_dzs[i].dynamic_zone.GetZoneID(); - outbuf->choices[i].dz_instance_id = client_dzs[i].dynamic_zone.GetInstanceID(); - outbuf->choices[i].dz_type = static_cast(client_dzs[i].dynamic_zone.GetType()); - strn0cpy(outbuf->choices[i].description, client_dzs[i].description.c_str(), sizeof(outbuf->choices[i].description)); - strn0cpy(outbuf->choices[i].leader_name, client_dzs[i].leader_name.c_str(), sizeof(outbuf->choices[i].leader_name)); - } - QueuePacket(outapp.get()); + // client has more than one dz for this zone, send out the switchlist window + QueuePacket(CreateDzSwitchListPacket(client_dzs).get()); } } +std::unique_ptr Client::CreateDzSwitchListPacket( + const std::vector& client_dzs) +{ + uint32 count = static_cast(client_dzs.size()); + uint32 entries_size = sizeof(DynamicZoneChooseZoneEntry_Struct) * count; + uint32 outsize = sizeof(DynamicZoneChooseZone_Struct) + entries_size; + auto outapp = std::make_unique(OP_DzChooseZone, outsize); + auto outbuf = reinterpret_cast(outapp->pBuffer); + outbuf->count = count; + for (int i = 0; i < client_dzs.size(); ++i) + { + outbuf->choices[i].dz_zone_id = client_dzs[i]->GetZoneID(); + outbuf->choices[i].dz_instance_id = client_dzs[i]->GetInstanceID(); + outbuf->choices[i].dz_type = static_cast(client_dzs[i]->GetType()); + strn0cpy(outbuf->choices[i].description, client_dzs[i]->GetName().c_str(), sizeof(outbuf->choices[i].description)); + strn0cpy(outbuf->choices[i].leader_name, client_dzs[i]->GetLeaderName().c_str(), sizeof(outbuf->choices[i].leader_name)); + } + return outapp; +} + void Client::MovePCDynamicZone(const std::string& zone_name, int zone_version, bool msg_if_invalid) { auto zone_id = ZoneID(zone_name.c_str()); diff --git a/zone/client.h b/zone/client.h index 17af0c01d..f8df6f739 100644 --- a/zone/client.h +++ b/zone/client.h @@ -31,7 +31,6 @@ class Object; class Raid; class Seperator; class ServerPacket; -struct DynamicZoneInfo; struct DynamicZoneLocation; enum WaterRegionType : int; @@ -1356,7 +1355,9 @@ public: void GoToDzSafeReturnOrBind(const DynamicZone& dynamic_zone); void MovePCDynamicZone(uint32 zone_id, int zone_version = -1, bool msg_if_invalid = true); void MovePCDynamicZone(const std::string& zone_name, int zone_version = -1, bool msg_if_invalid = true); - std::vector GetDynamicZones(uint32_t zone_id = 0, int zone_version = -1); + std::vector GetDynamicZones(uint32_t zone_id = 0, int zone_version = -1); + std::unique_ptr CreateDzSwitchListPacket(const std::vector& dzs); + std::unique_ptr CreateCompassPacket(const std::vector& entries); void CalcItemScale(); bool CalcItemScale(uint32 slot_x, uint32 slot_y); // behavior change: 'slot_y' is now [RANGE]_END and not [RANGE]_END + 1 diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 05e6cf183..f4c7f1809 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -5634,30 +5634,26 @@ void Client::Handle_OP_DzAddPlayer(const EQApplicationPacket *app) void Client::Handle_OP_DzChooseZoneReply(const EQApplicationPacket *app) { auto dzmsg = reinterpret_cast(app->pBuffer); - LogDynamicZones( - "Character [{}] chose DynamicZone [{}]:[{}] type: [{}] with system id: [{}]", - CharacterID(), dzmsg->dz_zone_id, dzmsg->dz_instance_id, dzmsg->dz_type, dzmsg->unknown_id2 - ); + + LogDynamicZones("Character [{}] chose DynamicZone [{}]:[{}] type: [{}] with system id: [{}]", + CharacterID(), dzmsg->dz_zone_id, dzmsg->dz_instance_id, dzmsg->dz_type, dzmsg->unknown_id2); if (!dzmsg->dz_instance_id || !database.VerifyInstanceAlive(dzmsg->dz_instance_id, CharacterID())) { // live just no-ops this without a message - LogDynamicZones( - "Character [{}] chose invalid DynamicZone [{}]:[{}] or is no longer a member", - CharacterID(), dzmsg->dz_zone_id, dzmsg->dz_instance_id - ); + LogDynamicZones("Character [{}] chose invalid DynamicZone [{}]:[{}] or is no longer a member", + CharacterID(), dzmsg->dz_zone_id, dzmsg->dz_instance_id); return; } auto client_dzs = GetDynamicZones(); - auto it = std::find_if(client_dzs.begin(), client_dzs.end(), [&](const DynamicZoneInfo dz_info) { - return dz_info.dynamic_zone.IsSameDz(dzmsg->dz_zone_id, dzmsg->dz_instance_id); - }); + auto it = std::find_if(client_dzs.begin(), client_dzs.end(), [&](const DynamicZone* dz) { + return dz->IsSameDz(dzmsg->dz_zone_id, dzmsg->dz_instance_id); }); if (it != client_dzs.end()) { - DynamicZoneLocation loc = it->dynamic_zone.GetZoneInLocation(); - ZoneMode zone_mode = it->dynamic_zone.HasZoneInLocation() ? ZoneMode::ZoneSolicited : ZoneMode::ZoneToSafeCoords; + DynamicZoneLocation loc = (*it)->GetZoneInLocation(); + ZoneMode zone_mode = (*it)->HasZoneInLocation() ? ZoneMode::ZoneSolicited : ZoneMode::ZoneToSafeCoords; MovePC(dzmsg->dz_zone_id, dzmsg->dz_instance_id, loc.x, loc.y, loc.z, loc.heading, 0, zone_mode); } } diff --git a/zone/dynamiczone.cpp b/zone/dynamic_zone.cpp similarity index 99% rename from zone/dynamiczone.cpp rename to zone/dynamic_zone.cpp index ba367351e..72b42abba 100644 --- a/zone/dynamiczone.cpp +++ b/zone/dynamic_zone.cpp @@ -18,7 +18,7 @@ * */ -#include "dynamiczone.h" +#include "dynamic_zone.h" #include "client.h" #include "worldserver.h" #include "zonedb.h" diff --git a/zone/dynamiczone.h b/zone/dynamic_zone.h similarity index 91% rename from zone/dynamiczone.h rename to zone/dynamic_zone.h index d519539e0..19d186bba 100644 --- a/zone/dynamiczone.h +++ b/zone/dynamic_zone.h @@ -18,8 +18,8 @@ * */ -#ifndef DYNAMICZONE_H -#define DYNAMICZONE_H +#ifndef DYNAMIC_ZONE_H +#define DYNAMIC_ZONE_H #include #include @@ -73,6 +73,8 @@ public: uint16_t GetZoneID() const { return static_cast(m_zone_id); } uint32_t GetZoneIndex() const { return (m_instance_id << 16) | (m_zone_id & 0xffff); } uint32_t GetZoneVersion() const { return m_version; } + const std::string& GetLeaderName() const { return m_leader_name; } + const std::string& GetName() const { return m_name; } DynamicZoneType GetType() const { return m_type; } DynamicZoneLocation GetCompassLocation() const { return m_compass; } DynamicZoneLocation GetSafeReturnLocation() const { return m_safereturn; } @@ -91,6 +93,8 @@ public: void SaveInstanceMembersToDatabase(const std::vector& character_ids); void SendInstanceCharacterChange(uint32_t character_id, bool removed); void SetCompass(const DynamicZoneLocation& location, bool update_db = false); + void SetLeaderName(const std::string& leader_name) { m_leader_name = leader_name; } + void SetName(const std::string& name) { m_name = name; } void SetSafeReturn(const DynamicZoneLocation& location, bool update_db = false); void SetZoneInLocation(const DynamicZoneLocation& location, bool update_db = false); void SetUpdatedDuration(uint32_t seconds); @@ -109,7 +113,9 @@ private: uint32_t m_version = 0; bool m_never_expires = false; bool m_has_zonein = false; - DynamicZoneType m_type = DynamicZoneType::None; + std::string m_name; + std::string m_leader_name; + DynamicZoneType m_type{ DynamicZoneType::None }; DynamicZoneLocation m_compass; DynamicZoneLocation m_safereturn; DynamicZoneLocation m_zonein; @@ -118,15 +124,4 @@ private: std::chrono::time_point m_expire_time; }; -struct DynamicZoneInfo -{ - std::string description; // from owning system - std::string leader_name; - DynamicZone dynamic_zone; - - DynamicZoneInfo() = default; - DynamicZoneInfo(std::string desc, std::string leader, const DynamicZone& dz) - : description(std::move(desc)), leader_name(std::move(leader)), dynamic_zone(dz) {} -}; - #endif diff --git a/zone/entity.cpp b/zone/entity.cpp index d9f6c591f..4125cbe36 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -33,7 +33,7 @@ #include "../common/guilds.h" #include "entity.h" -#include "dynamiczone.h" +#include "dynamic_zone.h" #include "guild_mgr.h" #include "petitions.h" #include "quest_parser_collection.h" diff --git a/zone/expedition.cpp b/zone/expedition.cpp index 7b6d053c2..4236f68cc 100644 --- a/zone/expedition.cpp +++ b/zone/expedition.cpp @@ -50,17 +50,25 @@ const int32_t Expedition::REPLAY_TIMER_ID = -1; const int32_t Expedition::EVENT_TIMER_ID = 1; Expedition::Expedition( - uint32_t id, const std::string& uuid, const DynamicZone& dynamic_zone, const std::string& expedition_name, + uint32_t id, const std::string& uuid, DynamicZone&& dz, const std::string& expedition_name, const ExpeditionMember& leader, uint32_t min_players, uint32_t max_players ) : m_id(id), m_uuid(uuid), - m_dynamiczone(dynamic_zone), m_expedition_name(expedition_name), m_leader(leader), m_min_players(min_players), m_max_players(max_players) { + SetDynamicZone(std::move(dz)); +} + +void Expedition::SetDynamicZone(DynamicZone&& dz) +{ + dz.SetName(GetName()); + dz.SetLeaderName(GetLeaderName()); + + m_dynamiczone = std::move(dz); } Expedition* Expedition::TryCreate( @@ -105,7 +113,7 @@ Expedition* Expedition::TryCreate( auto expedition = std::make_unique( expedition_id, expedition_uuid, - dynamiczone, + std::move(dynamiczone), request.GetExpeditionName(), ExpeditionMember{ request.GetLeaderID(), request.GetLeaderName() }, request.GetMinPlayers(), @@ -219,7 +227,7 @@ void Expedition::CacheExpeditions(MySQLRequestResult& results) auto dz_iter = dynamic_zones.find(expedition->GetDynamicZoneID()); if (dz_iter != dynamic_zones.end()) { - expedition->m_dynamiczone = dz_iter->second; + expedition->SetDynamicZone(std::move(dz_iter->second)); } auto lockout_iter = expedition_lockouts.find(expedition->GetID()); @@ -1137,6 +1145,7 @@ void Expedition::ProcessLeaderChanged(uint32_t new_leader_id) LogExpeditionsModerate("Replaced [{}] leader [{}] with [{}]", m_id, m_leader.name, new_leader.name); m_leader = new_leader; + m_dynamiczone.SetLeaderName(m_leader.name); // update each client's expedition window in this zone auto outapp_leader = CreateLeaderNamePacket(); diff --git a/zone/expedition.h b/zone/expedition.h index 7e6c4a048..2b7a4ed4d 100644 --- a/zone/expedition.h +++ b/zone/expedition.h @@ -21,7 +21,7 @@ #ifndef EXPEDITION_H #define EXPEDITION_H -#include "dynamiczone.h" +#include "dynamic_zone.h" #include "expedition_lockout_timer.h" #include "../common/eq_constants.h" #include @@ -76,7 +76,7 @@ class Expedition { public: Expedition() = delete; - Expedition(uint32_t id, const std::string& uuid, const DynamicZone& dz, const std::string& expedition_name, + Expedition(uint32_t id, const std::string& uuid, DynamicZone&& dz, const std::string& expedition_name, const ExpeditionMember& leader, uint32_t min_players, uint32_t max_players); static Expedition* TryCreate(Client* requester, DynamicZone& dynamiczone, ExpeditionRequest& request); @@ -111,7 +111,7 @@ public: uint32_t GetMinPlayers() const { return m_min_players; } uint32_t GetMaxPlayers() const { return m_max_players; } uint32_t GetMemberCount() const { return static_cast(m_members.size()); } - const DynamicZone& GetDynamicZone() const { return m_dynamiczone; } + DynamicZone& GetDynamicZone() { return m_dynamiczone; } const std::string& GetName() const { return m_expedition_name; } const std::string& GetLeaderName() const { return m_leader.name; } const std::string& GetUUID() const { return m_uuid; } @@ -209,6 +209,7 @@ private: const std::string& add_char_name, uint32_t add_char_id); void SendWorldSetSecondsRemaining(uint32_t seconds_remaining); void SendWorldSettingChanged(uint16_t server_opcode, bool setting_value); + void SetDynamicZone(DynamicZone&& dz); void TryAddClient(Client* add_client, const std::string& inviter_name, const std::string& swap_remove_name, Client* leader_client = nullptr); void UpdateDzDuration(uint32_t new_duration) { m_dynamiczone.SetUpdatedDuration(new_duration); } diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 580f997e4..8db059c55 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -4,7 +4,7 @@ #include #include "client.h" -#include "dynamiczone.h" +#include "dynamic_zone.h" #include "expedition_lockout_timer.h" #include "expedition_request.h" #include "lua_client.h" diff --git a/zone/zone.h b/zone/zone.h index 31c0f16ee..6d9a0e963 100755 --- a/zone/zone.h +++ b/zone/zone.h @@ -33,7 +33,7 @@ #include "spawn2.h" #include "spawngroup.h" #include "aa_ability.h" -#include "dynamiczone.h" +#include "dynamic_zone.h" #include "pathfinder_interface.h" #include "global_loot_manager.h"