Add bot styles & bot spawn ACS function

This commit is contained in:
Sally Coolatta 2023-06-14 09:16:38 -04:00
parent 37efa6782a
commit e6e7056aae
10 changed files with 132 additions and 37 deletions

View file

@ -41,6 +41,7 @@
#include "../r_skins.h"
#include "../k_battle.h"
#include "../k_podium.h"
#include "../k_bot.h"
#include "../z_zone.h"
#include "call-funcs.hpp"
@ -1710,6 +1711,51 @@ bool CallFunc_MapWarp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Wor
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;
(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;
}
K_AddBot(skin, difficulty, style, &newplayernum);
thread->dataStk.push(newplayernum);
return false;
}
/*--------------------------------------------------
bool CallFunc_Get/SetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)

View file

@ -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_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_SetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);

View file

@ -166,6 +166,7 @@ Environment::Environment()
addFuncDataACS0( 502, addCallFunc(CallFunc_PodiumFinish));
addFuncDataACS0( 503, addCallFunc(CallFunc_SetLineRenderStyle));
addFuncDataACS0( 504, addCallFunc(CallFunc_MapWarp));
addFuncDataACS0( 505, addCallFunc(CallFunc_AddBot));
}
ACSVM::Thread *Environment::allocThread()

View file

@ -15,7 +15,6 @@
#include "thread.hpp"
extern "C" {
#include "../doomtype.h"
#include "../doomdef.h"
#include "../doomstat.h"
@ -26,7 +25,6 @@ extern "C" {
#include "../r_defs.h"
#include "../r_state.h"
#include "../p_polyobj.h"
}
using namespace srb2::acs;

View file

@ -16,6 +16,7 @@
#include "acsvm.hpp"
extern "C" {
#include "../doomtype.h"
#include "../doomdef.h"
#include "../doomstat.h"
@ -23,7 +24,7 @@
#include "../r_defs.h"
#include "../r_state.h"
#include "../p_spec.h"
}
namespace srb2::acs {

View file

@ -4010,6 +4010,7 @@ static void Got_AddBot(UINT8 **p, INT32 playernum)
INT16 newplayernum;
UINT8 skinnum = 0;
UINT8 difficulty = DIFFICULTBOT;
botStyle_e style = BOT_STYLE_NORMAL;
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{
@ -4025,6 +4026,7 @@ static void Got_AddBot(UINT8 **p, INT32 playernum)
newplayernum = READUINT8(*p);
skinnum = READUINT8(*p);
difficulty = READUINT8(*p);
style = READUINT8(*p);
CONS_Debug(DBG_NETPLAY, "addbot: %d\n", newplayernum);
@ -4045,6 +4047,7 @@ static void Got_AddBot(UINT8 **p, INT32 playernum)
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;

View file

@ -313,9 +313,20 @@ struct respawnvars_t
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
struct botvars_t
{
botStyle_e style; // Training mode-style CPU mode
UINT8 difficulty; // Bot's difficulty setting
UINT8 diffincrease; // In GP: bot difficulty will increase this much next round
boolean rival; // If true, they're the GP rival

View file

@ -37,11 +37,11 @@
#endif
/*--------------------------------------------------
boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *p)
boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p)
See header file for description.
--------------------------------------------------*/
boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *p)
boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p)
{
UINT8 buf[3];
UINT8 *buf_p = buf;
@ -96,6 +96,7 @@ boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *p)
}
WRITEUINT8(buf_p, difficulty);
WRITEUINT8(buf_p, style);
SendNetXCmd(XD_ADDBOT, buf, buf_p - buf);
@ -156,6 +157,9 @@ void K_UpdateMatchRaceBots(void)
// While we're here, we should update bot difficulty to the proper value.
players[i].botvars.difficulty = difficulty;
// Enforce normal style for Match Race
players[i].botvars.style = BOT_STYLE_NORMAL;
}
else
{
@ -169,7 +173,7 @@ void K_UpdateMatchRaceBots(void)
}
}
if (difficulty == 0 || !(gametyperules & GTR_BOTS))
if (difficulty == 0 || (gametyperules & GTR_BOTS) == 0)
{
wantedbots = 0;
}
@ -217,7 +221,7 @@ void K_UpdateMatchRaceBots(void)
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.
break;
@ -231,7 +235,6 @@ void K_UpdateMatchRaceBots(void)
UINT8 buf[2];
i = MAXPLAYERS;
while (numbots > wantedbots && i > 0)
{
i--;
@ -1473,11 +1476,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;
botprediction_t *predict = NULL;
@ -1487,29 +1490,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
INT32 turnamt = 0;
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
|| K_GetNumWaypoints() == 0 // No waypoints
|| leveltime <= introtime // During intro camera
@ -1762,6 +1742,59 @@ 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)
{
precise_t t = 0;
botprediction_t *predict = NULL;
boolean trySpindash = true;
angle_t destangle = 0;
UINT8 spindash = 0;
INT32 turnamt = 0;
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;
}
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);

View file

@ -142,13 +142,14 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t
/*--------------------------------------------------
boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *newplayernum);
boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *newplayernum);
Returns the waypoint actually being used as the finish line.
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.
@ -156,7 +157,7 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t
true if a bot packet can be sent, otherwise false.
--------------------------------------------------*/
boolean K_AddBot(UINT8 skin, UINT8 difficulty, UINT8 *newplayernum);
boolean K_AddBot(UINT8 skin, UINT8 difficulty, botStyle_e style, UINT8 *p);
/*--------------------------------------------------

View file

@ -256,7 +256,7 @@ void K_InitGrandPrixBots(void)
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;
}