mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-30 19:52:43 +00:00
Bot amount & difficulty is now controlled by cvars
This commit is contained in:
parent
d62cb8e9d1
commit
d2172fc54b
8 changed files with 324 additions and 62 deletions
|
|
@ -2687,7 +2687,7 @@ void CL_RemovePlayer(INT32 playernum, INT32 reason)
|
|||
|
||||
demo_extradata[playernum] |= DXD_PLAYSTATE;
|
||||
|
||||
if (server && !demo.playback)
|
||||
if (server && !demo.playback && !players[playernum].bot)
|
||||
{
|
||||
INT32 node = playernode[playernum];
|
||||
//playerpernode[node] = 0; // It'd be better to remove them all at once, but ghosting happened, so continue to let CL_RemovePlayer do it one-by-one
|
||||
|
|
@ -3696,6 +3696,7 @@ static boolean SV_AddWaitingPlayers(void)
|
|||
{
|
||||
UINT8 buf[4];
|
||||
UINT8 *buf_p = buf;
|
||||
UINT8 nobotoverwrite;
|
||||
|
||||
newplayer = true;
|
||||
|
||||
|
|
@ -3713,6 +3714,21 @@ static boolean SV_AddWaitingPlayers(void)
|
|||
break;
|
||||
}
|
||||
|
||||
nobotoverwrite = newplayernum;
|
||||
|
||||
while (playeringame[nobotoverwrite]
|
||||
&& players[nobotoverwrite].bot
|
||||
&& nobotoverwrite < MAXPLAYERS)
|
||||
{
|
||||
// Only overwrite bots if there are NO other slots available.
|
||||
nobotoverwrite++;
|
||||
}
|
||||
|
||||
if (nobotoverwrite < MAXPLAYERS)
|
||||
{
|
||||
newplayernum = nobotoverwrite;
|
||||
}
|
||||
|
||||
// should never happen since we check the playernum
|
||||
// before accepting the join
|
||||
I_Assert(newplayernum < MAXPLAYERS);
|
||||
|
|
@ -3801,9 +3817,6 @@ boolean SV_SpawnServer(void)
|
|||
if (!dedicated)
|
||||
CL_ConnectToServer(false);
|
||||
else doomcom->numslots = 1;
|
||||
|
||||
// TEST
|
||||
K_AddBots(7);
|
||||
}
|
||||
|
||||
return SV_AddWaitingPlayers();
|
||||
|
|
|
|||
|
|
@ -392,6 +392,14 @@ consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedome
|
|||
static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}};
|
||||
consvar_t cv_kartvoices = {"kartvoices", "Tasteful", CV_SAVE, kartvoices_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t kartbot_cons_t[] = {
|
||||
{1, "MIN"},
|
||||
{9, "MAX"},
|
||||
{0, "Off"},
|
||||
{0, NULL}
|
||||
};
|
||||
consvar_t cv_kartbot = {"kartbot", "5", CV_NETVAR|CV_CHEAT, kartbot_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_karteliminatelast = {"karteliminatelast", "Yes", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOSHOWHELP, CV_YesNo, KartEliminateLast_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_kartusepwrlv = {"kartusepwrlv", "Yes", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ extern consvar_t cv_kartencore;
|
|||
extern consvar_t cv_kartvoterulechanges;
|
||||
extern consvar_t cv_kartspeedometer;
|
||||
extern consvar_t cv_kartvoices;
|
||||
extern consvar_t cv_kartbot;
|
||||
extern consvar_t cv_karteliminatelast;
|
||||
extern consvar_t cv_kartusepwrlv;
|
||||
|
||||
|
|
|
|||
335
src/k_bot.c
335
src/k_bot.c
|
|
@ -24,92 +24,315 @@
|
|||
#include "i_system.h"
|
||||
#include "p_maputl.h"
|
||||
#include "d_ticcmd.h"
|
||||
#include "m_random.h"
|
||||
#include "r_things.h" // numskins
|
||||
|
||||
void K_AddBots(SINT8 numbots)
|
||||
boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *p)
|
||||
{
|
||||
UINT8 newplayernum = 0;
|
||||
UINT8 difficulty = MAXBOTDIFFICULTY;
|
||||
UINT8 buf[3];
|
||||
UINT8 *buf_p = buf;
|
||||
UINT8 newplayernum = *p;
|
||||
|
||||
if (dedicated)
|
||||
newplayernum = 1;
|
||||
|
||||
while (numbots > 0)
|
||||
// search for a free playernum
|
||||
// we can't use playeringame since it is not updated here
|
||||
for (; newplayernum < MAXPLAYERS; newplayernum++)
|
||||
{
|
||||
UINT8 buf[3];
|
||||
UINT8 *buf_p = buf;
|
||||
UINT8 n;
|
||||
|
||||
numbots--;
|
||||
|
||||
// search for a free playernum
|
||||
// we can't use playeringame since it is not updated here
|
||||
for (; newplayernum < MAXPLAYERS; newplayernum++)
|
||||
{
|
||||
UINT8 n;
|
||||
|
||||
for (n = 0; n < MAXNETNODES; n++)
|
||||
if (nodetoplayer[n] == newplayernum
|
||||
|| nodetoplayer2[n] == newplayernum
|
||||
|| nodetoplayer3[n] == newplayernum
|
||||
|| nodetoplayer4[n] == newplayernum)
|
||||
break;
|
||||
|
||||
if (n == MAXNETNODES)
|
||||
for (n = 0; n < MAXNETNODES; n++)
|
||||
if (nodetoplayer[n] == newplayernum
|
||||
|| nodetoplayer2[n] == newplayernum
|
||||
|| nodetoplayer3[n] == newplayernum
|
||||
|| nodetoplayer4[n] == newplayernum)
|
||||
break;
|
||||
|
||||
if (n == MAXNETNODES)
|
||||
break;
|
||||
}
|
||||
|
||||
while (playeringame[newplayernum]
|
||||
&& players[newplayernum].bot
|
||||
&& newplayernum < MAXPLAYERS)
|
||||
{
|
||||
newplayernum++;
|
||||
}
|
||||
|
||||
if (newplayernum >= MAXPLAYERS)
|
||||
{
|
||||
*p = newplayernum;
|
||||
return false;
|
||||
}
|
||||
|
||||
WRITEUINT8(buf_p, newplayernum);
|
||||
|
||||
if (skin > numskins)
|
||||
{
|
||||
skin = numskins;
|
||||
}
|
||||
|
||||
WRITEUINT8(buf_p, skin);
|
||||
|
||||
if (difficulty < 1)
|
||||
{
|
||||
difficulty = 1;
|
||||
}
|
||||
else if (difficulty > MAXBOTDIFFICULTY)
|
||||
{
|
||||
difficulty = MAXBOTDIFFICULTY;
|
||||
}
|
||||
|
||||
WRITEUINT8(buf_p, difficulty);
|
||||
|
||||
SendNetXCmd(XD_ADDBOT, buf, buf_p - buf);
|
||||
|
||||
DEBFILE(va("Server added bot %d\n", newplayernum));
|
||||
// use the next free slot (we can't put playeringame[newplayernum] = true here)
|
||||
newplayernum++;
|
||||
|
||||
*p = newplayernum;
|
||||
return true;
|
||||
}
|
||||
|
||||
void K_UpdateMatchRaceBots(void)
|
||||
{
|
||||
const UINT8 difficulty = cv_kartbot.value;
|
||||
UINT8 pmax = min((dedicated ? MAXPLAYERS-1 : MAXPLAYERS), cv_maxplayers.value);
|
||||
UINT8 numplayers = 0;
|
||||
UINT8 numbots = 0;
|
||||
UINT8 numwaiting = 0;
|
||||
SINT8 wantedbots = 0;
|
||||
UINT8 i;
|
||||
|
||||
if (difficulty != 0)
|
||||
{
|
||||
if (cv_ingamecap.value > 0)
|
||||
{
|
||||
pmax = min(pmax, cv_ingamecap.value);
|
||||
}
|
||||
|
||||
WRITEUINT8(buf_p, newplayernum);
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
if (!players[i].spectator)
|
||||
{
|
||||
if (players[i].bot)
|
||||
{
|
||||
numbots++;
|
||||
|
||||
// test skins
|
||||
if (numbots == 6)
|
||||
{
|
||||
difficulty = MAXBOTDIFFICULTY;
|
||||
WRITEUINT8(buf_p, 1);
|
||||
// While we're here, we should update bot difficulty to the proper value.
|
||||
players[i].botvars.difficulty = difficulty;
|
||||
}
|
||||
else
|
||||
{
|
||||
numplayers++;
|
||||
}
|
||||
}
|
||||
else if (players[i].pflags & PF_WANTSTOJOIN)
|
||||
{
|
||||
numwaiting++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (numbots == 5)
|
||||
|
||||
wantedbots = pmax - numplayers - numwaiting;
|
||||
|
||||
if (wantedbots < 0)
|
||||
{
|
||||
difficulty = MAXBOTDIFFICULTY;
|
||||
WRITEUINT8(buf_p, 0);
|
||||
wantedbots = 0;
|
||||
}
|
||||
else if (numbots == 4)
|
||||
}
|
||||
else
|
||||
{
|
||||
wantedbots = 0;
|
||||
}
|
||||
|
||||
if (numbots < wantedbots)
|
||||
{
|
||||
// We require MORE bots!
|
||||
UINT8 newplayernum = 0;
|
||||
|
||||
if (dedicated)
|
||||
{
|
||||
difficulty = MAXBOTDIFFICULTY-1;
|
||||
WRITEUINT8(buf_p, 2);
|
||||
newplayernum = 1;
|
||||
}
|
||||
else if (numbots == 3)
|
||||
|
||||
while (numbots < wantedbots)
|
||||
{
|
||||
difficulty = MAXBOTDIFFICULTY-2;
|
||||
WRITEUINT8(buf_p, 3);
|
||||
if (!K_AddBot(M_RandomKey(numskins), difficulty, &newplayernum))
|
||||
{
|
||||
// Not enough player slots to add the bot, break the loop.
|
||||
break;
|
||||
}
|
||||
|
||||
numbots++;
|
||||
}
|
||||
else if (numbots == 2)
|
||||
}
|
||||
else if (numbots > wantedbots)
|
||||
{
|
||||
UINT8 buf[2];
|
||||
|
||||
i = 0;
|
||||
|
||||
while (numbots > wantedbots && i < MAXPLAYERS)
|
||||
{
|
||||
difficulty = MAXBOTDIFFICULTY-4;
|
||||
WRITEUINT8(buf_p, 5);
|
||||
if (playeringame[i] && players[i].bot)
|
||||
{
|
||||
buf[0] = i;
|
||||
buf[1] = KR_LEAVE;
|
||||
SendNetXCmd(XD_REMOVEPLAYER, &buf, 2);
|
||||
|
||||
CONS_Printf("Removed bot %s\n", player_names[i]);
|
||||
numbots--;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
else if (numbots == 1)
|
||||
}
|
||||
|
||||
// We should have enough bots now :)
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This is mostly just pesudo code right now...
|
||||
void K_InitGrandPrixBots(void)
|
||||
{
|
||||
const UINT8 defaultbotskin = 9; // eggrobo
|
||||
|
||||
// startingdifficulty: Easy = 3, Normal = 6, Hard = 9
|
||||
const UINT8 startingdifficulty = min(MAXBOTDIFFICULTY, (cv_kartspeed.value + 1) * 3);
|
||||
UINT8 difficultylevels[MAXPLAYERS];
|
||||
|
||||
UINT8 playercount = 8;
|
||||
UINT8 wantedbots = 0;
|
||||
|
||||
UINT8 numplayers = 0;
|
||||
UINT8 competitors[4];
|
||||
|
||||
boolean skinusable[MAXSKINS];
|
||||
UINT8 botskinlist[MAXPLAYERS];
|
||||
UINT8 botskinlistpos = 0;
|
||||
|
||||
UINT8 i;
|
||||
|
||||
memset(difficultylevels, MAXBOTDIFFICULTY, sizeof (difficultylevels));
|
||||
memset(competitors, MAXPLAYERS, sizeof (competitors));
|
||||
memset(botskinlist, defaultbotskin, sizeof (botskinlist));
|
||||
|
||||
// init usable bot skins list
|
||||
for (i = 0; i < MAXSKINS; i++)
|
||||
{
|
||||
if (i < numskins)
|
||||
{
|
||||
difficulty = MAXBOTDIFFICULTY-4;
|
||||
WRITEUINT8(buf_p, 9);
|
||||
skinusable[i] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
difficulty = MAXBOTDIFFICULTY-2;
|
||||
WRITEUINT8(buf_p, 10);
|
||||
skinusable[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
WRITEUINT8(buf_p, difficulty);
|
||||
// init difficulty levels list
|
||||
//if (!mastermodebots) {
|
||||
difficultylevels[MAXPLAYERS] = {
|
||||
max(1, startingdifficulty),
|
||||
max(1, startingdifficulty-1),
|
||||
max(1, startingdifficulty-2),
|
||||
max(1, startingdifficulty-3),
|
||||
max(1, startingdifficulty-3),
|
||||
max(1, startingdifficulty-4),
|
||||
max(1, startingdifficulty-4),
|
||||
max(1, startingdifficulty-4),
|
||||
max(1, startingdifficulty-5),
|
||||
max(1, startingdifficulty-5),
|
||||
max(1, startingdifficulty-6),
|
||||
max(1, startingdifficulty-6),
|
||||
max(1, startingdifficulty-7),
|
||||
max(1, startingdifficulty-7),
|
||||
max(1, startingdifficulty-8),
|
||||
max(1, startingdifficulty-8),
|
||||
};
|
||||
|
||||
SendNetXCmd(XD_ADDBOT, buf, buf_p - buf);
|
||||
|
||||
if (difficulty > 0)
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (numplayers < MAXSPLITSCREENPLAYERS)
|
||||
{
|
||||
difficulty--;
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
{
|
||||
competitors[numplayers] = i;
|
||||
numplayers++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
players[i].spectator = true; // force spectate for all other players, if they happen to exist?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBFILE(va("Server added bot %d\n", newplayernum));
|
||||
// use the next free slot (we can't put playeringame[newplayernum] = true here)
|
||||
newplayernum++;
|
||||
if (numplayers > 2)
|
||||
{
|
||||
// Add 3 bots per player beyond 2P
|
||||
playercount += (numplayers-2) * 3;
|
||||
}
|
||||
|
||||
wantedbots = playercount - numplayers;
|
||||
|
||||
// Create rival list
|
||||
|
||||
// TODO: Use player skin's set rivals
|
||||
// Starting with P1's rival1, P2's rival1, P3's rival1, P4's rival1,
|
||||
// then P1's rival2, P2's rival2, etc etc etc etc.......
|
||||
// then skip over any duplicates.
|
||||
|
||||
// Pad the remaining list with random skins if we need to
|
||||
if (botskinlistpos < wantedbots)
|
||||
{
|
||||
for (i = botskinlistpos; i < wantedbots; i++)
|
||||
{
|
||||
UINT8 val = M_RandomKey(numskins);
|
||||
UINT8 loops = 0;
|
||||
|
||||
while (!skinusable[val])
|
||||
{
|
||||
if (loops >= numskins)
|
||||
{
|
||||
// no more skins
|
||||
break;
|
||||
}
|
||||
|
||||
val++;
|
||||
|
||||
if (val >= numskins)
|
||||
{
|
||||
val = 0;
|
||||
}
|
||||
|
||||
loops++;
|
||||
}
|
||||
|
||||
if (loops >= numskins)
|
||||
{
|
||||
// leave the rest of the table as the default skin
|
||||
break;
|
||||
}
|
||||
|
||||
botskinlist[i] = val;
|
||||
skinusable[val] = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < wantedbots; i++)
|
||||
{
|
||||
if (!K_AddBot(botskinlist[i], difficultylevels[i], &newplayernum))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
boolean K_PlayerUsesBotMovement(player_t *player)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ typedef struct botprediction_s {
|
|||
angle_t dir;
|
||||
} botprediction_t;
|
||||
|
||||
void K_AddBots(SINT8 numbots);
|
||||
boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *newplayernum);
|
||||
void K_UpdateMatchRaceBots(void);
|
||||
boolean K_PlayerUsesBotMovement(player_t *player);
|
||||
boolean K_BotCanTakeCut(player_t *player);
|
||||
fixed_t K_BotRubberband(player_t *player);
|
||||
|
|
|
|||
|
|
@ -623,6 +623,7 @@ void K_RegisterKartStuff(void)
|
|||
CV_RegisterVar(&cv_kartvoterulechanges);
|
||||
CV_RegisterVar(&cv_kartspeedometer);
|
||||
CV_RegisterVar(&cv_kartvoices);
|
||||
CV_RegisterVar(&cv_kartbot);
|
||||
CV_RegisterVar(&cv_karteliminatelast);
|
||||
CV_RegisterVar(&cv_kartusepwrlv);
|
||||
CV_RegisterVar(&cv_votetime);
|
||||
|
|
|
|||
13
src/p_mobj.c
13
src/p_mobj.c
|
|
@ -11762,9 +11762,20 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
}
|
||||
|
||||
// spawn as spectator determination
|
||||
if (multiplayer && demo.playback); // Don't mess with spectator values since the demo setup handles them already.
|
||||
if (multiplayer && demo.playback)
|
||||
{
|
||||
; // Don't mess with spectator values since the demo setup handles them already.
|
||||
}
|
||||
else if (!G_GametypeHasSpectators())
|
||||
{
|
||||
// We don't have spectators
|
||||
p->spectator = false;
|
||||
}
|
||||
else if (p->bot)
|
||||
{
|
||||
// No point in a spectating bot!
|
||||
p->spectator = false;
|
||||
}
|
||||
else if (netgame && p->jointime <= 1 && pcount)
|
||||
{
|
||||
p->spectator = true;
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@
|
|||
#include "k_battle.h" // K_SpawnBattleCapsules
|
||||
#include "k_pwrlv.h"
|
||||
#include "k_waypoint.h"
|
||||
#include "k_bot.h"
|
||||
|
||||
//
|
||||
// Map MD5, calculated on level load.
|
||||
|
|
@ -2425,6 +2426,9 @@ static void P_LevelInitStuff(void)
|
|||
|
||||
memset(&battleovertime, 0, sizeof(struct battleovertime));
|
||||
speedscramble = encorescramble = -1;
|
||||
|
||||
//if (!grandprix)
|
||||
K_UpdateMatchRaceBots();
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue