You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

468 lines
17 KiB

/**
* Copyright (C) 2014-2017 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#include <ctime>
#include "Jupiter/Timer.h"
#include "Jupiter/IRC_Client.h"
#include "RenX_Medals.h"
#include "RenX_Server.h"
#include "RenX_PlayerInfo.h"
#include "RenX_Functions.h"
#include "RenX_Core.h"
#include "RenX_Tags.h"
using namespace Jupiter::literals;
bool RenX_MedalsPlugin::initialize()
{
this->INTERNAL_RECS_TAG = RenX::getUniqueInternalTag();
this->INTERNAL_NOOB_TAG = RenX::getUniqueInternalTag();
this->INTERNAL_WORTH_TAG = RenX::getUniqueInternalTag();
init();
return true;
}
RenX_MedalsPlugin::~RenX_MedalsPlugin()
{
RenX::Core *core = RenX::getCore();
size_t sCount = core->getServerCount();
RenX::Server *server;
for (size_t i = 0; i < sCount; i++)
{
server = core->getServer(i);
if (server->players.size() != 0)
{
for (auto node = server->players.begin(); node != server->players.end(); ++node)
{
if (node->uuid.isNotEmpty() && node->isBot == false)
{
RenX_MedalsPlugin::medalsFile[node->uuid].set("Recs"_jrs, node->varData[this->getName()].get("Recs"_jrs));
RenX_MedalsPlugin::medalsFile[node->uuid].set("Noobs"_jrs, node->varData[this->getName()].get("Noobs"_jrs));
}
}
}
}
RenX_MedalsPlugin::medalsFile.write(RenX_MedalsPlugin::medalsFileName);
}
struct CongratPlayerData
{
RenX::Server *server;
Jupiter::StringS playerName;
unsigned int type;
};
void congratPlayer(unsigned int, void *params)
{
CongratPlayerData *congratPlayerData = reinterpret_cast<CongratPlayerData *>(params);
if (RenX::getCore()->hasServer(congratPlayerData->server) && congratPlayerData->server->isConnected())
{
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;
}
void RenX_MedalsPlugin::RenX_SanitizeTags(Jupiter::StringType &fmt)
{
fmt.replace(RenX_MedalsPlugin::recsTag, this->INTERNAL_RECS_TAG);
fmt.replace(RenX_MedalsPlugin::noobTag, this->INTERNAL_NOOB_TAG);
fmt.replace(RenX_MedalsPlugin::worthTag, this->INTERNAL_WORTH_TAG);
}
void RenX_MedalsPlugin::RenX_ProcessTags(Jupiter::StringType &msg, const RenX::Server *server, const RenX::PlayerInfo *player, const RenX::PlayerInfo *, const RenX::BuildingInfo *)
{
if (player != nullptr)
{
const Jupiter::ReadableString &recs = RenX_MedalsPlugin::medalsFile.get(player->uuid, "Recs"_jrs);
const Jupiter::ReadableString &noobs = RenX_MedalsPlugin::medalsFile.get(player->uuid, "Noobs"_jrs);
msg.replace(this->INTERNAL_RECS_TAG, recs);
msg.replace(this->INTERNAL_NOOB_TAG, noobs);
msg.replace(this->INTERNAL_WORTH_TAG, Jupiter::StringS::Format("%d", recs.asInt() - noobs.asInt()));
}
}
void RenX_MedalsPlugin::RenX_OnPlayerCreate(RenX::Server &, const RenX::PlayerInfo &player)
{
if (player.uuid.isNotEmpty() && player.isBot == false)
{
player.varData[this->getName()].set("Recs"_jrs, RenX_MedalsPlugin::medalsFile.get(player.uuid, "Recs"_jrs));
player.varData[this->getName()].set("Noobs"_jrs, RenX_MedalsPlugin::medalsFile.get(player.uuid, "Noobs"_jrs));
}
}
void RenX_MedalsPlugin::RenX_OnPlayerDelete(RenX::Server &, const RenX::PlayerInfo &player)
{
if (player.uuid.isNotEmpty() && player.isBot == false)
{
RenX_MedalsPlugin::medalsFile[player.uuid].set("Recs"_jrs, player.varData[this->getName()].get("Recs"_jrs));
RenX_MedalsPlugin::medalsFile[player.uuid].set("Noobs"_jrs, player.varData[this->getName()].get("Noobs"_jrs));
}
}
void RenX_MedalsPlugin::RenX_OnJoin(RenX::Server &server, const RenX::PlayerInfo &player)
{
if (player.uuid.isNotEmpty() && player.isBot == false && server.isMatchInProgress())
{
int worth = getWorth(player);
Jupiter::Config *section = RenX_MedalsPlugin::config.getSection(RenX_MedalsPlugin::firstSection);
if (section != nullptr)
{
while (section->get<int>("MaxRecs"_jrs, INT_MAX) < worth)
if ((section = RenX_MedalsPlugin::config.getSection(section->get("NextSection"_jrs))) == nullptr)
return; // No matching section found.
size_t table_size = section->getTable().size();
if (table_size != 0)
{
Jupiter::StringS msg = section->get(Jupiter::StringS::Format("%u", (rand() % table_size) + 1));
if (msg.isNotEmpty())
{
RenX::sanitizeTags(msg);
RenX::processTags(msg, &server, &player);
server.sendMessage(msg);
}
}
}
}
}
void RenX_MedalsPlugin::RenX_OnGameOver(RenX::Server &server, RenX::WinType winType, const RenX::TeamType &team, int gScore, int nScore)
{
if (server.isReliable() && server.players.size() != server.getBotCount())
{
RenX::PlayerInfo *bestScore = &server.players.front();
RenX::PlayerInfo *mostKills = &server.players.front();
RenX::PlayerInfo *mostVehicleKills = &server.players.front();
RenX::PlayerInfo *bestKD = &server.players.front();
for (auto node = server.players.begin(); node != server.players.end(); ++node)
{
if (node->score > bestScore->score)
bestScore = &*node;
if (node->kills > mostKills->kills)
mostKills = &*node;
if (node->vehicleKills > mostVehicleKills->vehicleKills)
mostVehicleKills = &*node;
if (RenX::getKillDeathRatio(*node) > RenX::getKillDeathRatio(*bestKD))
bestKD = &*node;
}
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)
{
addRec(*mostKills);
congratPlayerData = new CongratPlayerData();
congratPlayerData->server = &server;
congratPlayerData->playerName = mostKills->name;
congratPlayerData->type = 1;
new Jupiter::Timer(1, killCongratDelay, congratPlayer, congratPlayerData, false);
}
/** +1 for most Vehicle kills */
if (mostVehicleKills->uuid.isNotEmpty() && mostVehicleKills->isBot == false && mostVehicleKills->vehicleKills > 0)
{
addRec(*mostVehicleKills);
congratPlayerData = new CongratPlayerData();
congratPlayerData->server = &server;
congratPlayerData->playerName = mostVehicleKills->name;
congratPlayerData->type = 2;
new Jupiter::Timer(1, vehicleKillCongratDelay, congratPlayer, congratPlayerData, false);
}
/** +1 for best K/D ratio */
if (bestKD->uuid.isNotEmpty() && bestKD->isBot == false && RenX::getKillDeathRatio(*bestKD) > 1.0)
{
addRec(*bestKD);
congratPlayerData = new CongratPlayerData();
congratPlayerData->server = &server;
congratPlayerData->playerName = bestKD->name;
congratPlayerData->type = 3;
new Jupiter::Timer(1, kdrCongratDelay, congratPlayer, congratPlayerData, false);
}
}
RenX_MedalsPlugin::medalsFile.write(medalsFileName);
}
void RenX_MedalsPlugin::RenX_OnDestroy(RenX::Server &server, const RenX::PlayerInfo &player, const Jupiter::ReadableString &objectName, const RenX::TeamType &objectTeam, const Jupiter::ReadableString &damageType, RenX::ObjectType type)
{
if (type == RenX::ObjectType::Building)
{
addRec(player);
const Jupiter::ReadableString &translated = RenX::translateName(objectName);
server.sendMessage(Jupiter::StringS::Format("%.*s has been recommended for destroying the %.*s!", player.name.size(), player.name.ptr(), translated.size(), translated.ptr()));
}
}
int RenX_MedalsPlugin::OnRehash()
{
RenX::Plugin::OnRehash();
RenX_MedalsPlugin::medalsFile.write(RenX_MedalsPlugin::medalsFileName);
RenX_MedalsPlugin::medalsFile.erase();
init();
return 0;
}
void RenX_MedalsPlugin::init()
{
RenX_MedalsPlugin::killCongratDelay = std::chrono::seconds(this->config.get<long long>("KillCongratDelay"_jrs, 60));
RenX_MedalsPlugin::vehicleKillCongratDelay = std::chrono::seconds(this->config.get<long long>("VehicleKillCongratDelay"_jrs, 60));
RenX_MedalsPlugin::kdrCongratDelay = std::chrono::seconds(this->config.get<long long>("KDRCongratDelay"_jrs, 60));
RenX_MedalsPlugin::medalsFileName = this->config.get("MedalsFile"_jrs, "Medals.ini"_jrs);
RenX_MedalsPlugin::medalsFile.read(RenX_MedalsPlugin::medalsFileName);
RenX_MedalsPlugin::firstSection = RenX_MedalsPlugin::config.get("FirstSection"_jrs);
RenX_MedalsPlugin::recsTag = RenX_MedalsPlugin::config.get("RecsTag"_jrs, "{RECS}"_jrs);
RenX_MedalsPlugin::noobTag = RenX_MedalsPlugin::config.get("NoobsTag"_jrs, "{NOOBS}"_jrs);
RenX_MedalsPlugin::worthTag = RenX_MedalsPlugin::config.get("WorthTag"_jrs, "{WORTH}"_jrs);
RenX::Core *core = RenX::getCore();
unsigned int sCount = core->getServerCount();
RenX::Server *server;
for (unsigned int i = 0; i < sCount; i++)
{
server = core->getServer(i);
if (server->players.size() != server->getBotCount())
{
for (auto node = server->players.begin(); node != server->players.end(); ++node)
{
node->varData[this->getName()].set("Recs"_jrs, RenX_MedalsPlugin::medalsFile[node->name].get("Recs"_jrs));
node->varData[this->getName()].set("Noobs"_jrs, RenX_MedalsPlugin::medalsFile[node->name].get("Noobs"_jrs));
}
}
}
}
/** Game Commands */
/** Instance of RenX_MedalsPlugin */
RenX_MedalsPlugin pluginInstance;
// Recommendations Game Command
void RecsGameCommand::create()
{
this->addTrigger("recs"_jrs);
this->addTrigger("recommends"_jrs);
this->addTrigger("recommendations"_jrs);
this->addTrigger("noobs"_jrs);
this->addTrigger("n00bs"_jrs);
}
void RecsGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString &parameters)
{
if (parameters.isNotEmpty())
{
RenX::PlayerInfo *target = source->getPlayerByPartName(parameters);
if (target == nullptr)
{
Jupiter::Config *section = pluginInstance.medalsFile.getSection(parameters);
if (section == nullptr)
source->sendMessage(*player, "Error: Player not found! Syntax: recs [player]"_jrs);
else
{
unsigned int recs = section->get<unsigned int>("Recs"_jrs);
unsigned int noobs = section->get<unsigned int>("Noobs"_jrs);
source->sendMessage(*player, Jupiter::StringS::Format("[Archive] %.*s has %u and %u n00bs. Their worth: %d", section->getName().size(), section->getName().ptr(), recs, noobs, recs - noobs));
}
}
else if (target->uuid.isEmpty())
source->sendMessage(*player, "Error: Player is not using steam."_jrs);
else if (target->isBot)
source->sendMessage(*player, "Error: Bots do not have any recommendations."_jrs);
else if (target == player)
RecsGameCommand::trigger(source, player, Jupiter::ReferenceString::empty);
else
source->sendMessage(*player, Jupiter::StringS::Format("%.*s has %lu and %lu n00bs. Their worth: %d", target->name.size(), target->name.ptr(), getRecs(*target), getNoobs(*target), getWorth(*target)));
}
else if (player->uuid.isEmpty())
source->sendMessage(*player, "Error: You are not using steam."_jrs);
else
source->sendMessage(*player, Jupiter::StringS::Format("%.*s, you have %lu recs and %lu n00bs. Your worth: %d", player->name.size(), player->name.ptr(), getRecs(*player), getNoobs(*player), getWorth(*player)));
}
const Jupiter::ReadableString &RecsGameCommand::getHelp(const Jupiter::ReadableString &)
{
static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Gets a count of a player's recommendations and noobs. Syntax: recs [player]");
return defaultHelp;
}
GAME_COMMAND_INIT(RecsGameCommand)
// Recommend Game Command
void RecGameCommand::create()
{
this->addTrigger("rec"_jrs);
this->addTrigger("recommend"_jrs);
}
void RecGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString &parameters)
{
if (parameters.isNotEmpty())
{
RenX::PlayerInfo *target = source->getPlayerByPartName(parameters);
if (target == nullptr)
target = source->getPlayerByPartName(Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE));
if (target == nullptr)
source->sendMessage(*player, "Error: Player not found! Syntax: rec <player>"_jrs);
else if (target->uuid.isEmpty())
source->sendMessage(*player, "Error: Player is not using steam."_jrs);
else if (target->isBot)
source->sendMessage(*player, "Error: Bots can not receive recommendations."_jrs);
else if (target == player)
{
addNoob(*player);
source->sendMessage(*player, "You can't recommend yourself, you noob! (+1 noob)"_jrs);
}
else if (player->varData["RenX.Medals"_jrs].get("gr"_jrs) != nullptr && player->adminType.isEmpty())
source->sendMessage(*player, "You can only give one recommendation per game."_jrs);
else
{
addRec(*target);
source->sendMessage(Jupiter::StringS::Format("%.*s has recommended %.*s!", player->name.size(), player->name.ptr(), target->name.size(), target->name.ptr()));
player->varData["RenX.Medals"_jrs].set("gr"_jrs, "1"_jrs);
}
}
else RecsGameCommand_instance.trigger(source, player, parameters);
}
const Jupiter::ReadableString &RecGameCommand::getHelp(const Jupiter::ReadableString &)
{
static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Recommends a player for their gameplay. Syntax: rec [player]");
return defaultHelp;
}
GAME_COMMAND_INIT(RecGameCommand)
// Noob Game Command
void NoobGameCommand::create()
{
this->addTrigger("noob"_jrs);
this->addTrigger("n00b"_jrs);
}
void NoobGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString &parameters)
{
if (parameters.isNotEmpty())
{
RenX::PlayerInfo *target = source->getPlayerByPartName(parameters);
if (target == nullptr)
target = source->getPlayerByPartName(Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE));
if (target == nullptr)
source->sendMessage(*player, "Error: Player not found! Syntax: noob [player]"_jrs);
else if (target->uuid.isEmpty())
source->sendMessage(*player, "Error: Player is not using steam."_jrs);
else if (target->isBot)
source->sendMessage(*player, "Error: Bots can not receive n00bs."_jrs);
else if (player->varData["RenX.Medals"_jrs].get("gn"_jrs) != nullptr && player->adminType.isEmpty())
source->sendMessage(*player, "You can only give one noob per game."_jrs);
else
{
addNoob(*target);
source->sendMessage(Jupiter::StringS::Format("%.*s has noob'd %.*s!", player->name.size(), player->name.ptr(), target->name.size(), target->name.ptr()));
player->varData["RenX.Medals"_jrs].set("gn"_jrs, "1"_jrs);
}
}
else RecsGameCommand_instance.trigger(source, player, parameters);
}
const Jupiter::ReadableString &NoobGameCommand::getHelp(const Jupiter::ReadableString &)
{
static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Tells people that a player is bad. Syntax: noob [player]");
return defaultHelp;
}
GAME_COMMAND_INIT(NoobGameCommand)
void addRec(const RenX::PlayerInfo &player, int amount)
{
if (player.uuid.matchi("Player*") == false && player.isBot == false)
player.varData[pluginInstance.getName()].set("Recs"_jrs, Jupiter::StringS::Format("%u", getRecs(player) + amount));
}
void addNoob(const RenX::PlayerInfo &player, int amount)
{
if (player.uuid.matchi("Player*") == false && player.isBot == false)
player.varData[pluginInstance.getName()].set("Noobs"_jrs, Jupiter::StringS::Format("%u", getNoobs(player) + amount));
}
unsigned long getRecs(const RenX::PlayerInfo &player)
{
return player.varData[pluginInstance.getName()].get<unsigned long>("Recs"_jrs);
}
unsigned long getNoobs(const RenX::PlayerInfo &player)
{
return player.varData[pluginInstance.getName()].get<unsigned long>("Noobs"_jrs);
}
int getWorth(const RenX::PlayerInfo &player)
{
return getRecs(player) - getNoobs(player);
}
extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin()
{
return &pluginInstance;
}