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