diff --git a/Release/Plugins/RenX.Core.lib b/Release/Plugins/RenX.Core.lib index 5efde41..ccebe6c 100644 Binary files a/Release/Plugins/RenX.Core.lib and b/Release/Plugins/RenX.Core.lib differ diff --git a/RenX.Commands/RenX_Commands.cpp b/RenX.Commands/RenX_Commands.cpp index 620c1b8..f9d76f3 100644 --- a/RenX.Commands/RenX_Commands.cpp +++ b/RenX.Commands/RenX_Commands.cpp @@ -501,8 +501,8 @@ void PlayerTableIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableStri STRING_LITERAL_AS_NAMED_REFERENCE(NICK_COL_HEADER, "Nickname"); size_t maxNickLen = 8; int highID = 999; - float highScore = 99999.0; - float highCredits = 9999999.0; + double highScore = 99999.0; + double highCredits = 9999999.0; RenX::PlayerInfo *player; for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) @@ -836,7 +836,7 @@ void KillDeathRatioIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableS if (player->name.findi(parameters) != Jupiter::INVALID_INDEX) { Jupiter::String &playerName = RenX::getFormattedPlayerName(player); - msg.format(IRCBOLD "%.*s" IRCBOLD IRCCOLOR ": Kills: %u - Deaths: %u - KDR: %.2f", playerName.size(), playerName.ptr(), player->kills, player->deaths, ((float)player->kills) / (player->deaths == 0 ? 1.0 : (float)player->deaths)); + msg.format(IRCBOLD "%.*s" IRCBOLD IRCCOLOR ": Kills: %u - Deaths: %u - KDR: %.2f", playerName.size(), playerName.ptr(), player->kills, player->deaths, static_cast(player->kills) / (player->deaths == 0 ? 1.0f : static_cast(player->deaths))); source->sendMessage(channel, msg); } } diff --git a/RenX.Core/RenX_Core.cpp b/RenX.Core/RenX_Core.cpp index 9de547d..7dc2214 100644 --- a/RenX.Core/RenX_Core.cpp +++ b/RenX.Core/RenX_Core.cpp @@ -81,8 +81,9 @@ void RenX::Core::addServer(RenX::Server *server) int RenX::Core::getServerIndex(RenX::Server *server) { - for (size_t i = 0; i != RenX::Core::servers.size(); i++) - if (server == RenX::Core::servers.get(i)) + size_t i = RenX::Core::servers.size(); + while (i != 0) + if (server == RenX::Core::servers.get(--i)) return i; return -1; } @@ -117,6 +118,15 @@ int RenX::Core::removeServer(RenX::Server *server) return i; } +bool RenX::Core::hasServer(RenX::Server *server) +{ + size_t i = RenX::Core::servers.size(); + while (i != 0) + if (server == RenX::Core::servers.get(--i)) + return true; + return false; +} + unsigned int RenX::Core::getServerCount() { return RenX::Core::servers.size(); diff --git a/RenX.Core/RenX_Core.h b/RenX.Core/RenX_Core.h index 21be70d..2a4cad4 100644 --- a/RenX.Core/RenX_Core.h +++ b/RenX.Core/RenX_Core.h @@ -120,6 +120,14 @@ namespace RenX */ int removeServer(RenX::Server *server); + /** + * @brief Checks is a server is in the server list. + * + * @param server Pointer to the server to look for. + * @return True if the server is in the list, false otherwise. + */ + bool hasServer(RenX::Server *server); + /** * @brief Fetches the number of servers. * diff --git a/RenX.Core/RenX_Functions.cpp b/RenX.Core/RenX_Functions.cpp index 79ed045..0a63a7d 100644 --- a/RenX.Core/RenX_Functions.cpp +++ b/RenX.Core/RenX_Functions.cpp @@ -867,11 +867,9 @@ void RenX::sanitizeString(Jupiter::StringType &str) } } -time_t RenX::getGameTime(const RenX::PlayerInfo *player) +std::chrono::milliseconds RenX::getServerTime(const RenX::PlayerInfo *player) { - time_t currentTime = time(0); - if (player->joinTime == currentTime) currentTime++; - return currentTime - player->joinTime; + return std::chrono::duration_cast(std::chrono::steady_clock::now() - player->joinTime); } Jupiter::StringS RenX::default_uuid_func(RenX::PlayerInfo *player) @@ -891,9 +889,4 @@ double RenX::getHeadshotKillRatio(const RenX::PlayerInfo *player) { if (player->kills == 0) return 0; return ((double)player->headshots) / ((double)player->kills); -} - -double RenX::getKillsPerSecond(const RenX::PlayerInfo *player) -{ - return ((double)player->kills) / ((double)RenX::getGameTime(player)); } \ No newline at end of file diff --git a/RenX.Core/RenX_Functions.h b/RenX.Core/RenX_Functions.h index 8d38bac..83c1b09 100644 --- a/RenX.Core/RenX_Functions.h +++ b/RenX.Core/RenX_Functions.h @@ -23,6 +23,7 @@ * @brief Provides some functions to be used at your convenience. */ +#include #include "Jupiter/INIFile.h" #include "Jupiter/String.h" #include "RenX.h" @@ -144,13 +145,12 @@ namespace RenX RENX_API void sanitizeString(Jupiter::StringType &str); /** - * @brief Calculates for how many seconds a player has been in-game. - * Note: This will always be at least 1. + * @brief Calculates for how many seconds a player has been in the server. * * @param player A player's data. * @return Number of seconds a player has been in-game. */ - RENX_API time_t getGameTime(const RenX::PlayerInfo *player); + RENX_API std::chrono::milliseconds getServerTime(const RenX::PlayerInfo *player); /** * @brief Calculates a player's UUID, based on their steam ID. @@ -180,14 +180,6 @@ namespace RenX */ RENX_API double getHeadshotKillRatio(const RenX::PlayerInfo *player); - /** - * @brief Calculates a player's kills-per-second since joining. - * - * @param player A player's data. - * @return Player's Kill-Death ratio. - */ - RENX_API double getKillsPerSecond(const RenX::PlayerInfo *player); - /** Constant variables */ RENX_API extern const char DelimC; /** RCON message deliminator */ } diff --git a/RenX.Core/RenX_PlayerInfo.h b/RenX.Core/RenX_PlayerInfo.h index b3c01f7..6575b41 100644 --- a/RenX.Core/RenX_PlayerInfo.h +++ b/RenX.Core/RenX_PlayerInfo.h @@ -23,6 +23,7 @@ * @brief Defines the PlayerInfo structure. */ +#include #include "Jupiter/String.h" #include "Jupiter/INIFile.h" #include "RenX.h" @@ -53,11 +54,11 @@ namespace RenX TeamType team = TeamType::Other; int id = 0; bool isBot = false; - time_t joinTime = 0; + std::chrono::steady_clock::time_point joinTime = std::chrono::steady_clock::now(); unsigned short ping = 0; - float score = 0.0f; - float credits = 0.0f; + double score = 0.0f; + double credits = 0.0f; unsigned int kills = 0; unsigned int deaths = 0; unsigned int suicides = 0; diff --git a/RenX.Core/RenX_Server.cpp b/RenX.Core/RenX_Server.cpp index 0dcff13..cd7efd7 100644 --- a/RenX.Core/RenX_Server.cpp +++ b/RenX.Core/RenX_Server.cpp @@ -144,9 +144,9 @@ bool RenX::Server::isConnected() const return RenX::Server::connected; } -bool RenX::Server::isFirstGame() const +bool RenX::Server::hasSeenStart() const { - return RenX::Server::firstGame; + return RenX::Server::seenStart; } bool RenX::Server::isFirstKill() const @@ -243,6 +243,28 @@ RenX::BuildingInfo *RenX::Server::getBuildingByName(const Jupiter::ReadableStrin return nullptr; } +const Jupiter::ReadableString &RenX::Server::getCurrentRCONCommand() const +{ + return RenX::Server::lastCommand; +} + +const Jupiter::ReadableString &RenX::Server::getCurrentRCONCommandParameters() const +{ + return RenX::Server::lastCommandParams; +} + +std::chrono::milliseconds RenX::Server::getGameTime() const +{ + return std::chrono::duration_cast(std::chrono::steady_clock::now() - RenX::Server::gameStart); +} + +std::chrono::milliseconds RenX::Server::getGameTime(const RenX::PlayerInfo *player) const +{ + if (player->joinTime < RenX::Server::gameStart) + return RenX::Server::getGameTime(); + return std::chrono::duration_cast(std::chrono::steady_clock::now() - player->joinTime); +} + RenX::PlayerInfo *RenX::Server::getPlayer(int id) const { if (RenX::Server::players.size() == 0) return nullptr; @@ -904,7 +926,6 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) }; auto onPostGameOver = [this](RenX::WinType winType, RenX::TeamType team, int gScore, int nScore) { - this->firstGame = false; this->firstAction = false; this->firstKill = false; this->firstDeath = false; @@ -1026,7 +1047,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) r->steamid = steamid; if (r->isBot = isBot) r->formatNamePrefix = IRCCOLOR "05[B]"; - r->joinTime = time(nullptr); + r->joinTime = std::chrono::steady_clock::now(); if (id != 0) this->players.add(r); @@ -1139,11 +1160,11 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Score")); if (pair != nullptr) - player->score = static_cast(pair->getValue().asDouble()); + player->score = pair->getValue().asDouble(); pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Credits")); if (pair != nullptr) - player->credits = static_cast(pair->getValue().asDouble()); + player->credits = pair->getValue().asDouble(); pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Character")); if (pair != nullptr) @@ -1292,11 +1313,11 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Score")); if (pair != nullptr) - player->score = static_cast(pair->getValue().asDouble()); + player->score = pair->getValue().asDouble(); pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Credits")); if (pair != nullptr) - player->credits = static_cast(pair->getValue().asDouble()); + player->credits = pair->getValue().asDouble(); pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Character")); if (pair != nullptr) @@ -1996,7 +2017,6 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) if (buff.getToken(5, RenX::DelimC).equals("steamid")) steamid = buff.getToken(6, RenX::DelimC).asUnsignedLongLong(); RenX::PlayerInfo *player = getPlayerOrAdd(name, id, team, isBot, steamid, buff.getToken(4, RenX::DelimC)); - player->joinTime = time(0); for (size_t i = 0; i < xPlugins.size(); i++) xPlugins.get(i)->RenX_OnJoin(this, player); } @@ -2357,6 +2377,8 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) else if (subHeader.equals("Start;")) { // Map + this->seenStart = true; + this->gameStart = std::chrono::steady_clock::now(); Jupiter::ReferenceString map = buff.getToken(2, RenX::DelimC); this->map = map; for (size_t i = 0; i < xPlugins.size(); i++) @@ -2448,7 +2470,8 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) RenX::Server::fetchClientList(); RenX::Server::updateBuildingList(); - this->firstGame = true; + RenX::Server::gameStart = std::chrono::steady_clock::now(); + this->seenStart = false; this->seamless = true; for (size_t i = 0; i < xPlugins.size(); i++) diff --git a/RenX.Core/RenX_Server.h b/RenX.Core/RenX_Server.h index 18e1faf..9c0415d 100644 --- a/RenX.Core/RenX_Server.h +++ b/RenX.Core/RenX_Server.h @@ -95,11 +95,11 @@ namespace RenX bool isConnected() const; /** - * @brief Checks if the game in progress is the first game. + * @brief Checks if a map start event has fired. * - * @return True if this is the first game, false otherwise. + * @return True if a map start event has fired, false otherwise. */ - bool isFirstGame() const; + bool hasSeenStart() const; /** * @brief Checks if the first kill has already been processed. @@ -208,6 +208,37 @@ namespace RenX */ RenX::BuildingInfo *getBuildingByName(const Jupiter::ReadableString &name) const; + /** + * @brief Fetches the RCON command currently being processed. + * + * @return RCON command last executed. + */ + const Jupiter::ReadableString &getCurrentRCONCommand() const; + + /** + * @brief Fetches the parameters of the RCON command currently being processed. + * + * @return Parameters of last RCON command last executed. + */ + const Jupiter::ReadableString &getCurrentRCONCommandParameters() const; + + /** + * @brief Calculates the time since match start. + * Note: if hasSeenStart() is false, this is the time since the connection was established. + * + * @return Time since match start. + */ + std::chrono::milliseconds getGameTime() const; + + /** + * @brief Calculates the time the player has been playing. + * Note: This will never be greater than getGameTime(void) + * + * @param player Player to calculate game-time of. + * @return Time player has been playing. + */ + std::chrono::milliseconds getGameTime(const RenX::PlayerInfo *player) const; + /** * @brief Fetches a player's data based on their ID number. * @@ -829,7 +860,7 @@ namespace RenX bool needsCList = false; bool silenceParts = false; bool silenceJoins = false; - bool firstGame = true; + bool seenStart = true; bool firstKill = false; bool firstDeath = false; bool firstAction = false; @@ -837,6 +868,7 @@ namespace RenX unsigned int rconVersion = 0; time_t lastAttempt = 0; int attempts = 0; + std::chrono::steady_clock::time_point gameStart = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point lastClientListUpdate = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point lastBuildingListUpdate = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point lastActivity = std::chrono::steady_clock::now(); diff --git a/RenX.Core/RenX_Tags.cpp b/RenX.Core/RenX_Tags.cpp index 17dcab3..04332a3 100644 --- a/RenX.Core/RenX_Tags.cpp +++ b/RenX.Core/RenX_Tags.cpp @@ -366,7 +366,7 @@ void TagsImp::processTags(Jupiter::StringType &msg, const RenX::Server *server, PROCESS_TAG(this->INTERNAL_CREDITS_TAG, Jupiter::StringS::Format("%.0f", player->credits)); PROCESS_TAG(this->INTERNAL_KILLS_TAG, Jupiter::StringS::Format("%u", player->kills)); PROCESS_TAG(this->INTERNAL_DEATHS_TAG, Jupiter::StringS::Format("%u", player->deaths)); - PROCESS_TAG(this->INTERNAL_KDR_TAG, Jupiter::StringS::Format("%.2f", static_cast(player->kills) / (player->deaths == 0 ? 1.0f : static_cast(player->deaths)))); + PROCESS_TAG(this->INTERNAL_KDR_TAG, Jupiter::StringS::Format("%.2f", static_cast(player->kills) / (player->deaths == 0 ? 1.0f : static_cast(player->deaths)))); PROCESS_TAG(this->INTERNAL_SUICIDES_TAG, Jupiter::StringS::Format("%u", player->suicides)); PROCESS_TAG(this->INTERNAL_HEADSHOTS_TAG, Jupiter::StringS::Format("%u", player->headshots)); PROCESS_TAG(this->INTERNAL_VEHICLE_KILLS_TAG, Jupiter::StringS::Format("%u", player->vehicleKills)); @@ -401,7 +401,7 @@ void TagsImp::processTags(Jupiter::StringType &msg, const RenX::Server *server, PROCESS_TAG(this->INTERNAL_VICTIM_CREDITS_TAG, Jupiter::StringS::Format("%.0f", victim->credits)); PROCESS_TAG(this->INTERNAL_VICTIM_KILLS_TAG, Jupiter::StringS::Format("%u", victim->kills)); PROCESS_TAG(this->INTERNAL_VICTIM_DEATHS_TAG, Jupiter::StringS::Format("%u", victim->deaths)); - PROCESS_TAG(this->INTERNAL_VICTIM_KDR_TAG, Jupiter::StringS::Format("%.2f", static_cast(victim->kills) / (victim->deaths == 0 ? 1.0f : static_cast(victim->deaths)))); + PROCESS_TAG(this->INTERNAL_VICTIM_KDR_TAG, Jupiter::StringS::Format("%.2f", static_cast(victim->kills) / (victim->deaths == 0 ? 1.0f : static_cast(victim->deaths)))); PROCESS_TAG(this->INTERNAL_VICTIM_SUICIDES_TAG, Jupiter::StringS::Format("%u", victim->suicides)); PROCESS_TAG(this->INTERNAL_VICTIM_HEADSHOTS_TAG, Jupiter::StringS::Format("%u", victim->headshots)); PROCESS_TAG(this->INTERNAL_VICTIM_VEHICLE_KILLS_TAG, Jupiter::StringS::Format("%u", victim->vehicleKills)); diff --git a/RenX.ExcessiveHeadshots/ExcessiveHeadshots.cpp b/RenX.ExcessiveHeadshots/ExcessiveHeadshots.cpp index e766023..36e9ccb 100644 --- a/RenX.ExcessiveHeadshots/ExcessiveHeadshots.cpp +++ b/RenX.ExcessiveHeadshots/ExcessiveHeadshots.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 Justin James. + * Copyright (C) 2014-2015 Justin James. * * This license must be preserved. * Any applications, libraries, or code which make any use of any @@ -44,12 +44,14 @@ void RenX_ExcessiveHeadshotsPlugin::RenX_OnKill(RenX::Server *server, const RenX if (damageType.equals("Rx_DmgType_Headshot")) { unsigned int flags = 0; + std::chrono::milliseconds game_time = server->getGameTime(player); + double kps = game_time == std::chrono::milliseconds(0) ? static_cast(player->kills) : static_cast(player->kills) / static_cast(game_time.count()); if (player->kills >= RenX_ExcessiveHeadshotsPlugin::minKills) flags++; if (RenX::getHeadshotKillRatio(player) >= RenX_ExcessiveHeadshotsPlugin::ratio) flags++; if (RenX::getKillDeathRatio(player) >= RenX_ExcessiveHeadshotsPlugin::minKD) flags++; - if (RenX::getKillsPerSecond(player) >= RenX_ExcessiveHeadshotsPlugin::minKPS) flags++; - if (RenX::getKillsPerSecond(player) >= RenX_ExcessiveHeadshotsPlugin::minKPS * 2) flags++; - if (RenX::getGameTime(player) <= RenX_ExcessiveHeadshotsPlugin::maxGameTime) flags++; + if (kps >= RenX_ExcessiveHeadshotsPlugin::minKPS) flags++; + if (kps >= RenX_ExcessiveHeadshotsPlugin::minKPS * 2) flags++; + if (game_time <= RenX_ExcessiveHeadshotsPlugin::maxGameTime) flags++; if (flags >= RenX_ExcessiveHeadshotsPlugin::minFlags) { diff --git a/RenX.ExcessiveHeadshots/ExcessiveHeadshots.h b/RenX.ExcessiveHeadshots/ExcessiveHeadshots.h index d0a2610..78eb7fa 100644 --- a/RenX.ExcessiveHeadshots/ExcessiveHeadshots.h +++ b/RenX.ExcessiveHeadshots/ExcessiveHeadshots.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 Justin James. + * Copyright (C) 2014-2015 Justin James. * * This license must be preserved. * Any applications, libraries, or code which make any use of any @@ -18,6 +18,7 @@ #if !defined _EXCESSIVEHEADSHOTS_H_HEADER #define _EXCESSIVEHEADSHOTS_H_HEADER +#include #include "Jupiter/Plugin.h" #include "RenX_Plugin.h" @@ -38,7 +39,7 @@ private: double minKD = 5.0; double minKPS = 0.1; unsigned int minKills = 10; - time_t maxGameTime = 180; + std::chrono::seconds maxGameTime = std::chrono::seconds(180); }; #endif // _EXCESSIVEHEADSHOTS_H_HEADER \ No newline at end of file diff --git a/RenX.Medals/RenX_Medals.cpp b/RenX.Medals/RenX_Medals.cpp index 0a286f3..65af24c 100644 --- a/RenX.Medals/RenX_Medals.cpp +++ b/RenX.Medals/RenX_Medals.cpp @@ -26,6 +26,8 @@ #include "RenX_Core.h" #include "RenX_Tags.h" +using namespace Jupiter::literals; + RenX_MedalsPlugin::RenX_MedalsPlugin() { this->INTERNAL_RECS_TAG = RenX::getUniqueInternalTag(); @@ -68,21 +70,27 @@ struct CongratPlayerData void congratPlayer(unsigned int, void *params) { - CongratPlayerData *congratPlayerData = (CongratPlayerData *) params; + CongratPlayerData *congratPlayerData = reinterpret_cast(params); - switch (congratPlayerData->type) + if (RenX::getCore()->hasServer(congratPlayerData->server) && congratPlayerData->server->isConnected()) { - case 1: - congratPlayerData->server->sendMessage(Jupiter::StringS::Format("%.*s has been recommended for having the most kills last game!", congratPlayerData->playerName.size(), congratPlayerData->playerName.ptr())); - break; - case 2: - congratPlayerData->server->sendMessage(Jupiter::StringS::Format("%.*s has been recommended for having the most vehicle kills last game!", congratPlayerData->playerName.size(), congratPlayerData->playerName.ptr())); - break; - case 3: - congratPlayerData->server->sendMessage(Jupiter::StringS::Format("%.*s has been recommended for having the highest Kill-Death ratio last game!", congratPlayerData->playerName.size(), congratPlayerData->playerName.ptr())); - break; - default: - break; + switch (congratPlayerData->type) + { + case 0: + congratPlayerData->server->sendMessage(congratPlayerData->playerName + " has been recommended for having the highest score last game!"_jrs); + break; + case 1: + congratPlayerData->server->sendMessage(congratPlayerData->playerName + " has been recommended for having the most kills last game!"_jrs); + break; + case 2: + congratPlayerData->server->sendMessage(congratPlayerData->playerName + " has been recommended for having the most vehicle kills last game!"_jrs); + break; + case 3: + congratPlayerData->server->sendMessage(congratPlayerData->playerName + " has been recommended for having the highest Kill-Death ratio last game!"_jrs); + break; + default: + break; + } } delete congratPlayerData; } @@ -159,11 +167,11 @@ void RenX_MedalsPlugin::RenX_OnJoin(RenX::Server *server, const RenX::PlayerInfo void RenX_MedalsPlugin::RenX_OnGameOver(RenX::Server *server, RenX::WinType winType, const RenX::TeamType &team, int gScore, int nScore) { - if (server->isFirstGame() == false) // No unfair medals for the first game! :D + if (server->hasSeenStart() && server->players.size() != 0) // No unfair medals for the first game! :D { - if (server->players.size() == 0) return; Jupiter::DLList::Node *n = server->players.getNode(0); RenX::PlayerInfo *pInfo = n->data; + RenX::PlayerInfo *bestScore = pInfo; RenX::PlayerInfo *mostKills = pInfo; RenX::PlayerInfo *mostVehicleKills = pInfo; RenX::PlayerInfo *bestKD = pInfo; @@ -171,6 +179,9 @@ void RenX_MedalsPlugin::RenX_OnGameOver(RenX::Server *server, RenX::WinType winT while (n != nullptr) { pInfo = n->data; + if (pInfo->score > bestScore->score) + bestScore = pInfo; + if (pInfo->kills > mostKills->kills) mostKills = pInfo; @@ -185,6 +196,18 @@ void RenX_MedalsPlugin::RenX_OnGameOver(RenX::Server *server, RenX::WinType winT CongratPlayerData *congratPlayerData; + /** +1 for best score */ + if (bestScore->uuid.isNotEmpty() && bestScore->isBot == false && bestScore->score > 0) + { + addRec(bestScore); + + congratPlayerData = new CongratPlayerData(); + congratPlayerData->server = server; + congratPlayerData->playerName = bestScore->name; + congratPlayerData->type = 0; + new Jupiter::Timer(1, killCongratDelay, congratPlayer, congratPlayerData, false); + } + /** +1 for most kills */ if (mostKills->uuid.isNotEmpty() && mostKills->isBot == false && mostKills->kills > 0) {