mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-02-01 06:00:45 +00:00
Merge branch 'server-bots' into 'next'
Improve bots (resolves #710) Closes #710 See merge request STJr/SRB2!1679
This commit is contained in:
commit
c79c6531e6
3 changed files with 82 additions and 76 deletions
60
src/b_bot.c
60
src/b_bot.c
|
@ -17,6 +17,7 @@
|
|||
#include "p_local.h"
|
||||
#include "b_bot.h"
|
||||
#include "lua_hook.h"
|
||||
#include "i_system.h" // I_BaseTiccmd
|
||||
|
||||
void B_UpdateBotleader(player_t *player)
|
||||
{
|
||||
|
@ -132,17 +133,17 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
// Update catchup_tics
|
||||
if (mem->thinkstate == AI_SPINFOLLOW)
|
||||
{
|
||||
mem-> catchup_tics = 0;
|
||||
mem->catchup_tics = 0;
|
||||
}
|
||||
else if (dist > followmax || zdist > comfortheight || stalled)
|
||||
{
|
||||
mem-> catchup_tics = min(mem-> catchup_tics + 2, 70);
|
||||
if (mem-> catchup_tics >= 70)
|
||||
mem->catchup_tics = min(mem->catchup_tics + 2, 70);
|
||||
if (mem->catchup_tics >= 70)
|
||||
mem->thinkstate = AI_CATCHUP;
|
||||
}
|
||||
else
|
||||
{
|
||||
mem-> catchup_tics = max(mem-> catchup_tics - 1, 0);
|
||||
mem->catchup_tics = max(mem->catchup_tics - 1, 0);
|
||||
if (mem->thinkstate == AI_CATCHUP)
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
}
|
||||
|
@ -317,7 +318,6 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
{
|
||||
// Copy inputs
|
||||
cmd->angleturn = (sonic->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||
bot->drawangle = ang;
|
||||
cmd->forwardmove = 8 * pcmd->forwardmove / 10;
|
||||
cmd->sidemove = 8 * pcmd->sidemove / 10;
|
||||
}
|
||||
|
@ -344,7 +344,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)
|
||||
&& ((zdist > 32*scale && player->pflags & PF_JUMPED) // Following
|
||||
|| (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
|
||||
|| (bot->pflags & PF_SPINNING && !(bot->pflags & PF_JUMPED)))) // Spinning
|
||||
jump = true;
|
||||
|
@ -371,6 +371,8 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
|
||||
void B_BuildTiccmd(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver
|
||||
|
||||
// Can't build a ticcmd if we aren't spawned...
|
||||
if (!player->mo)
|
||||
return;
|
||||
|
@ -390,7 +392,7 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
return;
|
||||
|
||||
// Make sure we have a valid main character to follow
|
||||
B_UpdateBotleader(player);
|
||||
B_UpdateBotleader(player);
|
||||
if (!player->botleader)
|
||||
return;
|
||||
|
||||
|
@ -403,7 +405,7 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward
|
|||
{
|
||||
player_t *player = mo->player;
|
||||
// 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;
|
||||
// Turn the virtual keypresses into ticcmd_t.
|
||||
if (twodlevel || mo->flags2 & MF2_TWOD) {
|
||||
|
@ -593,25 +595,43 @@ void B_HandleFlightIndicator(player_t *player)
|
|||
{
|
||||
mobj_t *tails = player->mo;
|
||||
botmem_t *mem = &player->botmem;
|
||||
boolean shouldExist;
|
||||
|
||||
if (!tails)
|
||||
return;
|
||||
|
||||
if (mem->thinkstate == AI_THINKFLY && player->bot == BOT_2PAI && tails->health)
|
||||
shouldExist = (mem->thinkstate == AI_THINKFLY) && 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)
|
||||
{
|
||||
P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
|
||||
if (tails->hnext)
|
||||
{
|
||||
P_SetTarget(&tails->hnext->target, tails);
|
||||
P_SetTarget(&tails->hnext->hprev, tails);
|
||||
P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);
|
||||
}
|
||||
}
|
||||
// if it shouldn't exist, everything is fine
|
||||
if (!shouldExist)
|
||||
return;
|
||||
|
||||
// otherwise, spawn it
|
||||
P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
|
||||
P_SetTarget(&tails->hnext->target, tails);
|
||||
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_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;
|
||||
}
|
||||
|
|
96
src/g_game.c
96
src/g_game.c
|
@ -1547,12 +1547,17 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
cmd->sidemove = (SINT8)(cmd->sidemove + side);
|
||||
|
||||
// Note: Majority of botstuffs are handled in G_Ticker 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
|
||||
cmd->angleturn = (INT16)((localangle - *myangle) >> 16);
|
||||
player->bot = BOT_2PHUMAN; // A player-controlled bot. Returns to AI when it respawns.
|
||||
CV_SetValue(&cv_analog[1], true);
|
||||
}
|
||||
|
||||
if (player->bot == BOT_2PHUMAN)
|
||||
cmd->angleturn = (INT16)((localangle - *myangle) >> 16);
|
||||
|
||||
*myangle += (cmd->angleturn<<16);
|
||||
|
||||
if (controlstyle == CS_LMAOGALOG) {
|
||||
|
@ -2307,66 +2312,45 @@ void G_Ticker(boolean run)
|
|||
|
||||
buf = gametic % BACKUPTICS;
|
||||
|
||||
// Generate ticcmds for bots FIRST, then copy received ticcmds for players.
|
||||
// This emulates pre-2.2.10 behaviour where the bot referenced their leader's last copied ticcmd,
|
||||
// which is desirable because P_PlayerThink can override inputs (e.g. while PF_STASIS is applied or in a waterslide),
|
||||
// and the bot AI needs to respect that.
|
||||
#define ISHUMAN (players[i].bot == BOT_NONE || players[i].bot == BOT_2PHUMAN)
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
if (playeringame[i] && !ISHUMAN) // Less work is required if we're building a bot ticcmd.
|
||||
{
|
||||
INT16 received;
|
||||
// Save last frame's button readings
|
||||
players[i].lastbuttons = players[i].cmd.buttons;
|
||||
players[i].lastbuttons = players[i].cmd.buttons; // Save last frame's button readings
|
||||
B_BuildTiccmd(&players[i], &players[i].cmd);
|
||||
|
||||
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)
|
||||
{
|
||||
received = (players[i].cmd.angleturn & TICCMD_RECEIVED);
|
||||
players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn;
|
||||
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
||||
if (P_ControlStyle(&players[i]) == CS_LMAOGALOG)
|
||||
P_ForceLocalAngle(&players[i], players[i].angleturn << 16);
|
||||
else
|
||||
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.
|
||||
{
|
||||
// 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].angleturn = players[i].cmd.angleturn;
|
||||
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
||||
}
|
||||
players[i].cmd.angleturn |= received;
|
||||
// Since bot TicCmd is pre-determined for both the client and server, the latency and packet checks are simplified.
|
||||
players[i].cmd.latency = 0;
|
||||
P_SetPlayerAngle(&players[i], players[i].cmd.angleturn << 16);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && ISHUMAN)
|
||||
{
|
||||
players[i].lastbuttons = players[i].cmd.buttons; // Save last frame's button readings
|
||||
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
|
||||
|
||||
// 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.
|
||||
players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn;
|
||||
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
||||
if (P_ControlStyle(&players[i]) == CS_LMAOGALOG)
|
||||
P_ForceLocalAngle(&players[i], players[i].angleturn << 16);
|
||||
else
|
||||
players[i].cmd.angleturn = (players[i].angleturn & ~TICCMD_RECEIVED) | (players[i].cmd.angleturn & TICCMD_RECEIVED);
|
||||
}
|
||||
}
|
||||
#undef ISHUMAN
|
||||
|
||||
// do main actions
|
||||
switch (gamestate)
|
||||
{
|
||||
|
|
|
@ -11441,6 +11441,8 @@ void P_PlayerThink(player_t *player)
|
|||
{
|
||||
if (B_CheckRespawn(player))
|
||||
player->playerstate = PST_REBORN;
|
||||
else
|
||||
B_HandleFlightIndicator(player);
|
||||
}
|
||||
if (player->playerstate == PST_REBORN)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue