434 lines
12 KiB
C++
434 lines
12 KiB
C++
// BLANKART
|
|
//-----------------------------------------------------------------------------
|
|
// Copyright (C) 2024 by Sally "TehRealSalt" Cochenour
|
|
// Copyright (C) 2024 by Kart Krew
|
|
//
|
|
// This program is free software distributed under the
|
|
// terms of the GNU General Public License, version 2.
|
|
// See the 'LICENSE' file for more details.
|
|
//-----------------------------------------------------------------------------
|
|
/// \file k_bot.h
|
|
/// \brief Bot logic & ticcmd generation code
|
|
|
|
#ifndef __K_BOT__
|
|
#define __K_BOT__
|
|
|
|
#include "typedef.h"
|
|
#include "k_waypoint.h"
|
|
#include "d_player.h"
|
|
#include "r_defs.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
extern consvar_t cv_forcebots;
|
|
extern consvar_t cv_botcontrol;
|
|
|
|
// Maximum value of botvars.difficulty
|
|
#define MAXBOTDIFFICULTY (13)
|
|
|
|
// Level of a "difficult" bot. The max bot level was increased, but this keeps all of the same calculations.
|
|
#define DIFFICULTBOT (9)
|
|
|
|
// How many tics in a row do you need to turn in this direction before we'll let you turn.
|
|
// Made it as small as possible without making it look like the bots are twitching constantly.
|
|
#define BOTTURNCONFIRM 4
|
|
|
|
// How many tics with only one spindash-viable condition before we'll let you spindash.
|
|
#define BOTSPINDASHCONFIRM (4*TICRATE)
|
|
|
|
// How many tics without being able to make progress before we'll let you respawn.
|
|
#define BOTRESPAWNCONFIRM (4*TICRATE)
|
|
|
|
// How long it takes for a Lv.1 bot to decide to pick an item.
|
|
#define BOT_ITEM_DECISION_TIME (2*TICRATE)
|
|
|
|
// Minimum percentage for a (non-auto) drift to begin.
|
|
#define BOTDRIFTPERCENT (10)
|
|
|
|
// Minimum turning percentage for an auto drift to begin.
|
|
#define DRIFTSTARTPCT (45)
|
|
|
|
#define BOTDRIFTTICS (2*TICRATE/3)
|
|
#define BOTDRIFTLOCKOUT (TICRATE/2)
|
|
|
|
#define MAXDRIFTSKILL (FRACUNIT/2)
|
|
|
|
typedef enum
|
|
{
|
|
DRIFTSTATE_AUTO,
|
|
DRIFTSTATE_STARTING,
|
|
DRIFTSTATE_ACTIVE,
|
|
DRIFTSTATE_ENDING,
|
|
NUMDRIFTSTATES
|
|
} ATTRPACK botdrift_e;
|
|
|
|
// unsynced bot variables, exclusively for use by bot logic and ticcmd generation
|
|
// nobody except the server cares about this stuff!
|
|
struct botdata_t
|
|
{
|
|
// Point for bots to aim for
|
|
struct
|
|
{
|
|
fixed_t x, y;
|
|
fixed_t radius, baseRadius;
|
|
} predict;
|
|
|
|
tic_t itemdelay; // Delay before using item at all
|
|
tic_t itemconfirm; // When high enough, they will use their item
|
|
|
|
SINT8 turnconfirm; // Confirm turn direction
|
|
UINT8 respawnconfirm; // Confirm when respawn is needed.
|
|
|
|
botdrift_e driftstate; // Drifting state
|
|
SINT8 driftturn; // Drifting turn direction
|
|
tic_t drifttime; // Time spent drifting
|
|
tic_t driftlockout; // do not allow drifting for this many tics
|
|
|
|
UINT16 driftmaxdist; // how far to look for drift waypoints
|
|
UINT16 driftpowerdiv; // arbitrary divider on drift turning
|
|
UINT16 driftstatedelay; // max time to wait between drift state changes
|
|
|
|
fixed_t driftskill; // The bot's "skill" at drifts.
|
|
// Determines how soon a bot starts to drift.
|
|
|
|
boolean acceldown, brakedown, driftdown, itemdown; // buttons
|
|
boolean dolookback; // look out behind you
|
|
boolean itemwasdown; // last tic's item button
|
|
SINT8 itemthrow; // throwdir
|
|
INT16 turnamt; // turning
|
|
|
|
angle_t predictionerror; // How bad is our momentum angle relative to where we're trying to go?
|
|
angle_t griplockout; // When you need to prevent grip braking, use this.
|
|
};
|
|
|
|
// AVAILABLE FOR LUA
|
|
|
|
void K_BotTicker(const player_t *player);
|
|
|
|
void K_DrawBotDebugger(const player_t *player);
|
|
|
|
/*--------------------------------------------------
|
|
boolean K_PlayerUsesBotMovement(const player_t *player);
|
|
|
|
Tells if this player is being controlled via bot movement code (is a bot, or is exiting).
|
|
|
|
Input Arguments:-
|
|
player - Player to check.
|
|
|
|
Return:-
|
|
true if using bot movement code, otherwise false.
|
|
--------------------------------------------------*/
|
|
|
|
boolean K_PlayerUsesBotMovement(const player_t *player);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
boolean K_BotCanTakeCut(const player_t *player);
|
|
|
|
Tells if this bot is able to take shortcuts (currently unaffected by offroad,
|
|
or has certain items ready).
|
|
|
|
Input Arguments:-
|
|
player - Player to check.
|
|
|
|
Return:-
|
|
true if able to take shortcuts, otherwise false.
|
|
--------------------------------------------------*/
|
|
|
|
boolean K_BotCanTakeCut(const player_t *player);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
botcontroller_t *K_GetBotController(const mobj_t *mobj);
|
|
|
|
Retrieves the current bot controller values from
|
|
the player's current sector.
|
|
|
|
Input Arguments:-
|
|
mobj - The player's object to get the bot controller for.
|
|
|
|
Return:-
|
|
Pointer to the sector's bot controller struct.
|
|
--------------------------------------------------*/
|
|
|
|
botcontroller_t *K_GetBotController(const mobj_t *mobj);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
fixed_t K_BotMapModifier(void);
|
|
|
|
Gives a multiplier, based on the track complexity.
|
|
Track complexity is a measure of how easy it is for
|
|
the bots to continuously rubberband. This is used
|
|
to make the rubberbanding and other difficulty
|
|
adjustments feel roughly the same between wildly
|
|
different layouts.
|
|
|
|
Input Arguments:-
|
|
N/A
|
|
|
|
Return:-
|
|
A multiplier in fixed point scale, between 0.0 and 2.0.
|
|
--------------------------------------------------*/
|
|
|
|
fixed_t K_BotMapModifier(void);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
fixed_t K_BotRubberband(const player_t *player);
|
|
|
|
Gives a multiplier for a bot's rubberbanding.
|
|
Meant to be used for acceleration and handling.
|
|
|
|
Input Arguments:-
|
|
player - Player to check.
|
|
|
|
Return:-
|
|
A multiplier in fixed point scale.
|
|
--------------------------------------------------*/
|
|
|
|
fixed_t K_BotRubberband(const player_t *player);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
fixed_t K_UpdateRubberband(player_t *player);
|
|
|
|
Eases the current rubberbanding value to the
|
|
new one, calculated by K_BotRubberband.
|
|
|
|
Input Arguments:-
|
|
player - Player to update.
|
|
|
|
Return:-
|
|
The new rubberband multiplier, in fixed point scale.
|
|
--------------------------------------------------*/
|
|
|
|
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);
|
|
|
|
Gets the distance of a point away from a line.
|
|
TODO: Could go in another file?
|
|
|
|
Input Arguments:-
|
|
v1x - Line's first vertex x position.
|
|
v1y - Line's first vertex y position.
|
|
v2x - Line's second vertex x position.
|
|
v2y - Line's second vertex y position.
|
|
cx - Point's x position.
|
|
cy - Point's y position.
|
|
|
|
Return:-
|
|
The distance between the point and the line.
|
|
--------------------------------------------------*/
|
|
|
|
fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y, fixed_t cx, fixed_t cy);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
boolean K_AddBot(UINT16 skin, UINT8 difficulty, botStyle_e style, UINT8 *p);
|
|
|
|
Adds a new bot, using code intended to run on all clients.
|
|
|
|
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 was added, otherwise false.
|
|
--------------------------------------------------*/
|
|
|
|
boolean K_AddBot(UINT16 skin, UINT8 difficulty, botStyle_e style, UINT8 *p);
|
|
|
|
|
|
// NOT AVAILABLE FOR LUA
|
|
|
|
|
|
/*--------------------------------------------------
|
|
void K_SetNameForBot(UINT8 newplayernum, const char *realname)
|
|
|
|
Sets a bot's name.
|
|
by K_AddBot, and indirectly by K_AddBotFromServer by sending
|
|
a packet.
|
|
|
|
Input Arguments:-
|
|
newplayernum - Player slot number to set name for.
|
|
realname - Proposed name for bot.
|
|
|
|
Return:-
|
|
None
|
|
--------------------------------------------------*/
|
|
|
|
void K_SetNameForBot(UINT8 newplayernum, const char *realname);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
void K_SetBot(UINT8 newplayernum, UINT16 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, UINT16 skinnum, UINT8 difficulty, botStyle_e style);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
void K_UpdateMatchRaceBots(void);
|
|
|
|
Updates the number of bots in the server and their difficulties for Match Race.
|
|
--------------------------------------------------*/
|
|
|
|
void K_UpdateMatchRaceBots(void);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
UINT8 K_EggboxStealth(fixed_t x, fixed_t y);
|
|
|
|
Gets a "stealth" value for a position, to figure out how
|
|
well Eggman boxes blend into random items.
|
|
|
|
Input Arguments:-
|
|
x - X coordinate to check.
|
|
y - Y coordinate to check.
|
|
|
|
Return:-
|
|
Stealth value for the position.
|
|
--------------------------------------------------*/
|
|
|
|
UINT8 K_EggboxStealth(fixed_t x, fixed_t y);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
boolean K_BotHatesThisSector(const player_t *player, sector_t *sec, fixed_t x, fixed_t y)
|
|
|
|
Tells us if a bot will play more careful around
|
|
this sector. Checks FOFs in the sector, as well.
|
|
|
|
Input Arguments:-
|
|
player - Player to check against.
|
|
sec - Sector to check against.
|
|
x - Linedef cross X position, for slopes
|
|
y - Linedef cross Y position, for slopes
|
|
|
|
Return:-
|
|
true if avoiding this sector, false otherwise.
|
|
--------------------------------------------------*/
|
|
|
|
boolean K_BotHatesThisSector(const player_t *player, sector_t *sec, fixed_t x, fixed_t y);
|
|
|
|
// Moves the bot's prediction, based on objects around the bot.
|
|
void K_NudgePredictionTowardsObjects(botdata_t *bd, const player_t *player);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
INT32 K_PositionBully(const player_t *player)
|
|
|
|
Calculates a turn value to reach a player that can be bullied.
|
|
|
|
Input Arguments:-
|
|
player - Bot to run this for.
|
|
|
|
Return:-
|
|
INT32_MAX if couldn't find anything, otherwise a steering value.
|
|
--------------------------------------------------*/
|
|
|
|
INT32 K_PositionBully(const player_t *player);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
boolean K_GetBlockedBubbleItem(const player_t *player, , fixed_t radius)
|
|
|
|
Searches the blockmap for items to block with the Bubble Shield
|
|
|
|
Input Arguments:-
|
|
player - Bot to run this for.
|
|
radius - Radius around player to check for items.
|
|
|
|
Return:-
|
|
false if couldn't find anything, otherwise true to attempt blocking item.
|
|
--------------------------------------------------*/
|
|
|
|
boolean K_GetBlockedBubbleItem(const player_t *player, fixed_t radius);
|
|
|
|
/*--------------------------------------------------
|
|
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd);
|
|
|
|
Creates a bot's ticcmd, looking at its surroundings to
|
|
try and figure out what it should do.
|
|
|
|
Input Arguments:-
|
|
player - Player to generate the ticcmd for.
|
|
cmd - The player's ticcmd to modify.
|
|
|
|
Return:-
|
|
None
|
|
--------------------------------------------------*/
|
|
|
|
void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
void K_UpdateBotGameplayVarsItemUsage(player_t *player)
|
|
|
|
Updates gamestate affecting botvars, relating to
|
|
item usage. This must be called for both client
|
|
and server.
|
|
|
|
Input Arguments:-
|
|
player - Player to whom to update the botvars.
|
|
|
|
Return:-
|
|
N/A
|
|
--------------------------------------------------*/
|
|
|
|
void K_UpdateBotGameplayVarsItemUsage(player_t *player);
|
|
|
|
|
|
/*--------------------------------------------------
|
|
void K_UpdateBotGameplayVars(player_t *player);
|
|
|
|
Updates gamestate affecting botvars. This must be
|
|
called for both client and server.
|
|
|
|
Input Arguments:-
|
|
player - Player to whom to update the botvars.
|
|
|
|
Return:-
|
|
None
|
|
--------------------------------------------------*/
|
|
|
|
void K_UpdateBotGameplayVars(player_t *player);
|
|
|
|
// Item usage part of ticcmd generation.
|
|
void K_BotItemUsage(botdata_t *bd, const player_t *player);
|
|
|
|
void K_BotReborn(const player_t *player);
|
|
|
|
void K_BotResetItemConfirm(const player_t *player, boolean setdelay);
|
|
|
|
void K_BotSetDriftState(const player_t *player, botdrift_e newstate, tic_t lockout);
|
|
|
|
botdata_t *K_GetBotData(UINT8 num);
|
|
|
|
#ifdef __cplusplus
|
|
} // extern "C"
|
|
#endif
|
|
|
|
#endif
|