mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-02-23 20:31:06 +00:00
Improve bot handling:
- bot ticcmds are generated and sent by the server only - fix issue where server would not send all ticcmds to clients if bots were in the game - fix bots still responding to P1's inputs while P1's controls are locked - fix bot player's directional controls being rotated when controlled by P2
This commit is contained in:
parent
6504557393
commit
2794727201
10 changed files with 164 additions and 83 deletions
65
src/b_bot.c
65
src/b_bot.c
|
@ -127,17 +127,17 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
||||||
// Update catchup_tics
|
// Update catchup_tics
|
||||||
if (mem->thinkstate == AI_SPINFOLLOW)
|
if (mem->thinkstate == AI_SPINFOLLOW)
|
||||||
{
|
{
|
||||||
mem-> catchup_tics = 0;
|
mem->catchup_tics = 0;
|
||||||
}
|
}
|
||||||
else if (dist > followmax || zdist > comfortheight || stalled)
|
else if (dist > followmax || zdist > comfortheight || stalled)
|
||||||
{
|
{
|
||||||
mem-> catchup_tics = min(mem-> catchup_tics + 2, 70);
|
mem->catchup_tics = min(mem->catchup_tics + 2, 70);
|
||||||
if (mem-> catchup_tics >= 70)
|
if (mem->catchup_tics >= 70)
|
||||||
mem->thinkstate = AI_CATCHUP;
|
mem->thinkstate = AI_CATCHUP;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mem-> catchup_tics = max(mem-> catchup_tics - 1, 0);
|
mem->catchup_tics = max(mem->catchup_tics - 1, 0);
|
||||||
if (mem->thinkstate == AI_CATCHUP)
|
if (mem->thinkstate == AI_CATCHUP)
|
||||||
mem->thinkstate = AI_FOLLOW;
|
mem->thinkstate = AI_FOLLOW;
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,6 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
||||||
{
|
{
|
||||||
jump = true;
|
jump = true;
|
||||||
mem->thinkstate = AI_FLYSTANDBY;
|
mem->thinkstate = AI_FLYSTANDBY;
|
||||||
bot->pflags |= PF_CANCARRY;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +182,10 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
||||||
&& P_IsObjectOnGround(sonic) && P_IsObjectOnGround(tails)
|
&& P_IsObjectOnGround(sonic) && P_IsObjectOnGround(tails)
|
||||||
&& !(player->pflags & PF_STASIS)
|
&& !(player->pflags & PF_STASIS)
|
||||||
&& bot->charability == CA_FLY)
|
&& bot->charability == CA_FLY)
|
||||||
mem->thinkstate = AI_THINKFLY;
|
{
|
||||||
|
mem->thinkstate = AI_THINKFLY;
|
||||||
|
cmd->flags |= TCF_FLIGHTINDICATOR;
|
||||||
|
}
|
||||||
else if (mem->thinkstate == AI_THINKFLY)
|
else if (mem->thinkstate == AI_THINKFLY)
|
||||||
mem->thinkstate = AI_FOLLOW;
|
mem->thinkstate = AI_FOLLOW;
|
||||||
|
|
||||||
|
@ -204,6 +206,8 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
||||||
// Abort if the player moves away or spins
|
// Abort if the player moves away or spins
|
||||||
if (dist > followthres || player->dashspeed)
|
if (dist > followthres || player->dashspeed)
|
||||||
mem->thinkstate = AI_FOLLOW;
|
mem->thinkstate = AI_FOLLOW;
|
||||||
|
else
|
||||||
|
cmd->flags |= TCF_SETCARRY;
|
||||||
}
|
}
|
||||||
// Read player inputs while carrying
|
// Read player inputs while carrying
|
||||||
else if (mem->thinkstate == AI_FLYCARRY)
|
else if (mem->thinkstate == AI_FLYCARRY)
|
||||||
|
@ -312,7 +316,6 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
||||||
{
|
{
|
||||||
// Copy inputs
|
// Copy inputs
|
||||||
cmd->angleturn = (sonic->angle) >> 16; // NOT FRACBITS DAMNIT
|
cmd->angleturn = (sonic->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||||
bot->drawangle = ang;
|
|
||||||
cmd->forwardmove = 8 * pcmd->forwardmove / 10;
|
cmd->forwardmove = 8 * pcmd->forwardmove / 10;
|
||||||
cmd->sidemove = 8 * pcmd->sidemove / 10;
|
cmd->sidemove = 8 * pcmd->sidemove / 10;
|
||||||
}
|
}
|
||||||
|
@ -339,7 +342,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
||||||
else if (!jump_last && !(bot->pflags & PF_JUMPED) //&& !(player->pflags & PF_SPINNING)
|
else if (!jump_last && !(bot->pflags & PF_JUMPED) //&& !(player->pflags & PF_SPINNING)
|
||||||
&& ((zdist > 32*scale && player->pflags & PF_JUMPED) // Following
|
&& ((zdist > 32*scale && player->pflags & PF_JUMPED) // Following
|
||||||
|| (zdist > 64*scale && mem->thinkstate == AI_CATCHUP) // Vertical catch-up
|
|| (zdist > 64*scale && mem->thinkstate == AI_CATCHUP) // Vertical catch-up
|
||||||
|| (stalled && mem-> catchup_tics > 20 && bot->powers[pw_carry] == CR_NONE)
|
|| (stalled && mem->catchup_tics > 20 && bot->powers[pw_carry] == CR_NONE)
|
||||||
//|| (bmom < scale>>3 && dist > followthres && !(bot->powers[pw_carry])) // Stopped & not in carry state
|
//|| (bmom < scale>>3 && dist > followthres && !(bot->powers[pw_carry])) // Stopped & not in carry state
|
||||||
|| (bot->pflags & PF_SPINNING && !(bot->pflags & PF_JUMPED)))) // Spinning
|
|| (bot->pflags & PF_SPINNING && !(bot->pflags & PF_JUMPED)))) // Spinning
|
||||||
jump = true;
|
jump = true;
|
||||||
|
@ -385,7 +388,6 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Make sure we have a valid main character to follow
|
// Make sure we have a valid main character to follow
|
||||||
B_UpdateBotleader(player);
|
|
||||||
if (!player->botleader)
|
if (!player->botleader)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -398,7 +400,7 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward
|
||||||
{
|
{
|
||||||
player_t *player = mo->player;
|
player_t *player = mo->player;
|
||||||
// don't try to do stuff if your sonic is in a minecart or something
|
// don't try to do stuff if your sonic is in a minecart or something
|
||||||
if (&player->botleader && player->botleader->powers[pw_carry] && player->botleader->powers[pw_carry] != CR_PLAYER)
|
if (player->botleader && player->botleader->powers[pw_carry] && player->botleader->powers[pw_carry] != CR_PLAYER)
|
||||||
return;
|
return;
|
||||||
// Turn the virtual keypresses into ticcmd_t.
|
// Turn the virtual keypresses into ticcmd_t.
|
||||||
if (twodlevel || mo->flags2 & MF2_TWOD) {
|
if (twodlevel || mo->flags2 & MF2_TWOD) {
|
||||||
|
@ -587,26 +589,43 @@ void B_RespawnBot(INT32 playernum)
|
||||||
void B_HandleFlightIndicator(player_t *player)
|
void B_HandleFlightIndicator(player_t *player)
|
||||||
{
|
{
|
||||||
mobj_t *tails = player->mo;
|
mobj_t *tails = player->mo;
|
||||||
botmem_t *mem = &player->botmem;
|
boolean shouldExist;
|
||||||
|
|
||||||
if (!tails)
|
if (!tails)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mem->thinkstate == AI_THINKFLY && player->bot == BOT_2PAI && tails->health)
|
shouldExist = (player->cmd.flags & TCF_FLIGHTINDICATOR) && player->botleader
|
||||||
|
&& player->bot == BOT_2PAI && player->playerstate == PST_LIVE;
|
||||||
|
|
||||||
|
// check whether the indicator doesn't exist
|
||||||
|
if (P_MobjWasRemoved(tails->hnext))
|
||||||
{
|
{
|
||||||
if (!tails->hnext)
|
// if it shouldn't exist, everything is fine
|
||||||
{
|
if (!shouldExist)
|
||||||
P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
|
return;
|
||||||
if (tails->hnext)
|
|
||||||
{
|
// otherwise, spawn it
|
||||||
P_SetTarget(&tails->hnext->target, tails);
|
P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
|
||||||
P_SetTarget(&tails->hnext->hprev, tails);
|
P_SetTarget(&tails->hnext->target, tails);
|
||||||
P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);
|
P_SetTarget(&tails->hnext->hprev, tails);
|
||||||
}
|
P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (tails->hnext && tails->hnext->type == MT_OVERLAY && tails->hnext->state == states+S_FLIGHTINDICATOR)
|
|
||||||
|
// if the mobj isn't a flight indicator, let's not mess with it
|
||||||
|
if (tails->hnext->type != MT_OVERLAY || (tails->hnext->state != states+S_FLIGHTINDICATOR))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// if it shouldn't exist, remove it
|
||||||
|
if (!shouldExist)
|
||||||
{
|
{
|
||||||
P_RemoveMobj(tails->hnext);
|
P_RemoveMobj(tails->hnext);
|
||||||
P_SetTarget(&tails->hnext, NULL);
|
P_SetTarget(&tails->hnext, NULL);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// otherwise, update its visibility
|
||||||
|
if (P_IsLocalPlayer(player->botleader))
|
||||||
|
tails->hnext->flags2 &= ~MF2_DONTDRAW;
|
||||||
|
else
|
||||||
|
tails->hnext->flags2 |= MF2_DONTDRAW;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "lua_libs.h"
|
#include "lua_libs.h"
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
#include "m_perfstats.h"
|
#include "m_perfstats.h"
|
||||||
|
#include "b_bot.h" // B_BuildTiccmd
|
||||||
|
|
||||||
#ifndef NONET
|
#ifndef NONET
|
||||||
// cl loading screen
|
// cl loading screen
|
||||||
|
@ -5166,6 +5167,25 @@ static void Local_Maketic(INT32 realtics)
|
||||||
localcmds2.angleturn |= TICCMD_RECEIVED;
|
localcmds2.angleturn |= TICCMD_RECEIVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SV_MakeBotTics(void)
|
||||||
|
{
|
||||||
|
UINT8 i;
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (!playeringame[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (players[i].bot == BOT_2PAI || players[i].bot == BOT_MPAI)
|
||||||
|
{
|
||||||
|
ticcmd_t *cmd = &netcmds[maketic % BACKUPTICS][i];
|
||||||
|
|
||||||
|
G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver
|
||||||
|
B_BuildTiccmd(&players[i], cmd);
|
||||||
|
cmd->angleturn |= TICCMD_RECEIVED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// create missed tic
|
// create missed tic
|
||||||
static void SV_Maketic(void)
|
static void SV_Maketic(void)
|
||||||
{
|
{
|
||||||
|
@ -5409,6 +5429,15 @@ void NetUpdate(void)
|
||||||
if (client)
|
if (client)
|
||||||
maketic = neededtic;
|
maketic = neededtic;
|
||||||
|
|
||||||
|
// update players' lastbuttons so they can be used in ticcmd generation
|
||||||
|
for (i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (!playeringame[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
players[i].lastbuttons = players[i].cmd.buttons;
|
||||||
|
}
|
||||||
|
|
||||||
Local_Maketic(realtics); // make local tic, and call menu?
|
Local_Maketic(realtics); // make local tic, and call menu?
|
||||||
|
|
||||||
if (server)
|
if (server)
|
||||||
|
@ -5452,6 +5481,8 @@ void NetUpdate(void)
|
||||||
Net_ConnectionTimeout(i);
|
Net_ConnectionTimeout(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SV_MakeBotTics();
|
||||||
|
|
||||||
// Don't erase tics not acknowledged
|
// Don't erase tics not acknowledged
|
||||||
counts = realtics;
|
counts = realtics;
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,14 @@ typedef enum
|
||||||
BT_CUSTOM3 = 1<<15,
|
BT_CUSTOM3 = 1<<15,
|
||||||
} buttoncode_t;
|
} buttoncode_t;
|
||||||
|
|
||||||
|
// ticcmd flags
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TCF_FLIGHTINDICATOR = 1 << 0, // show flight indicator
|
||||||
|
TCF_SETCARRY = 1 << 1, // set PF_CARRY upon activating flight
|
||||||
|
// free up to and including 1 << 7
|
||||||
|
} ticcmdflag_t;
|
||||||
|
|
||||||
// The data sampled per tick (single player)
|
// The data sampled per tick (single player)
|
||||||
// and transmitted to other peers (multiplayer).
|
// and transmitted to other peers (multiplayer).
|
||||||
// Mainly movements/button commands per game tick,
|
// Mainly movements/button commands per game tick,
|
||||||
|
@ -66,6 +74,7 @@ typedef struct
|
||||||
INT16 aiming; // vertical aiming, see G_BuildTicCmd
|
INT16 aiming; // vertical aiming, see G_BuildTicCmd
|
||||||
UINT16 buttons;
|
UINT16 buttons;
|
||||||
UINT8 latency; // Netgames: how many tics ago was this ticcmd generated from this player's end?
|
UINT8 latency; // Netgames: how many tics ago was this ticcmd generated from this player's end?
|
||||||
|
UINT8 flags; // miscellaneous info
|
||||||
} ATTRPACK ticcmd_t;
|
} ATTRPACK ticcmd_t;
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
|
|
@ -5333,6 +5333,11 @@ struct int_const_s const INT_CONST[] = {
|
||||||
{"BT_CUSTOM2",BT_CUSTOM2}, // Lua customizable
|
{"BT_CUSTOM2",BT_CUSTOM2}, // Lua customizable
|
||||||
{"BT_CUSTOM3",BT_CUSTOM3}, // Lua customizable
|
{"BT_CUSTOM3",BT_CUSTOM3}, // Lua customizable
|
||||||
|
|
||||||
|
// Ticcmd flags (ticcmdflag_t)
|
||||||
|
// (maybe move these into their own table in the future but I cba when there's only 2 LOL)
|
||||||
|
{"TCF_FLIGHTINDICATOR", TCF_FLIGHTINDICATOR},
|
||||||
|
{"TCF_SETCARRY", TCF_SETCARRY},
|
||||||
|
|
||||||
// Lua command registration flags
|
// Lua command registration flags
|
||||||
{"COM_ADMIN",COM_ADMIN},
|
{"COM_ADMIN",COM_ADMIN},
|
||||||
{"COM_SPLITSCREEN",COM_SPLITSCREEN},
|
{"COM_SPLITSCREEN",COM_SPLITSCREEN},
|
||||||
|
|
12
src/g_demo.c
12
src/g_demo.c
|
@ -110,6 +110,7 @@ demoghost *ghosts = NULL;
|
||||||
#define ZT_BUTTONS 0x08
|
#define ZT_BUTTONS 0x08
|
||||||
#define ZT_AIMING 0x10
|
#define ZT_AIMING 0x10
|
||||||
#define ZT_LATENCY 0x20
|
#define ZT_LATENCY 0x20
|
||||||
|
#define ZT_FLAGS 0x40
|
||||||
#define DEMOMARKER 0x80 // demoend
|
#define DEMOMARKER 0x80 // demoend
|
||||||
#define METALDEATH 0x44
|
#define METALDEATH 0x44
|
||||||
#define METALSNICE 0x69
|
#define METALSNICE 0x69
|
||||||
|
@ -184,6 +185,8 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
oldcmd.aiming = READINT16(demo_p);
|
oldcmd.aiming = READINT16(demo_p);
|
||||||
if (ziptic & ZT_LATENCY)
|
if (ziptic & ZT_LATENCY)
|
||||||
oldcmd.latency = READUINT8(demo_p);
|
oldcmd.latency = READUINT8(demo_p);
|
||||||
|
if (ziptic & ZT_FLAGS)
|
||||||
|
oldcmd.flags = READUINT8(demo_p);
|
||||||
|
|
||||||
G_CopyTiccmd(cmd, &oldcmd, 1);
|
G_CopyTiccmd(cmd, &oldcmd, 1);
|
||||||
players[playernum].angleturn = cmd->angleturn;
|
players[playernum].angleturn = cmd->angleturn;
|
||||||
|
@ -248,6 +251,13 @@ void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|
||||||
ziptic |= ZT_LATENCY;
|
ziptic |= ZT_LATENCY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd->flags != oldcmd.flags)
|
||||||
|
{
|
||||||
|
WRITEUINT8(demo_p, cmd->flags);
|
||||||
|
oldcmd.flags = cmd->flags;
|
||||||
|
ziptic |= ZT_FLAGS;
|
||||||
|
}
|
||||||
|
|
||||||
*ziptic_p = ziptic;
|
*ziptic_p = ziptic;
|
||||||
|
|
||||||
// attention here for the ticcmd size!
|
// attention here for the ticcmd size!
|
||||||
|
@ -691,6 +701,8 @@ void G_GhostTicker(void)
|
||||||
g->p += 2;
|
g->p += 2;
|
||||||
if (ziptic & ZT_LATENCY)
|
if (ziptic & ZT_LATENCY)
|
||||||
g->p++;
|
g->p++;
|
||||||
|
if (ziptic & ZT_FLAGS)
|
||||||
|
g->p++;
|
||||||
|
|
||||||
// Grab ghost data.
|
// Grab ghost data.
|
||||||
ziptic = READUINT8(g->p);
|
ziptic = READUINT8(g->p);
|
||||||
|
|
63
src/g_game.c
63
src/g_game.c
|
@ -1546,12 +1546,17 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
||||||
cmd->forwardmove = (SINT8)(cmd->forwardmove + forward);
|
cmd->forwardmove = (SINT8)(cmd->forwardmove + forward);
|
||||||
cmd->sidemove = (SINT8)(cmd->sidemove + side);
|
cmd->sidemove = (SINT8)(cmd->sidemove + side);
|
||||||
|
|
||||||
// Note: Majority of botstuffs are handled in G_Ticker now.
|
// Note: Majority of botstuffs are handled in G_Ticker and NetUpdate now.
|
||||||
if (player->bot == BOT_2PHUMAN) //Player-controlled bot
|
if (player->bot == BOT_2PAI
|
||||||
|
&& !player->powers[pw_tailsfly]
|
||||||
|
&& (cmd->forwardmove || cmd->sidemove || cmd->buttons))
|
||||||
{
|
{
|
||||||
// Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Strafe
|
player->bot = BOT_2PHUMAN; // A player-controlled bot. Returns to AI when it respawns.
|
||||||
cmd->angleturn = (INT16)((localangle - *myangle) >> 16);
|
CV_SetValue(&cv_analog[1], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (player->bot == BOT_2PHUMAN)
|
||||||
|
cmd->angleturn = (localangle - *myangle) >> 16;
|
||||||
|
|
||||||
*myangle += (cmd->angleturn<<16);
|
*myangle += (cmd->angleturn<<16);
|
||||||
|
|
||||||
|
@ -1705,6 +1710,7 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
|
||||||
dest[i].aiming = (INT16)SHORT(src[i].aiming);
|
dest[i].aiming = (INT16)SHORT(src[i].aiming);
|
||||||
dest[i].buttons = (UINT16)SHORT(src[i].buttons);
|
dest[i].buttons = (UINT16)SHORT(src[i].buttons);
|
||||||
dest[i].latency = src[i].latency;
|
dest[i].latency = src[i].latency;
|
||||||
|
dest[i].flags = src[i].flags;
|
||||||
}
|
}
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
@ -2312,57 +2318,32 @@ void G_Ticker(boolean run)
|
||||||
if (playeringame[i])
|
if (playeringame[i])
|
||||||
{
|
{
|
||||||
INT16 received;
|
INT16 received;
|
||||||
// Save last frame's button readings
|
|
||||||
players[i].lastbuttons = players[i].cmd.buttons;
|
|
||||||
|
|
||||||
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
|
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
|
||||||
// Bot ticcmd handling
|
|
||||||
// Yes, ordinarily this would be handled in G_BuildTiccmd...
|
|
||||||
// ...however, bot players won't have a corresponding consoleplayer or splitscreen player 2 to send that information.
|
|
||||||
// Therefore, this has to be done after ticcmd sends are received.
|
|
||||||
if (players[i].bot == BOT_2PAI) { // Tailsbot for P2
|
|
||||||
if (!players[i].powers[pw_tailsfly] && (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons))
|
|
||||||
{
|
|
||||||
players[i].bot = BOT_2PHUMAN; // A player-controlled bot. Returns to AI when it respawns.
|
|
||||||
CV_SetValue(&cv_analog[1], true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
B_BuildTiccmd(&players[i], &players[i].cmd);
|
|
||||||
}
|
|
||||||
B_HandleFlightIndicator(&players[i]);
|
|
||||||
}
|
|
||||||
else if (players[i].bot == BOT_MPAI) {
|
|
||||||
B_BuildTiccmd(&players[i], &players[i].cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do angle adjustments.
|
|
||||||
if (players[i].bot == BOT_NONE || players[i].bot == BOT_2PHUMAN)
|
if (players[i].bot == BOT_NONE || players[i].bot == BOT_2PHUMAN)
|
||||||
{
|
{
|
||||||
|
// Use the leveltime sent in the player's ticcmd to determine control lag
|
||||||
|
players[i].cmd.latency = min(((leveltime & 0xFF) - players[i].cmd.latency) & 0xFF, MAXPREDICTTICS-1);
|
||||||
|
|
||||||
|
// Do angle adjustments.
|
||||||
received = (players[i].cmd.angleturn & TICCMD_RECEIVED);
|
received = (players[i].cmd.angleturn & TICCMD_RECEIVED);
|
||||||
|
|
||||||
players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn;
|
players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn;
|
||||||
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
||||||
if (P_ControlStyle(&players[i]) == CS_LMAOGALOG)
|
if (P_ControlStyle(&players[i]) == CS_LMAOGALOG)
|
||||||
P_ForceLocalAngle(&players[i], players[i].angleturn << 16);
|
P_ForceLocalAngle(&players[i], players[i].angleturn << 16);
|
||||||
else
|
else
|
||||||
players[i].cmd.angleturn = players[i].angleturn;
|
players[i].cmd.angleturn = players[i].angleturn;
|
||||||
if (P_ControlStyle(&players[i]) == CS_LMAOGALOG)
|
|
||||||
P_ForceLocalAngle(&players[i], players[i].angleturn << 16);
|
|
||||||
else
|
|
||||||
players[i].cmd.angleturn = players[i].angleturn;
|
|
||||||
|
|
||||||
players[i].cmd.angleturn &= ~TICCMD_RECEIVED;
|
|
||||||
// Use the leveltime sent in the player's ticcmd to determine control lag
|
|
||||||
players[i].cmd.latency = min(((leveltime & 0xFF) - players[i].cmd.latency) & 0xFF, MAXPREDICTTICS-1);
|
|
||||||
}
|
}
|
||||||
else // Less work is required if we're building a bot ticcmd.
|
else // Less work is required if we're building a bot ticcmd.
|
||||||
{
|
{
|
||||||
// Since bot TicCmd is pre-determined for both the client and server, the latency and packet checks are simplified.
|
// Since bot TicCmd is pre-determined for both the client and server, the latency and packet checks are simplified.
|
||||||
received = 1;
|
players[i].cmd.latency = 0;
|
||||||
players[i].cmd.latency = 0;
|
P_SetPlayerAngle(&players[i], players[i].cmd.angleturn << 16);
|
||||||
players[i].angleturn = players[i].cmd.angleturn;
|
|
||||||
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
players[i].cmd.angleturn &= ~TICCMD_RECEIVED;
|
||||||
players[i].cmd.angleturn |= received;
|
players[i].cmd.angleturn |= received;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "b_bot.h" // B_UpdateBotleader
|
#include "b_bot.h" // B_UpdateBotleader
|
||||||
#include "d_clisrv.h" // CL_RemovePlayer
|
#include "d_clisrv.h" // CL_RemovePlayer
|
||||||
#include "i_system.h" // I_GetPreciseTime, I_PreciseToMicros
|
#include "i_system.h" // I_GetPreciseTime, I_PreciseToMicros
|
||||||
|
#include "i_net.h" // doomcom
|
||||||
|
|
||||||
#include "lua_script.h"
|
#include "lua_script.h"
|
||||||
#include "lua_libs.h"
|
#include "lua_libs.h"
|
||||||
|
@ -3463,6 +3464,8 @@ static int lib_gAddPlayer(lua_State *L)
|
||||||
|
|
||||||
playeringame[newplayernum] = true;
|
playeringame[newplayernum] = true;
|
||||||
G_AddPlayer(newplayernum);
|
G_AddPlayer(newplayernum);
|
||||||
|
if (newplayernum+1 > doomcom->numslots)
|
||||||
|
doomcom->numslots = (INT16)(newplayernum+1);
|
||||||
newplayer = &players[newplayernum];
|
newplayer = &players[newplayernum];
|
||||||
|
|
||||||
newplayer->jointime = 0;
|
newplayer->jointime = 0;
|
||||||
|
|
|
@ -833,6 +833,8 @@ static int ticcmd_get(lua_State *L)
|
||||||
lua_pushinteger(L, cmd->buttons);
|
lua_pushinteger(L, cmd->buttons);
|
||||||
else if (fastcmp(field,"latency"))
|
else if (fastcmp(field,"latency"))
|
||||||
lua_pushinteger(L, cmd->latency);
|
lua_pushinteger(L, cmd->latency);
|
||||||
|
else if (fastcmp(field,"flags"))
|
||||||
|
lua_pushinteger(L, cmd->flags);
|
||||||
else
|
else
|
||||||
return NOFIELD;
|
return NOFIELD;
|
||||||
|
|
||||||
|
@ -861,6 +863,8 @@ static int ticcmd_set(lua_State *L)
|
||||||
cmd->buttons = (UINT16)luaL_checkinteger(L, 3);
|
cmd->buttons = (UINT16)luaL_checkinteger(L, 3);
|
||||||
else if (fastcmp(field,"latency"))
|
else if (fastcmp(field,"latency"))
|
||||||
return NOSET;
|
return NOSET;
|
||||||
|
else if (fastcmp(field,"flags"))
|
||||||
|
cmd->buttons = (UINT8)luaL_checkinteger(L, 3);
|
||||||
else
|
else
|
||||||
return NOFIELD;
|
return NOFIELD;
|
||||||
|
|
||||||
|
|
|
@ -51,14 +51,15 @@ UINT8 *save_p;
|
||||||
// than an UINT16
|
// than an UINT16
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
// RFLAGPOINT = 0x01,
|
// RFLAGPOINT = 0x001,
|
||||||
// BFLAGPOINT = 0x02,
|
// BFLAGPOINT = 0x002,
|
||||||
CAPSULE = 0x04,
|
CAPSULE = 0x004,
|
||||||
AWAYVIEW = 0x08,
|
AWAYVIEW = 0x008,
|
||||||
FIRSTAXIS = 0x10,
|
FIRSTAXIS = 0x010,
|
||||||
SECONDAXIS = 0x20,
|
SECONDAXIS = 0x020,
|
||||||
FOLLOW = 0x40,
|
FOLLOW = 0x040,
|
||||||
DRONE = 0x80,
|
DRONE = 0x080,
|
||||||
|
BOTLEADER = 0x100,
|
||||||
} player_saveflags;
|
} player_saveflags;
|
||||||
|
|
||||||
static inline void P_ArchivePlayer(void)
|
static inline void P_ArchivePlayer(void)
|
||||||
|
@ -197,10 +198,11 @@ static void P_NetArchivePlayers(void)
|
||||||
// Bots //
|
// Bots //
|
||||||
//////////
|
//////////
|
||||||
WRITEUINT8(save_p, players[i].bot);
|
WRITEUINT8(save_p, players[i].bot);
|
||||||
WRITEUINT8(save_p, players[i].botmem.lastForward);
|
// We no longer need to sync these since ticcmds are generated only by the server
|
||||||
WRITEUINT8(save_p, players[i].botmem.lastBlocked);
|
//WRITEUINT8(save_p, players[i].botmem.lastForward);
|
||||||
WRITEUINT8(save_p, players[i].botmem.catchup_tics);
|
//WRITEUINT8(save_p, players[i].botmem.lastBlocked);
|
||||||
WRITEUINT8(save_p, players[i].botmem.thinkstate);
|
//WRITEUINT8(save_p, players[i].botmem.catchup_tics);
|
||||||
|
//WRITEUINT8(save_p, players[i].botmem.thinkstate);
|
||||||
WRITEUINT8(save_p, players[i].removing);
|
WRITEUINT8(save_p, players[i].removing);
|
||||||
|
|
||||||
WRITEUINT8(save_p, players[i].blocked);
|
WRITEUINT8(save_p, players[i].blocked);
|
||||||
|
@ -293,6 +295,9 @@ static void P_NetArchivePlayers(void)
|
||||||
if (players[i].drone)
|
if (players[i].drone)
|
||||||
flags |= DRONE;
|
flags |= DRONE;
|
||||||
|
|
||||||
|
if (players[i].botleader)
|
||||||
|
flags |= BOTLEADER;
|
||||||
|
|
||||||
WRITEINT16(save_p, players[i].lastsidehit);
|
WRITEINT16(save_p, players[i].lastsidehit);
|
||||||
WRITEINT16(save_p, players[i].lastlinehit);
|
WRITEINT16(save_p, players[i].lastlinehit);
|
||||||
|
|
||||||
|
@ -325,6 +330,9 @@ static void P_NetArchivePlayers(void)
|
||||||
if (flags & DRONE)
|
if (flags & DRONE)
|
||||||
WRITEUINT32(save_p, players[i].drone->mobjnum);
|
WRITEUINT32(save_p, players[i].drone->mobjnum);
|
||||||
|
|
||||||
|
if (flags & BOTLEADER)
|
||||||
|
WRITEUINT8(save_p, (UINT8)(players[i].botleader - players));
|
||||||
|
|
||||||
WRITEFIXED(save_p, players[i].camerascale);
|
WRITEFIXED(save_p, players[i].camerascale);
|
||||||
WRITEFIXED(save_p, players[i].shieldscale);
|
WRITEFIXED(save_p, players[i].shieldscale);
|
||||||
|
|
||||||
|
@ -425,10 +433,10 @@ static void P_NetUnArchivePlayers(void)
|
||||||
//////////
|
//////////
|
||||||
players[i].bot = READUINT8(save_p);
|
players[i].bot = READUINT8(save_p);
|
||||||
|
|
||||||
players[i].botmem.lastForward = READUINT8(save_p);
|
//players[i].botmem.lastForward = READUINT8(save_p);
|
||||||
players[i].botmem.lastBlocked = READUINT8(save_p);
|
//players[i].botmem.lastBlocked = READUINT8(save_p);
|
||||||
players[i].botmem.catchup_tics = READUINT8(save_p);
|
//players[i].botmem.catchup_tics = READUINT8(save_p);
|
||||||
players[i].botmem.thinkstate = READUINT8(save_p);
|
//players[i].botmem.thinkstate = READUINT8(save_p);
|
||||||
players[i].removing = READUINT8(save_p);
|
players[i].removing = READUINT8(save_p);
|
||||||
|
|
||||||
players[i].blocked = READUINT8(save_p);
|
players[i].blocked = READUINT8(save_p);
|
||||||
|
@ -535,6 +543,9 @@ static void P_NetUnArchivePlayers(void)
|
||||||
if (flags & DRONE)
|
if (flags & DRONE)
|
||||||
players[i].drone = (mobj_t *)(size_t)READUINT32(save_p);
|
players[i].drone = (mobj_t *)(size_t)READUINT32(save_p);
|
||||||
|
|
||||||
|
if (flags & BOTLEADER)
|
||||||
|
players[i].botleader = &players[READUINT8(save_p)];
|
||||||
|
|
||||||
players[i].camerascale = READFIXED(save_p);
|
players[i].camerascale = READFIXED(save_p);
|
||||||
players[i].shieldscale = READFIXED(save_p);
|
players[i].shieldscale = READFIXED(save_p);
|
||||||
|
|
||||||
|
|
12
src/p_user.c
12
src/p_user.c
|
@ -5349,10 +5349,10 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
|
||||||
player->powers[pw_tailsfly] = tailsflytics + 1; // Set the fly timer
|
player->powers[pw_tailsfly] = tailsflytics + 1; // Set the fly timer
|
||||||
|
|
||||||
player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_STARTDASH);
|
player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_STARTDASH);
|
||||||
if (player->bot == BOT_2PAI)
|
if ((player->bot != BOT_2PAI) || (cmd->flags & TCF_SETCARRY))
|
||||||
player->pflags |= PF_THOKKED;
|
|
||||||
else
|
|
||||||
player->pflags |= (PF_THOKKED|PF_CANCARRY);
|
player->pflags |= (PF_THOKKED|PF_CANCARRY);
|
||||||
|
else
|
||||||
|
player->pflags |= PF_THOKKED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CA_GLIDEANDCLIMB:
|
case CA_GLIDEANDCLIMB:
|
||||||
|
@ -11450,6 +11450,12 @@ void P_PlayerThink(player_t *player)
|
||||||
{
|
{
|
||||||
if (B_CheckRespawn(player))
|
if (B_CheckRespawn(player))
|
||||||
player->playerstate = PST_REBORN;
|
player->playerstate = PST_REBORN;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (player->bot == BOT_2PAI)
|
||||||
|
B_UpdateBotleader(player);
|
||||||
|
B_HandleFlightIndicator(player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (player->playerstate == PST_REBORN)
|
if (player->playerstate == PST_REBORN)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue