mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 07:12:02 +00:00
Merge branch 'BotFunctions' of https://github.com/ChillyDoom/zdoom
This commit is contained in:
commit
ed5b0d902a
6 changed files with 335 additions and 351 deletions
|
@ -66,7 +66,7 @@ void DBot::Serialize (FArchive &arc)
|
|||
arc << savedyaw
|
||||
<< savedpitch;
|
||||
}
|
||||
else if (SaveVersion >= 4516)
|
||||
else
|
||||
{
|
||||
arc << player;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ void DBot::Tick ()
|
|||
|
||||
BotThinkCycles.Clock();
|
||||
bglobal.m_Thinking = true;
|
||||
bglobal.Think (player->mo, &netcmds[player - players][((gametic + 1)/ticdup)%BACKUPTICS]);
|
||||
Think ();
|
||||
bglobal.m_Thinking = false;
|
||||
BotThinkCycles.Unclock();
|
||||
}
|
||||
|
|
71
src/b_bot.h
71
src/b_bot.h
|
@ -89,7 +89,7 @@ public:
|
|||
|
||||
void ClearPlayer (int playernum, bool keepTeam);
|
||||
|
||||
//(B_Game.c)
|
||||
//(b_game.cpp)
|
||||
void Main ();
|
||||
void Init ();
|
||||
void End();
|
||||
|
@ -99,23 +99,16 @@ public:
|
|||
bool LoadBots ();
|
||||
void ForgetBots ();
|
||||
|
||||
//(B_Func.c)
|
||||
bool Check_LOS (AActor *mobj1, AActor *mobj2, angle_t vangle);
|
||||
//(b_func.cpp)
|
||||
void StartTravel ();
|
||||
void FinishTravel ();
|
||||
bool IsLeader (player_t *player);
|
||||
void SetBodyAt (fixed_t x, fixed_t y, fixed_t z, int hostnum);
|
||||
fixed_t FakeFire (AActor *source, AActor *dest, ticcmd_t *cmd);
|
||||
bool SafeCheckPosition (AActor *actor, fixed_t x, fixed_t y, FCheckPosition &tm);
|
||||
|
||||
//(B_Think.c)
|
||||
void Think (AActor *actor, ticcmd_t *cmd);
|
||||
void WhatToGet (AActor *actor, AActor *item);
|
||||
|
||||
//(B_move.c)
|
||||
void Roam (AActor *actor, ticcmd_t *cmd);
|
||||
bool Move (AActor *actor, ticcmd_t *cmd);
|
||||
bool TryWalk (AActor *actor, ticcmd_t *cmd);
|
||||
void NewChaseDir (AActor *actor, ticcmd_t *cmd);
|
||||
//(b_move.cpp)
|
||||
bool CleanAhead (AActor *thing, fixed_t x, fixed_t y, ticcmd_t *cmd);
|
||||
void TurnToAng (AActor *actor);
|
||||
void Pitch (AActor *actor, AActor *target);
|
||||
bool IsDangerous (sector_t *sec);
|
||||
|
||||
TArray<FString> getspawned; //Array of bots (their names) which should be spawned when starting a game.
|
||||
|
@ -132,24 +125,9 @@ public:
|
|||
bool m_Thinking;
|
||||
|
||||
private:
|
||||
//(B_Game.c)
|
||||
//(b_game.cpp)
|
||||
bool DoAddBot (BYTE *info, botskill_t skill);
|
||||
|
||||
//(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);
|
||||
fixed_t FakeFire (AActor *source, AActor *dest, ticcmd_t *cmd);
|
||||
angle_t FireRox (AActor *bot, AActor *enemy, ticcmd_t *cmd);
|
||||
bool SafeCheckPosition (AActor *actor, fixed_t x, fixed_t y, FCheckPosition &tm);
|
||||
|
||||
//(B_Think.c)
|
||||
void ThinkForMove (AActor *actor, ticcmd_t *cmd);
|
||||
void Set_enemy (AActor *actor);
|
||||
|
||||
protected:
|
||||
bool ctf;
|
||||
int loaded_bots;
|
||||
|
@ -168,13 +146,17 @@ public:
|
|||
void Serialize (FArchive &arc);
|
||||
void Tick ();
|
||||
|
||||
//(b_think.cpp)
|
||||
void WhatToGet (AActor *item);
|
||||
|
||||
//(b_func.cpp)
|
||||
bool Check_LOS (AActor *to, angle_t vangle);
|
||||
|
||||
player_t *player;
|
||||
angle_t angle; // The wanted angle that the bot try to get every tic.
|
||||
// (used to get a smooth view movement)
|
||||
TObjPtr<AActor> dest; // Move Destination.
|
||||
TObjPtr<AActor> prev; // Previous move destination.
|
||||
|
||||
|
||||
TObjPtr<AActor> enemy; // The dead meat.
|
||||
TObjPtr<AActor> missile; // A threatening missile that needs to be avoided.
|
||||
TObjPtr<AActor> mate; // Friend (used for grouping in teamplay or coop).
|
||||
|
@ -204,6 +186,27 @@ public:
|
|||
|
||||
fixed_t oldx;
|
||||
fixed_t oldy;
|
||||
|
||||
private:
|
||||
//(B_think.cpp)
|
||||
void Think ();
|
||||
void ThinkForMove (ticcmd_t *cmd);
|
||||
void Set_enemy ();
|
||||
|
||||
//(B_func.cpp)
|
||||
bool Reachable (AActor *target);
|
||||
void Dofire (ticcmd_t *cmd);
|
||||
AActor *Choose_Mate ();
|
||||
AActor *Find_enemy ();
|
||||
angle_t FireRox (AActor *enemy, ticcmd_t *cmd);
|
||||
|
||||
//(b_move.cpp)
|
||||
void Roam (ticcmd_t *cmd);
|
||||
bool Move (ticcmd_t *cmd);
|
||||
bool TryWalk (ticcmd_t *cmd);
|
||||
void NewChaseDir (ticcmd_t *cmd);
|
||||
void TurnToAng ();
|
||||
void Pitch (AActor *target);
|
||||
};
|
||||
|
||||
|
||||
|
@ -220,7 +223,3 @@ EXTERN_CVAR (Bool, bot_watersplash)
|
|||
EXTERN_CVAR (Bool, bot_chat)
|
||||
|
||||
#endif // __B_BOT_H__
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
200
src/b_func.cpp
200
src/b_func.cpp
|
@ -24,24 +24,23 @@
|
|||
static FRandom pr_botdofire ("BotDoFire");
|
||||
|
||||
|
||||
//Checks TRUE reachability from
|
||||
//one looker to another. First mobj (looker) is looker.
|
||||
bool FCajunMaster::Reachable (AActor *looker, AActor *rtarget)
|
||||
//Checks TRUE reachability from bot to a looker.
|
||||
bool DBot::Reachable (AActor *rtarget)
|
||||
{
|
||||
if (looker == rtarget)
|
||||
if (player->mo == rtarget)
|
||||
return false;
|
||||
|
||||
if ((rtarget->Sector->ceilingplane.ZatPoint (rtarget->x, rtarget->y) -
|
||||
rtarget->Sector->floorplane.ZatPoint (rtarget->x, rtarget->y))
|
||||
< looker->height) //Where rtarget is, looker can't be.
|
||||
< player->mo->height) //Where rtarget is, player->mo can't be.
|
||||
return false;
|
||||
|
||||
sector_t *last_s = looker->Sector;
|
||||
fixed_t last_z = last_s->floorplane.ZatPoint (looker->x, looker->y);
|
||||
fixed_t estimated_dist = P_AproxDistance (looker->x - rtarget->x, looker->y - rtarget->y);
|
||||
sector_t *last_s = player->mo->Sector;
|
||||
fixed_t last_z = last_s->floorplane.ZatPoint (player->mo->x, player->mo->y);
|
||||
fixed_t estimated_dist = P_AproxDistance (player->mo->x - rtarget->x, player->mo->y - rtarget->y);
|
||||
bool reachable = true;
|
||||
|
||||
FPathTraverse it(looker->x+looker->velx, looker->y+looker->vely, rtarget->x, rtarget->y, PT_ADDLINES|PT_ADDTHINGS);
|
||||
FPathTraverse it(player->mo->x+player->mo->velx, player->mo->y+player->mo->vely, rtarget->x, rtarget->y, PT_ADDLINES|PT_ADDTHINGS);
|
||||
intercept_t *in;
|
||||
while ((in = it.Next()))
|
||||
{
|
||||
|
@ -55,8 +54,8 @@ bool FCajunMaster::Reachable (AActor *looker, AActor *rtarget)
|
|||
frac = in->frac - FixedDiv (4*FRACUNIT, MAX_TRAVERSE_DIST);
|
||||
dist = FixedMul (frac, MAX_TRAVERSE_DIST);
|
||||
|
||||
hitx = it.Trace().x + FixedMul (looker->velx, frac);
|
||||
hity = it.Trace().y + FixedMul (looker->vely, frac);
|
||||
hitx = it.Trace().x + FixedMul (player->mo->velx, frac);
|
||||
hity = it.Trace().y + FixedMul (player->mo->vely, frac);
|
||||
|
||||
if (in->isaline)
|
||||
{
|
||||
|
@ -76,7 +75,7 @@ bool FCajunMaster::Reachable (AActor *looker, AActor *rtarget)
|
|||
if (!bglobal.IsDangerous (s) && //Any nukage/lava?
|
||||
(floorheight <= (last_z+MAXMOVEHEIGHT)
|
||||
&& ((ceilingheight == floorheight && line->special)
|
||||
|| (ceilingheight - floorheight) >= looker->height))) //Does it fit?
|
||||
|| (ceilingheight - floorheight) >= player->mo->height))) //Does it fit?
|
||||
{
|
||||
last_z = floorheight;
|
||||
last_s = s;
|
||||
|
@ -95,7 +94,7 @@ bool FCajunMaster::Reachable (AActor *looker, AActor *rtarget)
|
|||
}
|
||||
|
||||
thing = in->d.thing;
|
||||
if (thing == looker) //Can't reach self in this case.
|
||||
if (thing == player->mo) //Can't reach self in this case.
|
||||
continue;
|
||||
if (thing == rtarget && (rtarget->Sector->floorplane.ZatPoint (rtarget->x, rtarget->y) <= (last_z+MAXMOVEHEIGHT)))
|
||||
{
|
||||
|
@ -115,16 +114,16 @@ bool FCajunMaster::Reachable (AActor *looker, AActor *rtarget)
|
|||
//if these conditions are true, the function returns true.
|
||||
//GOOD TO KNOW is that the player's view angle
|
||||
//in doom is 90 degrees infront.
|
||||
bool FCajunMaster::Check_LOS (AActor *from, AActor *to, angle_t vangle)
|
||||
bool DBot::Check_LOS (AActor *to, angle_t vangle)
|
||||
{
|
||||
if (!P_CheckSight (from, to, SF_SEEPASTBLOCKEVERYTHING))
|
||||
if (!P_CheckSight (player->mo, to, SF_SEEPASTBLOCKEVERYTHING))
|
||||
return false; // out of sight
|
||||
if (vangle == ANGLE_MAX)
|
||||
return true;
|
||||
if (vangle == 0)
|
||||
return false; //Looker seems to be blind.
|
||||
|
||||
return (angle_t)abs (R_PointToAngle2 (from->x, from->y, to->x, to->y) - from->angle) <= vangle/2;
|
||||
return (angle_t)abs (R_PointToAngle2 (player->mo->x, player->mo->y, to->x, to->y) - player->mo->angle) <= vangle/2;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
@ -132,7 +131,7 @@ bool FCajunMaster::Check_LOS (AActor *from, AActor *to, angle_t vangle)
|
|||
//-------------------------------------
|
||||
//The bot will check if it's time to fire
|
||||
//and do so if that is the case.
|
||||
void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd)
|
||||
void DBot::Dofire (ticcmd_t *cmd)
|
||||
{
|
||||
bool no_fire; //used to prevent bot from pumping rockets into nearby walls.
|
||||
int aiming_penalty=0; //For shooting at shading target, if screen is red, MAKEME: When screen red.
|
||||
|
@ -140,49 +139,48 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd)
|
|||
fixed_t dist;
|
||||
angle_t an;
|
||||
int m;
|
||||
AActor *enemy = actor->player->Bot->enemy;
|
||||
|
||||
if (!enemy || !(enemy->flags & MF_SHOOTABLE) || enemy->health <= 0)
|
||||
return;
|
||||
|
||||
if (actor->player->ReadyWeapon == NULL)
|
||||
if (player->ReadyWeapon == NULL)
|
||||
return;
|
||||
|
||||
if (actor->player->damagecount > actor->player->Bot->skill.isp)
|
||||
if (player->damagecount > skill.isp)
|
||||
{
|
||||
actor->player->Bot->first_shot = true;
|
||||
first_shot = true;
|
||||
return;
|
||||
}
|
||||
|
||||
//Reaction skill thing.
|
||||
if (actor->player->Bot->first_shot &&
|
||||
!(actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_REACTION_SKILL_THING))
|
||||
if (first_shot &&
|
||||
!(player->ReadyWeapon->WeaponFlags & WIF_BOT_REACTION_SKILL_THING))
|
||||
{
|
||||
actor->player->Bot->t_react = (100-actor->player->Bot->skill.reaction+1)/((pr_botdofire()%3)+3);
|
||||
t_react = (100-skill.reaction+1)/((pr_botdofire()%3)+3);
|
||||
}
|
||||
actor->player->Bot->first_shot = false;
|
||||
if (actor->player->Bot->t_react)
|
||||
first_shot = false;
|
||||
if (t_react)
|
||||
return;
|
||||
|
||||
//MAKEME: Decrease the rocket suicides even more.
|
||||
|
||||
no_fire = true;
|
||||
//actor->player->angle = R_PointToAngle2(actor->x, actor->y, actor->player->enemy->x, actor->player->enemy->y);
|
||||
//angle = R_PointToAngle2(player->mo->x, player->mo->y, player->enemy->x, player->enemy->y);
|
||||
//Distance to enemy.
|
||||
dist = P_AproxDistance ((actor->x + actor->velx) - (enemy->x + enemy->velx),
|
||||
(actor->y + actor->vely) - (enemy->y + enemy->vely));
|
||||
dist = P_AproxDistance ((player->mo->x + player->mo->velx) - (enemy->x + enemy->velx),
|
||||
(player->mo->y + player->mo->vely) - (enemy->y + enemy->vely));
|
||||
|
||||
//FIRE EACH TYPE OF WEAPON DIFFERENT: Here should all the different weapons go.
|
||||
if (actor->player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON)
|
||||
if (player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON)
|
||||
{
|
||||
if ((actor->player->ReadyWeapon->ProjectileType != NULL))
|
||||
if ((player->ReadyWeapon->ProjectileType != NULL))
|
||||
{
|
||||
if (actor->player->ReadyWeapon->CheckAmmo (AWeapon::PrimaryFire, false, true))
|
||||
if (player->ReadyWeapon->CheckAmmo (AWeapon::PrimaryFire, false, true))
|
||||
{
|
||||
// This weapon can fire a projectile and has enough ammo to do so
|
||||
goto shootmissile;
|
||||
}
|
||||
else if (!(actor->player->ReadyWeapon->WeaponFlags & WIF_AMMO_OPTIONAL))
|
||||
else if (!(player->ReadyWeapon->WeaponFlags & WIF_AMMO_OPTIONAL))
|
||||
{
|
||||
// Ammo is required, so don't shoot. This is for weapons that shoot
|
||||
// missiles that die at close range, such as the powered-up Phoneix Rod.
|
||||
|
@ -195,51 +193,51 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd)
|
|||
no_fire = (dist > (MELEERANGE*4));
|
||||
}
|
||||
}
|
||||
else if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_BFG)
|
||||
else if (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)<=skill.reaction)
|
||||
if(Check_LOS(enemy, SHOOTFOV))
|
||||
no_fire = false;
|
||||
}
|
||||
else if (actor->player->ReadyWeapon->ProjectileType != NULL)
|
||||
else if (player->ReadyWeapon->ProjectileType != NULL)
|
||||
{
|
||||
if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE)
|
||||
if (player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE)
|
||||
{
|
||||
//Special rules for RL
|
||||
an = FireRox (actor, enemy, cmd);
|
||||
an = FireRox (enemy, cmd);
|
||||
if(an)
|
||||
{
|
||||
actor->player->Bot->angle = an;
|
||||
angle = an;
|
||||
//have to be somewhat precise. to avoid suicide.
|
||||
if (abs (actor->player->Bot->angle - actor->angle) < 12*ANGLE_1)
|
||||
if (abs (angle - player->mo->angle) < 12*ANGLE_1)
|
||||
{
|
||||
actor->player->Bot->t_rocket = 9;
|
||||
t_rocket = 9;
|
||||
no_fire = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// prediction aiming
|
||||
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);
|
||||
if (Check_LOS (actor, enemy, SHOOTFOV))
|
||||
dist = P_AproxDistance (player->mo->x - enemy->x, player->mo->y - enemy->y);
|
||||
m = dist / GetDefaultByType (player->ReadyWeapon->ProjectileType)->Speed;
|
||||
bglobal.SetBodyAt (enemy->x + enemy->velx*m*2, enemy->y + enemy->vely*m*2, enemy->z, 1);
|
||||
angle = R_PointToAngle2 (player->mo->x, player->mo->y, bglobal.body1->x, bglobal.body1->y);
|
||||
if (Check_LOS (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);
|
||||
angle = R_PointToAngle2 (player->mo->x, player->mo->y, enemy->x, enemy->y);
|
||||
aiming_penalty = 0;
|
||||
if (enemy->flags & MF_SHADOW)
|
||||
aiming_penalty += (pr_botdofire()%25)+10;
|
||||
if (enemy->Sector->lightlevel<WHATS_DARK/* && !(actor->player->powers & PW_INFRARED)*/)
|
||||
if (enemy->Sector->lightlevel<WHATS_DARK/* && !(player->powers & PW_INFRARED)*/)
|
||||
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;
|
||||
if (player->damagecount)
|
||||
aiming_penalty += player->damagecount; //Blood in face makes it hard to aim
|
||||
aiming_value = skill.aiming - aiming_penalty;
|
||||
if (aiming_value <= 0)
|
||||
aiming_value = 1;
|
||||
m = ((SHOOTFOV/2)-(aiming_value*SHOOTFOV/200)); //Higher skill is more accurate
|
||||
|
@ -248,18 +246,18 @@ shootmissile:
|
|||
|
||||
if (m)
|
||||
{
|
||||
if (actor->player->Bot->increase)
|
||||
actor->player->Bot->angle += m;
|
||||
if (increase)
|
||||
angle += m;
|
||||
else
|
||||
actor->player->Bot->angle -= m;
|
||||
angle -= m;
|
||||
}
|
||||
|
||||
if (abs (actor->player->Bot->angle - actor->angle) < 4*ANGLE_1)
|
||||
if (abs (angle - player->mo->angle) < 4*ANGLE_1)
|
||||
{
|
||||
actor->player->Bot->increase = !actor->player->Bot->increase;
|
||||
increase = !increase;
|
||||
}
|
||||
|
||||
if (Check_LOS (actor, enemy, (SHOOTFOV/2)))
|
||||
if (Check_LOS (enemy, (SHOOTFOV/2)))
|
||||
no_fire = false;
|
||||
}
|
||||
if (!no_fire) //If going to fire weapon
|
||||
|
@ -267,7 +265,7 @@ shootmissile:
|
|||
cmd->ucmd.buttons |= BT_ATTACK;
|
||||
}
|
||||
//Prevents bot from jerking, when firing automatic things with low skill.
|
||||
//actor->angle = R_PointToAngle2(actor->x, actor->y, actor->player->enemy->x, actor->player->enemy->y);
|
||||
//player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->enemy->x, player->enemy->y);
|
||||
}
|
||||
|
||||
bool FCajunMaster::IsLeader (player_t *player)
|
||||
|
@ -287,7 +285,7 @@ bool FCajunMaster::IsLeader (player_t *player)
|
|||
//This function is called every
|
||||
//tick (for each bot) to set
|
||||
//the mate (teammate coop mate).
|
||||
AActor *FCajunMaster::Choose_Mate (AActor *bot)
|
||||
AActor *DBot::Choose_Mate ()
|
||||
{
|
||||
int count;
|
||||
fixed_t closest_dist, test;
|
||||
|
@ -295,20 +293,20 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot)
|
|||
AActor *observer;
|
||||
|
||||
//is mate alive?
|
||||
if (bot->player->Bot->mate)
|
||||
if (mate)
|
||||
{
|
||||
if (bot->player->Bot->mate->health <= 0)
|
||||
bot->player->Bot->mate = NULL;
|
||||
if (mate->health <= 0)
|
||||
mate = NULL;
|
||||
else
|
||||
bot->player->Bot->last_mate = bot->player->Bot->mate;
|
||||
last_mate = mate;
|
||||
}
|
||||
if (bot->player->Bot->mate) //Still is..
|
||||
return bot->player->Bot->mate;
|
||||
if (mate) //Still is..
|
||||
return 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 (last_mate)
|
||||
if (last_mate->health <= 0)
|
||||
last_mate = NULL;
|
||||
|
||||
target = NULL;
|
||||
closest_dist = FIXED_MAX;
|
||||
|
@ -324,17 +322,17 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot)
|
|||
|
||||
if (playeringame[count]
|
||||
&& client->mo
|
||||
&& bot != client->mo
|
||||
&& (bot->IsTeammate (client->mo) || !deathmatch)
|
||||
&& player->mo != client->mo
|
||||
&& (player->mo->IsTeammate (client->mo) || !deathmatch)
|
||||
&& client->mo->health > 0
|
||||
&& client->mo != observer
|
||||
&& ((bot->health/2) <= client->mo->health || !deathmatch)
|
||||
&& !IsLeader(client)) //taken?
|
||||
&& ((player->mo->health/2) <= client->mo->health || !deathmatch)
|
||||
&& !bglobal.IsLeader(client)) //taken?
|
||||
{
|
||||
if (P_CheckSight (bot, client->mo, SF_IGNOREVISIBILITY))
|
||||
if (P_CheckSight (player->mo, client->mo, SF_IGNOREVISIBILITY))
|
||||
{
|
||||
test = P_AproxDistance (client->mo->x - bot->x,
|
||||
client->mo->y - bot->y);
|
||||
test = P_AproxDistance (client->mo->x - player->mo->x,
|
||||
client->mo->y - player->mo->y);
|
||||
|
||||
if (test < closest_dist)
|
||||
{
|
||||
|
@ -347,15 +345,15 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot)
|
|||
|
||||
/*
|
||||
//Make a introducing to mate.
|
||||
if(target && target!=bot->player->last_mate)
|
||||
if(target && target!=last_mate)
|
||||
{
|
||||
if((P_Random()%(200*bglobal.botnum))<3)
|
||||
{
|
||||
bot->player->chat = c_teamup;
|
||||
chat = c_teamup;
|
||||
if(target->bot)
|
||||
strcpy(bot->player->c_target, botsingame[target->bot_id]);
|
||||
strcpy(c_target, botsingame[target->bot_id]);
|
||||
else if(target->player)
|
||||
strcpy(bot->player->c_target, player_names[target->play_id]);
|
||||
strcpy(c_target, player_names[target->play_id]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -365,7 +363,7 @@ AActor *FCajunMaster::Choose_Mate (AActor *bot)
|
|||
}
|
||||
|
||||
//MAKEME: Make this a smart decision
|
||||
AActor *FCajunMaster::Find_enemy (AActor *bot)
|
||||
AActor *DBot::Find_enemy ()
|
||||
{
|
||||
int count;
|
||||
fixed_t closest_dist, temp; //To target.
|
||||
|
@ -375,15 +373,15 @@ AActor *FCajunMaster::Find_enemy (AActor *bot)
|
|||
|
||||
if (!deathmatch)
|
||||
{ // [RH] Take advantage of the Heretic/Hexen code to be a little smarter
|
||||
return P_RoughMonsterSearch (bot, 20);
|
||||
return P_RoughMonsterSearch (player->mo, 20);
|
||||
}
|
||||
|
||||
//Note: It's hard to ambush a bot who is not alone
|
||||
if (bot->player->Bot->allround || bot->player->Bot->mate)
|
||||
if (allround || mate)
|
||||
vangle = ANGLE_MAX;
|
||||
else
|
||||
vangle = ENEMY_SCAN_FOV;
|
||||
bot->player->Bot->allround = false;
|
||||
allround = false;
|
||||
|
||||
target = NULL;
|
||||
closest_dist = FIXED_MAX;
|
||||
|
@ -396,21 +394,21 @@ AActor *FCajunMaster::Find_enemy (AActor *bot)
|
|||
{
|
||||
player_t *client = &players[count];
|
||||
if (playeringame[count]
|
||||
&& !bot->IsTeammate (client->mo)
|
||||
&& !player->mo->IsTeammate (client->mo)
|
||||
&& client->mo != observer
|
||||
&& client->mo->health > 0
|
||||
&& bot != client->mo)
|
||||
&& player->mo != client->mo)
|
||||
{
|
||||
if (Check_LOS (bot, client->mo, vangle)) //Here's a strange one, when bot is standing still, the P_CheckSight within Check_LOS almost always returns false. tought it should be the same checksight as below but.. (below works) something must be fuckin wierd screded up.
|
||||
//if(P_CheckSight(bot, players[count].mo))
|
||||
if (Check_LOS (client->mo, vangle)) //Here's a strange one, when bot is standing still, the P_CheckSight within Check_LOS almost always returns false. tought it should be the same checksight as below but.. (below works) something must be fuckin wierd screded up.
|
||||
//if(P_CheckSight(player->mo, players[count].mo))
|
||||
{
|
||||
temp = P_AproxDistance (client->mo->x - bot->x,
|
||||
client->mo->y - bot->y);
|
||||
temp = P_AproxDistance (client->mo->x - player->mo->x,
|
||||
client->mo->y - player->mo->y);
|
||||
|
||||
//Too dark?
|
||||
if (temp > DARK_DIST &&
|
||||
client->mo->Sector->lightlevel < WHATS_DARK /*&&
|
||||
bot->player->Powers & PW_INFRARED*/)
|
||||
player->Powers & PW_INFRARED*/)
|
||||
continue;
|
||||
|
||||
if (temp < closest_dist)
|
||||
|
@ -494,16 +492,16 @@ fixed_t FCajunMaster::FakeFire (AActor *source, AActor *dest, ticcmd_t *cmd)
|
|||
return dist;
|
||||
}
|
||||
|
||||
angle_t FCajunMaster::FireRox (AActor *bot, AActor *enemy, ticcmd_t *cmd)
|
||||
angle_t DBot::FireRox (AActor *enemy, ticcmd_t *cmd)
|
||||
{
|
||||
fixed_t dist;
|
||||
angle_t ang;
|
||||
AActor *actor;
|
||||
int m;
|
||||
|
||||
SetBodyAt (bot->x + FixedMul(bot->velx, 5*FRACUNIT),
|
||||
bot->y + FixedMul(bot->vely, 5*FRACUNIT),
|
||||
bot->z + (bot->height / 2), 2);
|
||||
bglobal.SetBodyAt (player->mo->x + FixedMul(player->mo->velx, 5*FRACUNIT),
|
||||
player->mo->y + FixedMul(player->mo->vely, 5*FRACUNIT),
|
||||
player->mo->z + (player->mo->height / 2), 2);
|
||||
|
||||
actor = bglobal.body2;
|
||||
|
||||
|
@ -513,16 +511,16 @@ angle_t FCajunMaster::FireRox (AActor *bot, AActor *enemy, ticcmd_t *cmd)
|
|||
//Predict.
|
||||
m = (((dist+1)/FRACUNIT) / GetDefaultByName("Rocket")->Speed);
|
||||
|
||||
SetBodyAt (enemy->x + FixedMul(enemy->velx, (m+2*FRACUNIT)),
|
||||
enemy->y + FixedMul(enemy->vely, (m+2*FRACUNIT)), ONFLOORZ, 1);
|
||||
bglobal.SetBodyAt (enemy->x + FixedMul(enemy->velx, (m+2*FRACUNIT)),
|
||||
enemy->y + FixedMul(enemy->vely, (m+2*FRACUNIT)), ONFLOORZ, 1);
|
||||
dist = P_AproxDistance(actor->x-bglobal.body1->x, actor->y-bglobal.body1->y);
|
||||
//try the predicted location
|
||||
if (P_CheckSight (actor, bglobal.body1, SF_IGNOREVISIBILITY)) //See the predicted location, so give a test missile
|
||||
{
|
||||
FCheckPosition tm;
|
||||
if (SafeCheckPosition (bot, actor->x, actor->y, tm))
|
||||
if (bglobal.SafeCheckPosition (player->mo, actor->x, actor->y, tm))
|
||||
{
|
||||
if (FakeFire (actor, bglobal.body1, cmd) >= SAFE_SELF_MISDIST)
|
||||
if (bglobal.FakeFire (actor, bglobal.body1, cmd) >= SAFE_SELF_MISDIST)
|
||||
{
|
||||
ang = R_PointToAngle2 (actor->x, actor->y, bglobal.body1->x, bglobal.body1->y);
|
||||
return ang;
|
||||
|
@ -532,9 +530,9 @@ angle_t FCajunMaster::FireRox (AActor *bot, AActor *enemy, ticcmd_t *cmd)
|
|||
//Try fire straight.
|
||||
if (P_CheckSight (actor, enemy, 0))
|
||||
{
|
||||
if (FakeFire (bot, enemy, cmd) >= SAFE_SELF_MISDIST)
|
||||
if (bglobal.FakeFire (player->mo, enemy, cmd) >= SAFE_SELF_MISDIST)
|
||||
{
|
||||
ang = R_PointToAngle2(bot->x, bot->y, enemy->x, enemy->y);
|
||||
ang = R_PointToAngle2(player->mo->x, player->mo->y, enemy->x, enemy->y);
|
||||
return ang;
|
||||
}
|
||||
}
|
||||
|
|
123
src/b_move.cpp
123
src/b_move.cpp
|
@ -27,57 +27,57 @@ static FRandom pr_botnewchasedir ("BotNewChaseDir");
|
|||
extern dirtype_t opposite[9];
|
||||
extern dirtype_t diags[4];
|
||||
|
||||
//Called while the bot moves after its player->dest mobj
|
||||
//Called while the bot moves after its dest mobj
|
||||
//which can be a weapon/enemy/item whatever.
|
||||
void FCajunMaster::Roam (AActor *actor, ticcmd_t *cmd)
|
||||
void DBot::Roam (ticcmd_t *cmd)
|
||||
{
|
||||
int delta;
|
||||
|
||||
if (Reachable(actor, actor->player->Bot->dest))
|
||||
if (Reachable(dest))
|
||||
{ // Straight towards it.
|
||||
actor->player->Bot->angle = R_PointToAngle2(actor->x, actor->y, actor->player->Bot->dest->x, actor->player->Bot->dest->y);
|
||||
angle = R_PointToAngle2(player->mo->x, player->mo->y, dest->x, dest->y);
|
||||
}
|
||||
else if (actor->movedir < 8) // turn towards movement direction if not there yet
|
||||
else if (player->mo->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);
|
||||
angle &= (angle_t)(7<<29);
|
||||
delta = angle - (player->mo->movedir << 29);
|
||||
|
||||
if (delta > 0)
|
||||
actor->player->Bot->angle -= ANG45;
|
||||
angle -= ANG45;
|
||||
else if (delta < 0)
|
||||
actor->player->Bot->angle += ANG45;
|
||||
angle += ANG45;
|
||||
}
|
||||
|
||||
// chase towards destination.
|
||||
if (--actor->movecount < 0 || !Move (actor, cmd))
|
||||
if (--player->mo->movecount < 0 || !Move (cmd))
|
||||
{
|
||||
NewChaseDir (actor, cmd);
|
||||
NewChaseDir (cmd);
|
||||
}
|
||||
}
|
||||
|
||||
bool FCajunMaster::Move (AActor *actor, ticcmd_t *cmd)
|
||||
bool DBot::Move (ticcmd_t *cmd)
|
||||
{
|
||||
fixed_t tryx, tryy;
|
||||
bool try_ok;
|
||||
int good;
|
||||
|
||||
if (actor->movedir == DI_NODIR)
|
||||
if (player->mo->movedir == DI_NODIR)
|
||||
return false;
|
||||
|
||||
if ((unsigned)actor->movedir >= 8)
|
||||
if ((unsigned)player->mo->movedir >= 8)
|
||||
I_Error ("Weird bot movedir!");
|
||||
|
||||
tryx = actor->x + 8*xspeed[actor->movedir];
|
||||
tryy = actor->y + 8*yspeed[actor->movedir];
|
||||
tryx = player->mo->x + 8*xspeed[player->mo->movedir];
|
||||
tryy = player->mo->y + 8*yspeed[player->mo->movedir];
|
||||
|
||||
try_ok = CleanAhead (actor, tryx, tryy, cmd);
|
||||
try_ok = bglobal.CleanAhead (player->mo, tryx, tryy, cmd);
|
||||
|
||||
if (!try_ok) //Anything blocking that could be opened etc..
|
||||
{
|
||||
if (!spechit.Size ())
|
||||
return false;
|
||||
|
||||
actor->movedir = DI_NODIR;
|
||||
player->mo->movedir = DI_NODIR;
|
||||
|
||||
good = 0;
|
||||
line_t *ld;
|
||||
|
@ -86,16 +86,16 @@ bool FCajunMaster::Move (AActor *actor, ticcmd_t *cmd)
|
|||
{
|
||||
bool tryit = true;
|
||||
|
||||
if (ld->special == Door_LockedRaise && !P_CheckKeys (actor, ld->args[3], false))
|
||||
if (ld->special == Door_LockedRaise && !P_CheckKeys (player->mo, ld->args[3], false))
|
||||
tryit = false;
|
||||
else if (ld->special == Generic_Door && !P_CheckKeys (actor, ld->args[4], false))
|
||||
else if (ld->special == Generic_Door && !P_CheckKeys (player->mo, ld->args[4], false))
|
||||
tryit = false;
|
||||
|
||||
if (tryit &&
|
||||
(P_TestActivateLine (ld, actor, 0, SPAC_Use) ||
|
||||
P_TestActivateLine (ld, actor, 0, SPAC_Push)))
|
||||
(P_TestActivateLine (ld, player->mo, 0, SPAC_Use) ||
|
||||
P_TestActivateLine (ld, player->mo, 0, SPAC_Push)))
|
||||
{
|
||||
good |= ld == actor->BlockingLine ? 1 : 2;
|
||||
good |= ld == player->mo->BlockingLine ? 1 : 2;
|
||||
}
|
||||
}
|
||||
if (good && ((pr_botopendoor() >= 203) ^ (good & 1)))
|
||||
|
@ -113,16 +113,16 @@ bool FCajunMaster::Move (AActor *actor, ticcmd_t *cmd)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FCajunMaster::TryWalk (AActor *actor, ticcmd_t *cmd)
|
||||
bool DBot::TryWalk (ticcmd_t *cmd)
|
||||
{
|
||||
if (!Move (actor, cmd))
|
||||
if (!Move (cmd))
|
||||
return false;
|
||||
|
||||
actor->movecount = pr_bottrywalk() & 60;
|
||||
player->mo->movecount = pr_bottrywalk() & 60;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd)
|
||||
void DBot::NewChaseDir (ticcmd_t *cmd)
|
||||
{
|
||||
fixed_t deltax;
|
||||
fixed_t deltay;
|
||||
|
@ -134,7 +134,7 @@ void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd)
|
|||
|
||||
dirtype_t turnaround;
|
||||
|
||||
if (!actor->player->Bot->dest)
|
||||
if (!dest)
|
||||
{
|
||||
#ifndef BOT_RELEASE_COMPILE
|
||||
Printf ("Bot tried move without destination\n");
|
||||
|
@ -142,11 +142,11 @@ void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd)
|
|||
return;
|
||||
}
|
||||
|
||||
olddir = (dirtype_t)actor->movedir;
|
||||
olddir = (dirtype_t)player->mo->movedir;
|
||||
turnaround = opposite[olddir];
|
||||
|
||||
deltax = actor->player->Bot->dest->x - actor->x;
|
||||
deltay = actor->player->Bot->dest->y - actor->y;
|
||||
deltax = dest->x - player->mo->x;
|
||||
deltay = dest->y - player->mo->y;
|
||||
|
||||
if (deltax > 10*FRACUNIT)
|
||||
d[1] = DI_EAST;
|
||||
|
@ -165,8 +165,8 @@ void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd)
|
|||
// try direct route
|
||||
if (d[1] != DI_NODIR && d[2] != DI_NODIR)
|
||||
{
|
||||
actor->movedir = diags[((deltay<0)<<1)+(deltax>0)];
|
||||
if (actor->movedir != turnaround && TryWalk(actor, cmd))
|
||||
player->mo->movedir = diags[((deltay<0)<<1)+(deltax>0)];
|
||||
if (player->mo->movedir != turnaround && TryWalk(cmd))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -186,16 +186,16 @@ void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd)
|
|||
|
||||
if (d[1]!=DI_NODIR)
|
||||
{
|
||||
actor->movedir = d[1];
|
||||
if (TryWalk (actor, cmd))
|
||||
player->mo->movedir = d[1];
|
||||
if (TryWalk (cmd))
|
||||
return;
|
||||
}
|
||||
|
||||
if (d[2]!=DI_NODIR)
|
||||
{
|
||||
actor->movedir = d[2];
|
||||
player->mo->movedir = d[2];
|
||||
|
||||
if (TryWalk(actor, cmd))
|
||||
if (TryWalk(cmd))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -203,9 +203,9 @@ void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd)
|
|||
// so pick another direction.
|
||||
if (olddir!=DI_NODIR)
|
||||
{
|
||||
actor->movedir = olddir;
|
||||
player->mo->movedir = olddir;
|
||||
|
||||
if (TryWalk(actor, cmd))
|
||||
if (TryWalk(cmd))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -218,9 +218,9 @@ void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd)
|
|||
{
|
||||
if (tdir!=turnaround)
|
||||
{
|
||||
actor->movedir = tdir;
|
||||
player->mo->movedir = tdir;
|
||||
|
||||
if (TryWalk(actor, cmd))
|
||||
if (TryWalk(cmd))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -233,9 +233,9 @@ void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd)
|
|||
{
|
||||
if (tdir!=turnaround)
|
||||
{
|
||||
actor->movedir = tdir;
|
||||
player->mo->movedir = tdir;
|
||||
|
||||
if (TryWalk(actor, cmd))
|
||||
if (TryWalk(cmd))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -243,12 +243,12 @@ void FCajunMaster::NewChaseDir (AActor *actor, ticcmd_t *cmd)
|
|||
|
||||
if (turnaround != DI_NODIR)
|
||||
{
|
||||
actor->movedir = turnaround;
|
||||
if (TryWalk(actor, cmd))
|
||||
player->mo->movedir = turnaround;
|
||||
if (TryWalk(cmd))
|
||||
return;
|
||||
}
|
||||
|
||||
actor->movedir = DI_NODIR; // can not move
|
||||
player->mo->movedir = DI_NODIR; // can not move
|
||||
}
|
||||
|
||||
|
||||
|
@ -307,48 +307,48 @@ bool FCajunMaster::CleanAhead (AActor *thing, fixed_t x, fixed_t y, ticcmd_t *cm
|
|||
#define MAXTURN (15*ANGLE_1) //Max degrees turned in one tic. Lower is smother but may cause the bot not getting where it should = crash
|
||||
#define TURNSENS 3 //Higher is smoother but slower turn.
|
||||
|
||||
void FCajunMaster::TurnToAng (AActor *actor)
|
||||
void DBot::TurnToAng ()
|
||||
{
|
||||
int maxturn = MAXTURN;
|
||||
|
||||
if (actor->player->ReadyWeapon != NULL)
|
||||
if (player->ReadyWeapon != NULL)
|
||||
{
|
||||
if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE)
|
||||
if (player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE)
|
||||
{
|
||||
if (actor->player->Bot->t_roam && !actor->player->Bot->missile)
|
||||
if (t_roam && !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->ReadyWeapon->ProjectileType == NULL && !(actor->player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON))
|
||||
if(Check_LOS(actor, actor->player->Bot->enemy, SHOOTFOV+5*ANGLE_1))
|
||||
if(enemy)
|
||||
if(!dest) //happens when running after item in combat situations, or normal, prevents weak turns
|
||||
if(player->ReadyWeapon->ProjectileType == NULL && !(player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON))
|
||||
if(Check_LOS(enemy, SHOOTFOV+5*ANGLE_1))
|
||||
maxturn = 3;
|
||||
}
|
||||
|
||||
int distance = actor->player->Bot->angle - actor->angle;
|
||||
int distance = angle - player->mo->angle;
|
||||
|
||||
if (abs (distance) < OKAYRANGE && !actor->player->Bot->enemy)
|
||||
if (abs (distance) < OKAYRANGE && !enemy)
|
||||
return;
|
||||
|
||||
distance /= TURNSENS;
|
||||
if (abs (distance) > maxturn)
|
||||
distance = distance < 0 ? -maxturn : maxturn;
|
||||
|
||||
actor->angle += distance;
|
||||
player->mo->angle += distance;
|
||||
}
|
||||
|
||||
void FCajunMaster::Pitch (AActor *actor, AActor *target)
|
||||
void DBot::Pitch (AActor *target)
|
||||
{
|
||||
double aim;
|
||||
double diff;
|
||||
|
||||
diff = target->z - actor->z;
|
||||
aim = atan (diff / (double)P_AproxDistance (actor->x - target->x, actor->y - target->y));
|
||||
actor->pitch = -(int)(aim * ANGLE_180/M_PI);
|
||||
diff = target->z - player->mo->z;
|
||||
aim = atan (diff / (double)P_AproxDistance (player->mo->x - target->x, player->mo->y - target->y));
|
||||
player->mo->pitch = -(int)(aim * ANGLE_180/M_PI);
|
||||
}
|
||||
|
||||
//Checks if a sector is dangerous.
|
||||
|
@ -371,4 +371,3 @@ bool FCajunMaster::IsDangerous (sector_t *sec)
|
|||
|| special == Damage_InstantDeath
|
||||
|| special == sDamage_SuperHellslime;
|
||||
}
|
||||
|
||||
|
|
284
src/b_think.cpp
284
src/b_think.cpp
|
@ -24,47 +24,49 @@ static FRandom pr_botmove ("BotMove");
|
|||
|
||||
//This function is called each tic for each bot,
|
||||
//so this is what the bot does.
|
||||
void FCajunMaster::Think (AActor *actor, ticcmd_t *cmd)
|
||||
void DBot::Think ()
|
||||
{
|
||||
ticcmd_t *cmd = &netcmds[player - players][((gametic + 1)/ticdup)%BACKUPTICS];
|
||||
|
||||
memset (cmd, 0, sizeof(*cmd));
|
||||
|
||||
if (actor->player->Bot->enemy && actor->player->Bot->enemy->health <= 0)
|
||||
actor->player->Bot->enemy = NULL;
|
||||
if (enemy && enemy->health <= 0)
|
||||
enemy = NULL;
|
||||
|
||||
if (actor->health > 0) //Still alive
|
||||
if (player->mo->health > 0) //Still alive
|
||||
{
|
||||
if (teamplay || !deathmatch)
|
||||
actor->player->Bot->mate = Choose_Mate (actor);
|
||||
mate = Choose_Mate ();
|
||||
|
||||
angle_t oldyaw = actor->angle;
|
||||
int oldpitch = actor->pitch;
|
||||
angle_t oldyaw = player->mo->angle;
|
||||
int oldpitch = player->mo->pitch;
|
||||
|
||||
Set_enemy (actor);
|
||||
ThinkForMove (actor, cmd);
|
||||
TurnToAng (actor);
|
||||
Set_enemy ();
|
||||
ThinkForMove (cmd);
|
||||
TurnToAng ();
|
||||
|
||||
cmd->ucmd.yaw = (short)((actor->angle - oldyaw) >> 16) / ticdup;
|
||||
cmd->ucmd.pitch = (short)((oldpitch - actor->pitch) >> 16);
|
||||
cmd->ucmd.yaw = (short)((player->mo->angle - oldyaw) >> 16) / ticdup;
|
||||
cmd->ucmd.pitch = (short)((oldpitch - player->mo->pitch) >> 16);
|
||||
if (cmd->ucmd.pitch == -32768)
|
||||
cmd->ucmd.pitch = -32767;
|
||||
cmd->ucmd.pitch /= ticdup;
|
||||
actor->angle = oldyaw + (cmd->ucmd.yaw << 16) * ticdup;
|
||||
actor->pitch = oldpitch - (cmd->ucmd.pitch << 16) * ticdup;
|
||||
player->mo->angle = oldyaw + (cmd->ucmd.yaw << 16) * ticdup;
|
||||
player->mo->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 (t_active) t_active--;
|
||||
if (t_strafe) t_strafe--;
|
||||
if (t_react) t_react--;
|
||||
if (t_fight) t_fight--;
|
||||
if (t_rocket) t_rocket--;
|
||||
if (t_roam) t_roam--;
|
||||
|
||||
//Respawn ticker
|
||||
if (actor->player->Bot->t_respawn)
|
||||
if (t_respawn)
|
||||
{
|
||||
actor->player->Bot->t_respawn--;
|
||||
t_respawn--;
|
||||
}
|
||||
else if (actor->health <= 0)
|
||||
else if (player->mo->health <= 0)
|
||||
{ // Time to respawn
|
||||
cmd->ucmd.buttons |= BT_USE;
|
||||
}
|
||||
|
@ -72,62 +74,57 @@ void FCajunMaster::Think (AActor *actor, ticcmd_t *cmd)
|
|||
|
||||
//how the bot moves.
|
||||
//MAIN movement function.
|
||||
void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd)
|
||||
void DBot::ThinkForMove (ticcmd_t *cmd)
|
||||
{
|
||||
player_t *b;
|
||||
fixed_t dist;
|
||||
bool stuck;
|
||||
int r;
|
||||
|
||||
b = actor->player;
|
||||
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 = dest ? P_AproxDistance(player->mo->x-dest->x, player->mo->y-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 (missile &&
|
||||
((!missile->velx || !missile->vely) || !Check_LOS(missile, SHOOTFOV*3/2)))
|
||||
{
|
||||
b->Bot->sleft = !b->Bot->sleft;
|
||||
b->Bot->missile = NULL; //Probably ended its travel.
|
||||
sleft = !sleft;
|
||||
missile = NULL; //Probably ended its travel.
|
||||
}
|
||||
|
||||
if (actor->pitch > 0)
|
||||
actor->pitch -= 80;
|
||||
else if (actor->pitch <= -60)
|
||||
actor->pitch += 80;
|
||||
if (player->mo->pitch > 0)
|
||||
player->mo->pitch -= 80;
|
||||
else if (player->mo->pitch <= -60)
|
||||
player->mo->pitch += 80;
|
||||
|
||||
//HOW TO MOVE:
|
||||
if (b->Bot->missile && (P_AproxDistance(actor->x-b->Bot->missile->x, actor->y-b->Bot->missile->y)<AVOID_DIST)) //try avoid missile got from P_Mobj.c thinking part.
|
||||
if (missile && (P_AproxDistance(player->mo->x-missile->x, player->mo->y-missile->y)<AVOID_DIST)) //try avoid missile got from P_Mobj.c thinking part.
|
||||
{
|
||||
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;
|
||||
Pitch (missile);
|
||||
angle = R_PointToAngle2(player->mo->x, player->mo->y, missile->x, missile->y);
|
||||
cmd->ucmd.sidemove = 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(player->mo->x-oldx, player->mo->y-oldy)<50000)
|
||||
&& t_strafe<=0)
|
||||
{
|
||||
b->Bot->t_strafe = 5;
|
||||
b->Bot->sleft = !b->Bot->sleft;
|
||||
t_strafe = 5;
|
||||
sleft = !sleft;
|
||||
}
|
||||
|
||||
//If able to see enemy while avoiding missile, still fire at enemy.
|
||||
if (b->Bot->enemy && Check_LOS (actor, b->Bot->enemy, SHOOTFOV))
|
||||
Dofire (actor, cmd); //Order bot to fire current weapon
|
||||
if (enemy && Check_LOS (enemy, SHOOTFOV))
|
||||
Dofire (cmd); //Order bot to fire current weapon
|
||||
}
|
||||
else if (b->Bot->enemy && P_CheckSight (actor, b->Bot->enemy, 0)) //Fight!
|
||||
else if (enemy && P_CheckSight (player->mo, enemy, 0)) //Fight!
|
||||
{
|
||||
Pitch (actor, b->Bot->enemy);
|
||||
Pitch (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 (dest && (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) dest->IsKindOf (PClass::FindClass (#x))
|
||||
if (
|
||||
(
|
||||
(actor->health < b->Bot->skill.isp &&
|
||||
(player->mo->health < skill.isp &&
|
||||
(is (Medikit) ||
|
||||
is (Stimpack) ||
|
||||
is (Soulsphere) ||
|
||||
|
@ -140,78 +137,78 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd)
|
|||
is (Megasphere)
|
||||
) ||
|
||||
dist < (GETINCOMBAT/4) ||
|
||||
(b->ReadyWeapon == NULL || b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)
|
||||
(player->ReadyWeapon == NULL || player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)
|
||||
)
|
||||
&& (dist < GETINCOMBAT || (b->ReadyWeapon == NULL || b->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
|
||||
&& Reachable (actor, b->Bot->dest))
|
||||
&& (dist < GETINCOMBAT || (player->ReadyWeapon == NULL || player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
|
||||
&& Reachable (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
|
||||
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 (player->ReadyWeapon != NULL && !(player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
|
||||
player->mo->flags &= ~MF_DROPOFF; //Don't jump off any ledges when fighting.
|
||||
|
||||
if (!(b->Bot->enemy->flags3 & MF3_ISMONSTER))
|
||||
b->Bot->t_fight = AFTERTICS;
|
||||
if (!(enemy->flags3 & MF3_ISMONSTER))
|
||||
t_fight = AFTERTICS;
|
||||
|
||||
if (b->Bot->t_strafe <= 0 &&
|
||||
(P_AproxDistance(actor->x-b->Bot->oldx, actor->y-b->Bot->oldy)<50000
|
||||
if (t_strafe <= 0 &&
|
||||
(P_AproxDistance(player->mo->x-oldx, player->mo->y-oldy)<50000
|
||||
|| ((pr_botmove()%30)==10))
|
||||
)
|
||||
{
|
||||
stuck = true;
|
||||
b->Bot->t_strafe = 5;
|
||||
b->Bot->sleft = !b->Bot->sleft;
|
||||
t_strafe = 5;
|
||||
sleft = !sleft;
|
||||
}
|
||||
|
||||
b->Bot->angle = R_PointToAngle2(actor->x, actor->y, b->Bot->enemy->x, b->Bot->enemy->y);
|
||||
angle = R_PointToAngle2(player->mo->x, player->mo->y, enemy->x, enemy->y);
|
||||
|
||||
if (b->ReadyWeapon == NULL ||
|
||||
P_AproxDistance(actor->x-b->Bot->enemy->x, actor->y-b->Bot->enemy->y) >
|
||||
b->ReadyWeapon->MoveCombatDist)
|
||||
if (player->ReadyWeapon == NULL ||
|
||||
P_AproxDistance(player->mo->x-enemy->x, player->mo->y-enemy->y) >
|
||||
player->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 = (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 = (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 (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 = sleft ? -SIDEWALK : SIDEWALK;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd->ucmd.sidemove = b->Bot->sleft ? -SIDERUN : SIDERUN;
|
||||
cmd->ucmd.sidemove = sleft ? -SIDERUN : SIDERUN;
|
||||
}
|
||||
Dofire (actor, cmd); //Order bot to fire current weapon
|
||||
Dofire (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 (mate && !enemy && (!dest || dest==mate)) //Follow mate move.
|
||||
{
|
||||
fixed_t matedist;
|
||||
|
||||
Pitch (actor, b->Bot->mate);
|
||||
Pitch (mate);
|
||||
|
||||
if (!Reachable (actor, b->Bot->mate))
|
||||
if (!Reachable (mate))
|
||||
{
|
||||
if (b->Bot->mate == b->Bot->dest && pr_botmove.Random() < 32)
|
||||
if (mate == dest && pr_botmove.Random() < 32)
|
||||
{ // [RH] If the mate is the dest, pick a new dest sometimes
|
||||
b->Bot->dest = NULL;
|
||||
dest = NULL;
|
||||
}
|
||||
goto roam;
|
||||
}
|
||||
|
||||
actor->player->Bot->angle = R_PointToAngle2(actor->x, actor->y, b->Bot->mate->x, b->Bot->mate->y);
|
||||
angle = R_PointToAngle2(player->mo->x, player->mo->y, mate->x, mate->y);
|
||||
|
||||
matedist = P_AproxDistance(actor->x - b->Bot->mate->x, actor->y - b->Bot->mate->y);
|
||||
matedist = P_AproxDistance(player->mo->x - mate->x, player->mo->y - mate->y);
|
||||
if (matedist > (FRIEND_DIST*2))
|
||||
cmd->ucmd.forwardmove = FORWARDRUN;
|
||||
else if (matedist > FRIEND_DIST)
|
||||
|
@ -221,42 +218,42 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd)
|
|||
}
|
||||
else //Roam after something.
|
||||
{
|
||||
b->Bot->first_shot = true;
|
||||
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.
|
||||
Dofire (actor, cmd); //Order bot to fire current weapon
|
||||
if (enemy && Check_LOS (enemy, SHOOTFOV*3/2)) //If able to see enemy while avoiding missile , still fire at it.
|
||||
Dofire (cmd); //Order bot to fire current weapon
|
||||
|
||||
if (b->Bot->dest && !(b->Bot->dest->flags&MF_SPECIAL) && b->Bot->dest->health < 0)
|
||||
if (dest && !(dest->flags&MF_SPECIAL) && dest->health < 0)
|
||||
{ //Roaming after something dead.
|
||||
b->Bot->dest = NULL;
|
||||
dest = NULL;
|
||||
}
|
||||
|
||||
if (b->Bot->dest == NULL)
|
||||
if (dest == NULL)
|
||||
{
|
||||
if (b->Bot->t_fight && b->Bot->enemy) //Enemy/bot has jumped around corner. So what to do?
|
||||
if (t_fight && enemy) //Enemy/bot has jumped around corner. So what to do?
|
||||
{
|
||||
if (b->Bot->enemy->player)
|
||||
if (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.
|
||||
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);
|
||||
if (((enemy->player->ReadyWeapon != NULL && enemy->player->ReadyWeapon->WeaponFlags & WIF_BOT_EXPLOSIVE) ||
|
||||
(pr_botmove()%100)>skill.isp) && player->ReadyWeapon != NULL && !(player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
|
||||
dest = enemy;//Dont let enemy kill the bot by supressive fire. So charge enemy.
|
||||
else //hide while t_fight, but keep view at enemy.
|
||||
angle = R_PointToAngle2(player->mo->x, player->mo->y, enemy->x, enemy->y);
|
||||
} //Just a monster, so kill it.
|
||||
else
|
||||
b->Bot->dest = b->Bot->enemy;
|
||||
dest = enemy;
|
||||
|
||||
//VerifFavoritWeapon(actor->player); //Dont know why here.., but it must be here, i know the reason, but not why at this spot, uh.
|
||||
//VerifFavoritWeapon(player); //Dont know why here.., but it must be here, i know the reason, but not why at this spot, uh.
|
||||
}
|
||||
else //Choose a distant target. to get things going.
|
||||
{
|
||||
r = pr_botmove();
|
||||
if (r < 128)
|
||||
{
|
||||
TThinkerIterator<AInventory> it (STAT_INVENTORY, firstthing);
|
||||
TThinkerIterator<AInventory> it (STAT_INVENTORY, bglobal.firstthing);
|
||||
AInventory *item = it.Next();
|
||||
|
||||
if (item != NULL || (item = it.Next()) != NULL)
|
||||
|
@ -271,60 +268,53 @@ void FCajunMaster::ThinkForMove (AActor *actor, ticcmd_t *cmd)
|
|||
{
|
||||
item = it.Next();
|
||||
}
|
||||
firstthing = item;
|
||||
b->Bot->dest = item;
|
||||
bglobal.firstthing = item;
|
||||
dest = item;
|
||||
}
|
||||
}
|
||||
else if (b->Bot->mate && (r < 179 || P_CheckSight(actor, b->Bot->mate)))
|
||||
else if (mate && (r < 179 || P_CheckSight(player->mo, mate)))
|
||||
{
|
||||
b->Bot->dest = b->Bot->mate;
|
||||
dest = mate;
|
||||
}
|
||||
else if ((playeringame[(r&(MAXPLAYERS-1))]) && players[(r&(MAXPLAYERS-1))].mo->health > 0)
|
||||
{
|
||||
b->Bot->dest = players[(r&(MAXPLAYERS-1))].mo;
|
||||
dest = players[(r&(MAXPLAYERS-1))].mo;
|
||||
}
|
||||
}
|
||||
|
||||
if (b->Bot->dest)
|
||||
if (dest)
|
||||
{
|
||||
b->Bot->t_roam = MAXROAM;
|
||||
t_roam = MAXROAM;
|
||||
}
|
||||
}
|
||||
if (b->Bot->dest)
|
||||
if (dest)
|
||||
{ //Bot has a target so roam after it.
|
||||
Roam (actor, cmd);
|
||||
Roam (cmd);
|
||||
}
|
||||
|
||||
} //End of movement main part.
|
||||
|
||||
if (!b->Bot->t_roam && b->Bot->dest)
|
||||
if (!t_roam && dest)
|
||||
{
|
||||
b->Bot->prev = b->Bot->dest;
|
||||
b->Bot->dest = NULL;
|
||||
prev = dest;
|
||||
dest = NULL;
|
||||
}
|
||||
|
||||
if (b->Bot->t_fight<(AFTERTICS/2))
|
||||
actor->flags |= MF_DROPOFF;
|
||||
if (t_fight<(AFTERTICS/2))
|
||||
player->mo->flags |= MF_DROPOFF;
|
||||
|
||||
b->Bot->oldx = actor->x;
|
||||
b->Bot->oldy = actor->y;
|
||||
oldx = player->mo->x;
|
||||
oldy = player->mo->y;
|
||||
}
|
||||
|
||||
//BOT_WhatToGet
|
||||
//
|
||||
//Determines if the bot will roam after an item or not.
|
||||
void FCajunMaster::WhatToGet (AActor *actor, AActor *item)
|
||||
void DBot::WhatToGet (AActor *item)
|
||||
{
|
||||
player_t *b = actor->player;
|
||||
|
||||
if (b == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#define typeis(x) item->IsKindOf (PClass::FindClass (#x))
|
||||
if ((item->renderflags & RF_INVISIBLE) //Under respawn and away.
|
||||
|| item == b->Bot->prev)
|
||||
|| item == prev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -338,7 +328,7 @@ void FCajunMaster::WhatToGet (AActor *actor, AActor *item)
|
|||
// FIXME
|
||||
AWeapon *heldWeapon;
|
||||
|
||||
heldWeapon = static_cast<AWeapon *> (b->mo->FindInventory (item->GetClass()));
|
||||
heldWeapon = static_cast<AWeapon *> (player->mo->FindInventory (item->GetClass()));
|
||||
if (heldWeapon != NULL)
|
||||
{
|
||||
if (!weapgiveammo)
|
||||
|
@ -354,39 +344,38 @@ void FCajunMaster::WhatToGet (AActor *actor, AActor *item)
|
|||
{
|
||||
AAmmo *ammo = static_cast<AAmmo *> (item);
|
||||
const PClass *parent = ammo->GetParentAmmo ();
|
||||
AInventory *holdingammo = b->mo->FindInventory (parent);
|
||||
AInventory *holdingammo = player->mo->FindInventory (parent);
|
||||
|
||||
if (holdingammo != NULL && holdingammo->Amount >= holdingammo->MaxAmount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ((typeis (Megasphere) || typeis (Soulsphere) || typeis (HealthBonus)) && actor->health >= deh.MaxSoulsphere)
|
||||
else if ((typeis (Megasphere) || typeis (Soulsphere) || typeis (HealthBonus)) && player->mo->health >= deh.MaxSoulsphere)
|
||||
return;
|
||||
else if (item->IsKindOf (RUNTIME_CLASS(AHealth)) && actor->health >= deh.MaxHealth /*MAXHEALTH*/)
|
||||
else if (item->IsKindOf (RUNTIME_CLASS(AHealth)) && player->mo->health >= deh.MaxHealth /*MAXHEALTH*/)
|
||||
return;
|
||||
|
||||
if ((b->Bot->dest == NULL ||
|
||||
!(b->Bot->dest->flags & MF_SPECIAL)/* ||
|
||||
!Reachable (actor, b->dest)*/)/* &&
|
||||
Reachable (actor, item)*/) // Calling Reachable slows this down tremendously
|
||||
if ((dest == NULL ||
|
||||
!(dest->flags & MF_SPECIAL)/* ||
|
||||
!Reachable (dest)*/)/* &&
|
||||
Reachable (item)*/) // Calling Reachable slows this down tremendously
|
||||
{
|
||||
b->Bot->prev = b->Bot->dest;
|
||||
b->Bot->dest = item;
|
||||
b->Bot->t_roam = MAXROAM;
|
||||
prev = dest;
|
||||
dest = item;
|
||||
t_roam = MAXROAM;
|
||||
}
|
||||
}
|
||||
|
||||
void FCajunMaster::Set_enemy (AActor *actor)
|
||||
void DBot::Set_enemy ()
|
||||
{
|
||||
AActor *oldenemy;
|
||||
AActor **enemy = &actor->player->Bot->enemy;
|
||||
|
||||
if (*enemy
|
||||
&& (*enemy)->health > 0
|
||||
&& P_CheckSight (actor, *enemy))
|
||||
if (enemy
|
||||
&& enemy->health > 0
|
||||
&& P_CheckSight (player->mo, enemy))
|
||||
{
|
||||
oldenemy = *enemy;
|
||||
oldenemy = enemy;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -395,15 +384,14 @@ void FCajunMaster::Set_enemy (AActor *actor)
|
|||
|
||||
// [RH] Don't even bother looking for a different enemy if this is not deathmatch
|
||||
// and we already have an existing enemy.
|
||||
if (deathmatch || !*enemy)
|
||||
if (deathmatch || !enemy)
|
||||
{
|
||||
actor->player->Bot->allround = !!*enemy;
|
||||
*enemy = NULL;
|
||||
*enemy = Find_enemy(actor);
|
||||
if (!*enemy)
|
||||
*enemy = oldenemy; //Try go for last (it will be NULL if there wasn't anyone)
|
||||
allround = !!enemy;
|
||||
enemy = Find_enemy();
|
||||
if (!enemy)
|
||||
enemy = oldenemy; //Try go for last (it will be NULL if there wasn't anyone)
|
||||
}
|
||||
//Verify that that enemy is really something alive that bot can kill.
|
||||
if (*enemy && (((*enemy)->health < 0 || !((*enemy)->flags&MF_SHOOTABLE)) || actor->IsFriend(*enemy)))
|
||||
*enemy = NULL;
|
||||
if (enemy && ((enemy->health < 0 || !(enemy->flags&MF_SHOOTABLE)) || player->mo->IsFriend(enemy)))
|
||||
enemy = NULL;
|
||||
}
|
||||
|
|
|
@ -3259,7 +3259,7 @@ void AActor::Tick ()
|
|||
else if (flags & MF_SPECIAL)
|
||||
{ //Item pickup time
|
||||
//clock (BotWTG);
|
||||
bglobal.WhatToGet (players[i].mo, this);
|
||||
players[i].Bot->WhatToGet (this);
|
||||
//unclock (BotWTG);
|
||||
BotWTG++;
|
||||
}
|
||||
|
@ -3267,7 +3267,7 @@ void AActor::Tick ()
|
|||
{
|
||||
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))
|
||||
if (target != players[i].mo && players[i].Bot->Check_LOS (this, ANGLE_90))
|
||||
players[i].Bot->missile = this;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue