From 1001a9af15caaf5f2579cb363e3a686a0f572f66 Mon Sep 17 00:00:00 2001 From: cybermist2 Date: Mon, 28 Nov 2022 21:14:10 +0200 Subject: [PATCH] Implement AutoBroadcast system --- .../mangos_string_10000_autobroadcast.sql | 2 + sql/create/world.autobroadcast.sql | 10 ++ src/game/Chat/Chat.cpp | 1 + src/game/Chat/Chat.h | 1 + src/game/Chat/Level3.cpp | 8 ++ src/game/Tools/Language.h | 1 + src/game/World/World.cpp | 130 ++++++++++++++++++ src/game/World/World.h | 15 ++ src/mangosd/mangosd.conf.dist.in | 7 + 9 files changed, 175 insertions(+) create mode 100644 sql/create/mangos_string_10000_autobroadcast.sql create mode 100644 sql/create/world.autobroadcast.sql diff --git a/sql/create/mangos_string_10000_autobroadcast.sql b/sql/create/mangos_string_10000_autobroadcast.sql new file mode 100644 index 0000000000..4539f7d441 --- /dev/null +++ b/sql/create/mangos_string_10000_autobroadcast.sql @@ -0,0 +1,2 @@ +REPLACE INTO `mangos_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES +(10000, '|cffff0000[Server Announce]:|r %s', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); diff --git a/sql/create/world.autobroadcast.sql b/sql/create/world.autobroadcast.sql new file mode 100644 index 0000000000..f76ba2196c --- /dev/null +++ b/sql/create/world.autobroadcast.sql @@ -0,0 +1,10 @@ +CREATE TABLE `autobroadcast` ( + `id` TINYINT(3) UNSIGNED NOT NULL AUTO_INCREMENT, + `content` TEXT NULL DEFAULT NULL COLLATE 'utf8_general_ci', + `ratio` SMALLINT(6) UNSIGNED NOT NULL DEFAULT '1', + PRIMARY KEY (`id`) USING BTREE +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB +AUTO_INCREMENT=3 +; diff --git a/src/game/Chat/Chat.cpp b/src/game/Chat/Chat.cpp index 4d77d9d4f4..b339a06e77 100644 --- a/src/game/Chat/Chat.cpp +++ b/src/game/Chat/Chat.cpp @@ -604,6 +604,7 @@ ChatCommand* ChatHandler::getCommandTable() { "areatrigger_involvedrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestAreaTriggersCommand, "", nullptr }, { "areatrigger_tavern", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTavernCommand, "", nullptr }, { "areatrigger_teleport", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTeleportCommand, "", nullptr }, + { "autobroadcast", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAutoBroadcastCommand, "", nullptr }, { "command", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCommandCommand, "", nullptr }, { "conditions", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadConditionsCommand, "", nullptr }, { "creature_ai_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAIScriptsCommand, "", nullptr }, diff --git a/src/game/Chat/Chat.h b/src/game/Chat/Chat.h index a06ef3e60a..e14bad06f3 100644 --- a/src/game/Chat/Chat.h +++ b/src/game/Chat/Chat.h @@ -529,6 +529,7 @@ class ChatHandler bool HandleReloadAreaTriggerTavernCommand(char* args); bool HandleReloadAreaTriggerTeleportCommand(char* args); + bool HandleReloadAutoBroadcastCommand(char* args); bool HandleReloadBattleEventCommand(char* args); bool HandleReloadCommandCommand(char* args); bool HandleReloadConditionsCommand(char* args); diff --git a/src/game/Chat/Level3.cpp b/src/game/Chat/Level3.cpp index b96db18dc3..70881606e4 100644 --- a/src/game/Chat/Level3.cpp +++ b/src/game/Chat/Level3.cpp @@ -349,6 +349,14 @@ bool ChatHandler::HandleReloadAreaTriggerTeleportCommand(char* /*args*/) return true; } +bool ChatHandler::HandleReloadAutoBroadcastCommand(char* /*args*/) +{ + sLog.outString("Re-Loading broadcast strings..."); + sWorld.LoadBroadcastStrings(); + SendGlobalSysMessage("Broadcast strings reloaded."); + return true; +} + bool ChatHandler::HandleReloadLocalesAreaTriggerCommand(char* /*args*/) { sLog.outString("Re-Loading AreaTrigger teleport locales definitions..."); diff --git a/src/game/Tools/Language.h b/src/game/Tools/Language.h index 1f7e3b6fbb..cd35aa7ca0 100644 --- a/src/game/Tools/Language.h +++ b/src/game/Tools/Language.h @@ -1095,6 +1095,7 @@ enum MangosStrings // Use for not-in-official-sources patches // 10000-10999 + LANG_AUTOBROADCAST = 10000, /* |cffff0000[Server Announce]:|r%s */ // Use for custom patches 11000-11999 diff --git a/src/game/World/World.cpp b/src/game/World/World.cpp index 0e435971c5..610a39d41b 100644 --- a/src/game/World/World.cpp +++ b/src/game/World/World.cpp @@ -60,6 +60,7 @@ #include "MotionGenerators/WaypointManager.h" #include "GMTickets/GMTicketMgr.h" #include "Util.h" +#include "Tools/Language.h" #include "Tools/CharacterDatabaseCleaner.h" #include "Entities/CreatureLinkingMgr.h" #include "Weather/Weather.h" @@ -111,6 +112,8 @@ World::World() : mail_timer(0), mail_timer_expires(0), m_NextDailyQuestReset(0), m_startTime = m_gameTime; m_maxActiveSessionCount = 0; m_maxQueuedSessionCount = 0; + m_broadcastEnable = false; + m_broadcastList.clear(); m_defaultDbcLocale = DEFAULT_LOCALE; m_availableDbcLocaleMask = 0; @@ -375,6 +378,22 @@ void World::LoadConfigSettings(bool reload) SetPlayerLimit(sConfig.GetIntDefault("PlayerLimit", DEFAULT_PLAYER_LIMIT), true); SetMotd(sConfig.GetStringDefault("Motd", "Welcome to the Massive Network Game Object Server.")); + setConfigMin(CONFIG_UINT32_AUTOBROADCAST_INTERVAL, "Autobroadcast", 0, 0); + + if (getConfig(CONFIG_UINT32_AUTOBROADCAST_INTERVAL) > 0) + { + m_broadcastEnable = true; + } + else + { + m_broadcastEnable = false; + } + + if (reload && m_broadcastEnable) + { + m_broadcastTimer.SetInterval(getConfig(CONFIG_UINT32_AUTOBROADCAST_INTERVAL) * IN_MILLISECONDS); + } + ///- Read all rates from the config file setConfigPos(CONFIG_FLOAT_RATE_HEALTH, "Rate.Health", 1.0f); setConfigPos(CONFIG_FLOAT_RATE_POWER_MANA, "Rate.Mana", 1.0f); @@ -1339,6 +1358,23 @@ void World::SetInitialWorldSettings() m_timers[WUPDATE_AHBOT].SetInterval(20 * IN_MILLISECONDS); // every 20 sec #endif + // for AutoBroadcast + sLog.outString("Starting AutoBroadcast System"); + if (m_broadcastEnable) + { + LoadBroadcastStrings(); + } + else + { + sLog.outString("AutoBroadcast is disabled"); + } + sLog.outString(); + + if (m_broadcastEnable) + { + m_broadcastTimer.SetInterval(getConfig(CONFIG_UINT32_AUTOBROADCAST_INTERVAL) * IN_MILLISECONDS); + } + // Update groups with offline leader after delay in seconds m_timers[WUPDATE_GROUPS].SetInterval(IN_MILLISECONDS); @@ -1494,6 +1530,24 @@ void World::Update(uint32 diff) m_timer.SetCurrent(0); } + if (m_broadcastEnable) + { + if (m_broadcastTimer.GetCurrent() >= 0) + { + m_broadcastTimer.Update(diff); + } + else + { + m_broadcastTimer.SetCurrent(0); + } + + if (m_broadcastTimer.Passed()) + { + m_broadcastTimer.Reset(); + AutoBroadcast(); + } + } + ///- Update the game time and check for shutdown time _UpdateGameTime(); @@ -2799,3 +2853,79 @@ void World::LoadWorldSafeLocs() const sWorldSafeLocsStore.Load(true); sLog.outString(">> Loaded %u world safe locs", sWorldSafeLocsStore.GetRecordCount()); } + +void World::LoadBroadcastStrings() +{ + if (!m_broadcastEnable) + { + return; + } + + std::string queryStr = "SELECT `autobroadcast`.`id`, `autobroadcast`.`content`,`autobroadcast`.`ratio` FROM `autobroadcast`"; + + QueryResult* result = WorldDatabase.Query(queryStr.c_str()); + + if (!result) + { + m_broadcastEnable = false; + sLog.outErrorDb("DB table `autobroadcast` is empty."); + sLog.outString(); + return; + } + + m_broadcastList.clear(); + + BarGoLink bar(result->GetRowCount()); + m_broadcastWeight = 0; + + do + { + Field* fields = result->Fetch(); + bar.step(); + + uint32 ratio = fields[2].GetUInt32(); + if (ratio == 0) + { + continue; + } + + m_broadcastWeight += ratio; + + BroadcastString bs; + bs.text = fields[1].GetString(); + bs.freq = m_broadcastWeight; + m_broadcastList.push_back(bs); + } while (result->NextRow()); + + delete result; + if (m_broadcastWeight == 0) + { + sLog.outString(">> Loaded 0 broadcast strings."); + m_broadcastEnable = false; + } + else + { + sLog.outString(">> Loaded " SIZEFMTD " broadcast strings.", m_broadcastList.size()); + } +} + +void World::AutoBroadcast() +{ + if (m_broadcastList.size() == 1) + { + SendWorldText(LANG_AUTOBROADCAST, m_broadcastList[0].text.c_str()); + } + else + { + uint32 rn = urand(1, m_broadcastWeight); + std::vector::const_iterator it; + for (it = m_broadcastList.begin(); it != m_broadcastList.end(); ++it) + { + if (rn <= it->freq) + { + break; + } + } + SendWorldText(LANG_AUTOBROADCAST, it->text.c_str()); + } +} \ No newline at end of file diff --git a/src/game/World/World.h b/src/game/World/World.h index 7e247beac0..d593e1bbed 100644 --- a/src/game/World/World.h +++ b/src/game/World/World.h @@ -207,6 +207,7 @@ enum eConfigUInt32Values CONFIG_UINT32_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL, CONFIG_UINT32_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE, CONFIG_UINT32_SUNSREACH_COUNTER, + CONFIG_UINT32_AUTOBROADCAST_INTERVAL, CONFIG_UINT32_VALUE_COUNT }; @@ -631,6 +632,8 @@ class World std::vector GetSpamRecords() const { return m_spamRecords; } + void LoadBroadcastStrings(); + /** * \brief: force all client to request player data * \param: ObjectGuid guid : guid of the specified player @@ -774,6 +777,18 @@ class World Messager m_messager; + // AutoBroadcast system + void AutoBroadcast(); + struct BroadcastString + { + uint32 freq; + std::string text; + }; + std::vector m_broadcastList; + uint32 m_broadcastWeight; + bool m_broadcastEnable; + IntervalTimer m_broadcastTimer; + // Opcode logging std::vector> m_opcodeCounters; // online count logging diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 5b442f7487..c088624d0a 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -807,6 +807,12 @@ LogColors = "" # Motd # Message of the Day. Displayed at worldlogin for every user ('@' for a newline). # +# AutoBroadcast +# Timer interval (in seconds) for automatic server announcements (autobroadcasts). Zero value means AB is disabled +# 0 (AB is disabled) +# Default: 600 (AB every 10 minutes) +# N (>0, AB every N seconds) +# # PlayerCommands # Should player chat be parsed for GM commands. # Default: 1 (parse commands) @@ -882,6 +888,7 @@ BeepAtStart = 1 ShowProgressBars = 0 WaitAtStartupError = 0 Motd = "Welcome to the Continued Massive Network Game Object Server." +AutoBroadcast = 0 PlayerCommands = 1 ###################################################################################################################