diff --git a/include/core.h b/include/core.h index 3323f66..0ee7b9f 100644 --- a/include/core.h +++ b/include/core.h @@ -1020,7 +1020,8 @@ private: int FindGoal (void); void FilterGoals (const Array &goals, int *result); void FindItem (void); - void CheckTerrain (float movedDistance, const Vector &dir, const Vector &dirNormal); + void CheckTerrain (float movedDistance, const Vector &dirNormal); + void CheckCloseAvoidance (const Vector &dirNormal); void GetCampDirection (Vector *dest); void CollectGoalExperience (int damage, int team); diff --git a/source/basecode.cpp b/source/basecode.cpp index 8069ac0..80962b4 100644 --- a/source/basecode.cpp +++ b/source/basecode.cpp @@ -2009,7 +2009,7 @@ void Bot::SetConditions (void) } // don't listen if seeing enemy, just checked for sounds or being blinded (because its inhuman) - if (!yb_ignore_enemies.GetBool () && m_soundUpdateTime <= GetWorldTime () && m_blindTime < GetWorldTime ()) + if (!yb_ignore_enemies.GetBool () && m_soundUpdateTime < GetWorldTime () && m_blindTime < GetWorldTime () && m_seeEnemyTime + 1.0f < GetWorldTime ()) { ReactOnSound (); m_soundUpdateTime = GetWorldTime () + 0.25f; @@ -2019,10 +2019,7 @@ void Bot::SetConditions (void) if (IsEntityNull (m_enemy) && !IsEntityNull (m_lastEnemy) && m_lastEnemyOrigin != nullvec) { - TraceResult tr; - TraceLine (EyePosition (), m_lastEnemyOrigin, true, GetEntity (), &tr); - - if ((pev->origin - m_lastEnemyOrigin).GetLength () < 1600.0 && (tr.flFraction >= 0.2 || tr.pHit != g_worldEntity)) + if ((pev->origin - m_lastEnemyOrigin).GetLength () < 1600.0f) { m_aimFlags |= AIM_PREDICT_PATH; @@ -2926,7 +2923,7 @@ void Bot::ChooseAimDirection (void) { TraceLine (EyePosition (), m_lastEnemyOrigin, false, true, GetEntity (), &tr); - if (tr.flFraction <= 0.2 && tr.pHit == g_worldEntity) + if (tr.flFraction <= 0.2) { if ((m_aimFlags & (AIM_LAST_ENEMY | AIM_PREDICT_PATH)) && m_wantsToFire) m_wantsToFire = false; @@ -2940,7 +2937,7 @@ void Bot::ChooseAimDirection (void) m_aimFlags &= ~(AIM_LAST_ENEMY | AIM_PREDICT_PATH); // if in battle, and enemy is behind something for short period of time, look at that origin! - if (m_seeEnemyTime + 2.0f < GetWorldTime () && !(m_aimFlags & AIM_ENEMY) && m_lastEnemyOrigin != nullvec && IsAlive (m_lastEnemy)) + if (m_difficulty < 4 && m_seeEnemyTime + 2.0f < GetWorldTime () && !(m_aimFlags & AIM_ENEMY) && m_lastEnemyOrigin != nullvec && IsAlive (m_lastEnemy)) { m_aimFlags |= AIM_LAST_ENEMY; m_canChooseAimDirection = false; @@ -3447,8 +3444,11 @@ void Bot::RunTask (void) m_checkTerrain = false; m_navTimeset = GetWorldTime (); - m_moveSpeed = 0; - m_strafeSpeed = 0.0; + m_moveSpeed = 0.0f; + m_strafeSpeed = 0.0f; + + m_isStuck = false; + m_lastCollTime = GetWorldTime () + 0.5f; break; @@ -4917,13 +4917,10 @@ void Bot::BotAI (void) SetIdealReactionTimes (); // calculate 2 direction vectors, 1 without the up/down component - const Vector &directionOld = m_destOrigin - (pev->origin + pev->velocity * m_frameInterval); - Vector directionNormal = directionOld.Normalize (); + const Vector &dirOld = m_destOrigin - (pev->origin + pev->velocity * m_frameInterval); + const Vector &dirNormal = dirOld.Normalize2D (); - const Vector &direction = directionNormal; - directionNormal.z = 0.0; - - m_moveAngles = directionOld.ToAngles (); + m_moveAngles = dirOld.ToAngles (); m_moveAngles.ClampAngles (); m_moveAngles.x *= -1.0; // invert for engine @@ -4973,7 +4970,7 @@ void Bot::BotAI (void) } if (m_checkTerrain) // are we allowed to check blocking terrain (and react to it)? - CheckTerrain (movedDistance, direction, directionNormal); + CheckTerrain (movedDistance, dirNormal); // must avoid a grenade? if (m_needAvoidGrenade != 0) @@ -5975,7 +5972,7 @@ void Bot::ReactOnSound (void) // loop through all enemy clients to check for hearable stuff for (int i = 0; i < GetMaxClients (); i++) { - if (!(g_clients[i].flags & CF_USED) || !(g_clients[i].flags & CF_ALIVE) || g_clients[i].ent == GetEntity () || g_clients[i].timeSoundLasting < GetWorldTime ()) + if (!(g_clients[i].flags & CF_USED) || !(g_clients[i].flags & CF_ALIVE) || g_clients[i].ent == GetEntity () || g_clients[i].team == m_team || g_clients[i].timeSoundLasting < GetWorldTime ()) continue; float distance = (g_clients[i].soundPosition - pev->origin).GetLength (); @@ -5992,9 +5989,6 @@ void Bot::ReactOnSound (void) else volume = 2.0 * hearingDistance * (1.0 - distance / hearingDistance) * (g_clients[i].timeSoundLasting - GetWorldTime ()) / g_clients[i].maxTimeSoundLasting; - if (g_clients[i].team == m_team && yb_csdm_mode.GetInt () != 2) - volume = 0.3 * volume; - // we will care about the most hearable sound instead of the closest one - KWo if (volume < maxVolume) continue; @@ -6017,7 +6011,7 @@ void Bot::ReactOnSound (void) if (IsValidPlayer (player)) { // change to best weapon if heard something - if (!(m_states & STATE_SEEING_ENEMY) && m_seeEnemyTime + 2.5 < GetWorldTime () && IsOnFloor () && m_currentWeapon != WEAPON_C4 && m_currentWeapon != WEAPON_EXPLOSIVE && m_currentWeapon != WEAPON_SMOKE && m_currentWeapon != WEAPON_FLASHBANG && !yb_jasonmode.GetBool ()) + if (m_shootTime + 2.5 < GetWorldTime () && IsOnFloor () && m_currentWeapon != WEAPON_C4 && m_currentWeapon != WEAPON_EXPLOSIVE && m_currentWeapon != WEAPON_SMOKE && m_currentWeapon != WEAPON_FLASHBANG && !yb_jasonmode.GetBool ()) SelectBestWeapon (); m_heardSoundTime = GetWorldTime () + 5.0; diff --git a/source/navigate.cpp b/source/navigate.cpp index 5127b33..4e11658 100644 --- a/source/navigate.cpp +++ b/source/navigate.cpp @@ -317,27 +317,41 @@ void Bot::ResetCollideState (void) m_collideMoves[i] = 0; } -void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &dirNormal) +void Bot::CheckCloseAvoidance (const Vector &dirNormal) { - m_isStuck = false; + if (m_seeEnemyTime + 1.0f > GetWorldTime ()) + return; - Vector src = nullvec; - Vector dst = nullvec; - - Vector direction = dir; - Vector directionNormal = dirNormal; - - TraceResult tr; edict_t *nearest = NULL; + float nearestDist = 99999.0f; + int playerCount = 0; - if (g_timeRoundStart + 10.0f < GetWorldTime () && FindNearestPlayer (reinterpret_cast (&nearest), GetEntity (), pev->maxspeed, true, false, true, true)) // found somebody? + for (int i = 0; i < GetMaxClients (); i++) + { + Client *cl = &g_clients[i]; + + if (!(cl->flags & (CF_USED | CF_USED)) || cl->ent == GetEntity () || cl->team != m_team) + continue; + + float distance = (cl->ent->v.origin - pev->origin).GetLength (); + + if (distance < nearestDist && distance < pev->maxspeed) + { + nearestDist = distance; + nearest = cl->ent; + + playerCount++; + } + } + + if (playerCount < 3 && IsValidPlayer (nearest)) { MakeVectors (m_moveAngles); // use our movement angles // try to predict where we should be next frame Vector moved = pev->origin + g_pGlobals->v_forward * m_moveSpeed * m_frameInterval; - moved = moved + g_pGlobals->v_right * m_strafeSpeed * m_frameInterval; - moved = moved + pev->velocity * m_frameInterval; + moved += g_pGlobals->v_right * m_strafeSpeed * m_frameInterval; + moved += pev->velocity * m_frameInterval; float nearestDistance = (nearest->v.origin - pev->origin).GetLength2D (); float nextFrameDistance = ((nearest->v.origin + nearest->v.velocity * m_frameInterval) - pev->origin).GetLength2D (); @@ -349,9 +363,9 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di Vector dirToPoint = (pev->origin - nearest->v.origin).Get2D (); if ((dirToPoint | g_pGlobals->v_right.Get2D ()) > 0.0) - SetStrafeSpeed (directionNormal, pev->maxspeed); + SetStrafeSpeed (dirNormal, pev->maxspeed); else - SetStrafeSpeed (directionNormal, -pev->maxspeed); + SetStrafeSpeed (dirNormal, -pev->maxspeed); ResetCollideState (); @@ -359,6 +373,18 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di m_moveSpeed = -pev->maxspeed; } } +} + +void Bot::CheckTerrain (float movedDistance, const Vector &dirNormal) +{ + m_isStuck = false; + + Vector src = nullvec; + Vector dst = nullvec; + + TraceResult tr; + + CheckCloseAvoidance (dirNormal); // Standing still, no need to check? // FIXME: doesn't care for ladder movement (handled separately) should be included in some way @@ -378,7 +404,7 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di else // not stuck yet { // test if there's something ahead blocking the way - if ((cantMoveForward = CantMoveForward (directionNormal, &tr)) && !IsOnLadder ()) + if ((cantMoveForward = CantMoveForward (dirNormal, &tr)) && !IsOnLadder ()) { if (m_firstCollideTime == 0.0) m_firstCollideTime = GetWorldTime () + 0.2; @@ -392,7 +418,7 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di if (!m_isStuck) // not stuck? { - if (m_probeTime + 0.5 < GetWorldTime ()) + if (m_probeTime + 0.5f < GetWorldTime ()) ResetCollideState (); // reset collision memory if not being stuck for 0.5 secs else { @@ -414,7 +440,7 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di else if (IsInWater ()) bits |= (PROBE_JUMP | PROBE_STRAFE); else - bits |= ((Random.Long (0, 10) > (cantMoveForward ? 7 : 5) ? PROBE_JUMP : 0) | PROBE_STRAFE | PROBE_DUCK); + bits |= ((Random.Long (0, 20) > (cantMoveForward ? 15 : 10) ? PROBE_JUMP : 0) | PROBE_STRAFE | PROBE_DUCK); // collision check allowed if not flying through the air if (IsOnFloor () || IsOnLadder () || IsInWater ()) @@ -433,7 +459,7 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di { state[i] = 0; - if (CanJumpUp (directionNormal)) + if (CanJumpUp (dirNormal)) state[i] += 10; if (m_destOrigin.z >= pev->origin.z + 18.0) @@ -444,14 +470,14 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di MakeVectors (m_moveAngles); src = EyePosition (); - src = src + (g_pGlobals->v_right * 15); + src = src + g_pGlobals->v_right * 15; TraceLine (src, m_destOrigin, true, true, GetEntity (), &tr); if (tr.flFraction >= 1.0) { src = EyePosition (); - src = src - (g_pGlobals->v_right * 15); + src = src - g_pGlobals->v_right * 15; TraceLine (src, m_destOrigin, true, true, GetEntity (), &tr); @@ -464,7 +490,7 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di else src = pev->origin + Vector (0, 0, -17); - dst = src + directionNormal * 30; + dst = src + dirNormal * 30; TraceLine (src, dst, true, true, GetEntity (), &tr); if (tr.flFraction != 1.0) @@ -478,7 +504,7 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di { state[i] = 0; - if (CanDuckUnder (directionNormal)) + if (CanDuckUnder (dirNormal)) state[i] += 10; if ((m_destOrigin.z + 36.0 <= pev->origin.z) && EntityIsVisible (m_destOrigin)) @@ -509,14 +535,11 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di else dirLeft = true; - if (m_moveSpeed > 0) - direction = g_pGlobals->v_forward; - else - direction = -g_pGlobals->v_forward; + const Vector &testDir = m_moveSpeed > 0.0f ? g_pGlobals->v_forward : -g_pGlobals->v_forward; // now check which side is blocked src = pev->origin + (g_pGlobals->v_right * 32); - dst = src + (direction * 32); + dst = src + testDir * 32; TraceHull (src, dst, true, head_hull, GetEntity (), &tr); @@ -524,7 +547,7 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di blockedRight = true; src = pev->origin - (g_pGlobals->v_right * 32); - dst = src + (direction * 32); + dst = src + testDir * 32; TraceHull (src, dst, true, head_hull, GetEntity (), &tr); @@ -549,6 +572,7 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di if (blockedRight) state[i] -= 5; } + // weighted all possible moves, now sort them to start with most probable bool isSorting = false; @@ -616,12 +640,12 @@ void Bot::CheckTerrain (float movedDistance, const Vector &dir, const Vector &di case COLLISION_STRAFELEFT: pev->button |= IN_MOVELEFT; - SetStrafeSpeed (directionNormal, -pev->maxspeed); + SetStrafeSpeed (dirNormal, -pev->maxspeed); break; case COLLISION_STRAFERIGHT: pev->button |= IN_MOVERIGHT; - SetStrafeSpeed (directionNormal, pev->maxspeed); + SetStrafeSpeed (dirNormal, pev->maxspeed); break; } } @@ -2156,7 +2180,12 @@ int Bot::FindDefendWaypoint (const Vector &origin) if (waypointIndex[0] == -1) { Array found; - g_waypoint->FindInRadius (found, 1024.0f, origin); + + for (int i = 0; i < g_numWaypoints; i++) + { + if ((g_waypoint->GetPath (i)->origin - origin).GetLength () <= 1024.0f && !IsPointOccupied (i)) + found.Push (i); + } if (found.IsEmpty ()) return Random.Long (0, g_numWaypoints - 1); // most worst case, since there a evil error in waypoints @@ -2512,6 +2541,8 @@ bool Bot::CantMoveForward (const Vector &normal, TraceResult *tr) Vector src = EyePosition (); Vector forward = src + normal * 24; + MakeVectors (Vector (0, pev->angles.y, 0)); + // trace from the bot's eyes straight forward... TraceLine (src, forward, true, GetEntity (), tr); @@ -2523,7 +2554,6 @@ bool Bot::CantMoveForward (const Vector &normal, TraceResult *tr) return true; // bot's head will hit something } - MakeVectors (Vector (0, pev->angles.y, 0)); // bot's head is clear, check at shoulder level... // trace from the bot's shoulder left diagonal forward to the right shoulder...