diff --git a/src/b_bot.cpp b/src/b_bot.cpp index dc6f2cdc4..d2acdcab6 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -24,12 +24,14 @@ IMPLEMENT_POINTY_CLASS(DBot) END_POINTERS DBot::DBot () +: DThinker(STAT_BOT) { Clear (); } void DBot::Clear () { + player = NULL; angle = 0; dest = NULL; prev = NULL; @@ -64,6 +66,10 @@ void DBot::Serialize (FArchive &arc) arc << savedyaw << savedpitch; } + else if (SaveVersion >= 4516) + { + arc << player; + } arc << angle << dest @@ -88,6 +94,22 @@ void DBot::Serialize (FArchive &arc) << oldy; } +void DBot::Tick () +{ + Super::Tick (); + + if (player->mo == NULL || bglobal.freeze) + { + return; + } + + BotThinkCycles.Clock(); + bglobal.m_Thinking = true; + bglobal.Think (player->mo, &netcmds[player - players][((gametic + 1)/ticdup)%BACKUPTICS]); + bglobal.m_Thinking = false; + BotThinkCycles.Unclock(); +} + CVAR (Int, bot_next_color, 11, 0) CVAR (Bool, bot_observer, false, 0) diff --git a/src/b_bot.h b/src/b_bot.h index 1862faee5..7740e5e00 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -14,6 +14,7 @@ #include "d_ticcmd.h" #include "r_defs.h" #include "a_pickups.h" +#include "stats.h" #define FORWARDWALK 0x1900 #define FORWARDRUN 0x3200 @@ -89,20 +90,22 @@ public: void ClearPlayer (int playernum, bool keepTeam); //(B_Game.c) - void Main (int buf); + void Main (); void Init (); void End(); bool SpawnBot (const char *name, int color = NOCOLOR); - bool LoadBots (); - void ForgetBots (); void TryAddBot (BYTE **stream, int player); void RemoveAllBots (bool fromlist); - void DestroyAllBots (); + bool LoadBots (); + void ForgetBots (); //(B_Func.c) bool Check_LOS (AActor *mobj1, AActor *mobj2, angle_t vangle); + void StartTravel (); + void FinishTravel (); //(B_Think.c) + void Think (AActor *actor, ticcmd_t *cmd); void WhatToGet (AActor *actor, AActor *item); //(B_move.c) @@ -144,7 +147,6 @@ private: bool SafeCheckPosition (AActor *actor, fixed_t x, fixed_t y, FCheckPosition &tm); //(B_Think.c) - void Think (AActor *actor, ticcmd_t *cmd); void ThinkForMove (AActor *actor, ticcmd_t *cmd); void Set_enemy (AActor *actor); @@ -155,16 +157,18 @@ protected: bool observer; //Consoleplayer is observer. }; -class DBot : public DObject +class DBot : public DThinker { - DECLARE_CLASS(DBot,DObject) + DECLARE_CLASS(DBot,DThinker) HAS_OBJECT_POINTERS public: DBot (); void Clear (); void Serialize (FArchive &arc); + void Tick (); + player_t *player; angle_t angle; // The wanted angle that the bot try to get every tic. // (used to get a smooth view movement) TObjPtr dest; // Move Destination. @@ -205,6 +209,7 @@ public: //Externs extern FCajunMaster bglobal; +extern cycle_t BotThinkCycles, BotSupportCycles; EXTERN_CVAR (Float, bot_flag_return_time) EXTERN_CVAR (Int, bot_next_color) diff --git a/src/b_func.cpp b/src/b_func.cpp index 0303de8c6..349155a81 100644 --- a/src/b_func.cpp +++ b/src/b_func.cpp @@ -402,7 +402,7 @@ AActor *FCajunMaster::Find_enemy (AActor *bot) && bot != client->mo) { if (Check_LOS (bot, client->mo, vangle)) //Here's a strange one, when bot is standing still, the P_CheckSight within Check_LOS almost always returns false. tought it should be the same checksight as below but.. (below works) something must be fuckin wierd screded up. - //if(P_CheckSight( bot, players[count].mo)) + //if(P_CheckSight(bot, players[count].mo)) { temp = P_AproxDistance (client->mo->x - bot->x, client->mo->y - bot->y); @@ -552,3 +552,25 @@ bool FCajunMaster::SafeCheckPosition (AActor *actor, fixed_t x, fixed_t y, FChec actor->flags = savedFlags; return res; } + +void FCajunMaster::StartTravel () +{ + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (players[i].Bot != NULL) + { + players[i].Bot->ChangeStatNum (STAT_TRAVELLING); + } + } +} + +void FCajunMaster::FinishTravel () +{ + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (players[i].Bot != NULL) + { + players[i].Bot->ChangeStatNum (STAT_BOT); + } + } +} diff --git a/src/b_game.cpp b/src/b_game.cpp index 853ba7f23..44aff03fa 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -94,71 +94,46 @@ FCajunMaster::~FCajunMaster() ForgetBots(); } -//This function is called every tick (from g_game.c), -//send bots into thinking (+more). -void FCajunMaster::Main (int buf) +//This function is called every tick (from g_game.c). +void FCajunMaster::Main () { - int i; - BotThinkCycles.Reset(); - if (demoplayback) + if (demoplayback || gamestate != GS_LEVEL || consoleplayer != Net_Arbitrator) return; - if (gamestate != GS_LEVEL) - return; - - m_Thinking = true; - - //Think for bots. - if (botnum) + //Add new bots? + if (wanted_botnum > botnum && !freeze) { - BotThinkCycles.Clock(); - for (i = 0; i < MAXPLAYERS; i++) + if (t_join == ((wanted_botnum - botnum) * SPAWN_DELAY)) { - if (playeringame[i] && players[i].mo && !freeze && players[i].Bot != NULL) - Think (players[i].mo, &netcmds[i][buf]); + if (!SpawnBot (getspawned[spawn_tries])) + wanted_botnum--; + spawn_tries++; } - BotThinkCycles.Unclock(); + + t_join--; } - if (consoleplayer == Net_Arbitrator) + //Check if player should go observer. Or un observe + if (bot_observer && !observer && !netgame) { - //Add new bots? - if (wanted_botnum > botnum && !freeze) - { - if (t_join == ((wanted_botnum - botnum) * SPAWN_DELAY)) - { - if (!SpawnBot (getspawned[spawn_tries])) - wanted_botnum--; - spawn_tries++; - } - - t_join--; - } - - //Check if player should go observer. Or un observe - if (bot_observer && !observer && !netgame) - { - Printf ("%s is now observer\n", players[consoleplayer].userinfo.GetName()); - observer = true; - players[consoleplayer].mo->UnlinkFromWorld (); - players[consoleplayer].mo->flags = MF_DROPOFF|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH|MF_NOGRAVITY|MF_FRIENDLY; - players[consoleplayer].mo->flags2 |= MF2_FLY; - players[consoleplayer].mo->LinkToWorld (); - } - else if (!bot_observer && observer && !netgame) //Go back - { - Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.GetName()); - observer = false; - players[consoleplayer].mo->UnlinkFromWorld (); - players[consoleplayer].mo->flags = MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY; - players[consoleplayer].mo->flags2 &= ~MF2_FLY; - players[consoleplayer].mo->LinkToWorld (); - } + Printf ("%s is now observer\n", players[consoleplayer].userinfo.GetName()); + observer = true; + players[consoleplayer].mo->UnlinkFromWorld (); + players[consoleplayer].mo->flags = MF_DROPOFF|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH|MF_NOGRAVITY|MF_FRIENDLY; + players[consoleplayer].mo->flags2 |= MF2_FLY; + players[consoleplayer].mo->LinkToWorld (); + } + else if (!bot_observer && observer && !netgame) //Go back + { + Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.GetName()); + observer = false; + players[consoleplayer].mo->UnlinkFromWorld (); + players[consoleplayer].mo->flags = MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY; + players[consoleplayer].mo->flags2 &= ~MF2_FLY; + players[consoleplayer].mo->LinkToWorld (); } - - m_Thinking = false; } void FCajunMaster::Init () @@ -199,18 +174,13 @@ void FCajunMaster::End () //Arrange wanted botnum and their names, so they can be spawned next level. getspawned.Clear(); - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && players[i].Bot != NULL) - { - if (deathmatch) - { - getspawned.Push(players[i].userinfo.GetName()); - } - } - } if (deathmatch) { + for (i = 0; i < MAXPLAYERS; i++) + { + getspawned.Push(players[i].userinfo.GetName()); + } + wanted_botnum = botnum; } } @@ -400,7 +370,7 @@ bool FCajunMaster::DoAddBot (BYTE *info, botskill_t skill) multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost). players[bnum].Bot = new DBot; - GC::WriteBarrier (players[bnum].Bot); + players[bnum].Bot->player = &players[bnum]; players[bnum].Bot->skill = skill; playeringame[bnum] = true; players[bnum].mo = NULL; @@ -426,7 +396,7 @@ void FCajunMaster::RemoveAllBots (bool fromlist) for (i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i] && players[i].Bot != NULL) + if (players[i].Bot != NULL) { // If a player is looking through this bot's eyes, make him // look through his own eyes instead. @@ -456,18 +426,6 @@ void FCajunMaster::RemoveAllBots (bool fromlist) botnum = 0; } -void FCajunMaster::DestroyAllBots () -{ - for (int i = 0; i < MAXPLAYERS; ++i) - { - if (players[i].Bot != NULL) - { - players[i].Bot->Destroy (); - players[i].Bot = NULL; - } - } -} - //------------------ //Reads data for bot from diff --git a/src/g_game.cpp b/src/g_game.cpp index e419e09fc..734500e55 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1128,11 +1128,8 @@ void G_Ticker () // check, not just the player's x position like BOOM. DWORD rngsum = FRandom::StaticSumSeeds (); - if ((gametic % ticdup) == 0) - { - //Added by MC: For some of that bot stuff. The main bot function. - bglobal.Main (buf); - } + //Added by MC: For some of that bot stuff. The main bot function. + bglobal.Main (); for (i = 0; i < MAXPLAYERS; i++) { @@ -1395,7 +1392,6 @@ void G_PlayerReborn (int player) if (gamestate != GS_TITLELEVEL) { - // [GRB] Give inventory specified in DECORATE actor->GiveDefaultInventory (); p->ReadyWeapon = p->PendingWeapon; @@ -1406,6 +1402,7 @@ void G_PlayerReborn (int player) { botskill_t skill = p->Bot->skill; p->Bot->Clear (); + p->Bot->player = p; p->Bot->skill = skill; } } diff --git a/src/g_level.cpp b/src/g_level.cpp index 2a2d6471a..761ea4f48 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1164,6 +1164,8 @@ void G_StartTravel () } } } + + bglobal.StartTravel (); } //========================================================================== @@ -1261,6 +1263,8 @@ void G_FinishTravel () } } } + + bglobal.FinishTravel (); } //========================================================================== diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index fc3e863a2..1aab998a9 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1024,7 +1024,7 @@ void AInventory::Touch (AActor *toucher) //Added by MC: Check if item taken was the roam destination of any bot for (int i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && players[i].Bot != NULL && this == players[i].Bot->dest) + if (players[i].Bot != NULL && this == players[i].Bot->dest) players[i].Bot->dest = NULL; } } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index c7bfcea21..4ef075720 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -84,7 +84,6 @@ static void PlayerLandedOnThing (AActor *mo, AActor *onmobj); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- -extern cycle_t BotSupportCycles; extern int BotWTG; EXTERN_CVAR (Int, cl_rockettrails) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 53b288798..6b5d9403f 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -4175,7 +4175,6 @@ static void P_Shutdown () P_FreeLevelData (); P_FreeExtraLevelData (); ST_Clear(); - bglobal.DestroyAllBots (); } #if 0 diff --git a/src/p_user.cpp b/src/p_user.cpp index 72b92b7d1..bf656d2b9 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3066,7 +3066,6 @@ void player_t::Serialize (FArchive &arc) if (SaveVersion < 4514 && IsBot) { Bot = new DBot; - GC::WriteBarrier (Bot); arc << Bot->angle << Bot->dest @@ -3089,6 +3088,12 @@ void player_t::Serialize (FArchive &arc) << Bot->oldx << Bot->oldy; } + + if (SaveVersion < 4516 && Bot != NULL) + { + Bot->player = this; + } + if (arc.IsLoading ()) { // If the player reloaded because they pressed +use after dying, we diff --git a/src/statnums.h b/src/statnums.h index 344a328c8..25f644d1d 100644 --- a/src/statnums.h +++ b/src/statnums.h @@ -63,6 +63,7 @@ enum STAT_SECTOREFFECT, // All sector effects that cause floor and ceiling movement STAT_ACTORMOVER, // actor movers STAT_SCRIPTS, // The ACS thinker. This is to ensure that it can't tick before all actors called PostBeginPlay + STAT_BOT, // Bot thinker }; #endif \ No newline at end of file diff --git a/src/version.h b/src/version.h index f091f416a..15d01d315 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4515 +#define SAVEVER 4516 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)