diff --git a/common/servertalk.h b/common/servertalk.h index fc1881d88..cb541bd6c 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -163,6 +163,7 @@ #define ServerOP_ExpeditionDzDuration 0x0413 #define ServerOP_ExpeditionLockoutDuration 0x0414 #define ServerOP_ExpeditionSecondsRemaining 0x0415 +#define ServerOP_ExpeditionExpireWarning 0x0416 #define ServerOP_DzCharacterChange 0x0450 #define ServerOP_DzRemoveAllCharacters 0x0451 @@ -2088,6 +2089,11 @@ struct ServerExpeditionUpdateDuration_Struct { uint32_t new_duration_seconds; }; +struct ServerExpeditionExpireWarning_Struct { + uint32_t expedition_id; + uint32_t minutes_remaining; +}; + struct ServerDzCommand_Struct { uint32 expedition_id; uint8 is_char_online; // 0: target name is offline, 1: online diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index a38b79bf2..e1beff363 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1371,6 +1371,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { case ServerOP_ExpeditionDzCompass: case ServerOP_ExpeditionDzSafeReturn: case ServerOP_ExpeditionDzZoneIn: + case ServerOP_ExpeditionExpireWarning: { zoneserver_list.SendPacket(pack); break; diff --git a/zone/expedition.cpp b/zone/expedition.cpp index 20b2ebaf1..f2fcd808a 100644 --- a/zone/expedition.cpp +++ b/zone/expedition.cpp @@ -1436,6 +1436,15 @@ void Expedition::SendWorldPendingInvite(const ExpeditionInvite& invite, const st SendWorldAddPlayerInvite(invite.inviter_name, invite.swap_remove_name, add_name, true); } +std::unique_ptr Expedition::CreateExpireWarningPacket(uint32_t minutes_remaining) +{ + uint32_t outsize = sizeof(ExpeditionExpireWarning); + auto outapp = std::unique_ptr(new EQApplicationPacket(OP_DzExpeditionEndsWarning, outsize)); + auto buf = reinterpret_cast(outapp->pBuffer); + buf->minutes_remaining = minutes_remaining; + return outapp; +} + std::unique_ptr Expedition::CreateInfoPacket(bool clear) { uint32_t outsize = sizeof(ExpeditionInfo_Struct); @@ -1733,6 +1742,16 @@ void Expedition::SendWorldSetSecondsRemaining(uint32_t seconds_remaining) worldserver.SendPacket(pack.get()); } +void Expedition::SendWorldExpireWarning(uint32_t minutes_remaining) +{ + uint32_t pack_size = sizeof(ServerExpeditionExpireWarning_Struct); + auto pack = std::unique_ptr(new ServerPacket(ServerOP_ExpeditionExpireWarning, pack_size)); + auto buf = reinterpret_cast(pack->pBuffer); + buf->expedition_id = GetID(); + buf->minutes_remaining = minutes_remaining; + worldserver.SendPacket(pack.get()); +} + void Expedition::AddLockoutByCharacterID( uint32_t character_id, const std::string& expedition_name, const std::string& event_name, uint32_t seconds, const std::string& uuid) @@ -2075,6 +2094,16 @@ void Expedition::HandleWorldMessage(ServerPacket* pack) } break; } + case ServerOP_ExpeditionExpireWarning: + { + auto buf = reinterpret_cast(pack->pBuffer); + auto expedition = Expedition::FindCachedExpeditionByID(buf->expedition_id); + if (expedition) + { + expedition->SendMembersExpireWarning(buf->minutes_remaining); + } + break; + } } } @@ -2238,3 +2267,19 @@ std::vector Expedition::GetExpeditionLockoutsByCharacter return lockouts; } + +void Expedition::SendMembersExpireWarning(uint32_t minutes_remaining) +{ + // expeditions warn members in all zones not just the dz + auto outapp = CreateExpireWarningPacket(minutes_remaining); + for (const auto& member : m_members) + { + Client* member_client = entity_list.GetClientByCharID(member.char_id); + if (member_client) + { + member_client->QueuePacket(outapp.get()); + member_client->MessageString(Chat::Yellow, EXPEDITION_MIN_REMAIN, + fmt::format_int(minutes_remaining).c_str()); + } + } +} diff --git a/zone/expedition.h b/zone/expedition.h index b5c33570f..d8efb3052 100644 --- a/zone/expedition.h +++ b/zone/expedition.h @@ -142,6 +142,7 @@ public: void SetLootEventBySpawnID(uint32_t spawn_id, const std::string& event_name); void SendClientExpeditionInfo(Client* client); + void SendWorldExpireWarning(uint32_t minutes); void SendWorldPendingInvite(const ExpeditionInvite& invite, const std::string& add_name); void DzAddPlayer(Client* requester, const std::string& add_char_name, const std::string& swap_remove_name = {}); @@ -187,6 +188,7 @@ private: Client* client, const std::string& inviter_name, const std::string& swap_remove_name); void SendLeaderMessage(Client* leader_client, uint16_t chat_type, uint32_t string_id, const std::initializer_list& args = {}); + void SendMembersExpireWarning(uint32_t minutes); void SendUpdatesToZoneMembers(bool clear = false, bool message_on_clear = true); void SendWorldDzLocationUpdate(uint16_t server_opcode, const DynamicZoneLocation& location); void SendWorldExpeditionUpdate(uint16_t server_opcode); @@ -211,6 +213,7 @@ private: ExpeditionMember GetMemberData(uint32_t character_id); ExpeditionMember GetMemberData(const std::string& character_name); + std::unique_ptr CreateExpireWarningPacket(uint32_t minutes_remaining); std::unique_ptr CreateInfoPacket(bool clear = false); std::unique_ptr CreateInvitePacket(const std::string& inviter_name, const std::string& swap_remove_name); std::unique_ptr CreateMemberListPacket(bool clear = false); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index c144aadf6..920a3d958 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -2909,6 +2909,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) case ServerOP_ExpeditionDzZoneIn: case ServerOP_ExpeditionDzDuration: case ServerOP_ExpeditionCharacterLockout: + case ServerOP_ExpeditionExpireWarning: { Expedition::HandleWorldMessage(pack); break; diff --git a/zone/zone.cpp b/zone/zone.cpp index 3d46a0009..a4bd6cabe 100755 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1508,19 +1508,31 @@ bool Zone::Process() { if(Instance_Warning_timer == nullptr) { uint32 rem_time = Instance_Timer->GetRemainingTime(); + uint32_t minutes_warning = 0; if(rem_time < 60000 && rem_time > 55000) { - entity_list.ExpeditionWarning(1); - Instance_Warning_timer = new Timer(10000); + minutes_warning = 1; } else if(rem_time < 300000 && rem_time > 295000) { - entity_list.ExpeditionWarning(5); - Instance_Warning_timer = new Timer(10000); + minutes_warning = 5; } else if(rem_time < 900000 && rem_time > 895000) { - entity_list.ExpeditionWarning(15); + minutes_warning = 15; + } + + if (minutes_warning > 0) + { + auto expedition = Expedition::FindCachedExpeditionByZoneInstance(GetZoneID(), GetInstanceID()); + if (expedition) + { + expedition->SendWorldExpireWarning(minutes_warning); + } + else + { + entity_list.ExpeditionWarning(minutes_warning); + } Instance_Warning_timer = new Timer(10000); } }