From db323643f81cc3649782b5f5995187d2522a69bf Mon Sep 17 00:00:00 2001 From: ChillyDoom Date: Tue, 14 Oct 2014 19:57:11 +0100 Subject: [PATCH] - Renamed FBot to DBot and made it inherit from DThinker. - Fixed: Bots added by players other than the net arbitrator did not have their skill set. --- src/b_bot.cpp | 71 ++++++++++++++- src/b_bot.h | 16 ++-- src/b_func.cpp | 68 +++++++-------- src/b_game.cpp | 58 ++++--------- src/b_move.cpp | 30 +++---- src/b_think.cpp | 172 ++++++++++++++++++------------------- src/d_main.cpp | 12 +-- src/d_net.cpp | 36 ++++---- src/d_player.h | 2 +- src/d_protocol.h | 2 +- src/g_game.cpp | 21 +++-- src/g_level.cpp | 10 +++ src/g_shared/a_pickups.cpp | 4 +- src/p_acs.cpp | 4 +- src/p_doors.cpp | 2 +- src/p_interaction.cpp | 22 ++--- src/p_map.cpp | 6 +- src/p_mobj.cpp | 12 +-- src/p_pspr.cpp | 8 +- src/p_saveg.cpp | 3 +- src/p_tick.cpp | 2 +- src/p_user.cpp | 108 +++++++++-------------- src/version.h | 2 +- src/wi_stuff.cpp | 10 +-- 24 files changed, 355 insertions(+), 326 deletions(-) diff --git a/src/b_bot.cpp b/src/b_bot.cpp index 26c8f99bd..30a8e4877 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -1,7 +1,7 @@ -// Cajun bot console commands. +// Cajun bot // -// [RH] Moved out of d_netcmd.c (in Cajun source), because they don't really -// belong there. +// [RH] Moved console commands out of d_netcmd.c (in Cajun source), because +// they don't really belong there. #include "c_cvars.h" #include "c_dispatch.h" @@ -14,6 +14,71 @@ #include "d_net.h" #include "farchive.h" +IMPLEMENT_POINTY_CLASS(DBot) + DECLARE_POINTER(dest) + DECLARE_POINTER(prev) + DECLARE_POINTER(enemy) + DECLARE_POINTER(missile) + DECLARE_POINTER(mate) + DECLARE_POINTER(last_mate) +END_POINTERS + +DBot::DBot () +{ + savedyaw = 0; + savedpitch = 0; + angle = 0; + dest = NULL; + prev = NULL; + enemy = NULL; + missile = NULL; + mate = NULL; + last_mate = NULL; + memset(&skill, 0, sizeof(skill)); + t_active = 0; + t_respawn = 0; + t_strafe = 0; + t_react = 0; + t_fight = 0; + t_roam = 0; + t_rocket = 0; + first_shot = true; + sleft = false; + allround = false; + increase = false; + oldx = 0; + oldy = 0; +} + +void DBot::Serialize (FArchive &arc) +{ + Super::Serialize (arc); + + arc << savedyaw + << savedpitch + << angle + << dest + << prev + << enemy + << missile + << mate + << last_mate + << skill + << t_active + << t_respawn + << t_strafe + << t_react + << t_fight + << t_roam + << t_rocket + << first_shot + << sleft + << allround + << increase + << oldx + << oldy; +} + 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 c82ed03d1..f414a9687 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -85,11 +85,10 @@ public: void Main (int buf); void Init (); void End(); - void CleanBotstuff (player_t *p); bool SpawnBot (const char *name, int color = NOCOLOR); bool LoadBots (); void ForgetBots (); - void DoAddBot (int bnum, char *info); + void DoAddBot (BYTE **stream); void RemoveAllBots (bool fromlist); //(B_Func.c) @@ -109,7 +108,6 @@ public: bool IsDangerous (sector_t *sec); TArray getspawned; //Array of bots (their names) which should be spawned when starting a game. - bool botingame[MAXPLAYERS]; BYTE freeze:1; //Game in freeze mode. BYTE changefreeze:1; //Game wants to change freeze mode. int botnum; @@ -145,14 +143,20 @@ protected: bool observer; //Consoleplayer is observer. }; -class FBot +class DBot : public DThinker { + DECLARE_CLASS(DBot,DThinker) + HAS_OBJECT_POINTERS public: + DBot (); + + void Serialize (FArchive &arc); + angle_t savedyaw; int savedpitch; angle_t angle; // The wanted angle that the bot try to get every tic. - // (used to get a smoth view movement) + // (used to get a smooth view movement) TObjPtr dest; // Move Destination. TObjPtr prev; // Previous move destination. @@ -179,10 +183,10 @@ public: int t_rocket; //Misc booleans - bool isbot; bool first_shot; // Used for reaction skill. bool sleft; // If false, strafe is right. bool allround; + bool increase; fixed_t oldx; fixed_t oldy; diff --git a/src/b_func.cpp b/src/b_func.cpp index 8d2df6949..0c0ab1ebd 100644 --- a/src/b_func.cpp +++ b/src/b_func.cpp @@ -140,8 +140,7 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd) fixed_t dist; angle_t an; int m; - static bool inc[MAXPLAYERS]; - AActor *enemy = actor->player->Bot.enemy; + AActor *enemy = actor->player->Bot->enemy; if (!enemy || !(enemy->flags & MF_SHOOTABLE) || enemy->health <= 0) return; @@ -149,20 +148,20 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd) if (actor->player->ReadyWeapon == NULL) return; - if (actor->player->damagecount > actor->player->Bot.skill.isp) + if (actor->player->damagecount > actor->player->Bot->skill.isp) { - actor->player->Bot.first_shot = true; + actor->player->Bot->first_shot = true; return; } //Reaction skill thing. - if (actor->player->Bot.first_shot && + if (actor->player->Bot->first_shot && !(actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_REACTION_SKILL_THING)) { - actor->player->Bot.t_react = (100-actor->player->Bot.skill.reaction+1)/((pr_botdofire()%3)+3); + actor->player->Bot->t_react = (100-actor->player->Bot->skill.reaction+1)/((pr_botdofire()%3)+3); } - actor->player->Bot.first_shot = false; - if (actor->player->Bot.t_react) + actor->player->Bot->first_shot = false; + if (actor->player->Bot->t_react) return; //MAKEME: Decrease the rocket suicides even more. @@ -199,8 +198,8 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd) else if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_BFG) { //MAKEME: This should be smarter. - if ((pr_botdofire()%200)<=actor->player->Bot.skill.reaction) - if(Check_LOS(actor, actor->player->Bot.enemy, SHOOTFOV)) + if ((pr_botdofire()%200)<=actor->player->Bot->skill.reaction) + if(Check_LOS(actor, actor->player->Bot->enemy, SHOOTFOV)) no_fire = false; } else if (actor->player->ReadyWeapon->ProjectileType != NULL) @@ -211,11 +210,11 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd) an = FireRox (actor, enemy, cmd); if(an) { - actor->player->Bot.angle = an; + actor->player->Bot->angle = an; //have to be somewhat precise. to avoid suicide. - if (abs (actor->player->Bot.angle - actor->angle) < 12*ANGLE_1) + if (abs (actor->player->Bot->angle - actor->angle) < 12*ANGLE_1) { - actor->player->Bot.t_rocket = 9; + actor->player->Bot->t_rocket = 9; no_fire = false; } } @@ -225,14 +224,14 @@ shootmissile: dist = P_AproxDistance (actor->x - enemy->x, actor->y - enemy->y); m = dist / GetDefaultByType (actor->player->ReadyWeapon->ProjectileType)->Speed; SetBodyAt (enemy->x + enemy->velx*m*2, enemy->y + enemy->vely*m*2, enemy->z, 1); - actor->player->Bot.angle = R_PointToAngle2 (actor->x, actor->y, body1->x, body1->y); + actor->player->Bot->angle = R_PointToAngle2 (actor->x, actor->y, body1->x, body1->y); if (Check_LOS (actor, enemy, SHOOTFOV)) no_fire = false; } else { //Other weapons, mostly instant hit stuff. - actor->player->Bot.angle = R_PointToAngle2 (actor->x, actor->y, enemy->x, enemy->y); + actor->player->Bot->angle = R_PointToAngle2 (actor->x, actor->y, enemy->x, enemy->y); aiming_penalty = 0; if (enemy->flags & MF_SHADOW) aiming_penalty += (pr_botdofire()%25)+10; @@ -240,7 +239,7 @@ shootmissile: aiming_penalty += pr_botdofire()%40;//Dark if (actor->player->damagecount) aiming_penalty += actor->player->damagecount; //Blood in face makes it hard to aim - aiming_value = actor->player->Bot.skill.aiming - aiming_penalty; + aiming_value = actor->player->Bot->skill.aiming - aiming_penalty; if (aiming_value <= 0) aiming_value = 1; m = ((SHOOTFOV/2)-(aiming_value*SHOOTFOV/200)); //Higher skill is more accurate @@ -249,15 +248,15 @@ shootmissile: if (m) { - if (inc[actor->player - players]) - actor->player->Bot.angle += m; + if (actor->player->Bot->increase) + actor->player->Bot->angle += m; else - actor->player->Bot.angle -= m; + actor->player->Bot->angle -= m; } - if (abs (actor->player->Bot.angle - actor->angle) < 4*ANGLE_1) + if (abs (actor->player->Bot->angle - actor->angle) < 4*ANGLE_1) { - inc[actor->player - players] = !inc[actor->player - players]; + actor->player->Bot->increase = !actor->player->Bot->increase; } if (Check_LOS (actor, enemy, (SHOOTFOV/2))) @@ -285,20 +284,20 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot) bool p_leader[MAXPLAYERS]; //is mate alive? - if (bot->player->Bot.mate) + if (bot->player->Bot->mate) { - if (bot->player->Bot.mate->health <= 0) - bot->player->Bot.mate = NULL; + if (bot->player->Bot->mate->health <= 0) + bot->player->Bot->mate = NULL; else - bot->player->Bot.last_mate = bot->player->Bot.mate; + bot->player->Bot->last_mate = bot->player->Bot->mate; } - if (bot->player->Bot.mate) //Still is.. - return bot->player->Bot.mate; + if (bot->player->Bot->mate) //Still is.. + return bot->player->Bot->mate; //Check old_mates status. - if (bot->player->Bot.last_mate) - if (bot->player->Bot.last_mate->health <= 0) - bot->player->Bot.last_mate = NULL; + if (bot->player->Bot->last_mate) + if (bot->player->Bot->last_mate->health <= 0) + bot->player->Bot->last_mate = NULL; for (count = 0; count < MAXPLAYERS; count++) { @@ -307,8 +306,8 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot) p_leader[count] = false; for (count2 = 0; count2 < MAXPLAYERS; count2++) { - if (players[count].Bot.isbot - && players[count2].Bot.mate == players[count].mo) + if (players[count2].Bot != NULL + && players[count2].Bot->mate == players[count].mo) { p_leader[count] = true; break; @@ -337,7 +336,6 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot) && ((bot->health/2) <= client->mo->health || !deathmatch) && !p_leader[count]) //taken? { - if (P_CheckSight (bot, client->mo, SF_IGNOREVISIBILITY)) { test = P_AproxDistance (client->mo->x - bot->x, @@ -386,11 +384,11 @@ AActor *FCajunMaster::Find_enemy (AActor *bot) } //Note: It's hard to ambush a bot who is not alone - if (bot->player->Bot.allround || bot->player->Bot.mate) + if (bot->player->Bot->allround || bot->player->Bot->mate) vangle = ANGLE_MAX; else vangle = ENEMY_SCAN_FOV; - bot->player->Bot.allround = false; + bot->player->Bot->allround = false; target = NULL; closest_dist = FIXED_MAX; diff --git a/src/b_game.cpp b/src/b_game.cpp index e3f3c97d6..35de6ec86 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -118,7 +118,7 @@ void FCajunMaster::Main (int buf) BotThinkCycles.Clock(); for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && players[i].mo && !freeze && players[i].Bot.isbot) + if (playeringame[i] && players[i].mo && !freeze && players[i].Bot != NULL) Think (players[i].mo, &netcmds[i][buf]); } BotThinkCycles.Unclock(); @@ -172,16 +172,9 @@ void FCajunMaster::Init () body1 = NULL; body2 = NULL; - //Remove all bots upon each level start, they'll get spawned instead. for (i = 0; i < MAXPLAYERS; i++) { waitingforspawn[i] = false; - if (playeringame[i] && players[i].Bot.isbot) - { - CleanBotstuff (&players[i]); - players[i].Bot.isbot = false; - botingame[i] = false; - } } if (ctf && teamplay == false) @@ -214,13 +207,12 @@ void FCajunMaster::End () getspawned.Clear(); for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && players[i].Bot.isbot) + if (playeringame[i] && players[i].Bot != NULL) { if (deathmatch) { getspawned.Push(players[i].userinfo.GetName()); } - CleanBotstuff (&players[i]); } } if (deathmatch) @@ -335,8 +327,10 @@ bool FCajunMaster::SpawnBot (const char *name, int color) } Net_WriteString (concat); } - - players[playernumber].Bot.skill = thebot->skill; + Net_WriteByte(thebot->skill.aiming); + Net_WriteByte(thebot->skill.perfection); + Net_WriteByte(thebot->skill.reaction); + Net_WriteByte(thebot->skill.isp); thebot->inuse = true; @@ -346,9 +340,17 @@ bool FCajunMaster::SpawnBot (const char *name, int color) return true; } -void FCajunMaster::DoAddBot (int bnum, char *info) +void FCajunMaster::DoAddBot (BYTE **stream) { + int bnum = ReadByte (stream); + char *info = ReadString (stream); BYTE *infob = (BYTE *)info; + botskill_t skill; + skill.aiming = ReadByte (stream); + skill.perfection = ReadByte (stream); + skill.reaction = ReadByte (stream); + skill.isp = ReadByte (stream); + D_ReadUserInfoStrings (bnum, &infob, false); if (!deathmatch && playerstarts[bnum].type == 0) { @@ -363,11 +365,11 @@ void FCajunMaster::DoAddBot (int bnum, char *info) else { multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost). - players[bnum].Bot.isbot = true; + players[bnum].Bot = new DBot; + players[bnum].Bot->skill = skill; playeringame[bnum] = true; players[bnum].mo = NULL; players[bnum].playerstate = PST_ENTER; - botingame[bnum] = true; if (teamplay) Printf ("%s joined the %s team\n", players[bnum].userinfo.GetName(), Teams[players[bnum].userinfo.GetTeam()].GetName()); @@ -389,13 +391,13 @@ void FCajunMaster::RemoveAllBots (bool fromlist) for (i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[i] && botingame[i]) + if (playeringame[i] && players[i].Bot != NULL) { // If a player is looking through this bot's eyes, make him // look through his own eyes instead. for (j = 0; j < MAXPLAYERS; ++j) { - if (i != j && playeringame[j] && !botingame[j]) + if (i != j && playeringame[j] && players[j].Bot == NULL) { if (players[j].camera == players[i].mo) { @@ -421,28 +423,6 @@ void FCajunMaster::RemoveAllBots (bool fromlist) botnum = 0; } -//Clean the bot part of the player_t -//Used when bots are respawned or at level starts. -void FCajunMaster::CleanBotstuff (player_t *p) -{ - p->Bot.angle = ANG45; - p->Bot.dest = NULL; - p->Bot.enemy = NULL; //The dead meat. - p->Bot.missile = NULL; //A threatening missile that needs to be avoided. - p->Bot.mate = NULL; //Friend (used for grouping in templay or coop. - p->Bot.last_mate = NULL; //If bot's mate dissapeared (not if died) that mate is pointed to by this. Allows bot to roam to it if necessary. - //Tickers - p->Bot.t_active = 0; //Open door, lower lift stuff, door must open and lift must go down before bot does anything radical like try a stuckmove - p->Bot.t_respawn = 0; - p->Bot.t_strafe = 0; - p->Bot.t_react = 0; - //Misc bools - p->Bot.isbot = true; //Important. - p->Bot.first_shot = true; //Used for reaction skill. - p->Bot.sleft = false; //If false, strafe is right. - p->Bot.allround = false; -} - //------------------ //Reads data for bot from diff --git a/src/b_move.cpp b/src/b_move.cpp index 1f2e4c332..f020cf4fc 100644 --- a/src/b_move.cpp +++ b/src/b_move.cpp @@ -33,19 +33,19 @@ void FCajunMaster::Roam (AActor *actor, ticcmd_t *cmd) { int delta; - if (Reachable(actor, actor->player->Bot.dest)) + if (Reachable(actor, actor->player->Bot->dest)) { // Straight towards it. - actor->player->Bot.angle = R_PointToAngle2(actor->x, actor->y, actor->player->Bot.dest->x, actor->player->Bot.dest->y); + actor->player->Bot->angle = R_PointToAngle2(actor->x, actor->y, actor->player->Bot->dest->x, actor->player->Bot->dest->y); } else if (actor->movedir < 8) // turn towards movement direction if not there yet { - actor->player->Bot.angle &= (angle_t)(7<<29); - delta = actor->player->Bot.angle - (actor->movedir << 29); + actor->player->Bot->angle &= (angle_t)(7<<29); + delta = actor->player->Bot->angle - (actor->movedir << 29); if (delta > 0) - actor->player->Bot.angle -= ANG45; + actor->player->Bot->angle -= ANG45; else if (delta < 0) - actor->player->Bot.angle += ANG45; + actor->player->Bot->angle += ANG45; } // chase towards destination. @@ -134,7 +134,7 @@ void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd) dirtype_t turnaround; - if (!actor->player->Bot.dest) + if (!actor->player->Bot->dest) { #ifndef BOT_RELEASE_COMPILE Printf ("Bot tried move without destination\n"); @@ -145,8 +145,8 @@ void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd) olddir = (dirtype_t)actor->movedir; turnaround = opposite[olddir]; - deltax = actor->player->Bot.dest->x - actor->x; - deltay = actor->player->Bot.dest->y - actor->y; + deltax = actor->player->Bot->dest->x - actor->x; + deltay = actor->player->Bot->dest->y - actor->y; if (deltax > 10*FRACUNIT) d[1] = DI_EAST; @@ -315,23 +315,23 @@ void FCajunMaster::TurnToAng (AActor *actor) { if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE) { - if (actor->player->Bot.t_roam && !actor->player->Bot.missile) + if (actor->player->Bot->t_roam && !actor->player->Bot->missile) { //Keep angle that where when shot where decided. return; } } - if(actor->player->Bot.enemy) - if(!actor->player->Bot.dest) //happens when running after item in combat situations, or normal, prevents weak turns + if(actor->player->Bot->enemy) + if(!actor->player->Bot->dest) //happens when running after item in combat situations, or normal, prevents weak turns if(actor->player->ReadyWeapon->ProjectileType == NULL && !(actor->player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON)) - if(Check_LOS(actor, actor->player->Bot.enemy, SHOOTFOV+5*ANGLE_1)) + if(Check_LOS(actor, actor->player->Bot->enemy, SHOOTFOV+5*ANGLE_1)) maxturn = 3; } - int distance = actor->player->Bot.angle - actor->angle; + int distance = actor->player->Bot->angle - actor->angle; - if (abs (distance) < OKAYRANGE && !actor->player->Bot.enemy) + if (abs (distance) < OKAYRANGE && !actor->player->Bot->enemy) return; distance /= TURNSENS; diff --git a/src/b_think.cpp b/src/b_think.cpp index a5deec372..e5ee8775c 100644 --- a/src/b_think.cpp +++ b/src/b_think.cpp @@ -28,13 +28,13 @@ void FCajunMaster::Think (AActor *actor, ticcmd_t *cmd) { memset (cmd, 0, sizeof(*cmd)); - if (actor->player->Bot.enemy && actor->player->Bot.enemy->health <= 0) - actor->player->Bot.enemy = NULL; + if (actor->player->Bot->enemy && actor->player->Bot->enemy->health <= 0) + actor->player->Bot->enemy = NULL; if (actor->health > 0) //Still alive { if (teamplay || !deathmatch) - actor->player->Bot.mate = Choose_Mate (actor); + actor->player->Bot->mate = Choose_Mate (actor); angle_t oldyaw = actor->angle; int oldpitch = actor->pitch; @@ -52,17 +52,17 @@ void FCajunMaster::Think (AActor *actor, ticcmd_t *cmd) actor->pitch = oldpitch - (cmd->ucmd.pitch << 16) * ticdup; } - if (actor->player->Bot.t_active) actor->player->Bot.t_active--; - if (actor->player->Bot.t_strafe) actor->player->Bot.t_strafe--; - if (actor->player->Bot.t_react) actor->player->Bot.t_react--; - if (actor->player->Bot.t_fight) actor->player->Bot.t_fight--; - if (actor->player->Bot.t_rocket) actor->player->Bot.t_rocket--; - if (actor->player->Bot.t_roam) actor->player->Bot.t_roam--; + if (actor->player->Bot->t_active) actor->player->Bot->t_active--; + if (actor->player->Bot->t_strafe) actor->player->Bot->t_strafe--; + if (actor->player->Bot->t_react) actor->player->Bot->t_react--; + if (actor->player->Bot->t_fight) actor->player->Bot->t_fight--; + if (actor->player->Bot->t_rocket) actor->player->Bot->t_rocket--; + if (actor->player->Bot->t_roam) actor->player->Bot->t_roam--; //Respawn ticker - if (actor->player->Bot.t_respawn) + if (actor->player->Bot->t_respawn) { - actor->player->Bot.t_respawn--; + actor->player->Bot->t_respawn--; } else if (actor->health <= 0) { // Time to respawn @@ -80,17 +80,17 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd) int r; b = actor->player; - if (!b->Bot.isbot) + if (b->Bot == NULL) return; stuck = false; - dist = b->Bot.dest ? P_AproxDistance(actor->x-b->Bot.dest->x, actor->y-b->Bot.dest->y) : 0; + dist = b->Bot->dest ? P_AproxDistance(actor->x-b->Bot->dest->x, actor->y-b->Bot->dest->y) : 0; - if (b->Bot.missile && - ((!b->Bot.missile->velx || !b->Bot.missile->vely) || !Check_LOS(actor, b->Bot.missile, SHOOTFOV*3/2))) + if (b->Bot->missile && + ((!b->Bot->missile->velx || !b->Bot->missile->vely) || !Check_LOS(actor, b->Bot->missile, SHOOTFOV*3/2))) { - b->Bot.sleft = !b->Bot.sleft; - b->Bot.missile = NULL; //Probably ended its travel. + b->Bot->sleft = !b->Bot->sleft; + b->Bot->missile = NULL; //Probably ended its travel. } if (actor->pitch > 0) @@ -99,35 +99,35 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd) actor->pitch += 80; //HOW TO MOVE: - if (b->Bot.missile && (P_AproxDistance(actor->x-b->Bot.missile->x, actor->y-b->Bot.missile->y)Bot->missile && (P_AproxDistance(actor->x-b->Bot->missile->x, actor->y-b->Bot->missile->y)Bot.missile); - actor->player->Bot.angle = R_PointToAngle2(actor->x, actor->y, b->Bot.missile->x, b->Bot.missile->y); - cmd->ucmd.sidemove = b->Bot.sleft ? -SIDERUN : SIDERUN; + Pitch (actor, b->Bot->missile); + actor->player->Bot->angle = R_PointToAngle2(actor->x, actor->y, b->Bot->missile->x, b->Bot->missile->y); + cmd->ucmd.sidemove = b->Bot->sleft ? -SIDERUN : SIDERUN; cmd->ucmd.forwardmove = -FORWARDRUN; //Back IS best. - if ((P_AproxDistance(actor->x-b->Bot.oldx, actor->y-b->Bot.oldy)<50000) - && b->Bot.t_strafe<=0) + if ((P_AproxDistance(actor->x-b->Bot->oldx, actor->y-b->Bot->oldy)<50000) + && b->Bot->t_strafe<=0) { - b->Bot.t_strafe = 5; - b->Bot.sleft = !b->Bot.sleft; + b->Bot->t_strafe = 5; + b->Bot->sleft = !b->Bot->sleft; } //If able to see enemy while avoiding missile, still fire at enemy. - if (b->Bot.enemy && Check_LOS (actor, b->Bot.enemy, SHOOTFOV)) + if (b->Bot->enemy && Check_LOS (actor, b->Bot->enemy, SHOOTFOV)) Dofire (actor, cmd); //Order bot to fire current weapon } - else if (b->Bot.enemy && P_CheckSight (actor, b->Bot.enemy, 0)) //Fight! + else if (b->Bot->enemy && P_CheckSight (actor, b->Bot->enemy, 0)) //Fight! { - Pitch (actor, b->Bot.enemy); + Pitch (actor, b->Bot->enemy); //Check if it's more important to get an item than fight. - if (b->Bot.dest && (b->Bot.dest->flags&MF_SPECIAL)) //Must be an item, that is close enough. + if (b->Bot->dest && (b->Bot->dest->flags&MF_SPECIAL)) //Must be an item, that is close enough. { -#define is(x) b->Bot.dest->IsKindOf (PClass::FindClass (#x)) +#define is(x) b->Bot->dest->IsKindOf (PClass::FindClass (#x)) if ( ( - (actor->health < b->Bot.skill.isp && + (actor->health < b->Bot->skill.isp && (is (Medikit) || is (Stimpack) || is (Soulsphere) || @@ -143,75 +143,75 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd) (b->ReadyWeapon == NULL || b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON) ) && (dist < GETINCOMBAT || (b->ReadyWeapon == NULL || b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)) - && Reachable (actor, b->Bot.dest)) + && Reachable (actor, b->Bot->dest)) #undef is { goto roam; //Pick it up, no matter the situation. All bonuses are nice close up. } } - b->Bot.dest = NULL; //To let bot turn right + b->Bot->dest = NULL; //To let bot turn right if (b->ReadyWeapon != NULL && !(b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)) actor->flags &= ~MF_DROPOFF; //Don't jump off any ledges when fighting. - if (!(b->Bot.enemy->flags3 & MF3_ISMONSTER)) - b->Bot.t_fight = AFTERTICS; + if (!(b->Bot->enemy->flags3 & MF3_ISMONSTER)) + b->Bot->t_fight = AFTERTICS; - if (b->Bot.t_strafe <= 0 && - (P_AproxDistance(actor->x-b->Bot.oldx, actor->y-b->Bot.oldy)<50000 + if (b->Bot->t_strafe <= 0 && + (P_AproxDistance(actor->x-b->Bot->oldx, actor->y-b->Bot->oldy)<50000 || ((pr_botmove()%30)==10)) ) { stuck = true; - b->Bot.t_strafe = 5; - b->Bot.sleft = !b->Bot.sleft; + b->Bot->t_strafe = 5; + b->Bot->sleft = !b->Bot->sleft; } - b->Bot.angle = R_PointToAngle2(actor->x, actor->y, b->Bot.enemy->x, b->Bot.enemy->y); + b->Bot->angle = R_PointToAngle2(actor->x, actor->y, b->Bot->enemy->x, b->Bot->enemy->y); if (b->ReadyWeapon == NULL || - P_AproxDistance(actor->x-b->Bot.enemy->x, actor->y-b->Bot.enemy->y) > + P_AproxDistance(actor->x-b->Bot->enemy->x, actor->y-b->Bot->enemy->y) > b->ReadyWeapon->MoveCombatDist) { // If a monster, use lower speed (just for cooler apperance while strafing down doomed monster) - cmd->ucmd.forwardmove = (b->Bot.enemy->flags3 & MF3_ISMONSTER) ? FORWARDWALK : FORWARDRUN; + cmd->ucmd.forwardmove = (b->Bot->enemy->flags3 & MF3_ISMONSTER) ? FORWARDWALK : FORWARDRUN; } else if (!stuck) //Too close, so move away. { // If a monster, use lower speed (just for cooler apperance while strafing down doomed monster) - cmd->ucmd.forwardmove = (b->Bot.enemy->flags3 & MF3_ISMONSTER) ? -FORWARDWALK : -FORWARDRUN; + cmd->ucmd.forwardmove = (b->Bot->enemy->flags3 & MF3_ISMONSTER) ? -FORWARDWALK : -FORWARDRUN; } //Strafing. - if (b->Bot.enemy->flags3 & MF3_ISMONSTER) //It's just a monster so take it down cool. + if (b->Bot->enemy->flags3 & MF3_ISMONSTER) //It's just a monster so take it down cool. { - cmd->ucmd.sidemove = b->Bot.sleft ? -SIDEWALK : SIDEWALK; + cmd->ucmd.sidemove = b->Bot->sleft ? -SIDEWALK : SIDEWALK; } else { - cmd->ucmd.sidemove = b->Bot.sleft ? -SIDERUN : SIDERUN; + cmd->ucmd.sidemove = b->Bot->sleft ? -SIDERUN : SIDERUN; } Dofire (actor, cmd); //Order bot to fire current weapon } - else if (b->Bot.mate && !b->Bot.enemy && (!b->Bot.dest || b->Bot.dest==b->Bot.mate)) //Follow mate move. + else if (b->Bot->mate && !b->Bot->enemy && (!b->Bot->dest || b->Bot->dest==b->Bot->mate)) //Follow mate move. { fixed_t matedist; - Pitch (actor, b->Bot.mate); + Pitch (actor, b->Bot->mate); - if (!Reachable (actor, b->Bot.mate)) + if (!Reachable (actor, b->Bot->mate)) { - if (b->Bot.mate == b->Bot.dest && pr_botmove.Random() < 32) + if (b->Bot->mate == b->Bot->dest && pr_botmove.Random() < 32) { // [RH] If the mate is the dest, pick a new dest sometimes - b->Bot.dest = NULL; + b->Bot->dest = NULL; } goto roam; } - actor->player->Bot.angle = R_PointToAngle2(actor->x, actor->y, b->Bot.mate->x, b->Bot.mate->y); + actor->player->Bot->angle = R_PointToAngle2(actor->x, actor->y, b->Bot->mate->x, b->Bot->mate->y); - matedist = P_AproxDistance(actor->x - b->Bot.mate->x, actor->y - b->Bot.mate->y); + matedist = P_AproxDistance(actor->x - b->Bot->mate->x, actor->y - b->Bot->mate->y); if (matedist > (FRIEND_DIST*2)) cmd->ucmd.forwardmove = FORWARDRUN; else if (matedist > FRIEND_DIST) @@ -221,33 +221,33 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd) } else //Roam after something. { - b->Bot.first_shot = true; + b->Bot->first_shot = true; ///// roam: ///// - if (b->Bot.enemy && Check_LOS (actor, b->Bot.enemy, SHOOTFOV*3/2)) //If able to see enemy while avoiding missile , still fire at it. + if (b->Bot->enemy && Check_LOS (actor, b->Bot->enemy, SHOOTFOV*3/2)) //If able to see enemy while avoiding missile , still fire at it. Dofire (actor, cmd); //Order bot to fire current weapon - if (b->Bot.dest && !(b->Bot.dest->flags&MF_SPECIAL) && b->Bot.dest->health < 0) + if (b->Bot->dest && !(b->Bot->dest->flags&MF_SPECIAL) && b->Bot->dest->health < 0) { //Roaming after something dead. - b->Bot.dest = NULL; + b->Bot->dest = NULL; } - if (b->Bot.dest == NULL) + if (b->Bot->dest == NULL) { - if (b->Bot.t_fight && b->Bot.enemy) //Enemy/bot has jumped around corner. So what to do? + if (b->Bot->t_fight && b->Bot->enemy) //Enemy/bot has jumped around corner. So what to do? { - if (b->Bot.enemy->player) + if (b->Bot->enemy->player) { - if (((b->Bot.enemy->player->ReadyWeapon != NULL && b->Bot.enemy->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE) || - (pr_botmove()%100)>b->Bot.skill.isp) && b->ReadyWeapon != NULL && !(b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)) - b->Bot.dest = b->Bot.enemy;//Dont let enemy kill the bot by supressive fire. So charge enemy. + if (((b->Bot->enemy->player->ReadyWeapon != NULL && b->Bot->enemy->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE) || + (pr_botmove()%100)>b->Bot->skill.isp) && b->ReadyWeapon != NULL && !(b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)) + b->Bot->dest = b->Bot->enemy;//Dont let enemy kill the bot by supressive fire. So charge enemy. else //hide while b->t_fight, but keep view at enemy. - b->Bot.angle = R_PointToAngle2(actor->x, actor->y, b->Bot.enemy->x, b->Bot.enemy->y); + b->Bot->angle = R_PointToAngle2(actor->x, actor->y, b->Bot->enemy->x, b->Bot->enemy->y); } //Just a monster, so kill it. else - b->Bot.dest = b->Bot.enemy; + b->Bot->dest = b->Bot->enemy; //VerifFavoritWeapon(actor->player); //Dont know why here.., but it must be here, i know the reason, but not why at this spot, uh. } @@ -272,42 +272,42 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd) item = it.Next(); } firstthing = item; - b->Bot.dest = item; + b->Bot->dest = item; } } - else if (b->Bot.mate && (r < 179 || P_CheckSight(actor, b->Bot.mate))) + else if (b->Bot->mate && (r < 179 || P_CheckSight(actor, b->Bot->mate))) { - b->Bot.dest = b->Bot.mate; + b->Bot->dest = b->Bot->mate; } else if ((playeringame[(r&(MAXPLAYERS-1))]) && players[(r&(MAXPLAYERS-1))].mo->health > 0) { - b->Bot.dest = players[(r&(MAXPLAYERS-1))].mo; + b->Bot->dest = players[(r&(MAXPLAYERS-1))].mo; } } - if (b->Bot.dest) + if (b->Bot->dest) { - b->Bot.t_roam = MAXROAM; + b->Bot->t_roam = MAXROAM; } } - if (b->Bot.dest) + if (b->Bot->dest) { //Bot has a target so roam after it. Roam (actor, cmd); } } //End of movement main part. - if (!b->Bot.t_roam && b->Bot.dest) + if (!b->Bot->t_roam && b->Bot->dest) { - b->Bot.prev = b->Bot.dest; - b->Bot.dest = NULL; + b->Bot->prev = b->Bot->dest; + b->Bot->dest = NULL; } - if (b->Bot.t_fight<(AFTERTICS/2)) + if (b->Bot->t_fight<(AFTERTICS/2)) actor->flags |= MF_DROPOFF; - b->Bot.oldx = actor->x; - b->Bot.oldy = actor->y; + b->Bot->oldx = actor->x; + b->Bot->oldy = actor->y; } //BOT_WhatToGet @@ -324,7 +324,7 @@ void FCajunMaster::WhatToGet (AActor *actor, AActor *item) #define typeis(x) item->IsKindOf (PClass::FindClass (#x)) if ((item->renderflags & RF_INVISIBLE) //Under respawn and away. - || item == b->Bot.prev) + || item == b->Bot->prev) { return; } @@ -366,21 +366,21 @@ void FCajunMaster::WhatToGet (AActor *actor, AActor *item) else if (item->IsKindOf (RUNTIME_CLASS(AHealth)) && actor->health >= deh.MaxHealth /*MAXHEALTH*/) return; - if ((b->Bot.dest == NULL || - !(b->Bot.dest->flags & MF_SPECIAL)/* || + if ((b->Bot->dest == NULL || + !(b->Bot->dest->flags & MF_SPECIAL)/* || !Reachable (actor, b->dest)*/)/* && Reachable (actor, item)*/) // Calling Reachable slows this down tremendously { - b->Bot.prev = b->Bot.dest; - b->Bot.dest = item; - b->Bot.t_roam = MAXROAM; + b->Bot->prev = b->Bot->dest; + b->Bot->dest = item; + b->Bot->t_roam = MAXROAM; } } void FCajunMaster::Set_enemy (AActor *actor) { AActor *oldenemy; - AActor **enemy = &actor->player->Bot.enemy; + AActor **enemy = &actor->player->Bot->enemy; if (*enemy && (*enemy)->health > 0 @@ -397,7 +397,7 @@ void FCajunMaster::Set_enemy (AActor *actor) // and we already have an existing enemy. if (deathmatch || !*enemy) { - actor->player->Bot.allround = !!*enemy; + actor->player->Bot->allround = !!*enemy; *enemy = NULL; *enemy = Find_enemy(actor); if (!*enemy) diff --git a/src/d_main.cpp b/src/d_main.cpp index 9ce300e01..030387118 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -978,19 +978,19 @@ void D_DoomLoop () int i; for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && players[i].Bot.isbot && players[i].mo) + if (playeringame[i] && players[i].Bot != NULL && players[i].mo) { - players[i].Bot.savedyaw = players[i].mo->angle; - players[i].Bot.savedpitch = players[i].mo->pitch; + players[i].Bot->savedyaw = players[i].mo->angle; + players[i].Bot->savedpitch = players[i].mo->pitch; } } bglobal.Main (maketic%BACKUPTICS); for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && players[i].Bot.isbot && players[i].mo) + if (playeringame[i] && players[i].Bot != NULL && players[i].mo) { - players[i].mo->angle = players[i].Bot.savedyaw; - players[i].mo->pitch = players[i].Bot.savedpitch; + players[i].mo->angle = players[i].Bot->savedyaw; + players[i].mo->pitch = players[i].Bot->savedpitch; } } if (advancedemo) diff --git a/src/d_net.cpp b/src/d_net.cpp index dfc76f785..690a443ef 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -697,7 +697,7 @@ void PlayerIsGone (int netnode, int netconsole) // Pick a new network arbitrator for (int i = 0; i < MAXPLAYERS; i++) { - if (i != netconsole && playeringame[i] && !players[i].Bot.isbot) + if (i != netconsole && playeringame[i] && players[i].Bot == NULL) { Net_Arbitrator = i; players[i].settings_controller = true; @@ -902,7 +902,7 @@ void GetPackets (void) for (i = 0; i < numplayers; ++i) { - int node = !players[playerbytes[i]].Bot.isbot ? + int node = (players[playerbytes[i]].Bot == NULL) ? nodeforplayer[playerbytes[i]] : netnode; SkipTicCmd (&start, nettics[node] - realstart); @@ -918,7 +918,7 @@ void GetPackets (void) // packet. for (i = 0; i < numplayers; ++i) { - if (!players[playerbytes[i]].Bot.isbot) + if (players[playerbytes[i]].Bot == NULL) { nettics[nodeforplayer[playerbytes[i]]] = realend; } @@ -935,10 +935,10 @@ void AdjustBots (int gameticdiv) // be in even when gametic lags behind maketic. for (int i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && players[i].Bot.isbot && players[i].mo) + if (playeringame[i] && players[i].Bot != NULL && players[i].mo) { - players[i].Bot.savedyaw = players[i].mo->angle; - players[i].Bot.savedpitch = players[i].mo->pitch; + players[i].Bot->savedyaw = players[i].mo->angle; + players[i].Bot->savedpitch = players[i].mo->pitch; for (int j = gameticdiv; j < maketic/ticdup; j++) { players[i].mo->angle += (netcmds[i][j%BACKUPTICS].ucmd.yaw << 16) * ticdup; @@ -952,10 +952,10 @@ void UnadjustBots () { for (int i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && players[i].Bot.isbot && players[i].mo) + if (playeringame[i] && players[i].Bot != NULL && players[i].mo) { - players[i].mo->angle = players[i].Bot.savedyaw; - players[i].mo->pitch = players[i].Bot.savedpitch; + players[i].mo->angle = players[i].Bot->savedyaw; + players[i].mo->pitch = players[i].Bot->savedpitch; } } } @@ -1127,7 +1127,7 @@ void NetUpdate (void) { if (playeringame[j]) { - if (players[j].Bot.isbot || NetMode == NET_PacketServer) + if (players[j].Bot != NULL || NetMode == NET_PacketServer) { count++; } @@ -1269,7 +1269,7 @@ void NetUpdate (void) { if (playeringame[j] && j != playerfornode[i] && j != consoleplayer) { - if (players[j].Bot.isbot || NetMode == NET_PacketServer) + if (players[j].Bot != NULL || NetMode == NET_PacketServer) { playerbytes[l++] = j; netbuffer[k++] = j; @@ -1308,7 +1308,7 @@ void NetUpdate (void) } else if (i != 0) { - if (players[playerbytes[l]].Bot.isbot) + if (players[playerbytes[l]].Bot != NULL) { WriteWord (0, &cmddata); // fake consistancy word } @@ -2250,10 +2250,7 @@ void Net_DoCommand (int type, BYTE **stream, int player) break; case DEM_ADDBOT: - { - BYTE num = ReadByte (stream); - bglobal.DoAddBot (num, s = ReadString (stream)); - } + bglobal.DoAddBot (stream); break; case DEM_KILLBOTS: @@ -2709,10 +2706,13 @@ void Net_SkipCommand (int type, BYTE **stream) switch (type) { case DEM_SAY: - case DEM_ADDBOT: skip = strlen ((char *)(*stream + 1)) + 2; break; + case DEM_ADDBOT: + skip = strlen ((char *)(*stream + 1)) + 6; + break; + case DEM_GIVECHEAT: case DEM_TAKECHEAT: skip = strlen ((char *)(*stream)) + 3; @@ -2874,7 +2874,7 @@ static void Network_Controller (int playernum, bool add) return; } - if (players[playernum].Bot.isbot) + if (players[playernum].Bot != NULL) { Printf ("Bots cannot be added to the controller list.\n"); return; diff --git a/src/d_player.h b/src/d_player.h index 055cb75b4..ceb1ff894 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -442,7 +442,7 @@ public: FName LastDamageType; // [RH] For damage-specific pain and death sounds //Added by MC: - FBot Bot; + TObjPtr Bot; bool settings_controller; // Player can control game settings. diff --git a/src/d_protocol.h b/src/d_protocol.h index 028ad1606..0d11c7760 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -112,7 +112,7 @@ enum EDemoCommand DEM_DROPPLAYER, // 13 Not implemented, takes a byte DEM_CHANGEMAP, // 14 Name of map to change to DEM_SUICIDE, // 15 Player wants to die - DEM_ADDBOT, // 16 Byte: player#, String: userinfo for bot + DEM_ADDBOT, // 16 Byte: player#, String: userinfo for bot, 4 Bytes: skill (aiming, perfection, reaction, isp) DEM_KILLBOTS, // 17 Remove all bots from the world DEM_INVUSEALL, // 18 Use every item (panic!) DEM_INVUSE, // 19 4 bytes: ID of item to use diff --git a/src/g_game.cpp b/src/g_game.cpp index 3d166492e..fad7d9eb1 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -875,7 +875,7 @@ static void ChangeSpy (int changespy) pnum &= MAXPLAYERS-1; if (playeringame[pnum] && (!checkTeam || players[pnum].mo->IsTeammate (players[consoleplayer].mo) || - (bot_allowspy && players[pnum].Bot.isbot))) + (bot_allowspy && players[pnum].Bot != NULL))) { break; } @@ -1156,7 +1156,7 @@ void G_Ticker () Printf ("%s is turbo!\n", players[i].userinfo.GetName()); } - if (netgame && !players[i].Bot.isbot && !demoplayback && (gametic%ticdup) == 0) + if (netgame && players[i].Bot == NULL && !demoplayback && (gametic%ticdup) == 0) { //players[i].inconsistant = 0; if (gametic > BACKUPTICS*ticdup && consistancy[i][buf] != cmd->consistancy) @@ -1338,10 +1338,10 @@ void G_PlayerReborn (int player) int chasecam; BYTE currclass; userinfo_t userinfo; // [RH] Save userinfo - botskill_t b_skill; //Added by MC: APlayerPawn *actor; const PClass *cls; FString log; + DBot *OldBot; //Added by MC: p = &players[player]; @@ -1351,12 +1351,12 @@ void G_PlayerReborn (int player) itemcount = p->itemcount; secretcount = p->secretcount; currclass = p->CurrentPlayerClass; - b_skill = p->Bot.skill; //Added by MC: userinfo.TransferFrom(p->userinfo); actor = p->mo; cls = p->cls; log = p->LogText; chasecam = p->cheats & CF_CHASECAM; + OldBot = p->Bot; //Added by MC: // Reset player structure to its defaults p->~player_t(); @@ -1374,7 +1374,12 @@ void G_PlayerReborn (int player) p->LogText = log; p->cheats |= chasecam; - p->Bot.skill = b_skill; //Added by MC: + //Added by MC: Init bot structure. + if (OldBot != NULL) + { + p->Bot = new DBot; + p->Bot->skill = OldBot->skill; + } p->oldbuttons = ~0, p->attackdown = true; p->usedown = true; // don't do anything immediately p->original_oldbuttons = ~0; @@ -1385,12 +1390,6 @@ void G_PlayerReborn (int player) actor->GiveDefaultInventory (); p->ReadyWeapon = p->PendingWeapon; } - - //Added by MC: Init bot structure. - if (bglobal.botingame[player]) - bglobal.CleanBotstuff (p); - else - p->Bot.isbot = false; } // diff --git a/src/g_level.cpp b/src/g_level.cpp index d84a48776..2d3aeee3a 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1110,6 +1110,11 @@ void G_StartTravel () P_DelSector_List (); } } + + if (players[i].Bot != NULL) + { + players[i].Bot->ChangeStatNum (STAT_TRAVELLING); + } } } } @@ -1184,6 +1189,11 @@ void G_FinishTravel () pawn->SetState(pawn->SpawnState); pawn->player->SendPitchLimits(); + if (pawn->player->Bot != NULL) + { + pawn->player->Bot->ChangeStatNum (STAT_DEFAULT); + } + for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory) { inv->ChangeStatNum (STAT_INVENTORY); diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 4836ae033..a16a1316f 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1024,8 +1024,8 @@ 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] && this == players[i].Bot.dest) - players[i].Bot.dest = NULL; + if (playeringame[i] && players[i].Bot != NULL && this == players[i].Bot->dest) + players[i].Bot->dest = NULL; } } diff --git a/src/p_acs.cpp b/src/p_acs.cpp index d2780b4e4..afef9ffd3 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4228,7 +4228,7 @@ int DLevelScript::DoClassifyActor(int tid) { classify |= ACTOR_VOODOODOLL; } - if (actor->player->Bot.isbot) + if (actor->player->Bot != NULL) { classify |= ACTOR_BOT; } @@ -8632,7 +8632,7 @@ scriptwait: } else { - STACK(1) = players[STACK(1)].Bot.isbot; + STACK(1) = (players[STACK(1)].Bot != NULL); } break; diff --git a/src/p_doors.cpp b/src/p_doors.cpp index de4519505..844f23af9 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -460,7 +460,7 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing, // run into them (otherwise opening them would be // a real pain). { - if (!thing->player || thing->player->Bot.isbot) + if (!thing->player || thing->player->Bot != NULL) return false; // JDC: bad guys never close doors //Added by MC: Neither do bots. diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 1dcf0ebad..6aa1a28f6 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -100,10 +100,10 @@ void P_TouchSpecialThing (AActor *special, AActor *toucher) return; //Added by MC: Finished with this destination. - if (toucher->player != NULL && toucher->player->Bot.isbot && special == toucher->player->Bot.dest) + if (toucher->player != NULL && toucher->player->Bot != NULL && special == toucher->player->Bot->dest) { - toucher->player->Bot.prev = toucher->player->Bot.dest; - toucher->player->Bot.dest = NULL; + toucher->player->Bot->prev = toucher->player->Bot->dest; + toucher->player->Bot->dest = NULL; } special->Touch (toucher); @@ -608,17 +608,17 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) //Added by MC: Respawn bots if (bglobal.botnum && consoleplayer == Net_Arbitrator && !demoplayback) { - if (player->Bot.isbot) - player->Bot.t_respawn = (pr_botrespawn()%15)+((bglobal.botnum-1)*2)+TICRATE+1; + if (player->Bot != NULL) + player->Bot->t_respawn = (pr_botrespawn()%15)+((bglobal.botnum-1)*2)+TICRATE+1; //Added by MC: Discard enemies. for (int i = 0; i < MAXPLAYERS; i++) { - if (players[i].Bot.isbot && this == players[i].Bot.enemy) + if (players[i].Bot != NULL && this == players[i].Bot->enemy) { - if (players[i].Bot.dest == players[i].Bot.enemy) - players[i].Bot.dest = NULL; - players[i].Bot.enemy = NULL; + if (players[i].Bot->dest == players[i].Bot->enemy) + players[i].Bot->dest = NULL; + players[i].Bot->enemy = NULL; } } @@ -1194,9 +1194,9 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, if (player) { //Added by MC: Lets bots look allround for enemies if they survive an ambush. - if (player->Bot.isbot) + if (player->Bot != NULL) { - player->Bot.allround = true; + player->Bot->allround = true; } // end of game hell hack diff --git a/src/p_map.cpp b/src/p_map.cpp index 987d83293..e7c477955 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1919,13 +1919,13 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, } //Added by MC: To prevent bot from getting into dangerous sectors. - if (thing->player && thing->player->Bot.isbot && thing->flags & MF_SHOOTABLE) + if (thing->player && thing->player->Bot != NULL && thing->flags & MF_SHOOTABLE) { if (tm.sector != thing->Sector && bglobal.IsDangerous(tm.sector)) { - thing->player->Bot.prev = thing->player->Bot.dest; - thing->player->Bot.dest = NULL; + thing->player->Bot->prev = thing->player->Bot->dest; + thing->player->Bot->dest = NULL; thing->velx = 0; thing->vely = 0; thing->z = oldz; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index e023a7181..a67b96dfb 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3116,7 +3116,7 @@ void AActor::Tick () special2++; } //Added by MC: Freeze mode. - if (bglobal.freeze && !(player && !player->Bot.isbot)) + if (bglobal.freeze && !(player && player->Bot == NULL)) { return; } @@ -3237,18 +3237,18 @@ void AActor::Tick () bglobal.m_Thinking = true; for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i] || !players[i].Bot.isbot) + if (!playeringame[i] || players[i].Bot == NULL) continue; if (flags3 & MF3_ISMONSTER) { if (health > 0 - && !players[i].Bot.enemy + && !players[i].Bot->enemy && player ? !IsTeammate (players[i].mo) : true && P_AproxDistance (players[i].mo->x-x, players[i].mo->y-y) < MAX_MONSTER_TARGET_DIST && P_CheckSight (players[i].mo, this, SF_SEEPASTBLOCKEVERYTHING)) { //Probably a monster, so go kill it. - players[i].Bot.enemy = this; + players[i].Bot->enemy = this; } } else if (flags & MF_SPECIAL) @@ -3260,10 +3260,10 @@ void AActor::Tick () } else if (flags & MF_MISSILE) { - if (!players[i].Bot.missile && (flags3 & MF3_WARNBOT)) + if (!players[i].Bot->missile && (flags3 & MF3_WARNBOT)) { //warn for incoming missiles. if (target != players[i].mo && bglobal.Check_LOS (players[i].mo, this, ANGLE_90)) - players[i].Bot.missile = this; + players[i].Bot->missile = this; } } } diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index e050bff16..6e699a41b 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -227,7 +227,7 @@ void P_FireWeapon (player_t *player, FState *state) // [SO] 9/2/02: People were able to do an awful lot of damage // when they were observers... - if (!player->Bot.isbot && bot_observer) + if (player->Bot == NULL && bot_observer) { return; } @@ -263,7 +263,7 @@ void P_FireWeaponAlt (player_t *player, FState *state) // [SO] 9/2/02: People were able to do an awful lot of damage // when they were observers... - if (!player->Bot.isbot && bot_observer) + if (player->Bot == NULL && bot_observer) { return; } @@ -298,7 +298,7 @@ void P_FireWeaponAlt (player_t *player, FState *state) void P_ReloadWeapon (player_t *player, FState *state) { AWeapon *weapon; - if (!player->Bot.isbot && bot_observer) + if (player->Bot == NULL && bot_observer) { return; } @@ -329,7 +329,7 @@ void P_ReloadWeapon (player_t *player, FState *state) void P_ZoomWeapon (player_t *player, FState *state) { AWeapon *weapon; - if (!player->Bot.isbot && bot_observer) + if (player->Bot == NULL && bot_observer) { return; } diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index dd72a9cc8..5e9ecbdba 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -271,7 +271,7 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name) dst->cheats |= chasecam; - if (dst->Bot.isbot) + if (dst->Bot != NULL) { botinfo_t *thebot = bglobal.botinfo; while (thebot && stricmp (name, thebot->name)) @@ -283,7 +283,6 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name) thebot->inuse = true; } bglobal.botnum++; - bglobal.botingame[dst - players] = true; dst->userinfo.TransferFrom(uibackup2); } else diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 1a6e1e498..44fe88110 100644 --- a/src/p_tick.cpp +++ b/src/p_tick.cpp @@ -120,7 +120,7 @@ void P_Ticker (void) for (i = 0; iTick (); // [RH] moved this here diff --git a/src/p_user.cpp b/src/p_user.cpp index ee6957002..2036309ea 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -293,6 +293,7 @@ player_t::player_t() respawn_time(0), camera(0), air_finished(0), + Bot(0), BlendR(0), BlendG(0), BlendB(0), @@ -311,7 +312,6 @@ player_t::player_t() memset (&cmd, 0, sizeof(cmd)); memset (frags, 0, sizeof(frags)); memset (psprites, 0, sizeof(psprites)); - memset (&Bot, 0, sizeof(Bot)); } player_t &player_t::operator=(const player_t &p) @@ -379,29 +379,7 @@ player_t &player_t::operator=(const player_t &p) camera = p.camera; air_finished = p.air_finished; LastDamageType = p.LastDamageType; - Bot.savedyaw = p.Bot.savedyaw; - Bot.savedpitch = p.Bot.savedpitch; - Bot.angle = p.Bot.angle; - Bot.dest = p.Bot.dest; - Bot.prev = p.Bot.prev; - Bot.enemy = p.Bot.enemy; - Bot.missile = p.Bot.missile; - Bot.mate = p.Bot.mate; - Bot.last_mate = p.Bot.last_mate; - Bot.skill = p.Bot.skill; - Bot.t_active = p.Bot.t_active; - Bot.t_respawn = p.Bot.t_respawn; - Bot.t_strafe = p.Bot.t_strafe; - Bot.t_react = p.Bot.t_react; - Bot.t_fight = p.Bot.t_fight; - Bot.t_roam = p.Bot.t_roam; - Bot.t_rocket = p.Bot.t_rocket; - Bot.isbot = p.Bot.isbot; - Bot.first_shot = p.Bot.first_shot; - Bot.sleft = p.Bot.sleft; - Bot.allround = p.Bot.allround; - Bot.oldx = p.Bot.oldx; - Bot.oldy = p.Bot.oldy; + Bot = p.Bot; settings_controller = p.settings_controller; BlendR = p.BlendR; BlendG = p.BlendG; @@ -444,12 +422,7 @@ size_t player_t::FixPointers (const DObject *old, DObject *rep) if (*&poisoner == old) poisoner = replacement, changed++; if (*&attacker == old) attacker = replacement, changed++; if (*&camera == old) camera = replacement, changed++; - if (*&Bot.dest == old) Bot.dest = replacement, changed++; - if (*&Bot.prev == old) Bot.prev = replacement, changed++; - if (*&Bot.enemy == old) Bot.enemy = replacement, changed++; - if (*&Bot.missile == old) Bot.missile = replacement, changed++; - if (*&Bot.mate == old) Bot.mate = replacement, changed++; - if (*&Bot.last_mate == old) Bot.last_mate = replacement, changed++; + if (*&Bot == old) Bot = static_cast(rep), changed++; if (ReadyWeapon == old) ReadyWeapon = static_cast(rep), changed++; if (PendingWeapon == old) PendingWeapon = static_cast(rep), changed++; if (*&PremorphWeapon == old) PremorphWeapon = static_cast(rep), changed++; @@ -464,12 +437,7 @@ size_t player_t::PropagateMark() GC::Mark(poisoner); GC::Mark(attacker); GC::Mark(camera); - GC::Mark(Bot.dest); - GC::Mark(Bot.prev); - GC::Mark(Bot.enemy); - GC::Mark(Bot.missile); - GC::Mark(Bot.mate); - GC::Mark(Bot.last_mate); + GC::Mark(Bot); GC::Mark(ReadyWeapon); GC::Mark(ConversationNPC); GC::Mark(ConversationPC); @@ -718,10 +686,10 @@ void APlayerPawn::SetupWeaponSlots() // If we're the local player, then there's a bit more work to do. // This also applies if we're a bot and this is the net arbitrator. if (player - players == consoleplayer || - (player->Bot.isbot && consoleplayer == Net_Arbitrator)) + (player->Bot != NULL && consoleplayer == Net_Arbitrator)) { FWeaponSlots local_slots(player->weapons); - if (player->Bot.isbot) + if (player->Bot != NULL) { // Bots only need weapons from KEYCONF, not INI modifications. P_PlaybackKeyConfWeapons(&local_slots); } @@ -2153,7 +2121,7 @@ void P_DeathThink (player_t *player) if ((player->cmd.ucmd.buttons & BT_USE || ((multiplayer || alwaysapplydmflags) && (dmflags & DF_FORCE_RESPAWN))) && !(dmflags2 & DF2_NO_RESPAWN)) { - if (level.time >= player->respawn_time || ((player->cmd.ucmd.buttons & BT_USE) && !player->Bot.isbot)) + if (level.time >= player->respawn_time || ((player->cmd.ucmd.buttons & BT_USE) && player->Bot == NULL)) { player->cls = NULL; // Force a new class if the player is using a random class player->playerstate = (multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN)) ? PST_REBORN : PST_ENTER; @@ -2985,9 +2953,17 @@ void player_t::Serialize (FArchive &arc) << respawn_time << air_finished << turnticks - << oldbuttons - << Bot.isbot - << BlendR + << oldbuttons; + bool IsBot; + if (SaveVersion >= 4514) + { + arc << Bot; + } + else + { + arc << IsBot; + } + arc << BlendR << BlendG << BlendB << BlendA; @@ -3070,32 +3046,30 @@ void player_t::Serialize (FArchive &arc) onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (cheats & CF_NOCLIP2); } - if (Bot.isbot) + if (SaveVersion < 4514 && IsBot) { - arc << Bot.angle - << Bot.dest - << Bot.prev - << Bot.enemy - << Bot.missile - << Bot.mate - << Bot.last_mate - << Bot.skill - << Bot.t_active - << Bot.t_respawn - << Bot.t_strafe - << Bot.t_react - << Bot.t_fight - << Bot.t_roam - << Bot.t_rocket - << Bot.first_shot - << Bot.sleft - << Bot.allround - << Bot.oldx - << Bot.oldy; - } - else - { - Bot.dest = Bot.prev = Bot.enemy = Bot.missile = Bot.mate = Bot.last_mate = NULL; + Bot = new DBot; + + arc << Bot->angle + << Bot->dest + << Bot->prev + << Bot->enemy + << Bot->missile + << Bot->mate + << Bot->last_mate + << Bot->skill + << Bot->t_active + << Bot->t_respawn + << Bot->t_strafe + << Bot->t_react + << Bot->t_fight + << Bot->t_roam + << Bot->t_rocket + << Bot->first_shot + << Bot->sleft + << Bot->allround + << Bot->oldx + << Bot->oldy; } if (arc.IsLoading ()) { diff --git a/src/version.h b/src/version.h index a7226d8bb..d9597d2f4 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 4513 +#define SAVEVER 4514 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 9e773993b..02492f272 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -1330,7 +1330,7 @@ void WI_updateDeathmatchStats () for (i = 0; i < MAXPLAYERS; i++) { // If the player is in the game and not ready, stop checking - if (playeringame[i] && !players[i].Bot.isbot && !playerready[i]) + if (playeringame[i] && players[i].Bot == NULL && !playerready[i]) break; } @@ -1429,7 +1429,7 @@ void WI_drawDeathmatchStats () clamp(int(g*255.f), 0, 255), clamp(int(b*255.f), 0, 255)), 0.8f, x, y - ypadding, (deaths_x - x) + (8 * CleanXfac), lineheight); - if (playerready[pnum] || player->Bot.isbot) // Bots are automatically assumed ready, to prevent confusion + if (playerready[pnum] || player->Bot != NULL) // Bots are automatically assumed ready, to prevent confusion screen->DrawTexture(readyico, x - (readyico->GetWidth() * CleanXfac), y, DTA_CleanNoMove, true, TAG_DONE); color = (EColorRange)HU_GetRowColor(player, pnum == consoleplayer); @@ -1638,7 +1638,7 @@ void WI_updateNetgameStats () for (i = 0; i < MAXPLAYERS; i++) { // If the player is in the game and not ready, stop checking - if (playeringame[i] && !players[i].Bot.isbot && !playerready[i]) + if (playeringame[i] && players[i].Bot == NULL && !playerready[i]) break; } @@ -1735,7 +1735,7 @@ void WI_drawNetgameStats () clamp(int(g*255.f), 0, 255), clamp(int(b*255.f), 0, 255)), 0.8f, x, y - ypadding, (secret_x - x) + (8 * CleanXfac), lineheight); - if (playerready[i] || player->Bot.isbot) // Bots are automatically assumed ready, to prevent confusion + if (playerready[i] || player->Bot != NULL) // Bots are automatically assumed ready, to prevent confusion screen->DrawTexture(readyico, x - (readyico->GetWidth() * CleanXfac), y, DTA_CleanNoMove, true, TAG_DONE); color = (EColorRange)HU_GetRowColor(player, i == consoleplayer); @@ -2010,7 +2010,7 @@ void WI_checkForAccelerate(void) { if ((player->cmd.ucmd.buttons ^ player->oldbuttons) && ((players[i].cmd.ucmd.buttons & players[i].oldbuttons) - == players[i].oldbuttons) && !player->Bot.isbot) + == players[i].oldbuttons) && player->Bot == NULL) { acceleratestage = 1; playerready[i] = true;