|
@@ -0,0 +1,140 @@
|
|
|
+/**
|
|
|
+ * Sourcemod 1.7 Plugin Template
|
|
|
+ */
|
|
|
+#pragma semicolon 1
|
|
|
+#include <sourcemod>
|
|
|
+
|
|
|
+#include <tf2>
|
|
|
+#include <botmanager>
|
|
|
+
|
|
|
+#pragma newdecls required
|
|
|
+
|
|
|
+#define PLUGIN_VERSION "0.1.2"
|
|
|
+public Plugin myinfo = {
|
|
|
+ name = "[CSRD] Bot Names",
|
|
|
+ author = "nosoop",
|
|
|
+ description = "Pulls bot names from a database.",
|
|
|
+ version = PLUGIN_VERSION,
|
|
|
+ url = "localhost"
|
|
|
+}
|
|
|
+
|
|
|
+Database g_NameDatabase;
|
|
|
+DBStatement g_hGetBotNames;
|
|
|
+
|
|
|
+/**
|
|
|
+ * We use a stack so players can't force reconnecting bots to get new names
|
|
|
+ * An ArrayList would work just as well, too.
|
|
|
+ */
|
|
|
+ArrayStack g_BotNames;
|
|
|
+
|
|
|
+char g_OriginalBotName[MAXPLAYERS+1][MAX_NAME_LENGTH];
|
|
|
+
|
|
|
+public void OnPluginStart() {
|
|
|
+ char error[256];
|
|
|
+ g_NameDatabase = SQLite_UseDatabase("bot-names", error, sizeof(error));
|
|
|
+ g_hGetBotNames = SQL_PrepareQuery(g_NameDatabase,
|
|
|
+ "SELECT name FROM namelist ORDER BY random() LIMIT ?;",
|
|
|
+ error, sizeof(error));
|
|
|
+
|
|
|
+ if (!g_hGetBotNames) {
|
|
|
+ SetFailState("Failed to get bot names from database: %s", error);
|
|
|
+ }
|
|
|
+
|
|
|
+ g_BotNames = new ArrayStack(ByteCountToCells(MAX_NAME_LENGTH + 1));
|
|
|
+}
|
|
|
+
|
|
|
+public void OnPluginEnd() {
|
|
|
+ delete g_hGetBotNames;
|
|
|
+ delete g_NameDatabase;
|
|
|
+}
|
|
|
+
|
|
|
+public void OnMapStart() {
|
|
|
+ // deal with late loads just to be safe
|
|
|
+ ArrayList usedBotNames = new ArrayList(ByteCountToCells(MAX_NAME_LENGTH + 1));
|
|
|
+ int nExistingBots;
|
|
|
+ for (int i = 1; i <= MaxClients; i++) {
|
|
|
+ if (IsClientInGame(i) && IsFakeClient(i)) {
|
|
|
+ char name[MAX_NAME_LENGTH];
|
|
|
+ GetClientName(i, name, sizeof(name));
|
|
|
+
|
|
|
+ usedBotNames.PushString(name);
|
|
|
+
|
|
|
+ nExistingBots++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // use database
|
|
|
+ g_hGetBotNames.BindInt(0, MaxClients + nExistingBots);
|
|
|
+
|
|
|
+ SQL_Execute(g_hGetBotNames);
|
|
|
+ while (SQL_FetchRow(g_hGetBotNames)) {
|
|
|
+ char name[MAX_NAME_LENGTH];
|
|
|
+ SQL_FetchString(g_hGetBotNames, 0, name, sizeof(name));
|
|
|
+
|
|
|
+ if (usedBotNames.FindString(name) == -1) {
|
|
|
+ g_BotNames.PushString(name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ delete usedBotNames;
|
|
|
+}
|
|
|
+
|
|
|
+public void OnMapEnd() {
|
|
|
+ // empty the bot name stack
|
|
|
+ EmptyStack(g_BotNames);
|
|
|
+
|
|
|
+ for (int i = 1; i <= MAXPLAYERS; i++) {
|
|
|
+ g_OriginalBotName[i] = "";
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Sets the name of a freshly-added bot.
|
|
|
+ */
|
|
|
+public int Bot_OnBotAdd(TFClassType &class, TFTeam &team, int &difficulty,
|
|
|
+ char name[MAX_NAME_LENGTH]) {
|
|
|
+ // pop the name off the stack
|
|
|
+ if (strlen(name) == 0 && !g_BotNames.Empty) {
|
|
|
+ g_BotNames.PopString(name, MAX_NAME_LENGTH);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Store the bot's name at the time of connection.
|
|
|
+ * We'll assume it's a valid name from the pool.
|
|
|
+ */
|
|
|
+public void OnClientConnected(int client) {
|
|
|
+ if (IsFakeClient(client)) {
|
|
|
+ GetClientName(client, g_OriginalBotName[client], sizeof(g_OriginalBotName[]));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Returns the bot name to the name stack.
|
|
|
+ */
|
|
|
+public void OnClientDisconnect(int client) {
|
|
|
+ if (IsFakeClient(client)) {
|
|
|
+ char name[MAX_NAME_LENGTH];
|
|
|
+
|
|
|
+ if (strlen(g_OriginalBotName[client]) > 0) {
|
|
|
+ name = g_OriginalBotName[client];
|
|
|
+ g_OriginalBotName[client] = "";
|
|
|
+ g_BotNames.PushString(name);
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * else plugin got reloaded or a TFBot snuck in so we have no idea what's up
|
|
|
+ * don't worry about them
|
|
|
+ */
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Empties an ArrayStack.
|
|
|
+ */
|
|
|
+stock int EmptyStack(ArrayStack stack) {
|
|
|
+ int nPopped;
|
|
|
+ while (PopStack(stack)) {
|
|
|
+ nPopped++;
|
|
|
+ }
|
|
|
+ return nPopped;
|
|
|
+}
|