mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-27 20:41:46 +00:00
Merge branch 'training-mode' into 'master'
Add bot styles & bot spawn ACS function Closes #564 See merge request KartKrew/Kart!1288
This commit is contained in:
commit
8b2b3aaee8
12 changed files with 330 additions and 121 deletions
|
|
@ -41,6 +41,7 @@
|
||||||
#include "../r_skins.h"
|
#include "../r_skins.h"
|
||||||
#include "../k_battle.h"
|
#include "../k_battle.h"
|
||||||
#include "../k_podium.h"
|
#include "../k_podium.h"
|
||||||
|
#include "../k_bot.h"
|
||||||
#include "../z_zone.h"
|
#include "../z_zone.h"
|
||||||
|
|
||||||
#include "call-funcs.hpp"
|
#include "call-funcs.hpp"
|
||||||
|
|
@ -1710,6 +1711,52 @@ bool CallFunc_MapWarp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Wor
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
bool CallFunc_AddBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
|
Inserts a bot, if there's room for them.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
bool CallFunc_AddBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
{
|
||||||
|
ACSVM::MapScope *map = NULL;
|
||||||
|
|
||||||
|
ACSVM::String *skinStr = nullptr;
|
||||||
|
INT32 skin = -1;
|
||||||
|
|
||||||
|
UINT8 difficulty = 0;
|
||||||
|
botStyle_e style = BOT_STYLE_NORMAL;
|
||||||
|
|
||||||
|
UINT8 newplayernum = 0;
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
(void)argC;
|
||||||
|
|
||||||
|
map = thread->scopeMap;
|
||||||
|
|
||||||
|
skinStr = map->getString(argV[0]);
|
||||||
|
if (skinStr->len != 0)
|
||||||
|
{
|
||||||
|
skin = R_SkinAvailable(skinStr->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skin == -1)
|
||||||
|
{
|
||||||
|
skin = R_BotDefaultSkin();
|
||||||
|
}
|
||||||
|
|
||||||
|
difficulty = std::clamp(static_cast<int>(argV[1]), 1, MAXBOTDIFFICULTY);
|
||||||
|
|
||||||
|
style = static_cast<botStyle_e>(argV[2]);
|
||||||
|
if (style < BOT_STYLE_NORMAL || style >= BOT_STYLE__MAX)
|
||||||
|
{
|
||||||
|
style = BOT_STYLE_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
success = K_AddBot(skin, difficulty, style, &newplayernum);
|
||||||
|
thread->dataStk.push(success ? newplayernum : -1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
bool CallFunc_Get/SetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
bool CallFunc_Get/SetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ bool CallFunc_PodiumFinish(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM
|
||||||
bool CallFunc_SetLineRenderStyle(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
bool CallFunc_SetLineRenderStyle(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
|
||||||
bool CallFunc_MapWarp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
bool CallFunc_MapWarp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
bool CallFunc_AddBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
|
||||||
bool CallFunc_GetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
bool CallFunc_GetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
bool CallFunc_SetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
bool CallFunc_SetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,7 @@ Environment::Environment()
|
||||||
addFuncDataACS0( 502, addCallFunc(CallFunc_PodiumFinish));
|
addFuncDataACS0( 502, addCallFunc(CallFunc_PodiumFinish));
|
||||||
addFuncDataACS0( 503, addCallFunc(CallFunc_SetLineRenderStyle));
|
addFuncDataACS0( 503, addCallFunc(CallFunc_SetLineRenderStyle));
|
||||||
addFuncDataACS0( 504, addCallFunc(CallFunc_MapWarp));
|
addFuncDataACS0( 504, addCallFunc(CallFunc_MapWarp));
|
||||||
|
addFuncDataACS0( 505, addCallFunc(CallFunc_AddBot));
|
||||||
}
|
}
|
||||||
|
|
||||||
ACSVM::Thread *Environment::allocThread()
|
ACSVM::Thread *Environment::allocThread()
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
|
|
||||||
#include "thread.hpp"
|
#include "thread.hpp"
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "../doomtype.h"
|
#include "../doomtype.h"
|
||||||
#include "../doomdef.h"
|
#include "../doomdef.h"
|
||||||
#include "../doomstat.h"
|
#include "../doomstat.h"
|
||||||
|
|
@ -26,7 +25,6 @@ extern "C" {
|
||||||
#include "../r_defs.h"
|
#include "../r_defs.h"
|
||||||
#include "../r_state.h"
|
#include "../r_state.h"
|
||||||
#include "../p_polyobj.h"
|
#include "../p_polyobj.h"
|
||||||
}
|
|
||||||
|
|
||||||
using namespace srb2::acs;
|
using namespace srb2::acs;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "acsvm.hpp"
|
#include "acsvm.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
#include "../doomtype.h"
|
#include "../doomtype.h"
|
||||||
#include "../doomdef.h"
|
#include "../doomdef.h"
|
||||||
#include "../doomstat.h"
|
#include "../doomstat.h"
|
||||||
|
|
@ -23,7 +24,7 @@
|
||||||
#include "../r_defs.h"
|
#include "../r_defs.h"
|
||||||
#include "../r_state.h"
|
#include "../r_state.h"
|
||||||
#include "../p_spec.h"
|
#include "../p_spec.h"
|
||||||
|
}
|
||||||
|
|
||||||
namespace srb2::acs {
|
namespace srb2::acs {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4010,6 +4010,7 @@ static void Got_AddBot(UINT8 **p, INT32 playernum)
|
||||||
INT16 newplayernum;
|
INT16 newplayernum;
|
||||||
UINT8 skinnum = 0;
|
UINT8 skinnum = 0;
|
||||||
UINT8 difficulty = DIFFICULTBOT;
|
UINT8 difficulty = DIFFICULTBOT;
|
||||||
|
botStyle_e style = BOT_STYLE_NORMAL;
|
||||||
|
|
||||||
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
|
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
|
||||||
{
|
{
|
||||||
|
|
@ -4025,41 +4026,9 @@ static void Got_AddBot(UINT8 **p, INT32 playernum)
|
||||||
newplayernum = READUINT8(*p);
|
newplayernum = READUINT8(*p);
|
||||||
skinnum = READUINT8(*p);
|
skinnum = READUINT8(*p);
|
||||||
difficulty = READUINT8(*p);
|
difficulty = READUINT8(*p);
|
||||||
|
style = READUINT8(*p);
|
||||||
|
|
||||||
CONS_Debug(DBG_NETPLAY, "addbot: %d\n", newplayernum);
|
K_SetBot(newplayernum, skinnum, difficulty, style);
|
||||||
|
|
||||||
// Clear player before joining, lest some things get set incorrectly
|
|
||||||
CL_ClearPlayer(newplayernum);
|
|
||||||
G_DestroyParty(newplayernum);
|
|
||||||
|
|
||||||
playeringame[newplayernum] = true;
|
|
||||||
G_AddPlayer(newplayernum);
|
|
||||||
if (newplayernum+1 > doomcom->numslots)
|
|
||||||
doomcom->numslots = (INT16)(newplayernum+1);
|
|
||||||
|
|
||||||
playernode[newplayernum] = servernode;
|
|
||||||
|
|
||||||
// this will permit unlocks
|
|
||||||
memcpy(&players[newplayernum].availabilities, R_GetSkinAvailabilities(false, true), MAXAVAILABILITY*sizeof(UINT8));
|
|
||||||
|
|
||||||
players[newplayernum].splitscreenindex = 0;
|
|
||||||
players[newplayernum].bot = true;
|
|
||||||
players[newplayernum].botvars.difficulty = difficulty;
|
|
||||||
players[newplayernum].lives = 9;
|
|
||||||
|
|
||||||
players[newplayernum].skincolor = skins[skinnum].prefcolor;
|
|
||||||
sprintf(player_names[newplayernum], "%s", skins[skinnum].realname);
|
|
||||||
SetPlayerSkinByNum(newplayernum, skinnum);
|
|
||||||
|
|
||||||
playerconsole[newplayernum] = newplayernum;
|
|
||||||
G_BuildLocalSplitscreenParty(newplayernum);
|
|
||||||
|
|
||||||
if (netgame)
|
|
||||||
{
|
|
||||||
HU_AddChatText(va("\x82*Bot %d has been added to the game", newplayernum+1), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
LUA_HookInt(newplayernum, HOOK(PlayerJoin));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean SV_AddWaitingPlayers(SINT8 node, UINT8 *availabilities,
|
static boolean SV_AddWaitingPlayers(SINT8 node, UINT8 *availabilities,
|
||||||
|
|
|
||||||
|
|
@ -313,9 +313,20 @@ struct respawnvars_t
|
||||||
boolean init;
|
boolean init;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
BOT_STYLE_NORMAL,
|
||||||
|
BOT_STYLE_STAY,
|
||||||
|
//BOT_STYLE_CHASE,
|
||||||
|
//BOT_STYLE_ESCAPE,
|
||||||
|
BOT_STYLE__MAX
|
||||||
|
} botStyle_e;
|
||||||
|
|
||||||
// player_t struct for all bot variables
|
// player_t struct for all bot variables
|
||||||
struct botvars_t
|
struct botvars_t
|
||||||
{
|
{
|
||||||
|
botStyle_e style; // Training mode-style CPU mode
|
||||||
|
|
||||||
UINT8 difficulty; // Bot's difficulty setting
|
UINT8 difficulty; // Bot's difficulty setting
|
||||||
UINT8 diffincrease; // In GP: bot difficulty will increase this much next round
|
UINT8 diffincrease; // In GP: bot difficulty will increase this much next round
|
||||||
boolean rival; // If true, they're the GP rival
|
boolean rival; // If true, they're the GP rival
|
||||||
|
|
|
||||||
268
src/k_bot.c
268
src/k_bot.c
|
|
@ -31,20 +31,102 @@
|
||||||
#include "k_podium.h"
|
#include "k_podium.h"
|
||||||
#include "k_respawn.h"
|
#include "k_respawn.h"
|
||||||
#include "m_easing.h"
|
#include "m_easing.h"
|
||||||
|
#include "d_clisrv.h"
|
||||||
|
#include "g_party.h"
|
||||||
|
#include "k_grandprix.h" // K_CanChangeRules
|
||||||
|
#include "hu_stuff.h" // HU_AddChatText
|
||||||
|
#include "discord.h" // DRPC_UpdatePresence
|
||||||
|
#include "i_net.h" // doomcom
|
||||||
|
|
||||||
#ifdef DEVELOP
|
#ifdef DEVELOP
|
||||||
consvar_t cv_botcontrol = CVAR_INIT ("botcontrol", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
|
consvar_t cv_botcontrol = CVAR_INIT ("botcontrol", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *p)
|
void K_SetBot(UINT8 playerNum, UINT8 skinnum, UINT8 difficulty, botStyle_e style)
|
||||||
|
|
||||||
See header file for description.
|
See header file for description.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *p)
|
void K_SetBot(UINT8 newplayernum, UINT8 skinnum, UINT8 difficulty, botStyle_e style)
|
||||||
|
{
|
||||||
|
CONS_Debug(DBG_NETPLAY, "addbot: %d\n", newplayernum);
|
||||||
|
|
||||||
|
// Clear player before joining, lest some things get set incorrectly
|
||||||
|
CL_ClearPlayer(newplayernum);
|
||||||
|
G_DestroyParty(newplayernum);
|
||||||
|
|
||||||
|
playeringame[newplayernum] = true;
|
||||||
|
G_AddPlayer(newplayernum);
|
||||||
|
if (newplayernum+1 > doomcom->numslots)
|
||||||
|
doomcom->numslots = (INT16)(newplayernum+1);
|
||||||
|
|
||||||
|
playernode[newplayernum] = servernode;
|
||||||
|
|
||||||
|
// this will permit unlocks
|
||||||
|
memcpy(&players[newplayernum].availabilities, R_GetSkinAvailabilities(false, true), MAXAVAILABILITY*sizeof(UINT8));
|
||||||
|
|
||||||
|
players[newplayernum].splitscreenindex = 0;
|
||||||
|
players[newplayernum].bot = true;
|
||||||
|
players[newplayernum].botvars.difficulty = difficulty;
|
||||||
|
players[newplayernum].botvars.style = style;
|
||||||
|
players[newplayernum].lives = 9;
|
||||||
|
|
||||||
|
players[newplayernum].skincolor = skins[skinnum].prefcolor;
|
||||||
|
sprintf(player_names[newplayernum], "%s", skins[skinnum].realname);
|
||||||
|
SetPlayerSkinByNum(newplayernum, skinnum);
|
||||||
|
|
||||||
|
playerconsole[newplayernum] = newplayernum;
|
||||||
|
G_BuildLocalSplitscreenParty(newplayernum);
|
||||||
|
|
||||||
|
if (netgame)
|
||||||
|
{
|
||||||
|
HU_AddChatText(va("\x82*Bot %d has been added to the game", newplayernum+1), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
LUA_HookInt(newplayernum, HOOK(PlayerJoin));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p)
|
||||||
|
|
||||||
|
See header file for description.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p)
|
||||||
|
{
|
||||||
|
UINT8 newplayernum = *p;
|
||||||
|
|
||||||
|
for (; newplayernum < MAXPLAYERS; newplayernum++)
|
||||||
|
{
|
||||||
|
if (playeringame[newplayernum] == false)
|
||||||
|
{
|
||||||
|
// free player slot
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newplayernum >= MAXPLAYERS)
|
||||||
|
{
|
||||||
|
// nothing is free
|
||||||
|
*p = MAXPLAYERS;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
K_SetBot(newplayernum, skin, difficulty, style);
|
||||||
|
DEBFILE(va("Everyone added bot %d\n", newplayernum));
|
||||||
|
|
||||||
|
// use the next free slot
|
||||||
|
*p = newplayernum+1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
boolean K_AddBotFromServer(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p)
|
||||||
|
|
||||||
|
See header file for description.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
boolean K_AddBotFromServer(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p)
|
||||||
{
|
{
|
||||||
UINT8 buf[3];
|
|
||||||
UINT8 *buf_p = buf;
|
|
||||||
UINT8 newplayernum = *p;
|
UINT8 newplayernum = *p;
|
||||||
|
|
||||||
// search for a free playernum
|
// search for a free playernum
|
||||||
|
|
@ -54,56 +136,66 @@ boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *p)
|
||||||
UINT8 n;
|
UINT8 n;
|
||||||
|
|
||||||
for (n = 0; n < MAXNETNODES; n++)
|
for (n = 0; n < MAXNETNODES; n++)
|
||||||
|
{
|
||||||
if (nodetoplayer[n] == newplayernum
|
if (nodetoplayer[n] == newplayernum
|
||||||
|| nodetoplayer2[n] == newplayernum
|
|| nodetoplayer2[n] == newplayernum
|
||||||
|| nodetoplayer3[n] == newplayernum
|
|| nodetoplayer3[n] == newplayernum
|
||||||
|| nodetoplayer4[n] == newplayernum)
|
|| nodetoplayer4[n] == newplayernum)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (n == MAXNETNODES)
|
if (n == MAXNETNODES)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (playeringame[newplayernum]
|
for (; newplayernum < MAXPLAYERS; newplayernum++)
|
||||||
&& players[newplayernum].bot
|
|
||||||
&& newplayernum < MAXPLAYERS)
|
|
||||||
{
|
{
|
||||||
newplayernum++;
|
if (playeringame[newplayernum] == false)
|
||||||
|
{
|
||||||
|
// free player slot
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newplayernum >= MAXPLAYERS)
|
if (newplayernum >= MAXPLAYERS)
|
||||||
{
|
{
|
||||||
*p = newplayernum;
|
// nothing is free
|
||||||
|
*p = MAXPLAYERS;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITEUINT8(buf_p, newplayernum);
|
if (server)
|
||||||
|
|
||||||
if (skin > numskins)
|
|
||||||
{
|
{
|
||||||
skin = numskins;
|
UINT8 buf[4];
|
||||||
|
UINT8 *buf_p = buf;
|
||||||
|
|
||||||
|
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);
|
||||||
|
WRITEUINT8(buf_p, style);
|
||||||
|
|
||||||
|
SendNetXCmd(XD_ADDBOT, buf, buf_p - buf);
|
||||||
|
DEBFILE(va("Server added bot %d\n", newplayernum));
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
// use the next free slot (we can't put playeringame[newplayernum] = true here)
|
||||||
newplayernum++;
|
*p = newplayernum+1;
|
||||||
|
|
||||||
*p = newplayernum;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -125,11 +217,6 @@ void K_UpdateMatchRaceBots(void)
|
||||||
UINT8 grabskins[MAXSKINS+1];
|
UINT8 grabskins[MAXSKINS+1];
|
||||||
UINT8 i;
|
UINT8 i;
|
||||||
|
|
||||||
if (!server)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init usable bot skins list
|
// Init usable bot skins list
|
||||||
for (i = 0; i < numskins; i++)
|
for (i = 0; i < numskins; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -156,6 +243,9 @@ void K_UpdateMatchRaceBots(void)
|
||||||
|
|
||||||
// While we're here, we should update bot difficulty to the proper value.
|
// While we're here, we should update bot difficulty to the proper value.
|
||||||
players[i].botvars.difficulty = difficulty;
|
players[i].botvars.difficulty = difficulty;
|
||||||
|
|
||||||
|
// Enforce normal style for Match Race
|
||||||
|
players[i].botvars.style = BOT_STYLE_NORMAL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -169,12 +259,16 @@ void K_UpdateMatchRaceBots(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (difficulty == 0 || !(gametyperules & GTR_BOTS))
|
if (K_CanChangeRules(true) == false
|
||||||
|
|| (gametyperules & GTR_BOTS) == 0
|
||||||
|
|| difficulty == 0)
|
||||||
{
|
{
|
||||||
|
// Remove bots if there are any.
|
||||||
wantedbots = 0;
|
wantedbots = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Add bots to fill up MAXPLAYERS
|
||||||
wantedbots = pmax - numplayers - numwaiting;
|
wantedbots = pmax - numplayers - numwaiting;
|
||||||
|
|
||||||
if (wantedbots < 0)
|
if (wantedbots < 0)
|
||||||
|
|
@ -197,11 +291,15 @@ void K_UpdateMatchRaceBots(void)
|
||||||
for (i = 0; i < usableskins; i++)
|
for (i = 0; i < usableskins; i++)
|
||||||
{
|
{
|
||||||
if (!(grabskins[i] == MAXSKINS || !R_SkinUsable(-1, grabskins[i], true)))
|
if (!(grabskins[i] == MAXSKINS || !R_SkinUsable(-1, grabskins[i], true)))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
while (usableskins > i && (grabskins[usableskins] == MAXSKINS || !R_SkinUsable(-1, grabskins[usableskins], true)))
|
while (usableskins > i && (grabskins[usableskins] == MAXSKINS || !R_SkinUsable(-1, grabskins[usableskins], true)))
|
||||||
{
|
{
|
||||||
usableskins--;
|
usableskins--;
|
||||||
}
|
}
|
||||||
|
|
||||||
grabskins[i] = grabskins[usableskins];
|
grabskins[i] = grabskins[usableskins];
|
||||||
grabskins[usableskins] = MAXSKINS;
|
grabskins[usableskins] = MAXSKINS;
|
||||||
}
|
}
|
||||||
|
|
@ -212,12 +310,12 @@ void K_UpdateMatchRaceBots(void)
|
||||||
|
|
||||||
if (usableskins > 0)
|
if (usableskins > 0)
|
||||||
{
|
{
|
||||||
UINT8 index = M_RandomKey(usableskins);
|
UINT8 index = P_RandomKey(PR_BOTS, usableskins);
|
||||||
skinnum = grabskins[index];
|
skinnum = grabskins[index];
|
||||||
grabskins[index] = grabskins[--usableskins];
|
grabskins[index] = grabskins[--usableskins];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!K_AddBot(skinnum, difficulty, &newplayernum))
|
if (!K_AddBot(skinnum, difficulty, BOT_STYLE_NORMAL, &newplayernum))
|
||||||
{
|
{
|
||||||
// Not enough player slots to add the bot, break the loop.
|
// Not enough player slots to add the bot, break the loop.
|
||||||
break;
|
break;
|
||||||
|
|
@ -228,26 +326,25 @@ void K_UpdateMatchRaceBots(void)
|
||||||
}
|
}
|
||||||
else if (numbots > wantedbots)
|
else if (numbots > wantedbots)
|
||||||
{
|
{
|
||||||
UINT8 buf[2];
|
|
||||||
|
|
||||||
i = MAXPLAYERS;
|
i = MAXPLAYERS;
|
||||||
|
|
||||||
while (numbots > wantedbots && i > 0)
|
while (numbots > wantedbots && i > 0)
|
||||||
{
|
{
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
if (playeringame[i] && players[i].bot)
|
if (playeringame[i] && players[i].bot)
|
||||||
{
|
{
|
||||||
buf[0] = i;
|
CL_RemovePlayer(i, KR_LEAVE);
|
||||||
buf[1] = KR_LEAVE;
|
|
||||||
SendNetXCmd(XD_REMOVEPLAYER, &buf, 2);
|
|
||||||
|
|
||||||
numbots--;
|
numbots--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We should have enough bots now :)
|
// We should have enough bots now :)
|
||||||
|
|
||||||
|
#ifdef HAVE_DISCORDRPC
|
||||||
|
// Player count change was possible, so update presence
|
||||||
|
DRPC_UpdatePresence();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
|
|
@ -1473,11 +1570,11 @@ static void K_BuildBotPodiumTiccmd(player_t *player, ticcmd_t *cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd)
|
||||||
|
|
||||||
See header file for description.
|
Build ticcmd for bots with a style of BOT_STYLE_NORMAL
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd)
|
||||||
{
|
{
|
||||||
precise_t t = 0;
|
precise_t t = 0;
|
||||||
botprediction_t *predict = NULL;
|
botprediction_t *predict = NULL;
|
||||||
|
|
@ -1487,29 +1584,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
||||||
INT32 turnamt = 0;
|
INT32 turnamt = 0;
|
||||||
const line_t *botController = player->botvars.controller != UINT16_MAX ? &lines[player->botvars.controller] : NULL;
|
const line_t *botController = player->botvars.controller != UINT16_MAX ? &lines[player->botvars.controller] : NULL;
|
||||||
|
|
||||||
// Remove any existing controls
|
|
||||||
memset(cmd, 0, sizeof(ticcmd_t));
|
|
||||||
|
|
||||||
if (player->mo == NULL
|
|
||||||
|| player->spectator == true
|
|
||||||
|| G_GamestateUsesLevel() == false)
|
|
||||||
{
|
|
||||||
// Not in the level.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Complete override of all ticcmd functionality
|
|
||||||
if (LUA_HookTiccmd(player, cmd, HOOK(BotTiccmd)) == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (K_PodiumSequence() == true)
|
|
||||||
{
|
|
||||||
K_BuildBotPodiumTiccmd(player, cmd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(gametyperules & GTR_BOTS) // No bot behaviors
|
if (!(gametyperules & GTR_BOTS) // No bot behaviors
|
||||||
|| K_GetNumWaypoints() == 0 // No waypoints
|
|| K_GetNumWaypoints() == 0 // No waypoints
|
||||||
|| leveltime <= introtime // During intro camera
|
|| leveltime <= introtime // During intro camera
|
||||||
|
|
@ -1762,6 +1836,54 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
||||||
|
|
||||||
|
See header file for description.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
||||||
|
{
|
||||||
|
// Remove any existing controls
|
||||||
|
memset(cmd, 0, sizeof(ticcmd_t));
|
||||||
|
|
||||||
|
if (player->mo == NULL
|
||||||
|
|| player->spectator == true
|
||||||
|
|| G_GamestateUsesLevel() == false)
|
||||||
|
{
|
||||||
|
// Not in the level.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complete override of all ticcmd functionality.
|
||||||
|
// May add more hooks to individual pieces of bot ticcmd,
|
||||||
|
// but this should always be here so anyone can roll
|
||||||
|
// their own :)
|
||||||
|
if (LUA_HookTiccmd(player, cmd, HOOK(BotTiccmd)) == true)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (K_PodiumSequence() == true)
|
||||||
|
{
|
||||||
|
K_BuildBotPodiumTiccmd(player, cmd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (player->botvars.style)
|
||||||
|
{
|
||||||
|
case BOT_STYLE_STAY:
|
||||||
|
{
|
||||||
|
// Hey, this one's pretty easy :P
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
K_BuildBotTiccmdNormal(player, cmd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
void K_UpdateBotGameplayVars(player_t *player);
|
void K_UpdateBotGameplayVars(player_t *player);
|
||||||
|
|
||||||
|
|
|
||||||
56
src/k_bot.h
56
src/k_bot.h
|
|
@ -138,25 +138,67 @@ fixed_t K_UpdateRubberband(player_t *player);
|
||||||
fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy);
|
fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy);
|
||||||
|
|
||||||
|
|
||||||
// NOT AVAILABLE FOR LUA
|
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *newplayernum);
|
boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p);
|
||||||
|
|
||||||
Returns the waypoint actually being used as the finish line.
|
Adds a new bot, using code intended to run on all clients.
|
||||||
|
|
||||||
Input Arguments:-
|
Input Arguments:-
|
||||||
skin - Skin number that the bot will use.
|
skin - Skin number that the bot will use.
|
||||||
difficulty - Difficulty level this bot will use.
|
difficulty - Difficulty level this bot will use.
|
||||||
|
style - Bot style to spawn this bot with, see botStyle_e.
|
||||||
newplayernum - Pointer to the last valid player slot number.
|
newplayernum - Pointer to the last valid player slot number.
|
||||||
Is a pointer so that this function can be called multiple times to add more than one bot.
|
Is a pointer so that this function can be called multiple times to add more than one bot.
|
||||||
|
|
||||||
Return:-
|
Return:-
|
||||||
true if a bot packet can be sent, otherwise false.
|
true if a bot was added, otherwise false.
|
||||||
--------------------------------------------------*/
|
--------------------------------------------------*/
|
||||||
|
|
||||||
boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *newplayernum);
|
boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p);
|
||||||
|
|
||||||
|
|
||||||
|
// NOT AVAILABLE FOR LUA
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
void K_SetBot(UINT8 newplayernum, UINT8 skinnum, UINT8 difficulty, botStyle_e style);
|
||||||
|
|
||||||
|
Sets a player ID to be a new bot directly. Invoked directly
|
||||||
|
by K_AddBot, and indirectly by K_AddBotFromServer by sending
|
||||||
|
a packet.
|
||||||
|
|
||||||
|
Input Arguments:-
|
||||||
|
newplayernum - Player slot number to set as a bot.
|
||||||
|
skin - Skin number that the bot will use.
|
||||||
|
difficulty - Difficulty level this bot will use.
|
||||||
|
style - Bot style to spawn this bot with, see botStyle_e.
|
||||||
|
|
||||||
|
Return:-
|
||||||
|
None
|
||||||
|
--------------------------------------------------*/
|
||||||
|
|
||||||
|
void K_SetBot(UINT8 newplayernum, UINT8 skinnum, UINT8 difficulty, botStyle_e style);
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------
|
||||||
|
boolean K_AddBotFromServer(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *newplayernum);
|
||||||
|
|
||||||
|
Adds a new bot, using a server-sided packet sent to all clients.
|
||||||
|
Using regular K_AddBot wherever possible is better, but this is kept
|
||||||
|
as a back-up measure if this is the only option.
|
||||||
|
|
||||||
|
Input Arguments:-
|
||||||
|
skin - Skin number that the bot will use.
|
||||||
|
difficulty - Difficulty level this bot will use.
|
||||||
|
style - Bot style to spawn this bot with, see botStyle_e.
|
||||||
|
newplayernum - Pointer to the last valid player slot number.
|
||||||
|
Is a pointer so that this function can be called multiple times to add more than one bot.
|
||||||
|
|
||||||
|
Return:-
|
||||||
|
true if a bot can be added via a packet later, otherwise false.
|
||||||
|
--------------------------------------------------*/
|
||||||
|
|
||||||
|
boolean K_AddBotFromServer(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p);
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------
|
/*--------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,13 @@ void K_InitGrandPrixBots(void)
|
||||||
{
|
{
|
||||||
if (playeringame[i])
|
if (playeringame[i])
|
||||||
{
|
{
|
||||||
|
if (players[i].bot == true)
|
||||||
|
{
|
||||||
|
// Remove existing bots.
|
||||||
|
CL_RemovePlayer(i, KR_LEAVE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (numplayers < MAXSPLITSCREENPLAYERS && !players[i].spectator)
|
if (numplayers < MAXSPLITSCREENPLAYERS && !players[i].spectator)
|
||||||
{
|
{
|
||||||
competitors[numplayers] = i;
|
competitors[numplayers] = i;
|
||||||
|
|
@ -227,11 +234,15 @@ void K_InitGrandPrixBots(void)
|
||||||
for (i = 0; i < usableskins; i++)
|
for (i = 0; i < usableskins; i++)
|
||||||
{
|
{
|
||||||
if (!(grabskins[i] == MAXSKINS || !R_SkinUsable(-1, grabskins[i], true)))
|
if (!(grabskins[i] == MAXSKINS || !R_SkinUsable(-1, grabskins[i], true)))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
while (usableskins > i && (grabskins[usableskins] == MAXSKINS || !R_SkinUsable(-1, grabskins[usableskins], true)))
|
while (usableskins > i && (grabskins[usableskins] == MAXSKINS || !R_SkinUsable(-1, grabskins[usableskins], true)))
|
||||||
{
|
{
|
||||||
usableskins--;
|
usableskins--;
|
||||||
}
|
}
|
||||||
|
|
||||||
grabskins[i] = grabskins[usableskins];
|
grabskins[i] = grabskins[usableskins];
|
||||||
grabskins[usableskins] = MAXSKINS;
|
grabskins[usableskins] = MAXSKINS;
|
||||||
}
|
}
|
||||||
|
|
@ -245,7 +256,7 @@ void K_InitGrandPrixBots(void)
|
||||||
|
|
||||||
if (usableskins > 0)
|
if (usableskins > 0)
|
||||||
{
|
{
|
||||||
UINT8 index = M_RandomKey(usableskins);
|
UINT8 index = P_RandomKey(PR_BOTS, usableskins);
|
||||||
skinnum = grabskins[index];
|
skinnum = grabskins[index];
|
||||||
grabskins[index] = grabskins[--usableskins];
|
grabskins[index] = grabskins[--usableskins];
|
||||||
}
|
}
|
||||||
|
|
@ -256,7 +267,7 @@ void K_InitGrandPrixBots(void)
|
||||||
|
|
||||||
for (i = 0; i < wantedbots; i++)
|
for (i = 0; i < wantedbots; i++)
|
||||||
{
|
{
|
||||||
if (!K_AddBot(botskinlist[i], difficultylevels[i], &newplayernum))
|
if (!K_AddBot(botskinlist[i], difficultylevels[i], BOT_STYLE_NORMAL, &newplayernum))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -327,8 +338,10 @@ void K_UpdateGrandPrixBots(void)
|
||||||
UINT16 newrivalscore = 0;
|
UINT16 newrivalscore = 0;
|
||||||
UINT8 i;
|
UINT8 i;
|
||||||
|
|
||||||
if (K_PodiumSequence())
|
if (K_PodiumSequence() == true)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAXPLAYERS; i++)
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ typedef enum
|
||||||
// However each instance of RNG being used for
|
// However each instance of RNG being used for
|
||||||
// gameplay should be split up as much as possible.
|
// gameplay should be split up as much as possible.
|
||||||
|
|
||||||
|
// Place new ones at the end for demo compatibility.
|
||||||
|
|
||||||
PR_EXECUTOR, // Linedef executor
|
PR_EXECUTOR, // Linedef executor
|
||||||
PR_ACS, // ACS scripts
|
PR_ACS, // ACS scripts
|
||||||
|
|
||||||
|
|
@ -72,6 +74,8 @@ typedef enum
|
||||||
|
|
||||||
PR_MOVINGTARGET, // Randomised moving targets
|
PR_MOVINGTARGET, // Randomised moving targets
|
||||||
|
|
||||||
|
PR_BOTS, // Bot spawning
|
||||||
|
|
||||||
PRNUMCLASS
|
PRNUMCLASS
|
||||||
} pr_class_t;
|
} pr_class_t;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7742,7 +7742,7 @@ static void P_InitGametype(void)
|
||||||
grandprixinfo.wonround = false;
|
grandprixinfo.wonround = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!modeattacking)
|
else
|
||||||
{
|
{
|
||||||
// We're in a Match Race, use simplistic randomized bots.
|
// We're in a Match Race, use simplistic randomized bots.
|
||||||
K_UpdateMatchRaceBots();
|
K_UpdateMatchRaceBots();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue