csrd_bot_names.sp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /**
  2. * Sourcemod 1.7 Plugin Template
  3. */
  4. #pragma semicolon 1
  5. #include <sourcemod>
  6. #include <tf2>
  7. #include <botmanager>
  8. #pragma newdecls required
  9. #define PLUGIN_VERSION "0.1.2"
  10. public Plugin myinfo = {
  11. name = "[CSRD] Bot Names",
  12. author = "nosoop",
  13. description = "Pulls bot names from a database.",
  14. version = PLUGIN_VERSION,
  15. url = "localhost"
  16. }
  17. Database g_NameDatabase;
  18. DBStatement g_hGetBotNames;
  19. /**
  20. * We use a stack so players can't force reconnecting bots to get new names
  21. * An ArrayList would work just as well, too.
  22. */
  23. ArrayStack g_BotNames;
  24. char g_OriginalBotName[MAXPLAYERS+1][MAX_NAME_LENGTH];
  25. public void OnPluginStart() {
  26. char error[256];
  27. g_NameDatabase = SQLite_UseDatabase("bot-names", error, sizeof(error));
  28. g_hGetBotNames = SQL_PrepareQuery(g_NameDatabase,
  29. "SELECT name FROM namelist ORDER BY random() LIMIT ?;",
  30. error, sizeof(error));
  31. if (!g_hGetBotNames) {
  32. SetFailState("Failed to get bot names from database: %s", error);
  33. }
  34. g_BotNames = new ArrayStack(ByteCountToCells(MAX_NAME_LENGTH + 1));
  35. }
  36. public void OnPluginEnd() {
  37. delete g_hGetBotNames;
  38. delete g_NameDatabase;
  39. }
  40. public void OnMapStart() {
  41. // deal with late loads just to be safe
  42. ArrayList usedBotNames = new ArrayList(ByteCountToCells(MAX_NAME_LENGTH + 1));
  43. int nExistingBots;
  44. for (int i = 1; i <= MaxClients; i++) {
  45. if (IsClientInGame(i) && IsFakeClient(i)) {
  46. char name[MAX_NAME_LENGTH];
  47. GetClientName(i, name, sizeof(name));
  48. usedBotNames.PushString(name);
  49. nExistingBots++;
  50. }
  51. }
  52. // use database
  53. g_hGetBotNames.BindInt(0, MaxClients + nExistingBots);
  54. SQL_Execute(g_hGetBotNames);
  55. while (SQL_FetchRow(g_hGetBotNames)) {
  56. char name[MAX_NAME_LENGTH];
  57. SQL_FetchString(g_hGetBotNames, 0, name, sizeof(name));
  58. if (usedBotNames.FindString(name) == -1) {
  59. g_BotNames.PushString(name);
  60. }
  61. }
  62. delete usedBotNames;
  63. }
  64. public void OnMapEnd() {
  65. // empty the bot name stack
  66. EmptyStack(g_BotNames);
  67. for (int i = 1; i <= MAXPLAYERS; i++) {
  68. g_OriginalBotName[i] = "";
  69. }
  70. }
  71. /**
  72. * Sets the name of a freshly-added bot.
  73. */
  74. public int Bot_OnBotAdd(TFClassType &class, TFTeam &team, int &difficulty,
  75. char name[MAX_NAME_LENGTH]) {
  76. // pop the name off the stack
  77. if (strlen(name) == 0 && !g_BotNames.Empty) {
  78. g_BotNames.PopString(name, MAX_NAME_LENGTH);
  79. }
  80. }
  81. /**
  82. * Store the bot's name at the time of connection.
  83. * We'll assume it's a valid name from the pool.
  84. */
  85. public void OnClientConnected(int client) {
  86. if (IsFakeClient(client)) {
  87. GetClientName(client, g_OriginalBotName[client], sizeof(g_OriginalBotName[]));
  88. }
  89. }
  90. /**
  91. * Returns the bot name to the name stack.
  92. */
  93. public void OnClientDisconnect(int client) {
  94. if (IsFakeClient(client)) {
  95. char name[MAX_NAME_LENGTH];
  96. if (strlen(g_OriginalBotName[client]) > 0) {
  97. name = g_OriginalBotName[client];
  98. g_OriginalBotName[client] = "";
  99. g_BotNames.PushString(name);
  100. }
  101. /**
  102. * else plugin got reloaded or a TFBot snuck in so we have no idea what's up
  103. * don't worry about them
  104. */
  105. }
  106. }
  107. /**
  108. * Empties an ArrayStack.
  109. */
  110. stock int EmptyStack(ArrayStack stack) {
  111. int nPopped;
  112. while (PopStack(stack)) {
  113. nPopped++;
  114. }
  115. return nPopped;
  116. }