mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-02-22 05:21:11 +00:00
Bot controller is stored on the sector now
- Moved destination tag off of linedef tag and into args. - Bot controller values can be changed mid-level with ACS. (Linedefs using type 2004 will still be activated on level load.) - Add flag to make bots fastfall
This commit is contained in:
parent
de5b151985
commit
de9780ab3f
9 changed files with 136 additions and 114 deletions
|
|
@ -367,7 +367,6 @@ struct botvars_t
|
|||
// All entries above persist between rounds and must be recorded in demos
|
||||
|
||||
fixed_t rubberband; // Bot rubberband value
|
||||
UINT16 controller; // Special bot controller linedef ID
|
||||
|
||||
tic_t itemdelay; // Delay before using item at all
|
||||
tic_t itemconfirm; // When high enough, they will use their item
|
||||
|
|
|
|||
|
|
@ -2333,7 +2333,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->ringvolume = 255;
|
||||
|
||||
p->botvars.rubberband = FRACUNIT;
|
||||
p->botvars.controller = UINT16_MAX;
|
||||
|
||||
p->spectatorReentry = spectatorReentry;
|
||||
p->griefValue = griefValue;
|
||||
|
|
|
|||
153
src/k_bot.cpp
153
src/k_bot.cpp
|
|
@ -379,74 +379,23 @@ static fixed_t K_BotSpeedScaled(player_t *player, fixed_t speed)
|
|||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static line_t *K_FindBotController(mobj_t *mo)
|
||||
botcontroller_t *K_GetBotController(mobj_t *mobj)
|
||||
|
||||
Finds if any bot controller linedefs are tagged to the bot's sector.
|
||||
|
||||
Input Arguments:-
|
||||
mo - The bot player's mobj.
|
||||
|
||||
Return:-
|
||||
Linedef of the bot controller. nullptr if it doesn't exist.
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
static line_t *K_FindBotController(mobj_t *mo)
|
||||
botcontroller_t *K_GetBotController(mobj_t *mobj)
|
||||
{
|
||||
msecnode_t *node;
|
||||
ffloor_t *rover;
|
||||
INT16 lineNum = -1;
|
||||
mtag_t tag;
|
||||
|
||||
I_Assert(mo != nullptr);
|
||||
I_Assert(!P_MobjWasRemoved(mo));
|
||||
|
||||
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||
{
|
||||
if (!node->m_sector)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
tag = Tag_FGet(&node->m_sector->tags);
|
||||
lineNum = P_FindSpecialLineFromTag(2004, tag, -1); // todo: needs to not use P_FindSpecialLineFromTag
|
||||
|
||||
if (lineNum != -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
sector_t *rs = nullptr;
|
||||
|
||||
if (!(rover->fofflags & FOF_EXISTS))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mo->z > *rover->topheight || mo->z + mo->height < *rover->bottomheight)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rs = §ors[rover->secnum];
|
||||
tag = Tag_FGet(&rs->tags);
|
||||
lineNum = P_FindSpecialLineFromTag(2004, tag, -1);
|
||||
|
||||
if (lineNum != -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lineNum != -1)
|
||||
{
|
||||
return &lines[lineNum];
|
||||
}
|
||||
else
|
||||
if (P_MobjWasRemoved(mobj) == true)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mobj->subsector == nullptr || mobj->subsector->sector == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &mobj->subsector->sector->botController;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -555,18 +504,10 @@ fixed_t K_BotRubberband(player_t *player)
|
|||
return FRACUNIT;
|
||||
}
|
||||
|
||||
if (player->botvars.controller != UINT16_MAX)
|
||||
const botcontroller_t *botController = K_GetBotController(player->mo);
|
||||
if (botController != nullptr && (botController->flags & TMBOT_NORUBBERBAND) == TMBOT_NORUBBERBAND) // Disable rubberbanding
|
||||
{
|
||||
const line_t *botController = &lines[player->botvars.controller];
|
||||
|
||||
if (botController != nullptr)
|
||||
{
|
||||
// Disable rubberbanding
|
||||
if (botController->args[1] & TMBOT_NORUBBERBAND)
|
||||
{
|
||||
return FRACUNIT;
|
||||
}
|
||||
}
|
||||
return FRACUNIT;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -1121,19 +1062,19 @@ static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player)
|
|||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_BotTrick(player_t *player, ticcmd_t *cmd, line_t *botController)
|
||||
static void K_BotTrick(player_t *player, ticcmd_t *cmd, const botcontroller_t *botController)
|
||||
|
||||
Determines inputs for trick panels.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to generate the ticcmd for.
|
||||
cmd - The player's ticcmd to modify.
|
||||
botController - Linedef for the bot controller.
|
||||
botController - Bot controller struct.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static void K_BotTrick(player_t *player, ticcmd_t *cmd, const line_t *botController)
|
||||
static void K_BotTrick(player_t *player, ticcmd_t *cmd, const botcontroller_t *botController)
|
||||
{
|
||||
// Trick panel state -- do nothing until a controller line is found, in which case do a trick.
|
||||
if (botController == nullptr)
|
||||
|
|
@ -1143,21 +1084,18 @@ static void K_BotTrick(player_t *player, ticcmd_t *cmd, const line_t *botControl
|
|||
|
||||
if (player->trickpanel == 1)
|
||||
{
|
||||
INT32 type = botController->args[0];
|
||||
|
||||
// Y Offset: Trick type
|
||||
switch (type)
|
||||
switch (botController->trick)
|
||||
{
|
||||
case 1:
|
||||
case TMBOTTR_LEFT:
|
||||
cmd->turning = KART_FULLTURN;
|
||||
break;
|
||||
case 2:
|
||||
case TMBOTTR_RIGHT:
|
||||
cmd->turning = -KART_FULLTURN;
|
||||
break;
|
||||
case 3:
|
||||
case TMBOTTR_UP:
|
||||
cmd->throwdir = KART_FULLTURN;
|
||||
break;
|
||||
case 4:
|
||||
case TMBOTTR_DOWN:
|
||||
cmd->throwdir = -KART_FULLTURN;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1531,7 +1469,6 @@ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd)
|
|||
angle_t destangle = 0;
|
||||
UINT8 spindash = 0;
|
||||
INT32 turnamt = 0;
|
||||
const line_t *botController = player->botvars.controller != UINT16_MAX ? &lines[player->botvars.controller] : nullptr;
|
||||
|
||||
if (!(gametyperules & GTR_BOTS) // No bot behaviors
|
||||
|| K_GetNumWaypoints() == 0 // No waypoints
|
||||
|
|
@ -1554,15 +1491,9 @@ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd)
|
|||
if (!cv_botcontrol.value)
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Actual gameplay behaviors below this block!
|
||||
|
||||
if (K_TryRingShooter(player) == true)
|
||||
{
|
||||
// We want to respawn. Simply hold Y and stop here!
|
||||
cmd->buttons |= (BT_RESPAWN | BT_EBRAKEMASK);
|
||||
return;
|
||||
}
|
||||
|
||||
const botcontroller_t *botController = K_GetBotController(player->mo);
|
||||
if (player->trickpanel != 0)
|
||||
{
|
||||
K_BotTrick(player, cmd, botController);
|
||||
|
|
@ -1571,29 +1502,45 @@ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd)
|
|||
return;
|
||||
}
|
||||
|
||||
if (botController != nullptr && (botController->args[1] & TMBOT_NOCONTROL))
|
||||
if (botController != nullptr && (botController->flags & TMBOT_NOCONTROL) == TMBOT_NOCONTROL)
|
||||
{
|
||||
// Disable bot controls entirely.
|
||||
return;
|
||||
}
|
||||
|
||||
if (K_TryRingShooter(player) == true)
|
||||
{
|
||||
// We want to respawn. Simply hold Y and stop here!
|
||||
cmd->buttons |= (BT_RESPAWN | BT_EBRAKEMASK);
|
||||
return;
|
||||
}
|
||||
|
||||
destangle = player->mo->angle;
|
||||
|
||||
if (botController != nullptr && (botController->args[1] & TMBOT_FORCEDIR))
|
||||
if (botController != nullptr && (botController->flags & TMBOT_FORCEDIR) == TMBOT_FORCEDIR)
|
||||
{
|
||||
const fixed_t dist = DEFAULT_WAYPOINT_RADIUS * player->mo->scale;
|
||||
|
||||
// X Offset: Movement direction
|
||||
destangle = FixedAngle(botController->args[2] * FRACUNIT);
|
||||
|
||||
// Overwritten prediction
|
||||
predict = static_cast<botprediction_t *>(Z_Calloc(sizeof(botprediction_t), PU_STATIC, nullptr));
|
||||
|
||||
predict->x = player->mo->x + FixedMul(dist, FINECOSINE(destangle >> ANGLETOFINESHIFT));
|
||||
predict->y = player->mo->y + FixedMul(dist, FINESINE(destangle >> ANGLETOFINESHIFT));
|
||||
predict->x = player->mo->x + FixedMul(dist, FINECOSINE(botController->forceAngle >> ANGLETOFINESHIFT));
|
||||
predict->y = player->mo->y + FixedMul(dist, FINESINE(botController->forceAngle >> ANGLETOFINESHIFT));
|
||||
predict->radius = (DEFAULT_WAYPOINT_RADIUS / 4) * mapobjectscale;
|
||||
}
|
||||
|
||||
if (P_IsObjectOnGround(player->mo) == false)
|
||||
{
|
||||
if (botController != nullptr && (botController->flags & TMBOT_FASTFALL) == TMBOT_FASTFALL)
|
||||
{
|
||||
// Fast fall!
|
||||
cmd->buttons |= BT_EBRAKEMASK;
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (leveltime <= starttime && finishBeamLine != nullptr)
|
||||
{
|
||||
// Handle POSITION!!
|
||||
|
|
@ -1838,9 +1785,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
--------------------------------------------------*/
|
||||
void K_UpdateBotGameplayVars(player_t *player)
|
||||
{
|
||||
const line_t *botController;
|
||||
|
||||
player->botvars.controller = UINT16_MAX;
|
||||
player->botvars.rubberband = FRACUNIT;
|
||||
|
||||
if (gamestate != GS_LEVEL || !player->mo)
|
||||
|
|
@ -1849,8 +1793,5 @@ void K_UpdateBotGameplayVars(player_t *player)
|
|||
return;
|
||||
}
|
||||
|
||||
botController = K_FindBotController(player->mo);
|
||||
|
||||
player->botvars.controller = botController ? (botController - lines) : UINT16_MAX;
|
||||
player->botvars.rubberband = K_UpdateRubberband(player);
|
||||
}
|
||||
|
|
|
|||
17
src/k_bot.h
17
src/k_bot.h
|
|
@ -13,6 +13,7 @@
|
|||
#ifndef __K_BOT__
|
||||
#define __K_BOT__
|
||||
|
||||
#include "typedef.h"
|
||||
#include "k_waypoint.h"
|
||||
#include "d_player.h"
|
||||
#include "r_defs.h"
|
||||
|
|
@ -85,6 +86,22 @@ boolean K_PlayerUsesBotMovement(player_t *player);
|
|||
boolean K_BotCanTakeCut(player_t *player);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
botcontroller_t *K_GetBotController(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(mobj_t *mobj);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_BotMapModifier(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -611,7 +611,6 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
WRITEUINT8(save->p, players[i].botvars.diffincrease);
|
||||
WRITEUINT8(save->p, players[i].botvars.rival);
|
||||
WRITEFIXED(save->p, players[i].botvars.rubberband);
|
||||
WRITEUINT16(save->p, players[i].botvars.controller);
|
||||
WRITEUINT32(save->p, players[i].botvars.itemdelay);
|
||||
WRITEUINT32(save->p, players[i].botvars.itemconfirm);
|
||||
WRITESINT8(save->p, players[i].botvars.turnconfirm);
|
||||
|
|
@ -1126,7 +1125,6 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].botvars.diffincrease = READUINT8(save->p);
|
||||
players[i].botvars.rival = (boolean)READUINT8(save->p);
|
||||
players[i].botvars.rubberband = READFIXED(save->p);
|
||||
players[i].botvars.controller = READUINT16(save->p);
|
||||
players[i].botvars.itemdelay = READUINT32(save->p);
|
||||
players[i].botvars.itemconfirm = READUINT32(save->p);
|
||||
players[i].botvars.turnconfirm = READSINT8(save->p);
|
||||
|
|
@ -1729,6 +1727,7 @@ static void P_NetUnArchiveColormaps(savebuffer_t *save)
|
|||
|
||||
//diff5 flags
|
||||
#define SD_ACTIVATION 0x01
|
||||
#define SD_BOTCONTROLLER 0x02
|
||||
|
||||
static boolean P_SectorArgsEqual(const sector_t *sc, const sector_t *spawnsc)
|
||||
{
|
||||
|
|
@ -1964,6 +1963,12 @@ static void ArchiveSectors(savebuffer_t *save)
|
|||
diff4 |= SD_STRINGARGS;
|
||||
if (ss->activation != spawnss->activation)
|
||||
diff5 |= SD_ACTIVATION;
|
||||
if (ss->botController.trick != spawnss->botController.trick
|
||||
|| ss->botController.flags != spawnss->botController.flags
|
||||
|| ss->botController.forceAngle != spawnss->botController.forceAngle)
|
||||
{
|
||||
diff5 |= SD_BOTCONTROLLER;
|
||||
}
|
||||
|
||||
if (ss->ffloors && CheckFFloorDiff(ss))
|
||||
diff |= SD_FFLOORS;
|
||||
|
|
@ -2076,6 +2081,12 @@ static void ArchiveSectors(savebuffer_t *save)
|
|||
}
|
||||
if (diff5 & SD_ACTIVATION)
|
||||
WRITEUINT32(save->p, ss->activation);
|
||||
if (diff5 & SD_BOTCONTROLLER)
|
||||
{
|
||||
WRITEUINT8(save->p, ss->botController.trick);
|
||||
WRITEUINT32(save->p, ss->botController.flags);
|
||||
WRITEANGLE(save->p, ss->botController.forceAngle);
|
||||
}
|
||||
|
||||
if (diff & SD_FFLOORS)
|
||||
ArchiveFFloors(save, ss);
|
||||
|
|
@ -2232,6 +2243,12 @@ static void UnArchiveSectors(savebuffer_t *save)
|
|||
}
|
||||
if (diff5 & SD_ACTIVATION)
|
||||
sectors[i].activation = READUINT32(save->p);
|
||||
if (diff5 & SD_BOTCONTROLLER)
|
||||
{
|
||||
sectors[i].botController.trick = READUINT8(save->p);
|
||||
sectors[i].botController.flags = READUINT32(save->p);
|
||||
sectors[i].botController.forceAngle = READANGLE(save->p);
|
||||
}
|
||||
|
||||
if (diff & SD_FFLOORS)
|
||||
UnArchiveFFloors(save, §ors[i]);
|
||||
|
|
|
|||
33
src/p_spec.c
33
src/p_spec.c
|
|
@ -1380,7 +1380,8 @@ boolean P_CanActivateSpecial(INT16 special)
|
|||
{
|
||||
case 2001: // Finish line
|
||||
case 2003: // Respawn line
|
||||
case 2005: // Dismount Flying Object (always true here so that conditions are only kept on execution)
|
||||
case 2004: // Bot controller
|
||||
case 2005: // Dismount Flying Object
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2474,6 +2475,20 @@ mobj_t* P_FindObjectTypeFromTag(mobjtype_t type, mtag_t tag)
|
|||
}
|
||||
}
|
||||
|
||||
static void K_UpdateBotControllers(INT32 *args)
|
||||
{
|
||||
INT32 secnum;
|
||||
|
||||
TAG_ITER_SECTORS(args[0], secnum)
|
||||
{
|
||||
sector_t *const sec = sectors + secnum;
|
||||
|
||||
sec->botController.trick = args[1];
|
||||
sec->botController.flags = args[2];
|
||||
sec->botController.forceAngle = FixedAngle(args[3] * FRACUNIT);
|
||||
}
|
||||
}
|
||||
|
||||
/** Processes the line special triggered by an object.
|
||||
*
|
||||
* \param line Line with the special command on it.
|
||||
|
|
@ -4418,8 +4433,8 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha
|
|||
|
||||
if ((gametyperules & GTR_CIRCUIT) && (mo->player->exiting == 0) && !(mo->player->pflags & PF_HITFINISHLINE))
|
||||
{
|
||||
if (((line->args[0] & TMCFF_FLIP) && (side == 0))
|
||||
|| (!(line->args[0] & TMCFF_FLIP) && (side == 1))) // crossed from behind to infront
|
||||
if (((args[0] & TMCFF_FLIP) && (side == 0))
|
||||
|| (!(args[0] & TMCFF_FLIP) && (side == 1))) // crossed from behind to infront
|
||||
{
|
||||
K_HandleLapIncrement(mo->player);
|
||||
|
||||
|
|
@ -4446,7 +4461,7 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha
|
|||
if
|
||||
(
|
||||
mo->player->respawn.state == RESPAWNST_NONE &&
|
||||
(!(line->args[0] & TMCRF_FRONTONLY) || side == 0)
|
||||
(!(args[0] & TMCRF_FRONTONLY) || side == 0)
|
||||
)
|
||||
{
|
||||
P_DamageMobj(mo, NULL, NULL, 1, DMG_DEATHPIT);
|
||||
|
|
@ -4454,6 +4469,12 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha
|
|||
}
|
||||
break;
|
||||
|
||||
case 2004: // Bot Controller.
|
||||
{
|
||||
K_UpdateBotControllers(args);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2005: // Dismount Flying object
|
||||
// the rideroid is a bit complex so it's the one controlling the player rather than the player controlling it.
|
||||
// so it is the object needing to be checked for rather than the player
|
||||
|
|
@ -7641,6 +7662,10 @@ void P_SpawnSpecials(boolean fromnetsave)
|
|||
}
|
||||
break;
|
||||
|
||||
case 2004: // Bot Controller.
|
||||
K_UpdateBotControllers(lines[i].args);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
10
src/p_spec.h
10
src/p_spec.h
|
|
@ -525,8 +525,18 @@ typedef enum
|
|||
TMBOT_NORUBBERBAND = 1,
|
||||
TMBOT_NOCONTROL = 1<<1,
|
||||
TMBOT_FORCEDIR = 1<<2,
|
||||
TMBOT_FASTFALL = 1<<3,
|
||||
} textmapbotcontroller_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TMBOTTR_NONE = 0,
|
||||
TMBOTTR_LEFT = 1,
|
||||
TMBOTTR_RIGHT = 2,
|
||||
TMBOTTR_UP = 3,
|
||||
TMBOTTR_DOWN = 4,
|
||||
} textmapbottrick_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TMLOOP_ALPHA = 0,
|
||||
|
|
|
|||
13
src/r_defs.h
13
src/r_defs.h
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
#include "k_mapuser.h"
|
||||
|
||||
#include "k_bot.h" // botcontroller_t
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
@ -331,6 +333,14 @@ struct pslope_t
|
|||
#endif
|
||||
};
|
||||
|
||||
// Per-sector bot controller override
|
||||
struct botcontroller_t
|
||||
{
|
||||
UINT8 trick;
|
||||
UINT32 flags;
|
||||
angle_t forceAngle;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
// flipspecial - planes with effect
|
||||
|
|
@ -552,6 +562,9 @@ struct sector_t
|
|||
// colormap structure
|
||||
extracolormap_t *spawn_extra_colormap;
|
||||
|
||||
// Ring Racers bots
|
||||
botcontroller_t botController;
|
||||
|
||||
// Action specials
|
||||
INT16 action;
|
||||
INT32 args[NUM_SCRIPT_ARGS];
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ TYPEDEF (weakspot_t);
|
|||
|
||||
// k_bot.h
|
||||
TYPEDEF (botprediction_t);
|
||||
TYPEDEF (botcontroller_t);
|
||||
|
||||
// k_brightmap.h
|
||||
TYPEDEF (brightmapStorage_t);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue