Make adding replay timers to new members optional

Not all expeditions with a replay timer lockout add it to newly
added members automatically

This adds the Expedition::SetReplayLockoutOnMemberJoin(bool) method
to the quest api so it can be disabled
This commit is contained in:
hg 2020-05-23 22:48:29 -04:00
parent a7795eda5d
commit 5ddb62e275
10 changed files with 95 additions and 14 deletions

View File

@ -157,6 +157,7 @@
#define ServerOP_ExpeditionRemoveCharLockouts 0x040d #define ServerOP_ExpeditionRemoveCharLockouts 0x040d
#define ServerOP_ExpeditionSaveInvite 0x040e #define ServerOP_ExpeditionSaveInvite 0x040e
#define ServerOP_ExpeditionRequestInvite 0x040f #define ServerOP_ExpeditionRequestInvite 0x040f
#define ServerOP_ExpeditionReplayOnJoin 0x0410
#define ServerOP_DzCharacterChange 0x0450 #define ServerOP_DzCharacterChange 0x0450
#define ServerOP_DzRemoveAllCharacters 0x0451 #define ServerOP_DzRemoveAllCharacters 0x0451
@ -2054,6 +2055,13 @@ struct ServerExpeditionLockout_Struct {
char event_name[256]; char event_name[256];
}; };
struct ServerExpeditionSetting_Struct {
uint32 expedition_id;
uint32 sender_zone_id;
uint16 sender_instance_id;
uint8 enabled;
};
struct ServerExpeditionCharacterName_Struct { struct ServerExpeditionCharacterName_Struct {
char character_name[64]; char character_name[64];
char expedition_name[128]; char expedition_name[128];

View File

@ -6,6 +6,7 @@ CREATE TABLE `expedition_details` (
`min_players` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0, `min_players` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
`max_players` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0, `max_players` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
`has_replay_timer` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0, `has_replay_timer` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0,
`add_replay_on_join` TINYINT(3) UNSIGNED NOT NULL DEFAULT 1,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE INDEX `instance_id` (`instance_id`), UNIQUE INDEX `instance_id` (`instance_id`),
CONSTRAINT `FK_expedition_details_instance_list` FOREIGN KEY (`instance_id`) REFERENCES `instance_list` (`id`) ON DELETE SET NULL CONSTRAINT `FK_expedition_details_instance_list` FOREIGN KEY (`instance_id`) REFERENCES `instance_list` (`id`) ON DELETE SET NULL

View File

@ -1375,6 +1375,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
case ServerOP_ExpeditionMemberChange: case ServerOP_ExpeditionMemberChange:
case ServerOP_ExpeditionMemberSwap: case ServerOP_ExpeditionMemberSwap:
case ServerOP_ExpeditionMemberStatus: case ServerOP_ExpeditionMemberStatus:
case ServerOP_ExpeditionReplayOnJoin:
case ServerOP_ExpeditionDzCompass: case ServerOP_ExpeditionDzCompass:
case ServerOP_ExpeditionDzSafeReturn: case ServerOP_ExpeditionDzSafeReturn:
case ServerOP_ExpeditionDzZoneIn: case ServerOP_ExpeditionDzZoneIn:

View File

@ -160,7 +160,7 @@ void Expedition::CacheExpeditions(MySQLRequestResult& results)
if (expedition_id != last_expedition_id) if (expedition_id != last_expedition_id)
{ {
auto leader_id = static_cast<uint32_t>(strtoul(row[3], nullptr, 10)); auto leader_id = static_cast<uint32_t>(strtoul(row[3], nullptr, 10));
ExpeditionMember leader{ leader_id, row[7] }; // id, name ExpeditionMember leader{ leader_id, row[8] }; // id, name
auto instance_id = row[1] ? strtoul(row[1], nullptr, 10) : 0; // can be null from fk constraint auto instance_id = row[1] ? strtoul(row[1], nullptr, 10) : 0; // can be null from fk constraint
DynamicZone dynamic_zone = DynamicZone::LoadDzFromDatabase(instance_id); DynamicZone dynamic_zone = DynamicZone::LoadDzFromDatabase(instance_id);
@ -175,6 +175,9 @@ void Expedition::CacheExpeditions(MySQLRequestResult& results)
(strtoul(row[6], nullptr, 10) != 0) // has_replay_timer (strtoul(row[6], nullptr, 10) != 0) // has_replay_timer
)); ));
bool add_replay_on_join = (strtoul(row[7], nullptr, 10) != 0);
expedition->SetReplayLockoutOnMemberJoin(add_replay_on_join);
expedition->LoadMembers(); expedition->LoadMembers();
expedition->SendUpdatesToZoneMembers(); expedition->SendUpdatesToZoneMembers();
@ -188,17 +191,17 @@ void Expedition::CacheExpeditions(MySQLRequestResult& results)
last_expedition_id = expedition_id; last_expedition_id = expedition_id;
// optional lockouts from left join // optional lockouts from left join
if (row[8] && row[9] && row[10] && row[11]) if (row[9] && row[10] && row[11] && row[12])
{ {
auto it = zone->expedition_cache.find(last_expedition_id); auto it = zone->expedition_cache.find(last_expedition_id);
if (it != zone->expedition_cache.end()) if (it != zone->expedition_cache.end())
{ {
it->second->AddInternalLockout(ExpeditionLockoutTimer{ it->second->AddInternalLockout(ExpeditionLockoutTimer{
row[2], // expedition_name row[2], // expedition_name
row[8], // event_name row[9], // event_name
strtoull(row[9], nullptr, 10), // expire_time strtoull(row[10], nullptr, 10), // expire_time
static_cast<uint32_t>(strtoul(row[10], nullptr, 10)), // original duration static_cast<uint32_t>(strtoul(row[11], nullptr, 10)), // original duration
(strtoul(row[11], nullptr, 10) != 0) // is_inherited (strtoul(row[12], nullptr, 10) != 0) // is_inherited
}); });
} }
} }
@ -392,6 +395,17 @@ ExpeditionMember Expedition::GetMemberData(const std::string& character_name)
return member_data; return member_data;
} }
void Expedition::SetReplayLockoutOnMemberJoin(bool add_on_join, bool update_db)
{
m_add_replay_on_join = add_on_join;
if (update_db)
{
ExpeditionDatabase::UpdateReplayLockoutOnJoin(m_id, add_on_join);
SendWorldSettingChanged(ServerOP_ExpeditionReplayOnJoin, m_add_replay_on_join);
}
}
void Expedition::AddReplayLockout(uint32_t seconds) void Expedition::AddReplayLockout(uint32_t seconds)
{ {
AddLockout(DZ_REPLAY_TIMER_NAME, seconds); AddLockout(DZ_REPLAY_TIMER_NAME, seconds);
@ -774,12 +788,15 @@ void Expedition::DzInviteResponse(Client* add_client, bool accepted, const std::
if (!lockout.IsInherited() && if (!lockout.IsInherited() &&
!add_client->HasExpeditionLockout(m_expedition_name, lockout.GetEventName())) !add_client->HasExpeditionLockout(m_expedition_name, lockout.GetEventName()))
{ {
// replay timers are added to characters immediately on joining with // replay timers are optionally added to new members immediately on
// a fresh expire time using the original duration // join with a fresh expire time using the original duration.
if (m_has_replay_timer && lockout.IsReplayTimer()) if (m_has_replay_timer && lockout.IsReplayTimer())
{ {
add_client->AddNewExpeditionLockout( if (m_add_replay_on_join)
lockout.GetExpeditionName(), lockout.GetEventName(), lockout.GetDuration()); {
add_client->AddNewExpeditionLockout(
lockout.GetExpeditionName(), lockout.GetEventName(), lockout.GetDuration());
}
} }
else else
{ {
@ -1499,6 +1516,18 @@ void Expedition::SendWorldMemberSwapped(
worldserver.SendPacket(pack.get()); worldserver.SendPacket(pack.get());
} }
void Expedition::SendWorldSettingChanged(uint16_t server_opcode, bool setting_value)
{
uint32_t pack_size = sizeof(ServerExpeditionSetting_Struct);
auto pack = std::unique_ptr<ServerPacket>(new ServerPacket(server_opcode, pack_size));
auto buf = reinterpret_cast<ServerExpeditionSetting_Struct*>(pack->pBuffer);
buf->expedition_id = GetID();
buf->sender_zone_id = zone ? zone->GetZoneID() : 0;
buf->sender_instance_id = zone ? zone->GetInstanceID() : 0;
buf->enabled = setting_value;
worldserver.SendPacket(pack.get());
}
void Expedition::SendWorldGetOnlineMembers() void Expedition::SendWorldGetOnlineMembers()
{ {
// request online status of all characters in our expedition tracked by world // request online status of all characters in our expedition tracked by world
@ -1649,6 +1678,19 @@ void Expedition::HandleWorldMessage(ServerPacket* pack)
} }
break; break;
} }
case ServerOP_ExpeditionReplayOnJoin:
{
auto buf = reinterpret_cast<ServerExpeditionSetting_Struct*>(pack->pBuffer);
if (zone && !zone->IsZone(buf->sender_zone_id, buf->sender_instance_id))
{
auto expedition = Expedition::FindCachedExpeditionByID(buf->expedition_id);
if (expedition)
{
expedition->SetReplayLockoutOnMemberJoin(buf->enabled);
}
}
break;
}
case ServerOP_ExpeditionGetOnlineMembers: case ServerOP_ExpeditionGetOnlineMembers:
{ {
// reply from world for online member statuses request // reply from world for online member statuses request

View File

@ -113,6 +113,7 @@ public:
bool HasLockout(const std::string& event_name); bool HasLockout(const std::string& event_name);
bool HasReplayLockout(); bool HasReplayLockout();
void RemoveLockout(const std::string& event_name); void RemoveLockout(const std::string& event_name);
void SetReplayLockoutOnMemberJoin(bool add_on_join, bool update_db = false);
void SendClientExpeditionInfo(Client* client); void SendClientExpeditionInfo(Client* client);
void SendWorldPendingInvite(const ExpeditionInvite& invite, const std::string& add_name); void SendWorldPendingInvite(const ExpeditionInvite& invite, const std::string& add_name);
@ -163,6 +164,7 @@ private:
void SendWorldMemberChanged(const std::string& char_name, uint32_t char_id, bool remove); void SendWorldMemberChanged(const std::string& char_name, uint32_t char_id, bool remove);
void SendWorldMemberStatus(uint32_t character_id, ExpeditionMemberStatus status); void SendWorldMemberStatus(uint32_t character_id, ExpeditionMemberStatus status);
void SendWorldMemberSwapped(const std::string& remove_char_name, uint32_t remove_char_id, const std::string& add_char_name, uint32_t add_char_id); void SendWorldMemberSwapped(const std::string& remove_char_name, uint32_t remove_char_id, const std::string& add_char_name, uint32_t add_char_id);
void SendWorldSettingChanged(uint16_t server_opcode, bool setting_value);
void TryAddClient(Client* add_client, std::string inviter_name, std::string orig_add_name, std::string swap_remove_name, Client* leader_client = nullptr); void TryAddClient(Client* add_client, std::string inviter_name, std::string orig_add_name, std::string swap_remove_name, Client* leader_client = nullptr);
void UpdateMemberStatus(uint32_t update_character_id, ExpeditionMemberStatus status); void UpdateMemberStatus(uint32_t update_character_id, ExpeditionMemberStatus status);
@ -175,10 +177,11 @@ private:
std::unique_ptr<EQApplicationPacket> CreateMemberListStatusPacket(const std::string& name, ExpeditionMemberStatus status); std::unique_ptr<EQApplicationPacket> CreateMemberListStatusPacket(const std::string& name, ExpeditionMemberStatus status);
std::unique_ptr<EQApplicationPacket> CreateLeaderNamePacket(); std::unique_ptr<EQApplicationPacket> CreateLeaderNamePacket();
uint32_t m_id = 0; uint32_t m_id = 0;
uint32_t m_min_players = 0; uint32_t m_min_players = 0;
uint32_t m_max_players = 0; uint32_t m_max_players = 0;
bool m_has_replay_timer = false; bool m_has_replay_timer = false;
bool m_add_replay_on_join = true;
std::string m_expedition_name; std::string m_expedition_name;
DynamicZone m_dynamiczone { DynamicZoneType::Expedition }; DynamicZone m_dynamiczone { DynamicZoneType::Expedition };
ExpeditionMember m_leader; ExpeditionMember m_leader;

View File

@ -62,6 +62,7 @@ MySQLRequestResult ExpeditionDatabase::LoadExpedition(uint32_t expedition_id)
expedition_details.min_players, expedition_details.min_players,
expedition_details.max_players, expedition_details.max_players,
expedition_details.has_replay_timer, expedition_details.has_replay_timer,
expedition_details.add_replay_on_join,
character_data.name leader_name, character_data.name leader_name,
expedition_lockouts.event_name, expedition_lockouts.event_name,
UNIX_TIMESTAMP(expedition_lockouts.expire_time), UNIX_TIMESTAMP(expedition_lockouts.expire_time),
@ -93,6 +94,7 @@ MySQLRequestResult ExpeditionDatabase::LoadAllExpeditions()
expedition_details.min_players, expedition_details.min_players,
expedition_details.max_players, expedition_details.max_players,
expedition_details.has_replay_timer, expedition_details.has_replay_timer,
expedition_details.add_replay_on_join,
character_data.name leader_name, character_data.name leader_name,
expedition_lockouts.event_name, expedition_lockouts.event_name,
UNIX_TIMESTAMP(expedition_lockouts.expire_time), UNIX_TIMESTAMP(expedition_lockouts.expire_time),
@ -656,3 +658,18 @@ void ExpeditionDatabase::UpdateMemberRemoved(uint32_t expedition_id, uint32_t ch
LogExpeditions("Failed to remove [{}] from expedition [{}]", character_id, expedition_id); LogExpeditions("Failed to remove [{}] from expedition [{}]", character_id, expedition_id);
} }
} }
void ExpeditionDatabase::UpdateReplayLockoutOnJoin(uint32_t expedition_id, bool add_on_join)
{
LogExpeditionsDetail("Updating replay lockout on join [{}] for expedition [{}]", add_on_join, expedition_id);
auto query = fmt::format(SQL(
UPDATE expedition_details SET add_replay_on_join = {} WHERE id = {};
), add_on_join, expedition_id);
auto results = database.QueryDatabase(query);
if (!results.Success())
{
LogExpeditions("Failed to update expedition [{}] replay timer setting", expedition_id);
}
}

View File

@ -68,6 +68,7 @@ namespace ExpeditionDatabase
void InsertMembers(uint32_t expedition_id, const std::vector<ExpeditionMember>& members); void InsertMembers(uint32_t expedition_id, const std::vector<ExpeditionMember>& members);
void UpdateLeaderID(uint32_t expedition_id, uint32_t leader_id); void UpdateLeaderID(uint32_t expedition_id, uint32_t leader_id);
void UpdateMemberRemoved(uint32_t expedition_id, uint32_t character_id); void UpdateMemberRemoved(uint32_t expedition_id, uint32_t character_id);
void UpdateReplayLockoutOnJoin(uint32_t expedition_id, bool add_on_join);
}; };
#endif #endif

View File

@ -125,6 +125,11 @@ void Lua_Expedition::SetCompass(std::string zone_name, float x, float y, float z
return self->SetDzCompass(zone_name, x, y, z, true); return self->SetDzCompass(zone_name, x, y, z, true);
} }
void Lua_Expedition::SetReplayLockoutOnMemberJoin(bool enable) {
Lua_Safe_Call_Void();
self->SetReplayLockoutOnMemberJoin(enable, true);
}
void Lua_Expedition::SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading) { void Lua_Expedition::SetSafeReturn(uint32_t zone_id, float x, float y, float z, float heading) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
return self->SetDzSafeReturn(zone_id, x, y, z, heading, true); return self->SetDzSafeReturn(zone_id, x, y, z, heading, true);
@ -161,6 +166,7 @@ luabind::scope lua_register_expedition() {
.def("RemoveLockout", (void(Lua_Expedition::*)(std::string))&Lua_Expedition::RemoveLockout) .def("RemoveLockout", (void(Lua_Expedition::*)(std::string))&Lua_Expedition::RemoveLockout)
.def("SetCompass", (void(Lua_Expedition::*)(uint32_t, float, float, float))&Lua_Expedition::SetCompass) .def("SetCompass", (void(Lua_Expedition::*)(uint32_t, float, float, float))&Lua_Expedition::SetCompass)
.def("SetCompass", (void(Lua_Expedition::*)(std::string, float, float, float))&Lua_Expedition::SetCompass) .def("SetCompass", (void(Lua_Expedition::*)(std::string, float, float, float))&Lua_Expedition::SetCompass)
.def("SetReplayLockoutOnMemberJoin", (void(Lua_Expedition::*)(bool))&Lua_Expedition::SetReplayLockoutOnMemberJoin)
.def("SetSafeReturn", (void(Lua_Expedition::*)(uint32_t, float, float, float, float))&Lua_Expedition::SetSafeReturn) .def("SetSafeReturn", (void(Lua_Expedition::*)(uint32_t, float, float, float, float))&Lua_Expedition::SetSafeReturn)
.def("SetSafeReturn", (void(Lua_Expedition::*)(std::string, float, float, float, float))&Lua_Expedition::SetSafeReturn) .def("SetSafeReturn", (void(Lua_Expedition::*)(std::string, float, float, float, float))&Lua_Expedition::SetSafeReturn)
.def("SetZoneInLocation", (void(Lua_Expedition::*)(float, float, float, float))&Lua_Expedition::SetZoneInLocation); .def("SetZoneInLocation", (void(Lua_Expedition::*)(float, float, float, float))&Lua_Expedition::SetZoneInLocation);

View File

@ -68,6 +68,7 @@ public:
void RemoveLockout(std::string event_name); void RemoveLockout(std::string event_name);
void SetCompass(uint32 zone_id, float x, float y, float z); void SetCompass(uint32 zone_id, float x, float y, float z);
void SetCompass(std::string zone_name, float x, float y, float z); void SetCompass(std::string zone_name, float x, float y, float z);
void SetReplayLockoutOnMemberJoin(bool enable);
void SetSafeReturn(uint32 zone_id, float x, float y, float z, float heading); void SetSafeReturn(uint32 zone_id, float x, float y, float z, float heading);
void SetSafeReturn(std::string zone_name, float x, float y, float z, float heading); void SetSafeReturn(std::string zone_name, float x, float y, float z, float heading);
void SetZoneInLocation(float x, float y, float z, float heading); void SetZoneInLocation(float x, float y, float z, float heading);

View File

@ -2906,6 +2906,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
case ServerOP_ExpeditionMemberChange: case ServerOP_ExpeditionMemberChange:
case ServerOP_ExpeditionMemberSwap: case ServerOP_ExpeditionMemberSwap:
case ServerOP_ExpeditionMemberStatus: case ServerOP_ExpeditionMemberStatus:
case ServerOP_ExpeditionReplayOnJoin:
case ServerOP_ExpeditionGetOnlineMembers: case ServerOP_ExpeditionGetOnlineMembers:
case ServerOP_ExpeditionDzAddPlayer: case ServerOP_ExpeditionDzAddPlayer:
case ServerOP_ExpeditionDzMakeLeader: case ServerOP_ExpeditionDzMakeLeader: