fixed move angles not updated when not checking terrain

fixed reporting-in spam
fixed bot-s won't fight in jason mode
added yb_shoots_thru_walls 2 to use old method for checking shootable wall
This commit is contained in:
Dmitry 2015-06-07 19:43:16 +03:00
commit eb13736a00
7 changed files with 328 additions and 294 deletions

View file

@ -487,7 +487,7 @@ enum AimPosition
{ {
AIM_NAVPOINT = (1 << 0), // aim at nav point AIM_NAVPOINT = (1 << 0), // aim at nav point
AIM_CAMP = (1 << 1), // aim at camp vector AIM_CAMP = (1 << 1), // aim at camp vector
AIM_PREDICT_ENEMY = (1 << 2), // aim at predicted path AIM_PREDICT_PATH = (1 << 2), // aim at predicted path
AIM_LAST_ENEMY = (1 << 3), // aim at last enemy AIM_LAST_ENEMY = (1 << 3), // aim at last enemy
AIM_ENTITY = (1 << 4), // aim at entity like buttons, hostages AIM_ENTITY = (1 << 4), // aim at entity like buttons, hostages
AIM_ENEMY = (1 << 5), // aim at enemy AIM_ENEMY = (1 << 5), // aim at enemy
@ -1001,7 +1001,7 @@ private:
int FindDefendWaypoint (Vector origin); int FindDefendWaypoint (Vector origin);
int FindGoal (void); int FindGoal (void);
void FindItem (void); void FindItem (void);
void CheckTerrain (float movedDistance); void CheckTerrain (float movedDistance, const Vector &dir, const Vector &dirNormal);
void GetCampDirection (Vector *dest); void GetCampDirection (Vector *dest);
void CollectGoalExperience (int damage, int team); void CollectGoalExperience (int damage, int team);
@ -1015,9 +1015,11 @@ private:
bool IsBlockedLeft (void); bool IsBlockedLeft (void);
bool IsBlockedRight (void); bool IsBlockedRight (void);
bool IsPointOccupied (int index); bool IsPointOccupied (int index);
inline bool IsOnLadder (void) { return pev->movetype == MOVETYPE_FLY; } inline bool IsOnLadder (void) { return pev->movetype == MOVETYPE_FLY; }
inline bool IsOnFloor (void) { return (pev->flags & (FL_ONGROUND | FL_PARTIALGROUND)) != 0; } inline bool IsOnFloor (void) { return (pev->flags & (FL_ONGROUND | FL_PARTIALGROUND)) != 0; }
inline bool IsInWater (void) { return pev->waterlevel >= 2; } inline bool IsInWater (void) { return pev->waterlevel >= 2; }
inline float GetWalkSpeed (void) { return static_cast <float> ((static_cast <int> (pev->maxspeed) / 2) + (static_cast <int> (pev->maxspeed) / 50)) - 18; } inline float GetWalkSpeed (void) { return static_cast <float> ((static_cast <int> (pev->maxspeed) / 2) + (static_cast <int> (pev->maxspeed) / 50)) - 18; }
bool ItemIsVisible (const Vector &dest, char *itemName); bool ItemIsVisible (const Vector &dest, char *itemName);
@ -1067,7 +1069,10 @@ private:
void SelectPistol (void); void SelectPistol (void);
bool IsFriendInLineOfFire (float distance); bool IsFriendInLineOfFire (float distance);
bool IsGroupOfEnemies (Vector location, int numEnemies = 1, int radius = 256); bool IsGroupOfEnemies (Vector location, int numEnemies = 1, int radius = 256);
bool IsShootableThruObstacle (Vector dest);
bool IsShootableThruObstacle (const Vector &dest);
bool IsShootableThruObstacleEx (const Vector &dest);
int GetNearbyEnemiesNearPosition (Vector origin, int radius); int GetNearbyEnemiesNearPosition (Vector origin, int radius);
int GetNearbyFriendsNearPosition (Vector origin, int radius); int GetNearbyFriendsNearPosition (Vector origin, int radius);
void SelectWeaponByName (const char *name); void SelectWeaponByName (const char *name);

View file

@ -33,9 +33,9 @@
<ClCompile Include="..\source\basecode.cpp"> <ClCompile Include="..\source\basecode.cpp">
<WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level4</WarningLevel> <WarningLevel Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Level4</WarningLevel>
</ClCompile> </ClCompile>
<ClCompile Include="..\source\combat.cpp" />
<ClCompile Include="..\source\manager.cpp" /> <ClCompile Include="..\source\manager.cpp" />
<ClCompile Include="..\source\chatlib.cpp" /> <ClCompile Include="..\source\chatlib.cpp" />
<ClCompile Include="..\source\combat.cpp" />
<ClCompile Include="..\source\globals.cpp" /> <ClCompile Include="..\source\globals.cpp" />
<ClCompile Include="..\source\interface.cpp" /> <ClCompile Include="..\source\interface.cpp" />
<ClCompile Include="..\source\navigate.cpp" /> <ClCompile Include="..\source\navigate.cpp" />

View file

@ -71,9 +71,6 @@
<ClCompile Include="..\source\chatlib.cpp"> <ClCompile Include="..\source\chatlib.cpp">
<Filter>source</Filter> <Filter>source</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\source\combat.cpp">
<Filter>source</Filter>
</ClCompile>
<ClCompile Include="..\source\globals.cpp"> <ClCompile Include="..\source\globals.cpp">
<Filter>source</Filter> <Filter>source</Filter>
</ClCompile> </ClCompile>
@ -98,6 +95,9 @@
<ClCompile Include="..\source\basecode.cpp"> <ClCompile Include="..\source\basecode.cpp">
<Filter>source</Filter> <Filter>source</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\source\combat.cpp">
<Filter>source</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="yapb.rc"> <ResourceCompile Include="yapb.rc">

View file

@ -1139,8 +1139,9 @@ void Bot::CheckMessageQueue (void)
else else
InstantChatterMessage (Chatter_HearSomething); InstantChatterMessage (Chatter_HearSomething);
} }
else else if (g_randGen.Long (0, 100) < 40)
InstantChatterMessage (Chatter_ReportingIn); InstantChatterMessage (Chatter_ReportingIn);
break; break;
case TASK_MOVETOPOSITION: case TASK_MOVETOPOSITION:
@ -1828,7 +1829,7 @@ void Bot::SetConditions (void)
if ((pev->origin - m_lastEnemyOrigin).GetLength () < 1600.0 && (tr.flFraction >= 0.2 || tr.pHit != g_worldEdict)) if ((pev->origin - m_lastEnemyOrigin).GetLength () < 1600.0 && (tr.flFraction >= 0.2 || tr.pHit != g_worldEdict))
{ {
m_aimFlags |= AIM_PREDICT_ENEMY; m_aimFlags |= AIM_PREDICT_PATH;
if (EntityIsVisible (m_lastEnemyOrigin)) if (EntityIsVisible (m_lastEnemyOrigin))
m_aimFlags |= AIM_LAST_ENEMY; m_aimFlags |= AIM_LAST_ENEMY;
@ -2025,7 +2026,7 @@ void Bot::SetConditions (void)
float desireLevel = 0.0; float desireLevel = 0.0;
// calculate desire to attack // calculate desire to attack
if ((m_states & STATE_SEEING_ENEMY) && ReactOnEnemy () && g_taskFilters[TASK_MOVETOPOSITION].desire < TASKPRI_HIDE) if ((m_states & STATE_SEEING_ENEMY) && ReactOnEnemy ())
g_taskFilters[TASK_ATTACK].desire = TASKPRI_ATTACK; g_taskFilters[TASK_ATTACK].desire = TASKPRI_ATTACK;
else else
g_taskFilters[TASK_ATTACK].desire = 0; g_taskFilters[TASK_ATTACK].desire = 0;
@ -2324,7 +2325,7 @@ bool Bot::IsLastEnemyViewable (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) || IsEntityNull (m_lastEnemy) || GetTaskId () == TASK_PAUSE && m_lastEnemyOrigin != nullvec) if (!(m_aimFlags & AIM_LAST_ENEMY) || IsEntityNull (m_lastEnemy) || GetTaskId () == TASK_PAUSE || m_lastEnemyOrigin != nullvec)
return false; return false;
return GetShootingConeDeviation (GetEntity (), &m_lastEnemyOrigin) >= 0.90 && IsShootableThruObstacle (m_lastEnemy->v.origin); return GetShootingConeDeviation (GetEntity (), &m_lastEnemyOrigin) >= 0.90 && IsShootableThruObstacle (m_lastEnemy->v.origin);
@ -2647,7 +2648,7 @@ void Bot::CheckRadioCommands (void)
break; break;
case Radio_ReportTeam: case Radio_ReportTeam:
if (g_randGen.Long (0, 100) < 85) if (g_randGen.Long (0, 100) < 30)
RadioMessage ((GetNearbyEnemiesNearPosition (pev->origin, 400) == 0 && yb_communication_type.GetInt () != 2) ? Radio_SectorClear : Radio_ReportingIn); RadioMessage ((GetNearbyEnemiesNearPosition (pev->origin, 400) == 0 && yb_communication_type.GetInt () != 2) ? Radio_SectorClear : Radio_ReportingIn);
break; break;
@ -2891,19 +2892,19 @@ void Bot::ChooseAimDirection (void)
if ((pev->origin - m_lastEnemyOrigin).GetLength () >= 1600 && IsEntityNull (m_enemy) && !UsesSniper () || (tr.flFraction <= 0.2 && tr.pHit == g_hostEntity) && m_seeEnemyTime + 7.0 < GetWorldTime ()) if ((pev->origin - m_lastEnemyOrigin).GetLength () >= 1600 && IsEntityNull (m_enemy) && !UsesSniper () || (tr.flFraction <= 0.2 && tr.pHit == g_hostEntity) && m_seeEnemyTime + 7.0 < GetWorldTime ())
{ {
if ((m_aimFlags & (AIM_LAST_ENEMY | AIM_PREDICT_ENEMY)) && m_wantsToFire) if ((m_aimFlags & (AIM_LAST_ENEMY | AIM_PREDICT_PATH)) && m_wantsToFire)
m_wantsToFire = false; m_wantsToFire = false;
m_lastEnemyOrigin = nullvec; m_lastEnemyOrigin = nullvec;
m_aimFlags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_ENEMY); m_aimFlags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_PATH);
flags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_ENEMY); flags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_PATH);
} }
} }
else else
{ {
m_aimFlags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_ENEMY); m_aimFlags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_PATH);
flags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_ENEMY); flags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_PATH);
} }
// don't allow bot to look at danger positions under certain circumstances // don't allow bot to look at danger positions under certain circumstances
@ -2911,7 +2912,7 @@ void Bot::ChooseAimDirection (void)
{ {
if (IsOnLadder () || IsInWater () || (m_waypointFlags & FLAG_LADDER) || (m_currentTravelFlags & PATHFLAG_JUMP)) if (IsOnLadder () || IsInWater () || (m_waypointFlags & FLAG_LADDER) || (m_currentTravelFlags & PATHFLAG_JUMP))
{ {
flags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_ENEMY); flags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_PATH);
canChooseAimDirection = false; canChooseAimDirection = false;
} }
} }
@ -2943,7 +2944,7 @@ void Bot::ChooseAimDirection (void)
m_lastEnemyOrigin = nullvec; m_lastEnemyOrigin = nullvec;
} }
} }
else if (flags & AIM_PREDICT_ENEMY) else if (flags & AIM_PREDICT_PATH)
{ {
if (((pev->origin - m_lastEnemyOrigin).GetLength () < 1600 || UsesSniper ()) && (tr.flFraction >= 0.2 || tr.pHit != g_worldEdict)) if (((pev->origin - m_lastEnemyOrigin).GetLength () < 1600 || UsesSniper ()) && (tr.flFraction >= 0.2 || tr.pHit != g_worldEdict))
{ {
@ -2969,7 +2970,7 @@ void Bot::ChooseAimDirection (void)
} }
else // forget an enemy far away else // forget an enemy far away
{ {
m_aimFlags &= ~AIM_PREDICT_ENEMY; m_aimFlags &= ~AIM_PREDICT_PATH;
if ((pev->origin - m_lastEnemyOrigin).GetLength () >= 1600.0) if ((pev->origin - m_lastEnemyOrigin).GetLength () >= 1600.0)
m_lastEnemyOrigin = nullvec; m_lastEnemyOrigin = nullvec;
@ -2977,7 +2978,7 @@ void Bot::ChooseAimDirection (void)
} }
else if (flags & AIM_CAMP) else if (flags & AIM_CAMP)
m_lookAt = m_camp; m_lookAt = m_camp;
else if ((flags & AIM_NAVPOINT) && !(flags & (AIM_ENTITY | AIM_ENEMY))) else if (flags & AIM_NAVPOINT)
{ {
m_lookAt = m_destOrigin; m_lookAt = m_destOrigin;
@ -3505,7 +3506,7 @@ void Bot::RunTask (void)
} }
// bots skill higher than 60? // bots skill higher than 60?
if (yb_walking_allowed.GetBool () && mp_footsteps.GetBool () && m_difficulty >= 1) if (yb_walking_allowed.GetBool () && mp_footsteps.GetBool () && m_difficulty >= 1 && !yb_jasonmode.GetBool ())
{ {
// then make him move slow if near enemy // then make him move slow if near enemy
if (!(m_currentTravelFlags & PATHFLAG_JUMP)) if (!(m_currentTravelFlags & PATHFLAG_JUMP))
@ -3578,8 +3579,8 @@ void Bot::RunTask (void)
if ((m_reloadState == RELOAD_NONE) && (GetAmmoInClip () < 8) && (GetAmmo () != 0)) if ((m_reloadState == RELOAD_NONE) && (GetAmmoInClip () < 8) && (GetAmmo () != 0))
m_reloadState = RELOAD_PRIMARY; m_reloadState = RELOAD_PRIMARY;
m_moveSpeed = 0; m_moveSpeed = 0.0f;
m_strafeSpeed = 0; m_strafeSpeed = 0.0f;
m_moveToGoal = false; m_moveToGoal = false;
m_checkTerrain = true; m_checkTerrain = true;
@ -4170,7 +4171,7 @@ void Bot::RunTask (void)
} }
m_aimFlags |= AIM_NAVPOINT; m_aimFlags |= AIM_NAVPOINT;
if (yb_walking_allowed.GetBool () && m_targetEntity->v.maxspeed < m_moveSpeed) if (yb_walking_allowed.GetBool () && m_targetEntity->v.maxspeed < m_moveSpeed && !yb_jasonmode.GetBool ())
m_moveSpeed = GetWalkSpeed (); m_moveSpeed = GetWalkSpeed ();
if (IsShieldDrawn ()) if (IsShieldDrawn ())
@ -4908,10 +4909,22 @@ void Bot::BotAI (void)
// set the reaction time (surprise momentum) different each frame according to skill // set the reaction time (surprise momentum) different each frame according to skill
SetIdealReactionTimes (); SetIdealReactionTimes ();
#if 0 // calculate 2 direction vectors, 1 without the up/down component
Vector directionOld = m_destOrigin - (pev->origin + pev->velocity * m_frameInterval);
Vector directionNormal = directionOld.Normalize ();
Vector direction = directionNormal;
directionNormal.z = 0.0;
m_moveAngles = directionOld.ToAngles ();
m_moveAngles.ClampAngles ();
m_moveAngles.x *= -1.0; // invert for engine
#if 0 // get rid of ugly hack
if (yb_hardcore_mode && GetTaskId () == TASK_NORMAL && ((m_aimFlags & AIM_ENEMY) || (m_states & STATE_SEEING_ENEMY)) && !IsOnLadder ()) if (yb_hardcore_mode && GetTaskId () == TASK_NORMAL && ((m_aimFlags & AIM_ENEMY) || (m_states & STATE_SEEING_ENEMY)) && !IsOnLadder ())
CombatFight (); CombatFight ();
#else
if (m_difficulty == 4 && ((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 ()) if (m_difficulty == 4 && ((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_moveToGoal = false; // don't move to goal
@ -4921,6 +4934,7 @@ void Bot::BotAI (void)
CombatFight (); CombatFight ();
} }
#endif #endif
// check if we need to escape from bomb // check if we need to escape from bomb
if ((g_mapType & MAP_DE) && g_bombPlanted && m_notKilled && GetTaskId () != TASK_ESCAPEFROMBOMB && GetTaskId () != TASK_CAMP && OutOfBombTimer ()) if ((g_mapType & MAP_DE) && g_bombPlanted && m_notKilled && GetTaskId () != TASK_ESCAPEFROMBOMB && GetTaskId () != TASK_CAMP && OutOfBombTimer ())
{ {
@ -4957,7 +4971,7 @@ void Bot::BotAI (void)
} }
if (m_checkTerrain) // are we allowed to check blocking terrain (and react to it)? if (m_checkTerrain) // are we allowed to check blocking terrain (and react to it)?
CheckTerrain (movedDistance); CheckTerrain (movedDistance, direction, directionNormal);
// must avoid a grenade? // must avoid a grenade?
if (m_needAvoidGrenade != 0) if (m_needAvoidGrenade != 0)
@ -5148,12 +5162,13 @@ void Bot::BotAI (void)
selectTab++; selectTab++;
weaponCount++; weaponCount++;
} }
memset (aimFlags, 0, sizeof (aimFlags));
// set the aim flags // set the aim flags
sprintf (aimFlags, "%s%s%s%s%s%s%s%s", sprintf (aimFlags, "%s%s%s%s%s%s%s%s",
m_aimFlags & AIM_NAVPOINT ? " NavPoint" : "", m_aimFlags & AIM_NAVPOINT ? " NavPoint" : "",
m_aimFlags & AIM_CAMP ? " CampPoint" : "", m_aimFlags & AIM_CAMP ? " CampPoint" : "",
m_aimFlags & AIM_PREDICT_ENEMY ? " PredictEnemy" : "", m_aimFlags & AIM_PREDICT_PATH ? " predictPath" : "",
m_aimFlags & AIM_LAST_ENEMY ? " LastEnemy" : "", m_aimFlags & AIM_LAST_ENEMY ? " LastEnemy" : "",
m_aimFlags & AIM_ENTITY ? " Entity" : "", m_aimFlags & AIM_ENTITY ? " Entity" : "",
m_aimFlags & AIM_ENEMY ? " Enemy" : "", m_aimFlags & AIM_ENEMY ? " Enemy" : "",
@ -5171,19 +5186,19 @@ void Bot::BotAI (void)
switch (m_currentWeapon) switch (m_currentWeapon)
{ {
case WEAPON_EXPLOSIVE: case WEAPON_EXPLOSIVE:
sprintf (weaponName, "weapon_hegrenade"); strcpy (weaponName, "weapon_hegrenade");
break; break;
case WEAPON_FLASHBANG: case WEAPON_FLASHBANG:
sprintf (weaponName, "weapon_flashbang"); strcpy (weaponName, "weapon_flashbang");
break; break;
case WEAPON_SMOKE: case WEAPON_SMOKE:
sprintf (weaponName, "weapon_smokegrenade"); strcpy (weaponName, "weapon_smokegrenade");
break; break;
case WEAPON_C4: case WEAPON_C4:
sprintf (weaponName, "weapon_c4"); strcpy (weaponName, "weapon_c4");
break; break;
default: default:
@ -5400,7 +5415,7 @@ void Bot::TakeBlinded (const Vector &fade, int alpha)
m_blindSidemoveSpeed = -walkSpeed; m_blindSidemoveSpeed = -walkSpeed;
if (pev->health < 85) if (pev->health < 85)
m_blindMoveSpeed = -GetWalkSpeed (); m_blindMoveSpeed = -walkSpeed;
else if (m_personality == PERSONALITY_CAREFUL) else if (m_personality == PERSONALITY_CAREFUL)
{ {
m_blindMoveSpeed = 0.0; m_blindMoveSpeed = 0.0;
@ -5819,7 +5834,7 @@ void Bot::RunPlayerMovement (void)
// problems, such as bots getting stuck into each others. That's because the model's // problems, such as bots getting stuck into each others. That's because the model's
// bounding boxes, which are the boxes the engine uses to compute and detect all the // bounding boxes, which are the boxes the engine uses to compute and detect all the
// collisions of the model, only exist, and are only valid, while in the duration of the // collisions of the model, only exist, and are only valid, while in the duration of the
// movement. That's why if you get a pfnRunPlayerMove for one bot that lasts a little too // movement. That's why if you get a pfnRunPlayerMove for one boINFt that lasts a little too
// short in comparison with the frame's duration, the remaining time until the frame // short in comparison with the frame's duration, the remaining time until the frame
// elapses, that bot will behave like a ghost : no movement, but bullets and players can // elapses, that bot will behave like a ghost : no movement, but bullets and players can
// pass through it. Then, when the next frame will begin, the stucking problem will arise ! // pass through it. Then, when the next frame will begin, the stucking problem will arise !
@ -5882,7 +5897,7 @@ float Bot::GetBombTimeleft (void)
float Bot::GetEstimatedReachTime (void) float Bot::GetEstimatedReachTime (void)
{ {
float estimatedTime = 3.0f; // time to reach next waypoint float estimatedTime = 2.0f; // time to reach next waypoint
// calculate 'real' time that we need to get from one waypoint to another // calculate 'real' time that we need to get from one waypoint to another
if (m_currentWaypointIndex >= 0 && m_currentWaypointIndex < g_numWaypoints && m_prevWptIndex[0] >= 0 && m_prevWptIndex[0] < g_numWaypoints) if (m_currentWaypointIndex >= 0 && m_currentWaypointIndex < g_numWaypoints && m_prevWptIndex[0] >= 0 && m_prevWptIndex[0] < g_numWaypoints)
@ -5897,15 +5912,15 @@ float Bot::GetEstimatedReachTime (void)
// check for special waypoints, that can slowdown our movement // check for special waypoints, that can slowdown our movement
if ((m_currentPath->flags & FLAG_CROUCH) || (m_currentPath->flags & FLAG_LADDER) || (pev->button & IN_DUCK)) if ((m_currentPath->flags & FLAG_CROUCH) || (m_currentPath->flags & FLAG_LADDER) || (pev->button & IN_DUCK))
estimatedTime *= 3.0; estimatedTime *= 2.0;
// check for too low values // check for too low values
if (estimatedTime < 1.0f) if (estimatedTime < 1.0f)
estimatedTime = 1.0f; estimatedTime = 1.0f;
// check for too high values // check for too high values
if (estimatedTime > 8.0f) if (estimatedTime > 5.0f)
estimatedTime = 8.0f; estimatedTime = 5.0f;
} }
return estimatedTime; return estimatedTime;
} }
@ -6060,31 +6075,6 @@ void Bot::ReactOnSound (void)
return; return;
} }
} }
// useless?
#if 0
extern ConVar yb_shoots_thru_walls;
// check if heard enemy can be seen
if (CheckVisibility (VARS (player), &m_lastEnemyOrigin, &m_visibility))
{
m_enemy = player;
m_lastEnemy = player;
m_enemyOrigin = m_lastEnemyOrigin;
m_states |= STATE_SEEING_ENEMY;
m_seeEnemyTime = GetWorldTime ();
}
else if (m_lastEnemy == player && m_seeEnemyTime + 1.0 > GetWorldTime () && yb_shoots_thru_walls.GetBool () && IsShootableThruObstacle (player->v.origin))
{
m_enemy = player;
m_lastEnemy = player;
m_lastEnemyOrigin = player->v.origin;
m_states |= STATE_SEEING_ENEMY;
m_seeEnemyTime = GetWorldTime ();
}
#endif
} }
} }

View file

@ -254,7 +254,7 @@ bool Bot::LookupEnemy (void)
} }
// check if bots should reload... // check if bots should reload...
if ((m_aimFlags <= AIM_PREDICT_ENEMY && m_seeEnemyTime + 3.0 < GetWorldTime () && !(m_states & (STATE_SEEING_ENEMY | STATE_HEARING_ENEMY)) && IsEntityNull (m_lastEnemy) && IsEntityNull (m_enemy) && GetTaskId () != TASK_SHOOTBREAKABLE && GetTaskId () != TASK_PLANTBOMB && GetTaskId () != TASK_DEFUSEBOMB) || g_roundEnded) if ((m_aimFlags <= AIM_PREDICT_PATH && m_seeEnemyTime + 3.0 < GetWorldTime () && !(m_states & (STATE_SEEING_ENEMY | STATE_HEARING_ENEMY)) && IsEntityNull (m_lastEnemy) && IsEntityNull (m_enemy) && GetTaskId () != TASK_SHOOTBREAKABLE && GetTaskId () != TASK_PLANTBOMB && GetTaskId () != TASK_DEFUSEBOMB) || g_roundEnded)
{ {
if (!m_reloadState) if (!m_reloadState)
m_reloadState = RELOAD_PRIMARY; m_reloadState = RELOAD_PRIMARY;
@ -430,11 +430,14 @@ bool Bot::IsFriendInLineOfFire (float distance)
return false; return false;
} }
bool Bot::IsShootableThruObstacle (Vector dest) bool Bot::IsShootableThruObstacle (const Vector &dest)
{ {
// this function returns true if enemy can be shoot through some obstacle, false otherwise. // this function returns true if enemy can be shoot through some obstacle, false otherwise.
// credits goes to Immortal_BLG // credits goes to Immortal_BLG
if (yb_shoots_thru_walls.GetInt () == 2)
return IsShootableThruObstacleEx (dest);
if (m_difficulty < 2) if (m_difficulty < 2)
return false; return false;
@ -478,6 +481,46 @@ bool Bot::IsShootableThruObstacle (Vector dest)
return false; return false;
} }
bool Bot::IsShootableThruObstacleEx (const Vector &dest)
{
// this function returns if enemy can be shoot through some obstacle
if (m_difficulty < 2 || GetWeaponPenetrationPower (m_currentWeapon) == 0)
return false;
Vector source = EyePosition ();
Vector direction = (dest - source).Normalize (); // 1 unit long
Vector point = nullvec;
int thikness = 0;
int numHits = 0;
TraceResult tr;
TraceLine (source, dest, true, true, GetEntity (), &tr);
while (tr.flFraction != 1.0 && numHits < 3)
{
numHits++;
thikness++;
point = tr.vecEndPos + direction;
while (POINT_CONTENTS (point) == CONTENTS_SOLID && thikness < 98)
{
point = point + direction;
thikness++;
}
TraceLine (point, dest, true, true, GetEntity (), &tr);
}
if (numHits < 3 && thikness < 98)
{
if ((dest - point).GetLengthSquared () < 13143)
return true;
}
return false;
}
bool Bot::DoFirePause (float distance, FireDelay *fireDelay) bool Bot::DoFirePause (float distance, FireDelay *fireDelay)
{ {
// returns true if bot needs to pause between firing to compensate for punchangle & weapon spread // returns true if bot needs to pause between firing to compensate for punchangle & weapon spread
@ -818,8 +861,8 @@ WeaponSelectEnd:
pev->button &= ~IN_ATTACK; pev->button &= ~IN_ATTACK;
LookupEnemy(); LookupEnemy();
} }
pev->button |= IN_ATTACK; pev->button |= IN_ATTACK;
m_shootTime = GetWorldTime () + baseDelay + g_randGen.Float (minDelay, maxDelay); m_shootTime = GetWorldTime () + baseDelay + g_randGen.Float (minDelay, maxDelay);
m_zoomCheckTime = GetWorldTime (); m_zoomCheckTime = GetWorldTime ();
} }
@ -865,7 +908,7 @@ void Bot::FocusEnemy (void)
float distance = enemyOrigin.GetLength (); // how far away is the enemy scum? float distance = enemyOrigin.GetLength (); // how far away is the enemy scum?
if (distance < 128.0f) if (distance < 256.0f)
{ {
if (m_currentWeapon == WEAPON_KNIFE) if (m_currentWeapon == WEAPON_KNIFE)
{ {
@ -919,11 +962,8 @@ void Bot::CombatFight (void)
float distance = enemyOrigin.GetLength (); // how far away is the enemy scum? float distance = enemyOrigin.GetLength (); // how far away is the enemy scum?
if (m_timeWaypointMove + m_frameInterval + 0.5f < GetWorldTime ()) if (m_timeWaypointMove + m_frameInterval < GetWorldTime ())
{ {
if (m_currentWeapon == WEAPON_KNIFE)
return;
int approach; int approach;
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
@ -936,11 +976,12 @@ void Bot::CombatFight (void)
{ {
approach = static_cast <int> (pev->health * m_agressionLevel); approach = static_cast <int> (pev->health * m_agressionLevel);
if (UsesSniper () && (approach > 49)) if (UsesSniper () && approach > 49)
approach = 49; approach = 49;
} }
if (UsesPistol() && !(m_enemy->v.weapons & (1 << WEAPON_ELITE) || m_enemy->v.weapons & (1 << WEAPON_FIVESEVEN) || m_enemy->v.weapons & (1 << WEAPON_GLOCK) || m_enemy->v.weapons & (1 << WEAPON_USP) || m_enemy->v.weapons & (1 << WEAPON_DEAGLE) || m_enemy->v.weapons & (1 << WEAPON_SG550)) && !g_bombPlanted)
if (UsesPistol() && !((m_enemy->v.weapons & WEAPON_SECONDARY) || (m_enemy->v.weapons & (1 << WEAPON_SG550))) && !g_bombPlanted)
{ {
m_fearLevel += 0.5; m_fearLevel += 0.5;
@ -970,7 +1011,7 @@ void Bot::CombatFight (void)
else else
m_moveSpeed = pev->maxspeed; m_moveSpeed = pev->maxspeed;
if (distance < 96 && m_currentWeapon != WEAPON_KNIFE) if (distance < 96)
m_moveSpeed = -pev->maxspeed; m_moveSpeed = -pev->maxspeed;
if (UsesSniper ()) if (UsesSniper ())
@ -1007,7 +1048,7 @@ void Bot::CombatFight (void)
{ {
if (m_lastFightStyleCheck + 3.0 < GetWorldTime ()) if (m_lastFightStyleCheck + 3.0 < GetWorldTime ())
{ {
if (g_randGen.Long (0, 100) < 50) if ( g_randGen.Long (0, 100) < 50)
m_fightStyle = 1; m_fightStyle = 1;
else else
m_fightStyle = 0; m_fightStyle = 0;
@ -1061,7 +1102,7 @@ void Bot::CombatFight (void)
if (m_difficulty >= 3 && (m_jumpTime + 5.0 < GetWorldTime () && IsOnFloor () && g_randGen.Long (0, 1000) < (m_isReloading ? 8 : 2) && pev->velocity.GetLength2D () > 150.0)) if (m_difficulty >= 3 && (m_jumpTime + 5.0 < GetWorldTime () && IsOnFloor () && g_randGen.Long (0, 1000) < (m_isReloading ? 8 : 2) && pev->velocity.GetLength2D () > 150.0))
pev->button |= IN_JUMP; pev->button |= IN_JUMP;
if (m_moveSpeed > 0.0 && distance > 150.0) if (m_moveSpeed > 0.0 && distance > 150.0 && m_currentWeapon != WEAPON_KNIFE)
m_moveSpeed = 0.0; m_moveSpeed = 0.0;
} }
else if (m_fightStyle == 1) else if (m_fightStyle == 1)
@ -1072,6 +1113,7 @@ void Bot::CombatFight (void)
float enemyHalfHeight = ((m_enemy->v.flags & FL_DUCKING) == FL_DUCKING ? 36.0 : 72.0) / 2; float enemyHalfHeight = ((m_enemy->v.flags & FL_DUCKING) == FL_DUCKING ? 36.0 : 72.0) / 2;
// check center/feet // check center/feet
if (!IsVisible (m_enemy->v.origin, GetEntity ()) && !IsVisible (m_enemy->v.origin + Vector (0, 0, -enemyHalfHeight), GetEntity ())) if (!IsVisible (m_enemy->v.origin, GetEntity ()) && !IsVisible (m_enemy->v.origin + Vector (0, 0, -enemyHalfHeight), GetEntity ()))
shouldDuck = false; shouldDuck = false;
@ -1092,7 +1134,7 @@ void Bot::CombatFight (void)
m_strafeSpeed = 0.0; m_strafeSpeed = 0.0;
} }
if (m_moveSpeed > 0.0f) if (m_moveSpeed > 0.0f && m_currentWeapon != WEAPON_KNIFE)
m_moveSpeed = GetWalkSpeed (); m_moveSpeed = GetWalkSpeed ();
if (m_isReloading) if (m_isReloading)
@ -1254,9 +1296,9 @@ void Bot::SelectBestWeapon (void)
return; return;
} }
if (m_isReloading) if (m_isReloading)
return; return;
WeaponSelect *selectTab = &g_weaponSelect[0]; WeaponSelect *selectTab = &g_weaponSelect[0];
int selectIndex = 0; int selectIndex = 0;

View file

@ -309,7 +309,7 @@ bool Bot::GoalIsValid (void)
return false; return false;
} }
void Bot::CheckTerrain (float movedDistance) void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &dirNormal)
{ {
edict_t *ent = NULL; edict_t *ent = NULL;
@ -320,27 +320,17 @@ void Bot::CheckTerrain (float movedDistance)
m_campButtons = pev->button & IN_DUCK; m_campButtons = pev->button & IN_DUCK;
StartTask (TASK_SHOOTBREAKABLE, TASKPRI_SHOOTBREAKABLE, -1, 0.0, false); StartTask (TASK_SHOOTBREAKABLE, TASKPRI_SHOOTBREAKABLE, -1, 0.0, false);
m_breakableCheckTime = GetWorldTime () + 0.7f; m_breakableCheckTime = GetWorldTime () + 1.0f;
return; return;
} }
// calculate 2 direction vectors, 1 without the up/down component
Vector directionOld = m_destOrigin - (pev->origin + pev->velocity * m_frameInterval);
Vector directionNormal = directionOld.Normalize ();
Vector direction = directionNormal;
directionNormal.z = 0.0;
m_moveAngles = directionOld.ToAngles ();
m_moveAngles.ClampAngles ();
m_moveAngles.x *= -1.0; // invert for engine
m_isStuck = false; m_isStuck = false;
Vector src = nullvec; Vector src = nullvec;
Vector destination = nullvec; Vector dst = nullvec;
Vector direction = dir;
Vector directionNormal = dirNormal;
TraceResult tr; TraceResult tr;
@ -415,9 +405,10 @@ void Bot::CheckTerrain (float movedDistance)
if (m_collideMoves[m_collStateIndex] == COLLISION_DUCK && IsOnFloor () || IsInWater ()) if (m_collideMoves[m_collStateIndex] == COLLISION_DUCK && IsOnFloor () || IsInWater ())
pev->button |= IN_DUCK; pev->button |= IN_DUCK;
} }
return;
} }
else // bot is stuck! // bot is stuck!
{
// not yet decided what to do? // not yet decided what to do?
if (m_collisionState == COLLISION_NOTDECICED) if (m_collisionState == COLLISION_NOTDECICED)
{ {
@ -478,8 +469,8 @@ void Bot::CheckTerrain (float movedDistance)
else else
src = pev->origin + Vector (0, 0, -17); src = pev->origin + Vector (0, 0, -17);
destination = src + directionNormal * 30; dst = src + directionNormal * 30;
TraceLine (src, destination, true, true, GetEntity (), &tr); TraceLine (src, dst, true, true, GetEntity (), &tr);
if (tr.flFraction != 1.0) if (tr.flFraction != 1.0)
state[i] += 10; state[i] += 10;
@ -530,17 +521,17 @@ void Bot::CheckTerrain (float movedDistance)
// now check which side is blocked // now check which side is blocked
src = pev->origin + (g_pGlobals->v_right * 32); src = pev->origin + (g_pGlobals->v_right * 32);
destination = src + (direction * 32); dst = src + (direction * 32);
TraceHull (src, destination, true, head_hull, GetEntity (), &tr); TraceHull (src, dst, true, head_hull, GetEntity (), &tr);
if (tr.flFraction != 1.0) if (tr.flFraction != 1.0)
blockedRight = true; blockedRight = true;
src = pev->origin - (g_pGlobals->v_right * 32); src = pev->origin - (g_pGlobals->v_right * 32);
destination = src + (direction * 32); dst = src + (direction * 32);
TraceHull (src, destination, true, head_hull, GetEntity (), &tr); TraceHull (src, dst, true, head_hull, GetEntity (), &tr);
if (tr.flFraction != 1.0) if (tr.flFraction != 1.0)
blockedLeft = true; blockedLeft = true;
@ -649,7 +640,6 @@ void Bot::CheckTerrain (float movedDistance)
} }
} }
} }
}
} }
bool Bot::DoWaypointNav (void) bool Bot::DoWaypointNav (void)
@ -690,7 +680,7 @@ bool Bot::DoWaypointNav (void)
// pressing the jump button gives the illusion of the bot actual jmping. // pressing the jump button gives the illusion of the bot actual jmping.
if (IsOnFloor () || IsOnLadder ()) if (IsOnFloor () || IsOnLadder ())
{ {
pev->velocity = m_desiredVelocity; pev->velocity = m_desiredVelocity + m_desiredVelocity * 0.15; // cheating i know, but something changed in recent cs updates...
pev->button |= IN_JUMP; pev->button |= IN_JUMP;
m_jumpFinished = true; m_jumpFinished = true;
@ -1076,7 +1066,7 @@ bool Bot::DoWaypointNav (void)
} }
// make sure we are always facing the door when going through it // make sure we are always facing the door when going through it
m_aimFlags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_ENEMY); m_aimFlags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_PATH);
edict_t *button = FindNearestButton (STRING (tr.pHit->v.targetname)); edict_t *button = FindNearestButton (STRING (tr.pHit->v.targetname));
@ -1818,6 +1808,9 @@ bool Bot::FindWaypoint (void)
if (i == m_currentWaypointIndex || i == m_prevWptIndex[0] || i == m_prevWptIndex[1] || i == m_prevWptIndex[2] || i == m_prevWptIndex[3] || i == m_prevWptIndex[4]) if (i == m_currentWaypointIndex || i == m_prevWptIndex[0] || i == m_prevWptIndex[1] || i == m_prevWptIndex[2] || i == m_prevWptIndex[3] || i == m_prevWptIndex[4])
continue; continue;
if ((g_mapType & MAP_CS) && HasHostage () && (g_waypoint->GetPath (i)->flags & FLAG_NOHOSTAGE))
continue;
// ignore non-reacheable waypoints... // ignore non-reacheable waypoints...
if (!g_waypoint->Reachable (this, i)) if (!g_waypoint->Reachable (this, i))
continue; continue;
@ -1854,21 +1847,25 @@ bool Bot::FindWaypoint (void)
i = g_randGen.Long (0, 0); i = g_randGen.Long (0, 0);
else if (coveredWaypoint != -1) else if (coveredWaypoint != -1)
waypointIndeces[i = 0] = coveredWaypoint; {
i = 0;
waypointIndeces[i] = coveredWaypoint;
}
else else
{ {
i = 0;
Array <int> found; Array <int> found;
g_waypoint->FindInRadius (found, 256.0, pev->origin); g_waypoint->FindInRadius (found, 1024.0f, pev->origin);
if (!found.IsEmpty ()) if (!found.IsEmpty ())
waypointIndeces[i = 0] = found.GetRandomElement (); waypointIndeces[i] = found.GetRandomElement ();
else else
waypointIndeces[i = 0] = g_randGen.Long (0, g_numWaypoints - 1); waypointIndeces[i] = g_randGen.Long (0, g_numWaypoints - 1);
} }
m_collideTime = GetWorldTime (); m_collideTime = GetWorldTime ();
ChangeWptIndex (waypointIndeces[0]); ChangeWptIndex (waypointIndeces[i]);
return true; return true;
} }

View file

@ -1249,7 +1249,7 @@ bool Waypoint::Reachable (Bot *bot, int index)
return false; return false;
Vector src = bot->pev->origin; Vector src = bot->pev->origin;
Vector dest = GetPath (index)->origin; Vector dest = m_paths[index]->origin;
float distance = (dest - src).GetLength (); float distance = (dest - src).GetLength ();
@ -1262,7 +1262,7 @@ bool Waypoint::Reachable (Bot *bot, int index)
float distance2D = (dest - src).GetLength2D (); float distance2D = (dest - src).GetLength2D ();
// is destination waypoint higher that source (45 is max jump height), or destination waypoint higher that source // is destination waypoint higher that source (45 is max jump height), or destination waypoint higher that source
if ((dest.z > src.z + 40.0 || dest.z < src.z - 75.0) && (!(GetPath (index)->flags & FLAG_LADDER) || distance2D >= 16.0)) if ((dest.z > src.z + 40.0 || dest.z < src.z - 75.0) && (!(m_paths[index]->flags & FLAG_LADDER) || distance2D >= 16.0))
return false; // unable to reach this one return false; // unable to reach this one
} }
@ -1451,7 +1451,7 @@ char *Waypoint::GetWaypointInfo (int id)
{ {
// this function returns path information for waypoint pointed by id. // this function returns path information for waypoint pointed by id.
Path *path = GetPath (id); Path *path = m_paths[id];
// if this path is null, return // if this path is null, return
if (path == NULL) if (path == NULL)