Big update.

This commit is contained in:
UltraNix
2022-03-12 22:28:00 +01:00
parent 6006eeeb01
commit 12d41d1314
2064 changed files with 427245 additions and 268481 deletions

View File

@@ -19,7 +19,6 @@
#include "AccountMgr.h"
#include "Log.h"
#include "World.h"
#include "soapH.h"
#include "soapStub.h"
void ACSoapThread(const std::string& host, uint16 port)
@@ -36,18 +35,18 @@ void ACSoapThread(const std::string& host, uint16 port)
if (!soap_valid_socket(soap_bind(&soap, host.c_str(), port, 100)))
{
LOG_ERROR("network.soap", "ACSoap: couldn't bind to %s:%d", host.c_str(), port);
LOG_ERROR("network.soap", "ACSoap: couldn't bind to {}:{}", host, port);
exit(-1);
}
LOG_INFO("network.soap", "ACSoap: bound to http://%s:%d", host.c_str(), port);
LOG_INFO("network.soap", "ACSoap: bound to http://{}:{}", host, port);
while (!World::IsStopped())
{
if (!soap_valid_socket(soap_accept(&soap)))
continue; // ran into an accept timeout
LOG_DEBUG("network.soap", "ACSoap: accepted connection from IP=%d.%d.%d.%d", (int)(soap.ip >> 24) & 0xFF, (int)(soap.ip >> 16) & 0xFF, (int)(soap.ip >> 8) & 0xFF, (int)soap.ip & 0xFF);
LOG_DEBUG("network.soap", "ACSoap: accepted connection from IP={}.{}.{}.{}", (int)(soap.ip >> 24) & 0xFF, (int)(soap.ip >> 16) & 0xFF, (int)(soap.ip >> 8) & 0xFF, (int)soap.ip & 0xFF);
struct soap* thread_soap = soap_copy(&soap);// make a safe copy
process_message(thread_soap);
@@ -84,26 +83,26 @@ int ns1__executeCommand(soap* soap, char* command, char** result)
uint32 accountId = AccountMgr::GetId(soap->userid);
if (!accountId)
{
LOG_DEBUG("network", "ACSoap: Client used invalid username '%s'", soap->userid);
LOG_DEBUG("network", "ACSoap: Client used invalid username '{}'", soap->userid);
return 401;
}
if (!AccountMgr::CheckPassword(accountId, soap->passwd))
{
LOG_DEBUG("network.soap", "ACSoap: invalid password for account '%s'", soap->userid);
LOG_DEBUG("network.soap", "ACSoap: invalid password for account '{}'", soap->userid);
return 401;
}
if (AccountMgr::GetSecurity(accountId) < SEC_ADMINISTRATOR)
{
LOG_DEBUG("network.soap", "ACSoap: %s's gmlevel is too low", soap->userid);
LOG_DEBUG("network.soap", "ACSoap: {}'s gmlevel is too low", soap->userid);
return 403;
}
if (!command || !*command)
return soap_sender_fault(soap, "Command can not be empty", "The supplied command was an empty string");
LOG_DEBUG("network.soap", "ACSoap: got command '%s'", command);
LOG_DEBUG("network.soap", "ACSoap: got command '{}'", command);
SOAPCommand connection;
// commands are executed in the world thread. We have to wait for them to be completed

View File

@@ -20,13 +20,11 @@
/// \file
#include "CliRunnable.h"
#include "Common.h"
#include "Config.h"
#include "Errors.h"
#include "Log.h"
#include "ObjectMgr.h"
#include "Util.h"
#include "World.h"
#include <fmt/core.h>
#if AC_PLATFORM != AC_PLATFORM_WINDOWS
#include "Chat.h"
@@ -40,7 +38,7 @@ static constexpr char CLI_PREFIX[] = "AC> ";
static inline void PrintCliPrefix()
{
printf("%s", CLI_PREFIX);
fmt::print(CLI_PREFIX);
}
#if AC_PLATFORM != AC_PLATFORM_WINDOWS
@@ -77,14 +75,10 @@ namespace Acore::Impl::Readline
void utf8print(void* /*arg*/, std::string_view str)
{
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
std::wstring wbuf;
if (!Utf8toWStr(str, wbuf))
return;
wprintf(L"%s", wbuf.c_str());
fmt::print(str);
#else
{
printf(STRING_VIEW_FMT, STRING_VIEW_FMT_ARG(str));
fmt::print(str);
fflush(stdout);
}
#endif

View File

@@ -23,14 +23,12 @@
#include "AppenderDB.h"
#include "AsyncAcceptor.h"
#include "AsyncAuctionListing.h"
#include "AvgDiffTracker.h"
#include "Banner.h"
#include "BattlegroundMgr.h"
#include "BigNumber.h"
#include "CliRunnable.h"
#include "Common.h"
#include "Config.h"
#include "Configuration/Config.h"
#include "DatabaseEnv.h"
#include "DatabaseLoader.h"
#include "DeadlineTimer.h"
@@ -40,7 +38,6 @@
#include "Metric.h"
#include "ModulesScriptLoader.h"
#include "MySQLThreading.h"
#include "ObjectAccessor.h"
#include "OpenSSLCrypto.h"
#include "OutdoorPvPMgr.h"
#include "ProcessPriority.h"
@@ -55,10 +52,8 @@
#include "WorldSocket.h"
#include "WorldSocketMgr.h"
#include <boost/asio/signal_set.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/program_options.hpp>
#include <csignal>
#include <iostream>
#include <openssl/crypto.h>
#include <openssl/opensslv.h>
@@ -195,14 +190,11 @@ int main(int argc, char** argv)
}
// Add file and args in config
sConfigMgr->Configure(configFile, std::vector<std::string>(argv, argv + argc), CONFIG_FILE_LIST);
sConfigMgr->Configure(configFile, { argv, argv + argc }, CONFIG_FILE_LIST);
if (!sConfigMgr->LoadAppConfigs())
return 1;
// Loading modules configs
sConfigMgr->LoadModulesConfigs();
std::shared_ptr<Acore::Asio::IoContext> ioContext = std::make_shared<Acore::Asio::IoContext>();
// Init all logs
@@ -212,13 +204,13 @@ int main(int argc, char** argv)
Acore::Banner::Show("worldserver-daemon",
[](std::string_view text)
{
FMT_LOG_INFO("server.worldserver", text);
LOG_INFO("server.worldserver", text);
},
[]()
{
FMT_LOG_INFO("server.worldserver", "> Using configuration file {}", sConfigMgr->GetFilename());
FMT_LOG_INFO("server.worldserver", "> Using SSL version: {} (library: {})", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
FMT_LOG_INFO("server.worldserver", "> Using Boost version: {}.{}.{}", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
LOG_INFO("server.worldserver", "> Using configuration file {}", sConfigMgr->GetFilename());
LOG_INFO("server.worldserver", "> Using SSL version: {} (library: {})", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
LOG_INFO("server.worldserver", "> Using Boost version: {}.{}.{}", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
});
OpenSSLCrypto::threadsSetup();
@@ -235,10 +227,10 @@ int main(int argc, char** argv)
if (!pidFile.empty())
{
if (uint32 pid = CreatePIDFile(pidFile))
LOG_ERROR("server", "Daemon PID: %u\n", pid); // outError for red color in console
LOG_ERROR("server", "Daemon PID: {}\n", pid); // outError for red color in console
else
{
LOG_ERROR("server", "Cannot create PID file %s (possible error: permission)\n", pidFile.c_str());
LOG_ERROR("server", "Cannot create PID file {} (possible error: permission)\n", pidFile);
return 1;
}
}
@@ -277,6 +269,9 @@ int main(int argc, char** argv)
// Set process priority according to configuration settings
SetProcessPriority("server.worldserver", sConfigMgr->GetOption<int32>(CONFIG_PROCESSOR_AFFINITY, 0), sConfigMgr->GetOption<bool>(CONFIG_HIGH_PRIORITY, false));
// Loading modules configs before scripts
sConfigMgr->LoadModulesConfigs();
sScriptMgr->SetScriptLoader(AddScripts);
sScriptMgr->SetModulesLoader(AddModulesScripts);
@@ -296,7 +291,7 @@ int main(int argc, char** argv)
std::shared_ptr<void> dbHandle(nullptr, [](void*) { StopDB(); });
// set server offline (not connectable)
LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = (flag & ~%u) | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, REALM_FLAG_VERSION_MISMATCH, realm.Id.Realm);
LoginDatabase.DirectExecute("UPDATE realmlist SET flag = (flag & ~{}) | {} WHERE id = '{}'", REALM_FLAG_OFFLINE, REALM_FLAG_VERSION_MISMATCH, realm.Id.Realm);
LoadRealmInfo(*ioContext);
@@ -306,6 +301,7 @@ int main(int argc, char** argv)
METRIC_VALUE("db_queue_login", uint64(LoginDatabase.QueueSize()));
METRIC_VALUE("db_queue_character", uint64(CharacterDatabase.QueueSize()));
METRIC_VALUE("db_queue_world", uint64(WorldDatabase.QueueSize()));
sScriptMgr->OnMetricLogging();
});
METRIC_EVENT("events", "Worldserver started", "");
@@ -318,9 +314,6 @@ int main(int argc, char** argv)
Acore::Module::SetEnableModulesList(AC_MODULES_LIST);
// Loading modules configs
sConfigMgr->PrintLoadedModulesConfigs();
///- Initialize the World
sSecretMgr->Initialize();
sWorld->SetInitialWorldSettings();
@@ -332,6 +325,8 @@ int main(int argc, char** argv)
sOutdoorPvPMgr->Die(); // unload it before MapMgr
sMapMgr->UnloadAll(); // unload all grids (including locked in memory)
sScriptMgr->OnAfterUnloadAllMaps();
});
// Start the Remote Access port (acceptor) if enabled
@@ -385,7 +380,7 @@ int main(int argc, char** argv)
});
// Set server online (allow connecting now)
LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag & ~%u, population = 0 WHERE id = '%u'", REALM_FLAG_VERSION_MISMATCH, realm.Id.Realm);
LoginDatabase.DirectExecute("UPDATE realmlist SET flag = flag & ~{}, population = 0 WHERE id = '{}'", REALM_FLAG_VERSION_MISMATCH, realm.Id.Realm);
realm.PopulationLevel = 0.0f;
realm.Flags = RealmFlags(realm.Flags & ~uint32(REALM_FLAG_VERSION_MISMATCH));
@@ -395,10 +390,10 @@ int main(int argc, char** argv)
{
freezeDetector = std::make_shared<FreezeDetector>(*ioContext, coreStuckTime * 1000);
FreezeDetector::Start(freezeDetector);
LOG_INFO("server.worldserver", "Starting up anti-freeze thread (%u seconds max stuck time)...", coreStuckTime);
LOG_INFO("server.worldserver", "Starting up anti-freeze thread ({} seconds max stuck time)...", coreStuckTime);
}
LOG_INFO("server.worldserver", "%s (worldserver-daemon) ready...", GitRevision::GetFullVersion());
LOG_INFO("server.worldserver", "{} (worldserver-daemon) ready...", GitRevision::GetFullVersion());
sScriptMgr->OnStartup();
@@ -430,7 +425,7 @@ int main(int argc, char** argv)
sScriptMgr->OnShutdown();
// set server offline
LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realm.Id.Realm);
LoginDatabase.DirectExecute("UPDATE realmlist SET flag = flag | {} WHERE id = '{}'", REALM_FLAG_OFFLINE, realm.Id.Realm);
LOG_INFO("server.worldserver", "Halting process...");
@@ -456,16 +451,13 @@ bool StartDB()
if (!loader.Load())
return false;
#ifdef PLAYERBOTS
DatabaseLoader playerbotLoader("server.playerbot");
playerbotLoader.SetUpdateFlags(sConfigMgr->GetOption<bool>("Playerbot.Updates.EnableDatabases", true) ? DatabaseLoader::DATABASE_PLAYERBOT : 0);
playerbotLoader.AddDatabase(PlayerbotDatabase, "Playerbot");
if (!playerbotLoader.Load())
if (!sScriptMgr->OnDatabasesLoading())
{
return false;
#endif
}
///- Get the realm Id from the configuration file
realm.Id.Realm = sConfigMgr->GetIntDefault("RealmID", 0);
realm.Id.Realm = sConfigMgr->GetOption<uint32>("RealmID", 0);
if (!realm.Id.Realm)
{
LOG_ERROR("server.worldserver", "Realm ID not defined in configuration file");
@@ -483,18 +475,18 @@ bool StartDB()
}
LOG_INFO("server.loading", "Loading world information...");
LOG_INFO("server.loading", "> RealmID: %u", realm.Id.Realm);
LOG_INFO("server.loading", "> RealmID: {}", realm.Id.Realm);
///- Clean the database before starting
ClearOnlineAccounts();
///- Insert version info into DB
WorldDatabase.PExecute("UPDATE version SET core_version = '%s', core_revision = '%s'", GitRevision::GetFullVersion(), GitRevision::GetHash()); // One-time query
WorldDatabase.Execute("UPDATE version SET core_version = '{}', core_revision = '{}'", GitRevision::GetFullVersion(), GitRevision::GetHash()); // One-time query
sWorld->LoadDBVersion();
sWorld->LoadDBRevision();
LOG_INFO("server.loading", "> Version DB world: %s", sWorld->GetDBVersion());
LOG_INFO("server.loading", "> Version DB world: {}", sWorld->GetDBVersion());
sScriptMgr->OnAfterDatabasesLoaded(loader.GetUpdateFlags());
@@ -507,9 +499,7 @@ void StopDB()
WorldDatabase.Close();
LoginDatabase.Close();
#ifdef PLAYERBOTS
PlayerbotDatabase.Close();
#endif
sScriptMgr->OnDatabasesClosing();
MySQL::Library_End();
}
@@ -519,7 +509,7 @@ void ClearOnlineAccounts()
{
// Reset online status for all accounts with characters on the current realm
// pussywizard: tc query would set online=0 even if logged in on another realm >_>
LoginDatabase.DirectPExecute("UPDATE account SET online = 0 WHERE online = %u", realm.Id.Realm);
LoginDatabase.DirectExecute("UPDATE account SET online = 0 WHERE online = {}", realm.Id.Realm);
// Reset online status for all characters
CharacterDatabase.DirectExecute("UPDATE characters SET online = 0 WHERE online <> 0");
@@ -542,7 +532,7 @@ void ShutdownCLIThread(std::thread* cliThread)
if (!formatReturnCode)
errorBuffer = "Unknown error";
LOG_DEBUG("server.worldserver", "Error cancelling I/O of CliThread, error code %u, detail: %s", uint32(errorCode), errorBuffer);
LOG_DEBUG("server.worldserver", "Error cancelling I/O of CliThread, error code {}, detail: {}", uint32(errorCode), errorBuffer);
if (!formatReturnCode)
LocalFree((LPSTR)errorBuffer);
@@ -595,6 +585,8 @@ void WorldUpdateLoop()
CharacterDatabase.WarnAboutSyncQueries(true);
WorldDatabase.WarnAboutSyncQueries(true);
sScriptMgr->OnDatabaseWarnAboutSyncQueries(true);
///- While we have not World::m_stopEvent, update the world
while (!World::IsStopped())
{
@@ -607,8 +599,6 @@ void WorldUpdateLoop()
realPrevTime = realCurrTime;
uint32 executionTimeDiff = getMSTimeDiff(realCurrTime, getMSTime());
devDiffTracker.Update(executionTimeDiff);
avgDiffTracker.Update(executionTimeDiff > WORLD_SLEEP_CONST ? executionTimeDiff : WORLD_SLEEP_CONST);
// we know exactly how long it took to update the world, if the update took less than WORLD_SLEEP_CONST, sleep for WORLD_SLEEP_CONST - world update time
if (executionTimeDiff < WORLD_SLEEP_CONST)
@@ -625,6 +615,8 @@ void WorldUpdateLoop()
#endif
}
sScriptMgr->OnDatabaseWarnAboutSyncQueries(false);
LoginDatabase.WarnAboutSyncQueries(false);
CharacterDatabase.WarnAboutSyncQueries(false);
WorldDatabase.WarnAboutSyncQueries(false);
@@ -682,49 +674,49 @@ AsyncAcceptor* StartRaSocketAcceptor(Acore::Asio::IoContext& ioContext)
bool LoadRealmInfo(Acore::Asio::IoContext& ioContext)
{
QueryResult result = LoginDatabase.PQuery("SELECT id, name, address, localAddress, localSubnetMask, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild FROM realmlist WHERE id = %u", realm.Id.Realm);
QueryResult result = LoginDatabase.Query("SELECT id, name, address, localAddress, localSubnetMask, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild FROM realmlist WHERE id = {}", realm.Id.Realm);
if (!result)
return false;
Acore::Asio::Resolver resolver(ioContext);
Field* fields = result->Fetch();
realm.Name = fields[1].GetString();
realm.Name = fields[1].Get<std::string>();
Optional<boost::asio::ip::tcp::endpoint> externalAddress = resolver.Resolve(boost::asio::ip::tcp::v4(), fields[2].GetString(), "");
Optional<boost::asio::ip::tcp::endpoint> externalAddress = resolver.Resolve(boost::asio::ip::tcp::v4(), fields[2].Get<std::string>(), "");
if (!externalAddress)
{
LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[2].GetString().c_str());
LOG_ERROR("server.worldserver", "Could not resolve address {}", fields[2].Get<std::string>());
return false;
}
realm.ExternalAddress = std::make_unique<boost::asio::ip::address>(externalAddress->address());
Optional<boost::asio::ip::tcp::endpoint> localAddress = resolver.Resolve(boost::asio::ip::tcp::v4(), fields[3].GetString(), "");
Optional<boost::asio::ip::tcp::endpoint> localAddress = resolver.Resolve(boost::asio::ip::tcp::v4(), fields[3].Get<std::string>(), "");
if (!localAddress)
{
LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[3].GetString().c_str());
LOG_ERROR("server.worldserver", "Could not resolve address {}", fields[3].Get<std::string>());
return false;
}
realm.LocalAddress = std::make_unique<boost::asio::ip::address>(localAddress->address());
Optional<boost::asio::ip::tcp::endpoint> localSubmask = resolver.Resolve(boost::asio::ip::tcp::v4(), fields[4].GetString(), "");
Optional<boost::asio::ip::tcp::endpoint> localSubmask = resolver.Resolve(boost::asio::ip::tcp::v4(), fields[4].Get<std::string>(), "");
if (!localSubmask)
{
LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[4].GetString().c_str());
LOG_ERROR("server.worldserver", "Could not resolve address {}", fields[4].Get<std::string>());
return false;
}
realm.LocalSubnetMask = std::make_unique<boost::asio::ip::address>(localSubmask->address());
realm.Port = fields[5].GetUInt16();
realm.Type = fields[6].GetUInt8();
realm.Flags = RealmFlags(fields[7].GetUInt8());
realm.Timezone = fields[8].GetUInt8();
realm.AllowedSecurityLevel = AccountTypes(fields[9].GetUInt8());
realm.PopulationLevel = fields[10].GetFloat();
realm.Build = fields[11].GetUInt32();
realm.Port = fields[5].Get<uint16>();
realm.Type = fields[6].Get<uint8>();
realm.Flags = RealmFlags(fields[7].Get<uint8>());
realm.Timezone = fields[8].Get<uint8>();
realm.AllowedSecurityLevel = AccountTypes(fields[9].Get<uint8>());
realm.PopulationLevel = fields[10].Get<float>();
realm.Build = fields[11].Get<uint32>();
return true;
}

View File

@@ -27,7 +27,6 @@
#include "World.h"
#include <boost/asio/buffer.hpp>
#include <boost/asio/read_until.hpp>
#include <memory>
#include <thread>
using boost::asio::ip::tcp;
@@ -58,7 +57,7 @@ void RASession::Start()
if (username.empty())
return;
LOG_INFO("commands.ra", "Accepting RA connection from user %s (IP: %s)", username.c_str(), GetRemoteIpAddress().c_str());
LOG_INFO("commands.ra", "Accepting RA connection from user {} (IP: {})", username, GetRemoteIpAddress());
Send("Password: ");
@@ -73,7 +72,7 @@ void RASession::Start()
return;
}
LOG_INFO("commands.ra", "User %s (IP: %s) authenticated correctly to RA", username.c_str(), GetRemoteIpAddress().c_str());
LOG_INFO("commands.ra", "User {} (IP: {}) authenticated correctly to RA", username, GetRemoteIpAddress());
// Authentication successful, send the motd
Send(std::string(std::string(Motd::GetMotd()) + "\r\n").c_str());
@@ -127,25 +126,25 @@ bool RASession::CheckAccessLevel(const std::string& user)
Utf8ToUpperOnlyLatin(safeUser);
auto* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ACCESS);
stmt->setString(0, safeUser);
stmt->SetData(0, safeUser);
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (!result)
{
LOG_INFO("commands.ra", "User %s does not exist in database", user.c_str());
LOG_INFO("commands.ra", "User {} does not exist in database", user);
return false;
}
Field* fields = result->Fetch();
if (fields[1].GetUInt8() < sConfigMgr->GetOption<int32>("Ra.MinLevel", 3))
if (fields[1].Get<uint8>() < sConfigMgr->GetOption<int32>("Ra.MinLevel", 3))
{
LOG_INFO("commands.ra", "User %s has no privilege to login", user.c_str());
LOG_INFO("commands.ra", "User {} has no privilege to login", user);
return false;
}
else if (fields[2].GetInt32() != -1)
else if (fields[2].Get<int32>() != -1)
{
LOG_INFO("commands.ra", "User %s has to be assigned on all realms (with RealmID = '-1')", user.c_str());
LOG_INFO("commands.ra", "User {} has to be assigned on all realms (with RealmID = '-1')", user);
return false;
}
@@ -164,18 +163,18 @@ bool RASession::CheckPassword(const std::string& user, const std::string& pass)
auto* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME);
stmt->setString(0, safe_user);
stmt->SetData(0, safe_user);
if (PreparedQueryResult result = LoginDatabase.Query(stmt))
{
Acore::Crypto::SRP6::Salt salt = (*result)[0].GetBinary<Acore::Crypto::SRP6::SALT_LENGTH>();
Acore::Crypto::SRP6::Verifier verifier = (*result)[1].GetBinary<Acore::Crypto::SRP6::VERIFIER_LENGTH>();
Acore::Crypto::SRP6::Salt salt = (*result)[0].Get<Binary, Acore::Crypto::SRP6::SALT_LENGTH>();
Acore::Crypto::SRP6::Verifier verifier = (*result)[1].Get<Binary, Acore::Crypto::SRP6::VERIFIER_LENGTH>();
if (Acore::Crypto::SRP6::CheckLogin(safe_user, safe_pass, salt, verifier))
return true;
}
LOG_INFO("commands.ra", "Wrong password for user: %s", user.c_str());
LOG_INFO("commands.ra", "Wrong password for user: {}", user);
return false;
}
@@ -184,7 +183,7 @@ bool RASession::ProcessCommand(std::string& command)
if (command.length() == 0)
return true;
LOG_INFO("commands.ra", "Received command: %s", command.c_str());
LOG_INFO("commands.ra", "Received command: {}", command);
// handle quit, exit and logout commands to terminate connection
if (command == "quit" || command == "exit" || command == "logout")

View File

@@ -19,6 +19,7 @@
# GAME MASTER SETTINGS
# VISIBILITY AND DISTANCES
# SERVER RATES
# STATS LIMITS
# AUTO BROADCAST
# BATTLEGROUND CONFIG
# BATTLEFIELD CONFIG
@@ -867,6 +868,14 @@ StartPlayerMoney = 0
MaxHonorPoints = 75000
#
# MaxHonorPointsMoneyPerPoint
# Description: Convert excess honor points into money if players got more points than allowed after changing the honor cap.
# Honor points will be converted into copper according to the value set in this config.
# Default: 0 - Disabled
MaxHonorPointsMoneyPerPoint = 0
#
# StartHonorPoints
# Description: Amount of honor points that characters have after creation.
@@ -1758,6 +1767,14 @@ ListenRange.TextEmote = 40
ListenRange.Yell = 300
#
# Creature.MovingStopTimeForPlayer
# Description: Time (in milliseconds) during which creature will not move after
# interaction with player.
# Default: 180000
Creature.MovingStopTimeForPlayer = 180000
# WaypointMovementStopTimeForPlayer
# Description: Specifies the time (in seconds) that a creature with waypoint
# movement will wait after a player interacts with it.
@@ -1788,6 +1805,17 @@ NpcRegenHPIfTargetIsUnreachable = 1
NpcRegenHPTimeIfTargetIsUnreachable = 10
# Creatures.CustomIDs
# Description: The list of custom creatures with gossip dialogues hardcoded in core,
# divided by "," without spaces.
# It is implied that you do not use for these NPC dialogs data from "gossip_menu" table.
# Server will skip these IDs during the definitions validation process.
# Example: Creatures.CustomIDs = "190010,55005,999991,25462,98888,601014" - Npcs for Transmog, Guild-zone, 1v1-arena, Skip Dk,
# Racial Trait Swap, NPC - All Mounts Modules
# Default: ""
Creatures.CustomIDs = "190010,55005,999991,25462,98888,601014"
#
###################################################################################################
@@ -2252,21 +2280,28 @@ Rate.Drop.Item.ReferencedAmount = 1
# Description: Experience rates (outside battleground)
# Default: 1 - (Rate.XP.Kill)
# 1 - (Rate.XP.Quest)
# 1 - (Rate.XP.Quest.DF) - Dungeon Finder/LFG quests only.
# 1 - (Rate.XP.Explore)
# 1 - (Rate.XP.Pet)
Rate.XP.Kill = 1
Rate.XP.Quest = 1
Rate.XP.Explore = 1
Rate.XP.Pet = 1
Rate.XP.Kill = 1
Rate.XP.Quest = 1
Rate.XP.Quest.DF = 1
Rate.XP.Explore = 1
Rate.XP.Pet = 1
#
# Rate.XP.BattlegroundKill
# Description: Experience rate for honorable kills in battlegrounds. Not affected by Rate.XP.Kill
# Rate.XP.BattlegroundKill...
# Description: Experience rate for honorable kills in battlegrounds. Not affected by Rate.XP.Kill. Defined for each battleground.
# Only works if Battleground.GiveXPForKills = 1
# Default: 1
Rate.XP.BattlegroundKill = 1
Rate.XP.BattlegroundKillAV = 1
Rate.XP.BattlegroundKillWSG = 1
Rate.XP.BattlegroundKillAB = 1
Rate.XP.BattlegroundKillEOTS = 1
Rate.XP.BattlegroundKillSOTA = 1
Rate.XP.BattlegroundKillIC = 1
#
# Rate.RepairCost
@@ -2513,6 +2548,53 @@ Death.Bones.BattlegroundOrArena = 1
Die.Command.Mode = 1
# Rate.MissChanceMultiplier.Creature
# Rate.MissChanceMultiplier.Player
# Rate.MissChanceMultiplier.OnlyAffectsPlayer
#
# Description: When the target is 3 or more level higher than the player,
# the chance to hit is determined by the formula: 94 - (levelDiff - 2) * Rate.MissChanceMultiplier
# The higher the Rate.MissChanceMultiplier constant, the higher is the chance to miss.
#
# Note: this does not affect when the player is less than 3 levels different than the target,
# where this (linear) formula is used instead to calculate the hit chance: 96 - levelDiff.
# You can set Rate.MissChanceMultiplier.OnlyAffectsPlayer to 1 if you only want to affect the MissChance
# for player casters only. This way you won't be affecting creature missing chance.
#
# Example: if you want the chance to keep growing linearly, use 1.
#
# Default: Rate.MissChanceMultiplier.TargetCreature = 11
# Rate.MissChanceMultiplier.TargetPlayer = 7
# Rate.MissChanceMultiplier.OnlyAffectsPlayer = 0
#
Rate.MissChanceMultiplier.TargetCreature = 11
Rate.MissChanceMultiplier.TargetPlayer = 7
Rate.MissChanceMultiplier.OnlyAffectsPlayer = 0
#
###################################################################################################
###################################################################################################
# STATS LIMITS
#
# Stats.Limits.Enable
# Description: Enable or disable stats system limitations
# Default: 0 - Disabled
# 1 - Enabled
Stats.Limits.Enable = 0
#
# Stats.Limit.[STAT]
# Description: Set percentage limit for dodge, parry, block and crit rating
# Default: 95.0 (95%)
Stats.Limits.Dodge = 95.0
Stats.Limits.Parry = 95.0
Stats.Limits.Block = 95.0
Stats.Limits.Crit = 95.0
#
###################################################################################################
@@ -2542,6 +2624,13 @@ AutoBroadcast.Center = 0
AutoBroadcast.Timer = 60000
#
# AutoBroadcast.MinDisableLevel
# Description: Minimum level required to disable autobroadcast announcements if EnablePlayerSettings option is enabled.
# Default: 0 - (Not allowed to disable it)
AutoBroadcast.MinDisableLevel = 0
#
###################################################################################################
@@ -3136,15 +3225,13 @@ ItemDelete.ItemLevel = 80
PlayerStart.AllReputation = 0
#
# PlayerStart.AllSpells
# Description: If enabled, players will start with all their class spells (not talents).
# You must populate playercreateinfo_spell_custom table with the spells you
# want, or this will not work! The table has data for all classes / races up
# to TBC expansion.
# PlayerStart.CustomSpells
# Description: If enabled, players will start with custom spells defined in
# playercreateinfo_spell_custom table.
# Default: 0 - (Disabled)
# 1 - (Enabled)
PlayerStart.AllSpells = 0
PlayerStart.CustomSpells = 0
#
# PlayerStart.MapsExplored
@@ -3380,12 +3467,12 @@ StrictChannelNames = 0
#
# Instance.SharedNormalHeroicId
# Description: No description
# Default: 0 - Disable
# 1 - Enable
# Description: Forces ICC and RS Normal and Heroic to share lockouts. ToC is uneffected and Normal and Heroic will be separate.
# Default: 1 - Enable
# 0 - Disable
#
Instance.SharedNormalHeroicId = 0
Instance.SharedNormalHeroicId = 1
#
# Instance.ResetTimeRelativeTimestamp
@@ -3597,6 +3684,22 @@ LFG.MaxKickCount = 2
LFG.KickPreventionTimer = 900
#
# EnablePlayerSettings
# Description: Enables the usage of character specific settings.
# Default: 0 - Disabled
# 1 - Enabled
EnablePlayerSettings = 0
#
# JoinBGAndLFG.Enable
# Description: Allow queueing for BG and LFG at the same time.
# Default: 0 - Disabled
# 1 - Enabled
JoinBGAndLFG.Enable = 0
#
###################################################################################################
@@ -3699,6 +3802,8 @@ Logger.scripts.hotswap=4,Console Server
Logger.server=4,Console Server
Logger.sql.sql=2,Console DBErrors
Logger.sql=4,Console Server
Logger.time.update=4,Console Server
Logger.module=4,Console Server
#Logger.achievement=4,Console Server
#Logger.addon=4,Console Server