fixed bot's don't shoot thru walls
added some knife-mode movement some codestyle fixes
This commit is contained in:
parent
c850e45ed2
commit
04365ab202
5 changed files with 342 additions and 399 deletions
|
|
@ -1110,6 +1110,7 @@ private:
|
||||||
void ResetCollideState (void);
|
void ResetCollideState (void);
|
||||||
void IgnoreCollisionShortly (void);
|
void IgnoreCollisionShortly (void);
|
||||||
void SetConditions (void);
|
void SetConditions (void);
|
||||||
|
void SetConditionsOverride (void);
|
||||||
void UpdateEmotions (void);
|
void UpdateEmotions (void);
|
||||||
void SetStrafeSpeed (const Vector &moveDir, float strafeSpeed);
|
void SetStrafeSpeed (const Vector &moveDir, float strafeSpeed);
|
||||||
void StartGame (void);
|
void StartGame (void);
|
||||||
|
|
@ -1301,6 +1302,7 @@ public:
|
||||||
/// the things that can be executed while skipping frames
|
/// the things that can be executed while skipping frames
|
||||||
void ThinkDelayed (void);
|
void ThinkDelayed (void);
|
||||||
|
|
||||||
|
void DisplayDebugOverlay (void);
|
||||||
void NewRound (void);
|
void NewRound (void);
|
||||||
void EquipInBuyzone (int buyCount);
|
void EquipInBuyzone (int buyCount);
|
||||||
void PushMessageQueue (int message);
|
void PushMessageQueue (int message);
|
||||||
|
|
|
||||||
|
|
@ -1786,6 +1786,42 @@ void Bot::UpdateEmotions (void)
|
||||||
m_nextEmotionUpdate = GetWorldTime () + 1.0f;
|
m_nextEmotionUpdate = GetWorldTime () + 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bot::SetConditionsOverride (void)
|
||||||
|
{
|
||||||
|
if (m_currentWeapon != WEAPON_KNIFE && m_difficulty > 3 && ((m_aimFlags & AIM_ENEMY) || (m_states & (STATE_SEEING_ENEMY | STATE_SUSPECT_ENEMY)) || (GetTaskId () == TASK_SEEKCOVER && (m_isReloading || m_isVIP))) && !yb_jasonmode.GetBool () && GetTaskId () != TASK_CAMP && !IsOnLadder ())
|
||||||
|
{
|
||||||
|
m_moveToGoal = false; // don't move to goal
|
||||||
|
m_navTimeset = GetWorldTime ();
|
||||||
|
|
||||||
|
if (IsValidPlayer (m_enemy))
|
||||||
|
CombatFight ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we need to escape from bomb
|
||||||
|
if ((g_mapType & MAP_DE) && g_bombPlanted && m_notKilled && GetTaskId () != TASK_ESCAPEFROMBOMB && GetTaskId () != TASK_CAMP && OutOfBombTimer ())
|
||||||
|
{
|
||||||
|
TaskComplete (); // complete current task
|
||||||
|
|
||||||
|
// then start escape from bomb immidiate
|
||||||
|
PushTask (TASK_ESCAPEFROMBOMB, TASKPRI_ESCAPEFROMBOMB, -1, 0.0f, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// special handling, if we have a knife in our hands
|
||||||
|
if (m_currentWeapon == WEAPON_KNIFE && IsValidPlayer (m_enemy) && (GetTaskId () != TASK_MOVETOPOSITION || GetTask ()->desire != TASKPRI_HIDE))
|
||||||
|
{
|
||||||
|
if ((pev->origin - m_enemy->v.origin).GetLength2D () > 100.0f && (m_states & STATE_SEEING_ENEMY))
|
||||||
|
{
|
||||||
|
int nearestToEnemyPoint = waypoints.FindNearest (m_enemy->v.origin);
|
||||||
|
|
||||||
|
if (nearestToEnemyPoint != -1 && nearestToEnemyPoint != m_currentWaypointIndex && fabsf (waypoints.GetPath (nearestToEnemyPoint)->origin.z - m_enemy->v.origin.z) < 16.0f)
|
||||||
|
{
|
||||||
|
PushTask (TASK_MOVETOPOSITION, TASKPRI_HIDE, nearestToEnemyPoint, GetWorldTime () + Random.Float (5.0f, 10.0f), true);
|
||||||
|
m_enemy = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Bot::SetConditions (void)
|
void Bot::SetConditions (void)
|
||||||
{
|
{
|
||||||
// this function carried out each frame. does all of the sensing, calculates emotions and finally sets the desired
|
// this function carried out each frame. does all of the sensing, calculates emotions and finally sets the desired
|
||||||
|
|
@ -1988,7 +2024,7 @@ void Bot::ApplyTaskFilters (void)
|
||||||
ratio = timeHeard * 0.1f;
|
ratio = timeHeard * 0.1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_bombPlanted || m_isStuck)
|
if (g_bombPlanted || m_isStuck || m_currentWeapon == WEAPON_KNIFE)
|
||||||
ratio /= 3.0f; // reduce the seek cover desire if bomb is planted
|
ratio /= 3.0f; // reduce the seek cover desire if bomb is planted
|
||||||
else if (m_isVIP || m_isReloading)
|
else if (m_isVIP || m_isReloading)
|
||||||
ratio *= 3.0f; // triple the seek cover desire if bot is VIP or reloading
|
ratio *= 3.0f; // triple the seek cover desire if bot is VIP or reloading
|
||||||
|
|
@ -2194,14 +2230,12 @@ bool Bot::EnemyIsThreat (void)
|
||||||
if (IsEntityNull (m_enemy) || GetTaskId () == TASK_SEEKCOVER)
|
if (IsEntityNull (m_enemy) || GetTaskId () == TASK_SEEKCOVER)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
float distance = (m_enemy->v.origin - pev->origin).GetLength ();
|
|
||||||
|
|
||||||
// if bot is camping, he should be firing anyway and not leaving his position
|
// if bot is camping, he should be firing anyway and not leaving his position
|
||||||
if (GetTaskId () == TASK_CAMP)
|
if (GetTaskId () == TASK_CAMP)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// if enemy is near or facing us directly
|
// if enemy is near or facing us directly
|
||||||
if (distance < 256.0f || IsInViewCone (m_enemy->v.origin))
|
if ((m_enemy->v.origin - pev->origin).GetLength () < 256.0f || IsInViewCone (m_enemy->v.origin))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -2241,7 +2275,7 @@ bool Bot::ReactOnEnemy (void)
|
||||||
bool Bot::LastEnemyShootable (void)
|
bool Bot::LastEnemyShootable (void)
|
||||||
{
|
{
|
||||||
// don't allow shooting through walls
|
// don't allow shooting through walls
|
||||||
if (!(m_aimFlags & AIM_LAST_ENEMY) || !m_lastEnemyOrigin.IsZero () || IsEntityNull (m_lastEnemy))
|
if (!(m_aimFlags & AIM_LAST_ENEMY) || m_lastEnemyOrigin.IsZero () || IsEntityNull (m_lastEnemy))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return GetShootingConeDeviation (GetEntity (), &m_lastEnemyOrigin) >= 0.90f && IsShootableThruObstacle (m_lastEnemyOrigin);
|
return GetShootingConeDeviation (GetEntity (), &m_lastEnemyOrigin) >= 0.90f && IsShootableThruObstacle (m_lastEnemyOrigin);
|
||||||
|
|
@ -2554,6 +2588,7 @@ void Bot::CheckRadioCommands (void)
|
||||||
if (curDist < nearestDistance)
|
if (curDist < nearestDistance)
|
||||||
{
|
{
|
||||||
nearestDistance = curDist;
|
nearestDistance = curDist;
|
||||||
|
|
||||||
m_lastEnemy = enemy;
|
m_lastEnemy = enemy;
|
||||||
m_lastEnemyOrigin = enemy->v.origin;
|
m_lastEnemyOrigin = enemy->v.origin;
|
||||||
}
|
}
|
||||||
|
|
@ -3049,8 +3084,11 @@ void Bot::RunTask_Normal (void)
|
||||||
m_prevGoalIndex = -1;
|
m_prevGoalIndex = -1;
|
||||||
|
|
||||||
// spray logo sometimes if allowed to do so
|
// spray logo sometimes if allowed to do so
|
||||||
if (m_timeLogoSpray < GetWorldTime () && yb_spraypaints.GetBool () && Random.Long (1, 100) < 60 && m_moveSpeed > GetWalkSpeed () && IsEntityNull (m_pickupItem))
|
if (!g_bombPlanted && m_timeLogoSpray < GetWorldTime () && yb_spraypaints.GetBool () && Random.Long (1, 100) < 60 && m_moveSpeed > GetWalkSpeed () && IsEntityNull (m_pickupItem))
|
||||||
PushTask (TASK_SPRAY, TASKPRI_SPRAYLOGO, -1, GetWorldTime () + 1.0f, false);
|
{
|
||||||
|
if (!((g_mapType & MAP_DE) && g_bombPlanted && m_team == TEAM_CF))
|
||||||
|
PushTask (TASK_SPRAY, TASKPRI_SPRAYLOGO, -1, GetWorldTime () + 1.0f, false);
|
||||||
|
}
|
||||||
|
|
||||||
// reached waypoint is a camp waypoint
|
// reached waypoint is a camp waypoint
|
||||||
if ((m_currentPath->flags & FLAG_CAMP) && !yb_csdm_mode.GetBool () && yb_camping_allowed.GetBool ())
|
if ((m_currentPath->flags & FLAG_CAMP) && !yb_csdm_mode.GetBool () && yb_camping_allowed.GetBool ())
|
||||||
|
|
@ -3108,8 +3146,8 @@ void Bot::RunTask_Normal (void)
|
||||||
m_moveToGoal = false;
|
m_moveToGoal = false;
|
||||||
m_checkTerrain = false;
|
m_checkTerrain = false;
|
||||||
|
|
||||||
m_moveSpeed = 0;
|
m_moveSpeed = 0.0f;
|
||||||
m_strafeSpeed = 0;
|
m_strafeSpeed = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3182,7 +3220,7 @@ void Bot::RunTask_Normal (void)
|
||||||
// no more nodes to follow - search new ones (or we have a bomb)
|
// no more nodes to follow - search new ones (or we have a bomb)
|
||||||
else if (!GoalIsValid ())
|
else if (!GoalIsValid ())
|
||||||
{
|
{
|
||||||
m_moveSpeed = pev->maxspeed;
|
m_moveSpeed = 0.0f;
|
||||||
DeleteSearchNodes ();
|
DeleteSearchNodes ();
|
||||||
|
|
||||||
int destIndex = -1;
|
int destIndex = -1;
|
||||||
|
|
@ -3433,6 +3471,9 @@ void Bot::RunTask_Attack (void)
|
||||||
DeleteSearchNodes ();
|
DeleteSearchNodes ();
|
||||||
}
|
}
|
||||||
CombatFight ();
|
CombatFight ();
|
||||||
|
|
||||||
|
if (m_currentWeapon == WEAPON_KNIFE && !m_lastEnemyOrigin.IsZero ())
|
||||||
|
m_destOrigin = m_lastEnemyOrigin;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -3729,8 +3770,8 @@ void Bot::RunTask_PlantBomb (void)
|
||||||
else
|
else
|
||||||
pev->button |= IN_ATTACK;
|
pev->button |= IN_ATTACK;
|
||||||
|
|
||||||
m_moveSpeed = 0;
|
m_moveSpeed = 0.0f;
|
||||||
m_strafeSpeed = 0;
|
m_strafeSpeed = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // done with planting
|
else // done with planting
|
||||||
|
|
@ -4483,8 +4524,8 @@ void Bot::RunTask_PickupItem ()
|
||||||
m_moveToGoal = false;
|
m_moveToGoal = false;
|
||||||
m_checkTerrain = false;
|
m_checkTerrain = false;
|
||||||
|
|
||||||
m_moveSpeed = 0;
|
m_moveSpeed = 0.0f;
|
||||||
m_strafeSpeed = 0;
|
m_strafeSpeed = 0.0f;
|
||||||
|
|
||||||
PushTask (TASK_DEFUSEBOMB, TASKPRI_DEFUSEBOMB, -1, 0.0f, false);
|
PushTask (TASK_DEFUSEBOMB, TASKPRI_DEFUSEBOMB, -1, 0.0f, false);
|
||||||
}
|
}
|
||||||
|
|
@ -4846,23 +4887,7 @@ void Bot::BotAI (void)
|
||||||
m_moveAngles.ClampAngles ();
|
m_moveAngles.ClampAngles ();
|
||||||
m_moveAngles.x *= -1.0f; // invert for engine
|
m_moveAngles.x *= -1.0f; // invert for engine
|
||||||
|
|
||||||
if (m_difficulty > 3 && ((m_aimFlags & AIM_ENEMY) || (m_states & (STATE_SEEING_ENEMY | STATE_SUSPECT_ENEMY)) || (GetTaskId () == TASK_SEEKCOVER && (m_isReloading || m_isVIP))) && !yb_jasonmode.GetBool () && GetTaskId () != TASK_CAMP && !IsOnLadder ())
|
SetConditionsOverride ();
|
||||||
{
|
|
||||||
m_moveToGoal = false; // don't move to goal
|
|
||||||
m_navTimeset = GetWorldTime ();
|
|
||||||
|
|
||||||
if (IsValidPlayer (m_enemy))
|
|
||||||
CombatFight ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we need to escape from bomb
|
|
||||||
if ((g_mapType & MAP_DE) && g_bombPlanted && m_notKilled && GetTaskId () != TASK_ESCAPEFROMBOMB && GetTaskId () != TASK_CAMP && OutOfBombTimer ())
|
|
||||||
{
|
|
||||||
TaskComplete (); // complete current task
|
|
||||||
|
|
||||||
// then start escape from bomb immidiate
|
|
||||||
PushTask (TASK_ESCAPEFROMBOMB, TASKPRI_ESCAPEFROMBOMB, -1, 0.0f, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// allowed to move to a destination position?
|
// allowed to move to a destination position?
|
||||||
if (m_moveToGoal)
|
if (m_moveToGoal)
|
||||||
|
|
@ -4946,257 +4971,10 @@ void Bot::BotAI (void)
|
||||||
pev->button |= IN_MOVELEFT;
|
pev->button |= IN_MOVELEFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// display some debugging thingy to host entity
|
||||||
if (!IsEntityNull (g_hostEntity) && yb_debug.GetInt () >= 1)
|
if (!IsEntityNull (g_hostEntity) && yb_debug.GetInt () >= 1)
|
||||||
{
|
DisplayDebugOverlay ();
|
||||||
bool displayDebugOverlay = false;
|
|
||||||
|
|
||||||
if (g_hostEntity->v.iuser2 == IndexOfEntity (GetEntity ()))
|
|
||||||
displayDebugOverlay = true;
|
|
||||||
|
|
||||||
if (!displayDebugOverlay && yb_debug.GetInt () >= 2)
|
|
||||||
{
|
|
||||||
Bot *nearest = NULL;
|
|
||||||
|
|
||||||
if (FindNearestPlayer (reinterpret_cast <void **> (&nearest), g_hostEntity, 128.0f, true, true, true, true) && nearest == this)
|
|
||||||
displayDebugOverlay = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (displayDebugOverlay)
|
|
||||||
{
|
|
||||||
static float timeDebugUpdate = 0.0f;
|
|
||||||
static int index, goal, taskID;
|
|
||||||
|
|
||||||
if (!m_tasks.IsEmpty ())
|
|
||||||
{
|
|
||||||
if (taskID != GetTaskId () || index != m_currentWaypointIndex || goal != GetTask ()->data || timeDebugUpdate < GetWorldTime ())
|
|
||||||
{
|
|
||||||
taskID = GetTaskId ();
|
|
||||||
index = m_currentWaypointIndex;
|
|
||||||
goal = GetTask ()->data;
|
|
||||||
|
|
||||||
char taskName [80];
|
|
||||||
memset (taskName, 0, sizeof (taskName));
|
|
||||||
|
|
||||||
switch (taskID)
|
|
||||||
{
|
|
||||||
case TASK_NORMAL:
|
|
||||||
sprintf (taskName, "Normal");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_PAUSE:
|
|
||||||
sprintf (taskName, "Pause");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_MOVETOPOSITION:
|
|
||||||
sprintf (taskName, "MoveToPosition");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_FOLLOWUSER:
|
|
||||||
sprintf (taskName, "FollowUser");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_WAITFORGO:
|
|
||||||
sprintf (taskName, "WaitForGo");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_PICKUPITEM:
|
|
||||||
sprintf (taskName, "PickupItem");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_CAMP:
|
|
||||||
sprintf (taskName, "Camp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_PLANTBOMB:
|
|
||||||
sprintf (taskName, "PlantBomb");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_DEFUSEBOMB:
|
|
||||||
sprintf (taskName, "DefuseBomb");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_ATTACK:
|
|
||||||
sprintf (taskName, "AttackEnemy");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_HUNTENEMY:
|
|
||||||
sprintf (taskName, "HuntEnemy");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_SEEKCOVER:
|
|
||||||
sprintf (taskName, "SeekCover");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_THROWHEGRENADE:
|
|
||||||
sprintf (taskName, "ThrowExpGrenade");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_THROWFLASHBANG:
|
|
||||||
sprintf (taskName, "ThrowFlashGrenade");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_THROWSMOKE:
|
|
||||||
sprintf (taskName, "ThrowSmokeGrenade");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_DOUBLEJUMP:
|
|
||||||
sprintf (taskName, "PerformDoubleJump");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_ESCAPEFROMBOMB:
|
|
||||||
sprintf (taskName, "EscapeFromBomb");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_SHOOTBREAKABLE:
|
|
||||||
sprintf (taskName, "ShootBreakable");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_HIDE:
|
|
||||||
sprintf (taskName, "Hide");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_BLINDED:
|
|
||||||
sprintf (taskName, "Blinded");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TASK_SPRAY:
|
|
||||||
sprintf (taskName, "SprayLogo");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
char enemyName[80], weaponName[80], aimFlags[64], botType[32];
|
|
||||||
|
|
||||||
if (!IsEntityNull (m_enemy))
|
|
||||||
strncpy (enemyName, STRING (m_enemy->v.netname), SIZEOF_CHAR (enemyName));
|
|
||||||
else if (!IsEntityNull (m_lastEnemy))
|
|
||||||
{
|
|
||||||
strcpy (enemyName, " (L)");
|
|
||||||
strncat (enemyName, STRING (m_lastEnemy->v.netname), SIZEOF_CHAR (enemyName));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
strcpy (enemyName, " (null)");
|
|
||||||
|
|
||||||
char pickupName[80];
|
|
||||||
memset (pickupName, 0, sizeof (pickupName));
|
|
||||||
|
|
||||||
if (!IsEntityNull (m_pickupItem))
|
|
||||||
strncpy (pickupName, STRING (m_pickupItem->v.classname), SIZEOF_CHAR (pickupName));
|
|
||||||
else
|
|
||||||
strcpy (pickupName, " (null)");
|
|
||||||
|
|
||||||
WeaponSelect *selectTab = &g_weaponSelect[0];
|
|
||||||
char weaponCount = 0;
|
|
||||||
|
|
||||||
while (m_currentWeapon != selectTab->id && weaponCount < NUM_WEAPONS)
|
|
||||||
{
|
|
||||||
selectTab++;
|
|
||||||
weaponCount++;
|
|
||||||
}
|
|
||||||
memset (aimFlags, 0, sizeof (aimFlags));
|
|
||||||
|
|
||||||
// set the aim flags
|
|
||||||
sprintf (aimFlags, "%s%s%s%s%s%s%s%s",
|
|
||||||
(m_aimFlags & AIM_NAVPOINT) ? " NavPoint" : "",
|
|
||||||
(m_aimFlags & AIM_CAMP) ? " CampPoint" : "",
|
|
||||||
(m_aimFlags & AIM_PREDICT_PATH) ? " PredictPath" : "",
|
|
||||||
(m_aimFlags & AIM_LAST_ENEMY) ? " LastEnemy" : "",
|
|
||||||
(m_aimFlags & AIM_ENTITY) ? " Entity" : "",
|
|
||||||
(m_aimFlags & AIM_ENEMY) ? " Enemy" : "",
|
|
||||||
(m_aimFlags & AIM_GRENADE) ? " Grenade" : "",
|
|
||||||
(m_aimFlags & AIM_OVERRIDE) ? " Override" : "");
|
|
||||||
|
|
||||||
// set the bot type
|
|
||||||
sprintf (botType, "%s%s%s", m_personality == PERSONALITY_RUSHER ? " Rusher" : "",
|
|
||||||
m_personality == PERSONALITY_CAREFUL ? " Careful" : "",
|
|
||||||
m_personality == PERSONALITY_NORMAL ? " Normal" : "");
|
|
||||||
|
|
||||||
if (weaponCount >= NUM_WEAPONS)
|
|
||||||
{
|
|
||||||
// prevent printing unknown message from known weapons
|
|
||||||
switch (m_currentWeapon)
|
|
||||||
{
|
|
||||||
case WEAPON_EXPLOSIVE:
|
|
||||||
strcpy (weaponName, "weapon_hegrenade");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WEAPON_FLASHBANG:
|
|
||||||
strcpy (weaponName, "weapon_flashbang");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WEAPON_SMOKE:
|
|
||||||
strcpy (weaponName, "weapon_smokegrenade");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WEAPON_C4:
|
|
||||||
strcpy (weaponName, "weapon_c4");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
sprintf (weaponName, "Unknown! (%d)", m_currentWeapon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
strncpy (weaponName, selectTab->weaponName, SIZEOF_CHAR (weaponName));
|
|
||||||
|
|
||||||
char outputBuffer[512];
|
|
||||||
memset (outputBuffer, 0, sizeof (outputBuffer));
|
|
||||||
|
|
||||||
sprintf (outputBuffer, "\n\n\n\n%s (H:%.1f/A:%.1f)- Task: %d=%s Desire:%.02f\nItem: %s Clip: %d Ammo: %d%s Money: %d AimFlags: %s\nSP=%.02f SSP=%.02f I=%d PG=%d G=%d T: %.02f MT: %d\nEnemy=%s Pickup=%s Type=%s\n", STRING (pev->netname), pev->health, pev->armorvalue, taskID, taskName, GetTask ()->desire, &weaponName[7], GetAmmoInClip (), GetAmmo (), m_isReloading ? " (R)" : "", m_moneyAmount, aimFlags, m_moveSpeed, m_strafeSpeed, index, m_prevGoalIndex, goal, m_navTimeset - GetWorldTime (), pev->movetype, enemyName, pickupName, botType);
|
|
||||||
|
|
||||||
MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, NULL, g_hostEntity);
|
|
||||||
WRITE_BYTE (TE_TEXTMESSAGE);
|
|
||||||
WRITE_BYTE (1);
|
|
||||||
WRITE_SHORT (FixedSigned16 (-1, 1 << 13));
|
|
||||||
WRITE_SHORT (FixedSigned16 (0, 1 << 13));
|
|
||||||
WRITE_BYTE (0);
|
|
||||||
WRITE_BYTE (m_team == TEAM_CF ? 0 : 255);
|
|
||||||
WRITE_BYTE (100);
|
|
||||||
WRITE_BYTE (m_team != TEAM_CF ? 0 : 255);
|
|
||||||
WRITE_BYTE (0);
|
|
||||||
WRITE_BYTE (255);
|
|
||||||
WRITE_BYTE (255);
|
|
||||||
WRITE_BYTE (255);
|
|
||||||
WRITE_BYTE (0);
|
|
||||||
WRITE_SHORT (FixedUnsigned16 (0, 1 << 8));
|
|
||||||
WRITE_SHORT (FixedUnsigned16 (0, 1 << 8));
|
|
||||||
WRITE_SHORT (FixedUnsigned16 (1.0, 1 << 8));
|
|
||||||
WRITE_STRING (const_cast <const char *> (&outputBuffer[0]));
|
|
||||||
MESSAGE_END ();
|
|
||||||
|
|
||||||
timeDebugUpdate = GetWorldTime () + 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// green = destination origin
|
|
||||||
// blue = ideal angles
|
|
||||||
// red = view angles
|
|
||||||
|
|
||||||
DrawArrow (g_hostEntity, EyePosition (), m_destOrigin, 10, 0, 0, 255, 0, 250, 5, 1);
|
|
||||||
|
|
||||||
MakeVectors (m_idealAngles);
|
|
||||||
DrawArrow (g_hostEntity, EyePosition (), EyePosition () + g_pGlobals->v_forward * 300.0f, 10, 0, 0, 0, 255, 250, 5, 1);
|
|
||||||
|
|
||||||
MakeVectors (pev->v_angle);
|
|
||||||
DrawArrow (g_hostEntity, EyePosition (), EyePosition () + g_pGlobals->v_forward * 300.0f, 10, 0, 255, 0, 0, 250, 5, 1);
|
|
||||||
|
|
||||||
// now draw line from source to destination
|
|
||||||
PathNode *node = &m_navNode[0];
|
|
||||||
|
|
||||||
while (node != NULL)
|
|
||||||
{
|
|
||||||
const Vector &srcPath = waypoints.GetPath (node->index)->origin;
|
|
||||||
node = node->next;
|
|
||||||
|
|
||||||
if (node != NULL)
|
|
||||||
{
|
|
||||||
const Vector &dstPath = waypoints.GetPath (node->index)->origin;
|
|
||||||
DrawArrow (g_hostEntity, srcPath, dstPath, 15, 0, 255, 100, 55, 200, 5, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the previous speed (for checking if stuck)
|
// save the previous speed (for checking if stuck)
|
||||||
m_prevSpeed = fabsf (m_moveSpeed);
|
m_prevSpeed = fabsf (m_moveSpeed);
|
||||||
m_lastDamageType = -1; // reset damage
|
m_lastDamageType = -1; // reset damage
|
||||||
|
|
@ -5205,6 +4983,256 @@ void Bot::BotAI (void)
|
||||||
pev->v_angle.ClampAngles ();
|
pev->v_angle.ClampAngles ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bot::DisplayDebugOverlay (void)
|
||||||
|
{
|
||||||
|
bool displayDebugOverlay = false;
|
||||||
|
|
||||||
|
if (g_hostEntity->v.iuser2 == IndexOfEntity (GetEntity ()))
|
||||||
|
displayDebugOverlay = true;
|
||||||
|
|
||||||
|
if (!displayDebugOverlay && yb_debug.GetInt () >= 2)
|
||||||
|
{
|
||||||
|
Bot *nearest = NULL;
|
||||||
|
|
||||||
|
if (FindNearestPlayer (reinterpret_cast <void **> (&nearest), g_hostEntity, 128.0f, true, true, true, true) && nearest == this)
|
||||||
|
displayDebugOverlay = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (displayDebugOverlay)
|
||||||
|
{
|
||||||
|
static float timeDebugUpdate = 0.0f;
|
||||||
|
static int index, goal, taskID;
|
||||||
|
|
||||||
|
if (!m_tasks.IsEmpty ())
|
||||||
|
{
|
||||||
|
if (taskID != GetTaskId () || index != m_currentWaypointIndex || goal != GetTask ()->data || timeDebugUpdate < GetWorldTime ())
|
||||||
|
{
|
||||||
|
taskID = GetTaskId ();
|
||||||
|
index = m_currentWaypointIndex;
|
||||||
|
goal = GetTask ()->data;
|
||||||
|
|
||||||
|
char taskName[80];
|
||||||
|
memset (taskName, 0, sizeof (taskName));
|
||||||
|
|
||||||
|
switch (taskID)
|
||||||
|
{
|
||||||
|
case TASK_NORMAL:
|
||||||
|
sprintf (taskName, "Normal");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_PAUSE:
|
||||||
|
sprintf (taskName, "Pause");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_MOVETOPOSITION:
|
||||||
|
sprintf (taskName, "MoveToPosition");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_FOLLOWUSER:
|
||||||
|
sprintf (taskName, "FollowUser");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_WAITFORGO:
|
||||||
|
sprintf (taskName, "WaitForGo");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_PICKUPITEM:
|
||||||
|
sprintf (taskName, "PickupItem");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_CAMP:
|
||||||
|
sprintf (taskName, "Camp");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_PLANTBOMB:
|
||||||
|
sprintf (taskName, "PlantBomb");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_DEFUSEBOMB:
|
||||||
|
sprintf (taskName, "DefuseBomb");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_ATTACK:
|
||||||
|
sprintf (taskName, "AttackEnemy");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_HUNTENEMY:
|
||||||
|
sprintf (taskName, "HuntEnemy");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_SEEKCOVER:
|
||||||
|
sprintf (taskName, "SeekCover");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_THROWHEGRENADE:
|
||||||
|
sprintf (taskName, "ThrowExpGrenade");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_THROWFLASHBANG:
|
||||||
|
sprintf (taskName, "ThrowFlashGrenade");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_THROWSMOKE:
|
||||||
|
sprintf (taskName, "ThrowSmokeGrenade");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_DOUBLEJUMP:
|
||||||
|
sprintf (taskName, "PerformDoubleJump");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_ESCAPEFROMBOMB:
|
||||||
|
sprintf (taskName, "EscapeFromBomb");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_SHOOTBREAKABLE:
|
||||||
|
sprintf (taskName, "ShootBreakable");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_HIDE:
|
||||||
|
sprintf (taskName, "Hide");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_BLINDED:
|
||||||
|
sprintf (taskName, "Blinded");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TASK_SPRAY:
|
||||||
|
sprintf (taskName, "SprayLogo");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char enemyName[80], weaponName[80], aimFlags[64], botType[32];
|
||||||
|
|
||||||
|
if (!IsEntityNull (m_enemy))
|
||||||
|
strncpy (enemyName, STRING (m_enemy->v.netname), SIZEOF_CHAR (enemyName));
|
||||||
|
else if (!IsEntityNull (m_lastEnemy))
|
||||||
|
{
|
||||||
|
strcpy (enemyName, " (L)");
|
||||||
|
strncat (enemyName, STRING (m_lastEnemy->v.netname), SIZEOF_CHAR (enemyName));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strcpy (enemyName, " (null)");
|
||||||
|
|
||||||
|
char pickupName[80];
|
||||||
|
memset (pickupName, 0, sizeof (pickupName));
|
||||||
|
|
||||||
|
if (!IsEntityNull (m_pickupItem))
|
||||||
|
strncpy (pickupName, STRING (m_pickupItem->v.classname), SIZEOF_CHAR (pickupName));
|
||||||
|
else
|
||||||
|
strcpy (pickupName, " (null)");
|
||||||
|
|
||||||
|
WeaponSelect *selectTab = &g_weaponSelect[0];
|
||||||
|
char weaponCount = 0;
|
||||||
|
|
||||||
|
while (m_currentWeapon != selectTab->id && weaponCount < NUM_WEAPONS)
|
||||||
|
{
|
||||||
|
selectTab++;
|
||||||
|
weaponCount++;
|
||||||
|
}
|
||||||
|
memset (aimFlags, 0, sizeof (aimFlags));
|
||||||
|
|
||||||
|
// set the aim flags
|
||||||
|
sprintf (aimFlags, "%s%s%s%s%s%s%s%s",
|
||||||
|
(m_aimFlags & AIM_NAVPOINT) ? " NavPoint" : "",
|
||||||
|
(m_aimFlags & AIM_CAMP) ? " CampPoint" : "",
|
||||||
|
(m_aimFlags & AIM_PREDICT_PATH) ? " PredictPath" : "",
|
||||||
|
(m_aimFlags & AIM_LAST_ENEMY) ? " LastEnemy" : "",
|
||||||
|
(m_aimFlags & AIM_ENTITY) ? " Entity" : "",
|
||||||
|
(m_aimFlags & AIM_ENEMY) ? " Enemy" : "",
|
||||||
|
(m_aimFlags & AIM_GRENADE) ? " Grenade" : "",
|
||||||
|
(m_aimFlags & AIM_OVERRIDE) ? " Override" : "");
|
||||||
|
|
||||||
|
// set the bot type
|
||||||
|
sprintf (botType, "%s%s%s", m_personality == PERSONALITY_RUSHER ? " Rusher" : "",
|
||||||
|
m_personality == PERSONALITY_CAREFUL ? " Careful" : "",
|
||||||
|
m_personality == PERSONALITY_NORMAL ? " Normal" : "");
|
||||||
|
|
||||||
|
if (weaponCount >= NUM_WEAPONS)
|
||||||
|
{
|
||||||
|
// prevent printing unknown message from known weapons
|
||||||
|
switch (m_currentWeapon)
|
||||||
|
{
|
||||||
|
case WEAPON_EXPLOSIVE:
|
||||||
|
strcpy (weaponName, "weapon_hegrenade");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WEAPON_FLASHBANG:
|
||||||
|
strcpy (weaponName, "weapon_flashbang");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WEAPON_SMOKE:
|
||||||
|
strcpy (weaponName, "weapon_smokegrenade");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WEAPON_C4:
|
||||||
|
strcpy (weaponName, "weapon_c4");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
sprintf (weaponName, "Unknown! (%d)", m_currentWeapon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strncpy (weaponName, selectTab->weaponName, SIZEOF_CHAR (weaponName));
|
||||||
|
|
||||||
|
char outputBuffer[512];
|
||||||
|
memset (outputBuffer, 0, sizeof (outputBuffer));
|
||||||
|
|
||||||
|
sprintf (outputBuffer, "\n\n\n\n%s (H:%.1f/A:%.1f)- Task: %d=%s Desire:%.02f\nItem: %s Clip: %d Ammo: %d%s Money: %d AimFlags: %s\nSP=%.02f SSP=%.02f I=%d PG=%d G=%d T: %.02f MT: %d\nEnemy=%s Pickup=%s Type=%s\n", STRING (pev->netname), pev->health, pev->armorvalue, taskID, taskName, GetTask ()->desire, &weaponName[7], GetAmmoInClip (), GetAmmo (), m_isReloading ? " (R)" : "", m_moneyAmount, aimFlags, m_moveSpeed, m_strafeSpeed, index, m_prevGoalIndex, goal, m_navTimeset - GetWorldTime (), pev->movetype, enemyName, pickupName, botType);
|
||||||
|
|
||||||
|
MESSAGE_BEGIN (MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, NULL, g_hostEntity);
|
||||||
|
WRITE_BYTE (TE_TEXTMESSAGE);
|
||||||
|
WRITE_BYTE (1);
|
||||||
|
WRITE_SHORT (FixedSigned16 (-1, 1 << 13));
|
||||||
|
WRITE_SHORT (FixedSigned16 (0, 1 << 13));
|
||||||
|
WRITE_BYTE (0);
|
||||||
|
WRITE_BYTE (m_team == TEAM_CF ? 0 : 255);
|
||||||
|
WRITE_BYTE (100);
|
||||||
|
WRITE_BYTE (m_team != TEAM_CF ? 0 : 255);
|
||||||
|
WRITE_BYTE (0);
|
||||||
|
WRITE_BYTE (255);
|
||||||
|
WRITE_BYTE (255);
|
||||||
|
WRITE_BYTE (255);
|
||||||
|
WRITE_BYTE (0);
|
||||||
|
WRITE_SHORT (FixedUnsigned16 (0, 1 << 8));
|
||||||
|
WRITE_SHORT (FixedUnsigned16 (0, 1 << 8));
|
||||||
|
WRITE_SHORT (FixedUnsigned16 (1.0, 1 << 8));
|
||||||
|
WRITE_STRING (const_cast <const char *> (&outputBuffer[0]));
|
||||||
|
MESSAGE_END ();
|
||||||
|
|
||||||
|
timeDebugUpdate = GetWorldTime () + 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// green = destination origin
|
||||||
|
// blue = ideal angles
|
||||||
|
// red = view angles
|
||||||
|
|
||||||
|
DrawArrow (g_hostEntity, EyePosition (), m_destOrigin, 10, 0, 0, 255, 0, 250, 5, 1);
|
||||||
|
|
||||||
|
MakeVectors (m_idealAngles);
|
||||||
|
DrawArrow (g_hostEntity, EyePosition () - Vector (0.0f, 0.0f, 16.0f), EyePosition () + g_pGlobals->v_forward * 300.0f, 10, 0, 0, 0, 255, 250, 5, 1);
|
||||||
|
|
||||||
|
MakeVectors (pev->v_angle);
|
||||||
|
DrawArrow (g_hostEntity, EyePosition () - Vector (0.0f, 0.0f, 32.0f), EyePosition () + g_pGlobals->v_forward * 300.0f, 10, 0, 255, 0, 0, 250, 5, 1);
|
||||||
|
|
||||||
|
// now draw line from source to destination
|
||||||
|
PathNode *node = &m_navNode[0];
|
||||||
|
|
||||||
|
while (node != NULL)
|
||||||
|
{
|
||||||
|
const Vector &srcPath = waypoints.GetPath (node->index)->origin;
|
||||||
|
node = node->next;
|
||||||
|
|
||||||
|
if (node != NULL)
|
||||||
|
{
|
||||||
|
const Vector &dstPath = waypoints.GetPath (node->index)->origin;
|
||||||
|
DrawArrow (g_hostEntity, srcPath, dstPath, 15, 0, 255, 100, 55, 200, 5, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Bot::HasHostage (void)
|
bool Bot::HasHostage (void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_HOSTAGES; i++)
|
for (int i = 0; i < MAX_HOSTAGES; i++)
|
||||||
|
|
|
||||||
|
|
@ -913,7 +913,7 @@ WeaponSelectEnd:
|
||||||
{
|
{
|
||||||
if (distance < 64.0f)
|
if (distance < 64.0f)
|
||||||
{
|
{
|
||||||
if (Random.Long (1, 100) < 15 || HasShield ())
|
if (Random.Long (1, 100) < 30 || HasShield ())
|
||||||
pev->button |= IN_ATTACK; // use primary attack
|
pev->button |= IN_ATTACK; // use primary attack
|
||||||
else
|
else
|
||||||
pev->button |= IN_ATTACK2; // use secondary attack
|
pev->button |= IN_ATTACK2; // use secondary attack
|
||||||
|
|
@ -921,8 +921,6 @@ WeaponSelectEnd:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LookupEnemy ();
|
|
||||||
|
|
||||||
if (selectTab[chosenWeaponIndex].primaryFireHold && m_ammo[g_weaponDefs[selectTab[selectIndex].id].ammo1] > selectTab[selectIndex].minPrimaryAmmo) // if automatic weapon, just press attack
|
if (selectTab[chosenWeaponIndex].primaryFireHold && m_ammo[g_weaponDefs[selectTab[selectIndex].id].ammo1] > selectTab[selectIndex].minPrimaryAmmo) // if automatic weapon, just press attack
|
||||||
pev->button |= IN_ATTACK;
|
pev->button |= IN_ATTACK;
|
||||||
else // if not, toggle buttons
|
else // if not, toggle buttons
|
||||||
|
|
@ -993,15 +991,12 @@ bool Bot::IsWeaponBadInDistance (int weaponIndex, float distance)
|
||||||
void Bot::FocusEnemy (void)
|
void Bot::FocusEnemy (void)
|
||||||
{
|
{
|
||||||
// aim for the head and/or body
|
// aim for the head and/or body
|
||||||
Vector enemyOrigin = GetAimPosition ();
|
m_lookAt = GetAimPosition ();
|
||||||
m_lookAt = enemyOrigin;
|
|
||||||
|
|
||||||
if (m_enemySurpriseTime > GetWorldTime ())
|
if (m_enemySurpriseTime > GetWorldTime ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
enemyOrigin = (enemyOrigin - EyePosition ()).Get2D ();
|
float distance = (m_lookAt - EyePosition ()).GetLength2D (); // how far away is the enemy scum?
|
||||||
|
|
||||||
float distance = enemyOrigin.GetLength (); // how far away is the enemy scum?
|
|
||||||
|
|
||||||
if (distance < 128.0f)
|
if (distance < 128.0f)
|
||||||
{
|
{
|
||||||
|
|
@ -1044,25 +1039,18 @@ void Bot::CombatFight (void)
|
||||||
if (IsEntityNull (m_enemy))
|
if (IsEntityNull (m_enemy))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Vector enemyOrigin = m_lookAt;
|
float distance = (m_lookAt - EyePosition ()).GetLength2D (); // how far away is the enemy scum?
|
||||||
|
|
||||||
if (m_currentWeapon == WEAPON_KNIFE)
|
if (m_timeWaypointMove < GetWorldTime ())
|
||||||
m_destOrigin = m_enemy->v.origin;
|
|
||||||
|
|
||||||
enemyOrigin = (enemyOrigin - EyePosition ()).Get2D (); // ignore z component (up & down)
|
|
||||||
|
|
||||||
float distance = enemyOrigin.GetLength (); // how far away is the enemy scum?
|
|
||||||
|
|
||||||
if (m_timeWaypointMove + m_frameInterval + 0.5f < GetWorldTime ())
|
|
||||||
{
|
{
|
||||||
int approach;
|
int approach;
|
||||||
|
|
||||||
|
if (m_currentWeapon == WEAPON_KNIFE) // knife?
|
||||||
|
approach = 100;
|
||||||
if ((m_states & STATE_SUSPECT_ENEMY) && !(m_states & STATE_SEEING_ENEMY)) // if suspecting enemy stand still
|
if ((m_states & STATE_SUSPECT_ENEMY) && !(m_states & STATE_SEEING_ENEMY)) // if suspecting enemy stand still
|
||||||
approach = 49;
|
approach = 49;
|
||||||
else if (m_isReloading || m_isVIP) // if reloading or vip back off
|
else if (m_isReloading || m_isVIP) // if reloading or vip back off
|
||||||
approach = 29;
|
approach = 29;
|
||||||
else if (m_currentWeapon == WEAPON_KNIFE) // knife?
|
|
||||||
approach = 100;
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
approach = static_cast <int> (pev->health * m_agressionLevel);
|
approach = static_cast <int> (pev->health * m_agressionLevel);
|
||||||
|
|
@ -1071,17 +1059,6 @@ void Bot::CombatFight (void)
|
||||||
approach = 49;
|
approach = 49;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UsesPistol() && !((m_enemy->v.weapons & WEAPON_SECONDARY) || (m_enemy->v.weapons & (1 << WEAPON_SG550))) && !g_bombPlanted)
|
|
||||||
{
|
|
||||||
m_fearLevel += 0.5f;
|
|
||||||
|
|
||||||
CheckGrenades();
|
|
||||||
CheckThrow (EyePosition(), m_throw);
|
|
||||||
|
|
||||||
if ((m_states & STATE_SEEING_ENEMY) && !m_hasC4)
|
|
||||||
PushTask (TASK_SEEKCOVER, TASKPRI_SEEKCOVER, -1, Random.Long (10, 20), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// only take cover when bomb is not planted and enemy can see the bot or the bot is VIP
|
// only take cover when bomb is not planted and enemy can see the bot or the bot is VIP
|
||||||
if (approach < 30 && !g_bombPlanted && (IsInViewCone (m_enemy->v.origin) || m_isVIP))
|
if (approach < 30 && !g_bombPlanted && (IsInViewCone (m_enemy->v.origin) || m_isVIP))
|
||||||
{
|
{
|
||||||
|
|
@ -1108,7 +1085,7 @@ void Bot::CombatFight (void)
|
||||||
}
|
}
|
||||||
else if (UsesRifle () || UsesSubmachineGun ())
|
else if (UsesRifle () || UsesSubmachineGun ())
|
||||||
{
|
{
|
||||||
if (m_lastFightStyleCheck + 3.0 < GetWorldTime ())
|
if (m_lastFightStyleCheck + 3.0f < GetWorldTime ())
|
||||||
{
|
{
|
||||||
int rand = Random.Long (1, 100);
|
int rand = Random.Long (1, 100);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1105,31 +1105,14 @@ int ClientConnect (edict_t *ent, const char *name, const char *addr, char reject
|
||||||
if (strcmp (addr, "loopback") == 0)
|
if (strcmp (addr, "loopback") == 0)
|
||||||
g_hostEntity = ent; // save the edict of the listen server client...
|
g_hostEntity = ent; // save the edict of the listen server client...
|
||||||
|
|
||||||
|
bots.AdjustQuota (true, ent);
|
||||||
|
|
||||||
if (g_isMetamod)
|
if (g_isMetamod)
|
||||||
RETURN_META_VALUE (MRES_IGNORED, 0);
|
RETURN_META_VALUE (MRES_IGNORED, 0);
|
||||||
|
|
||||||
return (*g_functionTable.pfnClientConnect) (ent, name, addr, rejectReason);
|
return (*g_functionTable.pfnClientConnect) (ent, name, addr, rejectReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientPutInServer (edict_t *ent)
|
|
||||||
{
|
|
||||||
// this function is called once a just connected client actually enters the game, after
|
|
||||||
// having downloaded and synchronized its resources with the of the server's. It's the
|
|
||||||
// perfect place to hook for client connecting, since a client can always try to connect
|
|
||||||
// passing the ClientConnect() step, and not be allowed by the server later (because of a
|
|
||||||
// latency timeout or whatever reason). We can here keep track of both bots and players
|
|
||||||
// counts on occurence, since bots connect the server just like the way normal client do,
|
|
||||||
// and their third party bot flag is already supposed to be set then. If it's a bot which
|
|
||||||
// is connecting, we also have to awake its brain(s) by reading them from the disk.
|
|
||||||
|
|
||||||
bots.AdjustQuota (true, ent);
|
|
||||||
|
|
||||||
if (g_isMetamod)
|
|
||||||
RETURN_META (MRES_IGNORED);
|
|
||||||
|
|
||||||
(*g_functionTable.pfnClientPutInServer) (ent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClientDisconnect (edict_t *ent)
|
void ClientDisconnect (edict_t *ent)
|
||||||
{
|
{
|
||||||
// this function is called whenever a client is VOLUNTARILY disconnected from the server,
|
// this function is called whenever a client is VOLUNTARILY disconnected from the server,
|
||||||
|
|
@ -2783,7 +2766,7 @@ void pfnAlertMessage (ALERT_TYPE alertType, char *format, ...)
|
||||||
vsprintf (buffer, format, ap);
|
vsprintf (buffer, format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
|
|
||||||
if (strstr (buffer, "_Defuse_") != NULL)
|
if ((g_mapType & MAP_DE) && g_bombPlanted && strstr (buffer, "_Defuse_") != NULL)
|
||||||
{
|
{
|
||||||
// notify all terrorists that CT is starting bomb defusing
|
// notify all terrorists that CT is starting bomb defusing
|
||||||
for (int i = 0; i < GetMaxClients (); i++)
|
for (int i = 0; i < GetMaxClients (); i++)
|
||||||
|
|
@ -2840,7 +2823,6 @@ export int GetEntityAPI2 (gamefuncs_t *functionTable, int *)
|
||||||
functionTable->pfnTouch = Touch;
|
functionTable->pfnTouch = Touch;
|
||||||
functionTable->pfnClientConnect = ClientConnect;
|
functionTable->pfnClientConnect = ClientConnect;
|
||||||
functionTable->pfnClientDisconnect = ClientDisconnect;
|
functionTable->pfnClientDisconnect = ClientDisconnect;
|
||||||
functionTable->pfnClientPutInServer = ClientPutInServer;
|
|
||||||
functionTable->pfnClientUserInfoChanged = ClientUserInfoChanged;
|
functionTable->pfnClientUserInfoChanged = ClientUserInfoChanged;
|
||||||
functionTable->pfnClientCommand = ClientCommand;
|
functionTable->pfnClientCommand = ClientCommand;
|
||||||
functionTable->pfnServerActivate = ServerActivate;
|
functionTable->pfnServerActivate = ServerActivate;
|
||||||
|
|
|
||||||
|
|
@ -311,10 +311,6 @@ void BotManager::AddBot (const String &name, int difficulty, int personality, in
|
||||||
|
|
||||||
// put to queue
|
// put to queue
|
||||||
m_creationTab.Push (bot);
|
m_creationTab.Push (bot);
|
||||||
|
|
||||||
// keep quota number up to date
|
|
||||||
if (GetBotsNum () + 1 > yb_quota.GetInt ())
|
|
||||||
yb_quota.SetInt (GetBotsNum () + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotManager::AddBot (const String &name, const String &difficulty, const String &personality, const String &team, const String &member)
|
void BotManager::AddBot (const String &name, const String &difficulty, const String &personality, const String &team, const String &member)
|
||||||
|
|
@ -331,12 +327,6 @@ void BotManager::AddBot (const String &name, const String &difficulty, const Str
|
||||||
bot.personality = (personality.IsEmpty () || personality == any) ? -1 : personality.ToInt ();
|
bot.personality = (personality.IsEmpty () || personality == any) ? -1 : personality.ToInt ();
|
||||||
|
|
||||||
m_creationTab.Push (bot);
|
m_creationTab.Push (bot);
|
||||||
|
|
||||||
int newBotsNum = GetBotsNum () + 1;
|
|
||||||
|
|
||||||
// keep quota number up to date
|
|
||||||
if (newBotsNum < GetMaxClients () && newBotsNum > yb_quota.GetInt ())
|
|
||||||
yb_quota.SetInt (newBotsNum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotManager::AdjustQuota (bool isPlayerConnection, edict_t *ent)
|
void BotManager::AdjustQuota (bool isPlayerConnection, edict_t *ent)
|
||||||
|
|
@ -391,14 +381,6 @@ void BotManager::MaintainBotQuota (void)
|
||||||
if (yb_join_after_player.GetInt () > 0 && !numHumans)
|
if (yb_join_after_player.GetInt () > 0 && !numHumans)
|
||||||
desiredCount = 0;
|
desiredCount = 0;
|
||||||
|
|
||||||
if (m_quotaOption != QUOTA_NONE && numBots > 1 && desiredCount > 1)
|
|
||||||
{
|
|
||||||
if (m_quotaOption == QUOTA_INCREMENT)
|
|
||||||
desiredCount++;
|
|
||||||
else
|
|
||||||
desiredCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// quota mode
|
// quota mode
|
||||||
char mode = yb_quota_mode.GetString ()[0];
|
char mode = yb_quota_mode.GetString ()[0];
|
||||||
|
|
||||||
|
|
@ -412,57 +394,21 @@ void BotManager::MaintainBotQuota (void)
|
||||||
else
|
else
|
||||||
desiredCount = min (desiredCount, GetMaxClients () - numHumans);
|
desiredCount = min (desiredCount, GetMaxClients () - numHumans);
|
||||||
|
|
||||||
m_quotaOption = QUOTA_NONE;
|
if (m_quotaOption != QUOTA_NONE && numBots > 1 && desiredCount > 1)
|
||||||
|
{
|
||||||
|
if (m_quotaOption == QUOTA_INCREMENT)
|
||||||
|
desiredCount++;
|
||||||
|
else
|
||||||
|
desiredCount--;
|
||||||
|
|
||||||
|
m_quotaOption = QUOTA_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
if (desiredCount > numBots)
|
if (desiredCount > numBots)
|
||||||
AddRandom ();
|
AddRandom ();
|
||||||
else if (desiredCount < numBots)
|
else if (desiredCount < numBots)
|
||||||
RemoveRandom ();
|
RemoveRandom ();
|
||||||
|
|
||||||
#if 0
|
|
||||||
int botNumber = GetBotsNum ();
|
|
||||||
int humanNumber = GetHumansNum ();
|
|
||||||
|
|
||||||
if (botNumber > yb_quota.GetInt ())
|
|
||||||
RemoveRandom ();
|
|
||||||
|
|
||||||
if (humanNumber > 0 && yb_quota_match.GetInt () > 0)
|
|
||||||
{
|
|
||||||
int num = yb_quota_match.GetInt () * humanNumber;
|
|
||||||
|
|
||||||
if (num >= GetMaxClients () - humanNumber)
|
|
||||||
num = GetMaxClients () - humanNumber;
|
|
||||||
|
|
||||||
if (yb_quota_match_max.GetInt () > 0 && num > yb_quota_match_max.GetInt ())
|
|
||||||
num = yb_quota_match_max.GetInt ();
|
|
||||||
|
|
||||||
yb_quota.SetInt (num);
|
|
||||||
yb_autovacate.SetInt (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (yb_autovacate.GetBool ())
|
|
||||||
{
|
|
||||||
if (botNumber < yb_quota.GetInt () && humanNumber < GetMaxClients () - 1)
|
|
||||||
AddRandom ();
|
|
||||||
|
|
||||||
if (humanNumber >= GetMaxClients ())
|
|
||||||
RemoveRandom ();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (botNumber < yb_quota.GetInt () && humanNumber < GetMaxClients ())
|
|
||||||
AddRandom ();
|
|
||||||
}
|
|
||||||
|
|
||||||
int botQuota = yb_autovacate.GetBool () ? GetMaxClients () - humanNumber : GetMaxClients ();
|
|
||||||
|
|
||||||
// check valid range of quota
|
|
||||||
if (yb_quota.GetInt () > botQuota)
|
|
||||||
yb_quota.SetInt (botQuota);
|
|
||||||
|
|
||||||
else if (yb_quota.GetInt () < 0)
|
|
||||||
yb_quota.SetInt (0);
|
|
||||||
#endif
|
|
||||||
m_maintainTime = GetWorldTime () + 0.15f;
|
m_maintainTime = GetWorldTime () + 0.15f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -922,6 +868,12 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member, c
|
||||||
m_wantedTeam = team;
|
m_wantedTeam = team;
|
||||||
m_wantedClass = member;
|
m_wantedClass = member;
|
||||||
|
|
||||||
|
int newBotsNum = bots.GetBotsNum () + 1;
|
||||||
|
|
||||||
|
// keep quota number up to date
|
||||||
|
if (newBotsNum < GetMaxClients () && newBotsNum > yb_quota.GetInt ())
|
||||||
|
yb_quota.SetInt (newBotsNum);
|
||||||
|
|
||||||
NewRound ();
|
NewRound ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1220,9 +1172,11 @@ void Bot::Kick (void)
|
||||||
ServerCommand ("kick \"%s\"", STRING (pev->netname));
|
ServerCommand ("kick \"%s\"", STRING (pev->netname));
|
||||||
CenterPrint ("Bot '%s' kicked", STRING (pev->netname));
|
CenterPrint ("Bot '%s' kicked", STRING (pev->netname));
|
||||||
|
|
||||||
// balances quota
|
int newBotsNum = bots.GetBotsNum () - 1;
|
||||||
if (bots.GetBotsNum () - 1 < yb_quota.GetInt ())
|
|
||||||
yb_quota.SetInt (bots.GetBotsNum () - 1);
|
// keep quota number up to date
|
||||||
|
if (newBotsNum < GetMaxClients () && newBotsNum < yb_quota.GetInt ())
|
||||||
|
yb_quota.SetInt (newBotsNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::StartGame (void)
|
void Bot::StartGame (void)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue