diff --git a/include/yapb.h b/include/yapb.h index 010b712..7e8b0ed 100644 --- a/include/yapb.h +++ b/include/yapb.h @@ -949,6 +949,7 @@ private: void processPickups (void); void checkTerrain (float movedDistance, const Vector &dirNormal); void checkDarkness (void); + void checkParachute (void); bool doPlayerAvoidance (const Vector &normal); void getCampDir (Vector *dest); @@ -1138,6 +1139,7 @@ public: edict_t *m_radioEntity; // pointer to entity issuing a radio command int m_radioOrder; // actual command + float m_fallDownTime; // time bot started to fall float m_duckForJump; // is bot needed to duck for double jump float m_baseAgressionLevel; // base aggression level (on initializing) float m_baseFearLevel; // base fear level (on initializing) diff --git a/source/basecode.cpp b/source/basecode.cpp index f2c6774..3ab6846 100644 --- a/source/basecode.cpp +++ b/source/basecode.cpp @@ -1805,7 +1805,7 @@ void Bot::overrideConditions (void) { } // special handling, if we have a knife in our hands - if ((g_timeRoundStart + 6.0f > engine.timebase () || !hasAnyWeapons ()) && m_currentWeapon == WEAPON_KNIFE && isPlayer (m_enemy) && (taskId () != TASK_MOVETOPOSITION || task ()->desire != TASKPRI_HIDE)) { + if ((g_timeRoundStart + 6.0f > engine.timebase () || !hasAnyWeapons ()) && m_currentWeapon == WEAPON_KNIFE && isPlayer (m_enemy)) { float length = (pev->origin - m_enemy->v.origin).length2D (); // do waypoint movement if enemy is not reachable with a knife @@ -1813,12 +1813,15 @@ void Bot::overrideConditions (void) { int nearestToEnemyPoint = waypoints.getNearest (m_enemy->v.origin); if (nearestToEnemyPoint != INVALID_WAYPOINT_INDEX && nearestToEnemyPoint != m_currentWaypointIndex && cr::abs (waypoints[nearestToEnemyPoint].origin.z - m_enemy->v.origin.z) < 16.0f) { - startTask (TASK_MOVETOPOSITION, TASKPRI_HIDE, nearestToEnemyPoint, engine.timebase () + rng.getFloat (5.0f, 10.0f), true); + float taskTime = engine.timebase () + length / pev->maxspeed * 0.5f; + if (taskId () != TASK_MOVETOPOSITION && task ()->desire != TASKPRI_HIDE) { + startTask (TASK_MOVETOPOSITION, TASKPRI_HIDE, nearestToEnemyPoint, taskTime, true); + } m_isEnemyReachable = false; m_enemy = nullptr; - m_enemyIgnoreTimer = engine.timebase () + length / pev->maxspeed * 0.5f; + m_enemyIgnoreTimer = taskTime; } } } @@ -2888,6 +2891,25 @@ void Bot::checkDarkness (void) { m_checkDarkTime = engine.timebase (); } +void Bot::checkParachute (void) { + static auto parachute = g_engfuncs.pfnCVarGetPointer ("sv_parachute"); + + // if no cvar or it's not enabled do not bother + if (parachute && parachute->value > 0.0f) { + if (isOnLadder () || pev->velocity.z > -50.0f || isOnFloor ()) { + m_fallDownTime = 0.0f; + } + else if (cr::fzero (m_fallDownTime)) { + m_fallDownTime = engine.timebase (); + } + + // press use anyway + if (!cr::fzero (m_fallDownTime) && m_fallDownTime + 0.35f < engine.timebase ()) { + pev->button |= IN_USE; + } + } +} + void Bot::framePeriodic (void) { if (m_thinkFps <= engine.timebase ()) { // execute delayed think @@ -4979,6 +5001,9 @@ void Bot::ai (void) { } } + // check if need to use parachute + checkParachute (); + // display some debugging thingy to host entity if (!engine.isNullEntity (g_hostEntity) && yb_debug.integer () >= 1) { showDebugOverlay (); diff --git a/source/manager.cpp b/source/manager.cpp index 30e78aa..723adbe 100644 --- a/source/manager.cpp +++ b/source/manager.cpp @@ -1202,6 +1202,7 @@ void Bot::newRound (void) { m_ignoreBuyDelay = false; m_hasC4 = false; + m_fallDownTime = 0.0f; m_shieldCheckTime = 0.0f; m_zoomCheckTime = 0.0f; m_strafeSetTime = 0.0f;