Reworked the bot system

This commit is contained in:
smallmodel 2023-08-19 17:58:54 +02:00
parent d95cdcc142
commit 7a57a25c58
No known key found for this signature in database
GPG key ID: A96F163ED4891440
8 changed files with 152 additions and 50 deletions

View file

@ -1,6 +1,6 @@
/* /*
=========================================================================== ===========================================================================
Copyright (C) 2015 the OpenMoHAA team Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code. This file is part of OpenMoHAA source code.
@ -24,8 +24,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "g_local.h" #include "g_local.h"
#include "entity.h" #include "entity.h"
#include "playerbot.h" #include "playerbot.h"
#include "g_bot.h"
static gentity_t* firstBot = NULL; static gentity_t* firstBot = NULL;
static saved_bot_t* saved_bots = NULL;
static unsigned int current_bot_count = 0;
void G_BotBegin void G_BotBegin
( (
@ -64,7 +67,7 @@ gentity_t* G_GetFirstBot()
return firstBot; return firstBot;
} }
void G_AddBot(unsigned int num) void G_AddBot(unsigned int num, saved_bot_t* saved)
{ {
int n; int n;
int i; int i;
@ -72,8 +75,10 @@ void G_AddBot(unsigned int num)
gentity_t *e; gentity_t *e;
char botName[ MAX_NETNAME ]; char botName[ MAX_NETNAME ];
char challenge[ MAX_STRING_TOKENS ]; char challenge[ MAX_STRING_TOKENS ];
char userinfo[MAX_INFO_STRING]{ 0 };
Event* teamEv;
num = Q_min(num, maxbots->integer); num = Q_min(num, sv_maxbots->integer);
for( n = 0; n < num; n++ ) for( n = 0; n < num; n++ )
{ {
for( i = maxclients->integer; i < game.maxclients; i++ ) for( i = maxclients->integer; i < game.maxclients; i++ )
@ -107,37 +112,67 @@ void G_AddBot(unsigned int num)
e->s.clientNum = clientNum; e->s.clientNum = clientNum;
e->s.number = clientNum; e->s.number = clientNum;
Info_SetValueForKey( e->client->pers.userinfo, "name", botName ); if (saved) {
Info_SetValueForKey( e->client->pers.userinfo, "dm_playermodel", "allied_pilot" ); strncpy(userinfo, saved->pers.userinfo, ARRAY_LEN(userinfo));
Info_SetValueForKey( e->client->pers.userinfo, "dm_playergermanmodel", "german_afrika_officer" ); } else {
Info_SetValueForKey( e->client->pers.userinfo, "fov", "80" ); Info_SetValueForKey(userinfo, "name", botName);
Info_SetValueForKey( e->client->pers.userinfo, "protocol", "8" ); Info_SetValueForKey(userinfo, "dm_playermodel", "allied_pilot");
Info_SetValueForKey( e->client->pers.userinfo, "ip", "0.0.0.0" ); Info_SetValueForKey(userinfo, "dm_playergermanmodel", "german_afrika_officer");
Info_SetValueForKey( e->client->pers.userinfo, "qport", "0" ); Info_SetValueForKey(userinfo, "fov", "80");
Info_SetValueForKey( e->client->pers.userinfo, "challenge", challenge ); Info_SetValueForKey(userinfo, "protocol", "8");
Info_SetValueForKey( e->client->pers.userinfo, "snaps", "1" ); Info_SetValueForKey(userinfo, "ip", "0.0.0.0");
Info_SetValueForKey( e->client->pers.userinfo, "rate", "1" ); Info_SetValueForKey(userinfo, "qport", "0");
Info_SetValueForKey( e->client->pers.userinfo, "dmprimary", "smg" ); Info_SetValueForKey(userinfo, "challenge", challenge);
Info_SetValueForKey(userinfo, "snaps", "1");
Info_SetValueForKey(userinfo, "rate", "1");
Info_SetValueForKey(userinfo, "dmprimary", "smg");
}
G_BotConnect( clientNum ); current_bot_count++;
G_BotConnect( clientNum, userinfo );
if (saved) {
e->client->pers = saved->pers;
}
if( !firstBot ) if( !firstBot )
firstBot = e; firstBot = e;
G_BotBegin( e ); G_BotBegin( e );
e->entity->PostEvent( EV_Player_AutoJoinDMTeam, level.frametime ); if (saved) {
/*
switch (saved->team)
{
case TEAM_ALLIES:
teamEv = new Event(EV_Player_JoinDMTeam);
teamEv->AddString("allies");
break;
case TEAM_AXIS:
teamEv = new Event(EV_Player_JoinDMTeam);
teamEv->AddString("axis");
break;
default:
teamEv = new Event(EV_Player_AutoJoinDMTeam);
break;
}
*/
} else {
teamEv = new Event(EV_Player_AutoJoinDMTeam);
e->entity->PostEvent(teamEv, level.frametime);
Event *ev = new Event( EV_Player_PrimaryDMWeapon ); Event* ev = new Event(EV_Player_PrimaryDMWeapon);
ev->AddString( "smg" ); ev->AddString("smg");
e->entity->PostEvent( ev, level.frametime ); e->entity->PostEvent(ev, level.frametime);
}
} }
} }
void G_RemoveBot(unsigned int num) void G_RemoveBot(unsigned int num)
{ {
num = Q_min(atoi(gi.Argv(1)), maxbots->integer); num = Q_min(atoi(gi.Argv(1)), sv_maxbots->integer);
for( int n = 0; n < num; n++ ) for( int n = 0; n < num; n++ )
{ {
@ -145,6 +180,70 @@ void G_RemoveBot(unsigned int num)
if( e->inuse && e->client ) if( e->inuse && e->client )
{ {
G_ClientDisconnect( e ); G_ClientDisconnect( e );
current_bot_count--;
} }
} }
} }
void G_SaveBots() {
unsigned int n;
if (saved_bots) {
delete[] saved_bots;
saved_bots = NULL;
}
if (!current_bot_count) {
return;
}
saved_bots = new saved_bot_t[current_bot_count];
for (n = 0; n < current_bot_count; n++) {
gentity_t* e = &g_entities[game.maxclients - sv_maxbots->integer + n];
saved_bot_t& saved = saved_bots[n];
if (e->inuse && e->client)
{
Player* player = static_cast<Player*>(e->entity);
saved.bValid = true;
//saved.team = player->GetTeam();
saved.pers = player->client->pers;
}
}
}
void G_RestoreBots() {
unsigned int n;
if (!saved_bots) {
return;
}
for (n = 0; n < sv_numbots->integer; n++) {
saved_bot_t& saved = saved_bots[n];
G_AddBot(1, &saved);
}
delete[] saved_bots;
saved_bots = NULL;
}
void G_ResetBots() {
G_SaveBots();
current_bot_count = 0;
}
void G_SpawnBots() {
if (saved_bots) {
G_RestoreBots();
}
if (sv_numbots->integer > current_bot_count) {
G_AddBot(sv_numbots->integer - current_bot_count);
} else if (sv_numbots->integer < current_bot_count) {
G_RemoveBot(current_bot_count - sv_numbots->integer);
}
}

View file

@ -786,11 +786,10 @@ void G_ClientUserinfoChanged(gentity_t *ent, const char *u)
Q_strncpyz(client->pers.userinfo, u, sizeof(client->pers.userinfo)); Q_strncpyz(client->pers.userinfo, u, sizeof(client->pers.userinfo));
} }
void G_BotConnect(int clientNum) void G_BotConnect(int clientNum, const char* userinfo)
{ {
gclient_t *client; gclient_t *client;
gentity_t *ent; gentity_t *ent;
char userinfo[MAX_INFO_STRING];
ent = &g_entities[clientNum]; ent = &g_entities[clientNum];
@ -799,8 +798,6 @@ void G_BotConnect(int clientNum)
client = ent->client; client = ent->client;
Q_strncpyz(userinfo, client->pers.userinfo, sizeof(userinfo));
// read the session data // read the session data
memset(client, 0, sizeof(*client)); memset(client, 0, sizeof(*client));
G_InitSessionData(client, userinfo); G_InitSessionData(client, userinfo);

View file

@ -423,7 +423,7 @@ void QDECL G_Error(errorParm_t type, const char *fmt, ...);
// //
// g_client.c // g_client.c
// //
void G_BotConnect(int clientNum); void G_BotConnect(int clientNum, const char* userinfo);
const char *G_ClientConnect(int clientNum, qboolean firstTime); const char *G_ClientConnect(int clientNum, qboolean firstTime);
void G_ClientUserinfoChanged(gentity_t *ent, const char *userinfo); void G_ClientUserinfoChanged(gentity_t *ent, const char *userinfo);
void G_ClientDisconnect(gentity_t *ent); void G_ClientDisconnect(gentity_t *ent);
@ -457,7 +457,7 @@ void Svcmd_GameMem_f(void);
// g_session.c // g_session.c
// //
void G_ReadSessionData(gclient_t *client); void G_ReadSessionData(gclient_t *client);
void G_InitSessionData(gclient_t *client, char *userinfo); void G_InitSessionData(gclient_t *client, const char *userinfo);
void G_InitWorldSession(void); void G_InitWorldSession(void);
void G_WriteSessionData(void); void G_WriteSessionData(void);
@ -472,11 +472,6 @@ void Svcmd_AbortPodium_f(void);
// //
// g_bot.c // g_bot.c
// //
void G_BotBegin(gentity_t *ent);
void G_BotThink(gentity_t *ent, int msec);
gentity_t* G_GetFirstBot();
void G_AddBot(unsigned int num);
void G_RemoveBot(unsigned int num);
typedef struct mmove_s { typedef struct mmove_s {
vec3_t origin; vec3_t origin;

View file

@ -35,6 +35,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "lodthing.h" #include "lodthing.h"
#include "viewthing.h" #include "viewthing.h"
#include "playerbot.h" #include "playerbot.h"
#include "g_bot.h"
#include <tiki.h> #include <tiki.h>
#ifdef WIN32 #ifdef WIN32
@ -270,7 +271,7 @@ void G_InitGame(int levelTime, int randomSeed)
game.maxentities = game.maxclients * 8; game.maxentities = game.maxclients * 8;
} }
game.maxclients = maxclients->integer + maxbots->integer; game.maxclients = maxclients->integer + sv_maxbots->integer;
L_InitEvents(); L_InitEvents();
@ -286,6 +287,8 @@ G_SpawnEntities
void G_SpawnEntities(char *entities, int svsTime) void G_SpawnEntities(char *entities, int svsTime)
{ {
level.SpawnEntities(entities, svsTime); level.SpawnEntities(entities, svsTime);
G_SpawnBots();
} }
/* /*
@ -642,6 +645,9 @@ void G_RunFrame(int levelTime, int frameTime)
} }
} }
} }
// Add or delete bots that were added using addbot/removebot
G_SpawnBots();
} }
catch (const char *error) { catch (const char *error) {

View file

@ -83,7 +83,7 @@ G_InitSessionData
Called on a first-time connect Called on a first-time connect
================ ================
*/ */
void G_InitSessionData( gclient_t *client, char *userinfo ) void G_InitSessionData( gclient_t *client, const char *userinfo )
{ {
G_WriteClientSessionData( client ); G_WriteClientSessionData( client );
} }

View file

@ -34,6 +34,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <scriptcompiler.h> #include <scriptcompiler.h>
#include "playerbot.h" #include "playerbot.h"
#include "consoleevent.h" #include "consoleevent.h"
#include "g_bot.h"
typedef struct typedef struct
{ {
@ -630,6 +631,7 @@ qboolean G_AddBotCommand
) )
{ {
unsigned int numbots; unsigned int numbots;
unsigned int totalnumbots;
int clientNum = -1; int clientNum = -1;
if( gi.Argc() <= 1 ) if( gi.Argc() <= 1 )
@ -639,13 +641,15 @@ qboolean G_AddBotCommand
} }
numbots = atoi( gi.Argv( 1 ) ); numbots = atoi( gi.Argv( 1 ) );
if(numbots > maxbots->integer) if(numbots > sv_maxbots->integer)
{ {
gi.Printf( "addbot must be between 1-%d\n", maxbots->integer ); gi.Printf( "addbot must be between 1-%d\n", sv_maxbots->integer );
return qfalse; return qfalse;
} }
G_AddBot(numbots); totalnumbots = Q_min(numbots + sv_numbots->integer, sv_maxbots->integer);
gi.cvar_set("sv_numbots", va("%d", totalnumbots));
return qtrue; return qtrue;
} }
@ -655,6 +659,7 @@ qboolean G_RemoveBotCommand
) )
{ {
unsigned int numbots; unsigned int numbots;
unsigned int totalnumbots;
if( gi.Argc() <= 1 ) if( gi.Argc() <= 1 )
{ {
@ -662,18 +667,10 @@ qboolean G_RemoveBotCommand
return qfalse; return qfalse;
} }
numbots = Q_min(atoi(gi.Argv(1)), maxbots->integer); numbots = atoi(gi.Argv(1));
totalnumbots = Q_min(numbots, sv_numbots->integer);
for( int n = 0; n < numbots; n++ ) gi.cvar_set("sv_numbots", va("%d", totalnumbots));
{
gentity_t *e = &g_entities[ game.maxclients - 1 - n ];
if( e->inuse && e->client )
{
G_ClientDisconnect( e );
}
}
G_RemoveBot(numbots);
return qtrue; return qtrue;
} }

View file

@ -262,7 +262,8 @@ cvar_t* g_obituarylocation;
cvar_t *sv_scriptfiles; cvar_t *sv_scriptfiles;
cvar_t *maxbots; cvar_t *sv_maxbots;
cvar_t *sv_numbots;
cvar_t *g_rankedserver; cvar_t *g_rankedserver;
cvar_t *g_spectatefollow_firstperson; cvar_t *g_spectatefollow_firstperson;
@ -596,7 +597,13 @@ void CVAR_Init(void)
} }
sv_scriptfiles = gi.Cvar_Get("sv_scriptfiles", "0", 0); sv_scriptfiles = gi.Cvar_Get("sv_scriptfiles", "0", 0);
maxbots = gi.Cvar_Get("sv_maxbots", "2", 0); sv_maxbots = gi.Cvar_Get("sv_maxbots", "0", CVAR_LATCH);
sv_numbots = gi.Cvar_Get("sv_numbots", "0", CVAR_LATCH);
g_rankedserver = gi.Cvar_Get("g_rankedserver", "0", 0); g_rankedserver = gi.Cvar_Get("g_rankedserver", "0", 0);
g_spectatefollow_firstperson = gi.Cvar_Get("g_spectatefollow_firstperson", "0", 0); g_spectatefollow_firstperson = gi.Cvar_Get("g_spectatefollow_firstperson", "0", 0);
if (sv_numbots->integer > sv_maxbots->integer) {
gi.Printf("numbots overflow, setting to %d\n", sv_maxbots->integer);
gi.cvar_set("sv_numbots", sv_maxbots->string);
}
} }

View file

@ -267,7 +267,8 @@ extern cvar_t* g_obituarylocation;
extern cvar_t *sv_scriptfiles; extern cvar_t *sv_scriptfiles;
extern cvar_t *maxbots; extern cvar_t *sv_maxbots;
extern cvar_t * sv_numbots;
extern cvar_t *g_rankedserver; extern cvar_t *g_rankedserver;
extern cvar_t *g_spectatefollow_firstperson; extern cvar_t *g_spectatefollow_firstperson;