Somewhere in BotSetConditions in bot.cpp:
Code:
// Check if throwing a Grenade is a good thing to do...
if ((pBot->f_grenade_check_time < gpGlobals->time) && (!bUsingGrenade) && (!g_bIgnoreEnemies)
&& (!pBot->bIsReloading) && (pBot->current_weapon.iId != CS_WEAPON_INSWITCH)
&& (!g_b_cv_jasonmode) && (g_i_botthink_index == g_iFrameCounter)) // KWo - 25.06.2006
{
// Check again in some seconds
pBot->f_grenade_check_time = gpGlobals->time + g_f_cv_timer_grenade; // KWo - 06.04.2006
int weapons = pBot->pEdict->v.weapons; // KWo - 21.03.2006
bool bWantThrowFlashbang = FALSE; // KWo - 21.03.2006
if ((pBot->current_weapon.iId != CS_WEAPON_HEGRENADE) && (weapons & (1 << CS_WEAPON_FLASHBANG))) // KWo - 20.06.2006
bWantThrowFlashbang = BotCheckCorridor(pBot); // KWo - 21.03.2006
if (bWantThrowFlashbang) // KWo - 21.03.2006
{
bool bThrowGrenade = TRUE;
Vector vec_mov_dir;
Vector v_dest;
Vector vecSource;
// UTIL_ServerPrint ("[Debug] Bot %s wants to throw a flashbang .\n", pBot->name);
if ((pBot->prev_wpt_index[0]<0) || (pBot->prev_wpt_index[0] >= g_iNumWaypoints))
bThrowGrenade = FALSE;
if (bThrowGrenade)
{
vec_mov_dir = (pBot->wpt_origin - paths[pBot->prev_wpt_index[0]]->origin).Normalize();
vec_mov_dir = vec_mov_dir * 500;
v_dest = pBot->wpt_origin + vec_mov_dir;
if (NumTeammatesNearPos (pBot, v_dest, 256) > 0)
{
bThrowGrenade = FALSE;
}
else
{
pBot->vecThrow = v_dest;
}
}
if (bThrowGrenade)
{
pBot->iStates |= STATE_THROWFLASHBANG;
bottask_t TempTask = {NULL, NULL, TASK_THROWFLASHBANG, TASKPRI_THROWGRENADE, -1, gpGlobals->time + 3.0, FALSE};
BotPushTask (pBot, &TempTask);
pBot->f_grenade_check_time = gpGlobals->time + 3.0;
}
else
pBot->iStates &= ~STATE_THROWFLASHBANG;
}
else if (!FNullEnt (pBot->pLastEnemy))
{
if (IsAlive (pBot->pLastEnemy)) // KWo - 06.08.2006
{
// Check if we have Grenades to throw
int iGrenadeType = BotCheckGrenades (pBot);
// If we don't have grenades no need to check
// it this round again -
// KWo - wrong - how about CSDM? ;)
if ((iGrenadeType = CS_WEAPON_HEGRENADE) || (iGrenadeType = CS_WEAPON_SMOKEGRENADE)) // KWo - 21.03.2006
{
edict_t *pEnemy = pBot->pLastEnemy;
Vector v_distance = pBot->vecLastEnemyOrigin - pEdict->v.origin;
f_distance = v_distance.Length ();
// Too high to throw ?
if (pEnemy->v.origin.z > pEdict->v.origin.z + 500.0)
f_distance = 9999;
// Enemy within a good Throw distance ?
if ((f_distance > 400) && (f_distance < 1600))
{
Vector v_enemypos;
Vector vecSource;
Vector v_dest;
TraceResult tr;
bool bThrowGrenade = TRUE;
Vector vecPredict;
float fRandom = RANDOM_FLOAT(0.0,100.0);
if ((weapons & (1 << CS_WEAPON_HEGRENADE)) && (weapons & (1 << CS_WEAPON_SMOKEGRENADE)))
{
if ((fRandom > 20) || (pBot->current_weapon.iId == CS_WEAPON_HEGRENADE)) // KWo - 20.06.2006
iGrenadeType = CS_WEAPON_HEGRENADE;
else
iGrenadeType = CS_WEAPON_SMOKEGRENADE;
}
if ((weapons & (1 << CS_WEAPON_HEGRENADE)) && !(weapons & (1 << CS_WEAPON_SMOKEGRENADE)))
iGrenadeType = CS_WEAPON_HEGRENADE;
if (!(weapons & (1 << CS_WEAPON_HEGRENADE)) && (weapons & (1 << CS_WEAPON_SMOKEGRENADE)))
iGrenadeType = CS_WEAPON_SMOKEGRENADE;
// Care about different Grenades
switch (iGrenadeType)
{
case CS_WEAPON_HEGRENADE:
if (NumTeammatesNearPos (pBot, pBot->pLastEnemy->v.origin, 256) > 0)
bThrowGrenade = FALSE;
else
{
// vecPredict = pBot->pLastEnemy->v.velocity * 0.5;
vecPredict = pBot->pLastEnemy->v.velocity * f_distance / 400.0; // KWo - 18.06.2006
vecPredict.z = 0.0;
vecPredict = vecPredict + pBot->pLastEnemy->v.origin;
bThrowGrenade = TRUE;
pBot->vecThrow = vecPredict;
vecSource = VecCheckThrow (pBot, GetGunPosition (pEdict), pBot->vecThrow, 1.0);
if (vecSource == g_vecZero)
vecSource = VecCheckToss (pEdict, GetGunPosition (pEdict), pBot->vecThrow);
if (vecSource == g_vecZero)
{
// UTIL_ServerPrint("[Debug] Bot %s failed with checking throw for he nades.\n", pBot->name);
bThrowGrenade = FALSE;
}
}
// Start throwing ?
if (bThrowGrenade)
pBot->iStates |= STATE_THROWHEGREN;
else
pBot->iStates &= ~STATE_THROWHEGREN;
break;
case CS_WEAPON_SMOKEGRENADE:
// Check if Enemy is directly facing us
// Don't throw if that's the case !!
if (bThrowGrenade && !FNullEnt (pBot->pBotEnemy))
{
if (GetShootingConeDeviation (pBot->pBotEnemy, &pEdict->v.origin) >= 0.9)
bThrowGrenade = FALSE;
}
// KWo - 25.06.2006 - rewritten a bit
vecSource = pBot->vecLastEnemyOrigin;
vecSource = vecSource - pEdict->v.velocity;
// Predict where the enemy is in 0.5 secs
if (!FNullEnt (pBot->pBotEnemy))
vecSource = vecSource + pBot->pBotEnemy->v.velocity * 0.5;
pBot->vecThrow = vecSource;
pBot->vecGrenade = VecCheckThrow (pBot, GetGunPosition (pEdict), v_dest, 1.0);
if (pBot->vecGrenade == g_vecZero)
pBot->vecGrenade = VecCheckToss (pEdict, GetGunPosition (pEdict), v_dest);
if (pBot->vecGrenade == g_vecZero)
bThrowGrenade = FALSE;
if (bThrowGrenade)
pBot->iStates |= STATE_THROWSMOKEGREN;
else
pBot->iStates &= ~STATE_THROWSMOKEGREN;
break;
}
bottask_t TempTask = {NULL, NULL, TASK_THROWHEGRENADE, TASKPRI_THROWGRENADE, -1, gpGlobals->time + 3.0, FALSE}; // KWo - 24.02.2006 TIME_GRENPRIME
if (bThrowGrenade) // KWo - 24.02.2006
{
pBot->f_grenade_check_time = gpGlobals->time + 3.0;
}
if (pBot->iStates & STATE_THROWHEGREN)
BotPushTask (pBot, &TempTask);
else if (pBot->iStates & STATE_THROWSMOKEGREN)
{
TempTask.iTask = TASK_THROWSMOKEGRENADE;
BotPushTask (pBot, &TempTask);
}
}
else
{
pBot->iStates &= ~STATE_THROWHEGREN;
pBot->iStates &= ~STATE_THROWFLASHBANG;
pBot->iStates &= ~STATE_THROWSMOKEGREN;
}
}
else
{
pBot->iStates &= ~STATE_THROWHEGREN;
pBot->iStates &= ~STATE_THROWFLASHBANG;
pBot->iStates &= ~STATE_THROWSMOKEGREN;
}
}
}
}
else if (!bUsingGrenade) // KWo - 22.03.2006
{
pBot->iStates &= ~STATE_THROWHEGREN;
pBot->iStates &= ~STATE_THROWFLASHBANG;
pBot->iStates &= ~STATE_THROWSMOKEGREN;
}
This part is to take the decision about throwing, the rest is in the TASK_THROWHEGRENADE (in BotThinkFunction in bot.cpp).
[EDIT]
Something for Nova - Bold could be done better for 'code' part
[/EDIT]