nuclide/src/botlib/profiles.qc

220 lines
4.9 KiB
Plaintext

/*
* Copyright (c) 2023 Vera Visions LLC.
*
* Permission to use, copy, modify, and 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 MIND, 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.
*/
bool
Bot_ExistsInServer(string botName)
{
for (entity e = world;(e = find(e, ::classname, "player"));) {
if (clienttype(e) == CLIENTTYPE_BOT) {
if (e.netname == botName) {
return (true);
}
}
}
return (false);
}
bool
Bot_AddBot_f(string botName, float teamValue, float spawnDelay, string newName)
{
int extraCount = 0i;
int foundID = -1i;
entity oldSelf;
NSBot newBot;
int i = 0i;
if (!botName) {
print("Usage: Addbot <botname> [skill 1-5] [team] [msec delay] [altname]\n");
return (false);
}
if (!g_nodes_present) {
NSError("Can't add bot. No nodes.");
return (false);
}
/* grab the right profile id */
for (i = 0i; i < g_botScriptCount; i++) {
if (g_bots[i].m_strName == botName) {
foundID = i;
break;
}
}
if (foundID == -1i) {
NSError("Named profile %S not found.", botName);
return (false);
}
oldSelf = self;
self = spawnclient();
if (!self) {
NSError("Unable to add bot. Server is full.");
self = oldSelf;
return (false);
}
newBot = (NSBot)self;
newBot.SetInfoKey("name", g_bots[foundID].m_strNetName);
extraCount = tokenize(g_bots[foundID].m_strExtra);
for (i = 0i; i < extraCount; i+=2) {
newBot.SetInfoKey(argv(i), argv(i+1));
}
ClientConnect();
PutClientInServer();
self = oldSelf;
return (true);
}
bool
BotProfile_AddRandom(void)
{
int startValue = (int)floor(random(0, g_botScriptCount));
int spawnBot = -1i;
/* start at a random index */
for (int i = startValue; i < g_botScriptCount; i++) {
if (Bot_ExistsInServer(g_bots[i].m_strNetName) == false) {
spawnBot = i;
break;
}
}
/* still haven't found it. count down. */
if (spawnBot == -1i) {
for (int i = startValue - 1i; i > 0i; i--) {
if (Bot_ExistsInServer(g_bots[i].m_strNetName) == false) {
spawnBot = i;
break;
}
}
}
/* every bot exists already */
if (spawnBot == -1i) {
NSError("Not enough profiles available.");
return (false);
}
Bot_AddBot_f(g_bots[spawnBot].m_strName, 0, 0.0f, __NULL__);
return (true);
}
void
BotProfile_Init(void)
{
filestream botScript;
string tempString;
botScript_t currentDef;
int braceDepth = 0i;
InitStart();
currentDef.m_strName = "";
currentDef.m_strNetName = "";
currentDef.m_strExtra = "";
g_botScriptCount = 0i;
if (autocvar(bot_enable, 1) == 0) {
return;
}
botScript = fopen("scripts/bots.txt", FILE_READ);
if (botScript < 0) {
NSError("Missing file scripts/bots.txt");
return;
}
/* line by line */
while ((tempString = fgets(botScript))) {
int lineSegments = tokenize_console(tempString);
/* word for word */
for (int i = 0i; i < lineSegments; i++) {
string word = argv(i);
switch (word) {
case "{":
braceDepth++;
break;
case "}":
braceDepth--;
/* we've reached the end of a definition */
if (braceDepth == 0) {
/* we have something somewhat valid I guess */
if (currentDef.m_strName != "") {
g_bots[g_botScriptCount].m_strNetName = currentDef.m_strNetName;
g_bots[g_botScriptCount].m_strExtra = currentDef.m_strExtra;
if (g_bots[g_botScriptCount].m_strNetName == "") {
g_bots[g_botScriptCount].m_strNetName = currentDef.m_strName;
}
g_bots[g_botScriptCount].m_strName = strtolower(currentDef.m_strName);
/* increment the def count */
if (g_botScriptCount < BOTSCRIPT_MAX)
g_botScriptCount++;
}
currentDef.m_strName = "";
currentDef.m_strNetName = "";
currentDef.m_strExtra = "";
}
break;
default:
if (braceDepth == 1) {
if (word == "name") {
currentDef.m_strName = argv(i+1);
i++;
} else if (word == "funname") {
currentDef.m_strNetName = argv(i+1);
i++;
} else { /* rest gets dumped into extra */
currentDef.m_strExtra = strcat(currentDef.m_strExtra, "\"", word, "\"", " ");
}
}
}
}
}
fclose(botScript);
NSLog("...%i bots parsed.", g_botScriptCount);
InitEnd();
}
void
Bot_ListBotProfiles_f(void)
{
if (!g_botScriptCount) {
NSError("No bot profiles available.");
return;
}
for (int i = 0; i < g_botScriptCount; i++) {
print(sprintf("%i: %s\n", i, g_bots[i].m_strName));
print(sprintf("\t%S\n", g_bots[i].m_strNetName));
print(sprintf("\t%s\n", g_bots[i].m_strExtra));
}
}