diff --git a/RenX.MinPlayers/RenX.MinPlayers.vcxproj b/RenX.MinPlayers/RenX.MinPlayers.vcxproj
new file mode 100644
index 0000000..2b3f714
--- /dev/null
+++ b/RenX.MinPlayers/RenX.MinPlayers.vcxproj
@@ -0,0 +1,85 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {99D34DCB-A484-437C-9FC5-D4051FEDC18C}
+ RenX.MinPlayers
+
+
+
+ Application
+ true
+ v140
+ MultiByte
+
+
+ DynamicLibrary
+ false
+ v140
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+ $(SolutionDir)$(Configuration)\Plugins\
+ AllRules.ruleset
+
+
+
+ Level3
+ Disabled
+ true
+
+
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ ../Bot;../Jupiter;../RenX.Core
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RenX.MinPlayers/RenX.MinPlayers.vcxproj.filters b/RenX.MinPlayers/RenX.MinPlayers.vcxproj.filters
new file mode 100644
index 0000000..48d98fa
--- /dev/null
+++ b/RenX.MinPlayers/RenX.MinPlayers.vcxproj.filters
@@ -0,0 +1,38 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/RenX.MinPlayers/RenX_MinPlayers.cpp b/RenX.MinPlayers/RenX_MinPlayers.cpp
new file mode 100644
index 0000000..1a16118
--- /dev/null
+++ b/RenX.MinPlayers/RenX_MinPlayers.cpp
@@ -0,0 +1,134 @@
+/**
+ * Copyright (C) 2015 Justin James.
+ *
+ * This license must be preserved.
+ * Any applications, libraries, or code which make any use of any
+ * component of this program must not be commercial, unless explicit
+ * permission is granted from the original author. The use of this
+ * program for non-profit purposes is permitted.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * In the event that this license restricts you from making desired use of this program, contact the original author.
+ * Written by Justin James
+ */
+
+#include "Jupiter/IRC_Client.h"
+#include "Jupiter/INIFile.h"
+#include "RenX_Server.h"
+#include "RenX_PlayerInfo.h"
+#include "RenX_MinPlayers.h"
+
+using namespace Jupiter::literals;
+
+RenX_MinPlayersPlugin::RenX_MinPlayersPlugin()
+{
+ RenX_MinPlayersPlugin::player_threshold = Jupiter::IRC::Client::Config->getInt(this->getName(), "PlayerThreshold"_jrs, 20);
+}
+
+void RenX_MinPlayersPlugin::RenX_OnMapStart(RenX::Server *server, const Jupiter::ReadableString &map)
+{
+ if (server->players.size() < RenX_MinPlayersPlugin::player_threshold)
+ server->send(Jupiter::StringS::Format("addbots %d", RenX_MinPlayersPlugin::player_threshold - server->players.size()));
+}
+
+void RenX_MinPlayersPlugin::RenX_OnJoin(RenX::Server *server, const RenX::PlayerInfo *player)
+{
+ if (server->players.size() > RenX_MinPlayersPlugin::player_threshold)
+ ++RenX_MinPlayersPlugin::phase_bots;
+}
+
+void RenX_MinPlayersPlugin::RenX_OnPart(RenX::Server *server, const RenX::PlayerInfo *player)
+{
+ if (server->players.size() <= player_threshold)
+ {
+ switch (player->team)
+ {
+ case RenX::TeamType::GDI:
+ server->send("addredbots 1"_jrs);
+ break;
+ case RenX::TeamType::Nod:
+ server->send("addbluebots 1"_jrs);
+ break;
+ case RenX::TeamType::None:
+ break;
+ default:
+ server->send("addbots 1"_jrs);
+ break;
+ }
+ }
+}
+
+void RenX_MinPlayersPlugin::AnyDeath(RenX::Server *server, const RenX::PlayerInfo *player)
+{
+ if (RenX_MinPlayersPlugin::phase_bots != 0 && player->isBot && server->players.size() != 0)
+ {
+ size_t gdi_count = 0, nod_count = 0;
+ for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next)
+ {
+ switch (node->data->team)
+ {
+ case RenX::TeamType::GDI:
+ ++gdi_count;
+ break;
+ case RenX::TeamType::Nod:
+ ++nod_count;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (gdi_count > nod_count)
+ {
+ if (player->team != RenX::TeamType::Nod)
+ {
+ server->kickPlayer(player, "Bot Phasing"_jrs);
+ --RenX_MinPlayersPlugin::phase_bots;
+ }
+ }
+ else if (nod_count > gdi_count)
+ {
+ if (player->team != RenX::TeamType::GDI)
+ {
+ server->kickPlayer(player, "Bot Phasing"_jrs);
+ --RenX_MinPlayersPlugin::phase_bots;
+ }
+ }
+ else
+ {
+ server->kickPlayer(player, "Bot Phasing"_jrs);
+ --RenX_MinPlayersPlugin::phase_bots;
+ }
+ }
+}
+
+void RenX_MinPlayersPlugin::RenX_OnSuicide(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &damageType)
+{
+ this->AnyDeath(server, player);
+}
+
+void RenX_MinPlayersPlugin::RenX_OnKill(RenX::Server *server, const RenX::PlayerInfo *player, const RenX::PlayerInfo *victim, const Jupiter::ReadableString &damageType)
+{
+ this->AnyDeath(server, player);
+}
+
+void RenX_MinPlayersPlugin::RenX_OnKill(RenX::Server *server, const Jupiter::ReadableString &killer, const RenX::TeamType &killerTeam, const RenX::PlayerInfo *victim, const Jupiter::ReadableString &damageType)
+{
+ this->AnyDeath(server, victim);
+}
+
+void RenX_MinPlayersPlugin::RenX_OnDie(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &damageType)
+{
+ this->AnyDeath(server, player);
+}
+
+// Plugin instantiation and entry point.
+RenX_MinPlayersPlugin pluginInstance;
+
+extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin()
+{
+ return &pluginInstance;
+}
diff --git a/RenX.MinPlayers/RenX_MinPlayers.h b/RenX.MinPlayers/RenX_MinPlayers.h
new file mode 100644
index 0000000..507a316
--- /dev/null
+++ b/RenX.MinPlayers/RenX_MinPlayers.h
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2015 Justin James.
+ *
+ * This license must be preserved.
+ * Any applications, libraries, or code which make any use of any
+ * component of this program must not be commercial, unless explicit
+ * permission is granted from the original author. The use of this
+ * program for non-profit purposes is permitted.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * In the event that this license restricts you from making desired use of this program, contact the original author.
+ * Written by Justin James
+ */
+
+#if !defined _RENX_MINPLAYERS_H_HEADER
+#define _RENX_MINPLAYERS_H_HEADER
+
+#include "Jupiter/Plugin.h"
+#include "Jupiter/Reference_String.h"
+#include "RenX_Plugin.h"
+
+class RenX_MinPlayersPlugin : public RenX::Plugin
+{
+public:
+ void RenX_OnMapStart(RenX::Server *server, const Jupiter::ReadableString &map) override;
+ void RenX_OnJoin(RenX::Server *server, const RenX::PlayerInfo *player) override;
+ void RenX_OnPart(RenX::Server *server, const RenX::PlayerInfo *player) override;
+
+ void RenX_OnSuicide(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &damageType) override;
+ void RenX_OnKill(RenX::Server *server, const RenX::PlayerInfo *player, const RenX::PlayerInfo *victim, const Jupiter::ReadableString &damageType) override;
+ void RenX_OnKill(RenX::Server *server, const Jupiter::ReadableString &killer, const RenX::TeamType &killerTeam, const RenX::PlayerInfo *victim, const Jupiter::ReadableString &damageType) override;
+ void RenX_OnDie(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &damageType) override;
+
+ const Jupiter::ReadableString &getName() override { return name; }
+
+ RenX_MinPlayersPlugin();
+
+private:
+ void AnyDeath(RenX::Server *server, const RenX::PlayerInfo *player);
+ size_t phase_bots;
+
+ /** Configuration variables */
+ size_t player_threshold;
+ STRING_LITERAL_AS_NAMED_REFERENCE(name, "RenX.MinPlayers");
+};
+
+#endif // _RENX_MINPLAYERS_H_HEADER
\ No newline at end of file