in doom_py/src/vizdoom/src/b_think.cpp [77:308]
void DBot::ThinkForMove (ticcmd_t *cmd)
{
fixed_t dist;
bool stuck;
int r;
stuck = false;
dist = dest ? player->mo->AproxDistance(dest) : 0;
if (missile &&
((!missile->velx || !missile->vely) || !Check_LOS(missile, SHOOTFOV*3/2)))
{
sleft = !sleft;
missile = NULL; //Probably ended its travel.
}
if (player->mo->pitch > 0)
player->mo->pitch -= 80;
else if (player->mo->pitch <= -60)
player->mo->pitch += 80;
//HOW TO MOVE:
if (missile && (player->mo->AproxDistance(missile)<AVOID_DIST)) //try avoid missile got from P_Mobj.c thinking part.
{
Pitch (missile);
angle = player->mo->AngleTo(missile);
cmd->ucmd.sidemove = sleft ? -SIDERUN : SIDERUN;
cmd->ucmd.forwardmove = -FORWARDRUN; //Back IS best.
if ((player->mo->AproxDistance(oldx, oldy)<50000)
&& t_strafe<=0)
{
t_strafe = 5;
sleft = !sleft;
}
//If able to see enemy while avoiding missile, still fire at enemy.
if (enemy && Check_LOS (enemy, SHOOTFOV))
Dofire (cmd); //Order bot to fire current weapon
}
else if (enemy && P_CheckSight (player->mo, enemy, 0)) //Fight!
{
Pitch (enemy);
//Check if it's more important to get an item than fight.
if (dest && (dest->flags&MF_SPECIAL)) //Must be an item, that is close enough.
{
#define is(x) dest->IsKindOf (PClass::FindClass (#x))
if (
(
(player->mo->health < skill.isp &&
(is (Medikit) ||
is (Stimpack) ||
is (Soulsphere) ||
is (Megasphere) ||
is (CrystalVial)
)
) || (
is (Invulnerability) ||
is (Invisibility) ||
is (Megasphere)
) ||
dist < (GETINCOMBAT/4) ||
(player->ReadyWeapon == NULL || player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON)
)
&& (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.
}
}
dest = NULL; //To let bot turn right
if (player->ReadyWeapon != NULL && !(player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))
player->mo->flags &= ~MF_DROPOFF; //Don't jump off any ledges when fighting.
if (!(enemy->flags3 & MF3_ISMONSTER))
t_fight = AFTERTICS;
if (t_strafe <= 0 &&
(player->mo->AproxDistance(oldx, oldy)<50000
|| ((pr_botmove()%30)==10))
)
{
stuck = true;
t_strafe = 5;
sleft = !sleft;
}
angle = player->mo->AngleTo(enemy);
if (player->ReadyWeapon == NULL ||
player->mo->AproxDistance(enemy) >
player->ReadyWeapon->MoveCombatDist)
{
// If a monster, use lower speed (just for cooler apperance while strafing down doomed monster)
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 = (enemy->flags3 & MF3_ISMONSTER) ? -FORWARDWALK : -FORWARDRUN;
}
//Strafing.
if (enemy->flags3 & MF3_ISMONSTER) //It's just a monster so take it down cool.
{
cmd->ucmd.sidemove = sleft ? -SIDEWALK : SIDEWALK;
}
else
{
cmd->ucmd.sidemove = sleft ? -SIDERUN : SIDERUN;
}
Dofire (cmd); //Order bot to fire current weapon
}
else if (mate && !enemy && (!dest || dest==mate)) //Follow mate move.
{
fixed_t matedist;
Pitch (mate);
if (!Reachable (mate))
{
if (mate == dest && pr_botmove.Random() < 32)
{ // [RH] If the mate is the dest, pick a new dest sometimes
dest = NULL;
}
goto roam;
}
angle = player->mo->AngleTo(mate);
matedist = player->mo->AproxDistance(mate);
if (matedist > (FRIEND_DIST*2))
cmd->ucmd.forwardmove = FORWARDRUN;
else if (matedist > FRIEND_DIST)
cmd->ucmd.forwardmove = FORWARDWALK; //Walk, when starting to get close.
else if (matedist < FRIEND_DIST-(FRIEND_DIST/3)) //Got too close, so move away.
cmd->ucmd.forwardmove = -FORWARDWALK;
}
else //Roam after something.
{
first_shot = true;
/////
roam:
/////
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 (dest && !(dest->flags&MF_SPECIAL) && dest->health < 0)
{ //Roaming after something dead.
dest = NULL;
}
if (dest == NULL)
{
if (t_fight && enemy) //Enemy/bot has jumped around corner. So what to do?
{
if (enemy->player)
{
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 = player->mo->AngleTo(enemy);
} //Just a monster, so kill it.
else
dest = enemy;
//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, bglobal.firstthing);
AInventory *item = it.Next();
if (item != NULL || (item = it.Next()) != NULL)
{
r &= 63; // Only scan up to 64 entries at a time
while (r)
{
--r;
item = it.Next();
}
if (item == NULL)
{
item = it.Next();
}
bglobal.firstthing = item;
dest = item;
}
}
else if (mate && (r < 179 || P_CheckSight(player->mo, mate)))
{
dest = mate;
}
else if ((playeringame[(r&(MAXPLAYERS-1))]) && players[(r&(MAXPLAYERS-1))].mo->health > 0)
{
dest = players[(r&(MAXPLAYERS-1))].mo;
}
}
if (dest)
{
t_roam = MAXROAM;
}
}
if (dest)
{ //Bot has a target so roam after it.
Roam (cmd);
}
} //End of movement main part.
if (!t_roam && dest)
{
prev = dest;
dest = NULL;
}
if (t_fight<(AFTERTICS/2))
player->mo->flags |= MF_DROPOFF;
oldx = player->mo->X();
oldy = player->mo->Y();
}