From 83d84eaae9e4e13e92c1ec585855fddd276eb2dc Mon Sep 17 00:00:00 2001 From: ChillyDoom Date: Mon, 13 Oct 2014 18:40:25 +0100 Subject: [PATCH 01/39] - Moved bot related variables from player_t into a new FBot class. --- src/b_bot.h | 43 ++++++++++ src/b_func.cpp | 62 ++++++------- src/b_game.cpp | 40 ++++----- src/b_move.cpp | 30 +++---- src/b_think.cpp | 172 ++++++++++++++++++------------------- src/d_main.cpp | 12 +-- src/d_net.cpp | 27 +++--- src/d_player.h | 39 +-------- src/g_game.cpp | 18 ++-- src/g_shared/a_pickups.cpp | 4 +- src/p_acs.cpp | 4 +- src/p_doors.cpp | 2 +- src/p_interaction.cpp | 28 +++--- src/p_map.cpp | 6 +- src/p_mobj.cpp | 12 +-- src/p_pspr.cpp | 8 +- src/p_saveg.cpp | 2 +- src/p_tick.cpp | 2 +- src/p_user.cpp | 146 +++++++++++++------------------ src/wi_stuff.cpp | 10 +-- 20 files changed, 324 insertions(+), 343 deletions(-) diff --git a/src/b_bot.h b/src/b_bot.h index d178a85faf..c82ed03d12 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -145,6 +145,49 @@ protected: bool observer; //Consoleplayer is observer. }; +class FBot +{ +public: + 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) + TObjPtr dest; // Move Destination. + TObjPtr prev; // Previous move destination. + + + TObjPtr enemy; // The dead meat. + TObjPtr missile; // A threatening missile that needs to be avoided. + TObjPtr mate; // Friend (used for grouping in teamplay or coop). + TObjPtr last_mate; // If bots mate disappeared (not if died) that mate is + // pointed to by this. Allows bot to roam to it if + // necessary. + + //Skills + struct botskill_t skill; + + //Tickers + int t_active; // Open door, lower lift stuff, door must open and + // lift must go down before bot does anything + // radical like try a stuckmove + int t_respawn; + int t_strafe; + int t_react; + int t_fight; + int t_roam; + int t_rocket; + + //Misc booleans + bool isbot; + bool first_shot; // Used for reaction skill. + bool sleft; // If false, strafe is right. + bool allround; + + fixed_t oldx; + fixed_t oldy; +}; + //Externs extern FCajunMaster bglobal; diff --git a/src/b_func.cpp b/src/b_func.cpp index 2703a19337..8d2df6949e 100644 --- a/src/b_func.cpp +++ b/src/b_func.cpp @@ -141,7 +141,7 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd) angle_t an; int m; static bool inc[MAXPLAYERS]; - AActor *enemy = actor->player->enemy; + AActor *enemy = actor->player->Bot.enemy; if (!enemy || !(enemy->flags & MF_SHOOTABLE) || enemy->health <= 0) return; @@ -149,20 +149,20 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd) if (actor->player->ReadyWeapon == NULL) return; - if (actor->player->damagecount > actor->player->skill.isp) + if (actor->player->damagecount > actor->player->Bot.skill.isp) { - actor->player->first_shot = true; + actor->player->Bot.first_shot = true; return; } //Reaction skill thing. - if (actor->player->first_shot && + if (actor->player->Bot.first_shot && !(actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_REACTION_SKILL_THING)) { - actor->player->t_react = (100-actor->player->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->first_shot = false; - if (actor->player->t_react) + actor->player->Bot.first_shot = false; + if (actor->player->Bot.t_react) return; //MAKEME: Decrease the rocket suicides even more. @@ -199,8 +199,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->skill.reaction) - if(Check_LOS(actor, actor->player->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 +211,11 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd) an = FireRox (actor, enemy, cmd); if(an) { - actor->player->angle = an; + actor->player->Bot.angle = an; //have to be somewhat precise. to avoid suicide. - if (abs (actor->player->angle - actor->angle) < 12*ANGLE_1) + if (abs (actor->player->Bot.angle - actor->angle) < 12*ANGLE_1) { - actor->player->t_rocket = 9; + actor->player->Bot.t_rocket = 9; no_fire = false; } } @@ -225,14 +225,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->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->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 +240,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->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 @@ -250,12 +250,12 @@ shootmissile: if (m) { if (inc[actor->player - players]) - actor->player->angle += m; + actor->player->Bot.angle += m; else - actor->player->angle -= m; + actor->player->Bot.angle -= m; } - if (abs (actor->player->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]; } @@ -285,20 +285,20 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot) bool p_leader[MAXPLAYERS]; //is mate alive? - if (bot->player->mate) + if (bot->player->Bot.mate) { - if (bot->player->mate->health <= 0) - bot->player->mate = NULL; + if (bot->player->Bot.mate->health <= 0) + bot->player->Bot.mate = NULL; else - bot->player->last_mate = bot->player->mate; + bot->player->Bot.last_mate = bot->player->Bot.mate; } - if (bot->player->mate) //Still is.. - return bot->player->mate; + if (bot->player->Bot.mate) //Still is.. + return bot->player->Bot.mate; //Check old_mates status. - if (bot->player->last_mate) - if (bot->player->last_mate->health <= 0) - bot->player->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 +307,8 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot) p_leader[count] = false; for (count2 = 0; count2 < MAXPLAYERS; count2++) { - if (players[count].isbot - && players[count2].mate == players[count].mo) + if (players[count].Bot.isbot + && players[count2].Bot.mate == players[count].mo) { p_leader[count] = true; break; @@ -386,11 +386,11 @@ AActor *FCajunMaster::Find_enemy (AActor *bot) } //Note: It's hard to ambush a bot who is not alone - if (bot->player->allround || bot->player->mate) + if (bot->player->Bot.allround || bot->player->Bot.mate) vangle = ANGLE_MAX; else vangle = ENEMY_SCAN_FOV; - bot->player->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 f3878b8bbf..e3f3c97d63 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].isbot) + if (playeringame[i] && players[i].mo && !freeze && players[i].Bot.isbot) Think (players[i].mo, &netcmds[i][buf]); } BotThinkCycles.Unclock(); @@ -176,10 +176,10 @@ void FCajunMaster::Init () for (i = 0; i < MAXPLAYERS; i++) { waitingforspawn[i] = false; - if (playeringame[i] && players[i].isbot) + if (playeringame[i] && players[i].Bot.isbot) { CleanBotstuff (&players[i]); - players[i].isbot = false; + players[i].Bot.isbot = false; botingame[i] = false; } } @@ -214,7 +214,7 @@ void FCajunMaster::End () getspawned.Clear(); for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && players[i].isbot) + if (playeringame[i] && players[i].Bot.isbot) { if (deathmatch) { @@ -336,7 +336,7 @@ bool FCajunMaster::SpawnBot (const char *name, int color) Net_WriteString (concat); } - players[playernumber].skill = thebot->skill; + players[playernumber].Bot.skill = thebot->skill; thebot->inuse = true; @@ -363,7 +363,7 @@ void FCajunMaster::DoAddBot (int bnum, char *info) else { multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost). - players[bnum].isbot = true; + players[bnum].Bot.isbot = true; playeringame[bnum] = true; players[bnum].mo = NULL; players[bnum].playerstate = PST_ENTER; @@ -425,22 +425,22 @@ void FCajunMaster::RemoveAllBots (bool fromlist) //Used when bots are respawned or at level starts. void FCajunMaster::CleanBotstuff (player_t *p) { - p->angle = ANG45; - p->dest = NULL; - p->enemy = NULL; //The dead meat. - p->missile = NULL; //A threatening missile that needs to be avoided. - p->mate = NULL; //Friend (used for grouping in templay or coop. - p->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. + 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->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->t_respawn = 0; - p->t_strafe = 0; - p->t_react = 0; + 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->isbot = true; //Important. - p->first_shot = true; //Used for reaction skill. - p->sleft = false; //If false, strafe is right. - p->allround = false; + 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; } diff --git a/src/b_move.cpp b/src/b_move.cpp index 0345bccfb4..1f2e4c3322 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->dest)) + if (Reachable(actor, actor->player->Bot.dest)) { // Straight towards it. - actor->player->angle = R_PointToAngle2(actor->x, actor->y, actor->player->dest->x, actor->player->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->angle &= (angle_t)(7<<29); - delta = actor->player->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->angle -= ANG45; + actor->player->Bot.angle -= ANG45; else if (delta < 0) - actor->player->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->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->dest->x - actor->x; - deltay = actor->player->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->t_roam && !actor->player->missile) + if (actor->player->Bot.t_roam && !actor->player->Bot.missile) { //Keep angle that where when shot where decided. return; } } - if(actor->player->enemy) - if(!actor->player->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->enemy, SHOOTFOV+5*ANGLE_1)) + if(Check_LOS(actor, actor->player->Bot.enemy, SHOOTFOV+5*ANGLE_1)) maxturn = 3; } - int distance = actor->player->angle - actor->angle; + int distance = actor->player->Bot.angle - actor->angle; - if (abs (distance) < OKAYRANGE && !actor->player->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 cc7f087e66..a5deec3720 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->enemy && actor->player->enemy->health <= 0) - actor->player->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->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->t_active) actor->player->t_active--; - if (actor->player->t_strafe) actor->player->t_strafe--; - if (actor->player->t_react) actor->player->t_react--; - if (actor->player->t_fight) actor->player->t_fight--; - if (actor->player->t_rocket) actor->player->t_rocket--; - if (actor->player->t_roam) actor->player->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->t_respawn) + if (actor->player->Bot.t_respawn) { - actor->player->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->isbot) + if (!b->Bot.isbot) return; stuck = false; - dist = b->dest ? P_AproxDistance(actor->x-b->dest->x, actor->y-b->dest->y) : 0; + dist = b->Bot.dest ? P_AproxDistance(actor->x-b->Bot.dest->x, actor->y-b->Bot.dest->y) : 0; - if (b->missile && - ((!b->missile->velx || !b->missile->vely) || !Check_LOS(actor, b->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->sleft = !b->sleft; - b->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->missile && (P_AproxDistance(actor->x-b->missile->x, actor->y-b->missile->y)Bot.missile && (P_AproxDistance(actor->x-b->Bot.missile->x, actor->y-b->Bot.missile->y)missile); - actor->player->angle = R_PointToAngle2(actor->x, actor->y, b->missile->x, b->missile->y); - cmd->ucmd.sidemove = b->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->oldx, actor->y-b->oldy)<50000) - && b->t_strafe<=0) + if ((P_AproxDistance(actor->x-b->Bot.oldx, actor->y-b->Bot.oldy)<50000) + && b->Bot.t_strafe<=0) { - b->t_strafe = 5; - b->sleft = !b->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->enemy && Check_LOS (actor, b->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->enemy && P_CheckSight (actor, b->enemy, 0)) //Fight! + else if (b->Bot.enemy && P_CheckSight (actor, b->Bot.enemy, 0)) //Fight! { - Pitch (actor, b->enemy); + Pitch (actor, b->Bot.enemy); //Check if it's more important to get an item than fight. - if (b->dest && (b->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->dest->IsKindOf (PClass::FindClass (#x)) +#define is(x) b->Bot.dest->IsKindOf (PClass::FindClass (#x)) if ( ( - (actor->health < b->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->dest)) + && Reachable (actor, b->Bot.dest)) #undef is { goto roam; //Pick it up, no matter the situation. All bonuses are nice close up. } } - b->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->enemy->flags3 & MF3_ISMONSTER)) - b->t_fight = AFTERTICS; + if (!(b->Bot.enemy->flags3 & MF3_ISMONSTER)) + b->Bot.t_fight = AFTERTICS; - if (b->t_strafe <= 0 && - (P_AproxDistance(actor->x-b->oldx, actor->y-b->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->t_strafe = 5; - b->sleft = !b->sleft; + b->Bot.t_strafe = 5; + b->Bot.sleft = !b->Bot.sleft; } - b->angle = R_PointToAngle2(actor->x, actor->y, b->enemy->x, b->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->enemy->x, actor->y-b->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->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->enemy->flags3 & MF3_ISMONSTER) ? -FORWARDWALK : -FORWARDRUN; + cmd->ucmd.forwardmove = (b->Bot.enemy->flags3 & MF3_ISMONSTER) ? -FORWARDWALK : -FORWARDRUN; } //Strafing. - if (b->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->sleft ? -SIDEWALK : SIDEWALK; + cmd->ucmd.sidemove = b->Bot.sleft ? -SIDEWALK : SIDEWALK; } else { - cmd->ucmd.sidemove = b->sleft ? -SIDERUN : SIDERUN; + cmd->ucmd.sidemove = b->Bot.sleft ? -SIDERUN : SIDERUN; } Dofire (actor, cmd); //Order bot to fire current weapon } - else if (b->mate && !b->enemy && (!b->dest || b->dest==b->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->mate); + Pitch (actor, b->Bot.mate); - if (!Reachable (actor, b->mate)) + if (!Reachable (actor, b->Bot.mate)) { - if (b->mate == b->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->dest = NULL; + b->Bot.dest = NULL; } goto roam; } - actor->player->angle = R_PointToAngle2(actor->x, actor->y, b->mate->x, b->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->mate->x, actor->y - b->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->first_shot = true; + b->Bot.first_shot = true; ///// roam: ///// - if (b->enemy && Check_LOS (actor, b->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->dest && !(b->dest->flags&MF_SPECIAL) && b->dest->health < 0) + if (b->Bot.dest && !(b->Bot.dest->flags&MF_SPECIAL) && b->Bot.dest->health < 0) { //Roaming after something dead. - b->dest = NULL; + b->Bot.dest = NULL; } - if (b->dest == NULL) + if (b->Bot.dest == NULL) { - if (b->t_fight && b->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->enemy->player) + if (b->Bot.enemy->player) { - if (((b->enemy->player->ReadyWeapon != NULL && b->enemy->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE) || - (pr_botmove()%100)>b->skill.isp) && b->ReadyWeapon != NULL && !(b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)) - b->dest = b->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->angle = R_PointToAngle2(actor->x, actor->y, b->enemy->x, b->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->dest = b->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->dest = item; + b->Bot.dest = item; } } - else if (b->mate && (r < 179 || P_CheckSight(actor, b->mate))) + else if (b->Bot.mate && (r < 179 || P_CheckSight(actor, b->Bot.mate))) { - b->dest = b->mate; + b->Bot.dest = b->Bot.mate; } else if ((playeringame[(r&(MAXPLAYERS-1))]) && players[(r&(MAXPLAYERS-1))].mo->health > 0) { - b->dest = players[(r&(MAXPLAYERS-1))].mo; + b->Bot.dest = players[(r&(MAXPLAYERS-1))].mo; } } - if (b->dest) + if (b->Bot.dest) { - b->t_roam = MAXROAM; + b->Bot.t_roam = MAXROAM; } } - if (b->dest) + if (b->Bot.dest) { //Bot has a target so roam after it. Roam (actor, cmd); } } //End of movement main part. - if (!b->t_roam && b->dest) + if (!b->Bot.t_roam && b->Bot.dest) { - b->prev = b->dest; - b->dest = NULL; + b->Bot.prev = b->Bot.dest; + b->Bot.dest = NULL; } - if (b->t_fight<(AFTERTICS/2)) + if (b->Bot.t_fight<(AFTERTICS/2)) actor->flags |= MF_DROPOFF; - b->oldx = actor->x; - b->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->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->dest == NULL || - !(b->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->prev = b->dest; - b->dest = item; - b->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->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->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 a24586bc4d..9ce300e01a 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].isbot && players[i].mo) + if (playeringame[i] && players[i].Bot.isbot && players[i].mo) { - players[i].savedyaw = players[i].mo->angle; - players[i].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].isbot && players[i].mo) + if (playeringame[i] && players[i].Bot.isbot && players[i].mo) { - players[i].mo->angle = players[i].savedyaw; - players[i].mo->pitch = players[i].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 bc4bc73523..dfc76f785d 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].isbot) + if (i != netconsole && playeringame[i] && !players[i].Bot.isbot) { 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]].isbot ? + int node = !players[playerbytes[i]].Bot.isbot ? 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]].isbot) + if (!players[playerbytes[i]].Bot.isbot) { 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].isbot && players[i].mo) + if (playeringame[i] && players[i].Bot.isbot && players[i].mo) { - players[i].savedyaw = players[i].mo->angle; - players[i].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].isbot && players[i].mo) + if (playeringame[i] && players[i].Bot.isbot && players[i].mo) { - players[i].mo->angle = players[i].savedyaw; - players[i].mo->pitch = players[i].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].isbot || NetMode == NET_PacketServer) + if (players[j].Bot.isbot || NetMode == NET_PacketServer) { count++; } @@ -1269,7 +1269,7 @@ void NetUpdate (void) { if (playeringame[j] && j != playerfornode[i] && j != consoleplayer) { - if (players[j].isbot || NetMode == NET_PacketServer) + if (players[j].Bot.isbot || NetMode == NET_PacketServer) { playerbytes[l++] = j; netbuffer[k++] = j; @@ -1308,9 +1308,8 @@ void NetUpdate (void) } else if (i != 0) { - if (players[playerbytes[l]].isbot) + if (players[playerbytes[l]].Bot.isbot) { - WriteWord (0, &cmddata); // fake consistancy word } else @@ -2875,7 +2874,7 @@ static void Network_Controller (int playernum, bool add) return; } - if (players[playernum].isbot) + if (players[playernum].Bot.isbot) { Printf ("Bots cannot be added to the controller list.\n"); return; diff --git a/src/d_player.h b/src/d_player.h index 5affd6913c..055cb75b4f 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -442,47 +442,10 @@ public: FName LastDamageType; // [RH] For damage-specific pain and death sounds //Added by MC: - 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) - TObjPtr dest; // Move Destination. - TObjPtr prev; // Previous move destination. - - - TObjPtr enemy; // The dead meat. - TObjPtr missile; // A threatening missile that needs to be avoided. - TObjPtr mate; // Friend (used for grouping in teamplay or coop). - TObjPtr last_mate; // If bots mate disappeared (not if died) that mate is - // pointed to by this. Allows bot to roam to it if - // necessary. + FBot Bot; bool settings_controller; // Player can control game settings. - //Skills - struct botskill_t skill; - - //Tickers - int t_active; // Open door, lower lift stuff, door must open and - // lift must go down before bot does anything - // radical like try a stuckmove - int t_respawn; - int t_strafe; - int t_react; - int t_fight; - int t_roam; - int t_rocket; - - //Misc booleans - bool isbot; - bool first_shot; // Used for reaction skill. - bool sleft; // If false, strafe is right. - bool allround; - - fixed_t oldx; - fixed_t oldy; - float BlendR; // [RH] Final blending values float BlendG; float BlendB; diff --git a/src/g_game.cpp b/src/g_game.cpp index 95b0f587d8..3d166492e0 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].isbot))) + (bot_allowspy && players[pnum].Bot.isbot))) { break; } @@ -1156,7 +1156,7 @@ void G_Ticker () Printf ("%s is turbo!\n", players[i].userinfo.GetName()); } - if (netgame && !players[i].isbot && !demoplayback && (gametic%ticdup) == 0) + if (netgame && !players[i].Bot.isbot && !demoplayback && (gametic%ticdup) == 0) { //players[i].inconsistant = 0; if (gametic > BACKUPTICS*ticdup && consistancy[i][buf] != cmd->consistancy) @@ -1351,7 +1351,7 @@ void G_PlayerReborn (int player) itemcount = p->itemcount; secretcount = p->secretcount; currclass = p->CurrentPlayerClass; - b_skill = p->skill; //Added by MC: + b_skill = p->Bot.skill; //Added by MC: userinfo.TransferFrom(p->userinfo); actor = p->mo; cls = p->cls; @@ -1374,7 +1374,7 @@ void G_PlayerReborn (int player) p->LogText = log; p->cheats |= chasecam; - p->skill = b_skill; //Added by MC: + p->Bot.skill = b_skill; //Added by MC: p->oldbuttons = ~0, p->attackdown = true; p->usedown = true; // don't do anything immediately p->original_oldbuttons = ~0; @@ -1386,11 +1386,11 @@ void G_PlayerReborn (int player) p->ReadyWeapon = p->PendingWeapon; } - //Added by MC: Init bot structure. - if (bglobal.botingame[player]) - bglobal.CleanBotstuff (p); - else - p->isbot = false; + //Added by MC: Init bot structure. + if (bglobal.botingame[player]) + bglobal.CleanBotstuff (p); + else + p->Bot.isbot = false; } // diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 429cb649b8..4836ae0332 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].dest) - players[i].dest = NULL; + if (playeringame[i] && this == players[i].Bot.dest) + players[i].Bot.dest = NULL; } } diff --git a/src/p_acs.cpp b/src/p_acs.cpp index bc4cbdb758..d2780b4e49 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->isbot) + if (actor->player->Bot.isbot) { classify |= ACTOR_BOT; } @@ -8632,7 +8632,7 @@ scriptwait: } else { - STACK(1) = players[STACK(1)].isbot; + STACK(1) = players[STACK(1)].Bot.isbot; } break; diff --git a/src/p_doors.cpp b/src/p_doors.cpp index 7c6952d7f2..de45195058 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->isbot) + if (!thing->player || thing->player->Bot.isbot) 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 c3be908ea8..1dcf0ebad9 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->isbot && special == toucher->player->dest) + if (toucher->player != NULL && toucher->player->Bot.isbot && special == toucher->player->Bot.dest) { - toucher->player->prev = toucher->player->dest; - toucher->player->dest = NULL; + toucher->player->Bot.prev = toucher->player->Bot.dest; + toucher->player->Bot.dest = NULL; } special->Touch (toucher); @@ -593,7 +593,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) // even those caused by other monsters players[0].killcount++; } - + if (player) { // [RH] Death messages @@ -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->isbot) - player->t_respawn = (pr_botrespawn()%15)+((bglobal.botnum-1)*2)+TICRATE+1; + if (player->Bot.isbot) + 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].isbot && this == players[i].enemy) + if (players[i].Bot.isbot && this == players[i].Bot.enemy) { - if (players[i].dest == players[i].enemy) - players[i].dest = NULL; - players[i].enemy = NULL; + if (players[i].Bot.dest == players[i].Bot.enemy) + players[i].Bot.dest = NULL; + players[i].Bot.enemy = NULL; } } @@ -1193,11 +1193,10 @@ 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->isbot) + //Added by MC: Lets bots look allround for enemies if they survive an ambush. + if (player->Bot.isbot) { - player->allround = true; + player->Bot.allround = true; } // end of game hell hack @@ -1711,7 +1710,6 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, P_SetMobjState(target, target->info->painstate); } */ - return; } diff --git a/src/p_map.cpp b/src/p_map.cpp index f0087e2201..987d832934 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->isbot && thing->flags & MF_SHOOTABLE) + if (thing->player && thing->player->Bot.isbot && thing->flags & MF_SHOOTABLE) { if (tm.sector != thing->Sector && bglobal.IsDangerous(tm.sector)) { - thing->player->prev = thing->player->dest; - thing->player->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 3e06561a9d..e023a7181e 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->isbot)) + if (bglobal.freeze && !(player && !player->Bot.isbot)) { return; } @@ -3237,18 +3237,18 @@ void AActor::Tick () bglobal.m_Thinking = true; for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i] || !players[i].isbot) + if (!playeringame[i] || !players[i].Bot.isbot) continue; if (flags3 & MF3_ISMONSTER) { if (health > 0 - && !players[i].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].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].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].missile = this; + players[i].Bot.missile = this; } } } diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index e477d97519..e050bff161 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->isbot && bot_observer) + if (!player->Bot.isbot && 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->isbot && bot_observer) + if (!player->Bot.isbot && 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->isbot && bot_observer) + if (!player->Bot.isbot && 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->isbot && bot_observer) + if (!player->Bot.isbot && bot_observer) { return; } diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index bf0da0cbe3..dd72a9cc83 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->isbot) + if (dst->Bot.isbot) { botinfo_t *thebot = bglobal.botinfo; while (thebot && stricmp (name, thebot->name)) diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 07e153ffa4..1a6e1e498b 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 6595f7309a..ee69570021 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -293,28 +293,6 @@ player_t::player_t() respawn_time(0), camera(0), air_finished(0), - savedyaw(0), - savedpitch(0), - angle(0), - dest(0), - prev(0), - enemy(0), - missile(0), - mate(0), - last_mate(0), - t_active(0), - t_respawn(0), - t_strafe(0), - t_react(0), - t_fight(0), - t_roam(0), - t_rocket(0), - isbot(0), - first_shot(0), - sleft(0), - allround(0), - oldx(0), - oldy(0), BlendR(0), BlendG(0), BlendB(0), @@ -333,7 +311,7 @@ player_t::player_t() memset (&cmd, 0, sizeof(cmd)); memset (frags, 0, sizeof(frags)); memset (psprites, 0, sizeof(psprites)); - memset (&skill, 0, sizeof(skill)); + memset (&Bot, 0, sizeof(Bot)); } player_t &player_t::operator=(const player_t &p) @@ -401,30 +379,30 @@ player_t &player_t::operator=(const player_t &p) camera = p.camera; air_finished = p.air_finished; LastDamageType = p.LastDamageType; - savedyaw = p.savedyaw; - savedpitch = p.savedpitch; - angle = p.angle; - dest = p.dest; - prev = p.prev; - enemy = p.enemy; - missile = p.missile; - mate = p.mate; - last_mate = p.last_mate; + 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; settings_controller = p.settings_controller; - skill = p.skill; - t_active = p.t_active; - t_respawn = p.t_respawn; - t_strafe = p.t_strafe; - t_react = p.t_react; - t_fight = p.t_fight; - t_roam = p.t_roam; - t_rocket = p.t_rocket; - isbot = p.isbot; - first_shot = p.first_shot; - sleft = p.sleft; - allround = p.allround; - oldx = p.oldx; - oldy = p.oldy; BlendR = p.BlendR; BlendG = p.BlendG; BlendB = p.BlendB; @@ -466,12 +444,12 @@ 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 (*&dest == old) dest = replacement, changed++; - if (*&prev == old) prev = replacement, changed++; - if (*&enemy == old) enemy = replacement, changed++; - if (*&missile == old) missile = replacement, changed++; - if (*&mate == old) mate = replacement, changed++; - if (*&last_mate == old) last_mate = 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 (ReadyWeapon == old) ReadyWeapon = static_cast(rep), changed++; if (PendingWeapon == old) PendingWeapon = static_cast(rep), changed++; if (*&PremorphWeapon == old) PremorphWeapon = static_cast(rep), changed++; @@ -486,12 +464,12 @@ size_t player_t::PropagateMark() GC::Mark(poisoner); GC::Mark(attacker); GC::Mark(camera); - GC::Mark(dest); - GC::Mark(prev); - GC::Mark(enemy); - GC::Mark(missile); - GC::Mark(mate); - GC::Mark(last_mate); + 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(ReadyWeapon); GC::Mark(ConversationNPC); GC::Mark(ConversationPC); @@ -740,10 +718,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->isbot && consoleplayer == Net_Arbitrator)) + (player->Bot.isbot && consoleplayer == Net_Arbitrator)) { FWeaponSlots local_slots(player->weapons); - if (player->isbot) + if (player->Bot.isbot) { // Bots only need weapons from KEYCONF, not INI modifications. P_PlaybackKeyConfWeapons(&local_slots); } @@ -2175,7 +2153,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->isbot)) + if (level.time >= player->respawn_time || ((player->cmd.ucmd.buttons & BT_USE) && !player->Bot.isbot)) { 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; @@ -3008,7 +2986,7 @@ void player_t::Serialize (FArchive &arc) << air_finished << turnticks << oldbuttons - << isbot + << Bot.isbot << BlendR << BlendG << BlendB @@ -3092,32 +3070,32 @@ void player_t::Serialize (FArchive &arc) onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF) || (cheats & CF_NOCLIP2); } - if (isbot) + if (Bot.isbot) { - arc << 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 - << oldx - << oldy; + 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 { - dest = prev = enemy = missile = mate = last_mate = NULL; + Bot.dest = Bot.prev = Bot.enemy = Bot.missile = Bot.mate = Bot.last_mate = NULL; } if (arc.IsLoading ()) { diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 2ab93f0905..9e773993b5 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].isbot && !playerready[i]) + if (playeringame[i] && !players[i].Bot.isbot && !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->isbot) // Bots are automatically assumed ready, to prevent confusion + if (playerready[pnum] || player->Bot.isbot) // 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].isbot && !playerready[i]) + if (playeringame[i] && !players[i].Bot.isbot && !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->isbot) // Bots are automatically assumed ready, to prevent confusion + if (playerready[i] || player->Bot.isbot) // 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->isbot) + == players[i].oldbuttons) && !player->Bot.isbot) { acceleratestage = 1; playerready[i] = true; From db323643f81cc3649782b5f5995187d2522a69bf Mon Sep 17 00:00:00 2001 From: ChillyDoom Date: Tue, 14 Oct 2014 19:57:11 +0100 Subject: [PATCH 02/39] - 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 26c8f99bd5..30a8e4877c 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 c82ed03d12..f414a9687b 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 8d2df6949e..0c0ab1ebdd 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 e3f3c97d63..35de6ec868 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 1f2e4c3322..f020cf4fc0 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 a5deec3720..e5ee8775c2 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 9ce300e01a..0303871180 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 dfc76f785d..690a443ef7 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 055cb75b4f..ceb1ff894e 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 028ad1606f..0d11c7760f 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 3d166492e0..fad7d9eb17 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 d84a487768..2d3aeee3ad 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 4836ae0332..a16a1316f0 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 d2780b4e49..afef9ffd31 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 de45195058..844f23af96 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 1dcf0ebad9..6aa1a28f64 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 987d832934..e7c4779551 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 e023a7181e..a67b96dfb9 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 e050bff161..6e699a41b0 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 dd72a9cc83..5e9ecbdba9 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 1a6e1e498b..44fe881100 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 ee69570021..2036309ea5 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 a7226d8bb7..d9597d2f40 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 9e773993b5..02492f272c 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; From c400dcf7365f5624d8a18881244b6675c64389e4 Mon Sep 17 00:00:00 2001 From: ChillyDoom Date: Wed, 15 Oct 2014 17:54:12 +0100 Subject: [PATCH 03/39] - Made DBot inherit from DObject. --- src/b_bot.cpp | 10 ++++++++++ src/b_bot.h | 6 ++++-- src/b_game.cpp | 15 +++++++++++++++ src/g_game.cpp | 20 +++++++++++--------- src/g_level.cpp | 10 ---------- src/p_setup.cpp | 1 + 6 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/b_bot.cpp b/src/b_bot.cpp index 30a8e4877c..3494dc4c46 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -24,6 +24,11 @@ IMPLEMENT_POINTY_CLASS(DBot) END_POINTERS DBot::DBot () +{ + Clear (); +} + +void DBot::Clear () { savedyaw = 0; savedpitch = 0; @@ -123,6 +128,11 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam) bot->inuse = false; bot->lastteam = keepTeam ? players[i].userinfo.GetTeam() : TEAM_NONE; } + if (players[i].Bot != NULL) + { + players[i].Bot->Destroy (); + players[i].Bot = NULL; + } players[i].~player_t(); ::new(&players[i]) player_t; players[i].userinfo.Reset(); diff --git a/src/b_bot.h b/src/b_bot.h index f414a9687b..7844597cde 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -90,6 +90,7 @@ public: void ForgetBots (); void DoAddBot (BYTE **stream); void RemoveAllBots (bool fromlist); + void DestroyAllBots (); //(B_Func.c) bool Check_LOS (AActor *mobj1, AActor *mobj2, angle_t vangle); @@ -143,13 +144,14 @@ protected: bool observer; //Consoleplayer is observer. }; -class DBot : public DThinker +class DBot : public DObject { - DECLARE_CLASS(DBot,DThinker) + DECLARE_CLASS(DBot,DObject) HAS_OBJECT_POINTERS public: DBot (); + void Clear (); void Serialize (FArchive &arc); angle_t savedyaw; diff --git a/src/b_game.cpp b/src/b_game.cpp index 35de6ec868..30c2c483ba 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -352,6 +352,9 @@ void FCajunMaster::DoAddBot (BYTE **stream) skill.isp = ReadByte (stream); D_ReadUserInfoStrings (bnum, &infob, false); + + delete[] info; + if (!deathmatch && playerstarts[bnum].type == 0) { Printf ("%s tried to join, but there was no player %d start\n", @@ -423,6 +426,18 @@ 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 fad7d9eb17..a58753b869 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1341,7 +1341,7 @@ void G_PlayerReborn (int player) APlayerPawn *actor; const PClass *cls; FString log; - DBot *OldBot; //Added by MC: + DBot *Bot; //Added by MC: p = &players[player]; @@ -1356,7 +1356,7 @@ void G_PlayerReborn (int player) cls = p->cls; log = p->LogText; chasecam = p->cheats & CF_CHASECAM; - OldBot = p->Bot; //Added by MC: + Bot = p->Bot; //Added by MC: // Reset player structure to its defaults p->~player_t(); @@ -1373,13 +1373,7 @@ void G_PlayerReborn (int player) p->cls = cls; p->LogText = log; p->cheats |= chasecam; - - //Added by MC: Init bot structure. - if (OldBot != NULL) - { - p->Bot = new DBot; - p->Bot->skill = OldBot->skill; - } + p->Bot = Bot; //Added by MC: p->oldbuttons = ~0, p->attackdown = true; p->usedown = true; // don't do anything immediately p->original_oldbuttons = ~0; @@ -1390,6 +1384,14 @@ void G_PlayerReborn (int player) actor->GiveDefaultInventory (); p->ReadyWeapon = p->PendingWeapon; } + + //Added by MC: Init bot structure. + if (p->Bot != NULL) + { + botskill_t skill = p->Bot->skill; + p->Bot->Clear (); + p->Bot->skill = skill; + } } // diff --git a/src/g_level.cpp b/src/g_level.cpp index 2d3aeee3ad..d84a487768 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1110,11 +1110,6 @@ void G_StartTravel () P_DelSector_List (); } } - - if (players[i].Bot != NULL) - { - players[i].Bot->ChangeStatNum (STAT_TRAVELLING); - } } } } @@ -1189,11 +1184,6 @@ 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/p_setup.cpp b/src/p_setup.cpp index 6b5d9403f0..53b2887986 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -4175,6 +4175,7 @@ static void P_Shutdown () P_FreeLevelData (); P_FreeExtraLevelData (); ST_Clear(); + bglobal.DestroyAllBots (); } #if 0 From 82255c4dfd0a7a8bcc92cda6958f4d951147157b Mon Sep 17 00:00:00 2001 From: John Palomo Jr Date: Sun, 19 Oct 2014 20:52:48 -0400 Subject: [PATCH 04/39] Using PickActor will only set the TID if the picked actor doesn't have a TID already. An optional 8th parameter (bool forceTID) was added to revert to the old behavior. --- src/p_acs.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index bc4cbdb758..aeb47a8075 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5619,15 +5619,27 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) wallMask = args[6]; } + bool forceTID = 0; + if (argCount >= 8) + { + if (args[7] != 0) + forceTID = 1; + } + AActor* pickedActor = P_LinePickActor(actor, args[1] << 16, args[3], args[2] << 16, actorMask, wallMask); if (pickedActor == NULL) { return 0; } - pickedActor->RemoveFromHash(); - pickedActor->tid = args[4]; - pickedActor->AddToHash(); - + if (!(forceTID) && (args[4] == 0) && (pickedActor->tid == 0)) + return 0; + + if ((pickedActor->tid == 0) || (forceTID)) + { + pickedActor->RemoveFromHash(); + pickedActor->tid = args[4]; + pickedActor->AddToHash(); + } return 1; } break; From 759f1bb81bd0c91cdd4f8df72bb3a44f18fc4acd Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Tue, 21 Oct 2014 23:38:45 +1300 Subject: [PATCH 05/39] Fix handshakes between GCC and MSVC u_long has two different sizes between Linux GCC and MSVC Stopped netgames from starting up if player count wont fit --- src/i_net.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/i_net.cpp b/src/i_net.cpp index 6fdcb52ba9..03db5a15c1 100644 --- a/src/i_net.cpp +++ b/src/i_net.cpp @@ -135,7 +135,7 @@ struct PreGamePacket }; struct { - u_long address; + DWORD address; u_short port; BYTE player; BYTE pad; @@ -660,6 +660,12 @@ void HostGame (int i) numplayers = 2; } + if (numplayers > MAXNETNODES) + { + I_FatalError("You cannot host a game with %d players. The limit is currently %d.", numplayers, MAXNETNODES); + return; + } + if (numplayers == 1) { // Special case: Only 1 player, so don't bother starting the network netgame = false; From ed5108357269f07964a876ba0e893090dc3b3f67 Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Tue, 21 Oct 2014 23:44:14 +1300 Subject: [PATCH 06/39] Change u_short as well. --- src/i_net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i_net.cpp b/src/i_net.cpp index 03db5a15c1..188d2871e3 100644 --- a/src/i_net.cpp +++ b/src/i_net.cpp @@ -136,7 +136,7 @@ struct PreGamePacket struct { DWORD address; - u_short port; + WORD port; BYTE player; BYTE pad; } machines[MAXNETNODES]; From c9bc9b427ca3238324b3f89b690c1c1dbf4be1cf Mon Sep 17 00:00:00 2001 From: ChillyDoom Date: Tue, 21 Oct 2014 19:31:11 +0100 Subject: [PATCH 07/39] - Removed p_leader. --- src/b_bot.h | 1 + src/b_func.cpp | 33 ++++++++++++++------------------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/b_bot.h b/src/b_bot.h index 7844597cde..51fe64129a 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -125,6 +125,7 @@ private: //(B_Func.c) bool Reachable (AActor *actor, AActor *target); void Dofire (AActor *actor, ticcmd_t *cmd); + bool IsLeader (player_t *player); AActor *Choose_Mate (AActor *bot); AActor *Find_enemy (AActor *bot); void SetBodyAt (fixed_t x, fixed_t y, fixed_t z, int hostnum); diff --git a/src/b_func.cpp b/src/b_func.cpp index 0c0ab1ebdd..0303de8c6f 100644 --- a/src/b_func.cpp +++ b/src/b_func.cpp @@ -270,6 +270,19 @@ shootmissile: //actor->angle = R_PointToAngle2(actor->x, actor->y, actor->player->enemy->x, actor->player->enemy->y); } +bool FCajunMaster::IsLeader (player_t *player) +{ + for (int count = 0; count < MAXPLAYERS; count++) + { + if (players[count].Bot != NULL + && players[count].Bot->mate == player->mo) + { + return true; + } + } + + return false; +} //This function is called every //tick (for each bot) to set @@ -277,11 +290,9 @@ shootmissile: AActor *FCajunMaster::Choose_Mate (AActor *bot) { int count; - int count2; fixed_t closest_dist, test; AActor *target; AActor *observer; - bool p_leader[MAXPLAYERS]; //is mate alive? if (bot->player->Bot->mate) @@ -299,22 +310,6 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot) if (bot->player->Bot->last_mate->health <= 0) bot->player->Bot->last_mate = NULL; - for (count = 0; count < MAXPLAYERS; count++) - { - if (!playeringame[count]) - continue; - p_leader[count] = false; - for (count2 = 0; count2 < MAXPLAYERS; count2++) - { - if (players[count2].Bot != NULL - && players[count2].Bot->mate == players[count].mo) - { - p_leader[count] = true; - break; - } - } - } - target = NULL; closest_dist = FIXED_MAX; if (bot_observer) @@ -334,7 +329,7 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot) && client->mo->health > 0 && client->mo != observer && ((bot->health/2) <= client->mo->health || !deathmatch) - && !p_leader[count]) //taken? + && !IsLeader(client)) //taken? { if (P_CheckSight (bot, client->mo, SF_IGNOREVISIBILITY)) { From 6166e83d287136ecc9d68de4beae4b2d2644ec99 Mon Sep 17 00:00:00 2001 From: ChillyDoom Date: Tue, 21 Oct 2014 19:32:15 +0100 Subject: [PATCH 08/39] - Fixed: Only setting controllers should be able to remove bots. --- src/b_bot.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/b_bot.cpp b/src/b_bot.cpp index 3494dc4c46..969d57a1bb 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -141,6 +141,12 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam) CCMD (removebots) { + if (!players[consoleplayer].settings_controller) + { + Printf ("Only setting controllers can remove bots\n"); + return; + } + Net_WriteByte (DEM_KILLBOTS); } From acd4a71de2c9cdc12fe37ac88cdb413b01169ea9 Mon Sep 17 00:00:00 2001 From: ChillyDoom Date: Tue, 21 Oct 2014 19:33:48 +0100 Subject: [PATCH 09/39] - Fixed: New DBot instances were missing write barriers. --- src/b_game.cpp | 1 + src/p_user.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/b_game.cpp b/src/b_game.cpp index 30c2c483ba..807ec2b463 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -369,6 +369,7 @@ void FCajunMaster::DoAddBot (BYTE **stream) { multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost). players[bnum].Bot = new DBot; + GC::WriteBarrier (players[bnum].Bot); players[bnum].Bot->skill = skill; playeringame[bnum] = true; players[bnum].mo = NULL; diff --git a/src/p_user.cpp b/src/p_user.cpp index 8980050e73..51105cd3d0 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3049,6 +3049,7 @@ void player_t::Serialize (FArchive &arc) if (SaveVersion < 4514 && IsBot) { Bot = new DBot; + GC::WriteBarrier (Bot); arc << Bot->angle << Bot->dest From d6a33a601d76748afd636ee77235a9b3cfe95601 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 23 Oct 2014 17:33:42 +0200 Subject: [PATCH 10/39] - fixed: The sorting of 3D floors was incomplete and missed cases where translucent volumes overlapped non-translucent ones only at their top. It also didn't account for one translucent volume being intersected by more than solid one. --- src/p_3dfloors.cpp | 83 +++++++++++++++++++++++++++++++++++++++++----- src/p_3dfloors.h | 7 ++++ 2 files changed, 81 insertions(+), 9 deletions(-) diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index bdeb45d782..d13e462042 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -120,6 +120,7 @@ static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flag //Add the floor ffloor = new F3DFloor; + ffloor->top.copied = ffloor->bottom.copied = false; ffloor->top.model = ffloor->bottom.model = ffloor->model = sec2; ffloor->target = sec; ffloor->ceilingclip = ffloor->floorclip = NULL; @@ -420,6 +421,8 @@ void P_Recalculate3DFloors(sector_t * sector) F3DFloor * pick; unsigned pickindex; F3DFloor * clipped=NULL; + F3DFloor * solid=NULL; + fixed_t solid_bottom=0; fixed_t clipped_top; fixed_t clipped_bottom=0; fixed_t maxheight, minheight; @@ -477,6 +480,7 @@ void P_Recalculate3DFloors(sector_t * sector) } oldlist.Delete(pickindex); + fixed_t pick_bottom=pick->bottom.plane->ZatPoint(CenterSpot(sector)); if (pick->flags & FF_THISINSIDE) { @@ -486,10 +490,38 @@ void P_Recalculate3DFloors(sector_t * sector) } else if (pick->flags&(FF_SWIMMABLE|FF_TRANSLUCENT) && pick->flags&FF_EXISTS) { - clipped=pick; - clipped_top=height; - clipped_bottom=pick->bottom.plane->ZatPoint(CenterSpot(sector)); - ffloors.Push(pick); + // We must check if this nonsolid segment gets clipped from the top by another 3D floor + if (solid != NULL && solid_bottom < height) + { + ffloors.Push(pick); + if (solid_bottom < pick_bottom) + { + // this one is fully covered + pick->flags|=FF_CLIPPED; + pick->flags&=~FF_EXISTS; + } + else + { + F3DFloor * dyn=new F3DFloor; + *dyn=*pick; + pick->flags|=FF_CLIPPED; + pick->flags&=~FF_EXISTS; + dyn->flags|=FF_DYNAMIC; + dyn->top.copyPlane(&solid->bottom); + ffloors.Push(dyn); + + clipped = dyn; + clipped_top = solid_bottom; + clipped_bottom = pick_bottom; + } + } + else + { + clipped = pick; + clipped_top = height; + clipped_bottom = pick_bottom; + ffloors.Push(pick); + } } else if (clipped && clipped_bottomflags|=FF_CLIPPED; clipped->flags&=~FF_EXISTS; dyn->flags|=FF_DYNAMIC; - dyn->bottom=pick->top; + dyn->bottom.copyPlane(&pick->top); ffloors.Push(dyn); ffloors.Push(pick); - fixed_t pick_bottom=pick->bottom.plane->ZatPoint(CenterSpot(sector)); - if (pick_bottom<=clipped_bottom) { clipped=NULL; @@ -515,14 +545,25 @@ void P_Recalculate3DFloors(sector_t * sector) dyn=new F3DFloor; *dyn=*clipped; dyn->flags|=FF_DYNAMIC|FF_EXISTS; - dyn->top=pick->bottom; + dyn->top.copyPlane(&pick->bottom); ffloors.Push(dyn); + clipped = dyn; + clipped_top = pick_bottom; } + solid = pick; + solid_bottom = pick_bottom; } else { - clipped=NULL; + clipped = NULL; + if (solid == NULL || solid_bottom > pick_bottom) + { + // only if this one is lower + solid = pick; + solid_bottom = pick_bottom; + } ffloors.Push(pick); + } } @@ -910,3 +951,27 @@ int P_Find3DFloor(sector_t * sec, fixed_t x, fixed_t y, fixed_t z, bool above, b } #endif + +#include "c_dispatch.h" + + +CCMD (dump3df) +{ + if (argv.argc() > 1) + { + int sec = strtol(argv[1], NULL, 10); + sector_t *sector = §ors[sec]; + TArray & ffloors=sector->e->XFloor.ffloors; + + for (unsigned int i = 0; i < ffloors.Size(); i++) + { + fixed_t height=ffloors[i]->top.plane->ZatPoint(CenterSpot(sector)); + fixed_t bheight=ffloors[i]->bottom.plane->ZatPoint(CenterSpot(sector)); + + Printf("FFloor %d @ top = %f (model = %d), bottom = %f (model = %d), flags = %B, alpha = %d %s %s\n", + i, height / 65536., ffloors[i]->top.model->sectornum, + bheight / 65536., ffloors[i]->bottom.model->sectornum, + ffloors[i]->flags, ffloors[i]->alpha, (ffloors[i]->flags&FF_EXISTS)? "Exists":"", (ffloors[i]->flags&FF_DYNAMIC)? "Dynamic":""); + } + } +} diff --git a/src/p_3dfloors.h b/src/p_3dfloors.h index d0bca5e8fd..8d42560af0 100644 --- a/src/p_3dfloors.h +++ b/src/p_3dfloors.h @@ -77,6 +77,13 @@ struct F3DFloor sector_t * model; int isceiling; int vindex; + bool copied; + + void copyPlane(planeref * other) + { + *this = *other; + copied = true; + } }; planeref bottom; From 68246051548602182df480cc280384246b5b2b07 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 24 Oct 2014 00:06:18 +0200 Subject: [PATCH 11/39] - added pickup sprite and editor number for Heretic's gold wand. --- wadsrc/static/actors/heretic/hereticweaps.txt | 6 +++++- wadsrc/static/language.enu | 1 + wadsrc/static/sprites/GWANA0.png | Bin 0 -> 315 bytes 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 wadsrc/static/sprites/GWANA0.png diff --git a/wadsrc/static/actors/heretic/hereticweaps.txt b/wadsrc/static/actors/heretic/hereticweaps.txt index 972fba5fb8..ca85437e0a 100644 --- a/wadsrc/static/actors/heretic/hereticweaps.txt +++ b/wadsrc/static/actors/heretic/hereticweaps.txt @@ -110,7 +110,7 @@ ACTOR StaffPuff2 // Gold wand ---------------------------------------------------------------- -ACTOR GoldWand : HereticWeapon +ACTOR GoldWand : HereticWeapon 9042 { Game Heretic +BLOODSPLATTER @@ -120,6 +120,7 @@ ACTOR GoldWand : HereticWeapon Weapon.AmmoType "GoldWandAmmo" Weapon.SisterWeapon "GoldWandPowered" Weapon.YAdjust 5 + Inventory.PickupMessage "$TXT_WPNGOLDWAND" Obituary "$OB_MPGOLDWAND" Tag "$TAG_GOLDWAND" @@ -127,6 +128,9 @@ ACTOR GoldWand : HereticWeapon States { + Spawn: + GWAN A -1 + Stop Ready: GWND A 1 A_WeaponReady Loop diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index a92e22dfec..17b56f6f3e 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1242,6 +1242,7 @@ TXT_AMMOPHOENIXROD2 = "INFERNO ORB"; // Weapons +TXT_WPNGOLDWAND = "GOLD WAND"; TXT_WPNMACE = "FIREMACE"; TXT_WPNCROSSBOW = "ETHEREAL CROSSBOW"; TXT_WPNBLASTER = "DRAGON CLAW"; diff --git a/wadsrc/static/sprites/GWANA0.png b/wadsrc/static/sprites/GWANA0.png new file mode 100644 index 0000000000000000000000000000000000000000..f887f04c65d070bff04ff7b7d19354a91daf471a GIT binary patch literal 315 zcmeAS@N?(olHy`uVBq!ia0vp^oItG3!3-o{y_}Q+q&U)x9Fu@FNJvdwaFREWjtcMz zaTO2{U}9oYQBiSobF;RwUYRbHnwn~EZf+>eXDiR==jT^bQ`6nuZEtTM78Yh;VBn=H z9B(Y0ZY`galXGW^Ot`+dj*d=ANlCT0dVjQWY;3HAgv6iSmcQ>-e_Wr?2DF8-B*-tA z!Qt7BG$5zi)5S5QB5v-v>s(HTJZulntlQjPyyt)Rt(Uz@NeXY-pZasH6v=wIj`#bC zCijIYoDSljvR^bvgo?~$IH9z-mqB9Pas!oy(8XriulxT_V_huC%^ Date: Fri, 24 Oct 2014 04:46:43 -0400 Subject: [PATCH 12/39] Added Inventory.AlwaysRespawn flag. --- src/g_shared/a_pickups.cpp | 2 +- src/g_shared/a_pickups.h | 1 + src/thingdef/thingdef_data.cpp | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index a16a1316f0..fc3e863a2c 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -499,7 +499,7 @@ bool AInventory::ShouldRespawn () { if ((ItemFlags & IF_BIGPOWERUP) && !(dmflags2 & DF2_RESPAWN_SUPER)) return false; if (ItemFlags & IF_NEVERRESPAWN) return false; - return !!(dmflags & DF_ITEMS_RESPAWN); + return !!((dmflags & DF_ITEMS_RESPAWN) || (ItemFlags & IF_ALWAYSRESPAWN)); } //=========================================================================== diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 72548776a5..8616393e71 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -135,6 +135,7 @@ enum IF_NEVERRESPAWN = 1<<20, // Never, ever respawns IF_NOSCREENFLASH = 1<<21, // No pickup flash on the player's screen IF_TOSSED = 1<<22, // Was spawned by P_DropItem (i.e. as a monster drop) + IF_ALWAYSRESPAWN = 1<<23, // Always respawn, regardless of dmflag }; diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 013415cc78..5c52c45e37 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -311,6 +311,7 @@ static FFlagDef InventoryFlags[] = DEFINE_FLAG(IF, NEVERRESPAWN, AInventory, ItemFlags), DEFINE_FLAG(IF, NOSCREENFLASH, AInventory, ItemFlags), DEFINE_FLAG(IF, TOSSED, AInventory, ItemFlags), + DEFINE_FLAG(IF, ALWAYSRESPAWN, AInventory, ItemFlags), DEFINE_DEPRECATED_FLAG(PICKUPFLASH), DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),}; From 9402bcf6cd654091f9ae2fdb848b04f9654d08dc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 24 Oct 2014 22:47:40 +0200 Subject: [PATCH 13/39] - fixed: The targeter must reset its HUD sprites when being reactivated during the blinking phase. --- src/g_shared/a_artifacts.cpp | 12 ++++++++++++ src/g_shared/a_artifacts.h | 1 + 2 files changed, 13 insertions(+) diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 8891c8674d..7fd15fa219 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -1296,6 +1296,18 @@ void APowerTargeter::InitEffect () PositionAccuracy (); } +bool APowerTargeter::HandlePickup(AInventory *item) +{ + if (Super::HandlePickup(item)) + { + InitEffect(); // reset the HUD sprites + return true; + } + return false; +} + + + void APowerTargeter::DoEffect () { Super::DoEffect (); diff --git a/src/g_shared/a_artifacts.h b/src/g_shared/a_artifacts.h index 0efd64ab8e..a216cf74c8 100644 --- a/src/g_shared/a_artifacts.h +++ b/src/g_shared/a_artifacts.h @@ -173,6 +173,7 @@ protected: void EndEffect (); void PositionAccuracy (); void Travelled (); + bool HandlePickup(AInventory *item); }; class APowerFrightener : public APowerup From e662e4321ac114fc507da48075ea9e66a990419e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 24 Oct 2014 22:56:10 +0200 Subject: [PATCH 14/39] - fixed: Creating an OPL MIDI device can fail if no GENMIDI lump is found, and an exception is thrown. We need to handle this exception to prevent an abort. --- src/sound/music_midistream.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/sound/music_midistream.cpp b/src/sound/music_midistream.cpp index 15f4caec80..5cb04ed0ee 100644 --- a/src/sound/music_midistream.cpp +++ b/src/sound/music_midistream.cpp @@ -38,6 +38,7 @@ #include "templates.h" #include "doomdef.h" #include "m_swap.h" +#include "doomerrors.h" // MACROS ------------------------------------------------------------------ @@ -277,7 +278,16 @@ MIDIDevice *MIDIStreamer::CreateMIDIDevice(EMidiDevice devtype) const return new TimidityMIDIDevice; case MDEV_OPL: - return new OPLMIDIDevice; + try + { + return new OPLMIDIDevice; + } + catch (CRecoverableError &err) + { + // The creation of an OPL MIDI device can abort with an error if no GENMIDI lump can be found. + Printf("Unable to create OPL MIDI device: %s\nFalling back to FModEx playback", err.GetMessage()); + return new FMODMIDIDevice; + } case MDEV_TIMIDITY: return new TimidityPPMIDIDevice; From 15b1c712578351fa523597216fbebcdf9de682a9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 24 Oct 2014 23:02:02 +0200 Subject: [PATCH 15/39] - use proper CheckCheatMode semantics for throwing players out of chasecam mode if DF2_CHASECAM gets unset. --- src/d_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 0303871180..255994fb5f 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -466,7 +466,7 @@ CUSTOM_CVAR (Int, dmflags2, 0, CVAR_SERVERINFO) } // Come out of chasecam mode if we're not allowed to use chasecam. - if (!(dmflags2 & DF2_CHASECAM) && !G_SkillProperty (SKILLP_DisableCheats) && !sv_cheats) + if (!(dmflags2 & DF2_CHASECAM) && CheckCheatmode(false)) { // Take us out of chasecam mode only. if (p->cheats & CF_CHASECAM) From 6f7b83faa1383be3eee2ca841c67850568093c65 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 24 Oct 2014 23:12:38 +0200 Subject: [PATCH 16/39] - fixed: EV_DoFloor was a bit too selective about which movement types were allowed to crush. Changed so that the crush parameter is always used. Also changed all non-crushing calls to explicitly pass -1 as crush damage instead of relying on EV_DoFloor to ignore the passed value. --- src/g_strife/a_alienspectres.cpp | 4 ++-- src/g_strife/a_crusader.cpp | 2 +- src/g_strife/a_strifestuff.cpp | 2 +- src/p_enemy.cpp | 8 +++---- src/p_floor.cpp | 4 +--- src/p_lnspec.cpp | 36 ++++++++++++++++---------------- 6 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/g_strife/a_alienspectres.cpp b/src/g_strife/a_alienspectres.cpp index 4626891bbe..2b9f499e9a 100644 --- a/src/g_strife/a_alienspectres.cpp +++ b/src/g_strife/a_alienspectres.cpp @@ -106,7 +106,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_AlienSpectreDeath) switch (self->GetClass()->TypeName) { case NAME_AlienSpectre1: - EV_DoFloor (DFloor::floorLowerToLowest, NULL, 999, FRACUNIT, 0, 0, 0, false); + EV_DoFloor (DFloor::floorLowerToLowest, NULL, 999, FRACUNIT, 0, -1, 0, false); log = 95; break; @@ -180,7 +180,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_AlienSpectreDeath) { // Another Sigil piece. Woohoo! log = 83; } - EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, FRACUNIT, 0, 0, 0, false); + EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, FRACUNIT, 0, -1, 0, false); break; default: diff --git a/src/g_strife/a_crusader.cpp b/src/g_strife/a_crusader.cpp index 6d34182f4f..7ef0b24a18 100644 --- a/src/g_strife/a_crusader.cpp +++ b/src/g_strife/a_crusader.cpp @@ -80,6 +80,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderDeath) { if (CheckBossDeath (self)) { - EV_DoFloor (DFloor::floorLowerToLowest, NULL, 667, FRACUNIT, 0, 0, 0, false); + EV_DoFloor (DFloor::floorLowerToLowest, NULL, 667, FRACUNIT, 0, -1, 0, false); } } diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index d51b618b70..95b0030a09 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -548,7 +548,7 @@ void APowerCoupling::Die (AActor *source, AActor *inflictor, int dmgflags) P_NoiseAlert (source, this); } EV_DoDoor (DDoor::doorClose, NULL, players[i].mo, 225, 2*FRACUNIT, 0, 0, 0); - EV_DoFloor (DFloor::floorLowerToHighest, NULL, 44, FRACUNIT, 0, 0, 0, false); + EV_DoFloor (DFloor::floorLowerToHighest, NULL, 44, FRACUNIT, 0, -1, 0, false); players[i].mo->GiveInventoryType (QuestItemClasses[5]); S_Sound (CHAN_VOICE, "svox/voc13", 1, ATTN_NORM); players[i].SetLogNumber (13); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 00e2a3dc29..20b61200fa 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3275,13 +3275,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_BossDeath) { if (type == NAME_Fatso) { - EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, FRACUNIT, 0, 0, 0, false); + EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, FRACUNIT, 0, -1, 0, false); return; } if (type == NAME_Arachnotron) { - EV_DoFloor (DFloor::floorRaiseByTexture, NULL, 667, FRACUNIT, 0, 0, 0, false); + EV_DoFloor (DFloor::floorRaiseByTexture, NULL, 667, FRACUNIT, 0, -1, 0, false); return; } } @@ -3290,11 +3290,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_BossDeath) switch (level.flags & LEVEL_SPECACTIONSMASK) { case LEVEL_SPECLOWERFLOOR: - EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, FRACUNIT, 0, 0, 0, false); + EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, FRACUNIT, 0, -1, 0, false); return; case LEVEL_SPECLOWERFLOORTOHIGHEST: - EV_DoFloor (DFloor::floorLowerToHighest, NULL, 666, FRACUNIT, 0, 0, 0, false); + EV_DoFloor (DFloor::floorLowerToHighest, NULL, 666, FRACUNIT, 0, -1, 0, false); return; case LEVEL_SPECOPENDOOR: diff --git a/src/p_floor.cpp b/src/p_floor.cpp index f630876195..9a5a6eaf82 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -320,7 +320,7 @@ manual_floor: rtn = true; floor = new DFloor (sec); floor->m_Type = floortype; - floor->m_Crush = -1; + floor->m_Crush = crush; floor->m_Hexencrush = hexencrush; floor->m_Speed = speed; floor->m_ResetCount = 0; // [RH] @@ -374,7 +374,6 @@ manual_floor: break; case DFloor::floorRaiseAndCrushDoom: - floor->m_Crush = crush; case DFloor::floorRaiseToLowestCeiling: floor->m_Direction = 1; newheight = sec->FindLowestCeilingSurrounding (&spot); @@ -406,7 +405,6 @@ manual_floor: break; case DFloor::floorRaiseAndCrush: - floor->m_Crush = crush; floor->m_Direction = 1; newheight = sec->FindLowestCeilingPoint (&spot) - 8*FRACUNIT; floor->m_FloorDestDist = sec->floorplane.PointToDist (spot, newheight); diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 14bcd430cd..0d74b4d423 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -281,43 +281,43 @@ FUNC(LS_Generic_Door) FUNC(LS_Floor_LowerByValue) // Floor_LowerByValue (tag, speed, height) { - return EV_DoFloor (DFloor::floorLowerByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2, 0, 0, false); + return EV_DoFloor (DFloor::floorLowerByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2, -1, 0, false); } FUNC(LS_Floor_LowerToLowest) // Floor_LowerToLowest (tag, speed) { - return EV_DoFloor (DFloor::floorLowerToLowest, ln, arg0, SPEED(arg1), 0, 0, 0, false); + return EV_DoFloor (DFloor::floorLowerToLowest, ln, arg0, SPEED(arg1), 0, -1, 0, false); } FUNC(LS_Floor_LowerToHighest) // Floor_LowerToHighest (tag, speed, adjust, hereticlower) { - return EV_DoFloor (DFloor::floorLowerToHighest, ln, arg0, SPEED(arg1), (arg2-128)*FRACUNIT, 0, 0, false, arg3==1); + return EV_DoFloor (DFloor::floorLowerToHighest, ln, arg0, SPEED(arg1), (arg2-128)*FRACUNIT, -1, 0, false, arg3==1); } FUNC(LS_Floor_LowerToNearest) // Floor_LowerToNearest (tag, speed) { - return EV_DoFloor (DFloor::floorLowerToNearest, ln, arg0, SPEED(arg1), 0, 0, 0, false); + return EV_DoFloor (DFloor::floorLowerToNearest, ln, arg0, SPEED(arg1), 0, -1, 0, false); } FUNC(LS_Floor_RaiseByValue) // Floor_RaiseByValue (tag, speed, height) { - return EV_DoFloor (DFloor::floorRaiseByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2, 0, 0, false); + return EV_DoFloor (DFloor::floorRaiseByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2, -1, 0, false); } FUNC(LS_Floor_RaiseToHighest) // Floor_RaiseToHighest (tag, speed) { - return EV_DoFloor (DFloor::floorRaiseToHighest, ln, arg0, SPEED(arg1), 0, 0, 0, false); + return EV_DoFloor (DFloor::floorRaiseToHighest, ln, arg0, SPEED(arg1), 0, -1, 0, false); } FUNC(LS_Floor_RaiseToNearest) // Floor_RaiseToNearest (tag, speed) { - return EV_DoFloor (DFloor::floorRaiseToNearest, ln, arg0, SPEED(arg1), 0, 0, 0, false); + return EV_DoFloor (DFloor::floorRaiseToNearest, ln, arg0, SPEED(arg1), 0, -1, 0, false); } FUNC(LS_Floor_RaiseAndCrush) @@ -335,13 +335,13 @@ FUNC(LS_Floor_RaiseAndCrushDoom) FUNC(LS_Floor_RaiseByValueTimes8) // FLoor_RaiseByValueTimes8 (tag, speed, height) { - return EV_DoFloor (DFloor::floorRaiseByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2*8, 0, 0, false); + return EV_DoFloor (DFloor::floorRaiseByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2*8, -1, 0, false); } FUNC(LS_Floor_LowerByValueTimes8) // Floor_LowerByValueTimes8 (tag, speed, height) { - return EV_DoFloor (DFloor::floorLowerByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2*8, 0, 0, false); + return EV_DoFloor (DFloor::floorLowerByValue, ln, arg0, SPEED(arg1), FRACUNIT*arg2*8, -1, 0, false); } FUNC(LS_Floor_CrushStop) @@ -353,51 +353,51 @@ FUNC(LS_Floor_CrushStop) FUNC(LS_Floor_LowerInstant) // Floor_LowerInstant (tag, unused, height) { - return EV_DoFloor (DFloor::floorLowerInstant, ln, arg0, 0, arg2*FRACUNIT*8, 0, 0, false); + return EV_DoFloor (DFloor::floorLowerInstant, ln, arg0, 0, arg2*FRACUNIT*8, -1, 0, false); } FUNC(LS_Floor_RaiseInstant) // Floor_RaiseInstant (tag, unused, height) { - return EV_DoFloor (DFloor::floorRaiseInstant, ln, arg0, 0, arg2*FRACUNIT*8, 0, 0, false); + return EV_DoFloor (DFloor::floorRaiseInstant, ln, arg0, 0, arg2*FRACUNIT*8, -1, 0, false); } FUNC(LS_Floor_MoveToValueTimes8) // Floor_MoveToValueTimes8 (tag, speed, height, negative) { return EV_DoFloor (DFloor::floorMoveToValue, ln, arg0, SPEED(arg1), - arg2*FRACUNIT*8*(arg3?-1:1), 0, 0, false); + arg2*FRACUNIT*8*(arg3?-1:1), -1, 0, false); } FUNC(LS_Floor_MoveToValue) // Floor_MoveToValue (tag, speed, height, negative) { return EV_DoFloor (DFloor::floorMoveToValue, ln, arg0, SPEED(arg1), - arg2*FRACUNIT*(arg3?-1:1), 0, 0, false); + arg2*FRACUNIT*(arg3?-1:1), -1, 0, false); } FUNC(LS_Floor_RaiseToLowestCeiling) // Floor_RaiseToLowestCeiling (tag, speed) { - return EV_DoFloor (DFloor::floorRaiseToLowestCeiling, ln, arg0, SPEED(arg1), 0, 0, 0, false); + return EV_DoFloor (DFloor::floorRaiseToLowestCeiling, ln, arg0, SPEED(arg1), 0, -1, 0, false); } FUNC(LS_Floor_RaiseByTexture) // Floor_RaiseByTexture (tag, speed) { - return EV_DoFloor (DFloor::floorRaiseByTexture, ln, arg0, SPEED(arg1), 0, 0, 0, false); + return EV_DoFloor (DFloor::floorRaiseByTexture, ln, arg0, SPEED(arg1), 0, -1, 0, false); } FUNC(LS_Floor_RaiseByValueTxTy) // Floor_RaiseByValueTxTy (tag, speed, height) { - return EV_DoFloor (DFloor::floorRaiseAndChange, ln, arg0, SPEED(arg1), arg2*FRACUNIT, 0, 0, false); + return EV_DoFloor (DFloor::floorRaiseAndChange, ln, arg0, SPEED(arg1), arg2*FRACUNIT, -1, 0, false); } FUNC(LS_Floor_LowerToLowestTxTy) // Floor_LowerToLowestTxTy (tag, speed) { - return EV_DoFloor (DFloor::floorLowerAndChange, ln, arg0, SPEED(arg1), arg2*FRACUNIT, 0, 0, false); + return EV_DoFloor (DFloor::floorLowerAndChange, ln, arg0, SPEED(arg1), arg2*FRACUNIT, -1, 0, false); } FUNC(LS_Floor_Waggle) @@ -1764,7 +1764,7 @@ FUNC(LS_FloorAndCeiling_LowerRaise) // more or less unintuitive value for the fourth arg to trigger Boom's broken behavior if (arg3 != 1998 || !res) // (1998 for the year in which Boom was released... :P) { - res |= EV_DoFloor (DFloor::floorLowerToLowest, ln, arg0, SPEED(arg1), 0, 0, 0, false); + res |= EV_DoFloor (DFloor::floorLowerToLowest, ln, arg0, SPEED(arg1), 0, -1, 0, false); } return res; } From e28234a8b847e2701a596caf40261a8d615e0c29 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 24 Oct 2014 23:19:57 +0200 Subject: [PATCH 17/39] - replaced pistol pickup sprite. --- wadsrc/static/sprites/pista0.png | Bin 407 -> 377 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/wadsrc/static/sprites/pista0.png b/wadsrc/static/sprites/pista0.png index b3d9cd09a5831dadb93984064d0c877f46592bbc..9e3a4a05242a9e3fb25cab0c3fcce08d02cb0797 100644 GIT binary patch delta 350 zcmV-k0iphv1Nj1wB!38JazSDM000O8000hEbPJ#W003Q3OjJbx|Nj6002dDj8yg!7 z3kxG7BPS;(H$NvYHyisOeMaiNpvD_qMu71&Ziv>1XMl2slL;|neWoY4{!@=aqU7(JZzL$< wJ7{$A$RyGtU?l6rG)?QWv}qgE5s+H)1hJ0@AUrJvGynhq07*qoM6N<$f>dLHj{pDw delta 361 zcmV-v0ha#x0+$1jB!7)iOjJbxFE2MYHzy}29~TQRFE1-24?8Ew- zcV9nOS64qT7Yi2$Q$H_TTU$RX8(&K|BO@b2GaF}9Gh<_8Z*Omli;IJ6OGigXM>8Ws zFB=yh2TL~_BP$PsgM*WklS@lWYey%`%gZk}9~Tb?r>Cc%pCq4ue}7Xy9~&DRcXxN6 zgJU-%6ZpA2p#T5?0d!JMQvg8b*k+L-7k{KlL_t(|UX{s3a>Fnb0ML(OnIQ;e?){Hf zH>-F?o4oCV#g|SW7M(NBpqTlxd4GPJh2V;+sv_r7vW+mwqy2u^G Date: Sat, 25 Oct 2014 00:01:04 +0200 Subject: [PATCH 18/39] - fixed some bad logic operations. --- src/c_cvars.cpp | 7 ++++--- src/p_interaction.cpp | 2 +- src/p_map.cpp | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index 19187353f6..ce4e886323 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -500,9 +500,10 @@ UCVarValue FBaseCVar::FromString (const char *value, ECVarType type) goodv = false; break; default: - if (value[i] < '0' && value[i] > '9' && - value[i] < 'A' && value[i] > 'F' && - value[i] < 'a' && value[i] > 'f') + if (value[i] < '0' || + (value[i] > '9' && value[i] < 'A') || + (value[i] > 'F' && value[i] < 'a') || + value[i] > 'f') { goodv = false; } diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 6aa1a28f64..fad7a42e5c 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1672,7 +1672,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, target->health -= damage; if (target->health <= 0) { // Death - if (player->cheats & CF_BUDDHA) + if (player->cheats & CF_BUDDHA && damage < TELEFRAG_DAMAGE) { // [SP] Save the player... player->health = target->health = 1; } diff --git a/src/p_map.cpp b/src/p_map.cpp index e7c4779551..3a4187c9a7 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -198,7 +198,7 @@ void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags) if (ff_top > tmf.floorz) { - if (ff_top <= tmf.z || (!(flags && FFCF_3DRESTRICT) && (tmf.thing != NULL && ff_bottom < tmf.z && ff_top < tmf.z + tmf.thing->MaxStepHeight))) + if (ff_top <= tmf.z || (!(flags & FFCF_3DRESTRICT) && (tmf.thing != NULL && ff_bottom < tmf.z && ff_top < tmf.z + tmf.thing->MaxStepHeight))) { tmf.dropoffz = tmf.floorz = ff_top; tmf.floorpic = *rover->top.texture; @@ -2157,7 +2157,7 @@ bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y) { // too big a step up return false; } - else if ((thing->flags & MF_MISSILE) && !(thing->flags6 && MF6_STEPMISSILE) && tm.floorz > newz) + else if ((thing->flags & MF_MISSILE) && !(thing->flags6 & MF6_STEPMISSILE) && tm.floorz > newz) { // [RH] Don't let normal missiles climb steps return false; } From b6f4862024d8c9b09145731892a11d9f39aa3548 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 00:05:52 +0200 Subject: [PATCH 19/39] - fixed: A_Warp didn't initialize oldx/y/z in all situations. --- src/thingdef/thingdef_codeptr.cpp | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index d17bbc75ff..1fb3827db9 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -4348,12 +4348,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) ACTION_PARAM_INT(flags, 5); ACTION_PARAM_STATE(success_state, 6); - fixed_t - - oldx, - oldy, - oldz; - AActor *reference = COPY_AAPTR(self, destination_selector); if (!reference) @@ -4362,6 +4356,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) return; } + fixed_t oldx = self->x; + fixed_t oldy = self->y; + fixed_t oldz = self->z; + if (!(flags & WARPF_ABSOLUTEANGLE)) { angle += (flags & WARPF_USECALLERANGLE) ? self->angle : reference->angle; @@ -4371,20 +4369,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) if (!(flags & WARPF_ABSOLUTEOFFSET)) { angle_t fineangle = angle >> ANGLETOFINESHIFT; - oldx = xofs; + fixed_t xofs1 = xofs; // (borrowed from A_SpawnItemEx, assumed workable) // in relative mode negative y values mean 'left' and positive ones mean 'right' // This is the inverse orientation of the absolute mode! - xofs = FixedMul(oldx, finecosine[fineangle]) + FixedMul(yofs, finesine[fineangle]); - yofs = FixedMul(oldx, finesine[fineangle]) - FixedMul(yofs, finecosine[fineangle]); + xofs = FixedMul(xofs1, finecosine[fineangle]) + FixedMul(yofs, finesine[fineangle]); + yofs = FixedMul(xofs1, finesine[fineangle]) - FixedMul(yofs, finecosine[fineangle]); } - oldx = self->x; - oldy = self->y; - oldz = self->z; - if (flags & WARPF_TOFLOOR) { // set correct xy From 5ac7e4fc386ed7850a18b9b9d2f1a748553ef062 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 00:30:36 +0200 Subject: [PATCH 20/39] - added HARMFRIENDS flag. --- src/actor.h | 1 + src/p_map.cpp | 31 +++++++++++++++++-------------- src/thingdef/thingdef_data.cpp | 1 + 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/actor.h b/src/actor.h index 9a3c6844a4..11d1a6429f 100644 --- a/src/actor.h +++ b/src/actor.h @@ -341,6 +341,7 @@ enum MF7_ALWAYSTELEFRAG = 0x00000004, // will unconditionally be telefragged when in the way. Overrides all other settings. MF7_HANDLENODELAY = 0x00000008, // respect NoDelay state flag MF7_WEAPONSPAWN = 0x00000010, // subject to DF_NO_COOP_WEAPON_SPAWN dmflag + MF7_HARMFRIENDS = 0x00000020, // is allowed to harm friendly monsters. // --- mobj.renderflags --- diff --git a/src/p_map.cpp b/src/p_map.cpp index 3a4187c9a7..43b16a5064 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1111,24 +1111,27 @@ bool PIT_CheckThing(AActor *thing, FCheckPosition &tm) // cases where they are clearly supposed to do that if (thing->IsFriend(tm.thing->target)) { - // Friends never harm each other - return false; + // Friends never harm each other, unless the shooter has the HARMFRIENDS set. + if (!(thing->flags7 & MF7_HARMFRIENDS)) return false; } - if (thing->TIDtoHate != 0 && thing->TIDtoHate == tm.thing->target->TIDtoHate) + else { - // [RH] Don't hurt monsters that hate the same thing as you do - return false; - } - if (thing->GetSpecies() == tm.thing->target->GetSpecies() && !(thing->flags6 & MF6_DOHARMSPECIES)) - { - // Don't hurt same species or any relative - - // but only if the target isn't one's hostile. - if (!thing->IsHostile(tm.thing->target)) + if (thing->TIDtoHate != 0 && thing->TIDtoHate == tm.thing->target->TIDtoHate) { - // Allow hurting monsters the shooter hates. - if (thing->tid == 0 || tm.thing->target->TIDtoHate != thing->tid) + // [RH] Don't hurt monsters that hate the same thing as you do + return false; + } + if (thing->GetSpecies() == tm.thing->target->GetSpecies() && !(thing->flags6 & MF6_DOHARMSPECIES)) + { + // Don't hurt same species or any relative - + // but only if the target isn't one's hostile. + if (!thing->IsHostile(tm.thing->target)) { - return false; + // Allow hurting monsters the shooter hates. + if (thing->tid == 0 || tm.thing->target->TIDtoHate != thing->tid) + { + return false; + } } } } diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 5c52c45e37..b8ee13fd59 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -241,6 +241,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF7, NOTELESTOMP, AActor, flags7), DEFINE_FLAG(MF7, ALWAYSTELEFRAG, AActor, flags7), DEFINE_FLAG(MF7, WEAPONSPAWN, AActor, flags7), + DEFINE_FLAG(MF7, HARMFRIENDS, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), From 83be901ad6f3254b1cd470ec1bf5faa7e60a36ea Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 00:52:27 +0200 Subject: [PATCH 21/39] - fixed: damage of amount TELEFRAG_DAMAGE should not be reduced by armors absorbing some damage, it'd lose its magic-ness, that is needed to ensure a guaranteed kill. The same applies to autousing health items. --- src/p_interaction.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index fad7a42e5c..4a960cc17d 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1218,8 +1218,13 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, if (!(flags & DMG_NO_ARMOR) && player->mo->Inventory != NULL) { int newdam = damage; - player->mo->Inventory->AbsorbDamage (damage, mod, newdam); - damage = newdam; + player->mo->Inventory->AbsorbDamage(damage, mod, newdam); + if (damage < TELEFRAG_DAMAGE) + { + // if we are telefragging don't let the damage value go below that magic value. Some further checks would fail otherwise. + damage = newdam; + } + if (damage <= 0) { // If MF6_FORCEPAIN is set, make the player enter the pain state. @@ -1232,7 +1237,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, } } - if (damage >= player->health + if (damage >= player->health && damage < TELEFRAG_DAMAGE && && (G_SkillProperty(SKILLP_AutoUseHealth) || deathmatch) && !player->morphTics) { // Try to use some inventory health From aa338a4dc674128db4899942bc92e03539f8f53f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 01:00:40 +0200 Subject: [PATCH 22/39] - fixed: G_FinishTravel must synchronize the CF_FLY flag with MF2_FLY. --- src/g_level.cpp | 9 +++++++++ src/p_interaction.cpp | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index d84a487768..525f673185 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1183,6 +1183,15 @@ void G_FinishTravel () pawn->AddToHash (); pawn->SetState(pawn->SpawnState); pawn->player->SendPitchLimits(); + // Sync the FLY flags. + if (pawn->flags2 & MF2_FLY) + { + pawn->player->cheats |= CF_FLY; + } + else + { + pawn->player->cheats &= ~CF_FLY; + } for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory) { diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 4a960cc17d..5e1fbd49f6 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1237,7 +1237,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, } } - if (damage >= player->health && damage < TELEFRAG_DAMAGE && + if (damage >= player->health && damage < TELEFRAG_DAMAGE && (G_SkillProperty(SKILLP_AutoUseHealth) || deathmatch) && !player->morphTics) { // Try to use some inventory health From 5513966165ce6b773558fecfddf6d05dd42b4dce Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 01:15:39 +0200 Subject: [PATCH 23/39] - fixed: Strife's peasants couldn't harm the player because they were defined as friendly. --- wadsrc/static/actors/strife/peasants.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/actors/strife/peasants.txt b/wadsrc/static/actors/strife/peasants.txt index e7bbdadcf4..af12b75df1 100644 --- a/wadsrc/static/actors/strife/peasants.txt +++ b/wadsrc/static/actors/strife/peasants.txt @@ -9,7 +9,7 @@ ACTOR Peasant : StrifeHumanoid Radius 20 Height 56 Monster - +FRIENDLY + +NEVERTARGET -COUNTKILL +NOSPLASHALERT +FLOORCLIP From 1c500cead6c06d56416f27db414f5f247869c54b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 01:27:34 +0200 Subject: [PATCH 24/39] - fixed: A_Respawn did not restore the flags6 and flags7 fields. --- src/thingdef/thingdef_codeptr.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 1fb3827db9..2b382f989b 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2912,6 +2912,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn) self->flags3 = (defs->flags3 & ~(MF3_NOSIGHTCHECK | MF3_HUNTPLAYERS)) | (self->flags3 & (MF3_NOSIGHTCHECK | MF3_HUNTPLAYERS)); self->flags4 = (defs->flags4 & ~MF4_NOHATEPLAYERS) | (self->flags4 & MF4_NOHATEPLAYERS); self->flags5 = defs->flags5; + self->flags6 = defs->flags6; + self->flags7 = defs->flags7; self->SetState (self->SpawnState); self->renderflags &= ~RF_INVISIBLE; From b9800693679a860477713ef06880edd8ee4d0d09 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Fri, 24 Oct 2014 19:31:28 -0500 Subject: [PATCH 25/39] - Added GOD2 and BUDDHA2 cheats. - Ensures that not even telefrag damage can kill the player. - Fixed: Players with NODAMAGE could still hurt and kill themselves via voodoo dolls. --- src/c_cmds.cpp | 18 ++++++++++++++++++ src/d_player.h | 2 ++ src/d_protocol.h | 4 +++- src/m_cheat.cpp | 17 +++++++++++++++++ src/p_interaction.cpp | 15 ++++++++------- wadsrc/static/language.enu | 4 ++++ 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index 89005dbc78..3dd97434e2 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -124,6 +124,15 @@ CCMD (god) Net_WriteByte (CHT_GOD); } +CCMD(god2) +{ + if (CheckCheatmode()) + return; + + Net_WriteByte(DEM_GENERICCHEAT); + Net_WriteByte(CHT_GOD2); +} + CCMD (iddqd) { if (CheckCheatmode ()) @@ -142,6 +151,15 @@ CCMD (buddha) Net_WriteByte(CHT_BUDDHA); } +CCMD(buddha2) +{ + if (CheckCheatmode()) + return; + + Net_WriteByte(DEM_GENERICCHEAT); + Net_WriteByte(CHT_BUDDHA2); +} + CCMD (notarget) { if (CheckCheatmode ()) diff --git a/src/d_player.h b/src/d_player.h index ceb1ff894e..e5644e8cb7 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -205,6 +205,8 @@ typedef enum CF_DOUBLEFIRINGSPEED= 1 << 21, // Player owns a double firing speed artifact CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths. CF_INFINITEAMMO = 1 << 23, // Player owns an infinite ammo artifact + CF_BUDDHA2 = 1 << 24, // [MC] Absolute buddha. No voodoo can kill it either. + CF_GODMODE2 = 1 << 25, // [MC] Absolute godmode. No voodoo can kill it either. CF_BUDDHA = 1 << 27, // [SP] Buddha mode - take damage, but don't die CF_NOCLIP2 = 1 << 30, // [RH] More Quake-like noclip } cheat_t; diff --git a/src/d_protocol.h b/src/d_protocol.h index 0d11c7760f..da54d3f2bb 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -219,7 +219,9 @@ enum ECheatCommand CHT_GIMMIEJ, CHT_GIMMIEZ, CHT_BUDDHA, - CHT_NOCLIP2 + CHT_NOCLIP2, + CHT_BUDDHA2, + CHT_GOD2 }; void StartChunk (int id, BYTE **stream); diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 5d9d48bea6..ac4eb140dd 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -99,6 +99,23 @@ void cht_DoCheat (player_t *player, int cheat) msg = GStrings("TXT_BUDDHAOFF"); break; + case CHT_GOD2: + player->cheats ^= CF_GODMODE2; + if (player->cheats & CF_GODMODE2) + msg = GStrings("STSTR_DQD2ON"); + else + msg = GStrings("STSTR_DQD2OFF"); + ST_SetNeedRefresh(); + break; + + case CHT_BUDDHA2: + player->cheats ^= CF_BUDDHA2; + if (player->cheats & CF_BUDDHA2) + msg = GStrings("TXT_BUDDHA2ON"); + else + msg = GStrings("TXT_BUDDHA2OFF"); + break; + case CHT_NOCLIP: player->cheats ^= CF_NOCLIP; if (player->cheats & CF_NOCLIP) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 5e1fbd49f6..5ce20f5980 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -938,7 +938,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FState * woundstate = NULL; PainChanceList * pc = NULL; bool justhit = false; - + if (target == NULL || !((target->flags & MF_SHOOTABLE) || (target->flags6 & MF6_VULNERABLE))) { // Shouldn't happen return -1; @@ -1209,8 +1209,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, if (!(flags & DMG_FORCED)) { // check the real player, not a voodoo doll here for invulnerability effects - if (damage < TELEFRAG_DAMAGE && ((player->mo->flags2 & MF2_INVULNERABLE) || - (player->cheats & CF_GODMODE))) + if ((damage < TELEFRAG_DAMAGE && ((player->mo->flags2 & MF2_INVULNERABLE) || + (player->cheats & CF_GODMODE))) || + (player->cheats & CF_GODMODE2) || (player->mo->flags5 & MF5_NODAMAGE)) + //Absolutely no hurting if NODAMAGE is involved. Same for GODMODE2. { // player is invulnerable, so don't hurt him return -1; } @@ -1259,9 +1261,8 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // This does not save the player if damage >= TELEFRAG_DAMAGE, still need to // telefrag him right? ;) (Unfortunately the damage is "absorbed" by armor, // but telefragging should still do enough damage to kill the player) - if ((player->cheats & CF_BUDDHA) && damage < TELEFRAG_DAMAGE - // Ignore players that are already dead. - && player->playerstate != PST_DEAD) + // Ignore players that are already dead. + if ((player->cheats & CF_BUDDHA2) || ((player->cheats & CF_BUDDHA) && damage < TELEFRAG_DAMAGE) && player->playerstate != PST_DEAD) { // If this is a voodoo doll we need to handle the real player as well. player->mo->health = target->health = player->health = 1; @@ -1677,7 +1678,7 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, target->health -= damage; if (target->health <= 0) { // Death - if (player->cheats & CF_BUDDHA && damage < TELEFRAG_DAMAGE) + if ((player->cheats & CF_BUDDHA && damage < TELEFRAG_DAMAGE) || (player->cheats & CF_BUDDHA2)) { // [SP] Save the player... player->health = target->health = 1; } diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 17b56f6f3e..a01a03559d 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -292,6 +292,8 @@ STSTR_MUS = "Music Change"; STSTR_NOMUS = "IMPOSSIBLE SELECTION"; STSTR_DQDON = "Degreelessness Mode ON"; STSTR_DQDOFF = "Degreelessness Mode OFF"; +STSTR_DQD2ON = "Ultimate Degreelessness Mode ON"; +STSTR_DQD2OFF = "Ultimate Degreelessness Mode OFF"; STSTR_KFAADDED = "Very Happy Ammo Added"; STSTR_FAADDED = "Ammo (no keys) Added"; STSTR_NCON = "No Clipping Mode ON"; @@ -303,6 +305,8 @@ STSTR_CHOPPERS = "... doesn't suck - GM"; STSTR_CLEV = "Changing Level...\n"; TXT_BUDDHAON = "Buddha mode ON"; TXT_BUDDHAOFF = "Buddha mode OFF"; +TXT_BUDDHA2ON = "Ultimate Buddha Mode ON"; +TXT_BUDDHA2OFF = "Ultimate Buddha Mode OFF"; TXT_DEFAULTPICKUPMSG = "You got a pickup"; E1TEXT = From d1dc6fd59aa6ff64fc3b39924b173f3ac7f55172 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Fri, 24 Oct 2014 23:09:39 -0500 Subject: [PATCH 26/39] - Added: BUDDHA and FOILBUDDHA. - Fixed: mugshot didn't take the god2 cheat into account. --- src/actor.h | 2 ++ src/g_shared/sbar_mugshot.cpp | 2 +- src/p_interaction.cpp | 63 +++++++++++++++++++--------------- src/thingdef/thingdef_data.cpp | 2 ++ 4 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/actor.h b/src/actor.h index 11d1a6429f..f4d1604e5e 100644 --- a/src/actor.h +++ b/src/actor.h @@ -342,6 +342,8 @@ enum MF7_HANDLENODELAY = 0x00000008, // respect NoDelay state flag MF7_WEAPONSPAWN = 0x00000010, // subject to DF_NO_COOP_WEAPON_SPAWN dmflag MF7_HARMFRIENDS = 0x00000020, // is allowed to harm friendly monsters. + MF7_BUDDHA = 0x00000040, // Behaves just like the buddha cheat. + MF7_FOILBUDDHA = 0x00000080, // Similar to FOILINVUL, foils buddha mode. // --- mobj.renderflags --- diff --git a/src/g_shared/sbar_mugshot.cpp b/src/g_shared/sbar_mugshot.cpp index 96dd072656..b8f419ef05 100644 --- a/src/g_shared/sbar_mugshot.cpp +++ b/src/g_shared/sbar_mugshot.cpp @@ -444,7 +444,7 @@ int FMugShot::UpdateState(player_t *player, StateFlags stateflags) if (bNormal) { bool good; - if ((player->cheats & CF_GODMODE) || (player->mo != NULL && player->mo->flags2 & MF2_INVULNERABLE)) + if ((player->cheats & CF_GODMODE) || (player->cheats & CF_GODMODE2) || (player->mo != NULL && player->mo->flags2 & MF2_INVULNERABLE)) { good = SetState((stateflags & ANIMATEDGODMODE) ? "godanimated" : "god"); } diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 5ce20f5980..252e8e8498 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1322,43 +1322,52 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, if (target->health <= 0) - { // Death - target->special1 = damage; - - // use inflictor's death type if it got one. - if (inflictor && inflictor->DeathType != NAME_None) mod = inflictor->DeathType; - - // check for special fire damage or ice damage deaths - if (mod == NAME_Fire) + { + if ((target->flags7 & MF7_BUDDHA) && (damage < TELEFRAG_DAMAGE) && (!(inflictor->flags3 & MF7_FOILBUDDHA) && !(flags & DMG_FOILBUDDHA))) + { //Make sure FOILINVUL flags work here too for monsters. Or perhaps consider a FOILBUDDHA flag... + target->health = 1; + } + else { - if (player && !player->morphTics) - { // Check for flame death - if (!inflictor || - ((target->health > -50) && (damage > 25)) || - !(inflictor->flags5 & MF5_SPECIALFIREDAMAGE)) + + // Death + target->special1 = damage; + + // use inflictor's death type if it got one. + if (inflictor && inflictor->DeathType != NAME_None) mod = inflictor->DeathType; + + // check for special fire damage or ice damage deaths + if (mod == NAME_Fire) + { + if (player && !player->morphTics) + { // Check for flame death + if (!inflictor || + ((target->health > -50) && (damage > 25)) || + !(inflictor->flags5 & MF5_SPECIALFIREDAMAGE)) + { + target->DamageType = NAME_Fire; + } + } + else { target->DamageType = NAME_Fire; } } else { - target->DamageType = NAME_Fire; + target->DamageType = mod; } - } - else - { - target->DamageType = mod; - } - if (source && source->tracer && (source->flags5 & MF5_SUMMONEDMONSTER)) - { // Minotaur's kills go to his master - // Make sure still alive and not a pointer to fighter head - if (source->tracer->player && (source->tracer->player->mo == source->tracer)) - { - source = source->tracer; + if (source && source->tracer && (source->flags5 & MF5_SUMMONEDMONSTER)) + { // Minotaur's kills go to his master + // Make sure still alive and not a pointer to fighter head + if (source->tracer->player && (source->tracer->player->mo == source->tracer)) + { + source = source->tracer; + } } + target->Die (source, inflictor, flags); + return damage; } - target->Die (source, inflictor, flags); - return damage; } woundstate = target->FindState(NAME_Wound, mod); diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index b8ee13fd59..90c3313a69 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -242,6 +242,8 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF7, ALWAYSTELEFRAG, AActor, flags7), DEFINE_FLAG(MF7, WEAPONSPAWN, AActor, flags7), DEFINE_FLAG(MF7, HARMFRIENDS, AActor, flags7), + DEFINE_FLAG(MF7, BUDDHA, AActor, flags7), + DEFINE_FLAG(MF7, FOILBUDDHA, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), From a19620968d92123eac5788492b57fa76fbfb7e0a Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Fri, 24 Oct 2014 23:14:07 -0500 Subject: [PATCH 27/39] - Follow-up of the previous commit. - Cleaned up the DoDamage and DoKill functionality. - Added DMSS_FOILBUDDHA and KILS_FOILBUDDHA. --- src/p_local.h | 1 + src/thingdef/thingdef_codeptr.cpp | 69 ++++++++++++------------------ wadsrc/static/actors/constants.txt | 2 + 3 files changed, 30 insertions(+), 42 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 2dc8c773eb..f7e4738456 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -559,6 +559,7 @@ enum EDmgFlags DMG_NO_FACTOR = 16, DMG_PLAYERATTACK = 32, DMG_FOILINVUL = 64, + DMG_FOILBUDDHA = 128, }; diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 2b382f989b..6a1cf6e674 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -4831,43 +4831,26 @@ enum DMSS DMSS_AFFECTARMOR = 2, DMSS_KILL = 4, DMSS_NOFACTOR = 8, + DMSS_FOILBUDDHA = 16, }; static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageType, int flags) { - if ((amount > 0) || (flags & DMSS_KILL)) - { - if (!(dmgtarget->flags2 & MF2_INVULNERABLE) || (flags & DMSS_FOILINVUL)) - { - if (flags & DMSS_KILL) - { - P_DamageMobj(dmgtarget, self, self, dmgtarget->health, DamageType, DMG_NO_FACTOR | DMG_NO_ARMOR | DMG_FOILINVUL); - } - if (flags & DMSS_AFFECTARMOR) - { - if (flags & DMSS_NOFACTOR) - { - P_DamageMobj(dmgtarget, self, self, amount, DamageType, DMG_FOILINVUL | DMG_NO_FACTOR); - } - else - { - P_DamageMobj(dmgtarget, self, self, amount, DamageType, DMG_FOILINVUL); - } - } - else - { - if (flags & DMSS_NOFACTOR) - { - P_DamageMobj(dmgtarget, self, self, amount, DamageType, DMG_FOILINVUL | DMG_NO_ARMOR | DMG_NO_FACTOR); - } - //[MC] DMG_FOILINVUL is needed for making the damage occur on the actor. - else - { - P_DamageMobj(dmgtarget, self, self, amount, DamageType, DMG_FOILINVUL | DMG_NO_ARMOR); - } - } - } - } + int dmgFlags = 0; + if (flags & DMSS_FOILINVUL) + dmgFlags += DMG_FOILINVUL; + if (flags & DMSS_FOILBUDDHA) + dmgFlags += DMG_FOILBUDDHA; + if ((flags & DMSS_KILL) || (flags & DMSS_NOFACTOR)) //Kill implies NoFactor + dmgFlags += DMG_NO_FACTOR; + if (!(flags & DMSS_AFFECTARMOR) || (flags & DMSS_KILL)) //Kill overrides AffectArmor + dmgFlags += DMG_NO_ARMOR; + if (flags & DMSS_KILL) //Kill adds the value of the damage done to it. Allows for more controlled extreme death types. + amount += dmgtarget->health; + + if (amount > 0) + P_DamageMobj(dmgtarget, self, self, amount, DamageType, dmgFlags); //Should wind up passing them through just fine. + else if (amount < 0) { amount = -amount; @@ -4991,30 +4974,32 @@ enum KILS KILS_FOILINVUL = 1 << 0, KILS_KILLMISSILES = 1 << 1, KILS_NOMONSTERS = 1 << 2, + KILS_FOILBUDDHA = 1 << 3, }; static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags) { + int dmgFlags = DMG_NO_ARMOR + DMG_NO_FACTOR; + + if (KILS_FOILINVUL) + dmgFlags += DMG_FOILINVUL; + if (KILS_FOILBUDDHA) + dmgFlags += DMG_FOILBUDDHA; + if ((killtarget->flags & MF_MISSILE) && (flags & KILS_KILLMISSILES)) { //[MC] Now that missiles can set masters, lets put in a check to properly destroy projectiles. BUT FIRST! New feature~! //Check to see if it's invulnerable. Disregarded if foilinvul is on, but never works on a missile with NODAMAGE //since that's the whole point of it. - if ((!(killtarget->flags2 & MF2_INVULNERABLE) || (flags & KILS_FOILINVUL)) && !(killtarget->flags5 & MF5_NODAMAGE)) + if ((!(killtarget->flags2 & MF2_INVULNERABLE) || (flags & KILS_FOILINVUL)) && + (!(killtarget->flags2 & MF7_BUDDHA) || (flags & KILS_FOILBUDDHA)) && !(killtarget->flags5 & MF5_NODAMAGE)) { P_ExplodeMissile(killtarget, NULL, NULL); } } if (!(flags & KILS_NOMONSTERS)) { - if (flags & KILS_FOILINVUL) - { - P_DamageMobj(killtarget, self, self, killtarget->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR | DMG_FOILINVUL); - } - else - { - P_DamageMobj(killtarget, self, self, killtarget->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR); - } + P_DamageMobj(killtarget, self, self, killtarget->health, damagetype, dmgFlags); } } diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index da289dc50e..f806f8224f 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -375,12 +375,14 @@ enum const int KILS_FOILINVUL = 1; const int KILS_KILLMISSILES = 2; const int KILS_NOMONSTERS = 4; +const int KILS_FOILBUDDHA = 8; // Flags for A_Damage (Master/Target/Tracer/Children/Siblings/Self) series const int DMSS_FOILINVUL = 1; const int DMSS_AFFECTARMOR = 2; const int DMSS_KILL = 4; const int DMSS_NOFACTOR = 8; +const int DMSS_FOILBUDDHA = 16; // Flags for A_AlertMonsters const int AMF_TARGETEMITTER = 1; From 313245dd77e7bd56cda09da105302e1ce51ded81 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 09:53:23 +0200 Subject: [PATCH 28/39] - added a Buddha powerup --- src/g_shared/a_artifacts.cpp | 36 +++++++++++++++++++++++ src/g_shared/a_artifacts.h | 8 +++++ wadsrc/static/actors/shared/inventory.txt | 5 ++++ 3 files changed, 49 insertions(+) diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 7fd15fa219..1fa3ca985b 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -1396,6 +1396,42 @@ void APowerFrightener::EndEffect () Owner->player->cheats &= ~CF_FRIGHTENING; } +// Buddha Powerup -------------------------------- + +IMPLEMENT_CLASS (APowerBuddha) + +//=========================================================================== +// +// APowerBuddha :: InitEffect +// +//=========================================================================== + +void APowerBuddha::InitEffect () +{ + Super::InitEffect(); + + if (Owner== NULL || Owner->player == NULL) + return; + + Owner->player->cheats |= CF_FRIGHTENING; +} + +//=========================================================================== +// +// APowerBuddha :: EndEffect +// +//=========================================================================== + +void APowerBuddha::EndEffect () +{ + Super::EndEffect(); + + if (Owner== NULL || Owner->player == NULL) + return; + + Owner->player->cheats &= ~CF_FRIGHTENING; +} + // Scanner powerup ---------------------------------------------------------- IMPLEMENT_CLASS (APowerScanner) diff --git a/src/g_shared/a_artifacts.h b/src/g_shared/a_artifacts.h index a216cf74c8..4e1823f5a0 100644 --- a/src/g_shared/a_artifacts.h +++ b/src/g_shared/a_artifacts.h @@ -184,6 +184,14 @@ protected: void EndEffect (); }; +class APowerBuddha : public APowerup +{ + DECLARE_CLASS (APowerBuddha, APowerup) +protected: + void InitEffect (); + void EndEffect (); +}; + class APowerTimeFreezer : public APowerup { DECLARE_CLASS( APowerTimeFreezer, APowerup ) diff --git a/wadsrc/static/actors/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt index e293282b8b..e9f57a607d 100644 --- a/wadsrc/static/actors/shared/inventory.txt +++ b/wadsrc/static/actors/shared/inventory.txt @@ -271,6 +271,11 @@ ACTOR PowerFrightener : Powerup native Powerup.Duration -60 } +ACTOR PowerBuddha : Powerup native +{ + Powerup.Duration -60 +} + ACTOR PowerScanner : Powerup native { Powerup.Duration -80 From 8edace83c5b089530f6c34814ba08dbb2e748feb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 10:19:14 +0200 Subject: [PATCH 29/39] - made CheatKey and EasyKey vector graphics configurable through MAPINFO. --- src/am_map.cpp | 4 ++-- src/gi.cpp | 3 +++ src/gi.h | 1 + wadsrc/static/mapinfo/common.txt | 5 +++++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index 904593dfb7..29cd607937 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -908,8 +908,8 @@ void AM_StaticInit() if (gameinfo.mMapArrow.IsNotEmpty()) AM_ParseArrow(MapArrow, gameinfo.mMapArrow); if (gameinfo.mCheatMapArrow.IsNotEmpty()) AM_ParseArrow(CheatMapArrow, gameinfo.mCheatMapArrow); - AM_ParseArrow(CheatKey, "maparrows/key.txt"); - AM_ParseArrow(EasyKey, "maparrows/ravenkey.txt"); + AM_ParseArrow(CheatKey, gameinfo.mCheatKey); + AM_ParseArrow(EasyKey, gameinfo.mEasyKey); if (MapArrow.Size() == 0) I_FatalError("No automap arrow defined"); char namebuf[9]; diff --git a/src/gi.cpp b/src/gi.cpp index 4e64dd4256..a17e97631c 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -290,6 +290,9 @@ void FMapInfoParser::ParseGameInfo() else gameinfo.mCheatMapArrow = ""; } // Insert valid keys here. + GAMEINFOKEY_STRING(mCheatKey, "cheatKey") + GAMEINFOKEY_STRING(mEasyKey, "easyKey") + GAMEINFOKEY_STRING(TitlePage, "titlePage") GAMEINFOKEY_STRING(TitlePage, "titlePage") GAMEINFOKEY_STRINGARRAY(creditPages, "addcreditPage", 8, false) GAMEINFOKEY_STRINGARRAY(creditPages, "CreditPage", 8, true) diff --git a/src/gi.h b/src/gi.h index bbfbe73ff6..d8d19a14bc 100644 --- a/src/gi.h +++ b/src/gi.h @@ -169,6 +169,7 @@ struct gameinfo_t int TextScreenY; FName DefaultEndSequence; FString mMapArrow, mCheatMapArrow; + FString mEasyKey, mCheatKey; FGIFont mStatscreenMapNameFont; FGIFont mStatscreenFinishedFont; FGIFont mStatscreenEnteringFont; diff --git a/wadsrc/static/mapinfo/common.txt b/wadsrc/static/mapinfo/common.txt index 8e7886987f..fc6379d01c 100644 --- a/wadsrc/static/mapinfo/common.txt +++ b/wadsrc/static/mapinfo/common.txt @@ -1,3 +1,8 @@ +Gameinfo +{ + CheatKey = "maparrows/key.txt" + EasyKey = "maparrows/ravenkey.txt" +} Intermission Inter_Titlescreen { From 0d3908a4f38bd9618fa5cbc150808daea0f423c2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 10:44:00 +0200 Subject: [PATCH 30/39] - fixed: Hitscan traces crossing a two sided line right at the height of the back sector's floor or ceiling must not be considered a hit. --- src/p_trace.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_trace.cpp b/src/p_trace.cpp index d1b9f63ac8..26852269ab 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -366,7 +366,7 @@ bool FTraceInfo::TraceTraverse (int ptflags) Results->HitTexture = CurSector->GetTexture(sector_t::ceiling); } else if (entersector == NULL || - hitz <= bf || hitz >= bc || + hitz < bf || hitz > bc || in->d.line->flags & WallMask) { // hit the wall Results->HitType = TRACE_HitWall; From cfe97b0f0f596d19bdaea88e4571ee95f25967fc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 11:33:28 +0200 Subject: [PATCH 31/39] - Fixed: Killing a morphed monster must trigger A_BossDeath on its unmorphed self. --- src/g_shared/a_morph.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 2b3a6040d3..6014d6feee 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -12,6 +12,7 @@ #include "doomstat.h" #include "g_level.h" #include "farchive.h" +#include "p_enemy.h" static FRandom pr_morphmonst ("MorphMonster"); @@ -527,11 +528,11 @@ bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *mor if (actor->GetClass()->IsDescendantOf(RUNTIME_CLASS(AMorphedMonster))) { AMorphedMonster *fakeme = static_cast(actor); + AActor *realme = fakeme->UnmorphedMe; if ((fakeme->UnmorphTime) && (fakeme->MorphStyle & MORPH_UNDOBYDEATH) && - (fakeme->UnmorphedMe)) + (realme)) { - AActor *realme = fakeme->UnmorphedMe; int realstyle = fakeme->MorphStyle; int realhealth = fakeme->health; if (P_UndoMonsterMorph(fakeme, !!(fakeme->MorphStyle & MORPH_UNDOBYDEATHFORCED))) @@ -542,6 +543,11 @@ bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *mor return true; } } + if (realme->flags4 & MF4_BOSSDEATH) + { + realme->health = 0; // make sure that A_BossDeath considers it dead. + CALL_ACTION(A_BossDeath, realme); + } fakeme->flags3 |= MF3_STAYMORPHED; // moved here from AMorphedMonster::Die() return false; } From fc40e9723a2b907e083783705a7b17106773c905 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 11:51:29 +0200 Subject: [PATCH 32/39] - fixed: CHANGELEVEL_RESETINVENTORY may not change the player's health. APlayerPawn::GiveDefaultInventory altered the player_t's health value which was ok as long as this function was only called from G_PlayerReborn. For all other cases this initialization was wrong and G_PlayerReborn should do this itself. --- src/g_game.cpp | 3 +++ src/m_cheat.cpp | 1 - src/p_user.cpp | 3 --- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index a58753b869..8419fc017c 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1363,6 +1363,7 @@ void G_PlayerReborn (int player) ::new(p) player_t; memcpy (p->frags, frags, sizeof(p->frags)); + p->health = actor->health; p->fragcount = fragcount; p->killcount = killcount; p->itemcount = itemcount; @@ -1381,6 +1382,8 @@ void G_PlayerReborn (int player) if (gamestate != GS_TITLELEVEL) { + + // [GRB] Give inventory specified in DECORATE actor->GiveDefaultInventory (); p->ReadyWeapon = p->PendingWeapon; } diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index ac4eb140dd..e48b79980a 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -340,7 +340,6 @@ void cht_DoCheat (player_t *player, int cheat) player->mo->Translation = TRANSLATION(TRANSLATION_Players, BYTE(player-players)); } player->mo->DamageType = NAME_None; -// player->mo->GiveDefaultInventory(); if (player->ReadyWeapon != NULL) { P_SetPsprite(player, ps_weapon, player->ReadyWeapon->GetUpState()); diff --git a/src/p_user.cpp b/src/p_user.cpp index 51105cd3d0..045e619694 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1203,9 +1203,6 @@ void APlayerPawn::GiveDefaultInventory () { if (player == NULL) return; - // [GRB] Give inventory specified in DECORATE - player->health = GetDefault ()->health; - // HexenArmor must always be the first item in the inventory because // it provides player class based protection that should not affect // any other protection item. From ef5707d73ba453968f61ac10f2bb31f80152697b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 12:12:06 +0200 Subject: [PATCH 33/39] - added a compatibility option for stopping sounds when the owning actor is destroyed. --- src/compatibility.cpp | 1 + src/d_main.cpp | 1 + src/doomdef.h | 1 + src/g_mapinfo.cpp | 1 + src/s_sound.cpp | 2 +- wadsrc/static/menudef.txt | 1 + 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/compatibility.cpp b/src/compatibility.cpp index 351c2672a9..7bd28e5d94 100644 --- a/src/compatibility.cpp +++ b/src/compatibility.cpp @@ -141,6 +141,7 @@ static FCompatOption Options[] = { "maskedmidtex", COMPATF_MASKEDMIDTEX, SLOT_COMPAT }, { "badangles", COMPATF2_BADANGLES, SLOT_COMPAT2 }, { "floormove", COMPATF2_FLOORMOVE, SLOT_COMPAT2 }, + { "soundcutoff", COMPATF2_SOUNDCUTOFF, SLOT_COMPAT2 }, { NULL, 0, 0 } }; diff --git a/src/d_main.cpp b/src/d_main.cpp index 255994fb5f..79c8990855 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -620,6 +620,7 @@ CVAR (Flag, compat_polyobj, compatflags, COMPATF_POLYOBJ); CVAR (Flag, compat_maskedmidtex, compatflags, COMPATF_MASKEDMIDTEX); CVAR (Flag, compat_badangles, compatflags2, COMPATF2_BADANGLES); CVAR (Flag, compat_floormove, compatflags2, COMPATF2_FLOORMOVE); +CVAR (Flag, compat_soundcutoff, compatflags2, COMPATF2_SOUNDCUTOFF); //========================================================================== // diff --git a/src/doomdef.h b/src/doomdef.h index 3e00975cfc..767f976618 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -339,6 +339,7 @@ enum COMPATF2_BADANGLES = 1 << 0, // It is impossible to face directly NSEW. COMPATF2_FLOORMOVE = 1 << 1, // Use the same floor motion behavior as Doom. + COMPATF2_SOUNDCUTOFF = 1 << 2, // Cut off sounds when an actor vanishes instead of making it owner-less }; // Emulate old bugs for select maps. These are not exposed by a cvar diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index 5a451dfaaa..b68408237a 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -1306,6 +1306,7 @@ MapFlagHandlers[] = { "compat_maskedmidtex", MITYPE_COMPATFLAG, COMPATF_MASKEDMIDTEX, 0 }, { "compat_badangles", MITYPE_COMPATFLAG, 0, COMPATF2_BADANGLES }, { "compat_floormove", MITYPE_COMPATFLAG, 0, COMPATF2_FLOORMOVE }, + { "compat_soundcutoff", MITYPE_COMPATFLAG, 0, COMPATF2_SOUNDCUTOFF }, { "cd_start_track", MITYPE_EATNEXT, 0, 0 }, { "cd_end1_track", MITYPE_EATNEXT, 0, 0 }, { "cd_end2_track", MITYPE_EATNEXT, 0, 0 }, diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 035b71c74c..75bd33d471 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1575,7 +1575,7 @@ void S_RelinkSound (AActor *from, AActor *to) { chan->Actor = to; } - else if (!(chan->ChanFlags & CHAN_LOOP)) + else if (!(chan->ChanFlags & CHAN_LOOP) && !(compatflags2 & COMPATF2_SOUNDCUTOFF)) { chan->Actor = NULL; chan->SourceType = SOURCE_Unattached; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 13565da7f2..3d5a3ea3cf 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1300,6 +1300,7 @@ OptionMenu "CompatibilityOptions" Option "Ignore Y offsets on masked midtextures", "compat_MASKEDMIDTEX", "YesNo" Option "Cannot travel straight NSEW", "compat_badangles", "YesNo" Option "Use Doom's floor motion behavior", "compat_floormove", "YesNo" + Option "Sounds stop when actor vanishes", "compat_soundcutoff", "YesNo" Class "CompatibilityMenu" } From dcc318fdee62eec607978a8864c780ec4575ab62 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 12:33:08 +0200 Subject: [PATCH 34/39] - print a warning when a state label can't be found. Preferably this would be an error but the oversight had been in the engine for too long so nobody knows --- src/p_states.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/p_states.cpp b/src/p_states.cpp index cfe455716a..3ba0ae14f3 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -39,6 +39,7 @@ #include "cmdlib.h" #include "i_system.h" #include "c_dispatch.h" +#include "v_text.h" #include "thingdef/thingdef.h" // Each state is owned by an actor. Actors can own any number of @@ -699,6 +700,10 @@ FState *FStateDefinitions::ResolveGotoLabel (AActor *actor, const PClass *mytype { I_Error ("Attempt to get invalid state %s from actor %s.", label, type->TypeName.GetChars()); } + else + { + Printf (TEXTCOLOR_RED "Attempt to get invalid state %s from actor %s.\n", label, type->TypeName.GetChars()); + } delete[] namestart; // free the allocated string buffer return state; } From edd53f22a1d67fcc3d7bf2114543e852bcebc540 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 12:34:46 +0200 Subject: [PATCH 35/39] - fixed: The buddha powerup set the wrong flag. --- src/g_shared/a_artifacts.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 1fa3ca985b..4a2d066cde 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -1413,7 +1413,7 @@ void APowerBuddha::InitEffect () if (Owner== NULL || Owner->player == NULL) return; - Owner->player->cheats |= CF_FRIGHTENING; + Owner->player->cheats |= CF_BUDDHA; } //=========================================================================== @@ -1429,7 +1429,7 @@ void APowerBuddha::EndEffect () if (Owner== NULL || Owner->player == NULL) return; - Owner->player->cheats &= ~CF_FRIGHTENING; + Owner->player->cheats &= ~CF_BUDDHA; } // Scanner powerup ---------------------------------------------------------- From ad2e16576c078ead9c67219af691f4754d527969 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 13:10:38 +0200 Subject: [PATCH 36/39] - fixed_ P_ExplodeMissile skipped most of its logic when the missile got destroyed by having no death state. Apparently a band-aid fix was applied to this function because AActor::Destroy could not be called on an already destroyed actor again which could happen here due to incorrect ordering of actions. Moving the state change to a later point in this function - after hitting a sky has been checked and decals have been spawned - returns everything to a safe state and ensures that nothing gets skipped. --- src/p_mobj.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a67b96dfb9..2b0782b8fe 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1199,13 +1199,7 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target) if (nextstate == NULL) nextstate = mo->FindState(NAME_Death, NAME_Extreme); } if (nextstate == NULL) nextstate = mo->FindState(NAME_Death); - mo->SetState (nextstate); - if (mo->ObjectFlags & OF_EuthanizeMe) - { - return; - } - if (line != NULL && line->special == Line_Horizon && !(mo->flags3 & MF3_SKYEXPLODE)) { // [RH] Don't explode missiles on horizon lines. @@ -1280,8 +1274,17 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target) } } - if (nextstate != NULL) + // play the sound before changing the state, so that AActor::Destroy can call S_RelinkSounds on it and the death state can override it. + if (mo->DeathSound) { + S_Sound (mo, CHAN_VOICE, mo->DeathSound, 1, + (mo->flags3 & MF3_FULLVOLDEATH) ? ATTN_NONE : ATTN_NORM); + } + + mo->SetState (nextstate); + if (!(mo->ObjectFlags & OF_EuthanizeMe)) + { + // The rest only applies if the missile actor still exists. // [RH] Change render style of exploding rockets if (mo->flags5 & MF5_DEHEXPLOSION) { @@ -1314,11 +1317,6 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target) mo->flags &= ~MF_MISSILE; - if (mo->DeathSound) - { - S_Sound (mo, CHAN_VOICE, mo->DeathSound, 1, - (mo->flags3 & MF3_FULLVOLDEATH) ? ATTN_NONE : ATTN_NORM); - } } } From 2e1fa70cbf45e3b3bd89c686265aa9753ce41e96 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 13:12:57 +0200 Subject: [PATCH 37/39] - some parentheses to silence GCC. --- src/p_interaction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 252e8e8498..2ac29e11cf 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1262,7 +1262,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // telefrag him right? ;) (Unfortunately the damage is "absorbed" by armor, // but telefragging should still do enough damage to kill the player) // Ignore players that are already dead. - if ((player->cheats & CF_BUDDHA2) || ((player->cheats & CF_BUDDHA) && damage < TELEFRAG_DAMAGE) && player->playerstate != PST_DEAD) + if (((player->cheats & CF_BUDDHA2) || ((player->cheats & CF_BUDDHA) && damage < TELEFRAG_DAMAGE)) && player->playerstate != PST_DEAD) { // If this is a voodoo doll we need to handle the real player as well. player->mo->health = target->health = player->health = 1; From 9435cdc5c9d18100fa8a8a7cbe37cd705080220b Mon Sep 17 00:00:00 2001 From: Edward Richardson Date: Sun, 26 Oct 2014 01:09:19 +1300 Subject: [PATCH 38/39] Fixed NULL refrence in P_SpawnBlood --- src/p_mobj.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a67b96dfb9..829e172cb3 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5018,10 +5018,11 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc cls = cls->ParentClass; } } + + statedone: + if (!(bloodtype <= 1)) th->renderflags |= RF_INVISIBLE; } -statedone: - if (!(bloodtype <= 1)) th->renderflags |= RF_INVISIBLE; if (bloodtype >= 1) P_DrawSplash2 (40, x, y, z, dir, 2, bloodcolor); } From d4c50b1662706b252ecbdceb95cf61a1d528d7f8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 25 Oct 2014 14:59:30 +0200 Subject: [PATCH 39/39] - fixed: AActor::IsTeammate must consider monsters friendly to a specific player as members of the same team as the owning player. Such monsters cannot be made members of a designated team, though, because their association needs to change if the player changes teams. --- src/actor.h | 3 +++ src/p_enemy.cpp | 2 +- src/p_mobj.cpp | 35 +++++++++++++++++++++++++++-------- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/actor.h b/src/actor.h index f4d1604e5e..f1c733ab24 100644 --- a/src/actor.h +++ b/src/actor.h @@ -716,6 +716,9 @@ public: // Transforms the actor into a finely-ground paste virtual bool Grind(bool items); + // Get this actor's team + int GetTeam(); + // Is the other actor on my team? bool IsTeammate (AActor *other); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 20b61200fa..e51d601f3a 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1592,7 +1592,7 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) } #endif // [SP] If you don't see any enemies in deathmatch, look for players (but only when friend to a specific player.) - if (actor->FriendPlayer == 0 && (!teamplay || actor->DesignatedTeam == TEAM_NONE)) return result; + if (actor->FriendPlayer == 0 && (!teamplay || actor->GetTeam() == TEAM_NONE)) return result; if (result || !deathmatch) return true; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 2b0782b8fe..16d83943fd 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5855,22 +5855,41 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, return NULL; } +int AActor::GetTeam() +{ + if (player) + { + return player->userinfo.GetTeam(); + } + + int myTeam = DesignatedTeam; + + // Check for monsters that belong to a player on the team but aren't part of the team themselves. + if (myTeam == TEAM_NONE && FriendPlayer != 0) + { + myTeam = players[FriendPlayer - 1].userinfo.GetTeam(); + } + return myTeam; + +} + bool AActor::IsTeammate (AActor *other) { if (!other) + { return false; + } else if (!deathmatch && player && other->player) - return true; - int myTeam = DesignatedTeam; - int otherTeam = other->DesignatedTeam; - if (player) - myTeam = player->userinfo.GetTeam(); - if (other->player) - otherTeam = other->player->userinfo.GetTeam(); - if (teamplay && myTeam != TEAM_NONE && myTeam == otherTeam) { return true; } + else if (teamplay) + { + int myTeam = GetTeam(); + int otherTeam = other->GetTeam(); + + return (myTeam != TEAM_NONE && myTeam == otherTeam); + } return false; }