diff --git a/common/ruletypes.h b/common/ruletypes.h index 67a63c02d..31fb54fce 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -796,6 +796,7 @@ RULE_INT(Expedition, WorldExpeditionProcessRateMS, 6000, "Timer interval (ms) th RULE_BOOL(Expedition, AlwaysNotifyNewLeaderOnChange, false, "Always notify clients when made expedition leader. If false (live-like) new leaders are only notified when made leader via /dzmakeleader") RULE_REAL(Expedition, LockoutDurationMultiplier, 1.0, "Multiplies lockout duration by this value when new lockouts are added") RULE_BOOL(Expedition, EnableInDynamicZoneStatus, false, "Enables the 'In Dynamic Zone' member status in expedition window. If false (live-like) players inside the dz will show as 'Online'") +RULE_INT(Expedition, ChooseLeaderCooldownTime, 2000, "Cooldown time (ms) between choosing a new leader for automatic leader changes") RULE_CATEGORY_END() RULE_CATEGORY(DynamicZone) diff --git a/world/expedition.cpp b/world/expedition.cpp index b3b1dd682..c2562b5c2 100644 --- a/world/expedition.cpp +++ b/world/expedition.cpp @@ -25,6 +25,7 @@ #include "zonelist.h" #include "zoneserver.h" #include "../common/eqemu_logsys.h" +#include "../common/rulesys.h" extern ClientList client_list; extern ZSList zoneserver_list; @@ -38,7 +39,8 @@ Expedition::Expedition(uint32_t expedition_id, uint32_t dz_id, uint32_t dz_insta m_dz_zone_id(dz_zone_id), m_start_time(std::chrono::system_clock::from_time_t(start_time)), m_duration(duration), - m_leader_id(leader_id) + m_leader_id(leader_id), + m_choose_leader_cooldown_timer{ static_cast(RuleI(Expedition, ChooseLeaderCooldownTime)) } { m_expire_time = m_start_time + m_duration; m_warning_cooldown_timer.Enable(); @@ -67,7 +69,7 @@ void Expedition::RemoveMember(uint32_t character_id) [&](uint32_t member_id) { return member_id == character_id; } ), m_member_ids.end()); - if (!m_member_ids.empty() && character_id == m_leader_id) + if (character_id == m_leader_id) { ChooseNewLeader(); } @@ -75,6 +77,12 @@ void Expedition::RemoveMember(uint32_t character_id) void Expedition::ChooseNewLeader() { + if (m_member_ids.empty() || !m_choose_leader_cooldown_timer.Check()) + { + m_choose_leader_needed = true; + return; + } + // we don't track expedition member status in world so may choose a linkdead member // this is fine since it will trigger another change when that member goes offline auto it = std::find_if(m_member_ids.begin(), m_member_ids.end(), [&](uint32_t member_id) { @@ -89,9 +97,9 @@ void Expedition::ChooseNewLeader() [&](uint32_t member_id) { return (member_id != m_leader_id); }); } - if (it != m_member_ids.end()) + if (it != m_member_ids.end() && SetNewLeader(*it)) { - SetNewLeader(*it); + m_choose_leader_needed = false; } } @@ -193,3 +201,11 @@ void Expedition::CheckExpireWarning() } } } + +void Expedition::CheckLeader() +{ + if (m_choose_leader_needed) + { + ChooseNewLeader(); + } +} diff --git a/world/expedition.h b/world/expedition.h index 0b5f04e78..d166419bb 100644 --- a/world/expedition.h +++ b/world/expedition.h @@ -37,6 +37,7 @@ public: void RemoveMember(uint32_t character_id); void RemoveAllMembers() { m_member_ids.clear(); } void CheckExpireWarning(); + void CheckLeader(); void ChooseNewLeader(); uint32_t GetID() const { return m_expedition_id; } uint16_t GetInstanceID() const { return static_cast(m_dz_instance_id); } @@ -62,8 +63,10 @@ private: uint32_t m_dz_instance_id = 0; uint32_t m_dz_zone_id = 0; uint32_t m_leader_id = 0; - bool m_pending_delete = false; - Timer m_warning_cooldown_timer; + bool m_pending_delete = false; + bool m_choose_leader_needed = false; + Timer m_choose_leader_cooldown_timer; + Timer m_warning_cooldown_timer; std::vector m_member_ids; std::chrono::seconds m_duration; std::chrono::time_point m_start_time; diff --git a/world/expedition_state.cpp b/world/expedition_state.cpp index 332231f1b..794cfeb36 100644 --- a/world/expedition_state.cpp +++ b/world/expedition_state.cpp @@ -145,6 +145,7 @@ void ExpeditionState::Process() else { it->CheckExpireWarning(); + it->CheckLeader(); } it = is_deleted ? m_expeditions.erase(it) : it + 1;